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}