code wiki / _hdl_build / nx_ascii_kat.nx
nx_ascii_kat.nx source
↩ module page · 93 lines · 4963 B
1// nx_ascii_kat.nx -- EXHAUSTIVE differential gate for nx_ascii (HONESTY SYSTEM weak point reach=267; used
2// across lexer/formatter/strconv/path -- a boundary bug there cascades). For ALL 256 byte values, each
3// classifier must equal the independently-computed ASCII ground truth -> catches every off-by-one at every
4// boundary at once (stronger than the in-file smoke). Self-validating: ground truth is inlined, not the organ.
5// license_tier: ORIGINAL expect_exit:0
6import "nx_syscalls.nx"
7import "nx_ascii.nx"
8
9func aw(s: *u8) -> i64 { var n:i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
10func an(v: i64) -> i64 { let b:*u8=sys_mmap(24); var m:i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} let t:*u8=sys_mmap(24); var k:i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var j:i64=0; while j<k{b[j]=t[k-1-j];j=j+1} sys_write(1,b,k); return 0 }
11
12// ground-truth predicates (independent of the organ)
13func gt_digit(c: i64) -> i64 { if c>=48 { if c<=57 { return 1 } } return 0 }
14func gt_lower(c: i64) -> i64 { if c>=97 { if c<=122 { return 1 } } return 0 }
15func gt_upper(c: i64) -> i64 { if c>=65 { if c<=90 { return 1 } } return 0 }
16func gt_alpha(c: i64) -> i64 { if gt_lower(c)==1 { return 1 } return gt_upper(c) }
17func gt_alnum(c: i64) -> i64 { if gt_alpha(c)==1 { return 1 } return gt_digit(c) }
18func gt_hex(c: i64) -> i64 { if gt_digit(c)==1 { return 1 } if c>=97 { if c<=102 { return 1 } } if c>=65 { if c<=70 { return 1 } } return 0 }
19func gt_space(c: i64) -> i64 { if c==32 { return 1 } if c==9 { return 1 } if c==10 { return 1 } if c==13 { return 1 } if c==11 { return 1 } if c==12 { return 1 } return 0 }
20func gt_print(c: i64) -> i64 { if c>=32 { if c<=126 { return 1 } } return 0 }
21func gt_id_start(c: i64) -> i64 { if gt_alpha(c)==1 { return 1 } if c==95 { return 1 } return 0 }
22func gt_id_cont(c: i64) -> i64 { if gt_alnum(c)==1 { return 1 } if c==95 { return 1 } return 0 }
23
24func main() -> i64 {
25 var pass: i64 = 0
26
27 // T1: is_digit / is_lower / is_upper exhaustive
28 var m1: i64 = 0
29 var c: i64 = 0
30 while c < 256 {
31 if nx_ascii_is_digit(c) != gt_digit(c) { m1 = m1 + 1 }
32 if nx_ascii_is_lower(c) != gt_lower(c) { m1 = m1 + 1 }
33 if nx_ascii_is_upper(c) != gt_upper(c) { m1 = m1 + 1 }
34 c = c + 1
35 }
36 if m1 == 0 { pass = pass + 1; aw("T1 digit/lower/upper (256x3) PASS\n" as *u8) } else { aw("T1 FAIL mismatches=" as *u8); an(m1); aw("\n" as *u8) }
37
38 // T2: is_alpha / is_alnum exhaustive
39 var m2: i64 = 0
40 c = 0
41 while c < 256 {
42 if nx_ascii_is_alpha(c) != gt_alpha(c) { m2 = m2 + 1 }
43 if nx_ascii_is_alnum(c) != gt_alnum(c) { m2 = m2 + 1 }
44 c = c + 1
45 }
46 if m2 == 0 { pass = pass + 1; aw("T2 alpha/alnum PASS\n" as *u8) } else { aw("T2 FAIL mismatches=" as *u8); an(m2); aw("\n" as *u8) }
47
48 // T3: is_id_start / is_id_cont exhaustive (the lexer's identifier rule)
49 var m3: i64 = 0
50 c = 0
51 while c < 256 {
52 if nx_ascii_is_id_start(c) != gt_id_start(c) { m3 = m3 + 1 }
53 if nx_ascii_is_id_cont(c) != gt_id_cont(c) { m3 = m3 + 1 }
54 c = c + 1
55 }
56 if m3 == 0 { pass = pass + 1; aw("T3 id_start/id_cont PASS\n" as *u8) } else { aw("T3 FAIL mismatches=" as *u8); an(m3); aw("\n" as *u8) }
57
58 // T4: is_space / is_print exhaustive
59 var m4: i64 = 0
60 c = 0
61 while c < 256 {
62 if nx_ascii_is_space(c) != gt_space(c) { m4 = m4 + 1 }
63 if nx_ascii_is_print(c) != gt_print(c) { m4 = m4 + 1 }
64 c = c + 1
65 }
66 if m4 == 0 { pass = pass + 1; aw("T4 space/print PASS\n" as *u8) } else { aw("T4 FAIL mismatches=" as *u8); an(m4); aw("\n" as *u8) }
67
68 // T5: is_hex exhaustive (a wrong bound here silently corrupts every hex/base16 decode)
69 var m5: i64 = 0
70 c = 0
71 while c < 256 { if nx_ascii_is_hex(c) != gt_hex(c) { m5 = m5 + 1 } c = c + 1 }
72 if m5 == 0 { pass = pass + 1; aw("T5 hex PASS\n" as *u8) } else { aw("T5 FAIL mismatches=" as *u8); an(m5); aw("\n" as *u8) }
73
74 // T6: to_lower / to_upper -- correct mapping + inverse consistency + idempotence
75 var m6: i64 = 0
76 c = 0
77 while c < 256 {
78 var el: i64 = c; if gt_upper(c)==1 { el = c + 32 }
79 var eu: i64 = c; if gt_lower(c)==1 { eu = c - 32 }
80 if nx_ascii_to_lower(c) != el { m6 = m6 + 1 }
81 if nx_ascii_to_upper(c) != eu { m6 = m6 + 1 }
82 // idempotence: lowering a lowered char is stable
83 if nx_ascii_to_lower(nx_ascii_to_lower(c)) != nx_ascii_to_lower(c) { m6 = m6 + 1 }
84 if nx_ascii_to_upper(nx_ascii_to_upper(c)) != nx_ascii_to_upper(c) { m6 = m6 + 1 }
85 c = c + 1
86 }
87 if m6 == 0 { pass = pass + 1; aw("T6 to_lower/to_upper (map+idempotent) PASS\n" as *u8) } else { aw("T6 FAIL mismatches=" as *u8); an(m6); aw("\n" as *u8) }
88
89 aw("NX-ASCII-KAT " as *u8); an(pass); aw("/6 (exhaustive over all 256 bytes)" as *u8)
90 if pass == 6 { aw(" GREEN\n" as *u8); return 0 }
91 aw(" RED\n" as *u8)
92 return 1
93}