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}