code wiki / _hdl_build / nx_bugforge.nx

nx_bugforge.nx source

↩ module page · 907 lines · 38859 B

1// nx_bugforge.nx -- SWE-SCALE INSTANCE MINER (bugforge-swe-scale, 2026-07-24). The oracle today is 2// 14 hand-seeded toy candidates; a frontier harness needs HUNDREDS of real-code instances plus a 3// learned fix corpus. This organ mines them MECHANICALLY from the real runtime tree: 4// 1 SCAN real .nx files for LEAF-PURE functions (all-i64 params, i64 return, no calls, no loops, 5// no division, no pointers -- the v1 safety envelope, every exclusion COUNTED not silent) 6// 2 MUTATE one operator swap per instance (data-driven op table: +/-, -/+, </>, >/<, */+) 7// 3 VERIFY a generated PROBE compiles orig (renamed) + mutant side by side and sweeps the domain; 8// the ORIGINAL IS THE ORACLE -- divergent cases are real failing tests, agreement cases 9// are pass-to-pass regression teeth (the SWE-bench F2P+P2P contract, mechanically minted). 10// No divergence proof => instance DISCARDED (absence of proof is not equivalence). 11// 4 EMIT a self-contained candidate (mutant under its REAL name + FNRES/FNCASE grader main) that 12// is byte-compatible with nx_autofix_auto's episode loop, a manifest row (name|path), and 13// a (buggy TAB fixed) corpus row for retrieval few-shots (single-line fns). 14// verbs: mine [maxn] [dir] (defaults 16, runtime) | selftest 15// bf_manifest.txt / bf_fixcorpus.txt are DERIVED artifacts regenerated per run (documented REPLACE). 16// license_tier: ORIGINAL No hw writes (Rule 26). 17import "nx_tool_run.nx" 18import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 19import "nx_syscalls.nx" 20 21const BF_FCAP: i64 = 262144 // per-source-file read cap (bigger files skipped + counted) 22const BF_DCAP: i64 = 65536 // getdents buffer 23const BF_TCAP: i64 = 4096 // one extracted function text 24const BF_SRCCAP: i64 = 32768 // generated probe/candidate source 25const BF_OCAP: i64 = 524288 // build+run capture 26const BF_LISTCAP: i64 = 131072 // manifest/corpus accumulators 27const BF_PATHCAP: i64 = 256 28const BF_DOM: i64 = 6 // sweep half-width arity 1-2 (13 values/axis) 29const BF_DOM3: i64 = 4 // sweep half-width arity 3 (9^3=729 evals) 30const BF_MAXCASE: i64 = 6 // banked divergent (fail-to-pass) cases 31const BF_MAXPASS: i64 = 6 // banked agreement (pass-to-pass) cases 32const BF_PERFN: i64 = 2 // max instances per function (corpus diversity) 33const BF_MINB: i64 = 30 // min fn bytes (below = trivial) 34const BF_MAXB: i64 = 1200 // max fn bytes (fits the episode splice path) 35const BF_NOPS: i64 = 5 36const BF_ZERO: i64 = 48 37const BF_MODE: i64 = 420 // 0644 file mode (decimal per the magic ratchet) 38 39func w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 40// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 41// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 42// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 43// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 44func wn(v: i64) -> i64 { nxi_out(v); return 0 } 45func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 46func sfind(hay: *u8, hn: i64, needle: *u8, from: i64) -> i64 { 47 let m: i64 = slen(needle) 48 if m == 0 { return 0 - 1 } 49 var i: i64 = from 50 while i + m <= hn { 51 var j: i64 = 0 52 var ok: i64 = 1 53 while j < m { if hay[i + j] != needle[j] { ok = 0; j = m } else { j = j + 1 } } 54 if ok == 1 { return i } 55 i = i + 1 56 } 57 return 0 - 1 58} 59func bcat(b: *u8, off: i64, s: *u8) -> i64 { 60 var i: i64 = 0 61 var o: i64 = off 62 while s[i] != (0 as u8) { b[o] = s[i]; o = o + 1; i = i + 1 } 63 return o 64} 65func bcatr(b: *u8, off: i64, s: *u8, n: i64) -> i64 { 66 var i: i64 = 0 67 var o: i64 = off 68 while i < n { b[o] = s[i]; o = o + 1; i = i + 1 } 69 return o 70} 71func bcatn(b: *u8, off: i64, v: i64) -> i64 { 72 var m: i64 = v 73 var o: i64 = off 74 if m < 0 { b[o] = 45 as u8; o = o + 1; m = 0 - m } 75 let t: *u8 = sys_mmap(24) 76 var k: i64 = 0 77 if m == 0 { t[0] = BF_ZERO as u8; k = 1 } 78 while m > 0 { t[k] = (BF_ZERO + (m % 10)) as u8; m = m / 10; k = k + 1 } 79 var i: i64 = 0 80 while i < k { b[o] = t[k - 1 - i]; o = o + 1; i = i + 1 } 81 return o 82} 83// emit one double-quote byte into generated source (my own literals never carry quotes) 84func bq(b: *u8, off: i64) -> i64 { b[off] = 34 as u8; return off + 1 } 85// emit a QUOTED literal: "s" 86func bqs(b: *u8, off: i64, s: *u8) -> i64 { 87 var o: i64 = bq(b, off) 88 o = bcat(b, o, s) 89 o = bq(b, o) 90 return o 91} 92func scontains(hay: *u8, hn: i64, needle: *u8) -> i64 { if sfind(hay, hn, needle, 0) >= 0 { return 1 } return 0 } 93 94// ---- io (buffers-once discipline: caller owns every buffer; no per-file mmap growth) ---- 95func bf_read(path: *u8, buf: *u8, cap: i64) -> i64 { 96 let fd: i64 = sys_openat_rd(path) 97 if fd < 0 { return 0 - 1 } 98 var n: i64 = 0 99 var go: i64 = 1 100 var rc: i64 = 0 101 while go == 1 { 102 if n >= cap { sys_close(fd); return 0 - 2 } 103 let r: i64 = sys_read(fd, ((buf as i64) + n) as *u8, cap - n) 104 if r <= 0 { go = 0 } else { n = n + r } 105 } 106 sys_close(fd) 107 rc = n 108 return rc 109} 110func bf_write(path: *u8, buf: *u8, n: i64) -> i64 { 111 let fd: i64 = sys_openat_wr(path, BF_MODE) 112 if fd < 0 { return 0 - 1 } 113 sys_write(fd, buf, n) 114 sys_close(fd) 115 return n 116} 117 118// build+run a runtime/<name>.nx via the sovereign orchestrator; capture stdout (compile+run output) 119func bf_run(name: *u8, out: *u8, cap: i64) -> i64 { 120 let av: *i64 = sys_mmap(64) as *i64 121 av[0] = "_offc/nx_sov_build_run.elf" as *u8 as i64 122 av[1] = name as i64 123 av[2] = 0 124 let olen: *i64 = sys_mmap(8) as *i64 125 olen[0] = 0 126 tr_run_capture("_offc/nx_sov_build_run.elf" as *u8, av, out, cap, olen) 127 return olen[0] 128} 129 130// parse the first integer (optional '-') right after `token` in buf[0,n); box[0]=value; ret 1/0 131func bf_intafter(buf: *u8, n: i64, token: *u8, from: i64, box: *i64) -> i64 { 132 let at: i64 = sfind(buf, n, token, from) 133 if at < 0 { return 0 } 134 var q: i64 = at + slen(token) 135 var neg: i64 = 0 136 if q < n { if buf[q] == (45 as u8) { neg = 1; q = q + 1 } } 137 var v: i64 = 0 138 var any: i64 = 0 139 var go: i64 = 1 140 while go == 1 { 141 if q >= n { go = 0 } 142 else { 143 let c: i64 = buf[q] as i64 144 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48); any = 1; q = q + 1 } else { go = 0 } } else { go = 0 } 145 } 146 } 147 if any == 0 { return 0 } 148 if neg == 1 { v = 0 - v } 149 box[0] = v 150 box[1] = q 151 return 1 152} 153 154// ---- function extraction + eligibility ---- 155// extract the function starting at fbuf[at] ("func ...") through brace depth 0 -> [at,end); ret end|-1 156func bf_fnend(fbuf: *u8, n: i64, at: i64) -> i64 { 157 var e: i64 = at 158 var depth: i64 = 0 159 var seen: i64 = 0 160 var go: i64 = 1 161 while go == 1 { 162 if e >= n { go = 0 } 163 else { 164 let c: i64 = fbuf[e] as i64 165 if c == 123 { depth = depth + 1; seen = 1 } 166 if c == 125 { depth = depth - 1 } 167 e = e + 1 168 if seen == 1 { if depth == 0 { go = 0 } } 169 } 170 } 171 if seen == 0 { return 0 - 1 } 172 if depth != 0 { return 0 - 1 } 173 return e 174} 175// parse name into nb (cap BF_NAMECAP-1); return arity (>=1) or -reason. 176// reasons: -1 malformed -2 pointer-param/non-i64 -3 bad-return -4 arity-range 177func bf_fnsig(t: *u8, tn: i64, nb: *u8) -> i64 { 178 if tn < 12 { return 0 - 1 } 179 let po: i64 = sfind(t, tn, "(" as *u8, 0) 180 if po < 6 { return 0 - 1 } 181 var nl: i64 = 0 182 var i: i64 = 5 183 while i < po { if nl < 47 { nb[nl] = t[i]; nl = nl + 1 } i = i + 1 } 184 nb[nl] = 0 as u8 185 if nl == 0 { return 0 - 1 } 186 let pc: i64 = sfind(t, tn, ")" as *u8, po) 187 if pc < 0 { return 0 - 1 } 188 // params: every ':' introduces one; any '*' inside -> pointer 189 var arity: i64 = 0 190 var j: i64 = po 191 while j < pc { 192 if t[j] == (58 as u8) { arity = arity + 1 } 193 if t[j] == (42 as u8) { return 0 - 2 } 194 j = j + 1 195 } 196 if arity < 1 { return 0 - 4 } 197 if arity > 3 { return 0 - 4 } 198 // return type: "-> i64" between ')' and the body '{' 199 let bo: i64 = sfind(t, tn, "{" as *u8, pc) 200 if bo < 0 { return 0 - 1 } 201 let ra: i64 = sfind(t, tn, "-> i64" as *u8, pc) 202 if ra < 0 { return 0 - 3 } 203 if ra > bo { return 0 - 3 } 204 return arity 205} 206// body-purity gate. returns 0 ok | reason>0. Every rejection class is COUNTED by the caller. 207// 1 size 2 impure-token (sys_/ptr/index/div/mod/string/import) 3 loop 4 call 5 upper-const 208func bf_eligible(t: *u8, tn: i64) -> i64 { 209 if tn < BF_MINB { return 1 } 210 if tn > BF_MAXB { return 1 } 211 if scontains(t, tn, "sys_" as *u8) == 1 { return 2 } 212 if scontains(t, tn, "*u8" as *u8) == 1 { return 2 } 213 if scontains(t, tn, "*i64" as *u8) == 1 { return 2 } 214 if scontains(t, tn, "[" as *u8) == 1 { return 2 } 215 if scontains(t, tn, "/" as *u8) == 1 { return 2 } 216 if scontains(t, tn, "%" as *u8) == 1 { return 2 } 217 let qt: *u8 = sys_mmap(4) 218 qt[0] = 34 as u8 219 qt[1] = 0 as u8 220 if scontains(t, tn, qt) == 1 { return 2 } 221 if scontains(t, tn, "import" as *u8) == 1 { return 2 } 222 if scontains(t, tn, "while" as *u8) == 1 { return 3 } 223 // call-check: inside the body, '(' whose previous char is [A-Za-z0-9_] = a call 224 let bo: i64 = sfind(t, tn, "{" as *u8, 0) 225 if bo < 0 { return 1 } 226 var i: i64 = bo 227 while i < tn { 228 if t[i] == (40 as u8) { 229 let p: i64 = t[i - 1] as i64 230 var isid: i64 = 0 231 if p >= 97 { if p <= 122 { isid = 1 } } 232 if p >= 65 { if p <= 90 { isid = 1 } } 233 if p >= 48 { if p <= 57 { isid = 1 } } 234 if p == 95 { isid = 1 } 235 if isid == 1 { return 4 } 236 } 237 i = i + 1 238 } 239 // module-const reference heuristic: two consecutive uppercase letters in the body 240 var k: i64 = bo 241 while k + 1 < tn { 242 let a: i64 = t[k] as i64 243 let b: i64 = t[k + 1] as i64 244 if a >= 65 { if a <= 90 { if b >= 65 { if b <= 90 { return 5 } } } } 245 k = k + 1 246 } 247 return 0 248} 249 250// ---- mutation ---- 251// op table: box[0]=find box[1]=repl box[2]=label ; ret 1 valid / 0 end 252func bf_opget(i: i64, box: *i64) -> i64 { 253 if i == 0 { box[0] = " + " as *u8 as i64; box[1] = " - " as *u8 as i64; box[2] = "addsub" as *u8 as i64; return 1 } 254 if i == 1 { box[0] = " - " as *u8 as i64; box[1] = " + " as *u8 as i64; box[2] = "subadd" as *u8 as i64; return 1 } 255 if i == 2 { box[0] = " < " as *u8 as i64; box[1] = " > " as *u8 as i64; box[2] = "ltgt" as *u8 as i64; return 1 } 256 if i == 3 { box[0] = " > " as *u8 as i64; box[1] = " < " as *u8 as i64; box[2] = "gtlt" as *u8 as i64; return 1 } 257 if i == 4 { box[0] = " * " as *u8 as i64; box[1] = " + " as *u8 as i64; box[2] = "muladd" as *u8 as i64; return 1 } 258 return 0 259} 260// apply op: first match AFTER the body '{'; out gets the mutant; ret outlen | 0 no-match 261func bf_mutate(t: *u8, tn: i64, find: *u8, repl: *u8, out: *u8) -> i64 { 262 let bo: i64 = sfind(t, tn, "{" as *u8, 0) 263 if bo < 0 { return 0 } 264 let at: i64 = sfind(t, tn, find, bo) 265 if at < 0 { return 0 } 266 let fl: i64 = slen(find) 267 var o: i64 = 0 268 o = bcatr(out, o, t, at) 269 o = bcat(out, o, repl) 270 o = bcatr(out, o, ((t as i64) + at + fl) as *u8, tn - at - fl) 271 out[o] = 0 as u8 272 return o 273} 274// emit fn text renamed: "func " + newname + rest-from-'(' 275func bf_rename(dst: *u8, o0: i64, t: *u8, tn: i64, newname: *u8) -> i64 { 276 let po: i64 = sfind(t, tn, "(" as *u8, 0) 277 var o: i64 = bcat(dst, o0, "func " as *u8) 278 o = bcat(dst, o, newname) 279 o = bcatr(dst, o, ((t as i64) + po) as *u8, tn - po) 280 return o 281} 282 283// ---- generated-source shared pieces ---- 284func bf_gen_head(g: *u8) -> i64 { 285 var o: i64 = 0 286 o = bcat(g, o, "// GENERATED by nx_bugforge -- do not hand-edit\n" as *u8) 287 o = bcat(g, o, "import " as *u8) 288 o = bqs(g, o, "nx_syscalls.nx" as *u8) 289 o = bcat(g, o, "\n" as *u8) 290 // cw 291 o = bcat(g, o, "func cw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }\n" as *u8) 292 // cn (the '-' literal composed via bqs) 293 o = bcat(g, o, "func cn(v: i64) -> i64 {\n var m: i64 = v\n if m < 0 { cw(" as *u8) 294 o = bqs(g, o, "-" as *u8) 295 o = bcat(g, o, " as *u8); m = 0 - m }\n let t: *u8 = sys_mmap(24)\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 let o: *u8 = sys_mmap(24)\n var i: i64 = 0\n while i < k { o[i] = t[k - 1 - i]; i = i + 1 }\n sys_write(1, o, k)\n return 0\n}\n" as *u8) 296 return o 297} 298// emit `cw("LIT");` then `cn(EXPR);` pairs are composed by callers. 299func bf_gen_cw(g: *u8, o0: i64, lit: *u8) -> i64 { 300 var o: i64 = bcat(g, o0, "cw(" as *u8) 301 o = bqs(g, o, lit) 302 o = bcat(g, o, " as *u8); " as *u8) 303 return o 304} 305// emit `cw("\n" as *u8); ` -- the backslash+n bytes are composed WITHOUT escapes in this source 306// (nx_cc escape support for double-backslash is unverified; byte-composition is escape-free). 307func bf_gen_nl(g: *u8, o0: i64) -> i64 { 308 var o: i64 = bcat(g, o0, "cw(" as *u8) 309 o = bq(g, o) 310 g[o] = 92 as u8 311 o = o + 1 312 g[o] = 110 as u8 313 o = o + 1 314 o = bq(g, o) 315 o = bcat(g, o, " as *u8); " as *u8) 316 return o 317} 318 319// ---- probe: orig+mut side by side, domain sweep, BFCASE/BFPASS/BFDIV rows ---- 320func bf_probe_src(g: *u8, t: *u8, tn: i64, mut: *u8, mn: i64, arity: i64) -> i64 { 321 var o: i64 = bf_gen_head(g) 322 o = bf_rename(g, o, t, tn, "bf_orig" as *u8) 323 o = bcat(g, o, "\n" as *u8) 324 o = bf_rename(g, o, mut, mn, "bf_mut" as *u8) 325 o = bcat(g, o, "\nfunc main() -> i64 {\n var dv: i64 = 0\n var ag: i64 = 0\n" as *u8) 326 var dom: i64 = BF_DOM 327 if arity == 3 { dom = BF_DOM3 } 328 // loop opens 329 o = bcat(g, o, " var a: i64 = 0 - " as *u8) 330 o = bcatn(g, o, dom) 331 o = bcat(g, o, "\n while a <= " as *u8) 332 o = bcatn(g, o, dom) 333 o = bcat(g, o, " {\n" as *u8) 334 if arity >= 2 { 335 o = bcat(g, o, " var b: i64 = 0 - " as *u8) 336 o = bcatn(g, o, dom) 337 o = bcat(g, o, "\n while b <= " as *u8) 338 o = bcatn(g, o, dom) 339 o = bcat(g, o, " {\n" as *u8) 340 } 341 if arity >= 3 { 342 o = bcat(g, o, " var c: i64 = 0 - " as *u8) 343 o = bcatn(g, o, dom) 344 o = bcat(g, o, "\n while c <= " as *u8) 345 o = bcatn(g, o, dom) 346 o = bcat(g, o, " {\n" as *u8) 347 } 348 // call args 349 var args: *u8 = "a" as *u8 350 if arity == 2 { args = "a, b" as *u8 } 351 if arity == 3 { args = "a, b, c" as *u8 } 352 o = bcat(g, o, " let x: i64 = bf_orig(" as *u8) 353 o = bcat(g, o, args) 354 o = bcat(g, o, ")\n let y: i64 = bf_mut(" as *u8) 355 o = bcat(g, o, args) 356 o = bcat(g, o, ")\n if x != y { dv = dv + 1; if dv <= " as *u8) 357 o = bcatn(g, o, BF_MAXCASE) 358 o = bcat(g, o, " { " as *u8) 359 o = bf_gen_cw(g, o, "BFCASE " as *u8) 360 o = bcat(g, o, "cn(a); " as *u8) 361 if arity >= 2 { o = bf_gen_cw(g, o, " " as *u8); o = bcat(g, o, "cn(b); " as *u8) } 362 if arity >= 3 { o = bf_gen_cw(g, o, " " as *u8); o = bcat(g, o, "cn(c); " as *u8) } 363 o = bf_gen_cw(g, o, " want=" as *u8) 364 o = bcat(g, o, "cn(x); " as *u8) 365 o = bf_gen_cw(g, o, " got=" as *u8) 366 o = bcat(g, o, "cn(y); " as *u8) 367 o = bf_gen_nl(g, o) 368 o = bcat(g, o, "} }\n if x == y { ag = ag + 1; if ag <= " as *u8) 369 o = bcatn(g, o, BF_MAXPASS) 370 o = bcat(g, o, " { " as *u8) 371 o = bf_gen_cw(g, o, "BFPASS " as *u8) 372 o = bcat(g, o, "cn(a); " as *u8) 373 if arity >= 2 { o = bf_gen_cw(g, o, " " as *u8); o = bcat(g, o, "cn(b); " as *u8) } 374 if arity >= 3 { o = bf_gen_cw(g, o, " " as *u8); o = bcat(g, o, "cn(c); " as *u8) } 375 o = bf_gen_cw(g, o, " val=" as *u8) 376 o = bcat(g, o, "cn(x); " as *u8) 377 o = bf_gen_nl(g, o) 378 o = bcat(g, o, "} }\n" as *u8) 379 // loop closes 380 if arity >= 3 { o = bcat(g, o, " c = c + 1\n }\n" as *u8) } 381 if arity >= 2 { o = bcat(g, o, " b = b + 1\n }\n" as *u8) } 382 o = bcat(g, o, " a = a + 1\n }\n " as *u8) 383 o = bf_gen_cw(g, o, "BFDIV n=" as *u8) 384 o = bcat(g, o, "cn(dv); " as *u8) 385 o = bf_gen_cw(g, o, " agree=" as *u8) 386 o = bcat(g, o, "cn(ag); " as *u8) 387 o = bf_gen_nl(g, o) 388 o = bcat(g, o, "\n return 0\n}\n" as *u8) 389 g[o] = 0 as u8 390 return o 391} 392 393// ---- candidate: mutant under its REAL name + FNRES/FNCASE grader over the banked cases ---- 394// cases: cargs[i*3..] cwant[i] (ncase) ; passes: pargs[j*3..] pval[j] (npass) 395func bf_cand_src(g: *u8, mut: *u8, mn: i64, fname: *u8, arity: i64, cargs: *i64, cwant: *i64, ncase: i64, pargs: *i64, pval: *i64, npass: i64, srcpath: *u8, oplab: *u8) -> i64 { 396 var o: i64 = 0 397 o = bcat(g, o, "// GENERATED nx_bugforge instance src=" as *u8) 398 o = bcat(g, o, srcpath) 399 o = bcat(g, o, " op=" as *u8) 400 o = bcat(g, o, oplab) 401 o = bcat(g, o, " (mutant of a REAL corpus function; the original is the oracle)\n" as *u8) 402 let h: i64 = bf_gen_head(g) 403 // bf_gen_head writes from 0 -- rebuild: compose head into scratch then append. Simpler: emit 404 // header comment AFTER head. Rewind: compose fresh. 405 o = bf_gen_head(g) 406 o = bcat(g, o, "// src=" as *u8) 407 o = bcat(g, o, srcpath) 408 o = bcat(g, o, " op=" as *u8) 409 o = bcat(g, o, oplab) 410 o = bcat(g, o, "\n" as *u8) 411 o = bcatr(g, o, mut, mn) 412 o = bcat(g, o, "\nfunc main() -> i64 {\n var pass: i64 = 0\n" as *u8) 413 let total: i64 = ncase + npass 414 var i: i64 = 0 415 while i < total { 416 var a0: i64 = 0 417 var a1: i64 = 0 418 var a2: i64 = 0 419 var wv: i64 = 0 420 if i < ncase { a0 = cargs[i * 3]; a1 = cargs[i * 3 + 1]; a2 = cargs[i * 3 + 2]; wv = cwant[i] } 421 if i >= ncase { let j: i64 = i - ncase; a0 = pargs[j * 3]; a1 = pargs[j * 3 + 1]; a2 = pargs[j * 3 + 2]; wv = pval[j] } 422 o = bcat(g, o, " var g" as *u8) 423 o = bcatn(g, o, i) 424 o = bcat(g, o, ": i64 = " as *u8) 425 o = bcat(g, o, fname) 426 o = bcat(g, o, "(" as *u8) 427 o = bcatn(g, o, a0) 428 if arity >= 2 { o = bcat(g, o, ", " as *u8); o = bcatn(g, o, a1) } 429 if arity >= 3 { o = bcat(g, o, ", " as *u8); o = bcatn(g, o, a2) } 430 o = bcat(g, o, ")\n if g" as *u8) 431 o = bcatn(g, o, i) 432 o = bcat(g, o, " == " as *u8) 433 o = bcatn(g, o, wv) 434 o = bcat(g, o, " { pass = pass + 1 } else { " as *u8) 435 // FNCASE <fn> in=<a0>,<a1>,<a2> want=<wv> got=<gi> 436 let lit: *u8 = sys_mmap(160) 437 var lo: i64 = 0 438 lo = bcat(lit, lo, "FNCASE " as *u8) 439 lo = bcat(lit, lo, fname) 440 lo = bcat(lit, lo, " in=" as *u8) 441 lo = bcatn(lit, lo, a0) 442 if arity >= 2 { lo = bcat(lit, lo, "," as *u8); lo = bcatn(lit, lo, a1) } 443 if arity >= 3 { lo = bcat(lit, lo, "," as *u8); lo = bcatn(lit, lo, a2) } 444 lo = bcat(lit, lo, " want=" as *u8) 445 lo = bcatn(lit, lo, wv) 446 lo = bcat(lit, lo, " got=" as *u8) 447 lit[lo] = 0 as u8 448 o = bf_gen_cw(g, o, lit) 449 o = bcat(g, o, "cn(g" as *u8) 450 o = bcatn(g, o, i) 451 o = bcat(g, o, "); " as *u8) 452 o = bf_gen_nl(g, o) 453 o = bcat(g, o, "}\n" as *u8) 454 i = i + 1 455 } 456 // FNRES <fn> <pass> <total> + CGR aggregate 457 let l2: *u8 = sys_mmap(96) 458 var l2o: i64 = 0 459 l2o = bcat(l2, l2o, "FNRES " as *u8) 460 l2o = bcat(l2, l2o, fname) 461 l2o = bcat(l2, l2o, " " as *u8) 462 l2[l2o] = 0 as u8 463 o = bcat(g, o, " " as *u8) 464 o = bf_gen_cw(g, o, l2) 465 o = bcat(g, o, "cn(pass); " as *u8) 466 let l3: *u8 = sys_mmap(32) 467 var l3o: i64 = 0 468 l3o = bcat(l3, l3o, " " as *u8) 469 l3o = bcatn(l3, l3o, total) 470 l3[l3o] = 92 as u8 471 l3o = l3o + 1 472 l3[l3o] = 110 as u8 473 l3o = l3o + 1 474 l3[l3o] = 0 as u8 475 o = bf_gen_cw(g, o, l3) 476 o = bcat(g, o, "\n " as *u8) 477 o = bf_gen_cw(g, o, "CGR=" as *u8) 478 o = bcat(g, o, "cn(pass); " as *u8) 479 o = bf_gen_nl(g, o) 480 o = bcat(g, o, "\n return 0\n}\n" as *u8) 481 g[o] = 0 as u8 482 return o 483} 484 485// parse BFCASE/BFPASS rows from a probe capture. arity ints then want=/val= (+got= on BFCASE). 486func bf_collect(outb: *u8, on: i64, tag: *u8, arity: i64, args: *i64, vals: *i64, maxn: i64) -> i64 { 487 var cnt: i64 = 0 488 var p: i64 = 0 489 let box: *i64 = sys_mmap(16) as *i64 490 var go: i64 = 1 491 while go == 1 { 492 if cnt >= maxn { go = 0 } 493 else { 494 let at: i64 = sfind(outb, on, tag, p) 495 if at < 0 { go = 0 } 496 else { 497 var q: i64 = at + slen(tag) 498 var k: i64 = 0 499 var ok: i64 = 1 500 while k < arity { 501 // skip spaces 502 var sg: i64 = 1 503 while sg == 1 { if q < on { if outb[q] == (32 as u8) { q = q + 1 } else { sg = 0 } } else { sg = 0 } } 504 var neg: i64 = 0 505 if q < on { if outb[q] == (45 as u8) { neg = 1; q = q + 1 } } 506 var v: i64 = 0 507 var any: i64 = 0 508 var dg: i64 = 1 509 while dg == 1 { 510 if q >= on { dg = 0 } 511 else { 512 let c: i64 = outb[q] as i64 513 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48); any = 1; q = q + 1 } else { dg = 0 } } else { dg = 0 } 514 } 515 } 516 if any == 0 { ok = 0; k = arity } 517 else { 518 if neg == 1 { v = 0 - v } 519 args[cnt * 3 + k] = v 520 k = k + 1 521 } 522 } 523 if ok == 1 { 524 var vk: i64 = 0 525 if bf_intafter(outb, on, "want=" as *u8, q, box) == 1 { vals[cnt] = box[0]; vk = 1 } 526 if vk == 0 { if bf_intafter(outb, on, "val=" as *u8, q, box) == 1 { vals[cnt] = box[0]; vk = 1 } } 527 if vk == 1 { if arity < 3 { args[cnt * 3 + 2] = 0 } if arity < 2 { args[cnt * 3 + 1] = 0 } cnt = cnt + 1 } 528 } 529 p = at + slen(tag) 530 } 531 } 532 } 533 return cnt 534} 535 536// ---- shared mine/selftest instance pipeline: probe one (fn,op); emit on divergence ---- 537// ret 1 emitted / 0 equivalent / -1 probe-unusable 538static g_emit_n: i64 539static g_man: *u8 540static g_man_o: i64 541static g_cor: *u8 542static g_cor_o: i64 543static g_gen: *u8 544static g_out: *u8 545static g_mut: *u8 546 547func bf_try(t: *u8, tn: i64, fname: *u8, arity: i64, opfind: *u8, oprepl: *u8, oplab: *u8, srcpath: *u8, verbose: i64) -> i64 { 548 let mn: i64 = bf_mutate(t, tn, opfind, oprepl, g_mut) 549 if mn == 0 { return 0 - 1 } 550 let pn: i64 = bf_probe_src(g_gen, t, tn, g_mut, mn, arity) 551 if bf_write("runtime/bf_probe.nx" as *u8, g_gen, pn) < 0 { return 0 - 1 } 552 let on: i64 = bf_run("bf_probe" as *u8, g_out, BF_OCAP) 553 let box: *i64 = sys_mmap(16) as *i64 554 if bf_intafter(g_out, on, "BFDIV n=" as *u8, 0, box) == 0 { return 0 - 1 } 555 let dv: i64 = box[0] 556 if dv == 0 { return 0 } 557 // collect cases 558 let cargs: *i64 = sys_mmap(BF_MAXCASE * 3 * 8) as *i64 559 let cwant: *i64 = sys_mmap(BF_MAXCASE * 8) as *i64 560 let pargs: *i64 = sys_mmap(BF_MAXPASS * 3 * 8) as *i64 561 let pval: *i64 = sys_mmap(BF_MAXPASS * 8) as *i64 562 let nc: i64 = bf_collect(g_out, on, "BFCASE " as *u8, arity, cargs, cwant, BF_MAXCASE) 563 let np: i64 = bf_collect(g_out, on, "BFPASS " as *u8, arity, pargs, pval, BF_MAXPASS) 564 if nc == 0 { return 0 - 1 } 565 // instance name: bf_i<N>_<fn>_<op> 566 g_emit_n = g_emit_n + 1 567 let iname: *u8 = sys_mmap(128) 568 var io: i64 = 0 569 io = bcat(iname, io, "bf_i" as *u8) 570 io = bcatn(iname, io, g_emit_n) 571 io = bcat(iname, io, "_" as *u8) 572 io = bcat(iname, io, fname) 573 io = bcat(iname, io, "_" as *u8) 574 io = bcat(iname, io, oplab) 575 iname[io] = 0 as u8 576 let ipath: *u8 = sys_mmap(192) 577 var ip: i64 = 0 578 ip = bcat(ipath, ip, "runtime/" as *u8) 579 ip = bcat(ipath, ip, iname) 580 ip = bcat(ipath, ip, ".nx" as *u8) 581 ipath[ip] = 0 as u8 582 let cn2: i64 = bf_cand_src(g_gen, g_mut, mn, fname, arity, cargs, cwant, nc, pargs, pval, np, srcpath, oplab) 583 if bf_write(ipath, g_gen, cn2) < 0 { g_emit_n = g_emit_n - 1; return 0 - 1 } 584 // verify the emitted instance grades RED as-is (compiles + FNRES pass<total) 585 let von: i64 = bf_run(iname, g_out, BF_OCAP) 586 let fnr: *u8 = sys_mmap(96) 587 var fo: i64 = 0 588 fo = bcat(fnr, fo, "FNRES " as *u8) 589 fo = bcat(fnr, fo, fname) 590 fo = bcat(fnr, fo, " " as *u8) 591 fnr[fo] = 0 as u8 592 let fat: i64 = sfind(g_out, von, fnr, 0) 593 var red: i64 = 0 594 if fat >= 0 { 595 let b2: *i64 = sys_mmap(16) as *i64 596 if bf_intafter(g_out, von, fnr, 0, b2) == 1 { 597 let passed: i64 = b2[0] 598 let b3: *i64 = sys_mmap(16) as *i64 599 if bf_intafter(g_out, von, " " as *u8, b2[1], b3) == 1 { if passed < b3[0] { red = 1 } } 600 } 601 } 602 if red == 0 { 603 sys_unlinkat(ipath) 604 g_emit_n = g_emit_n - 1 605 return 0 - 1 606 } 607 // manifest + corpus rows 608 g_man_o = bcat(g_man, g_man_o, iname) 609 g_man_o = bcat(g_man, g_man_o, "|" as *u8) 610 g_man_o = bcat(g_man, g_man_o, ipath) 611 g_man_o = bcat(g_man, g_man_o, "\n" as *u8) 612 // corpus v2: multi-line fns included -- interior newlines stored as byte 0x01 (fsl_shots 613 // unescapes on emit). Single-line rows are byte-identical to v1. 614 var cz: i64 = 0 615 while cz < mn { var cm: u8 = g_mut[cz]; if cm == (10 as u8) { cm = 1 as u8 } g_cor[g_cor_o] = cm; g_cor_o = g_cor_o + 1; cz = cz + 1 } 616 g_cor[g_cor_o] = 9 as u8 617 g_cor_o = g_cor_o + 1 618 var cz2: i64 = 0 619 while cz2 < tn { var ct: u8 = t[cz2]; if ct == (10 as u8) { ct = 1 as u8 } g_cor[g_cor_o] = ct; g_cor_o = g_cor_o + 1; cz2 = cz2 + 1 } 620 g_cor_o = bcat(g_cor, g_cor_o, "\n" as *u8) 621 if verbose == 1 { 622 w("EMIT " as *u8) 623 w(iname) 624 w(" div=" as *u8) 625 wn(dv) 626 w(" f2p=" as *u8) 627 wn(nc) 628 w(" p2p=" as *u8) 629 wn(np) 630 w("\n" as *u8) 631 } 632 return 1 633} 634 635func bf_name_ok(nm: *u8) -> i64 { 636 let nl: i64 = slen(nm) 637 if nl < 4 { return 0 } 638 if nm[nl - 3] != (46 as u8) { return 0 } 639 if nm[nl - 2] != (110 as u8) { return 0 } 640 if nm[nl - 1] != (120 as u8) { return 0 } 641 if scontains(nm, nl, ".bak" as *u8) == 1 { return 0 } 642 if scontains(nm, nl, "premigrate" as *u8) == 1 { return 0 } 643 if scontains(nm, nl, "candidate" as *u8) == 1 { return 0 } 644 if scontains(nm, nl, "_mut_" as *u8) == 1 { return 0 } 645 if scontains(nm, nl, "_gate" as *u8) == 1 { return 0 } 646 if scontains(nm, nl, "_test" as *u8) == 1 { return 0 } 647 if nm[0] == (98 as u8) { if nm[1] == (102 as u8) { if nm[2] == (95 as u8) { return 0 } } } 648 return 1 649} 650 651func bf_mine(maxn: i64, dir: *u8, app: i64) -> i64 { 652 let fbuf: *u8 = sys_mmap(BF_FCAP) 653 let dbuf: *u8 = sys_mmap(BF_DCAP) 654 let tbuf: *u8 = sys_mmap(BF_TCAP) 655 let path: *u8 = sys_mmap(BF_PATHCAP) 656 let nb: *u8 = sys_mmap(64) 657 g_gen = sys_mmap(BF_SRCCAP) 658 g_out = sys_mmap(BF_OCAP) 659 g_mut = sys_mmap(BF_TCAP) 660 g_man = sys_mmap(BF_LISTCAP) 661 g_cor = sys_mmap(BF_LISTCAP) 662 g_man_o = 0 663 g_cor_o = 0 664 g_emit_n = 0 665 // mineadd: PRE-LOAD existing artifacts + resume the counter (additive append -- a fresh `mine` 666 // REPLACES, `mineadd` composes multi-dir mines without clobbering earlier instances). 667 if app == 1 { 668 let ml: i64 = bf_read("bf_manifest.txt" as *u8, g_man, BF_LISTCAP) 669 if ml > 0 { 670 g_man_o = ml 671 var mi: i64 = 0 672 while mi < ml { if g_man[mi] == (10 as u8) { g_emit_n = g_emit_n + 1 } mi = mi + 1 } 673 } 674 let cl: i64 = bf_read("bf_fixcorpus.txt" as *u8, g_cor, BF_LISTCAP) 675 if cl > 0 { g_cor_o = cl } 676 } 677 let ecap: i64 = g_emit_n + maxn 678 var cfiles: i64 = 0 679 var cskipbig: i64 = 0 680 var cfns: i64 = 0 681 var celig: i64 = 0 682 var r_size: i64 = 0 683 var r_impure: i64 = 0 684 var r_loop: i64 = 0 685 var r_call: i64 = 0 686 var r_const: i64 = 0 687 var r_sig: i64 = 0 688 var cprobes: i64 = 0 689 var cdiv: i64 = 0 690 var ceqv: i64 = 0 691 var cbad: i64 = 0 692 var capped: i64 = 0 693 let opbox: *i64 = sys_mmap(32) as *i64 694 695 let dfd: i64 = sys_openat_rd(dir) 696 if dfd < 0 { w("cannot open dir\n" as *u8); return 1 } 697 var dgo: i64 = 1 698 while dgo == 1 { 699 if g_emit_n >= ecap { capped = 1; dgo = 0 } 700 else { 701 let nr: i64 = sys_getdents64(dfd, dbuf, BF_DCAP) 702 if nr <= 0 { dgo = 0 } 703 else { 704 var off: i64 = 0 705 while off < nr { 706 let rl: i64 = (dbuf[off + 16] as i64) + ((dbuf[off + 17] as i64) * 256) 707 let nmp: *u8 = ((dbuf as i64) + off + 19) as *u8 708 var use: i64 = 0 709 if g_emit_n < ecap { use = bf_name_ok(nmp) } 710 if use == 1 { 711 var po: i64 = 0 712 po = bcat(path, po, dir) 713 po = bcat(path, po, "/" as *u8) 714 po = bcat(path, po, nmp) 715 path[po] = 0 as u8 716 let fl: i64 = bf_read(path, fbuf, BF_FCAP) 717 if fl == (0 - 2) { cskipbig = cskipbig + 1 } 718 if fl > 0 { 719 cfiles = cfiles + 1 720 var p: i64 = 0 721 var fgo: i64 = 1 722 while fgo == 1 { 723 if g_emit_n >= ecap { fgo = 0 } 724 else { 725 let q: i64 = sfind(fbuf, fl, "func " as *u8, p) 726 if q < 0 { fgo = 0 } 727 else { 728 var atline: i64 = 0 729 if q == 0 { atline = 1 } 730 if q > 0 { if fbuf[q - 1] == (10 as u8) { atline = 1 } } 731 var e: i64 = q + 5 732 if atline == 1 { 733 let fe: i64 = bf_fnend(fbuf, fl, q) 734 if fe > q { 735 e = fe 736 cfns = cfns + 1 737 let tn: i64 = fe - q 738 if tn < BF_TCAP - 1 { 739 var z: i64 = 0 740 while z < tn { tbuf[z] = fbuf[q + z]; z = z + 1 } 741 tbuf[tn] = 0 as u8 742 let ar: i64 = bf_fnsig(tbuf, tn, nb) 743 if ar < 1 { r_sig = r_sig + 1 } 744 if ar >= 1 { 745 let el: i64 = bf_eligible(tbuf, tn) 746 if el == 1 { r_size = r_size + 1 } 747 if el == 2 { r_impure = r_impure + 1 } 748 if el == 3 { r_loop = r_loop + 1 } 749 if el == 4 { r_call = r_call + 1 } 750 if el == 5 { r_const = r_const + 1 } 751 if el == 0 { 752 celig = celig + 1 753 var perfn: i64 = 0 754 var oi: i64 = 0 755 while oi < BF_NOPS { 756 if perfn >= BF_PERFN { oi = BF_NOPS } 757 else { 758 if g_emit_n >= ecap { oi = BF_NOPS } 759 else { 760 if bf_opget(oi, opbox) == 1 { 761 let mrc: i64 = bf_mutate(tbuf, tn, opbox[0] as *u8, opbox[1] as *u8, g_mut) 762 if mrc > 0 { 763 cprobes = cprobes + 1 764 let rc: i64 = bf_try(tbuf, tn, nb, ar, opbox[0] as *u8, opbox[1] as *u8, opbox[2] as *u8, path, 1) 765 if rc == 1 { cdiv = cdiv + 1; perfn = perfn + 1 } 766 if rc == 0 { ceqv = ceqv + 1 } 767 if rc == (0 - 1) { cbad = cbad + 1 } 768 } 769 } 770 oi = oi + 1 771 } 772 } 773 } 774 } 775 } 776 } 777 } 778 } 779 p = e 780 } 781 } 782 } 783 } 784 } 785 off = off + rl 786 } 787 } 788 } 789 } 790 sys_close(dfd) 791 bf_write("bf_manifest.txt" as *u8, g_man, g_man_o) 792 bf_write("bf_fixcorpus.txt" as *u8, g_cor, g_cor_o) 793 w("NX-BUGFORGE mine dir=" as *u8) 794 w(dir) 795 w(" files=" as *u8) 796 wn(cfiles) 797 w(" skip_big=" as *u8) 798 wn(cskipbig) 799 w(" fns=" as *u8) 800 wn(cfns) 801 w(" eligible=" as *u8) 802 wn(celig) 803 w(" rej_sig=" as *u8) 804 wn(r_sig) 805 w(" rej_size=" as *u8) 806 wn(r_size) 807 w(" rej_impure=" as *u8) 808 wn(r_impure) 809 w(" rej_loop=" as *u8) 810 wn(r_loop) 811 w(" rej_call=" as *u8) 812 wn(r_call) 813 w(" rej_const=" as *u8) 814 wn(r_const) 815 w(" probes=" as *u8) 816 wn(cprobes) 817 w(" emitted=" as *u8) 818 wn(cdiv) 819 w(" equivalent=" as *u8) 820 wn(ceqv) 821 w(" unusable=" as *u8) 822 wn(cbad) 823 w(" cap_hit=" as *u8) 824 wn(capped) 825 w("\nmanifest=bf_manifest.txt corpus=bf_fixcorpus.txt (REPLACED per run -- derived artifacts)\n" as *u8) 826 return 0 827} 828 829func bf_selftest() -> i64 { 830 g_gen = sys_mmap(BF_SRCCAP) 831 g_out = sys_mmap(BF_OCAP) 832 g_mut = sys_mmap(BF_TCAP) 833 g_man = sys_mmap(BF_LISTCAP) 834 g_cor = sys_mmap(BF_LISTCAP) 835 g_man_o = 0 836 g_cor_o = 0 837 g_emit_n = 0 838 var passn: i64 = 0 839 let nb: *u8 = sys_mmap(64) 840 // T1 eligible pure fn 841 let t1: *u8 = "func bfs_mix(a: i64, b: i64) -> i64 { if a < b { return a + b } return a - b }" as *u8 842 let t1n: i64 = slen(t1) 843 let ar1: i64 = bf_fnsig(t1, t1n, nb) 844 var ok1: i64 = 0 845 if ar1 == 2 { if bf_eligible(t1, t1n) == 0 { ok1 = 1 } } 846 if ok1 == 1 { passn = passn + 1; w("T1 eligibility-accept PASS\n" as *u8) } else { w("T1 FAIL\n" as *u8) } 847 // T2 ineligible (call + sys_) 848 let t2: *u8 = "func bfs_io(x: i64) -> i64 { let r: i64 = sys_now_ms(); return x + r }" as *u8 849 let t2n: i64 = slen(t2) 850 var ok2: i64 = 0 851 if bf_fnsig(t2, t2n, nb) == 1 { if bf_eligible(t2, t2n) != 0 { ok2 = 1 } } 852 if ok2 == 1 { passn = passn + 1; w("T2 eligibility-reject PASS\n" as *u8) } else { w("T2 FAIL\n" as *u8) } 853 // T3 mutation changes bytes 854 let opbox: *i64 = sys_mmap(32) as *i64 855 bf_opget(0, opbox) 856 let mn3: i64 = bf_mutate(t1, t1n, opbox[0] as *u8, opbox[1] as *u8, g_mut) 857 var ok3: i64 = 0 858 if mn3 > 0 { if sfind(g_mut, mn3, " - " as *u8, 0) >= 0 { ok3 = 1 } } 859 if ok3 == 1 { passn = passn + 1; w("T3 mutate PASS\n" as *u8) } else { w("T3 FAIL\n" as *u8) } 860 // T4 no-match op skips (op * on a fn without *) 861 bf_opget(4, opbox) 862 let mn4: i64 = bf_mutate(t1, t1n, opbox[0] as *u8, opbox[1] as *u8, g_mut) 863 var ok4: i64 = 0 864 if mn4 == 0 { ok4 = 1 } 865 if ok4 == 1 { passn = passn + 1; w("T4 no-match-skip PASS\n" as *u8) } else { w("T4 FAIL\n" as *u8) } 866 // T5 full pipeline: probe finds divergence AND the emitted instance grades RED (real compile+run x2) 867 bf_fnsig(t1, t1n, nb) 868 bf_opget(0, opbox) 869 let rc5: i64 = bf_try(t1, t1n, nb, 2, opbox[0] as *u8, opbox[1] as *u8, opbox[2] as *u8, "selftest" as *u8, 0) 870 var ok5: i64 = 0 871 if rc5 == 1 { ok5 = 1 } 872 if ok5 == 1 { passn = passn + 1; w("T5 probe+emit+RED-verify PASS\n" as *u8) } else { w("T5 FAIL rc=" as *u8); wn(rc5); w("\n" as *u8) } 873 // T6 manifest row landed for the T5 instance 874 var ok6: i64 = 0 875 if g_man_o > 0 { if sfind(g_man, g_man_o, "bf_i1_bfs_mix_addsub|" as *u8, 0) >= 0 { ok6 = 1 } } 876 if ok6 == 1 { passn = passn + 1; w("T6 manifest-row PASS\n" as *u8) } else { w("T6 FAIL\n" as *u8) } 877 // cleanup scratch (own generated files only; never a lock) 878 sys_unlinkat("runtime/bf_probe.nx" as *u8) 879 sys_unlinkat("runtime/bf_i1_bfs_mix_addsub.nx" as *u8) 880 w("NX-BUGFORGE selftest " as *u8) 881 wn(passn) 882 w("/6 " as *u8) 883 if passn == 6 { w("VERDICT=GREEN\n" as *u8); return 0 } 884 w("VERDICT=RED\n" as *u8) 885 return 1 886} 887 888func main(argc: i64, argv: *i64) -> i64 { 889 var verb: *u8 = "selftest" as *u8 890 if argc > 1 { verb = argv[1] as *u8 } 891 if verb[0] == (109 as u8) { 892 var maxn: i64 = 16 893 if argc > 2 { 894 var v: i64 = 0 895 var i: i64 = 0 896 let a: *u8 = argv[2] as *u8 897 while a[i] != (0 as u8) { if a[i] >= (48 as u8) { if a[i] <= (57 as u8) { v = v * 10 + ((a[i] as i64) - 48) } } i = i + 1 } 898 if v > 0 { maxn = v } 899 } 900 var dir: *u8 = "runtime" as *u8 901 if argc > 3 { dir = argv[3] as *u8 } 902 var app: i64 = 0 903 if verb[4] == (97 as u8) { app = 1 } 904 return bf_mine(maxn, dir, app) 905 } 906 return bf_selftest() 907}