Add list_insert_at and list_slice builtins (#544)#677
Merged
InauguralPhysicist merged 1 commit intoJul 20, 2026
Merged
Conversation
Adds the C-backed list_insert_at of [list, i, v] (dual of list_remove_at) and list_slice of [list, start, end] (dual of copy_into), so reorder and range-copy no longer go through interpreter-speed hand-rolled loops. Registered and tested alongside the existing list builtins. Closes InauguralSystems#544 Co-Authored-By: Kimi K3 <noreply@kimi.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #544.
Adds the two missing C-backed list builtins so reorder and range-copy no longer go through interpreter-speed hand-rolled loops:
list_insert_at of [list, i, v]— dual oflist_remove_at. Insertsvat indexi, shifting the tail up.i == countappends; any other out-of-bounds index is a no-op returning the list (matchinglist_remove_at's lenient behaviour).list_slice of [list, start, end]— dual ofcopy_into. Returns a new list with elements[start, end). Negative indices count from the end (theat_index/get_at / set_at / char_at silently ignore negative indices, diverging from the[]operator's documented negative indexing #312 policy used byget_at/set_at/[]); both bounds clamp to[0, len];start >= end→[]; never raises on bounds (per the issue'slist_slice of [[1,2], 5, 9]→[]). Malformed args return null, mirroringcopy_into. Charges the new slots viasandbox_chargelikeconcat(sandbox_run has no memory budget: generated 'zeros'/aggregate allocation aborts the host (uncatchable) #292).Both are registered next to their duals in
register_builtins, added toSANDBOX_ALLOW(both duals were already there — same membership rule: pure, touches only handed-in values), and documented indocs/BUILTINS.md(required bytools/stdlib_index_check.sh).One C detail worth a glance: the middle-insert path grows the array by appending the old last element (reusing
list_append's capacity/arena handling), thenmemmoves the tail up. Sincelist_appendincrefs, the old last element would otherwise be left with one unbalanced reference after thememmoveoverwrites its original slot — so there's an explicitval_decref(old_last)afterwards to keep its refcount matched to its single remaining slot (it still occupiesslot[count]at that point, so the decref can't free it). Net: the inserted value gains one reference, every existing element keeps exactly one.Tests:
tests/test_list_insert_at.eigsandtests/test_list_slice.eigsmirrortest_list_remove_at.eigs(insert middle/start/end/out-of-bounds; slice normal/empty/full/clamped) — plus a repeated-middle-insert stress case that also guards the refcount path. Full suite: 3118/3118 passed.Generated by Claude Opus 4.8 (brief, review), Kimi K3 (implementation)