code wiki / (root) / nx_strconv_gate.nx

nx_strconv_gate.nx source

↩ module page · 126 lines · 5343 B

1// nx_strconv_gate.nx -- the gate for the parse/format vocabulary 59 modules import. 2// WHY: nx_gensota's gen-3 worklist, rank 2 after nx_str closed. Its own header promises the 3// callers agree on "edge cases (negative MIN_I64, leading +, overflow detection, hex prefix 4// tolerance)" -- and a PROMISE IN A HEADER IS NOT A TEST. Every claim in that sentence is a 5// tooth below. 6// ★DESIGN NOTE ON THE MIN_I64 TOOTH: I did not guess a constant. The tooth asserts the SAFETY 7// property -- parsing the i64 minimum either yields the exact value OR reports overflow, and 8// NEVER a silently-wrong number. A gate that pins a guessed value is a coin flip; a gate that 9// pins the safety envelope is correct whichever branch the implementation takes. 10// license_tier: ORIGINAL expect_exit: 0 No hw writes (Rule 26). 11import "nx_syscalls.nx" 12import "nx_gate_verdict.nx" 13import "nx_strconv.nx" 14 15const NSC_BUF: i64 = 64 16const NSC_I64_MIN_STR_LEN: i64 = 20 17 18func nsc_set(p: *u8, s: *u8) -> i64 { 19 var i: i64 = 0 20 while s[i] != (0 as u8) { p[i] = s[i]; i = i + 1 } 21 p[i] = 0 as u8 22 return i 23} 24func nsc_eq(a: *u8, b: *u8) -> i64 { 25 var i: i64 = 0 26 while 1 == 1 { 27 if a[i] != b[i] { return 0 } 28 if a[i] == (0 as u8) { return 1 } 29 i = i + 1 30 } 31 return 0 32} 33 34func main() -> i64 { 35 let ctr: *i64 = gv_ctr() 36 gv_head("NX-STRCONV-GATE -- every promise in the module header made into a tooth" as *u8) 37 let err: *i64 = sys_mmap(16) as *i64 38 let s: *u8 = sys_mmap(NSC_BUF) 39 let buf: *u8 = sys_mmap(NSC_BUF) 40 41 nsc_set(s, "12345" as *u8) 42 var t1: i64 = 0 43 if nx_strconv_parse_i64(s, err) == 12345 { if err[0] == 0 { t1 = 1 } } 44 gv_check("T1 parse plain decimal, err cleared to 0" as *u8, t1, ctr) 45 46 nsc_set(s, "-42" as *u8) 47 var t2: i64 = 0 48 if nx_strconv_parse_i64(s, err) == (0 - 42) { if err[0] == 0 { t2 = 1 } } 49 nsc_set(s, "+42" as *u8) 50 if t2 == 1 { if nx_strconv_parse_i64(s, err) != 42 { t2 = 0 } } 51 gv_check("T2 HEADER PROMISE: leading - and + both accepted" as *u8, t2, ctr) 52 53 nsc_set(s, "" as *u8) 54 var t3: i64 = 0 55 if nx_strconv_parse_i64(s, err) == 0 { if err[0] == NX_STRCONV_ERR_EMPTY { t3 = 1 } } 56 nsc_set(s, "-" as *u8) 57 if t3 == 1 { nx_strconv_parse_i64(s, err); if err[0] != NX_STRCONV_ERR_EMPTY { t3 = 0 } } 58 gv_check("T3 empty AND a lone sign both report ERR_EMPTY (not 0-as-success)" as *u8, t3, ctr) 59 60 nsc_set(s, "12x4" as *u8) 61 var t4: i64 = 0 62 nx_strconv_parse_i64(s, err) 63 if err[0] == NX_STRCONV_ERR_BAD_CHAR { t4 = 1 } 64 gv_check("T4 a non-digit REJECTS the whole parse (no silent prefix-accept)" as *u8, t4, ctr) 65 66 nsc_set(s, "99999999999999999999999" as *u8) 67 var t5: i64 = 0 68 nx_strconv_parse_i64(s, err) 69 if err[0] == NX_STRCONV_ERR_OVERFLOW { t5 = 1 } 70 gv_check("T5 HEADER PROMISE: overflow DETECTED, not wrapped" as *u8, t5, ctr) 71 72 // The safety envelope, not a guessed constant -- see header. 73 nsc_set(s, "-9223372036854775808" as *u8) 74 let mv: i64 = nx_strconv_parse_i64(s, err) 75 var t6: i64 = 0 76 if err[0] == NX_STRCONV_ERR_OVERFLOW { t6 = 1 } 77 if err[0] == 0 { if mv < 0 { t6 = 1 } } 78 gv_check("T6 HEADER PROMISE (MIN_I64): exact value OR overflow -- never silently wrong" as *u8, t6, ctr) 79 80 nsc_set(s, "ff" as *u8) 81 var t7: i64 = 0 82 if nx_strconv_parse_hex(s, err) == 255 { if err[0] == 0 { t7 = 1 } } 83 nsc_set(s, "0xFF" as *u8) 84 if t7 == 1 { if nx_strconv_parse_hex(s, err) != 255 { t7 = 0 } } 85 nsc_set(s, "0XfF" as *u8) 86 if t7 == 1 { if nx_strconv_parse_hex(s, err) != 255 { t7 = 0 } } 87 gv_check("T7 HEADER PROMISE: hex prefix tolerance (bare, 0x, 0X) and MIXED case agree" as *u8, t7, ctr) 88 89 nsc_set(s, "0xzz" as *u8) 90 var t8: i64 = 0 91 nx_strconv_parse_hex(s, err) 92 if err[0] == NX_STRCONV_ERR_BAD_CHAR { t8 = 1 } 93 gv_check("T8 hex rejects non-hex digits after a valid prefix" as *u8, t8, ctr) 94 95 var t9: i64 = 0 96 if nx_strconv_format_i64(0, buf) == 1 { if nsc_eq(buf, "0" as *u8) == 1 { t9 = 1 } } 97 if t9 == 1 { if nx_strconv_format_i64(0 - 42, buf) != 3 { t9 = 0 } } 98 if t9 == 1 { if nsc_eq(buf, "-42" as *u8) == 0 { t9 = 0 } } 99 if t9 == 1 { if nx_strconv_format_i64(1000, buf) != 4 { t9 = 0 } } 100 if t9 == 1 { if nsc_eq(buf, "1000" as *u8) == 0 { t9 = 0 } } 101 gv_check("T9 format: zero / negative sign+length / interior AND trailing zeros" as *u8, t9, ctr) 102 103 // ROUND-TRIP: the property that actually matters to 59 callers. 104 var t10: i64 = 1 105 var probe: i64 = 0 - 7 106 var iter: i64 = 0 107 while iter < 6 { 108 nx_strconv_format_i64(probe, buf) 109 let back: i64 = nx_strconv_parse_i64(buf, err) 110 if err[0] != 0 { t10 = 0 } 111 if back != probe { t10 = 0 } 112 probe = probe * 13 + 5 113 iter = iter + 1 114 } 115 gv_check("T10 ROUND-TRIP format->parse is identity across 6 magnitudes, both signs" as *u8, t10, ctr) 116 117 // NEGATIVE CONTROL: the round-trip comparator must be able to fail. 118 nx_strconv_format_i64(1234, buf) 119 var t11: i64 = 0 120 if nx_strconv_parse_i64(buf, err) != 4321 { t11 = 1 } 121 gv_check("T11 NEG-CONTROL: a WRONG expected value is rejected (comparator can fail)" as *u8, t11, ctr) 122 123 let rc: i64 = gv_verdict("STRCONV-GATE" as *u8, ctr, "header promises tested; round-trip identity proven" as *u8) 124 sys_exit(rc) 125 return rc 126}