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}