code wiki / _hdl_build / nx_asset_emit_gen.nx
nx_asset_emit_gen.nx source
↩ module page · 110 lines · 6206 B
1// nx_asset_emit_gen.nx -- EMITTER-GENERATOR: turns any text asset into a NISHILANG EMITTER ORGAN,
2// making the .nx the SSOT and the asset a generated artifact (operator 2026-07-02: "use and build up
3// the nishi ecosystem including nishi lang" -- the last mile must be EMITTED by an organ, never
4// hand-edited). usage: nx_asset_emit_gen <asset> <out.nx> <organ_name> <target_path>
5// The generated organ: main(argc,argv) emits the asset bytes to <target_path> (argv[1] overrides the
6// target -- that is the DRIFT-KILL seam: emit to a compare path, byte-diff vs the canonical file).
7// Escaping: printable ASCII raw; '"'->\" '\\'->\\ LF->\n; all else -> \xHH with a FORCED literal
8// break when the next byte is a hex digit (so the lexer can never over-consume the escape).
9// license_tier: ORIGINAL
10import "nx_syscalls.nx"
11const K_MAGIC_65536: i64 = 65536
12const K_MAGIC_1200: i64 = 1200
13
14func gl(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
15func ap(b: *u8, n: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){b[n+i]=s[i];i=i+1} return n+i }
16func apn(b: *u8, n: i64, v: i64) -> i64 {
17 let t: *u8=sys_mmap(28); var m: i64=v; var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}
18 var i: i64=0; var p: i64=n; while i<k{b[p]=t[k-1-i];p=p+1;i=i+1} return p }
19func hexd(v: i64) -> i64 { if v < 10 { return 48 + v } return 87 + v } // 0-9 a-f
20func ishex(c: i64) -> i64 {
21 if c >= 48 { if c <= 57 { return 1 } }
22 if c >= 97 { if c <= 102 { return 1 } }
23 if c >= 65 { if c <= 70 { return 1 } }
24 return 0 }
25
26func main(argc: i64, argv: *i64) -> i64 {
27 if argc < 5 { sys_write(1, "usage: nx_asset_emit_gen <asset> <out.nx> <organ_name> <target_path>\n" as *u8, 70); return 2 }
28 let srcp: *u8 = argv[1] as *u8
29 let outp: *u8 = argv[2] as *u8
30 let name: *u8 = argv[3] as *u8
31 let tgt: *u8 = argv[4] as *u8
32 let box: *i64 = sys_mmap(16) as *i64
33 let src: *u8 = sys_read_file(srcp, box)
34 if (src as i64) == 0 { sys_write(1, "cannot read asset\n" as *u8, 18); return 1 }
35 let sn: i64 = box[0]
36 let out: *u8 = sys_mmap(sn * 6 + K_MAGIC_65536)
37 var o: i64 = 0
38 o = ap(out, o, "// " as *u8)
39 o = ap(out, o, name)
40 o = ap(out, o, ".nx -- GENERATED EMITTER (nx_asset_emit_gen). THIS ORGAN IS THE SSOT for\n// " as *u8)
41 o = ap(out, o, tgt)
42 o = ap(out, o, " -- edit HERE (or regenerate), NEVER the emitted artifact.\n// argv[1] overrides the target (the drift-kill seam: emit to a compare path + byte-diff).\n// license_tier: ORIGINAL\nimport \"nx_syscalls.nx\"\n\n" as *u8)
43 // parts: cap ~1200 source bytes per literal; break early after \xHH if next is a hex digit
44 var parts: i64 = 0
45 var i: i64 = 0
46 while i < sn {
47 o = ap(out, o, "const P" as *u8)
48 o = apn(out, o, parts)
49 o = ap(out, o, ": *u8 = \"" as *u8)
50 var used: i64 = 0
51 var open: i64 = 1
52 while open == 1 {
53 if i >= sn { open = 0 } else { if used >= K_MAGIC_1200 { open = 0 } else {
54 let c: i64 = src[i] as i64
55 if c == 34 { out[o]=92 as u8; out[o+1]=34 as u8; o=o+2 }
56 else { if c == 92 { out[o]=92 as u8; out[o+1]=92 as u8; o=o+2 }
57 else { if c == 10 { out[o]=92 as u8; out[o+1]=110 as u8; o=o+2 }
58 else { if c >= 32 { if c <= 126 { out[o]=c as u8; o=o+1 } else {
59 out[o]=92 as u8; out[o+1]=120 as u8; out[o+2]=hexd(c/16) as u8; out[o+3]=hexd(c%16) as u8; o=o+4
60 if i+1 < sn { if ishex(src[i+1] as i64)==1 { open = 0 } } // force break: lexer safety
61 } } else {
62 out[o]=92 as u8; out[o+1]=120 as u8; out[o+2]=hexd(c/16) as u8; out[o+3]=hexd(c%16) as u8; o=o+4
63 if i+1 < sn { if ishex(src[i+1] as i64)==1 { open = 0 } }
64 } } } }
65 i = i + 1
66 used = used + 1
67 } }
68 }
69 o = ap(out, o, "\"\n" as *u8)
70 parts = parts + 1
71 }
72 o = ap(out, o, "\nfunc ep(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return n }\n\nfunc main(argc: i64, argv: *i64) -> i64 {\n var tgt: *u8 = \"" as *u8)
73 // target path into the generated organ (escape just \" and \\ -- paths are plain ASCII)
74 var q: i64 = 0
75 while tgt[q] != (0 as u8) {
76 let tc: i64 = tgt[q] as i64
77 if tc == 34 { out[o]=92 as u8; out[o+1]=34 as u8; o=o+2 } else { if tc == 92 { out[o]=92 as u8; out[o+1]=92 as u8; o=o+2 } else { out[o]=tc as u8; o=o+1 } }
78 q = q + 1
79 }
80 o = ap(out, o, "\" as *u8\n if argc >= 2 { tgt = argv[1] as *u8 }\n let fd: i64 = sys_openat_wr(tgt, 0x1a4)\n if fd < 0 { sys_write(1, \"emit: cannot open target\\n\" as *u8, 25); return 1 }\n var n: i64 = 0\n" as *u8)
81 var pctr: i64 = 0
82 while pctr < parts {
83 o = ap(out, o, " n = n + ep(fd, P" as *u8)
84 o = apn(out, o, pctr)
85 o = ap(out, o, ")\n" as *u8)
86 pctr = pctr + 1
87 }
88 o = ap(out, o, " sys_close(fd)\n sys_write(1, \"EMITTED \" as *u8, 8)\n let b: *u8 = sys_mmap(28)\n var m: i64 = n\n let t: *u8 = sys_mmap(28)\n var k: i64 = 0\n if m == 0 { t[0] = 48 as u8; k = 1 }\n while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }\n var i: i64 = 0\n while i < k { b[i] = t[k-1-i]; i = i + 1 }\n sys_write(1, b, k)\n sys_write(1, \" bytes\\n\" as *u8, 7)\n return 0\n}\n" as *u8)
89 let fd: i64 = sys_openat_wr(outp, 0x1a4)
90 if fd < 0 { sys_write(1, "cannot write out.nx\n" as *u8, 20); return 1 }
91 var wr: i64 = 0
92 while wr < o {
93 let w: i64 = sys_write(fd, out + wr, o - wr)
94 if w <= 0 { sys_close(fd); return 1 }
95 wr = wr + w
96 }
97 sys_close(fd)
98 sys_write(1, "GENERATED emitter organ: parts=" as *u8, 31)
99 let b2: *u8 = sys_mmap(28)
100 var m2: i64 = parts
101 let t2: *u8 = sys_mmap(28)
102 var k2: i64 = 0
103 if m2 == 0 { t2[0]=48 as u8; k2=1 }
104 while m2 > 0 { t2[k2]=(48+(m2%10)) as u8; m2=m2/10; k2=k2+1 }
105 var i2: i64 = 0
106 while i2 < k2 { b2[i2]=t2[k2-1-i2]; i2=i2+1 }
107 sys_write(1, b2, k2)
108 sys_write(1, "\n" as *u8, 1)
109 return 0
110}