code wiki / _hdl_build / nx_lang_struct.nx

nx_lang_struct.nx source

↩ module page · 143 lines · 7416 B

1// nx_lang_struct.nx -- LANG-EXPORT FRONTEND, atom 1 (the SSA structurizer foundation). Takes a REAL NishiLang 2// .nx source, runs it through nxc2's OWN frontend (lex_source -> parse_module -> SSA Module), then WALKS the 3// SSA of function 0 and RECOVERS the structured export IR (the "AST etc" nxc2 lacks): SSA value-numbering maps 4// each value-id to a single-letter var, constants materialize as `V <var> <int>`, binops become `BIN <lhs> <a> 5// <op> <b>` / `IDIV`, and the function's RETURN becomes `PRINT <var>`. The body is wrapped in `LOOP <free> 1` 6// so the existing nx_lang_export_grow interp+emitter consumes it -> 6 languages, all from REAL Nishi source. 7// ATOM 1 SCOPE: straight-line arithmetic (const + + - * / % + return). Control flow (if/loop recovery from the 8// CFG) + params/locals are the next structurizer atoms. license_tier: ORIGINAL 9import "nx_syscalls.nx" 10import "nx_types.nx" 11import "nx_lex_kinds.nx" 12import "nx_ir.nx" 13import "nx_tokenizer.nx" 14import "nx_parse.nx" 15const K_MAGIC_8192: i64 = 8192 16const K_MAGIC_4096: i64 = 4096 17 18func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 19func sp(s: *u8) -> i64 { sys_write(1, s, slen(s)); return 0 } 20func bcat(buf: *u8, off: i64, s: *u8) -> i64 { var o: i64 = off; var i: i64 = 0; while s[i] != (0 as u8) { buf[o] = s[i]; o = o + 1; i = i + 1 } return o } 21func bch(buf: *u8, off: i64, c: i64) -> i64 { buf[off] = c as u8; return off + 1 } 22func bnum(buf: *u8, off: i64, v: i64) -> i64 { 23 var o: i64 = off 24 var m: i64 = v 25 if m < 0 { buf[o] = (45 as u8); o = o + 1; m = 0 - m } 26 let t: *u8 = sys_mmap(32) 27 var k: i64 = 0 28 if m == 0 { t[0] = (48 as u8); k = 1 } 29 while m > 0 { t[k] = ((48 + (m % 10)) as u8); m = m / 10; k = k + 1 } 30 var i: i64 = 0 31 while i < k { buf[o + i] = t[k - 1 - i]; i = i + 1 } 32 return o + k 33} 34func readfile(path: *u8, buf: *u8, cap: i64) -> i64 { 35 let fd: i64 = sys_openat_rd(path) 36 if fd < 0 { return 0 - 1 } 37 var n: i64 = 0 38 var go: i64 = 1 39 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 } } 40 sys_close(fd) 41 return n 42} 43func 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 } 44 45// resolve SSA value-id rid to a letter index; materialize a constant as a `V <letter> <int>` line into body. 46// st[0] = body write offset, st[1] = next free letter index. returns letter index, or -1 if non-const & unmapped. 47func letter_of(f: *Function, rid: i64, vmap: *i64, body: *u8, st: *i64) -> i64 { 48 if vmap[rid] >= 0 { return vmap[rid] } 49 let v: *Value = (f.values as i64 + rid * 48) as *Value 50 if v.kind == 0 { 51 let l: i64 = st[1] 52 st[1] = st[1] + 1 53 var o: i64 = st[0] 54 o = bcat(body, o, "V " as *u8); o = bch(body, o, 97 + l); o = bch(body, o, 32); o = bnum(body, o, v.const_int); o = bch(body, o, 10) 55 st[0] = o 56 vmap[rid] = l 57 return l 58 } 59 return 0 - 1 60} 61 62func main() -> i64 { 63 let src: *u8 = sys_mmap(K_MAGIC_8192) 64 let srcn: i64 = readfile("knowledge/registry/lang_export_source.nx" as *u8, src, K_MAGIC_8192) 65 if srcn <= 0 { sp("STRUCT verdict=RED reason=source-unreadable\n" as *u8); return 1 } 66 let toks: *Tok = lex_source(src, K_MAGIC_4096) 67 if toks == (0 as *Tok) { sp("STRUCT verdict=RED reason=lex-failed\n" as *u8); return 1 } 68 let m: *Module = parse_module(toks, 0 as *Module) 69 if m == (0 as *Module) { sp("STRUCT verdict=RED reason=parse-failed\n" as *u8); return 1 } 70 if m.n_functions < 1 { sp("STRUCT verdict=RED reason=no-functions\n" as *u8); return 1 } 71 let f: *Function = m.functions 72 let vmap: *i64 = sys_mmap(8 * (f.n_values + 8)) 73 var z: i64 = 0 74 while z < f.n_values + 8 { vmap[z] = 0 - 1; z = z + 1 } 75 let body: *u8 = sys_mmap(K_MAGIC_8192) 76 let ops: *u8 = sys_mmap(K_MAGIC_8192) 77 let st: *i64 = sys_mmap(32) 78 st[0] = 0 79 st[1] = 0 80 st[2] = 0 81 var retl: i64 = 0 - 1 82 var ok: i64 = 1 83 var badop: i64 = 0 84 let bb: *BasicBlock = f.entry 85 var ins: *Instr = bb.head 86 while (ins as i64) != 0 { 87 let op: i64 = ins.op 88 if op == OP_RETURN { 89 let rl: i64 = letter_of(f, ins.op0, vmap, body, st) 90 if rl < 0 { ok = 0 } else { retl = rl } 91 } else { 92 var opc: i64 = 0 93 var isdiv: i64 = 0 94 if op == OP_ADD { opc = 43 } 95 if op == OP_SUB { opc = 45 } 96 if op == OP_MUL { opc = 42 } 97 if op == OP_REM_S { opc = 37 } 98 if op == OP_DIV_S { isdiv = 1 } 99 var handled: i64 = 0 100 if opc != 0 { handled = 1 } 101 if isdiv == 1 { handled = 1 } 102 if handled == 1 { 103 let la: i64 = letter_of(f, ins.op0, vmap, body, st) 104 let lb: i64 = letter_of(f, ins.op1, vmap, body, st) 105 if la < 0 { ok = 0 } 106 if lb < 0 { ok = 0 } 107 if la >= 0 { if lb >= 0 { 108 let lr: i64 = st[1] 109 st[1] = st[1] + 1 110 vmap[ins.result] = lr 111 // declare the result var pre-loop (C/Java need a declaration; the op below is assignment) 112 var d: i64 = st[0] 113 d = bcat(body, d, "V " as *u8); d = bch(body, d, 97 + lr); d = bcat(body, d, " 0\n" as *u8) 114 st[0] = d 115 var o: i64 = st[2] 116 if isdiv == 1 { 117 o = bcat(ops, o, "IDIV " as *u8); o = bch(ops, o, 97 + lr); o = bch(ops, o, 32); o = bch(ops, o, 97 + la); o = bch(ops, o, 32); o = bch(ops, o, 97 + lb); o = bch(ops, o, 10) 118 } else { 119 o = bcat(ops, o, "BIN " as *u8); o = bch(ops, o, 97 + lr); o = bch(ops, o, 32); o = bch(ops, o, 97 + la); o = bch(ops, o, 32); o = bch(ops, o, opc); o = bch(ops, o, 32); o = bch(ops, o, 97 + lb); o = bch(ops, o, 10) 120 } 121 st[2] = o 122 } } 123 } else { ok = 0; badop = op } 124 } 125 ins = ins.next 126 } 127 if ok == 0 { sp("STRUCT verdict=RED reason=unsupported-op opcode=" as *u8); let eb: *u8 = sys_mmap(32); let en: i64 = bnum(eb, 0, badop); sys_write(1, eb, en); sp(" (atom1 = straight-line arithmetic only)\n" as *u8); return 1 } 128 if retl < 0 { sp("STRUCT verdict=RED reason=no-return\n" as *u8); return 1 } 129 let outb: *u8 = sys_mmap(K_MAGIC_8192) 130 var oo: i64 = 0 131 oo = bcat(outb, oo, "# AUTO-GENERATED from knowledge/registry/lang_export_source.nx via nxc2 SSA structurizer (nx_lang_struct)\n" as *u8) 132 var i: i64 = 0 133 while i < st[0] { outb[oo] = body[i]; oo = oo + 1; i = i + 1 } 134 oo = bcat(outb, oo, "LOOP " as *u8); oo = bch(outb, oo, 97 + st[1]); oo = bcat(outb, oo, " 1\n" as *u8) 135 var j: i64 = 0 136 while j < st[2] { outb[oo] = ops[j]; oo = oo + 1; j = j + 1 } 137 oo = bcat(outb, oo, "ENDLOOP\n" as *u8) 138 oo = bcat(outb, oo, "PRINT " as *u8); oo = bch(outb, oo, 97 + retl); oo = bch(outb, oo, 10) 139 wfile("knowledge/registry/lang_export_program.tsv" as *u8, outb, oo) 140 sp("STRUCT verdict=GREEN structurized nxc2 SSA -> export IR (straight-line); letters=" as *u8) 141 let nb: *u8 = sys_mmap(32); let nn: i64 = bnum(nb, 0, st[1]); sys_write(1, nb, nn); sp("\n" as *u8) 142 return 0 143}