R2IL gains a fold reading: one arity table, two classids, twelve new bytes - #306
Conversation
…bytes The capstone ruling was that we already have the instruction set and keep re-implementing programs as Rust enum variants. mask-risc's Pred/Terminal, quack's Filter/Agg and lgj's LgjOpDesc are three mirrors of one meaning. The carrier that removes the mirroring is a loco body under a vocabulary, and the vocabulary already existed here. So R2ILVocabulary now answers for TWO readings of the SAME table. The registry's plug() refuses only a taken concept id and copies the table, so one CheckedVocabulary plugs under CONCEPT_R2IL_MACHINE and CONCEPT_R2IL_FOLD with no code change, and compose() samples the hooks once -- arity, pushes and body_refs are identical under both by construction. Only the dialect differs. The 0xE2..=0xED band adds the twelve population ops P-Code cannot spell: VIA, RANGE, SUM, MIN, MAX, GROUP_SUM, KEY_RUNS, ANY, ALL, KEEP, SCATTER_OR, BLEND. Each is backed by a mask-risc terminal that already earned its existence with its own parity case, so a byte names what passed. FIRST, MATCH and SCATTER_COUNT stay unminted for want of a falsifier. 18 slots stay free. Three selection findings removed rows nobody has to mint. Load (arity 1, pushes true) needs no new byte: P-Code's shape already fits, with the lane index as the single stack operand and the lane kind riding the immediate as the address space. P-Code's signed/unsigned split maps onto mask-risc's, so four compare bytes plus operand order cover all six compares. GROUP_SUM selects between the local and via terminals off its key operand's kind. The band lives in separate arrays because the drift test asserts MNEMONICS.len() == R2IL_OPS against r2sleigh's enum; all three protected arrays are byte-identical to origin/main and both guard tests are unchanged. domain_name was never wired, so name() was None for all 82 opcodes despite MNEMONICS existing -- wired here as an additive fix with nothing outside this crate depending on it. Concept ids are provisional in ConceptDomain::BinaryLifting, whose own doc names architecture-agnostic lift/IR and sends platform facts to 0xC6XX. No persisted GUID may use them until minted. This crate gains no executor and stays proxy glue, so the 2026-08-26 ruling needs no storno -- only a narrowing of "the runtime path" to "the machine reading's runtime path", applied in place. 10 tests, 5 disable arms red-then-green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GXUahz73MZxtxWcfpHp9dG
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Essentials Run ID: 📒 Files selected for processing (2)
Included review availability: 1 review is currently available. Your included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour. 📝 WalkthroughWalkthroughThe change adds a 12-opcode fold band to R2IL, registers machine and fold concept IDs, extends vocabulary lookups, preserves existing R2IL behavior, and documents the fold runtime boundary. ChangesR2IL Fold Vocabulary
Priority: ➖ Normal Estimated code review effort: 4 (Complex) | ~35 minutes Change: Feature Suggested reviewers: Merge Risk: ⚪ Minimal · up to This change adds fold vocabulary metadata while preserving existing R2IL behavior; the reported validation passes, so it is ready to merge with normal checks. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
A rabbit checks the fold-band sign, Comment |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_d8aedd34-7348-4c8c-b806-a779533eb06c) |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Why
The capstone ruling: we already built the instruction set; stop re-implementing programs as Rust enum variants.
mask_risc::{Pred, Terminal},quack::{Filter, Agg}and lgj'sLgjOpDescare three mirror enums of one meaning. The carrier that removes the mirroring is a loco body under a vocabulary — and the vocabulary already existed here.Evidence it works: lance-graph #1258 carried a join-count as loco bytes through the existing
Interpreterinto the fused executor, 2 facade passes againstquack::lower's 3, allocation identical at 1,000 and 65,536 rows. That probe used a local vocabulary. This PR gives it a real one.One table, two readings
R2ILVocabularynow answers for the machine reading and a folded reading of the sameVocabularyTable.VocabularyRegistry::plugrefuses only a taken concept id and copies*v.table(), so oneCheckedVocabularyplugs under both ids with no code change, andcomposesamples the hooks once — arity, pushes andbody_refsare identical under both by construction. Only the dialect differs.That is what closes the ambiguity: the classid binds the dialect, so a stored body is never semantically undecidable.
The 0xE2..=0xED band — twelve rows, eighteen slots left free
VIA·RANGE·SUM·MIN·MAX·GROUP_SUM·KEY_RUNS·ANY·ALL·KEEP·SCATTER_OR·BLENDEach is backed by a mask-risc
Pred/Terminalthat already earned its existence in a prior wave with its own parity case. A byte names what passed — that is the line between this and enum explosion. Unminted for want of a falsifier:FIRST(the witness; earns 0xEE when areceive-shaped probe fails without it),MATCH(no P-Code spelling, no frontend emits it),SCATTER_COUNT(the mask-risc terminal is HELD).Three selection findings that removed rows nobody has to mint
Loadis ordinal 1, arity 1, pushes true — exactly P-Code's shapeLaneRef's three variants). No inference, no schema dep.IntSLessplus operand ORDER givesLtI32andGtI32. Four compare bytes cover all six mask-risc compares. P-Code has noGreater, as no ISA does. UnsignedIntLessbecomes a named refusal, not a silent signed substitution.GROUP_SUMreads its key operand's kindAddr::LaneselectsGroupSumI32,Addr::ViaselectsGroupSumViaI32. One byte, both terminal shapes, by selection not by variant.The constraint that shaped the implementation
The drift test asserts
MNEMONICS.len() == R2IL_OPSagainst r2sleigh's own enum, so a row added toMNEMONICS/ARITY/PUSHESwould break the pin that keeps R2IL honest. The band therefore lives in separate arrays. Verified: all three protected arrays are byte-identical toorigin/main, and both guard tests (the_table_matches_r2il_s_own_enum,every_opcode_sits_above_the_domain_floor_and_below_the_next_domain) are byte-identical too.Additive side-fix:
domain_namewas never wiredVocabularyTable::name()returnedNonefor all 82 R2IL opcodes even thoughMNEMONICSexisted — the same shape of gapdomain_pushes_resultclosed earlier. Wired for both bands. Nothing outside this crate depends onogar-r2il(the one hit inogar-loco/Cargo.tomlis a comment line), so the fix is observable and carries no cross-crate risk.Concept ids are PROVISIONAL
CONCEPT_R2IL_MACHINE = 0xC400,CONCEPT_R2IL_FOLD = 0xC401, inConceptDomain::BinaryLifting— the domain whose own doc names architecture-agnostic lift/IR and sends platform facts like$D021to0xC6XXinstead. No persisted GUID may use them until minted inogar-vocab; minting stays an operator decision. Both doc comments say so.The 2026-08-26 ruling needs no storno
It rules out the
ruff_r2ilR2IL→SPO pre-pass, and that stands unchanged. This crate gains no executor and remains an arity table plus addressing glue. What was narrowed, in place: "the runtime path is r2sleigh's interpreter" → "the machine reading's runtime path", since the folded reading's dialect lives in a consumer. Both readings execute R2IL; neither pre-converts it.Gates (run scoped,
-p ogar-r2il, never--all)Five disable arms red-then-green (full table in the commit); two re-verified independently after the doc edits landed:
FOLD_BASEoff by one → 2 red; the two-classidplugfalsifier collapsed to one id → 1 red. Every patch anchor was assertion-checked before applying, becausecargo fmthas already silently moved an anchor once in this arc.Measured gap, named not hidden
Dialect::truthyreturns a bareboolthrough&self, so a fold dialect cannot refuse a branch on a population — whatever it answers, loco proceeds. Detectable via a poison flag, never abortable. Making it a true refusal needstruthy -> Result<bool, Self::Error>inogar-loco: its own PR, its own blast radius.Not in this PR
No
R2ILOp/r2sleigh change. No machine dialect (the 6510 / MemoryBus / r2conc-oracle arm is its own wave). No fold dialect — that lands next in lance-graph's excluded-tier probe, where the OGAR path deps already resolve, so no lance-graph workspace crate gains an OGAR dependency and no restructure is needed.Ledger:
docs/DISCOVERY-MAP.mdD-R2IL-FOLD-BAND(appended, per the map's append-only discipline).🤖 Generated with Claude Code
https://claude.ai/code/session_01GXUahz73MZxtxWcfpHp9dG
Generated by Claude Code
Summary by CodeRabbit
New Features
Documentation