code wiki / _hdl_build / nx_doc_autoheal.nx
nx_doc_autoheal.nx source
↩ module page · 63 lines · 3888 B
1// nx_doc_autoheal.nx -- the Doctor's autonomous RESOLVE loop. Closes the two halves the team already has
2// (RECALL: the ki- known-issue catalogue; FIX: nx_doc_heal_let) into ONE hands-free pass: given a source that hit
3// the empty-.s symptom AND the diagnostic the runner/compiler emitted, it (1) RECALLs the lesson from the catalogue,
4// (2) ROUTEs to the matching auto-fixer iff the recalled class is one we can fix, (3) APPLIEs the fix, and (4)
5// VERIFIEs the defect is actually gone (static post-condition: no reassigned `let` remains). The real recompile is
6// the caller's next step on the healed bytes -- nesting a full rebuild HERE would trip NX-GATE-NESTED-BUILD (a
7// lesson we recorded), so the safe, honest boundary is decision+transform+postcondition. Honest by construction:
8// no recall -> DAH_UNKNOWN (invents nothing); recalled but not our class / no applicable change -> DAH_NOFIX (does
9// not falsely claim a heal); only a verified-clean rewrite returns DAH_HEALED. license_tier: ORIGINAL
10import "nx_syscalls.nx"
11import "nx_known_issue_store.nx"
12import "nx_doc_heal_let.nx"
13
14const DAH_HEALED: i64 = 1 // recalled + fixed + verified the reassigned-let defect is gone
15const DAH_NOFIX: i64 = 0 // recalled (or off-class) but our auto-fixer had no applicable change -- honest
16const DAH_UNKNOWN: i64 = 0-1 // no lesson recalled -> genuinely novel; resolve invents nothing
17
18func dah_tlen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
19func dah_copy(src: *u8, n: i64, out: *u8, outcap: i64) -> i64 {
20 var c: i64 = 0
21 while c < n { if c < outcap-1 { out[c] = src[c] } c = c + 1 }
22 out[n] = 0 as u8
23 return n
24}
25// 1 if any `let NAME` in src is later REASSIGNED (the post-condition we must clear). Reuses the fixer's own
26// detectors (dhl_isident / dhl_name_at / dhl_is_reassigned) so "fixed" means fixed by the SAME definition.
27func dah_has_reassigned_let(src: *u8, n: i64) -> i64 {
28 let nb: *u8 = sys_mmap(256)
29 var i: i64 = 0
30 while i + 4 <= n {
31 if src[i]==(108 as u8) { if src[i+1]==(101 as u8) { if src[i+2]==(116 as u8) { if src[i+3]==(32 as u8) {
32 var bb: i64 = 0
33 if i==0 { bb=1 } else { if dhl_isident(src[i-1] as i64)==0 { bb=1 } }
34 if bb==1 {
35 var np: i64 = i + 4
36 var sk: i64 = 0
37 while sk==0 { if np<n { if src[np]==(32 as u8) { np=np+1 } else { sk=1 } } else { sk=1 } }
38 let nl: i64 = dhl_name_at(src, n, np, nb)
39 if nl>0 { if dhl_is_reassigned(src, n, nb, nl, np)==1 { return 1 } }
40 }
41 } } } }
42 i = i + 1
43 }
44 return 0
45}
46// the closed loop. diag = the diagnostic the runner/compiler emitted; src = the failing source. out gets the
47// healed source (or an unchanged copy when we cannot fix); outid/outrem get the recalled lesson id + remedy.
48func dah_resolve(diag: *u8, dlen: i64, src: *u8, n: i64, out: *u8, outcap: i64, outid: *u8, outrem: *u8) -> i64 {
49 let ostat: *u8 = sys_mmap(64)
50 let r: i64 = ki_recall(KI_PREFIX, diag, dlen, outid, outrem, ostat)
51 if r != KI_HIT { dah_copy(src, n, out, outcap); return DAH_UNKNOWN }
52 // ROUTE: only the empty-.s / let-reassign class is one our auto-fixer handles.
53 var ours: i64 = 0
54 if ki_substr(outid, dah_tlen(outid), "EMPTYS" as *u8, 6) >= 0 { ours = 1 }
55 if ki_substr(outid, dah_tlen(outid), "LET-REASSIGN" as *u8, 12) >= 0 { ours = 1 }
56 if ours == 0 { dah_copy(src, n, out, outcap); return DAH_NOFIX }
57 // APPLY the let-reassign fixer.
58 let changes: i64 = dhl_heal(src, n, out, outcap)
59 if changes <= 0 { return DAH_NOFIX } // off-sub-case (e.g. reserved-kw): honest no-claim
60 // VERIFY the defect is actually gone before claiming a heal.
61 if dah_has_reassigned_let(out, dah_tlen(out)) == 0 { return DAH_HEALED }
62 return DAH_NOFIX
63}