code wiki / _hdl_build / nx_build_imports_gate.nx

nx_build_imports_gate.nx source

↩ module page · 173 lines · 8956 B

1// nx_build_imports_gate.nx -- SECOND genealogy LENS (operator: "multiple ways to look at ancestors and 2// descendants, fine with all ... rooted from god so we can rebuild anything"). Where nx_build_lineage_gate 3// gives the genesis-anchor view (organ -> DESC-ORGANS -> god), THIS gives the IMPORT-DEPENDENCY view = the 4// REAL rebuild DAG: an organ's true ancestors are the organs it `import`s, recursively, bottoming out at 5// nx_syscalls (the toolchain leaf, which roots to god via DESC-TOOLCHAIN). To REBUILD an organ you must 6// first build its imports -> the import graph IS the rebuild order. A dangling import (names a file that 7// does not exist) = a broken-lineage orphan = forbidden. 8// BOTH directions: ANCESTORS(organ) = its imports; DESCENDANTS(lib) = who imports it. 9// GATE w/ NEG-CONTROL: GREEN iff EVERY registered organ's imports all RESOLVE (0 dangling) AND a bogus 10// import name is detected as unresolvable. Self-contained. license_tier: ORIGINAL expect_exit: 0 11import "nx_syscalls.nx" 12 13const REG: *u8 = "knowledge/registry/build_registry.log" 14const FB: i64 = 262144 15const MAXO: i64 = 8192 16const SLOT: i64 = 160 17 18func ip(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 19func ilen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 20func ipn(v: i64) -> i64 { 21 let bb: *u8 = sys_mmap(28); var m: i64 = v 22 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 23 let t: *u8 = sys_mmap(28); var k: i64 = 0 24 if m == 0 { t[0] = 48 as u8; k = 1 } 25 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 26 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 27 sys_write(1, bb, k); return 0 28} 29func istreq(a: *u8, b: *u8) -> i64 { 30 var i: i64 = 0 31 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } 32 if b[i] != (0 as u8) { return 0 } 33 return 1 34} 35func iread(path: *u8, buf: *u8, cap: i64) -> i64 { 36 let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 - 1 } 37 var total: i64 = 0; var nrd: i64 = sys_read(fd, buf, cap) 38 while nrd > 0 { total = total + nrd; if total >= cap { nrd = 0 } else { nrd = sys_read(fd, ((buf as i64) + total) as *u8, cap - total) } } 39 sys_close(fd); return total 40} 41func iexists(path: *u8) -> i64 { let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 } sys_close(fd); return 1 } 42func ijoin(pfx: *u8, name: *u8, out: *u8) -> i64 { 43 var o: i64 = 0; var i: i64 = 0 44 while pfx[i] != (0 as u8) { out[o] = pfx[i]; o = o + 1; i = i + 1 } 45 i = 0; while name[i] != (0 as u8) { out[o] = name[i]; o = o + 1; i = i + 1 } 46 out[o] = 0 as u8; return 0 47} 48// resolve an import name to a real file in runtime/_hdl_build or runtime. 1 if it exists. 49func iresolve(name: *u8) -> i64 { 50 let p: i64 = sys_mmap(512) as i64 51 ijoin("runtime/_hdl_build/" as *u8, name, p as *u8); if iexists(p as *u8) == 1 { return 1 } 52 ijoin("runtime/" as *u8, name, p as *u8); if iexists(p as *u8) == 1 { return 1 } 53 return 0 54} 55// set out to the existing path of organ `name` (try _hdl_build then runtime). 1 if found. 56func iorgan_path(name: *u8, out: *u8) -> i64 { 57 ijoin("runtime/_hdl_build/" as *u8, name, out); if iexists(out) == 1 { return 1 } 58 ijoin("runtime/" as *u8, name, out); if iexists(out) == 1 { return 1 } 59 return 0 60} 61func ifind(buf: *u8, from: i64, to: i64, pat: *u8) -> i64 { 62 let pl: i64 = ilen(pat); if pl == 0 { return 0 - 1 } 63 var i: i64 = from 64 while i + pl <= to { var j: i64 = 0; var ok: i64 = 1; while j < pl { if buf[i + j] != pat[j] { ok = 0; j = pl } else { j = j + 1 } } if ok == 1 { return i } i = i + 1 } 65 return 0 - 1 66} 67// scan a file's bytes for import "<name>" -> out[] names (ptrs). returns count. 68func imp_scan(buf: *u8, n: i64, out: *i64, cap: i64) -> i64 { 69 var cnt: i64 = 0; var i: i64 = 0 70 while i < n { 71 let pos: i64 = ifind(buf, i, n, "import " as *u8) 72 if pos < 0 { i = n } else { 73 // find the opening quote (char 34) after "import " 74 var q: i64 = pos + 7; var g: i64 = 1 75 while g == 1 { if q >= n { g = 0 } else { if buf[q] == (34 as u8) { g = 0 } else { q = q + 1 } } } 76 if q < n { 77 var s: i64 = q + 1; var o: i64 = 0; let nb: *u8 = sys_mmap(SLOT); var g2: i64 = 1 78 while g2 == 1 { if s >= n { g2 = 0 } else { if buf[s] == (34 as u8) { g2 = 0 } else { if o < SLOT - 1 { nb[o] = buf[s]; o = o + 1 } s = s + 1 } } } 79 nb[o] = 0 as u8 80 if o > 0 { if cnt < cap { out[cnt] = nb as i64; cnt = cnt + 1 } } 81 i = s + 1 82 } else { i = n } 83 } 84 } 85 return cnt 86} 87// does organ file `organ` import `target`? 88func imports_target(organ: *u8, target: *u8) -> i64 { 89 let op: *u8 = sys_mmap(512) 90 if iorgan_path(organ, op) == 0 { return 0 } 91 let buf: *u8 = sys_mmap(FB); let n: i64 = iread(op, buf, FB) 92 if n <= 0 { return 0 } 93 let imps: *i64 = sys_mmap(8 * 64) as *i64 94 let ic: i64 = imp_scan(buf, n, imps, 64) 95 var k: i64 = 0 96 while k < ic { if istreq(imps[k] as *u8, target) == 1 { return 1 } k = k + 1 } 97 return 0 98} 99 100func main() -> i64 { 101 ip("=== nx_build_imports_gate: IMPORT-DEPENDENCY genealogy (the real rebuild DAG) ===\n" as *u8) 102 let rbuf: *u8 = sys_mmap(FB); let rn: i64 = iread(REG, rbuf, FB) 103 if rn <= 0 { ip(" ERROR: no build registry\n" as *u8); sys_exit(2); return 2 } 104 105 // distinct registered organ names 106 let names: *i64 = sys_mmap(8 * MAXO) as *i64 107 var cnt: i64 = 0; var i: i64 = 0 108 while i < rn { 109 let ls: i64 = i; var le: i64 = ls; var g: i64 = 1 110 while g == 1 { if le >= rn { g = 0 } else { if rbuf[le] == (10 as u8) { g = 0 } else { le = le + 1 } } } 111 let kp: i64 = ifind(rbuf, ls, le, "organ=" as *u8) 112 if kp >= 0 { 113 var v: i64 = kp + 6; var o: i64 = 0; let ob: *u8 = sys_mmap(SLOT) 114 while v < le { if rbuf[v] == (32 as u8) { v = le } else { if o < SLOT - 1 { ob[o] = rbuf[v]; o = o + 1 } v = v + 1 } } 115 ob[o] = 0 as u8 116 var found: i64 = 0; var k: i64 = 0 117 while k < cnt { if istreq(names[k] as *u8, ob) == 1 { found = 1; k = cnt } else { k = k + 1 } } 118 if found == 0 { if cnt < MAXO { names[cnt] = ob as i64; cnt = cnt + 1 } } 119 } 120 i = le + 1 121 } 122 123 // verify EVERY registered organ's imports resolve (0 dangling = no broken lineage) 124 var total_imp: i64 = 0; var dangling: i64 = 0 125 var di: i64 = 0 126 while di < cnt { 127 let op: *u8 = sys_mmap(512) 128 if iorgan_path(names[di] as *u8, op) == 1 { 129 let buf: *u8 = sys_mmap(FB); let n: i64 = iread(op, buf, FB) 130 let imps: *i64 = sys_mmap(8 * 64) as *i64 131 let ic: i64 = imp_scan(buf, n, imps, 64) 132 var k: i64 = 0 133 while k < ic { 134 total_imp = total_imp + 1 135 if iresolve(imps[k] as *u8) == 0 { dangling = dangling + 1; ip(" DANGLING import: " as *u8); ip(names[di] as *u8); ip(" -> " as *u8); ip(imps[k] as *u8); ip("\n" as *u8) } 136 k = k + 1 137 } 138 } 139 di = di + 1 140 } 141 ip(" registered organs=" as *u8); ipn(cnt); ip(" total import edges=" as *u8); ipn(total_imp); ip(" DANGLING(broken lineage)=" as *u8); ipn(dangling); ip("\n" as *u8) 142 143 // ANCESTORS view: the direct imports of one organ = what you must build first to rebuild it 144 ip(" ANCESTORS(nx_build_registry.nx) [imports = rebuild-first]: " as *u8) 145 let op2: *u8 = sys_mmap(512) 146 if iorgan_path("nx_build_registry.nx" as *u8, op2) == 1 { 147 let buf2: *u8 = sys_mmap(FB); let n2: i64 = iread(op2, buf2, FB) 148 let imps2: *i64 = sys_mmap(8 * 64) as *i64; let ic2: i64 = imp_scan(buf2, n2, imps2, 64) 149 var k: i64 = 0 150 while k < ic2 { ip(imps2[k] as *u8); ip(" " as *u8); k = k + 1 } 151 } 152 ip("\n" as *u8) 153 154 // DESCENDANTS view: who imports the lib (the other direction) 155 ip(" DESCENDANTS(nx_build_registry_lib.nx) [who imports it]: " as *u8) 156 var dd: i64 = 0 157 while dd < cnt { if imports_target(names[dd] as *u8, "nx_build_registry_lib.nx" as *u8) == 1 { ip(names[dd] as *u8); ip(" " as *u8) } dd = dd + 1 } 158 ip("\n" as *u8) 159 160 // NEG-CONTROL: a bogus import name must NOT resolve; a real leaf must. 161 let nc_bad: i64 = iresolve("nx_zzz_nonexistent_organ.nx" as *u8) 162 let nc_good: i64 = iresolve("nx_syscalls.nx" as *u8) 163 ip(" neg-control: resolve(bogus)=" as *u8); ipn(nc_bad); ip(" (expect 0) resolve(nx_syscalls.nx)=" as *u8); ipn(nc_good); ip(" (expect 1)\n" as *u8) 164 165 var ok: i64 = 1 166 if dangling != 0 { ok = 0 } 167 if nc_bad != 0 { ok = 0 } 168 if nc_good != 1 { ok = 0 } 169 ip(" verdict=" as *u8) 170 if ok == 1 { ip("GREEN (every organ's imports resolve = rebuildable DAG; dangling rejected)\n" as *u8); sys_exit(0); return 0 } 171 ip("RED (a dangling import = broken lineage, or neg-control disarmed)\n" as *u8) 172 sys_exit(1); return 1 173}