code wiki / _hdl_build / nx_room_protocol_gate.nx
nx_room_protocol_gate.nx source
↩ module page · 192 lines · 8695 B
1import "nx_gate_base.nx"
2// nx_room_protocol_gate.nx -- the room wire/memory CONTRACT as a Nishi-owned SSOT (api-first).
3// The video room's protocol constants (linear-memory region map + lane/codec params) were hand-duplicated
4// across app.v2.js AND nishi-video.component.js AND the wasm core -- three hand-maintained copies of one
5// contract (violates rule #11 no-magic-numbers + rule #15 DRY). This organ makes NishiLang the SINGLE
6// source of truth: it (1) EMITS the documented contract web_assets/nishi_room_protocol.txt and (2) VALIDATES
7// that BOTH shipped JS clients conform to it. Any client that drifts a constant -> RED. A mobile-native
8// client consumes the SAME contract with ZERO JS. This is the "lean into nishi lang / api-first" rung.
9// expect_exit: 0 license_tier: ORIGINAL
10import "nx_syscalls.nx"
11import "nx_gate_verdict.nx"
12
13func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
14" as *u8); return ok }
15func gn(v: i64) -> i64 {
16 let b: *u8=sys_mmap(28); var m: i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m}
17 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}
18 var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1} sys_write(1,b,k); return 0 }
19
20// ---- the SSOT contract table (the ONE authoritative definition) ----
21func rp_count() -> i64 { return 23 }
22func rp_name(i: i64) -> *u8 {
23 if i==0 { return "R_ID" as *u8 }
24 if i==1 { return "R_PAY" as *u8 }
25 if i==2 { return "R_WOUT" as *u8 }
26 if i==3 { return "R_WIN" as *u8 }
27 if i==4 { return "R_INFO" as *u8 }
28 if i==5 { return "R_F32" as *u8 }
29 if i==6 { return "R_FOUT" as *u8 }
30 if i==7 { return "R_PCM" as *u8 }
31 if i==8 { return "R_SCR" as *u8 }
32 if i==9 { return "R_STAGE" as *u8 }
33 if i==10 { return "R_STAGE2" as *u8 }
34 if i==11 { return "R_FTBL" as *u8 }
35 if i==12 { return "R_FSD" as *u8 }
36 if i==13 { return "R_FSS" as *u8 }
37 if i==14 { return "R_FOUT2" as *u8 }
38 if i==15 { return "R_FSCRA" as *u8 }
39 if i==16 { return "R_FSCRSH" as *u8 }
40 if i==17 { return "R_FDEC" as *u8 }
41 if i==18 { return "R_CHAT" as *u8 }
42 if i==19 { return "R_FST" as *u8 }
43 if i==20 { return "LANES" as *u8 }
44 if i==21 { return "AUDIO_CHUNK" as *u8 }
45 if i==22 { return "R_PLAN" as *u8 }
46 return "" as *u8 }
47func rp_val(i: i64) -> i64 {
48 if i==0 { return 0x200000 }
49 if i==1 { return 0x200100 }
50 if i==2 { return 0x220000 }
51 if i==3 { return 0x240000 }
52 if i==4 { return 0x260000 }
53 if i==5 { return 0x270000 }
54 if i==6 { return 0x280000 }
55 if i==7 { return 0x290000 }
56 if i==8 { return 0x2A0000 }
57 if i==9 { return 0x300000 }
58 if i==10 { return 0x400000 }
59 if i==11 { return 0x3000000 }
60 if i==12 { return 0x3010000 }
61 if i==13 { return 0x3020000 }
62 if i==14 { return 0x3030000 }
63 if i==15 { return 0x3040000 }
64 if i==16 { return 0x3050000 }
65 if i==17 { return 0x3060000 }
66 if i==18 { return 0x3080000 }
67 if i==19 { return 0x3100000 }
68 if i==20 { return 3 }
69 if i==21 { return 1024 }
70 if i==22 { return 0x2B0000 } // mb_plan output region (9 i64) -- the resource-intelligence API
71 return 0 }
72
73func is_ic(c: i64) -> i64 {
74 if c>=48 { if c<=57 { return 1 } }
75 if c>=65 { if c<=90 { return 1 } }
76 if c>=97 { if c<=122 { return 1 } }
77 if c==95 { return 1 }
78 return 0 }
79
80// parse an integer literal at hay[p0..] -- supports 0x hex and decimal
81func parse_int_at(hay: *u8, n: i64, p0: i64) -> i64 {
82 var p: i64 = p0
83 var base: i64 = 10
84 if p+1<n { if (hay[p] as i64)==48 { if (hay[p+1] as i64)==120 { base=16; p=p+2 } } }
85 var v: i64 = 0
86 var g: i64 = 1
87 while g==1 {
88 if p<n {
89 let c: i64 = hay[p] as i64
90 var d: i64 = 0-1
91 if c>=48 { if c<=57 { d=c-48 } }
92 if base==16 { if c>=97 { if c<=102 { d=c-97+10 } } }
93 if base==16 { if c>=65 { if c<=70 { d=c-65+10 } } }
94 if d<0 { g=0 } else { v=v*base+d; p=p+1 }
95 } else { g=0 }
96 }
97 return v }
98
99// find whole-word `name` FOLLOWED BY `= <int>` (a definition, not a usage); return value or -1
100func find_word_int(hay: *u8, n: i64, name: *u8) -> i64 {
101 var nl: i64=0; while name[nl]!=(0 as u8){nl=nl+1}
102 var i: i64=0
103 while i+nl<=n {
104 var j: i64=0; var ok: i64=1
105 while j<nl { if hay[i+j]!=name[j]{ok=0;j=nl} else {j=j+1} }
106 if ok==1 {
107 var bound: i64=1
108 if i>0 { if is_ic(hay[i-1] as i64)==1 { bound=0 } }
109 if i+nl<n { if is_ic(hay[i+nl] as i64)==1 { bound=0 } }
110 if bound==1 {
111 var p: i64=i+nl
112 var g: i64=1
113 while g==1 { if p<n { if (hay[p] as i64)==32 { p=p+1 } else { g=0 } } else { g=0 } }
114 if p<n { if (hay[p] as i64)==61 {
115 p=p+1
116 var g3: i64=1
117 while g3==1 { if p<n { if (hay[p] as i64)==32 { p=p+1 } else { g3=0 } } else { g3=0 } }
118 if p<n { if (hay[p] as i64)>=48 { if (hay[p] as i64)<=57 { return parse_int_at(hay,n,p) } } }
119 } }
120 }
121 }
122 i=i+1
123 }
124 return 0 - 1 }
125
126func fw(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 }
127func fhex(fd: i64, v: i64) -> i64 {
128 sys_write(fd, "0x" as *u8, 2)
129 let t: *u8 = sys_mmap(24); var m: i64=v; var k: i64=0
130 if m==0 { t[0]=48 as u8; k=1 }
131 while m>0 { let d: i64=m%16; if d<10 { t[k]=(48+d) as u8 } else { t[k]=(97+d-10) as u8 } m=m/16; k=k+1 }
132 let b: *u8 = sys_mmap(24); var i: i64=0
133 while i<k { b[i]=t[k-1-i]; i=i+1 }
134 sys_write(fd, b, k); return 0 }
135func fdec(fd: i64, v: i64) -> i64 {
136 let t: *u8 = sys_mmap(24); var m: i64=v; var k: i64=0
137 if m==0 { t[0]=48 as u8; k=1 }
138 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 }
139 let b: *u8 = sys_mmap(24); var i: i64=0
140 while i<k { b[i]=t[k-1-i]; i=i+1 }
141 sys_write(fd, b, k); return 0 }
142
143func main() -> i64 {
144 gw("=== nx_room_protocol_gate: Nishi-owned room contract SSOT + client conformance ===\n" as *u8)
145 // read both shipped JS clients
146 let abox: *i64 = sys_mmap(16) as *i64; abox[0]=0
147 let app: *u8 = sys_read_file("sites/nishifamily/video/app.v2.js" as *u8, abox)
148 if (app as i64)==0 { gw("no app.v2.js\n" as *u8); return 1 }
149 let an: i64 = abox[0]
150 let cbox: *i64 = sys_mmap(16) as *i64; cbox[0]=0
151 let comp: *u8 = sys_read_file("sites/nishifamily/video/nishi-video.component.js" as *u8, cbox)
152 if (comp as i64)==0 { gw("no nishi-video.component.js\n" as *u8); return 1 }
153 let cn: i64 = cbox[0]
154
155 // 1. EMIT the documented contract (the SSOT artifact any client -- web OR mobile-native -- consumes)
156 let fd: i64 = sys_openat_wr("web_assets/nishi_room_protocol.txt" as *u8, 0x1a4)
157 if fd < 0 { gw("cannot write nishi_room_protocol.txt\n" as *u8); return 1 }
158 fw(fd, "# Nishi Room Protocol -- SSOT (emitted by nx_room_protocol_gate). Clients CONSUME; never hand-copy.\n" as *u8)
159 fw(fd, "# wasm linear-memory region map + lane/codec params. A mobile-native client uses these with ZERO JS.\n" as *u8)
160 var t: i64 = 0
161 while t < rp_count() {
162 fw(fd, rp_name(t)); fw(fd, "=" as *u8); fhex(fd, rp_val(t)); fw(fd, " (" as *u8); fdec(fd, rp_val(t)); fw(fd, ")\n" as *u8)
163 t = t + 1
164 }
165 sys_close(fd)
166 gw(" emitted web_assets/nishi_room_protocol.txt (" as *u8); gn(rp_count()); gw(" contract constants)\n" as *u8)
167
168 // 2. VALIDATE both clients conform to the SSOT
169 var green: i64 = 1
170 var i: i64 = 0
171 while i < rp_count() {
172 let want: i64 = rp_val(i)
173 let av: i64 = find_word_int(app, an, rp_name(i))
174 let cv: i64 = find_word_int(comp, cn, rp_name(i))
175 var okrow: i64 = 1
176 if av != want { okrow = 0 }
177 if cv != want { okrow = 0 }
178 gw(" " as *u8); gw(rp_name(i))
179 gw(" want=" as *u8); gn(want); gw(" app.v2=" as *u8); gn(av); gw(" component=" as *u8); gn(cv)
180 if okrow==1 { gw(" OK\n" as *u8) } else { gw(" !!! DRIFT\n" as *u8); green=0 }
181 i = i + 1
182 }
183 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
184 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
185 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
186 let ctr__dry: *i64 = gv_ctr()
187 ctr__dry[0] = green
188 ctr__dry[1] = 1
189 let rc__dry: i64 = gv_verdict("ROOM-PROTOCOL-GATE" as *u8, ctr__dry, "both JS clients conform to the Nishi-owned contract SSOT" as *u8)
190 sys_exit(rc__dry)
191 return rc__dry
192}