Repository navigation
fix(ccl): execute branch and read-branch jump tables - #436
Conversation
A CCL program whose first instruction is branch failed in Neomacs with "Error in CCL program at 3th code" and exited 255. GNU Emacs runs the same program and prints the selected block. Reported in #435 with (branch r0 (write "A")), which ccl.el compiles to a vector whose first real word is opcode 0x0D (CCL_Branch). (write "A") alone already worked, because CCL_WriteConstString was implemented. The driver matched raw opcode numbers and treated every unimplemented code as an invalid program. CCL_Branch was one of those codes, so a valid jump table was rejected at vector index 2. GNU's driver (src/ccl.c) indexes the following words by the register when it is in range, and uses one extra slot otherwise. Each entry is a raw relative offset from the table head. CCL_ReadBranch reads one character and then uses that same table; EOF skips the table, and a suspended read resumes on the same word. CclCommand is now a repr(u8) enum of every GNU opcode. strum::FromRepr turns the 5-bit field into a variant with a safe const match, and the driver matches that enum with no wildcard. branch and read-branch share ccl_branch_target. Opcodes that are still unimplemented stay in one explicit arm and still signal "Error in CCL program". The new tests run GNU ccl-compile vectors: r0 selects "A", an out-of-range or negative register writes nothing, a later register selects "B", and read-branch covers both blocks, the extra slot, EOF, and suspend. Verified: cargo test -p neovm-core --offline --lib emacs_core::ccl:: (31 passed). The installed Neomacs binary was not rebuilt.
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (3)
✨ Finishing Touches📝 Generate docstrings
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The branch/read-branch handlers, enum discriminants, and all four test vectors were hand-verified against GNU src/ccl.c semantics, the refactor preserves existing opcode behavior, and no issues were found.
Review effort: Balanced
Findings: None
What changed in this PR
This PR fixes issue #435, where a CCL program whose first instruction is branch failed with Error in CCL program at 3th code. The CCL bytecode driver in neovm-core had no arm for the CCL_Branch (0x0D) opcode (nor CCL_ReadBranch, 0x10), so ccl.el-emitted jump tables were rejected as invalid. The change introduces a typed CclCommand enum for all 32 GNU opcodes, converts the 5-bit opcode field via strum::FromRepr, and adds jump-table execution for branch/read-branch matching GNU's src/ccl.c semantics. This restores parity with GNU Emacs for CCL programs that use branch dispatch, benefiting CCL-backed coding systems and ccl-execute-on-string consumers such as FLIM.
Changes:
- Add
command.rsdefiningCclCommand(#[repr(u8)],strum::FromRepr) with GNU opcode discriminants0x00–0x1f. - Replace the raw
code & 0x1finteger dispatch with an exhaustive enum match (no wildcard), and implementBranch/ReadBranchvia a sharedccl_branch_targethelper; remaining opcodes stay in one explicit arm that still signalsError in CCL program. - Add tests covering branch selection, the out-of-range slot, a later block, and read-branch (both blocks, extra slot, EOF, and suspend).
| File | Description |
|---|---|
crates/neovm-core/src/emacs_core/text/ccl/command.rs |
New CclCommand enum enumerating every GNU 5-bit opcode as repr(u8) discriminants. |
crates/neovm-core/src/emacs_core/text/ccl/mod.rs |
Adds ccl_branch_target, decodes opcodes into CclCommand, and adds exhaustive-match arms for Branch/ReadBranch. |
crates/neovm-core/src/emacs_core/text/ccl/tests/mod.rs |
Adds an execute_ccl_on_string helper and tests for branch/read-branch against GNU-compiled vectors. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Summary
Fixes #435.
A CCL program whose first instruction is
branchfailed withError in CCL program at 3th code. GNU Emacs runs the same program.ccl.elalready emitted a validCCL_Branch(0x0D) jump table; the bytecode driver had no arm for that opcode and treated it as an invalid program.(write "A")alone worked becauseCCL_WriteConstStringwas already implemented.CclCommandis now a#[repr(u8)]enum of every GNU opcode.strum::FromReprconverts the 5-bit field with a safe const match, and the driver matches the enum with no wildcard.branchandread-branchshare GNU's jump table: the register selects a slot when it is in range, and one extra slot covers an out-of-range value.read-branchreads one character first; EOF skips the table, and a suspended read resumes on the same word. Opcodes that are still unimplemented stay in one explicit arm and still signalError in CCL program.Test plan
cargo test -p neovm-core --offline --lib emacs_core::ccl::(31 passed), including GNUccl-compilevectors for the reported program, an out-of-range register, a later block, andread-branch(both blocks, the extra slot, EOF, and suspend).repro.el. The installed binary was not rebuilt here.std11-default-ccl-lexical-analyzer. It may still stop on a later unimplemented opcode (expressions, arrays,call, or an extended command).