vm/cranelift: lift grp + uniqby + srt-2arg + partition via tree-bridge (HOF dispatch PR 3b)#279
Merged
Merged
Conversation
The existing call_builtin_for_bridge constructs an empty Env, which works for tree-only builtins that have no FnRef args (rgx, fmt, sleep, etc.) but cannot dispatch user-fn callbacks. The next step in the HOF chain (grp/uniqby/partition/srt-2arg) needs those callbacks to resolve, so add a program-aware variant that registers every Decl::Function and Decl::Tool into the Env before dispatching, mirroring the prefix of run_with_env.
The HOFs that take a FnRef + list (grp, uniqby, partition, 2-arg srt) can all run on the bridge once the bridge has access to the user-defined functions in the source program. Three pieces: - CompiledProgram retains an Arc<Program> (populated by vm::compile) - VM::execute and with_active_registry publish it through an ACTIVE_AST_PROGRAM TLS, cleared by an RAII guard parallel to the existing ACTIVE_REGISTRY/ACTIVE_FUNC_NAMES/ACTIVE_PROGRAM slots - is_tree_bridge_eligible accepts (Grp, 2), (Uniqby, 2), (Partition, 2), (Srt, 2). Cranelift gets them for free via the existing jit_call_builtin_tree helper, which also reads the new TLS OP_CALL_BUILTIN_TREE and jit_call_builtin_tree now pick the program-aware bridge entry when the TLS is set, falling back to the no-program variant for the test-shell case where CompiledProgram is constructed by hand without an AST. Unignores the corresponding vm_grp_* and vm_srt_* tests in src/vm/mod.rs (grp by string/numeric/bool/float key + empty list + key-returning-list error path; 2-arg srt by length/numeric/text key + bool ordering + wrong-arg). A handful of dynamic-dispatch tests that need direct FnRef-variable calls (PR 3d) get re-ignored with an updated note. Closure-bind 3-arg ctx forms still error here; they land in PR 3c.
…artition tests/regression_hof_3b.rs: thirteen cases covering grp (by string, numeric key, empty list), uniqby (keeps first per key, empty list), partition (mixed, all-pass, all-fail), 2-arg srt (by abs, by length, empty), chained uniqby + grp (catches stale-Env bugs across consecutive bridge invocations), and a tree/VM error path for wrong list arg. Each case runs on tree, VM, and Cranelift and asserts identical output. examples/grp-basics.ilo and examples/srt-by-key.ilo: new docs-as-tests covering the 2-arg HOF shapes for grp and srt. Both run on all three engines via the bridge. examples/uniqby.ilo and examples/partition.ilo: lift the vm/cranelift engine-skip lines now that the bridge handles them. jit (LLVM) skip stays in place pending the LLVM backend's own HOF dispatch work. Cranelift's jit_call_builtin_tree still swallows bridge errors as Nil (matching jit_rgxsub/jit_rd precedent); the error-path test asserts tree + VM surface the typed runtime error and notes the Cranelift follow-up.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This was referenced May 15, 2026
danieljohnmorris
added a commit
that referenced
this pull request
May 15, 2026
- slc / take / drop accept negative indices counting from end (bounds clamp), matching at xs i. Closes the quant-trader fencepost and the slc xs -np 1 np ergonomics gap (#266). - Map keys are typed: text or integer. mset m 7 v and mget m 7 work directly, no str conversion. Int(1) and Text("1") are distinct. Float keys floor to i64; jdmp stringifies numeric keys for JSON (#267). - Add map / flt / fld to the builtin reference. All HOFs (map, flt, fld, srt, grp, uniqby, partition, flatmap) now work cross-engine on tree, VM, Cranelift JIT, and AOT (#274 #277 #278 #279 #280 #283). - New Inline lambdas subsection: Phase 1 literals are cross-engine, Phase 2 closure capture is tree-only with automatic fallthrough surfacing ILO-R012 on VM and Cranelift (#265 #284). - AOT-compiled binaries from ilo compile now strip the top-level ~/^ wrapper byte-for-byte the same as in-process runners (#281).
5 tasks
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.
Summary
Fourth in the HOF dispatch chain after PR 1 (#274, FnRef NaN-tagging), PR 2 (#277,
mapnative), PR 3a (#278, flt/fld/flatmap native).The remaining tree-only HOFs (
grp,uniqby,partition, 2-argsrt) call back into user-defined functions per element, so the existing tree-bridge couldn't dispatch them:call_builtin_for_bridgeconstructs an empty Env. This PR plumbs the AST through to the bridge so it can register everyDecl::Functionbefore invoking the tree interpreter, and extendsis_tree_bridge_eligibleto cover the four HOFs.Manifesto framing: every HOF that was previously tree-only now runs on every engine without a per-builtin native lift. Future PRs can graduate any specific HOF off the bridge with a native opcode (the existing PR 3a pattern) without changing observable behaviour.
Repro
Before:
After (matches
--run-treebyte-for-byte):Same for
uniqby,partition, and 2-argsrton VM and Cranelift.What is in the diff
interpreter: program-aware bridge entry for HOF dispatch— addscall_builtin_for_bridge_with_program(name, args, program)that registers user functions/tools into a fresh Env before dispatch.vm: route grp/uniqby/srt-2arg/partition through tree-bridge—CompiledProgramnow retainsArc<Program>(populated byvm::compile);VM::executeandwith_active_registrypublish it via a newACTIVE_AST_PROGRAMTLS, cleared by an RAII guard that parallels the existingACTIVE_REGISTRY/ACTIVE_FUNC_NAMES/ACTIVE_PROGRAMslots.OP_CALL_BUILTIN_TREEandjit_call_builtin_treepick the program-aware bridge entry when the TLS is set.is_tree_bridge_eligibleaccepts(Grp, 2),(Uniqby, 2),(Partition, 2),(Srt, 2). Cranelift gets these for free through the existingjit_call_builtin_treehelper.test + example: cross-engine coverage— newtests/regression_hof_3b.rs(13 cases, tree/VM/Cranelift), newexamples/grp-basics.iloandexamples/srt-by-key.ilo, lifted vm/cranelift skips fromexamples/uniqby.iloandexamples/partition.ilo.Test plan
cargo build --release --features craneliftcleancargo test --release --features craneliftgreen across all 117 suites (2932 lib + 13 new regression + 1 examples_engines)cargo clippy --release --features cranelift --all-targets -- -D warningscleancargo fmtcleanvm_grp_*andvm_srt_*dynamic-dispatch tests insrc/vm/mod.rspassFollow-ups
cb x y ctxshape) — unignores the 14 closure-bind HOF tests.Expr::Callwhen callee resolves to a FnRef-typed local).engine-skipfrom inline lambda examples once the lambda lift pass is in.jit_call_builtin_treestill collapses bridge errors to Nil. Documented as a follow-up in its rustdoc; the new regression test only asserts the typed error on tree + VM.