Repository navigation
lance-graph-r2il: R1 successor, native prepared plans over CompiledProgram - #1897
Conversation
…are/run) binding::prepare resolves an admitted DT64 MethodBinding once, cold: frame, focus, scope and route guards, class basis, admit, then per effect the lens (OGAR's R2IL fold reading), the word's label resolved to exactly one opcode by OGAR's vocabulary, the translatable subset, and OGAR's arity against the lens's declared arity and the argument count. binding::run executes the bound opcodes through FoldDialect, hot, rechecking only the guards, the route and an explicit execution permit, and returns a receipt bounded by the plan's step count. This reading is optional: no consumer is required to execute through it. Unsupported shapes (WHEN guards, three-valued truth, immediates, sinks, out-of-range lane constants, unbound fields) are refused by name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMNZqKXSaeb9g2ypywF
…rces BindStore::register refuses an effect whose argument count differs from the lens's declared arity, so comparing OGAR's arity with the declared one could never fire on its own (a disable run left every test green). The check is OGAR's arity against the argument count; the declared arity is still reported in the refusal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMNZqKXSaeb9g2ypywF
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMNZqKXSaeb9g2ypywF
… compiled)
Seven arms on SUM { a : a < t }: direct ndarray, ClassId → LazyLock
prebound callable, prebound plus the dt64 guard R1 runs, mask-risc
prepared, R2IL prepared (FoldDialect once, CompiledProgram kept),
FoldDialect per call, and R1 binding::run.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XAqKMNZqKXSaeb9g2ypywF
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMNZqKXSaeb9g2ypywF
…tup) Measured on 4 cores, median ns per call, answers asserted equal across arms: 64 rows: direct 29.4, prebound 30.0, +guard 60.9, mask-risc prepared 103.3, r2il prepared 103.2, dialect 205.9, R1 run 398.4. R1 runs FoldDialect once per call and allocates 5 times per call; prepared paths allocate 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMNZqKXSaeb9g2ypywF
…clusion The R1 arm discarded failures with if let Ok; every arm now counts calls that returned the oracle's answer and the run fails unless that count equals the call count. Board entry records the 4-row-size table (65,536 included), the conclusion (prepared R2IL equals prepared mask-risc; R1's extra cost is its interpreter and receipt) and the operator decision on #1892. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMNZqKXSaeb9g2ypywF
…ogram prepare_native runs a Prepared plan once through FoldDialect, keeps each fold's program as a mask-risc CompiledProgram in step order, and records the output layout. run_native checks guards, route and permit exactly as run does, then executes the programs with no allocation and returns a fixed-size receipt. Plans whose values compiling once would freeze are refused by name: a fold fed by a fold result, a scalar computed after a fold, a fold-free scalar read from the planes, too many outputs, and changed planes. ExecPermit stays a lab permission. Tests: agreement with run on every runnable fixture, step-ordered multi-fold, each refusal with a can-stay-silent twin, run's early refusals reproduced, and zero allocations per run_native call (the counter is shown to see run allocate). Benchmark gains an 8th arm. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMNZqKXSaeb9g2ypywF
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMNZqKXSaeb9g2ypywF
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9e6e848137
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…alect state per run Two review findings on the binding layer, both reproduced first: - IntAnd's survivor gating rewrites the last predicate in place, so a field that is the right operand of an AND and is read again later changed meaning. m = a<5; t = a<10; u = m AND t; s = POP_COUNT(t) counted a<5. The dialect gains call_shared, which emits a separate And; binding::call_step uses it when an operand field is read by a later step, in run and prepare_native. Stack programs that consume their operands keep the gating. - run left a plan's unconsumed predicates in the caller's dialect, so repeated predicate-only plans grew its ops until a later fold failed with ScratchBufferTooSmall. FoldDialect::discard_pending drops them and advances the epoch; run calls it before and after the steps, on success and error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMNZqKXSaeb9g2ypywF
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMNZqKXSaeb9g2ypywF
… unused Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMNZqKXSaeb9g2ypywF
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XAqKMNZqKXSaeb9g2ypywF
This is the successor to #1892, which stays open as measured evidence until this one replaces it. The branch contains #1892's
bindingseam plus the new native path.What changes. #1892's
runre-interprets every step throughFoldDialecton every call. It keeps per-runBTreeMapvalues, rebuilds the stack and allocates the receipt, which costs about 280 ns and 5 allocations per call.binding_native::prepare_nativeruns the plan once throughFoldDialect, which is the compilation D-MPF-4 proved. It keeps each fold's program as a mask-riscCompiledProgram, in step order, and records the output layout.run_nativeexecutes those programs withexecute_compiledand fills a fixed-size receipt. It allocates nothing and adds no new interpreter.Validation stays independent.
run_nativechecks guards (frame, focus, scope), route and permit exactly asrundoes, in the same order and with the same refusals.ExecPermitremains a lab permission, and its doc now says so. It makes no production authorization claim, and #1891'sExecutionPolicystays lab too.Refusals instead of frozen values. Compiling once must never freeze a value that should be recomputed, so these cases are refused by name:
FoldResultFeedsFold: a fold that consumes an earlier fold's result;ScalarAfterFold: a scalar computed from a fold result;DataScalarNotPrepared: a fold-free scalar read from the planes;TooManyOutputs;PlanesChanged: the shape differs from preparation.Multi-fold plans run their programs in step order.
Tests (
tests/integration/binding_native.rs, 16):run_nativeagrees withrunon every runnable fixture: values,programs_run,plan_id, frame and intermediates;run's early refusals are reproduced, with their precedence;run_nativecalls for four plans. The same counter is shown to seerunallocate, so it can fire.Four refusal guards were disabled one at a time, and each turned its test red. When only the pre-call
FoldResultFeedsFoldcheck is disabled, the suite stays green, because the post-fold check catches the same case.Benchmark (
r1_vs_prebound, 8 arms). Every timed call is checked against the oracle. Median ns per call, from the clean run of three; the other two were disturbed by VM load.Allocations per call: R1 native 0, R1 run 5.
R1 native costs a constant ~50–60 ns above prepared mask-risc, independent of row count. The guard check alone costs ~30 ns (the prebound vs prebound+guard arms), and route lookup and the permit scan account for the rest. That split is a working model and was not timed separately.
Not done:
cargo test -p lance-graph-r2il --releasepasses (9 + 28 + 22), andclippy -D warningsandfmtare clean.Generated by Claude Code