code wiki / _hdl_build / nx_stem_gate.nx
nx_stem_gate.nx source
↩ module page · 63 lines · 5197 B
1// nx_stem_gate.nx -- KAT for R-UX-2 (nx_stem): Porter Step 1a on real andelinwest/search vocabulary. expect_exit: 0
2import "nx_syscalls.nx"
3import "nx_stem.nx"
4
5func st_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
6func st_putb(p: *u8, n: i64) -> i64 { if n>0 { sys_write(1,p,n) } return 0 }
7func st_pn(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)}; let t: *u8=sys_mmap(28); 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 i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(1,bb,k); return 0 }
8func st_w(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
9func st_wn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; let t: *u8=sys_mmap(28); 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 i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(fd,bb,k); return 0 }
10func st_len(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
11
12// stem `word` and check the result == `expect` (length + bytes). prints the row. returns 1 pass / 0 fail.
13func st_case(word: *u8, expect: *u8) -> i64 {
14 let buf: *u8=sys_mmap(64)
15 let wl: i64=st_len(word)
16 var i: i64=0; while i<wl { buf[i]=word[i]; i=i+1 }
17 let nl: i64=vr_stem(buf, wl)
18 let el: i64=st_len(expect)
19 var ok: i64=1
20 if nl!=el { ok=0 } else { var j: i64=0; while j<nl { if buf[j]!=expect[j] { ok=0; j=nl } else { j=j+1 } } }
21 st_puts(" " as *u8); st_putb(word, wl); st_puts(" -> " as *u8); st_putb(buf, nl)
22 st_puts(" exp=" as *u8); st_putb(expect, el); st_puts(" " as *u8)
23 if ok==1 { st_puts("PASS\n" as *u8) } else { st_puts("FAIL\n" as *u8) }
24 return ok
25}
26
27func main() -> i64 {
28 st_puts("=== R-UX-2 STEMMING -- Porter Step 1a (plural normalization) on real search vocab ===\n" as *u8)
29 var pass: i64=0; var total: i64=0
30 total=total+1; pass=pass + st_case("plans\x00" as *u8, "plan\x00" as *u8) // s
31 total=total+1; pass=pass + st_case("claims\x00" as *u8, "claim\x00" as *u8) // s
32 total=total+1; pass=pass + st_case("contracts\x00" as *u8, "contract\x00" as *u8) // s
33 total=total+1; pass=pass + st_case("trusts\x00" as *u8, "trust\x00" as *u8) // s
34 total=total+1; pass=pass + st_case("businesses\x00" as *u8, "business\x00" as *u8) // sses->ss
35 total=total+1; pass=pass + st_case("families\x00" as *u8, "famili\x00" as *u8) // ies->i (Porter)
36 total=total+1; pass=pass + st_case("business\x00" as *u8, "business\x00" as *u8) // ss unchanged
37 total=total+1; pass=pass + st_case("car\x00" as *u8, "car\x00" as *u8) // no-s unchanged
38
39 // ---- PORTER-LITE conflation (2026-07-03 upgrade): -ed/-ing/-ly + derivational + over-stem safety ----
40 st_puts("-- conflation (variants share a stem; distinct words must not) --\n" as *u8)
41 total=total+1; pass=pass + st_case("running\x00" as *u8, "run\x00" as *u8) // ing + de-double
42 total=total+1; pass=pass + st_case("ranked\x00" as *u8, "rank\x00" as *u8) // ed
43 total=total+1; pass=pass + st_case("ranking\x00" as *u8, "rank\x00" as *u8) // ing
44 total=total+1; pass=pass + st_case("indexing\x00" as *u8, "index\x00" as *u8) // ing
45 total=total+1; pass=pass + st_case("crawling\x00" as *u8, "crawl\x00" as *u8) // ing
46 total=total+1; pass=pass + st_case("computing\x00" as *u8, "comput\x00" as *u8) // ing
47 total=total+1; pass=pass + st_case("computed\x00" as *u8, "comput\x00" as *u8) // ed (same stem as computing)
48 // NEG over-stemming: distinct words must NOT collapse to the same root
49 let sa: *u8=sys_mmap(64); let sb: *u8=sys_mmap(64)
50 var i9: i64=0; while i9<3 { sa[i9]="run\x00"[i9]; i9=i9+1 } let la: i64=vr_stem(sa,3)
51 i9=0; while i9<4 { sb[i9]="rank\x00"[i9]; i9=i9+1 } let lb: i64=vr_stem(sb,4)
52 var diff: i64=1; if la==lb { var j9: i64=0; var eq: i64=1; while j9<la { if sa[j9]!=sb[j9] { eq=0; j9=la } else { j9=j9+1 } } if eq==1 { diff=0 } }
53 total=total+1; pass=pass+diff
54 st_puts(" NEG run != rank distinct: "); if diff==1 { st_puts("PASS\n") } else { st_puts("FAIL\n") }
55
56 st_puts("----\nSTEM gate " as *u8); st_pn(pass); st_puts("/" as *u8); st_pn(total); st_puts(" passed\n" as *u8)
57 st_puts("HONEST: Porter Step 1a (plural) only -- no irregulars (children->child needs a lexicon); fuller Porter\n" as *u8)
58 st_puts(" steps are the named extension. Recall win: query 'plan' now reaches docs that say 'plans'.\n" as *u8)
59 let lg: i64=sys_openat_append("knowledge/status/stem_gate.log" as *u8, 0x1a4)
60 if lg>=0 { st_w(lg, "R-UX-2 stem gate pass=" as *u8); st_wn(lg, pass); st_w(lg, "/" as *u8); st_wn(lg, total); if pass==total { st_w(lg, " GREEN\n" as *u8) } else { st_w(lg, " RED\n" as *u8) } sys_close(lg) }
61 if pass==total { st_puts("R-UX-2 GREEN (sovereign Porter-lite stemming: plurals + -ed/-ing/-ly + derivational, over-stem-guarded)\n" as *u8); sys_exit(0); return 0 }
62 st_puts("R-UX-2 RED\n" as *u8); sys_exit(1); return 1
63}