nx_closure_gate.nx
buildroot/runtime/nx_closure_gate.nx
about
nx_closure_gate.nx -- THE REFEREE FOR LN13b: the non-capturing function literal.
WHAT IS ACTUALLY AT RISK HERE, AND WHY THE TEETH ARE SHAPED THIS WAY. Admitting a new construct
is easy to observe: the compiler stops refusing it. That is the LEAST interesting thing this
gate could measure, because the pre-fix compiler refused the construct outright and any check of
compile status would go green the moment the parser stopped erroring -- including on an
implementation that lifted the wrong body. The failures worth guarding survive a clean compile:
a literal bound to the wrong code address, a parameter read from the wrong frame slot, or a
synthesized fall-off-the-end return carrying value id 0, which IS the first parameter. None of
those change the compiler's exit status; all of them change what the compiled program COMPUTES.
SO THE BEHAVIOUR AXIS IS A RUN, NOT AN ASSERTION ABOUT ASSEMBLY. nx_probe_closure_lift is a
self-checking program: it returns 0 only if every arithmetic identity in it held, and a distinct
non-zero code otherwise, so a failure names itself. This gate reads that exit code. It does NOT
inspect emitted assembly -- an asm-shaped tooth passes on a compiler that emits the right
instructions in the wrong order and fails on a compiler that improves its register allocation.
AND THE REFUSAL AXIS IS HALF THE RUNG. Rung 1 admits the EMPTY capture set and defers capture to
LN13c, so a literal reading a local of the function around it must be refused BY NAME. Without
that, the rung would silently compile a name that resolves to nothing, and this parser answers
an unresolved name with the CONSTANT ZERO -- a wrong number with no diagnostic. The refusal is
therefore not politeness; it is the only honest answer available at this rung, and the tooth
asserts the offending NAME appears in the message, not merely that something was refused.
THE DISCRIMINATION CONTROL IS LOAD-BEARING. A compiler that refused every func-typed construct
would pass the capture tooth perfectly. nx_probe_closure_named uses the PRE-EXISTING bare-name
and &name paths through the same func-typed slot; it must still compile and still run to 0. If
only that tooth fails, the lift broke a path that shipped long before it.
license_tier: ORIGINAL. Forks the compiler under test; writes only under its own /tmp dir.
No hw writes (Rule 26).
dependencies 4 imports · 0 importers
imports: nx_syscalls.nxnx_gate_verdict.nxnx_gatekit_lib.nxnx_tool_run.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 36 | const CG_CAP: i64 = 262144 |
| 37 | const CG_PATH: i64 = 4096 |
| 38 | const CG_SPAN: i64 = 8 |
| 39 | const CG_ARGV: i64 = 4 |
| 42 | const CG_SUBJ_DEFAULT: *u8 = "_offc/nx_cc_sovereign.elf" |
| 43 | const CG_ASM_A: *u8 = "_offc/nxasm_x86_main.elf" |
| 44 | const CG_ASM_B: *u8 = "_offc/nxasm_x86.elf" |
| 45 | const CG_P_LIFT: *u8 = "runtime/nx_probe_closure_lift.nx" |
| 46 | const CG_P_CAP: *u8 = "runtime/nx_probe_closure_capture.nx" |
| 47 | const CG_P_NAMED: *u8 = "runtime/nx_probe_closure_named.nx" |
| 48 | const CG_EXIT_UNRESOLVED: i64 = 3 |
| 49 | const CG_MODE_0755: i64 = 493 |
functions
| 51 | func cg_exists(p: *u8) -> i64 |
| 64 | func cg_compile(subject: *u8, src: *u8, out_s: *u8, err_p: *u8, buf: *u8, ln: *i64) -> i64 |
| 78 | func main(argc: i64, argv: **u8) -> i64 |