code wiki / (root) / nx_macro_axis_gate.nx

nx_macro_axis_gate.nx source

↩ module page · 116 lines · 4973 B

1// nx_macro_axis_gate.nx -- mechanically prove the BACKEND-OWNED TARGET AXIS of the self-host 2// preprocessor. Closes debt 1785516163, which asked for exactly this: a gate that FAILS if a compiled 3// corpus ever resolves TARGET_X86_64 as DEFINED, so the pin is held by a MECHANISM instead of a comment. 4// 5// WHY THIS MATTERS MORE THAN IT LOOKS. The x86 self-host emits through x86ctx_rv64_to_x86_64_syscall, 6// which expects source to carry RV64 syscall numbers and translates them at emit time. So: 7// 8// TARGET_X86_64 MUST be UNDEFINED -> the @ifndef branch (RV64 numbers) is the live one 9// TARGET_RV64 MUST be DEFINED -> the source axis, the exact complement 10// 11// If someone fixes the preprocessor by predefining TARGET_X86_64 as an ordinary macro -- the natural 12// looking change when adding a macro table -- the raw-x86 branch of nx_syscalls / nx_hal / nx_dirent / 13// nx_poll / nx_probe / nx_fcntl / nx_self_build switches on, and EVERY syscall const is then translated 14// TWICE. Silent ecosystem-wide corruption, not a build error: the binaries still link and still run, 15// they just call the wrong kernel entry points. A comment cannot stop that. This gate can. 16// 17// NON-VACUITY BY CONSTRUCTION. Every block that MUST be dropped contains a poison identifier that does 18// not exist anywhere in the corpus. If a drop path ever fails, the poison reaches the parser and THE 19// BUILD FAILS. So this gate cannot pass vacuously -- a preprocessor that ignored @ifdef entirely could 20// not compile this file at all. 21// 22// expect_exit: 0 license_tier: ORIGINAL 23 24import "nx_kernel_v2.nx" 25 26// ===== AXIS 1: TARGET_X86_64 MUST BE UNDEFINED ===== 27@ifdef TARGET_X86_64 28func axis_x86_state() -> nx_int { return BROKEN_X86_AXIS_LEAKED } 29@endif 30 31@ifndef TARGET_X86_64 32func axis_x86_state() -> nx_int { return 1 } 33@endif 34 35// ===== AXIS 2: TARGET_RV64 MUST BE DEFINED (the complement) ===== 36@ifdef TARGET_RV64 37func axis_rv64_state() -> nx_int { return 1 } 38@endif 39 40@ifndef TARGET_RV64 41func axis_rv64_state() -> nx_int { return BROKEN_RV64_AXIS_MISSING } 42@endif 43 44// ===== AXIS 3: NXC_VERSION MUST BE DEFINED (compiler identity) ===== 45@ifdef NXC_VERSION 46func axis_nxc_state() -> nx_int { return 1 } 47@endif 48 49@ifndef NXC_VERSION 50func axis_nxc_state() -> nx_int { return BROKEN_NXC_VERSION_MISSING } 51@endif 52 53// ===== AXIS 4: AN ARBITRARY UNDEFINED NAME MUST RESOLVE UNDEFINED ===== 54// Regression tooth for the ORIGINAL defect: the preprocessor compared against exactly one hardcoded 55// string, so every OTHER name resolved as DEFINED and @ifdef ANYTHING kept its block. 56@ifdef NX_AXIS_NAME_THAT_IS_NEVER_DEFINED 57func axis_unknown_state() -> nx_int { return BROKEN_UNKNOWN_NAME_TREATED_AS_DEFINED } 58@endif 59 60@ifndef NX_AXIS_NAME_THAT_IS_NEVER_DEFINED 61func axis_unknown_state() -> nx_int { return 1 } 62@endif 63 64// ===== AXIS 5: @undef MUST ACTUALLY RETRACT ===== 65@macro NX_AXIS_TEMP 1 66 67@ifdef NX_AXIS_TEMP 68func axis_undef_before() -> nx_int { return 1 } 69@endif 70 71@undef NX_AXIS_TEMP 72 73@ifdef NX_AXIS_TEMP 74func axis_undef_after() -> nx_int { return BROKEN_UNDEF_DID_NOT_RETRACT } 75@endif 76 77@ifndef NX_AXIS_TEMP 78func axis_undef_after() -> nx_int { return 1 } 79@endif 80 81func main() -> nx_exit { 82 println("=== nx_macro_axis_gate -- backend-owned target axis (debt 1785516163) ===" as *u8) 83 84 let a1: nx_int = axis_x86_state() 85 if a1 != 1 { println("T1 x86_undefined FAIL" as *u8); return 1 } 86 println("T1 x86_undefined PASS TARGET_X86_64 resolves UNDEFINED (RV64 branch is live)" as *u8) 87 88 let a2: nx_int = axis_rv64_state() 89 if a2 != 1 { println("T2 rv64_defined FAIL" as *u8); return 2 } 90 println("T2 rv64_defined PASS TARGET_RV64 resolves DEFINED (source axis)" as *u8) 91 92 let a3: nx_int = axis_nxc_state() 93 if a3 != 1 { println("T3 nxc_version FAIL" as *u8); return 3 } 94 println("T3 nxc_version PASS NXC_VERSION resolves DEFINED (compiler identity)" as *u8) 95 96 let a4: nx_int = axis_unknown_state() 97 if a4 != 1 { println("T4 unknown_undefined FAIL" as *u8); return 4 } 98 println("T4 unknown_undefined PASS an undeclared name resolves UNDEFINED, not defined" as *u8) 99 100 let a5: nx_int = axis_undef_before() 101 if a5 != 1 { println("T5 undef_before FAIL" as *u8); return 5 } 102 println("T5 undef_before PASS @ifdef before @undef kept its block" as *u8) 103 104 let a6: nx_int = axis_undef_after() 105 if a6 != 1 { println("T6 undef_after FAIL" as *u8); return 6 } 106 println("T6 undef_after PASS @undef retracted; later @ifdef dropped its block" as *u8) 107 108 println("" as *u8) 109 println("=== DROP PROOF (compile-time, no runtime check possible) ===" as *u8) 110 println("Five blocks above MUST be dropped, each holding a poison identifier that" as *u8) 111 println("exists nowhere in the corpus. Successful COMPILATION is the verdict --" as *u8) 112 println("this gate cannot pass vacuously." as *u8) 113 println("" as *u8) 114 println("GATE VERDICT: GREEN 6/6" as *u8) 115 return 0 116}