code wiki / _hdl_build / nx_tok_fold_gate.nx
nx_tok_fold_gate.nx source
↩ module page · 182 lines · 9084 B
1// nx_tok_fold_gate.nx -- KATs for the accent-folding UTF-8 tokenizer (the Unicode rung): Latin diacritics
2// fold to ASCII base letters on BOTH tokenize sides, unfoldable codepoints separate cleanly (whole sequence
3// consumed -- continuation bytes never leak into tokens), ASCII behavior is byte-identical to before, and
4// the STORE-LEVEL proof: an indexed doc containing "Kyōka" is found by ss_term("kyoka") and the quoted
5// phrase evaluator (fold-consistent positions). license_tier: ORIGINAL
6import "nx_seg_store.nx"
7
8func gf_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
9func gf_num(v: i64) -> i64 {
10 let bb: *u8 = sys_mmap(28); var m: i64 = v
11 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
12 let t: *u8 = sys_mmap(28); var k: i64 = 0
13 if m == 0 { t[0] = 48 as u8; k = 1 }
14 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
15 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
16 sys_write(1, bb, k); return 0
17}
18func gf_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
19func gf_check(name: *u8, cond: i64, pass: *i64, total: *i64) -> i64 {
20 total[0] = total[0] + 1
21 gf_puts(name)
22 if cond == 1 { pass[0] = pass[0] + 1; gf_puts(" PASS\n" as *u8) } else { gf_puts(" FAIL\n" as *u8) }
23 return 0
24}
25// tokenize a whole string; join tokens with '|' into out; return token count
26func gf_toks(s: *u8, out: *u8) -> i64 {
27 let tbl: *u8 = sys_mmap(272)
28 ss_tok_table(tbl)
29 let pos: *i64 = sys_mmap(16) as *i64
30 pos[0] = 0
31 let t: *u8 = sys_mmap(64)
32 var n: i64 = 0
33 var o: i64 = 0
34 let sl: i64 = gf_len(s)
35 var go: i64 = 1
36 while go == 1 {
37 let l: i64 = ss_tok_next2(s, sl, pos, t, tbl)
38 if l < 0 { go = 0 } else {
39 if n > 0 { out[o] = 124 as u8; o = o + 1 }
40 var x: i64 = 0
41 while x < l { out[o] = t[x]; o = o + 1; x = x + 1 }
42 n = n + 1
43 }
44 }
45 out[o] = 0 as u8
46 return n
47}
48func gf_eq(a: *u8, b: *u8) -> i64 {
49 var i: i64 = 0
50 var go: i64 = 1
51 while go == 1 {
52 if a[i] != b[i] { return 0 }
53 if a[i] == (0 as u8) { return 1 }
54 i = i + 1
55 }
56 return 1
57}
58
59func main() -> i64 {
60 gf_puts("=== nx_tok_fold gate (UTF-8 accent folding; ASCII purity; store-level round trip) ===\n" as *u8)
61 let pass: *i64 = sys_mmap(16) as *i64; pass[0] = 0
62 let total: *i64 = sys_mmap(16) as *i64; total[0] = 0
63 let out: *u8 = sys_mmap(512)
64
65 // T1 the operator's own case: Kyōka (U+014D)
66 let n1: i64 = gf_toks("Ky\xC5\x8Dka" as *u8, out)
67 var t1: i64 = 0
68 if n1 == 1 { if gf_eq(out, "kyoka" as *u8) == 1 { t1 = 1 } }
69 gf_check("T1 Ky\\u014Dka -> kyoka" as *u8, t1, pass, total)
70
71 // T2 Latin-1: cafe / naive / Muller
72 let n2: i64 = gf_toks("caf\xC3\xA9 na\xC3\xAFve M\xC3\xBCller" as *u8, out)
73 var t2: i64 = 0
74 if n2 == 3 { if gf_eq(out, "cafe|naive|muller" as *u8) == 1 { t2 = 1 } }
75 gf_check("T2 cafe|naive|muller (Latin-1 folds)" as *u8, t2, pass, total)
76
77 // T3 Latin-Ext-A: Škoda / žižek
78 let n3: i64 = gf_toks("\xC5\xA0koda \xC5\xBEi\xC5\xBEek" as *u8, out)
79 var t3: i64 = 0
80 if n3 == 2 { if gf_eq(out, "skoda|zizek" as *u8) == 1 { t3 = 1 } }
81 gf_check("T3 skoda|zizek (Latin-Ext-A folds)" as *u8, t3, pass, total)
82
83 // T4 multiplication sign stays a separator
84 let n4: i64 = gf_toks("ab\xC3\x97cd" as *u8, out)
85 var t4: i64 = 0
86 if n4 == 2 { if gf_eq(out, "ab|cd" as *u8) == 1 { t4 = 1 } }
87 gf_check("T4 U+00D7 times-sign separates (ab|cd)" as *u8, t4, pass, total)
88
89 // T5 CJK bigram rung BUILT (2026-07-23; replaces the old honest-limitation assertion): a 2-char
90 // Han run tokenizes as ONE bigram whose bytes are the two chars verbatim
91 let n5: i64 = gf_toks("\xE6\x97\xA5\xE6\x9C\xAC" as *u8, out)
92 var t5: i64 = 0
93 if n5 == 1 { if gf_eq(out, "\xE6\x97\xA5\xE6\x9C\xAC" as *u8) == 1 { t5 = 1 } }
94 gf_check("T5 CJK 2-char run -> ONE bigram token" as *u8, t5, pass, total)
95
96 // T6 mixed real-world line
97 let n6: i64 = gf_toks("Izumi Ky\xC5\x8Dka 1900" as *u8, out)
98 var t6: i64 = 0
99 if n6 == 3 { if gf_eq(out, "izumi|kyoka|1900" as *u8) == 1 { t6 = 1 } }
100 gf_check("T6 Izumi Ky\\u014Dka 1900 -> izumi|kyoka|1900" as *u8, t6, pass, total)
101
102 // T7 stray continuation byte never mangles
103 let n7: i64 = gf_toks("\x8Dab cd" as *u8, out)
104 var t7: i64 = 0
105 if n7 == 2 { if gf_eq(out, "ab|cd" as *u8) == 1 { t7 = 1 } }
106 gf_check("T7 stray continuation byte -> ab|cd" as *u8, t7, pass, total)
107
108 // T8 4-byte plane (emoji) consumed cleanly
109 let n8: i64 = gf_toks("\xF0\x9F\x98\x80ok yes" as *u8, out)
110 var t8: i64 = 0
111 if n8 == 2 { if gf_eq(out, "ok|yes" as *u8) == 1 { t8 = 1 } }
112 gf_check("T8 emoji consumed -> ok|yes" as *u8, t8, pass, total)
113
114 // T9 ASCII PURITY: identical to the pre-fold tokenizer on pure-ASCII text
115 let n9: i64 = gf_toks("Plain ASCII words 42 x" as *u8, out)
116 var t9: i64 = 0
117 if n9 == 4 { if gf_eq(out, "plain|ascii|words|42" as *u8) == 1 { t9 = 1 } }
118 gf_check("T9 ASCII purity (plain|ascii|words|42; 1-char x dropped)" as *u8, t9, pass, total)
119
120 // T10 STORE-LEVEL: index a doc containing the accented name; plain-ascii term + phrase both find it
121 let prefix: *u8 = "/tmp/foldgate-" as *u8
122 let w: *i64 = ss_begin()
123 ss_add(w, 1, "doc:1" as *u8, "Izumi Ky\xC5\x8Dka wrote gothic novels" as *u8, gf_len("Izumi Ky\xC5\x8Dka wrote gothic novels" as *u8))
124 ss_add(w, 1, "doc:2" as *u8, "plain control document" as *u8, 22)
125 ss_commit(prefix, w, 1)
126 let h: *i64 = ss_open(prefix)
127 let kp: *i64 = sys_mmap(8 * 16) as *i64
128 let kl: *i64 = sys_mmap(8 * 16) as *i64
129 let nt10: i64 = ss_term(h, "kyoka" as *u8, kp, kl, 16)
130 gf_check("T10 ss_term(kyoka) finds the accented doc" as *u8, (nt10 == 1) as i64, pass, total)
131
132 // T11 phrase positions fold-consistent: "izumi kyoka" adjacent
133 let terms: *i64 = sys_mmap(8 * 4) as *i64
134 terms[0] = "izumi" as *u8 as i64
135 terms[1] = "kyoka" as *u8 as i64
136 let ebox: *i64 = sys_mmap(16) as *i64
137 let np11: i64 = ss_phrase(prefix, h, terms, 2, kp, kl, 16, ebox)
138 var t11: i64 = 0
139 if np11 == 1 { if ebox[0] == 1 { t11 = 1 } }
140 gf_check("T11 phrase [izumi kyoka] exact via folded positions" as *u8, t11, pass, total)
141
142 // ==== MULTILINGUAL rung (2026-07-23): Cyrillic words + CJK overlapping bigrams + Hangul ====
143 // T12 3-char Han run -> TWO overlapping bigrams (ri-hon | hon-go)
144 let n12: i64 = gf_toks("\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E" as *u8, out)
145 var t12: i64 = 0
146 if n12 == 2 { if gf_eq(out, "\xE6\x97\xA5\xE6\x9C\xAC|\xE6\x9C\xAC\xE8\xAA\x9E" as *u8) == 1 { t12 = 1 } }
147 gf_check("T12 CJK 3-char run -> overlapping bigrams (AB|BC)" as *u8, t12, pass, total)
148
149 // T13 Russian case-fold: Moskva ROSSIYA -> lowercase Cyrillic word tokens
150 let n13: i64 = gf_toks("\xD0\x9C\xD0\xBE\xD1\x81\xD0\xBA\xD0\xB2\xD0\xB0 \xD0\xA0\xD0\x9E\xD0\xA1\xD0\xA1\xD0\x98\xD0\xAF" as *u8, out)
151 var t13: i64 = 0
152 if n13 == 2 { if gf_eq(out, "\xD0\xBC\xD0\xBE\xD1\x81\xD0\xBA\xD0\xB2\xD0\xB0|\xD1\x80\xD0\xBE\xD1\x81\xD1\x81\xD0\xB8\xD1\x8F" as *u8) == 1 { t13 = 1 } }
153 gf_check("T13 Cyrillic case-fold (Moskva ROSSIYA -> moskva|rossiya)" as *u8, t13, pass, total)
154
155 // T14 Hangul syllables -> bigram
156 let n14: i64 = gf_toks("\xED\x95\x9C\xEA\xB5\xAD" as *u8, out)
157 var t14: i64 = 0
158 if n14 == 1 { if gf_eq(out, "\xED\x95\x9C\xEA\xB5\xAD" as *u8) == 1 { t14 = 1 } }
159 gf_check("T14 Hangul 2-syllable run -> ONE bigram token" as *u8, t14, pass, total)
160
161 // T15 Latin word flushes cleanly at a CJK boundary (abc then the bigram; no byte bleed)
162 let n15: i64 = gf_toks("abc\xE6\x97\xA5\xE6\x9C\xAC" as *u8, out)
163 var t15: i64 = 0
164 if n15 == 2 { if gf_eq(out, "abc|\xE6\x97\xA5\xE6\x9C\xAC" as *u8) == 1 { t15 = 1 } }
165 gf_check("T15 latin|CJK boundary flush (abc|bigram)" as *u8, t15, pass, total)
166
167 // T16 STORE-LEVEL: Russian + CJK docs indexed and found via their native-script terms
168 let w2: *i64 = ss_begin()
169 ss_add(w2, 1, "doc:3" as *u8, "\xD0\xBD\xD0\xBE\xD0\xB2\xD0\xBE\xD1\x81\xD1\x82\xD0\xB8 \xD0\xA0\xD0\xBE\xD1\x81\xD1\x81\xD0\xB8\xD0\xB8 \xD1\x81\xD0\xB5\xD0\xB3\xD0\xBE\xD0\xB4\xD0\xBD\xD1\x8F" as *u8, 40)
170 ss_add(w2, 1, "doc:4" as *u8, "\xE6\x9D\xB1\xE4\xBA\xAC\xE5\xA4\xA7\xE5\xAD\xA6" as *u8, 12)
171 ss_commit(prefix, w2, 2)
172 let h2: *i64 = ss_open(prefix)
173 let ntru: i64 = ss_term(h2, "\xD1\x80\xD0\xBE\xD1\x81\xD1\x81\xD0\xB8\xD0\xB8" as *u8, kp, kl, 16)
174 let ntcj: i64 = ss_term(h2, "\xE6\x9D\xB1\xE4\xBA\xAC" as *u8, kp, kl, 16)
175 var t16: i64 = 0
176 if ntru == 1 { if ntcj == 1 { t16 = 1 } }
177 gf_check("T16 store-level: ss_term(rossii)=1 + ss_term(tokyo-bigram)=1" as *u8, t16, pass, total)
178
179 gf_puts("=== tok-fold gate: " as *u8); gf_num(pass[0]); gf_puts("/" as *u8); gf_num(total[0]); gf_puts(" " as *u8)
180 if pass[0] == total[0] { gf_puts("verdict=GREEN\n" as *u8); return 0 }
181 gf_puts("verdict=RED\n" as *u8); return 1
182}