code wiki / _hdl_build / nx_doctor_import.nx

nx_doctor_import.nx source

↩ module page · 105 lines · 4828 B

1// nx_doctor_import.nx -- DOCTOR sub-organ (the IMPORT-FIXER role; sibling of nx_doctor_fix). Turns the 2// CC-UNDEFFN known-issue ("call to undefined function: X") from recall-and-REPORT into a real AUTO-FIX 3// for the resolvable case: most such failures are a MISSING IMPORT, and every sys_* primitive lives in 4// nx_syscalls.nx (verified sys_write @ nx_syscalls.nx:79). So: extract the named function from the 5// Engineer's diagnostic, resolve it to the organ that defines it, and write a healed candidate with the 6// import prepended (ADDITIVE -- new file, the protected source is never clobbered). 7// 8// RACI: the Doctor produces a CANDIDATE only; it does NOT verify (the Engineer re-compiles) and does 9// NOT admit (Warden/Council). di_resolve returns 0 for names it cannot resolve -> the caller falls back 10// to recall-and-report (NO false fix -- honest). v1 rule = sys_*->nx_syscalls.nx (deterministic); a 11// general symbol-index over the corpus is the next extension. license_tier: ORIGINAL 12import "nx_syscalls.nx" 13 14func di_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 15 16// local unlinkat(AT_FDCWD,path,0) -- x86_64 raw 263 passthrough (the nx_novel_close.nx:61 precedent), 17// so a gate can clean up its own temp candidates without touching shared nx_syscalls.nx. 18func di_unlink(path: *u8) -> i64 { __syscall(263, AT_FDCWD, path, 0, 0, 0, 0) return 0 } 19 20// first index of needle in hay[0..hlen), or -1 21func di_find(hay: *u8, hlen: i64, needle: *u8) -> i64 { 22 let nlen: i64 = di_len(needle) 23 var i: i64 = 0 24 while i + nlen <= hlen { 25 var m: i64 = 1 26 var j: i64 = 0 27 while j < nlen { if hay[i + j] != needle[j] { m = 0; j = nlen } else { j = j + 1 } } 28 if m == 1 { return i } 29 i = i + 1 30 } 31 return 0 - 1 32} 33 34// extract the function name from a captured "call to undefined function: <name>" diagnostic into out 35// (NUL-terminated); returns its length, or 0 if the diagnostic is not this class. 36func di_undef_fn(diag_path: *u8, out: *u8) -> i64 { 37 let lenp: *i64 = sys_mmap(16) as *i64 38 let buf: *u8 = sys_read_file(diag_path, lenp) 39 let blen: i64 = lenp[0] 40 if blen <= 0 { out[0] = 0 as u8; return 0 } 41 let marker: *u8 = "call to undefined function: " as *u8 42 let at: i64 = di_find(buf, blen, marker) 43 if at < 0 { out[0] = 0 as u8; return 0 } 44 var i: i64 = at + di_len(marker) 45 var o: i64 = 0 46 var go: i64 = 1 47 while go == 1 { 48 if i >= blen { go = 0 } else { 49 let c: i64 = buf[i] 50 if c == 10 { go = 0 } else { 51 if c == 13 { go = 0 } else { out[o] = buf[i]; o = o + 1; i = i + 1 } 52 } 53 } 54 } 55 out[o] = 0 as u8 56 return o 57} 58 59// resolve an undefined-function name to the import that defines it. v1 deterministic rule: a sys_* 60// primitive lives in nx_syscalls.nx. Returns import length (out_import NUL-terminated), or 0 if 61// unresolved (honest -- NO false fix; the caller reports instead). Flat byte checks (avoids the 62// LM-002 deep-nested-if landmine); reads a few bytes past a short name's NUL land on 0 != expected. 63func di_resolve(name: *u8, out_import: *u8) -> i64 { 64 var issys: i64 = 1 65 if name[0] != (115 as u8) { issys = 0 } // 's' 66 if name[1] != (121 as u8) { issys = 0 } // 'y' 67 if name[2] != (115 as u8) { issys = 0 } // 's' 68 if name[3] != (95 as u8) { issys = 0 } // '_' 69 if issys == 1 { 70 let imp: *u8 = "nx_syscalls.nx" as *u8 71 var i: i64 = 0 72 while imp[i] != (0 as u8) { out_import[i] = imp[i]; i = i + 1 } 73 out_import[i] = 0 as u8 74 return i 75 } 76 out_import[0] = 0 as u8 77 return 0 78} 79 80// HEAL: write out_path = `import "<imp>"` + newline + the original source (additive candidate). 81// Returns chars added (= import-line length). The quote bytes are emitted directly (34) to avoid any 82// escaped-quote-in-literal dependency. 83func di_heal(src_path: *u8, out_path: *u8, imp: *u8) -> i64 { 84 let lenp: *i64 = sys_mmap(16) as *i64 85 let src: *u8 = sys_read_file(src_path, lenp) 86 let slen: i64 = lenp[0] 87 let ilen: i64 = di_len(imp) 88 let buf: *u8 = sys_mmap(slen + ilen + 64) 89 var o: i64 = 0 90 let pre: *u8 = "import " as *u8 91 var k: i64 = 0 92 while pre[k] != (0 as u8) { buf[o] = pre[k]; o = o + 1; k = k + 1 } 93 buf[o] = 34 as u8; o = o + 1 // opening quote 94 var ii: i64 = 0 95 while ii < ilen { buf[o] = imp[ii]; o = o + 1; ii = ii + 1 } 96 buf[o] = 34 as u8; o = o + 1 // closing quote 97 buf[o] = 10 as u8; o = o + 1 // newline 98 var t: i64 = 0 99 while t < slen { buf[o] = src[t]; o = o + 1; t = t + 1 } 100 let fd: i64 = sys_openat_wr(out_path, 0x1a4) 101 if fd < 0 { return 0 - 1 } 102 sys_write(fd, buf, o) 103 sys_close(fd) 104 return o - slen 105}