code wiki / (root) / nx_langsem_gate.nx

nx_langsem_gate.nx source

↩ module page · 155 lines · 9453 B

1// nx_langsem_gate.nx -- THE EXECUTABLE RECORD OF NISHILANG'S OWN SEMANTICS. 2// 3// WHY THIS EXISTS. Every fact below was learned by a seat the expensive way -- by a build failing, 4// by a test that quietly could not fail, or by an extraction that happened to work -- and then 5// written into prose that the next seat may or may not read. Prose is not a control. These are the 6// language's load-bearing behaviours, and until now NOTHING asserted them, so a compiler change 7// could alter one and the estate would find out through a silently wrong world, a silently 8// unshared static, or a comparison that never matches. 9// 10// Measured 2026-08-28 with nx_spendgate: no incumbent gates NishiLang semantics (nx_bless_compiler 11// self-deploys the compiler; nx_cc_equiv_gate proves an OPTIMISATION is equivalent; neither pins 12// the contract a source author writes against). So this is the missing referee, not a duplicate. 13// 14// WHAT IT DELIBERATELY DOES NOT PIN, stated so absence is not read as coverage: 15// * define-before-use. NishiLang is single-pass and the compiler REFUSES a const used above its 16// declaration; asserting a REFUSAL needs a fork of the compiler over a bad fixture, which is a 17// different (and heavier) gate than this in-process one. Named here as the owed rung. 18// * right-shift sign behaviour on negatives. I have no measured evidence for it in the record, 19// and a gate must not encode a guess: a tooth asserting the wrong answer would be worse than 20// no tooth, because it would read as coverage. Owed: measure it, then pin it. 21// 22// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 23import "nx_syscalls.nx" 24import "nx_gate_verdict.nx" 25import "nx_langsem_lib.nx" 26 27// the gate's OWN module static, to prove zero-initialisation on this side of the import too 28static LG_OWN: i64 29const LG_WRITE_A: i64 = 12345 30const LG_WRITE_B: i64 = 6789 31const LG_INTERNAL: i64 = 999 32 33func main() -> i64 { 34 let ctr: *i64 = gv_ctr() 35 gv_head("=== nx_langsem_gate -- NishiLang's own semantics, asserted not assumed ===" as *u8) 36 37 // ---- ZERO INITIALISATION ------------------------------------------------------------- 38 // Every arena-and-static discipline in the estate assumes a static starts at 0 (nx_worldpipe 39 // guards its bake with `if WP_HYD == 0`, the engine calls a zero region "no overrides by 40 // construction"). If statics ever started as garbage, those guards would fire at random. 41 gv_puts(" own-static=" as *u8); gv_num(LG_OWN) 42 gv_puts(" lib-untouched-static=" as *u8); gv_num(ls_untouched()); gv_puts("\n" as *u8) 43 var t1: i64 = 0 44 if LG_OWN == 0 { if ls_untouched() == 0 { t1 = 1 } } 45 gv_check("statics-are-zero-initialised-in-both-modules" as *u8, t1, ctr) 46 47 // ---- CROSS-MODULE CONST VISIBILITY --------------------------------------------------- 48 var t2: i64 = 0 49 if LS_CONST_ANSWER == 424242 { t2 = 1 } 50 gv_check("importer-reads-a-const-declared-in-an-imported-lib" as *u8, t2, ctr) 51 52 // ---- CROSS-MODULE STATIC ASSIGNMENT: THE LOAD-BEARING ONE ---------------------------- 53 // This is the fact the shared-core/base-class pattern rests on. nx_worldpipe_core owns 54 // WP_SEED and nx_worldpipe assigns it; if these were per-module copies the extracted core 55 // would generate terrain from a seed of 0 while its owner believed it had set one -- a 56 // silently wrong world, not a build error. Three legs: the importer's write is visible to 57 // the importer, it is visible INSIDE the declaring module, and a second write moves it (so 58 // the first result cannot be a coincidence of initial values). 59 LS_SHARED = LG_WRITE_A 60 let seen_here_a: i64 = LS_SHARED 61 let seen_there_a: i64 = ls_get() 62 LS_SHARED = LG_WRITE_B 63 let seen_here_b: i64 = LS_SHARED 64 let seen_there_b: i64 = ls_get() 65 gv_puts(" wrote " as *u8); gv_num(LG_WRITE_A) 66 gv_puts(" -> importer sees " as *u8); gv_num(seen_here_a) 67 gv_puts(", lib sees " as *u8); gv_num(seen_there_a) 68 gv_puts(" | wrote " as *u8); gv_num(LG_WRITE_B) 69 gv_puts(" -> importer sees " as *u8); gv_num(seen_here_b) 70 gv_puts(", lib sees " as *u8); gv_num(seen_there_b); gv_puts("\n" as *u8) 71 var t3: i64 = 0 72 if seen_here_a == LG_WRITE_A { if seen_here_b == LG_WRITE_B { t3 = 1 } } 73 gv_check("importer-may-ASSIGN-a-static-declared-in-an-imported-lib" as *u8, t3, ctr) 74 var t4: i64 = 0 75 if seen_there_a == LG_WRITE_A { if seen_there_b == LG_WRITE_B { t4 = 1 } } 76 gv_check("the-lib-SEES-the-importers-write-one-storage-not-a-copy" as *u8, t4, ctr) 77 78 // and the reverse direction: the lib writes, the importer sees it 79 ls_set(LG_INTERNAL) 80 var t5: i64 = 0 81 if LS_SHARED == LG_INTERNAL { t5 = 1 } 82 gv_check("the-importer-SEES-the-libs-write-same-storage-both-ways" as *u8, t5, ctr) 83 84 // ---- INTEGER DIVISION TRUNCATES TOWARD ZERO ------------------------------------------ 85 // Not a curiosity: the estate has been bitten by it repeatedly. wc_er_flux is antisymmetric 86 // ONLY because truncation is toward zero; a threshold written `x > y*N/M` truncates the bar 87 // DOWNWARD (a whole latent false-pass class, debt 1785565607); and nx_softdyn's damping term 88 // (v*C)/SD_G truncates to a dead zone that made a measured plant three times less damped than 89 // its own coefficient implied. If division ever floored instead, every one of those changes 90 // meaning -- silently, in the direction of "still compiles, still runs". 91 let dpos: i64 = 7/2 92 let dneg: i64 = (0 - 7)/2 93 let mpos: i64 = 7%2 94 let mneg: i64 = (0 - 7)%2 95 gv_puts(" 7/2=" as *u8); gv_num(dpos) 96 gv_puts(" -7/2=" as *u8); gv_num(dneg) 97 gv_puts(" 7%2=" as *u8); gv_num(mpos) 98 gv_puts(" -7%2=" as *u8); gv_num(mneg); gv_puts("\n" as *u8) 99 var t6: i64 = 0 100 if dpos == 3 { if dneg == 0 - 3 { t6 = 1 } } 101 gv_check("integer-division-TRUNCATES-toward-zero-both-signs" as *u8, t6, ctr) 102 // NEGATIVE CONTROL, named so the gate-law census can see it: floor division would give -4. 103 // This tooth fails the day the language changes that, which is exactly when the estate's 104 // antisymmetry and threshold arithmetic would start lying. 105 var t7: i64 = 0 106 if dneg != 0 - 4 { t7 = 1 } 107 gv_check("neg-control-division-is-NOT-floor-semantics" as *u8, t7, ctr) 108 var t8: i64 = 0 109 if mpos == 1 { if mneg == 0 - 1 { t8 = 1 } } 110 gv_check("modulo-sign-FOLLOWS-the-dividend-consistent-with-truncation" as *u8, t8, ctr) 111 112 // the same arithmetic evaluated INSIDE the other module: a compiler that changed division 113 // only in one translation unit would be caught here and nowhere else in the estate 114 let probe: i64 = ls_divmod_probe(0 - 7, 2) 115 gv_puts(" cross-module divmod probe(-7,2)=" as *u8); gv_num(probe) 116 gv_puts(" (want " as *u8); gv_num((0 - 3)*100 + (0 - 1)); gv_puts(")\n" as *u8) 117 var t9: i64 = 0 118 if probe == (0 - 3)*100 + (0 - 1) { t9 = 1 } 119 gv_check("division-and-modulo-agree-ACROSS-a-module-boundary" as *u8, t9, ctr) 120 121 // ---- INLINE-CAST STRING INDEXING ----------------------------------------------------- 122 // Pinned because its failure mode was the worst kind the estate has recorded: before the 123 // 2026-08-13 compiler fix, `("lit" as *u8)[j]` compiled clean and simply NEVER COMPARED EQUAL, 124 // so the only symptom was a test that quietly could not fail. It was found solely because a 125 // gv_bite tooth reported VACUOUS instead of passing. A regression here would be invisible 126 // again, so it gets a tooth of its own. 127 let c0: i64 = ("abc" as *u8)[0] as i64 128 let c1: i64 = ("abc" as *u8)[1] as i64 129 let c2: i64 = ("abc" as *u8)[2] as i64 130 gv_puts(" inline-cast index abc -> " as *u8); gv_num(c0) 131 gv_puts(" " as *u8); gv_num(c1) 132 gv_puts(" " as *u8); gv_num(c2); gv_puts(" (want 97 98 99)\n" as *u8) 133 var t10: i64 = 0 134 if c0 == 97 { if c1 == 98 { if c2 == 99 { t10 = 1 } } } 135 gv_check("inline-cast-string-literal-INDEXES-correctly" as *u8, t10, ctr) 136 // and it must EQUAL the same byte read through a hoisted binding -- the workaround the fix 137 // retired. If these two ever disagree the fix has regressed in one path only. 138 let hoisted: *u8 = "abc" as *u8 139 var t11: i64 = 0 140 if hoisted[1] as i64 == c1 { t11 = 1 } 141 gv_check("inline-cast-and-hoisted-binding-READ-THE-SAME-BYTE" as *u8, t11, ctr) 142 143 // ---- BITE CELL: the comparison itself must be capable of failing --------------------- 144 // The vacuity guard for this whole gate. If equality on these values could not distinguish, 145 // every tooth above would pass for free. bad = a comparison that MUST be false; good = one 146 // that MUST be true. 147 var bad: i64 = 0 148 var good: i64 = 0 149 if c1 == 97 { bad = 1 } 150 if c1 == 98 { good = 1 } 151 gv_bite("neg-control-equality-can-distinguish-97-from-98" as *u8, good, bad, ctr) 152 153 return gv_verdict("LANGSEM-GATE" as *u8, ctr, 154 "NishiLang's load-bearing semantics are now asserted, not folklore: statics zero-init, cross-module const AND static visibility with ONE storage in both directions (the fact the shared-core pattern rests on), truncation-toward-zero division with a named floor-semantics neg-control, and inline-cast string indexing pinned against the silent-miscompare class. NOT pinned yet, and said so: define-before-use refusal (needs a compiler fork) and right-shift sign on negatives (no measured evidence -- a guess would read as coverage)." as *u8) 155}