C: call #1 is opcode 8 (extend)OCaml: call #1 is opcode 0 (slot), call #2 is opcode 0 (slot), call #3 is opcode 7 (compose) This means for the same input formula [2 [0 3] [0 2]], C is directly executing opcode 8, while OCaml is executing the slot lookups [0 3] and [0 2] as separate Nock calls, then getting opcode 7. The problem is likely that OCaml is treating slot lookups as full recursive Nock evaluations, when they should be internal operations. Let me check the OCaml Nock 2 implementation: | 2 -> (* Nock 2: *[subject formula new_subject] - evaluate with new subject *) (* C evaluates tail first, then head - must match this order! *) if not (is_cell gal) then raise Exit; let c_gal = tail gal in let b_gal = head gal in let nex = nock_on bus c_gal in (* Tail first like C *) let seb = nock_on bus b_gal in (* Head second like C *) nock_on seb nex The issue is that when c_gal = [0 2] and b_gal = [0 3], we're calling nock_on recursively, which logs and increments the call counter. But maybe C handles slot lookups differently—perhaps as an internal operation without logging? Let me check what C does when it encounters [0 axis] - does it call u3n_nock_on recursively, or does it handle it inline? Should I investigate the C _n_nock_on or _n_burn implementation to see how it handles Nock 0 (slot) operations? -- C logs: >>> ENTER call #0 depth=0 opcode=2 bus=cell >>> ENTER call #1 depth=1 opcode=8 bus=cell ← Goes directly to opcode 8! OCaml logs: >>> ENTER call #0 depth=0 opcode=2(eval) bus=cell >>> ENTER call #1 depth=1 opcode=0(slot) bus=cell ← Evaluates [0 3] <<< EXIT call #1 depth=1 returns=cell >>> ENTER call #2 depth=1 opcode=0(slot) bus=cell ← Evaluates [0 2] <<< EXIT call #2 depth=1 returns=cell >>> ENTER call #3 depth=1 opcode=7(compose) bus=cell ← Result is opcode 7 The problem is clear: C doesn't call u3n_nock_on recursively for simple operations like [0 axis]. Instead, C compiles the Nock formula to bytecode first, and the bytecode handles slot lookups inline without recursive nock calls. This is why C shows opcode 8 directly - the bytecode compiler has already evaluated [0 3] and [0 2] internally and determined that the next operation is opcode 8. OCaml, on the other hand, is a pure interpreter - every Nock formula, even simple ones like [0 3], goes through nock_on recursively. This is not a bug in OCaml - it's the correct interpreter behavior! C's bytecode is an optimization. To make OCaml match C's log output, we'd need to either: 1. Add bytecode compilation to OCaml (major work) 2. Inline simple operations like slot lookup in Nock 2 (quick fix but changes the interpreter structure) 3. Accept that the logs will differ at this level but verify the final results match Would you like me to inline slot lookups in Nock 2 to reduce the logging noise, or should we focus on verifying that despite the different execution paths, both C and OCaml produce the same final results?