code wiki / _hdl_build / nx_lang_export_grow.nx
nx_lang_export_grow.nx source
↩ module page · 505 lines · 31030 B
1// nx_lang_export_grow.nx -- LANG-EXPORT-GROW: IR-driven multi-language codegen.
2// Advance over 002: the PROGRAM is now a NEUTRAL IR (knowledge/registry/lang_export_program.tsv, a
3// statement list) and each LANGUAGE is a set of per-CONSTRUCT templates (lang_export_constructs.tsv).
4// The engine WALKS the IR emitting each statement via the target language's construct-templates (with
5// depth-indent), so BOTH program and language are DATA -- the whole-organ architecture in miniature.
6// HONEST TRUTH: the organ also INTERPRETS the same IR (tiny evaluator) for the native value, so the
7// Nishi truth is literally the IR evaluated (the wheeler flip: Nishi = oracle). GATE = gcc/node/python
8// on the emitted source must each reproduce that truth. GROW = more constructs + nesting + wiring nxc2's
9// frontend to PRODUCE this IR so whole real organs export. license_tier: ORIGINAL
10import "nx_syscalls.nx"
11const K_MAGIC_8192: i64 = 8192
12
13func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
14func puts(s: *u8) -> i64 { sys_write(1, s, slen(s)); return 0 }
15func catn(dst: *u8, off: i64, v: i64) -> i64 {
16 var o: i64 = off
17 var m: i64 = v
18 if m < 0 { dst[o] = (45 as u8); o = o + 1; m = 0 - m }
19 let t: *u8 = sys_mmap(28)
20 var k: i64 = 0
21 if m == 0 { t[0] = (48 as u8); k = 1 }
22 while m > 0 { t[k] = ((48 + (m % 10)) as u8); m = m / 10; k = k + 1 }
23 var i: i64 = 0
24 while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 }
25 return o + k
26}
27func putn(v: i64) -> i64 { let b: *u8 = sys_mmap(28); let o: i64 = catn(b, 0, v); sys_write(1, b, o); return 0 }
28func cat(dst: *u8, off: i64, s: *u8) -> i64 { var o: i64 = off; var i: i64 = 0; while s[i] != (0 as u8) { dst[o] = s[i]; o = o + 1; i = i + 1 } return o }
29func copyslice(out: *u8, o: i64, src: *u8, start: i64, len: i64) -> i64 { var oo: i64 = o; var j: i64 = 0; while j < len { out[oo] = src[start + j]; oo = oo + 1; j = j + 1 } return oo }
30func scant(buf: *u8, start: i64, end: i64) -> i64 { var p: i64 = start; var g: i64 = 1; while g == 1 { if p >= end { g = 0 } else { if buf[p] == (9 as u8) { g = 0 } else { p = p + 1 } } } return p }
31func parseint(buf: *u8, start: i64, len: i64) -> i64 { var v: i64 = 0; var i: i64 = 0; while i < len { v = v * 10 + ((buf[start + i] as i64) - 48); i = i + 1 } return v }
32func readfile(path: *u8, buf: *u8, cap: i64) -> i64 {
33 let fd: i64 = sys_openat_rd(path)
34 if fd < 0 { return 0 - 1 }
35 var n: i64 = 0
36 var go: i64 = 1
37 while go == 1 { let r: i64 = sys_read(fd, ((buf as i64) + n) as *u8, cap - n); if r <= 0 { go = 0 } else { n = n + r } if n >= cap { go = 0 } }
38 sys_close(fd)
39 return n
40}
41func wfile(path: *u8, buf: *u8, n: i64) -> i64 { let fd: i64 = sys_openat_wr(path, 420); if fd < 0 { return 0 - 1 } sys_write(fd, buf, n); sys_close(fd); return 0 }
42
43// read one whitespace-separated token in buf[pos..end): res[0]=start res[1]=len res[2]=newpos; ret 1 if found.
44func tok(buf: *u8, pos: i64, end: i64, res: *i64) -> i64 {
45 var p: i64 = pos
46 var sg: i64 = 1
47 while sg == 1 { if p >= end { sg = 0 } else { if buf[p] == (32 as u8) { p = p + 1 } else { if buf[p] == (9 as u8) { p = p + 1 } else { sg = 0 } } } }
48 if p >= end { res[2] = p; return 0 }
49 let st: i64 = p
50 var eg: i64 = 1
51 while eg == 1 { if p >= end { eg = 0 } else { if buf[p] == (32 as u8) { eg = 0 } else { if buf[p] == (9 as u8) { eg = 0 } else { p = p + 1 } } } }
52 res[0] = st; res[1] = p - st; res[2] = p
53 return 1
54}
55// opcode from the op word: V=1 LOOP=2 SET=3 ENDLOOP=4 PRINT=5 IF=6 ENDIF=7 HASH=8.
56// ENDFUNC=9 FUNC=10 RET=11 CALL=12 RETV=13 IFNZ=14 DEC=15 BIN=16 (IFNZ <var>=if var!=0; DEC <dst> <src>=
57// dst=src-1; BIN <lhs> <a> <op> <b>=general binary op lhs=a<op>b, op in + - * % carried AS DATA in operand2).
58// IDIV=17 (<lhs> <a> <b>=integer floor-division lhs=a/b; faithful via per-lang int-div templates -- the one
59// operator whose semantics differ, so it is NOT a BIN operator). IFC=18 (<a> <cmp> <b>=general comparison
60// if a<cmp>b, cmp in < > == != <= >= carried AS DATA in operand1). IF/IFNZ/IDIV/IFC all start 'I' -> IDIV has
61// 'D' at char[1] (I-D-I-V); else char[2]: 'N' IFNZ, 'C' IFC, ' ' IF.
62// ADIM=19 AST=20 ALD=21 (integer arrays: ADIM <arr> <size> declare; AST <arr> <idx> <val> arr[idx]=val;
63// ALD <dst> <arr> <idx> dst=arr[idx]). All start 'A' -> disambiguate char[1]: 'D' ADIM, 'S' AST, 'L' ALD.
64// SP=22 (SP <word>=print a string literal). SET/SP both start 'S' -> char[1] 'P' for SP, 'E' for SET.
65// RET/RETV both start 'R', disambiguate on char[3]: RETV has 'V' there, RET has a space.
66// ENDLOOP/ENDIF/ENDFUNC all start 'E' -> disambiguate on char[3] (L=ENDLOOP, F=ENDFUNC, else ENDIF).
67func op_of(buf: *u8, start: i64) -> i64 {
68 let c0: i64 = buf[start] as i64
69 if c0 == 86 { return 1 }
70 if c0 == 76 { return 2 }
71 if c0 == 83 { if buf[start + 1] == (80 as u8) { return 22 } return 3 }
72 if c0 == 80 { return 5 }
73 if c0 == 73 { if buf[start + 1] == (68 as u8) { return 17 } if buf[start + 2] == (78 as u8) { return 14 } if buf[start + 2] == (67 as u8) { return 18 } return 6 }
74 if c0 == 72 { return 8 }
75 if c0 == 68 { return 15 }
76 if c0 == 66 { return 16 }
77 if c0 == 65 { if buf[start + 1] == (68 as u8) { return 19 } if buf[start + 1] == (83 as u8) { return 20 } if buf[start + 1] == (76 as u8) { return 21 } return 0 }
78 if c0 == 70 { return 10 }
79 if c0 == 82 { if buf[start + 3] == (86 as u8) { return 13 } return 11 }
80 if c0 == 67 { return 12 }
81 if c0 == 69 { if buf[start + 3] == (76 as u8) { return 4 } if buf[start + 3] == (70 as u8) { return 9 } return 7 }
82 return 0
83}
84// parse IR into sop[] + opd[] (8 i64 per stmt: o0s,o0l,o1s,o1l,o2s,o2l,o3s,o3l -- 4 operands). return stmt count.
85func parse_ir(ir: *u8, irn: i64, sop: *i64, opd: *i64) -> i64 {
86 var i: i64 = 0
87 var ns: i64 = 0
88 let res: *i64 = sys_mmap(8 * 3)
89 while i < irn {
90 let ls: i64 = i
91 var le: i64 = ls
92 var g: i64 = 1
93 while g == 1 { if le >= irn { g = 0 } else { if ir[le] == (10 as u8) { g = 0 } else { le = le + 1 } } }
94 var fs: i64 = ls
95 var sg: i64 = 1
96 while sg == 1 { if fs >= le { sg = 0 } else { if ir[fs] == (32 as u8) { fs = fs + 1 } else { if ir[fs] == (9 as u8) { fs = fs + 1 } else { sg = 0 } } } }
97 if fs < le { if ir[fs] != (35 as u8) {
98 if tok(ir, ls, le, res) == 1 {
99 sop[ns] = op_of(ir, res[0])
100 var pos: i64 = res[2]
101 var oi: i64 = 0
102 while oi < 4 {
103 if tok(ir, pos, le, res) == 1 { opd[ns*8 + oi*2] = res[0]; opd[ns*8 + oi*2 + 1] = res[1]; pos = res[2] } else { opd[ns*8 + oi*2] = 0; opd[ns*8 + oi*2 + 1] = 0 }
104 oi = oi + 1
105 }
106 ns = ns + 1
107 }
108 } }
109 i = le + 1
110 }
111 return ns
112}
113// true iff ir[s1..s1+l1) == ir[s2..s2+l2) (used to match a CALL fname against a FUNC name).
114func slice_eq(ir: *u8, s1: i64, l1: i64, s2: i64, l2: i64) -> i64 {
115 if l1 != l2 { return 0 }
116 var j: i64 = 0
117 while j < l1 { if ir[s1 + j] != ir[s2 + j] { return 0 } j = j + 1 }
118 return 1
119}
120// UNIVERSAL statement executor for a range [bs,be): V/SET/HASH/IF/ENDIF + CALL. Used for BOTH the main loop
121// body AND function bodies, so functions can call functions (composition) and themselves (recursion). Each
122// CALL SAVES the current frame (all 26 vars), binds params, runs the callee body (self-recursive -> nested
123// calls work), captures the return, then RESTORES the frame -- so a recursive call can't clobber its caller's
124// single-letter locals. RET/RETV are terminators read here from ftab, so skipped as statements. ftab = packed
125// function table (10 i64/func: nstart,nlen,param,param2,bodys,bodye,rettype,r0,r1,retvar).
126func exec_body(ir: *u8, sop: *i64, opd: *i64, val: *i64, bs: i64, be: i64, ftab: *i64, nf: i64, arrs: *i64) -> i64 {
127 var b: i64 = bs
128 var skip: i64 = 0
129 while b < be {
130 let op: i64 = sop[b]
131 if op == 6 { let vv: i64 = val[(ir[opd[b*8]] as i64) - 97]; let mm: i64 = parseint(ir, opd[b*8+2], opd[b*8+3]); let rr: i64 = parseint(ir, opd[b*8+4], opd[b*8+5]); if (vv % mm) == rr { skip = 0 } else { skip = 1 } }
132 if op == 18 {
133 let cav: i64 = val[(ir[opd[b*8]] as i64) - 97]
134 let ccs: i64 = opd[b*8+2]; let ccl: i64 = opd[b*8+3]; let cc0: i64 = ir[ccs] as i64
135 let cbv: i64 = val[(ir[opd[b*8+4]] as i64) - 97]
136 var cond: i64 = 0
137 if ccl == 1 { if cc0 == 60 { if cav < cbv { cond = 1 } } if cc0 == 62 { if cav > cbv { cond = 1 } } }
138 if ccl == 2 { if cc0 == 60 { if cav <= cbv { cond = 1 } } if cc0 == 62 { if cav >= cbv { cond = 1 } } if cc0 == 61 { if cav == cbv { cond = 1 } } if cc0 == 33 { if cav != cbv { cond = 1 } } }
139 if cond == 1 { skip = 0 } else { skip = 1 }
140 }
141 if op == 7 { skip = 0 }
142 if op == 1 { if skip == 0 { let vch: i64 = (ir[opd[b*8]] as i64) - 97; val[vch] = parseint(ir, opd[b*8+2], opd[b*8+3]) } }
143 if op == 3 { if skip == 0 { let aa: i64 = (ir[opd[b*8]] as i64) - 97; let bb: i64 = (ir[opd[b*8+2]] as i64) - 97; let cc: i64 = (ir[opd[b*8+4]] as i64) - 97; val[aa] = val[aa] + val[bb] * val[cc] } }
144 if op == 8 { if skip == 0 { let hh: i64 = (ir[opd[b*8]] as i64) - 97; let ha: i64 = val[(ir[opd[b*8+2]] as i64) - 97]; let hm: i64 = val[(ir[opd[b*8+4]] as i64) - 97]; val[hh] = (val[hh] * ha) % hm } }
145 if op == 14 { let nzv: i64 = val[(ir[opd[b*8]] as i64) - 97]; if nzv != 0 { skip = 0 } else { skip = 1 } }
146 if op == 15 { if skip == 0 { let dd: i64 = (ir[opd[b*8]] as i64) - 97; let ss: i64 = val[(ir[opd[b*8+2]] as i64) - 97]; val[dd] = ss - 1 } }
147 if op == 16 { if skip == 0 { let dl: i64 = (ir[opd[b*8]] as i64) - 97; let av: i64 = val[(ir[opd[b*8+2]] as i64) - 97]; let oc: i64 = ir[opd[b*8+4]] as i64; let bv: i64 = val[(ir[opd[b*8+6]] as i64) - 97]; if oc == 43 { val[dl] = av + bv } if oc == 45 { val[dl] = av - bv } if oc == 42 { val[dl] = av * bv } if oc == 37 { val[dl] = av % bv } } }
148 if op == 17 { if skip == 0 { let dz: i64 = (ir[opd[b*8]] as i64) - 97; let nz: i64 = val[(ir[opd[b*8+2]] as i64) - 97]; let dv: i64 = val[(ir[opd[b*8+4]] as i64) - 97]; val[dz] = nz / dv } }
149 if op == 20 { if skip == 0 { let ar: i64 = (ir[opd[b*8]] as i64) - 97; let ix: i64 = val[(ir[opd[b*8+2]] as i64) - 97]; let av: i64 = val[(ir[opd[b*8+4]] as i64) - 97]; arrs[ar*32 + ix] = av } }
150 if op == 21 { if skip == 0 { let ds: i64 = (ir[opd[b*8]] as i64) - 97; let ar: i64 = (ir[opd[b*8+2]] as i64) - 97; let ix: i64 = val[(ir[opd[b*8+4]] as i64) - 97]; val[ds] = arrs[ar*32 + ix] } }
151 if op == 12 { if skip == 0 {
152 let cfs: i64 = opd[b*8+2]; let cfl: i64 = opd[b*8+3]
153 var fi: i64 = 0
154 while fi < nf {
155 if slice_eq(ir, cfs, cfl, ftab[fi*10], ftab[fi*10+1]) == 1 {
156 let a1: i64 = val[(ir[opd[b*8+4]] as i64) - 97]
157 let p2: i64 = ftab[fi*10+3]
158 var a2: i64 = 0
159 if p2 >= 0 { a2 = val[(ir[opd[b*8+6]] as i64) - 97] }
160 let save: *i64 = sys_mmap(8 * 26)
161 var si: i64 = 0
162 while si < 26 { save[si] = val[si]; si = si + 1 }
163 val[ftab[fi*10+2]] = a1
164 if p2 >= 0 { val[p2] = a2 }
165 exec_body(ir, sop, opd, val, ftab[fi*10+4], ftab[fi*10+5], ftab, nf, arrs)
166 var rv: i64 = 0
167 if ftab[fi*10+6] == 0 { rv = val[ftab[fi*10+7]] * val[ftab[fi*10+8]] }
168 if ftab[fi*10+6] == 1 { rv = val[ftab[fi*10+9]] }
169 si = 0
170 while si < 26 { val[si] = save[si]; si = si + 1 }
171 val[(ir[opd[b*8]] as i64) - 97] = rv
172 }
173 fi = fi + 1
174 }
175 } }
176 b = b + 1
177 }
178 return 0
179}
180// interpret the IR (single loop; functions have multi-stmt bodies + RET a*b or RETV var, called via CALL) -> truth.
181func interp(ir: *u8, sop: *i64, opd: *i64, ns: i64) -> i64 {
182 let val: *i64 = sys_mmap(8 * 26)
183 var z: i64 = 0
184 while z < 26 { val[z] = 0; z = z + 1 }
185 let arrs: *i64 = sys_mmap(8 * 26 * 32) // 26 integer arrays x 32 elements (ADIM/AST/ALD), zero-init
186 // function table packed 10 i64/func: [0]nstart [1]nlen [2]param [3]param2(-1 if none) [4]bodys [5]bodye
187 // [6]rettype(0=a*b,1=var) [7]r0 [8]r1 [9]retvar. Built once; passed to exec_body for CALL dispatch.
188 let ftab: *i64 = sys_mmap(8 * 8 * 10)
189 var nf: i64 = 0
190 var fk: i64 = 0
191 while fk < ns {
192 if sop[fk] == 10 {
193 ftab[nf*10] = opd[fk*8]
194 ftab[nf*10 + 1] = opd[fk*8 + 1]
195 ftab[nf*10 + 2] = (ir[opd[fk*8 + 2]] as i64) - 97
196 if opd[fk*8 + 5] > 0 { ftab[nf*10 + 3] = (ir[opd[fk*8 + 4]] as i64) - 97 } else { ftab[nf*10 + 3] = 0 - 1 }
197 ftab[nf*10 + 4] = fk + 1
198 var e: i64 = fk + 1
199 var eg: i64 = 1
200 var frt: i64 = 0
201 var fa: i64 = 0
202 var fb: i64 = 0
203 var fv: i64 = 0
204 while eg == 1 {
205 if e >= ns { eg = 0 } else { if sop[e] == 9 { eg = 0 } else {
206 if sop[e] == 11 { frt = 0; fa = (ir[opd[e*8]] as i64) - 97; fb = (ir[opd[e*8+2]] as i64) - 97 }
207 if sop[e] == 13 { frt = 1; fv = (ir[opd[e*8]] as i64) - 97 }
208 e = e + 1
209 } }
210 }
211 ftab[nf*10 + 5] = e
212 ftab[nf*10 + 6] = frt; ftab[nf*10 + 7] = fa; ftab[nf*10 + 8] = fb; ftab[nf*10 + 9] = fv
213 nf = nf + 1
214 }
215 fk = fk + 1
216 }
217 var lo: i64 = 0 - 1
218 var lend: i64 = 0 - 1
219 var k: i64 = 0
220 while k < ns { if sop[k] == 2 { lo = k } if sop[k] == 4 { lend = k } k = k + 1 }
221 // pre-loop V inits
222 k = 0
223 while k < ns { if k != lo { if k != lend {
224 if sop[k] == 1 { let vch: i64 = (ir[opd[k*8]] as i64) - 97; val[vch] = parseint(ir, opd[k*8+2], opd[k*8+3]) }
225 } } k = k + 1 }
226 if lo >= 0 {
227 let lvch: i64 = (ir[opd[lo*8]] as i64) - 97
228 let bound: i64 = parseint(ir, opd[lo*8+2], opd[lo*8+3])
229 var lv: i64 = 1
230 while lv <= bound {
231 val[lvch] = lv
232 exec_body(ir, sop, opd, val, lo + 1, lend, ftab, nf, arrs)
233 lv = lv + 1
234 }
235 }
236 var truth: i64 = 0
237 k = 0
238 while k < ns { if sop[k] == 5 { truth = val[(ir[opd[k*8]] as i64) - 97] } k = k + 1 }
239 return truth
240}
241// find template for key in constructs buffer: res[0]=offset res[1]=len (0 if empty); ret 1 if key found.
242func lookup(cons: *u8, consn: i64, key: *u8, res: *i64) -> i64 {
243 let kl: i64 = slen(key)
244 var i: i64 = 0
245 while i < consn {
246 let ls: i64 = i
247 var le: i64 = ls
248 var g: i64 = 1
249 while g == 1 { if le >= consn { g = 0 } else { if cons[le] == (10 as u8) { g = 0 } else { le = le + 1 } } }
250 if le > ls { if cons[ls] != (35 as u8) {
251 let f0e: i64 = scant(cons, ls, le)
252 if f0e - ls == kl {
253 var same: i64 = 1
254 var j: i64 = 0
255 while j < kl { if cons[ls + j] != key[j] { same = 0; j = kl } else { j = j + 1 } }
256 if same == 1 {
257 if f0e < le { res[0] = f0e + 1; res[1] = le - (f0e + 1) } else { res[0] = ls; res[1] = 0 }
258 return 1
259 }
260 }
261 } }
262 i = le + 1
263 }
264 return 0
265}
266// render template tpl[0..tlen) into out at o: <A>/<B>/<C>/<D>=operand slices (ops 8 i64), <NL>/<DQ>/<S> tokens.
267func render(out: *u8, o: i64, tpl: *u8, tlen: i64, ir: *u8, ops: *i64) -> i64 {
268 var oo: i64 = o
269 var i: i64 = 0
270 while i < tlen {
271 let c: i64 = tpl[i] as i64
272 var handled: i64 = 0
273 if c == 60 {
274 if i + 2 < tlen { if tpl[i+2] == (62 as u8) {
275 let l: i64 = tpl[i+1] as i64
276 if l == 65 { oo = copyslice(out, oo, ir, ops[0], ops[1]); i = i + 3; handled = 1 }
277 if l == 66 { oo = copyslice(out, oo, ir, ops[2], ops[3]); i = i + 3; handled = 1 }
278 if l == 67 { oo = copyslice(out, oo, ir, ops[4], ops[5]); i = i + 3; handled = 1 }
279 if l == 68 { oo = copyslice(out, oo, ir, ops[6], ops[7]); i = i + 3; handled = 1 }
280 if l == 83 { out[oo] = (32 as u8); oo = oo + 1; i = i + 3; handled = 1 }
281 } }
282 if handled == 0 { if i + 3 < tlen { if tpl[i+3] == (62 as u8) {
283 if tpl[i+1] == (78 as u8) { if tpl[i+2] == (76 as u8) { out[oo] = (10 as u8); oo = oo + 1; i = i + 4; handled = 1 } }
284 if tpl[i+1] == (68 as u8) { if tpl[i+2] == (81 as u8) { out[oo] = (34 as u8); oo = oo + 1; i = i + 4; handled = 1 } }
285 } } }
286 }
287 if handled == 0 { out[oo] = tpl[i]; oo = oo + 1; i = i + 1 }
288 }
289 return oo
290}
291// emit one construct line: indent x depth + rendered template + newline. empty/missing template = nothing.
292func emit_line(out: *u8, o: i64, key: *u8, depth: i64, ind: *u8, indlen: i64, cons: *u8, consn: i64, ir: *u8, ops: *i64) -> i64 {
293 let res: *i64 = sys_mmap(16)
294 if lookup(cons, consn, key, res) == 0 { return o }
295 if res[1] == 0 { return o }
296 var oo: i64 = o
297 var di: i64 = 0
298 while di < depth { var j: i64 = 0; while j < indlen { out[oo] = ind[j]; oo = oo + 1; j = j + 1 } di = di + 1 }
299 oo = render(out, oo, ((cons as i64) + res[0]) as *u8, res[1], ir, ops)
300 out[oo] = (10 as u8); oo = oo + 1
301 return oo
302}
303func mkkey(kb: *u8, lang: *u8, construct: *u8) -> i64 { var o: i64 = cat(kb, 0, lang); kb[o] = (46 as u8); o = o + 1; o = cat(kb, o, construct); kb[o] = (0 as u8); return 0 }
304func mkpath(pathb: *u8, name: *u8, ext: *u8) -> i64 { var o: i64 = cat(pathb, 0, "_offc/lg_" as *u8); o = cat(pathb, o, name); pathb[o] = (46 as u8); o = o + 1; o = cat(pathb, o, ext); pathb[o] = (0 as u8); return 0 }
305func emitlog(name: *u8, bytes: i64) -> i64 { puts("EMIT lang=" as *u8); puts(name); puts(" file=_offc/lg_" as *u8); puts(name); puts(" bytes=" as *u8); putn(bytes); puts("\n" as *u8); return 0 }
306// render the <lang>.FNSEP parameter separator (e.g. ",") into out at o. No holes, so ir/ops are unused.
307func emit_sep(out: *u8, o: i64, lang: *u8, cons: *u8, consn: i64) -> i64 {
308 let kb: *u8 = sys_mmap(64)
309 let res: *i64 = sys_mmap(16)
310 mkkey(kb, lang, "FNSEP" as *u8)
311 if lookup(cons, consn, kb, res) == 1 { if res[1] > 0 { return render(out, o, ((cons as i64) + res[0]) as *u8, res[1], cons, res) } }
312 return o
313}
314// LOCALS-AS-PARAMS function signature for languages whose function locals are GLOBAL by default (awk): the
315// signature must list the body's V-declared locals as trailing params so recursion gets a fresh frame per call.
316// DATA-driven -- the language's syntax lives in <lang>.FNOPEN (`function <A>(`) / FNSEP (`,`) / FNCLOSE (`){`);
317// this just assembles FNOPEN + param1 [+ FNSEP param2] + (FNSEP local) per body V-var + FNCLOSE. Returns offset.
318func emit_localsig_funco(out: *u8, o: i64, lang: *u8, ir: *u8, sop: *i64, opd: *i64, fk: i64, ns: i64, fops: *i64, cons: *u8, consn: i64) -> i64 {
319 let kb: *u8 = sys_mmap(64)
320 let res: *i64 = sys_mmap(16)
321 var oo: i64 = o
322 mkkey(kb, lang, "FNOPEN" as *u8)
323 if lookup(cons, consn, kb, res) == 1 { oo = render(out, oo, ((cons as i64) + res[0]) as *u8, res[1], ir, fops) }
324 out[oo] = ir[fops[2]]; oo = oo + 1
325 if fops[5] > 0 { oo = emit_sep(out, oo, lang, cons, consn); out[oo] = ir[fops[4]]; oo = oo + 1 }
326 var e: i64 = fk + 1
327 var g: i64 = 1
328 while g == 1 {
329 if e >= ns { g = 0 } else { if sop[e] == 9 { g = 0 } else {
330 if sop[e] == 1 { oo = emit_sep(out, oo, lang, cons, consn); out[oo] = ir[opd[e*8]]; oo = oo + 1 }
331 e = e + 1
332 } }
333 }
334 mkkey(kb, lang, "FNCLOSE" as *u8)
335 if lookup(cons, consn, kb, res) == 1 { oo = render(out, oo, ((cons as i64) + res[0]) as *u8, res[1], ir, fops) }
336 out[oo] = (10 as u8); oo = oo + 1
337 return oo
338}
339// generate full source for one language into out; return length.
340func gen_lang(lang: *u8, ir: *u8, sop: *i64, opd: *i64, ns: i64, cons: *u8, consn: i64, out: *u8) -> i64 {
341 let kb: *u8 = sys_mmap(64)
342 let res: *i64 = sys_mmap(16)
343 let indbuf: *u8 = sys_mmap(64)
344 var indlen: i64 = 0
345 mkkey(kb, lang, "IND" as *u8)
346 if lookup(cons, consn, kb, res) == 1 { if res[1] > 0 { indlen = render(indbuf, 0, ((cons as i64) + res[0]) as *u8, res[1], ir, opd) } }
347 var o: i64 = 0
348 // HEAD (file head / class-open)
349 mkkey(kb, lang, "HD" as *u8); o = emit_line(out, o, kb, 0, indbuf, indlen, cons, consn, ir, opd)
350 // FUNCTION DEFINITIONS at file/class scope (before main) so Java's class-scope methods stay valid.
351 // The body (local VAR/SET/HASH + the RET/RETV terminator) is emitted at depth 1 inside the function.
352 var fdepth: i64 = 0
353 var infunc: i64 = 0
354 var fk: i64 = 0
355 while fk < ns {
356 let fop: i64 = sop[fk]
357 let fops: *i64 = ((opd as i64) + (fk * 64)) as *i64
358 if fop == 10 {
359 mkkey(kb, lang, "FNOPEN" as *u8)
360 if lookup(cons, consn, kb, res) == 1 {
361 o = emit_localsig_funco(out, o, lang, ir, sop, opd, fk, ns, fops, cons, consn)
362 } else {
363 if fops[5] > 0 { mkkey(kb, lang, "FUNCO2" as *u8) } else { mkkey(kb, lang, "FUNCO" as *u8) }
364 o = emit_line(out, o, kb, 0, indbuf, indlen, cons, consn, ir, fops)
365 }
366 fdepth = 1; infunc = 1
367 }
368 if fop == 9 { fdepth = 0; mkkey(kb, lang, "FUNCC" as *u8); o = emit_line(out, o, kb, 0, indbuf, indlen, cons, consn, ir, fops); infunc = 0 }
369 if infunc == 1 {
370 if fop == 1 { mkkey(kb, lang, "VAR" as *u8); o = emit_line(out, o, kb, fdepth, indbuf, indlen, cons, consn, ir, fops) }
371 if fop == 3 { mkkey(kb, lang, "SET" as *u8); o = emit_line(out, o, kb, fdepth, indbuf, indlen, cons, consn, ir, fops) }
372 if fop == 8 { mkkey(kb, lang, "HASH" as *u8); o = emit_line(out, o, kb, fdepth, indbuf, indlen, cons, consn, ir, fops) }
373 if fop == 15 { mkkey(kb, lang, "DEC" as *u8); o = emit_line(out, o, kb, fdepth, indbuf, indlen, cons, consn, ir, fops) }
374 if fop == 16 { mkkey(kb, lang, "BIN" as *u8); o = emit_line(out, o, kb, fdepth, indbuf, indlen, cons, consn, ir, fops) }
375 if fop == 17 { mkkey(kb, lang, "IDIV" as *u8); o = emit_line(out, o, kb, fdepth, indbuf, indlen, cons, consn, ir, fops) }
376 if fop == 19 { mkkey(kb, lang, "ADIM" as *u8); o = emit_line(out, o, kb, fdepth, indbuf, indlen, cons, consn, ir, fops) }
377 if fop == 20 { mkkey(kb, lang, "AST" as *u8); o = emit_line(out, o, kb, fdepth, indbuf, indlen, cons, consn, ir, fops) }
378 if fop == 21 { mkkey(kb, lang, "ALD" as *u8); o = emit_line(out, o, kb, fdepth, indbuf, indlen, cons, consn, ir, fops) }
379 if fop == 22 { mkkey(kb, lang, "SP" as *u8); o = emit_line(out, o, kb, fdepth, indbuf, indlen, cons, consn, ir, fops) }
380 if fop == 6 { mkkey(kb, lang, "IF" as *u8); o = emit_line(out, o, kb, fdepth, indbuf, indlen, cons, consn, ir, fops); fdepth = fdepth + 1 }
381 if fop == 14 { mkkey(kb, lang, "IFNZ" as *u8); o = emit_line(out, o, kb, fdepth, indbuf, indlen, cons, consn, ir, fops); fdepth = fdepth + 1 }
382 if fop == 18 { mkkey(kb, lang, "IFC" as *u8); o = emit_line(out, o, kb, fdepth, indbuf, indlen, cons, consn, ir, fops); fdepth = fdepth + 1 }
383 if fop == 7 { fdepth = fdepth - 1; mkkey(kb, lang, "ENDIF" as *u8); o = emit_line(out, o, kb, fdepth, indbuf, indlen, cons, consn, ir, fops) }
384 if fop == 12 {
385 if fops[7] > 0 { mkkey(kb, lang, "CALL2" as *u8) } else { mkkey(kb, lang, "CALL" as *u8) }
386 o = emit_line(out, o, kb, fdepth, indbuf, indlen, cons, consn, ir, fops)
387 }
388 if fop == 11 { mkkey(kb, lang, "RET" as *u8); o = emit_line(out, o, kb, fdepth, indbuf, indlen, cons, consn, ir, fops) }
389 if fop == 13 { mkkey(kb, lang, "RETV" as *u8); o = emit_line(out, o, kb, fdepth, indbuf, indlen, cons, consn, ir, fops) }
390 }
391 fk = fk + 1
392 }
393 // MAIN OPEN
394 mkkey(kb, lang, "PR" as *u8); o = emit_line(out, o, kb, 0, indbuf, indlen, cons, consn, ir, opd)
395 var depth: i64 = 0
396 var minf: i64 = 0
397 var k: i64 = 0
398 while k < ns {
399 let op: i64 = sop[k]
400 let ops: *i64 = ((opd as i64) + (k * 64)) as *i64
401 if op == 10 { minf = 1 }
402 if op == 9 { minf = 0 }
403 if minf == 0 { if op != 9 { if op != 10 {
404 if op == 1 { mkkey(kb, lang, "VAR" as *u8); o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops) }
405 if op == 2 { mkkey(kb, lang, "LOOPO" as *u8); o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops); depth = depth + 1 }
406 if op == 4 { depth = depth - 1; mkkey(kb, lang, "LOOPC" as *u8); o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops) }
407 if op == 3 { mkkey(kb, lang, "SET" as *u8); o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops) }
408 if op == 8 { mkkey(kb, lang, "HASH" as *u8); o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops) }
409 if op == 6 { mkkey(kb, lang, "IF" as *u8); o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops); depth = depth + 1 }
410 if op == 14 { mkkey(kb, lang, "IFNZ" as *u8); o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops); depth = depth + 1 }
411 if op == 18 { mkkey(kb, lang, "IFC" as *u8); o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops); depth = depth + 1 }
412 if op == 15 { mkkey(kb, lang, "DEC" as *u8); o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops) }
413 if op == 16 { mkkey(kb, lang, "BIN" as *u8); o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops) }
414 if op == 17 { mkkey(kb, lang, "IDIV" as *u8); o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops) }
415 if op == 19 { mkkey(kb, lang, "ADIM" as *u8); o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops) }
416 if op == 20 { mkkey(kb, lang, "AST" as *u8); o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops) }
417 if op == 21 { mkkey(kb, lang, "ALD" as *u8); o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops) }
418 if op == 22 { mkkey(kb, lang, "SP" as *u8); o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops) }
419 if op == 7 { depth = depth - 1; mkkey(kb, lang, "ENDIF" as *u8); o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops) }
420 if op == 12 {
421 if ops[7] > 0 { mkkey(kb, lang, "CALL2" as *u8) } else { mkkey(kb, lang, "CALL" as *u8) }
422 o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops)
423 }
424 if op == 5 { mkkey(kb, lang, "PRINT" as *u8); o = emit_line(out, o, kb, depth, indbuf, indlen, cons, consn, ir, ops) }
425 } } }
426 k = k + 1
427 }
428 // MAIN CLOSE + FOOTER (class-close)
429 mkkey(kb, lang, "EP" as *u8); o = emit_line(out, o, kb, 0, indbuf, indlen, cons, consn, ir, opd)
430 mkkey(kb, lang, "FT" as *u8); o = emit_line(out, o, kb, 0, indbuf, indlen, cons, consn, ir, opd)
431 return o
432}
433// true iff langbuf[off..](NUL-term) equals src[start..start+len)
434func streq_slice(buf: *u8, off: i64, src: *u8, start: i64, len: i64) -> i64 {
435 var k: i64 = 0
436 while k < len { if buf[off + k] != src[start + k] { return 0 } k = k + 1 }
437 if buf[off + len] != (0 as u8) { return 0 }
438 return 1
439}
440// enumerate the DISTINCT language prefixes (before '.') of the construct keys into langbuf/langoff. ret count.
441func enum_langs(cons: *u8, consn: i64, langbuf: *u8, langoff: *i64, maxl: i64) -> i64 {
442 var nl: i64 = 0
443 var wo: i64 = 0
444 var i: i64 = 0
445 while i < consn {
446 let ls: i64 = i
447 var le: i64 = ls
448 var g: i64 = 1
449 while g == 1 { if le >= consn { g = 0 } else { if cons[le] == (10 as u8) { g = 0 } else { le = le + 1 } } }
450 if le > ls { if cons[ls] != (35 as u8) {
451 let f0e: i64 = scant(cons, ls, le)
452 var dot: i64 = ls
453 var dg: i64 = 1
454 while dg == 1 { if dot >= f0e { dg = 0 } else { if cons[dot] == (46 as u8) { dg = 0 } else { dot = dot + 1 } } }
455 if dot < f0e {
456 let plen: i64 = dot - ls
457 var found: i64 = 0
458 var q: i64 = 0
459 while q < nl { if streq_slice(langbuf, langoff[q], cons, ls, plen) == 1 { found = 1 } q = q + 1 }
460 if found == 0 { if nl < maxl {
461 langoff[nl] = wo
462 var k: i64 = 0
463 while k < plen { langbuf[wo] = cons[ls + k]; wo = wo + 1; k = k + 1 }
464 langbuf[wo] = (0 as u8); wo = wo + 1
465 nl = nl + 1
466 } }
467 }
468 } }
469 i = le + 1
470 }
471 return nl
472}
473func main() -> i64 {
474 let ir: *u8 = sys_mmap(K_MAGIC_8192)
475 let irn: i64 = readfile("knowledge/registry/lang_export_program.tsv" as *u8, ir, K_MAGIC_8192)
476 if irn <= 0 { puts("LANG-EXPORT-GROW verdict=RED reason=program-unreadable\n" as *u8); return 1 }
477 let cons: *u8 = sys_mmap(K_MAGIC_8192)
478 let consn: i64 = readfile("knowledge/registry/lang_export_constructs.tsv" as *u8, cons, K_MAGIC_8192)
479 if consn <= 0 { puts("LANG-EXPORT-GROW verdict=RED reason=constructs-unreadable\n" as *u8); return 1 }
480 let sop: *i64 = sys_mmap(8 * 64)
481 let opd: *i64 = sys_mmap(8 * 64 * 8)
482 let ns: i64 = parse_ir(ir, irn, sop, opd)
483 let truth: i64 = interp(ir, sop, opd, ns)
484 puts("LANG-EXPORT-GROW native=" as *u8); putn(truth); puts(" stmts=" as *u8); putn(ns); puts(" (IR-interpreted truth)\n" as *u8)
485 // string-truth: if the program prints a string literal (SP <word>), report it so the gate can compare the
486 // emitted programs' stdout against it (the int native= is meaningless for a pure-string program).
487 var spk: i64 = 0
488 while spk < ns { if sop[spk] == 22 { puts("LANG-EXPORT-GROW native_str=" as *u8); sys_write(1, ((ir as i64) + opd[spk*8]) as *u8, opd[spk*8+1]); puts("\n" as *u8); spk = ns } else { spk = spk + 1 } }
489 let out: *u8 = sys_mmap(K_MAGIC_8192)
490 let pathb: *u8 = sys_mmap(128)
491 let langbuf: *u8 = sys_mmap(256)
492 let langoff: *i64 = sys_mmap(8 * 32)
493 let nl: i64 = enum_langs(cons, consn, langbuf, langoff, 32)
494 var li: i64 = 0
495 while li < nl {
496 let lang: *u8 = ((langbuf as i64) + langoff[li]) as *u8
497 let ol: i64 = gen_lang(lang, ir, sop, opd, ns, cons, consn, out)
498 mkpath(pathb, lang, lang)
499 wfile(pathb, out, ol)
500 emitlog(lang, ol)
501 li = li + 1
502 }
503 puts("LANG-EXPORT-GROW emitted=" as *u8); putn(nl); puts(" langs (enumerated from DATA); GATE: each must reproduce native=" as *u8); putn(truth); puts("\n" as *u8)
504 return 0
505}