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}