code wiki / (root) / nx_str_gate.nx

nx_str_gate.nx source

↩ module page · 95 lines · 4972 B

1// nx_str_gate.nx -- the gate for the string vocabulary 109 modules import. 2// WHY: nx_gensota's gen-3 worklist ranked it #3 by importers with no gate sibling. It DOES 3// carry a self-test -- inside its own main() -- and that is precisely the problem: 4// expand_imports STRIPS func main from every non-root file, so that self-test runs ONLY when 5// someone deliberately builds nx_str.nx as an entry point, which nothing does routinely, and 6// NO rollup can read its result. 7// ★LAW: A SELF-TEST INSIDE THE MODULE'S OWN main() IS STRIPPED FROM EVERY CONSUMER AND 8// INVISIBLE TO EVERY RULER -- it is documentation that happens to compile. 9// This gate re-derives the contract from OUTSIDE, in the ruler-readable shape. 10// ⚠FINDING PINNED, NOT SILENTLY FIXED (T9/T10): nx_str_chr(s,0) returns the TERMINATOR index 11// (C strchr convention) while nx_str_rchr(s,0) returns -1. The pair DISAGREES on the NUL 12// convention. 109 importers may depend on either; this gate PINS today's behaviour so any 13// future change is a loud diff, and the asymmetry is declared rather than quietly aligned. 14// license_tier: ORIGINAL expect_exit: 0 No hw writes (Rule 26). 15import "nx_syscalls.nx" 16import "nx_gate_verdict.nx" 17import "nx_str.nx" 18 19const NSG_BUF: i64 = 64 20 21func nsg_lit3(p: *u8, a: i64, b: i64, c: i64) -> i64 { 22 p[0] = a as u8; p[1] = b as u8; p[2] = c as u8; p[3] = 0 as u8 23 return 0 24} 25 26func main() -> i64 { 27 let ctr: *i64 = gv_ctr() 28 gv_head("NX-STR-GATE -- the string vocabulary 109 modules import, verified from OUTSIDE" as *u8) 29 30 let foo: *u8 = sys_mmap(NSG_BUF) 31 nsg_lit3(foo, 0x66, 0x6F, 0x6F) // "foo" 32 let bar: *u8 = sys_mmap(NSG_BUF) 33 nsg_lit3(bar, 0x62, 0x61, 0x72) // "bar" 34 let empty: *u8 = sys_mmap(NSG_BUF) 35 empty[0] = 0 as u8 36 let foobar: *u8 = sys_mmap(NSG_BUF) 37 nx_str_cpy(foobar, foo) 38 nx_str_cat(foobar, bar) // "foobar" 39 40 var t1: i64 = 0 41 if nx_str_len(foo) == 3 { if nx_str_len(empty) == 0 { if nx_str_len(foobar) == 6 { t1 = 1 } } } 42 gv_check("T1 len: 3 / 0 (empty) / 6 (after cpy+cat)" as *u8, t1, ctr) 43 44 var t2: i64 = 0 45 if nx_str_eq(foo, foo) == 1 { if nx_str_eq(foo, bar) == 0 { if nx_str_eq(foo, foobar) == 0 { t2 = 1 } } } 46 gv_check("T2 eq: reflexive; differs; PREFIX is not equality" as *u8, t2, ctr) 47 48 var t3: i64 = 0 49 if nx_str_cmp(foo, foo) == 0 { if nx_str_cmp(bar, foo) < 0 { if nx_str_cmp(foo, bar) > 0 { t3 = 1 } } } 50 gv_check("T3 cmp: 0 equal, sign follows byte order (bar<foo)" as *u8, t3, ctr) 51 52 var t4: i64 = 0 53 if nx_str_cmp(foo, foobar) < 0 { if nx_str_cmp(foobar, foo) > 0 { t4 = 1 } } 54 gv_check("T4 cmp: a PREFIX sorts before its extension, both directions" as *u8, t4, ctr) 55 56 var t5: i64 = 0 57 if nx_str_starts_with(foobar, foo) == 1 { if nx_str_starts_with(foo, foobar) == 0 { if nx_str_starts_with(foo, empty) == 1 { t5 = 1 } } } 58 gv_check("T5 starts_with: true / longer-prefix false / EMPTY prefix is true" as *u8, t5, ctr) 59 60 var t6: i64 = 0 61 if nx_str_ends_with(foobar, bar) == 1 { if nx_str_ends_with(foobar, foo) == 0 { if nx_str_ends_with(foo, empty) == 1 { t6 = 1 } } } 62 gv_check("T6 ends_with: true / a PREFIX is not a suffix / EMPTY suffix is true" as *u8, t6, ctr) 63 64 var t7: i64 = 0 65 if nx_str_str(foobar, bar) == 3 { if nx_str_str(foo, bar) == (0 - 1) { if nx_str_str(foo, empty) == 0 { t7 = 1 } } } 66 gv_check("T7 str: offset 3 / absent -1 / EMPTY needle matches at 0" as *u8, t7, ctr) 67 68 let dst: *u8 = sys_mmap(NSG_BUF) 69 nx_str_memset(dst, 0x41, 4) 70 dst[4] = 0 as u8 71 var t8: i64 = 0 72 if nx_str_len(dst) == 4 { if dst[0] == (0x41 as u8) { if dst[3] == (0x41 as u8) { t8 = 1 } } } 73 nx_str_memcpy(dst, foo, 3) 74 if t8 == 1 { if nx_str_memcmp(dst, foo, 3) != 0 { t8 = 0 } } 75 gv_check("T8 memset fills exactly n; memcpy then memcmp round-trips" as *u8, t8, ctr) 76 77 // PINNED ASYMMETRY -- see header. Not an assertion that this is RIGHT, an assertion that 78 // it is what 109 importers get today. 79 var t9: i64 = 0 80 if nx_str_chr(foobar, 0x62) == 3 { if nx_str_chr(foo, 0x62) == (0 - 1) { if nx_str_chr(foo, 0) == 3 { t9 = 1 } } } 81 gv_check("T9 chr: found / absent -1 / PINNED: chr(s,0) returns the TERMINATOR index" as *u8, t9, ctr) 82 83 var t10: i64 = 0 84 if nx_str_rchr(foobar, 0x6F) == 2 { if nx_str_rchr(foo, 0) == (0 - 1) { t10 = 1 } } 85 gv_check("T10 rchr: LAST occurrence / PINNED: rchr(s,0) returns -1 (DISAGREES with chr)" as *u8, t10, ctr) 86 87 // NEGATIVE CONTROL: the comparators must be capable of saying NO. 88 var t11: i64 = 0 89 if nx_str_eq(foo, bar) == 0 { if nx_str_str(foo, bar) < 0 { if nx_str_ends_with(foo, bar) == 0 { t11 = 1 } } } 90 gv_check("T11 NEG-CONTROL: unrelated strings REJECTED by eq, str and ends_with" as *u8, t11, ctr) 91 92 let rc: i64 = gv_verdict("STR-GATE" as *u8, ctr, "vocabulary verified from outside; NUL asymmetry pinned" as *u8) 93 sys_exit(rc) 94 return rc 95}