code wiki / (root) / nx_field_of_struct_gate.nx

nx_field_of_struct_gate.nx source

↩ module page · 116 lines · 6792 B

1// nx_field_of_struct_gate.nx -- LN29 (lang.plan, 2026-09-02): A FIELD NAME MUST BELONG TO THE STRUCT IT IS 2// READ FROM. End-to-end over the PROMOTED compiler: two fixtures are assembled at runtime in /tmp/<gate>/ 3// (never a file a source census could mistake for an organ), the compiler is forked on each with stderr 4// captured to a file, and the teeth read the captured bytes: 5// fx_bad reads p.c on a struct declaring a and b -> MUST be refused, naming the struct, the field and 6// the fields it really declares (the teaching voice: where, caret, why, fix) 7// fx_ok reads p.a and p.b on the same struct -> MUST compile with no error line (the positive control) 8// The refusal is the LN29 contract; the control is what keeps the gate from passing on a compiler that 9// refuses everything. The "corpus builds unchanged" half of the done-rule is nx_cc_equiv_gate's job 10// (10 rows + self-host), deliberately not duplicated here (one ruler per question). 11// nx_field_of_struct_gate -- verdict in the exit code (gv_verdict) 12// license_tier: ORIGINAL layer: lang module: nishi-core.lang.field_of_struct_gate 13import "nx_syscalls.nx" 14import "nx_gate_verdict.nx" 15 16const FG_DIR: *u8 = "/tmp/nx_field_of_struct_gate\x00" as *u8 17const FG_BAD: *u8 = "/tmp/nx_field_of_struct_gate/fx_bad.nx\x00" as *u8 18const FG_OK: *u8 = "/tmp/nx_field_of_struct_gate/fx_ok.nx\x00" as *u8 19const FG_BAD_ERR: *u8 = "/tmp/nx_field_of_struct_gate/fx_bad.err\x00" as *u8 20const FG_OK_ERR: *u8 = "/tmp/nx_field_of_struct_gate/fx_ok.err\x00" as *u8 21const FG_DEVNULL: *u8 = "/dev/null\x00" as *u8 22const FG_CC_NAS: *u8 = "buildroot/_offc/nx_cc_sovereign.elf\x00" as *u8 // NAS gate CWD = nishihost root 23const FG_CC_LAP: *u8 = "_offc/nx_cc_sovereign.elf\x00" as *u8 // laptop CWD = nxc2 root 24const FG_CAP: i64 = 65536 25const FG_MODE: i64 = 420 26 27func fg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 28func fg_w(s: *u8) -> i64 { sys_write(1, s, fg_slen(s)); return 0 } 29func fg_find(b: *u8, n: i64, pat: *u8) -> i64 { 30 let pl: i64 = fg_slen(pat) 31 if pl <= 0 { return 0 - 1 } 32 var i: i64 = 0 33 while i + pl <= n { 34 var j: i64 = 0; var ok: i64 = 1 35 while j < pl { if b[i + j] != pat[j] { ok = 0; j = pl } else { j = j + 1 } } 36 if ok == 1 { return i } 37 i = i + 1 38 } 39 return 0 - 1 40} 41func fg_write_file(path: *u8, body: *u8) -> i64 { 42 let fd: i64 = sys_openat_wr(path, FG_MODE) 43 if fd < 0 { return 0 - 1 } 44 let n: i64 = fg_slen(body) 45 sys_write(fd, body, n) 46 sys_close(fd) 47 return n 48} 49// fork the compiler on src with stderr -> errpath; returns the child's exit code, -1 if it could not fork/exec. 50func fg_compile(cc: *u8, src: *u8, errpath: *u8) -> i64 { 51 let pid: i64 = sys_fork() 52 if pid < 0 { return 0 - 1 } 53 if pid == 0 { 54 let dn: i64 = sys_openat_wr(FG_DEVNULL, FG_MODE) 55 if dn >= 0 { sys_dup3(dn, 1, 0) } 56 let ef: i64 = sys_openat_wr(errpath, FG_MODE) 57 if ef >= 0 { sys_dup3(ef, 2, 0) } 58 let argv: *i64 = sys_mmap(32) as *i64 59 argv[0] = cc as i64; argv[1] = src as i64; argv[2] = 0 60 let envp: *i64 = sys_mmap(16) as *i64; envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64; envp[1] = 0 61 sys_execve(cc, argv, envp) 62 sys_exit(127) 63 } 64 let st: *i64 = sys_mmap(16) as *i64 65 sys_wait4(pid, st, 0) 66 return (st[0] >> 8) & 0xff 67} 68func fg_read(path: *u8, buf: *u8, cap: i64) -> i64 { 69 let fd: i64 = sys_openat_rd(path) 70 if fd < 0 { return 0 - 1 } 71 var tot: i64 = 0; var go: i64 = 1 72 while go == 1 { 73 let n: i64 = sys_read(fd, ((buf as i64) + tot) as *u8, cap - tot) 74 if n <= 0 { go = 0 } else { tot = tot + n; if tot >= cap { go = 0 } } 75 } 76 sys_close(fd) 77 return tot 78} 79// the promoted compiler, wherever this gate runs from (two-root probe, announced). 80func fg_pick_cc() -> *u8 { 81 let fd: i64 = sys_openat_rd(FG_CC_NAS) 82 if fd >= 0 { sys_close(fd); return FG_CC_NAS } 83 return FG_CC_LAP 84} 85 86func main() -> i64 { 87 let c: *i64 = gv_ctr() 88 sys_mkdir(FG_DIR, 493) 89 let cc: *u8 = fg_pick_cc() 90 fg_w(" compiler=" as *u8); fg_w(cc); fg_w("\n" as *u8) 91 // fixtures assembled at RUNTIME; no imports, so they resolve from any CWD (the crash guard's absence 92 // is a named non-fatal notice in the driver, not an error). 93 let wb: i64 = fg_write_file(FG_BAD, "struct Pair { a: i64, b: i64 }\nfunc main() -> i64 {\n let p: *Pair = 4096 as *Pair\n p.a = 1\n return p.c\n}\n" as *u8) 94 let wo: i64 = fg_write_file(FG_OK, "struct Pair { a: i64, b: i64 }\nfunc main() -> i64 {\n let p: *Pair = 4096 as *Pair\n p.a = 1\n p.b = 2\n return p.a + p.b\n}\n" as *u8) 95 gv_check("fixtures-written-to-tmp-gate-dir" as *u8, (wb > 0) & (wo > 0), c) 96 97 let rc_bad: i64 = fg_compile(cc, FG_BAD, FG_BAD_ERR) 98 let rc_ok: i64 = fg_compile(cc, FG_OK, FG_OK_ERR) 99 let eb: *u8 = sys_mmap(FG_CAP); let nb: i64 = fg_read(FG_BAD_ERR, eb, FG_CAP - 1) 100 let eo: *u8 = sys_mmap(FG_CAP); let no: i64 = fg_read(FG_OK_ERR, eo, FG_CAP - 1) 101 fg_w(" bad: rc=" as *u8); gv_num(rc_bad); fg_w(" stderr_bytes=" as *u8); gv_num(nb) 102 fg_w(" ok: rc=" as *u8); gv_num(rc_ok); fg_w(" stderr_bytes=" as *u8); gv_num(no); fg_w("\n" as *u8) 103 if nb > 0 { fg_w(" bad stderr head: " as *u8); var k: i64 = 0; while k < nb { if k < 160 { if eb[k] == (10 as u8) { k = nb } else { sys_write(1, ((eb as i64) + k) as *u8, 1) } } k = k + 1 } fg_w("\n" as *u8) } 104 105 gv_check("fixture-reached-the-compiler-both-ran" as *u8, (rc_bad >= 0) & (rc_ok >= 0) & (rc_bad != 127) & (rc_ok != 127), c) 106 gv_check("bad-is-refused-nonzero-exit" as *u8, rc_bad != 0, c) 107 gv_check("bad-names-the-struct-and-the-field" as *u8, fg_find(eb, nb, "struct 'Pair' has no field named 'c'" as *u8) >= 0, c) 108 gv_check("bad-carries-the-location-anchor" as *u8, fg_find(eb, nb, "error at " as *u8) >= 0, c) 109 gv_check("bad-carries-why-the-build-stopped" as *u8, fg_find(eb, nb, "why the build stopped" as *u8) >= 0, c) 110 gv_check("bad-fix-lists-the-real-fields" as *u8, fg_find(eb, nb, "fix: use one of the fields this struct declares: a, b" as *u8) >= 0, c) 111 gv_check("bad-writes-no-program" as *u8, fg_find(eb, nb, "wrote no program" as *u8) >= 0, c) 112 gv_check("control-declared-fields-compile-exit-0" as *u8, rc_ok == 0, c) 113 gv_check("control-declared-fields-print-no-error-at" as *u8, fg_find(eo, no, "error at " as *u8) < 0, c) 114 gv_check("neg-control-the-refusal-is-specific-not-blanket" as *u8, fg_find(eo, no, "has no field named" as *u8) < 0, c) 115 return gv_verdict("FIELD-OF-STRUCT-GATE" as *u8, c, "LN29: an undeclared field on a declared struct is refused by name with the real fields listed; declared fields compile" as *u8) 116}