code wiki / _hdl_build / nx_eoe_prog.nx

nx_eoe_prog.nx source

↩ module page · 148 lines · 8846 B

1// nx_eoe_prog.nx -- EMITTER-OF-EMITTERS, GENERALITY RUNG 5 (THE INFLECTION): 2// a UNIFIED STATEMENT-LIST MINI-LANGUAGE, not a 4th single-shape emitter. 3// 4// Rungs 006g/h/i each emitted ONE fixed shape (a linear op-list / a 2-way branch / 5// a single-body while). This rung unifies them into a recursive GRAMMAR whose spec 6// is a LIST OF STATEMENTS, where a branch's or loop's body is ITSELF a statement 7// list (NESTING). That recursion is the qualitative jump: the team now specs an 8// organ in a real (if tiny) language -- sequence + conditional + iteration, 9// arbitrarily composed -- which is the shape of general control flow. A recursive 10// descent over the spec PRETTY-PRINTS the corresponding nested NishiLang; nx_cc 11// compiles it (codegen delegated to the compiler the team owns). 12// 13// nx_eoe_prog <basename> <start> <stmt...> 14// stmt grammar (tokens): 15// a<n> | m<n> | s<n> acc = acc + / * / - n 16// if <pred> [ <stmt...> ] one-armed conditional (pred = g<t>|l<t>|e<t>) 17// while <pred> [ <stmt...> ] predicate-driven loop (per-loop runaway guard) 18// `[` and `]` are their own tokens; blocks NEST. Emits main() that runs the 19// program over acc=<start> and prints "RESULT=<acc>\n". 20// 21// no-false-green plan (X-AUT-006d): nested specs that DIVERGE -- e.g. flipping an 22// inner threshold so the conditional inside a loop fires a different number of times 23// -> a DIFFERENT correct result; tamper any op/threshold -> result changes. 24// Sovereign, no gcc/.sh. HONEST SCOPE: single i64 accumulator, one-armed if, integer 25// ops; NOT yet multiple funcs/typed params/imports -- but the CONTROL-FLOW grammar is 26// now compositional, the real inflection toward general organ synthesis. 27// license_tier: ORIGINAL 28import "nx_syscalls.nx" 29const K_MAGIC_262144: i64 = 262144 30 31func eop_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { dst[off+i] = s[i]; i = i + 1 } return off + i } 32func eop_catn(dst: *u8, off: i64, v: i64) -> i64 { 33 var o: i64 = off 34 if v < 0 { dst[o] = 45 as u8; o = o + 1; return eop_catn(dst, o, 0 - v) } 35 if v == 0 { dst[o] = 48 as u8; return o + 1 } 36 var m: i64 = v 37 let t: *u8 = sys_mmap(28) 38 var k: i64 = 0 39 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 40 var i: i64 = 0 41 while i < k { dst[o+i] = t[k-1-i]; i = i + 1 } 42 return o + k 43} 44func eop_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 45func eop_atoi_from(s: *u8, from: i64) -> i64 { 46 var n: i64 = 0; var i: i64 = from 47 while s[i] != (0 as u8) { if s[i] >= (48 as u8) { if s[i] <= (57 as u8) { n = n * 10 + ((s[i] as i64) - 48) } } i = i + 1 } 48 return n 49} 50func eop_indent(buf: *u8, off: i64, depth: i64) -> i64 { 51 var o: i64 = off; var d: i64 = 0 52 while d < depth { o = eop_cat(buf, o, " " as *u8); d = d + 1 } 53 return o 54} 55// emit the comparison " <cmp> thr" from a predicate token "g<t>|l<t>|e<t>". 56func eop_cmp(buf: *u8, off: i64, pred: *u8) -> i64 { 57 var o: i64 = off 58 let pc: i64 = pred[0] as i64 59 if pc == 103 { o = eop_cat(buf, o, "> " as *u8) } // 'g' 60 if pc == 108 { o = eop_cat(buf, o, "< " as *u8) } // 'l' 61 if pc == 101 { o = eop_cat(buf, o, "== " as *u8) } // 'e' 62 o = eop_catn(buf, o, eop_atoi_from(pred, 1)) 63 return o 64} 65 66// Recursive descent: emit statements from token index `ti` until a `]` token (which 67// it consumes) or end-of-tokens, at indentation `depth`. Threads the output offset 68// as the return value and the next token index via out_ti. gid = per-loop guard-id 69// counter (so nested whiles get distinct guard vars). 70func eop_emit_stmts(buf: *u8, off: i64, argv: *i64, argc: i64, ti: i64, depth: i64, out_ti: *i64, gid: *i64) -> i64 { 71 var o: i64 = off 72 var i: i64 = ti 73 while i < argc { 74 let tok: *u8 = argv[i] as *u8 75 let c0: i64 = tok[0] as i64 76 if c0 == 93 { i = i + 1; out_ti[0] = i; return o } // ']' end block (consume) 77 if c0 == 97 { // 'a' add 78 o = eop_indent(buf, o, depth); o = eop_cat(buf, o, "acc = acc + " as *u8); o = eop_catn(buf, o, eop_atoi_from(tok, 1)); o = eop_cat(buf, o, "\n" as *u8); i = i + 1 79 } else { if c0 == 109 { // 'm' mul 80 o = eop_indent(buf, o, depth); o = eop_cat(buf, o, "acc = acc * " as *u8); o = eop_catn(buf, o, eop_atoi_from(tok, 1)); o = eop_cat(buf, o, "\n" as *u8); i = i + 1 81 } else { if c0 == 115 { // 's' sub 82 o = eop_indent(buf, o, depth); o = eop_cat(buf, o, "acc = acc - " as *u8); o = eop_catn(buf, o, eop_atoi_from(tok, 1)); o = eop_cat(buf, o, "\n" as *u8); i = i + 1 83 } else { if c0 == 105 { // 'i' if (tokens: if <pred> [ ... ]) 84 let pred: *u8 = argv[i+1] as *u8 85 o = eop_indent(buf, o, depth); o = eop_cat(buf, o, "if acc " as *u8); o = eop_cmp(buf, o, pred); o = eop_cat(buf, o, " {\n" as *u8) 86 let nti: *i64 = sys_mmap(8) as *i64 87 o = eop_emit_stmts(buf, o, argv, argc, i + 3, depth + 1, nti, gid) // body after 'if' pred '[' 88 o = eop_indent(buf, o, depth); o = eop_cat(buf, o, "}\n" as *u8) 89 i = nti[0] 90 } else { if c0 == 119 { // 'w' while (tokens: while <pred> [ ... ]) 91 let pred: *u8 = argv[i+1] as *u8 92 let myid: i64 = gid[0]; gid[0] = gid[0] + 1 93 o = eop_indent(buf, o, depth); o = eop_cat(buf, o, "var g" as *u8); o = eop_catn(buf, o, myid); o = eop_cat(buf, o, ": i64 = 0\n" as *u8) 94 o = eop_indent(buf, o, depth); o = eop_cat(buf, o, "while acc " as *u8); o = eop_cmp(buf, o, pred); o = eop_cat(buf, o, " {\n" as *u8) 95 let nti: *i64 = sys_mmap(8) as *i64 96 o = eop_emit_stmts(buf, o, argv, argc, i + 3, depth + 1, nti, gid) 97 o = eop_indent(buf, o, depth + 1); o = eop_cat(buf, o, "g" as *u8); o = eop_catn(buf, o, myid); o = eop_cat(buf, o, " = g" as *u8); o = eop_catn(buf, o, myid); o = eop_cat(buf, o, " + 1\n" as *u8) 98 o = eop_indent(buf, o, depth + 1); o = eop_cat(buf, o, "if g" as *u8); o = eop_catn(buf, o, myid); o = eop_cat(buf, o, " >= 100000 { break }\n" as *u8) 99 o = eop_indent(buf, o, depth); o = eop_cat(buf, o, "}\n" as *u8) 100 i = nti[0] 101 } else { i = i + 1 } } } } } // unknown token -> skip 102 } 103 out_ti[0] = i 104 return o 105} 106 107func main(argc: i64, argv: *i64) -> i64 { 108 if argc < 3 { eop_p("usage: nx_eoe_prog <basename> <start> <stmt...> (a/m/s<n> | if <pred> [ .. ] | while <pred> [ .. ])\n" as *u8); return 2 } 109 let base: *u8 = argv[1] as *u8 110 let start: i64 = eop_atoi_from(argv[2] as *u8, 0) 111 112 let path: *u8 = sys_mmap(512) 113 var po: i64 = 0 114 po = eop_cat(path, po, "runtime/_hdl_build/" as *u8) 115 po = eop_cat(path, po, base) 116 po = eop_cat(path, po, ".nx" as *u8) 117 path[po] = 0 as u8 118 119 let buf: *u8 = sys_mmap(K_MAGIC_262144) 120 var o: i64 = 0 121 o = eop_cat(buf, o, "// GENERATED BY nx_eoe_prog (emitter-of-emitters, unified statement-list mini-language) -- nested control flow synthesized from a DATA spec, compiled by nx_cc. license_tier: ORIGINAL\n" as *u8) 122 o = eop_cat(buf, o, "import \"nx_syscalls.nx\"\n" as *u8) 123 o = eop_cat(buf, o, "func main() -> i64 {\n" as *u8) 124 o = eop_cat(buf, o, " var acc: i64 = " as *u8); o = eop_catn(buf, o, start); o = eop_cat(buf, o, "\n" as *u8) 125 126 // recursive descent over the top-level statement list (tokens argv[3..argc)). 127 let nti: *i64 = sys_mmap(8) as *i64 128 let gid: *i64 = sys_mmap(8) as *i64; gid[0] = 0 129 o = eop_emit_stmts(buf, o, argv, argc, 3, 1, nti, gid) 130 131 o = eop_cat(buf, o, " sys_write(1, \"RESULT=\" as *u8, 7)\n" as *u8) 132 o = eop_cat(buf, o, " var m: i64 = acc\n" as *u8) 133 o = eop_cat(buf, o, " if m < 0 { sys_write(1, \"-\" as *u8, 1); m = 0 - m }\n" as *u8) 134 o = eop_cat(buf, o, " let t: *u8 = sys_mmap(28)\n" as *u8) 135 o = eop_cat(buf, o, " var k: i64 = 0\n" as *u8) 136 o = eop_cat(buf, o, " if m == 0 { t[0] = 48 as u8; k = 1 }\n" as *u8) 137 o = eop_cat(buf, o, " while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }\n" as *u8) 138 o = eop_cat(buf, o, " while k > 0 { k = k - 1; sys_write(1, (((t as i64)+k) as *u8), 1) }\n" as *u8) 139 o = eop_cat(buf, o, " sys_write(1, \"\\n\" as *u8, 1)\n" as *u8) 140 o = eop_cat(buf, o, " return 0\n}\n" as *u8) 141 142 let fd: i64 = sys_openat_wr(path, 420) 143 if fd < 0 { eop_p("EOEPROG verdict=RED reason=out-unwritable\n" as *u8); return 1 } 144 sys_write(fd, buf, o) 145 sys_close(fd) 146 eop_p("EOEPROG name=" as *u8); eop_p(path); eop_p(" verdict=EMITTED\n" as *u8) 147 return 0 148}