code wiki / (root) / nx_retire_onto_lib.nx

nx_retire_onto_lib.nx source

↩ module page · 787 lines · 40066 B

1// nx_retire_onto_lib.nx -- RETIRE A PRIVATE FUNCTION ONTO ITS SHARED OWNER, function side (global tooling, 2// 2026-08-24, born on procgen PG2). 3// 4// WHY THIS EXISTS: the library plane's first census (nx_libindex find isqrt) returned 106 of 5,517 libraries 5// carrying a private isqrt beside nx_vecmath's gate-proven vm_isqrt, and nx_nxa_fk carrying quaternion 6// primitives beside vm_q_*. nx_oo_extract moves BYTE-IDENTICAL bodies into one lib; these bodies are not 7// identical -- each is its own hand-rolled Newton loop -- so the move is "keep the private NAME, replace the 8// BODY with one call to the owner". That was done by hand for eight files earlier the same day. A hand edit 9// repeated 106 times is the class of work an organ exists for, and a hand edit is also the class of work 10// that silently half-lands (the estate's str.replace law). 11// 12// WHAT IT DOES: rewrites func <private>(<params>) -> <ret> { ... } 13// to func <private>(<params>) -> <ret> { return <owner>(<param names>) } 14// and inserts `import "<owner_lib basename>"` after the LAST import line when it is absent (before the first 15// top-level func/const when the file has no imports). Brace matching SKIPS string literals and line comments, 16// so a `}` inside a string or a comment cannot end the body early -- the gate plants exactly that. 17// 18// WHAT IT REFUSES, BY NAME: the function is absent or malformed; the owner lib is unreadable or lacks the 19// owner function; arity, any parameter TYPE, or the return type differ; the file IS the owner lib. A refusal 20// writes nothing. Idempotent: a body that already is the one-line delegation reports ALREADY and writes 21// nothing, so a sweep can be re-run after a partial apply and the partition still sums. 22// 23// WHAT IT DOES NOT DO: prove behaviour. The proof lane is the consumer's rebuild plus the consumer's own gates 24// on the roster. An exact floor replacing a capped Newton loop is a NAMED delta, never a silent one, and the 25// name of it is printed on the APPLIED line. 26// 27// NO SILENT CAPS: files are read whole through sys_read_file (sized from the file); the only bounded buffers 28// are a pattern scratch (RO_PAT_CAP, sized for "func <name>(" and `import "<basename>"`) and the parameter 29// table (RO_MAX_PARAMS -- a function with more parameters than that REFUSES by name rather than truncating). 30// license_tier: ORIGINAL 31 32import "nx_syscalls.nx" 33import "nx_store_seed_lib.nx" 34import "nx_gatekit_lib.nx" 35 36// ---- PROVE: the differential probe (added the same day, before the first real apply) ------------------------ 37// A private isqrt may be a capped Newton loop, a rounded root, or a root over a pre-shifted scale. Replacing its 38// body on the strength of a matching SIGNATURE would change semantics silently -- the exact "I don't know what 39// this is" defect. So before an APPLY the organ GENERATES a probe program that imports the candidate and the 40// owner, compares <private>(v) against <owner>(v) over a declared input ladder, builds it with the estate's own 41// builder and runs it. Only exit 0 permits the rewrite. The ladder is exhaustive over 0..RO_PROBE_DENSE and a 42// structured sparse set above it (powers of two +-1 and squares on a 3/2 ladder up to the i64 root bound) -- 43// declared here so nobody reads it as a sample of the whole domain. Unary i64 -> i64 only; anything else is 44// REFUSED-prove-unsupported by name. 45const RO_PROBE_DENSE: i64 = 1048576 46// RO_PROBE_MS is the slow roster's bound (nx_gate_roster_run GRR_MS_DEFAULT): a probe slower than the slow beat 47// is a hang, not a slow subject. RO_BUILD_MS is the same bound times the builder's cold-cache factor of 5. 48const RO_PROBE_MS: i64 = 60000 49const RO_BUILD_MS: i64 = 300000 50const RO_PROBE_OUTCAP: i64 = 65536 51const RO_PROBE_SRC_CAP: i64 = 4096 52// One corpus-root path plus a fixture or artifact name: PATH_MAX is 4096 on this host and no path here can exceed it. 53const RO_PROBE_PATH_CAP: i64 = 4096 54const RO_PROVE_PASS: i64 = 1 55const RO_PROVE_DIFFER: i64 = 0 56const RO_PROVE_UNBUILDABLE: i64 = 0 - 1 57const RO_PROVE_UNSUPPORTED: i64 = 0 - 2 58const RO_PROVE_NOROOT: i64 = 0 - 3 59// The builder REFUSED under admission (an I/O storm or CPU saturation on the box): that is a property of the 60// BOX, never of the candidate, and filing it as "unbuildable" would turn a busy hour into 95 false refusals. 61const RO_PROVE_ADMISSION: i64 = 0 - 4 62 63const RO_SYS_OPENAT: i64 = 257 64// getpid in the RV64 numbering __syscall TRANSLATES (172 -> x86-64 39). MEASURED 2026-08-24: pinning x86's 39 65// here reached x86 umount2, because 39 is a KNOWN RV64 key (umount2) and the translator maps known keys while 66// passing unknown numbers through raw -- which is also why 257/217 elsewhere in this tree only work by 67// passthrough luck. The pid makes every probe path unique per run: the gate's trial and a live sweep would 68// otherwise write and build the SAME probe file and hand each other verdicts about the other's candidate. 69const RO_SYS_GETPID: i64 = 172 70const RO_AT_FDCWD: i64 = 0 - 100 71const RO_O_WRONLY_CREAT_TRUNC: i64 = 0x241 72const RO_MODE_644: i64 = 420 73const RO_NL: i64 = 10 74const RO_CR: i64 = 13 75const RO_TAB: i64 = 9 76const RO_SP: i64 = 32 77const RO_LPAREN: i64 = 40 78const RO_RPAREN: i64 = 41 79const RO_LBRACE: i64 = 123 80const RO_RBRACE: i64 = 125 81const RO_COMMA: i64 = 44 82const RO_COLON: i64 = 58 83const RO_QUOTE: i64 = 34 84const RO_BSLASH: i64 = 92 85const RO_SLASH: i64 = 47 86const RO_MAX_PARAMS: i64 = 16 87const RO_P_STRIDE: i64 = 4 88// POSIX NAME_MAX is 255; a function name or a lib basename longer than that is an anomaly and refuses. 89const RO_PAT_CAP: i64 = 512 90const RO_PATH_CAP: i64 = 1024 91// Output slack over the input size: the new body is " return <owner>(<names>) " which is bounded by the 92// owner name plus the parameter names already present in the input, plus one import line. 93const RO_OUT_SLACK: i64 = 2 * RO_PAT_CAP 94 95// verdict codes -- every refusal class that a sweep must tally SEPARATELY gets its own code, because two 96// refusals with opposite remedies must never share a counter (a signature mismatch is "leave it", a build 97// failure is "this lib does not compile natively", a semantic difference is "this was never an isqrt"). 98const RO_RETIRABLE: i64 = 0 99const RO_ALREADY: i64 = 1 100const RO_REFUSED: i64 = 2 101const RO_APPLIED: i64 = 3 102const RO_PROVEN: i64 = 4 103const RO_REFUSED_DIFFER: i64 = 5 104const RO_REFUSED_UNBUILDABLE: i64 = 6 105const RO_REFUSED_UNSUPPORTED: i64 = 7 106const RO_DEFERRED_ADMISSION: i64 = 8 107const RO_CODES: i64 = 9 108// modes for ro_one / ro_sweep 109const RO_MODE_DRY: i64 = 0 110const RO_MODE_PROVE: i64 = 1 111const RO_MODE_APPLY: i64 = 2 112 113// locate slots 114const RO_L_FSTART: i64 = 0 115const RO_L_PSTART: i64 = 1 116const RO_L_PEND: i64 = 2 117const RO_L_BOPEN: i64 = 3 118const RO_L_BCLOSE: i64 = 4 119const RO_L_RSTART: i64 = 5 120const RO_L_REND: i64 = 6 121const RO_L_N: i64 = 8 122 123// sweep tally slots: RO_CODES codes then candidates 124const RO_T_CAND: i64 = 9 125const RO_T_N: i64 = 11 126 127func ro_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 128func ro_w(fd: i64, s: *u8) -> i64 { let n: i64 = ro_slen(s); if n > 0 { sys_write(fd, s, n) } return 0 } 129func ro_out(s: *u8) -> i64 { return ro_w(1, s) } 130func ro_num(v0: i64) -> i64 { 131 let b: *u8 = sys_mmap(32) 132 var v: i64 = v0 133 var neg: i64 = 0 134 if v < 0 { neg = 1; v = 0 - v } 135 var i: i64 = 31 136 b[i] = 0 as u8 137 if v == 0 { i = i - 1; b[i] = 48 as u8 } 138 while v > 0 { i = i - 1; b[i] = ((v % 10) + 48) as u8; v = v / 10 } 139 if neg == 1 { i = i - 1; b[i] = 45 as u8 } 140 var n: i64 = 0 141 while b[i+n] != (0 as u8) { n = n + 1 } 142 sys_write(1, b + i, n) 143 sys_munmap(b, 32) 144 return 0 145} 146func ro_is_ws(c: i64) -> i64 { if c == RO_SP { return 1 } if c == RO_TAB { return 1 } if c == RO_NL { return 1 } if c == RO_CR { return 1 } return 0 } 147func ro_streq(a: *u8, b: *u8) -> i64 { 148 var i: i64 = 0 149 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } 150 if b[i] != (0 as u8) { return 0 } 151 return 1 152} 153 154// find pat (C string) in buf[from..n); -1 when absent 155func ro_find(buf: *u8, n: i64, from: i64, pat: *u8) -> i64 { 156 let pl: i64 = ro_slen(pat) 157 if pl == 0 { return 0 - 1 } 158 var i: i64 = from 159 while i + pl <= n { 160 var k: i64 = 0 161 var same: i64 = 1 162 while k < pl { if buf[i + k] != pat[k] { same = 0; k = pl } k = k + 1 } 163 if same == 1 { return i } 164 i = i + 1 165 } 166 return 0 - 1 167} 168// find pat at the beginning of a line 169func ro_find_bol(buf: *u8, n: i64, pat: *u8) -> i64 { 170 var from: i64 = 0 171 var go: i64 = 1 172 while go == 1 { 173 let p: i64 = ro_find(buf, n, from, pat) 174 if p < 0 { go = 0 } 175 if go == 1 { 176 if p == 0 { return p } 177 if buf[p - 1] == (RO_NL as u8) { return p } 178 from = p + 1 179 } 180 } 181 return 0 - 1 182} 183func ro_count(buf: *u8, n: i64, pat: *u8) -> i64 { 184 var c: i64 = 0 185 var from: i64 = 0 186 var go: i64 = 1 187 while go == 1 { 188 let p: i64 = ro_find(buf, n, from, pat) 189 if p < 0 { go = 0 } 190 if go == 1 { c = c + 1; from = p + 1 } 191 } 192 return c 193} 194func ro_span_eq(a: *u8, ao: i64, al: i64, b: *u8, bo: i64, bl: i64) -> i64 { 195 if al != bl { return 0 } 196 var k: i64 = 0 197 while k < al { if a[ao + k] != b[bo + k] { return 0 } k = k + 1 } 198 return 1 199} 200func ro_ends_with(buf: *u8, s: i64, e: i64, suffix: *u8) -> i64 { 201 let sl: i64 = ro_slen(suffix) 202 if e - s < sl { return 0 } 203 return ro_span_eq(buf, e - sl, sl, suffix, 0, sl) 204} 205func ro_trim_start(buf: *u8, s: i64, e: i64) -> i64 { 206 var i: i64 = s 207 while i < e { if ro_is_ws(buf[i] as i64) == 1 { i = i + 1 } else { return i } } 208 return i 209} 210func ro_trim_end(buf: *u8, s: i64, e: i64) -> i64 { 211 var i: i64 = e 212 while i > s { if ro_is_ws(buf[i - 1] as i64) == 1 { i = i - 1 } else { return i } } 213 return i 214} 215func ro_basename(p: *u8) -> *u8 { 216 var i: i64 = 0 217 var last: i64 = 0 218 while p[i] != (0 as u8) { if p[i] == (RO_SLASH as u8) { last = i + 1 } i = i + 1 } 219 return p + last 220} 221 222// "func <name>(" into pat; returns its length; -1 when the name would overflow the pattern scratch 223func ro_mk_pat(pat: *u8, name: *u8) -> i64 { 224 if ro_slen(name) + 8 >= RO_PAT_CAP { return 0 - 1 } 225 var k: i64 = 0 226 let pre: *u8 = "func " as *u8 227 var i: i64 = 0 228 while pre[i] != (0 as u8) { pat[k] = pre[i]; k = k + 1; i = i + 1 } 229 i = 0 230 while name[i] != (0 as u8) { pat[k] = name[i]; k = k + 1; i = i + 1 } 231 pat[k] = RO_LPAREN as u8; k = k + 1 232 pat[k] = 0 as u8 233 return k 234} 235// `import "<lib>"` into pat; -1 on overflow 236func ro_mk_import(pat: *u8, lib: *u8) -> i64 { 237 if ro_slen(lib) + 12 >= RO_PAT_CAP { return 0 - 1 } 238 var k: i64 = 0 239 let pre: *u8 = "import \"" as *u8 240 var i: i64 = 0 241 while pre[i] != (0 as u8) { pat[k] = pre[i]; k = k + 1; i = i + 1 } 242 i = 0 243 while lib[i] != (0 as u8) { pat[k] = lib[i]; k = k + 1; i = i + 1 } 244 pat[k] = RO_QUOTE as u8; k = k + 1 245 pat[k] = 0 as u8 246 return k 247} 248 249// index just past the closing quote of the string literal opening at buf[i0] 250func ro_skip_str(buf: *u8, n: i64, i0: i64) -> i64 { 251 var i: i64 = i0 + 1 252 var go: i64 = 1 253 while go == 1 { 254 if i >= n { go = 0 } 255 if go == 1 { 256 let c: i64 = buf[i] as i64 257 if c == RO_BSLASH { i = i + 2 } 258 else { if c == RO_QUOTE { go = 0; i = i + 1 } else { i = i + 1 } } 259 } 260 } 261 return i 262} 263// index of the newline ending the line comment opening at buf[i0], or n 264func ro_skip_comment(buf: *u8, n: i64, i0: i64) -> i64 { 265 var i: i64 = i0 266 while i < n { if buf[i] == (RO_NL as u8) { return i } i = i + 1 } 267 return n 268} 269 270// locate `func <name>(` at BOL and its parameter span, return type span and body braces. 271// returns 1 found, 0 absent, -1 malformed, -2 name too long 272func ro_locate(buf: *u8, n: i64, name: *u8, loc: *i64) -> i64 { 273 let pat: *u8 = sys_mmap(RO_PAT_CAP) 274 let pl: i64 = ro_mk_pat(pat, name) 275 if pl < 0 { sys_munmap(pat, RO_PAT_CAP); return 0 - 2 } 276 let f: i64 = ro_find_bol(buf, n, pat) 277 sys_munmap(pat, RO_PAT_CAP) 278 if f < 0 { return 0 } 279 loc[RO_L_FSTART] = f 280 let ps: i64 = f + pl 281 loc[RO_L_PSTART] = ps 282 var i: i64 = ps 283 var depth: i64 = 1 284 var pe: i64 = 0 - 1 285 while i < n { 286 let c: i64 = buf[i] as i64 287 if c == RO_LPAREN { depth = depth + 1 } 288 if c == RO_RPAREN { depth = depth - 1; if depth == 0 { pe = i; i = n } } 289 i = i + 1 290 } 291 if pe < 0 { return 0 - 1 } 292 loc[RO_L_PEND] = pe 293 var bo: i64 = 0 - 1 294 i = pe + 1 295 while i < n { if buf[i] == (RO_LBRACE as u8) { bo = i; i = n } i = i + 1 } 296 if bo < 0 { return 0 - 1 } 297 loc[RO_L_BOPEN] = bo 298 loc[RO_L_RSTART] = 0 - 1 299 loc[RO_L_REND] = 0 - 1 300 let arrow: i64 = ro_find(buf, bo, pe, "->" as *u8) 301 if arrow >= 0 { 302 let rs: i64 = ro_trim_start(buf, arrow + 2, bo) 303 let re: i64 = ro_trim_end(buf, rs, bo) 304 loc[RO_L_RSTART] = rs 305 loc[RO_L_REND] = re 306 } 307 depth = 1 308 i = bo + 1 309 var bc: i64 = 0 - 1 310 while i < n { 311 let c2: i64 = buf[i] as i64 312 if c2 == RO_QUOTE { i = ro_skip_str(buf, n, i) } 313 else { 314 var handled: i64 = 0 315 if c2 == RO_SLASH { if i + 1 < n { if buf[i + 1] == (RO_SLASH as u8) { i = ro_skip_comment(buf, n, i); handled = 1 } } } 316 if handled == 0 { 317 if c2 == RO_LBRACE { depth = depth + 1 } 318 if c2 == RO_RBRACE { depth = depth - 1; if depth == 0 { bc = i; i = n } } 319 i = i + 1 320 } 321 } 322 } 323 if bc < 0 { return 0 - 1 } 324 loc[RO_L_BCLOSE] = bc 325 return 1 326} 327 328// parameters in buf[ps, pe): prm[4k] = name_off, name_len, type_off, type_len. returns count; 329// -1 when more than RO_MAX_PARAMS, -2 when a parameter carries no type. 330func ro_params(buf: *u8, ps: i64, pe: i64, prm: *i64) -> i64 { 331 var cnt: i64 = 0 332 var s: i64 = ps 333 var i: i64 = ps 334 var depth: i64 = 0 335 while i <= pe { 336 var c: i64 = RO_COMMA 337 if i < pe { c = buf[i] as i64 } 338 if c == RO_LPAREN { depth = depth + 1 } 339 if c == RO_RPAREN { depth = depth - 1 } 340 if c == RO_COMMA { if depth == 0 { 341 let ts: i64 = ro_trim_start(buf, s, i) 342 let te: i64 = ro_trim_end(buf, ts, i) 343 if te > ts { 344 if cnt >= RO_MAX_PARAMS { return 0 - 1 } 345 var col: i64 = 0 - 1 346 var k: i64 = ts 347 while k < te { if buf[k] == (RO_COLON as u8) { col = k; k = te } k = k + 1 } 348 if col < 0 { return 0 - 2 } 349 let ne: i64 = ro_trim_end(buf, ts, col) 350 let tys: i64 = ro_trim_start(buf, col + 1, te) 351 prm[cnt * RO_P_STRIDE + 0] = ts 352 prm[cnt * RO_P_STRIDE + 1] = ne - ts 353 prm[cnt * RO_P_STRIDE + 2] = tys 354 prm[cnt * RO_P_STRIDE + 3] = te - tys 355 cnt = cnt + 1 356 } 357 s = i + 1 358 } } 359 i = i + 1 360 } 361 return cnt 362} 363 364func ro_emit(out: *u8, o0: i64, s: *u8) -> i64 { 365 var o: i64 = o0 366 var i: i64 = 0 367 while s[i] != (0 as u8) { out[o] = s[i]; o = o + 1; i = i + 1 } 368 return o 369} 370 371// where an absent import line goes: after the last import line; else before the first BOL func/const; else 0 372func ro_import_slot(buf: *u8, n: i64) -> i64 { 373 var last: i64 = 0 - 1 374 var from: i64 = 0 375 var go: i64 = 1 376 while go == 1 { 377 let p: i64 = ro_find(buf, n, from, "import \"" as *u8) 378 if p < 0 { go = 0 } 379 if go == 1 { 380 if p == 0 { last = p } else { if buf[p - 1] == (RO_NL as u8) { last = p } } 381 from = p + 1 382 } 383 } 384 if last >= 0 { 385 var e: i64 = last 386 while e < n { if buf[e] == (RO_NL as u8) { return e + 1 } e = e + 1 } 387 return n 388 } 389 var f1: i64 = ro_find_bol(buf, n, "func " as *u8) 390 let c1: i64 = ro_find_bol(buf, n, "const " as *u8) 391 if c1 >= 0 { if f1 < 0 { f1 = c1 } else { if c1 < f1 { f1 = c1 } } } 392 if f1 < 0 { f1 = 0 } 393 return f1 394} 395 396// compose the retired file into out (cap >= n + RO_OUT_SLACK); returns its length. 397// import_added[0] = 1 when an import line was inserted. 398func ro_compose(buf: *u8, n: i64, loc: *i64, prm: *i64, np: i64, owner_fn: *u8, libname: *u8, out: *u8, import_added: *i64) -> i64 { 399 let ipat: *u8 = sys_mmap(RO_PAT_CAP) 400 ro_mk_import(ipat, libname) 401 var ins: i64 = 0 - 1 402 if ro_find(buf, n, 0, ipat) < 0 { ins = ro_import_slot(buf, n) } 403 import_added[0] = 0 404 let bo: i64 = loc[RO_L_BOPEN] 405 let bc: i64 = loc[RO_L_BCLOSE] 406 var o: i64 = 0 407 var i: i64 = 0 408 while i <= bo { 409 if i == ins { o = ro_emit(out, o, ipat); out[o] = RO_NL as u8; o = o + 1; import_added[0] = 1 } 410 out[o] = buf[i]; o = o + 1 411 i = i + 1 412 } 413 o = ro_emit(out, o, " return " as *u8) 414 o = ro_emit(out, o, owner_fn) 415 out[o] = RO_LPAREN as u8; o = o + 1 416 var p: i64 = 0 417 while p < np { 418 if p > 0 { o = ro_emit(out, o, ", " as *u8) } 419 var k: i64 = 0 420 while k < prm[p * RO_P_STRIDE + 1] { out[o] = buf[prm[p * RO_P_STRIDE + 0] + k]; o = o + 1; k = k + 1 } 421 p = p + 1 422 } 423 o = ro_emit(out, o, ") " as *u8) 424 i = bc 425 while i < n { 426 if i == ins { o = ro_emit(out, o, ipat); out[o] = RO_NL as u8; o = o + 1; import_added[0] = 1 } 427 out[o] = buf[i]; o = o + 1 428 i = i + 1 429 } 430 if ins == n { o = ro_emit(out, o, ipat); out[o] = RO_NL as u8; o = o + 1; import_added[0] = 1 } 431 sys_munmap(ipat, RO_PAT_CAP) 432 return o 433} 434 435func ro_report(path: *u8, fname: *u8, verdict: *u8, code: i64, quiet: i64) -> i64 { 436 if quiet == 0 { 437 ro_out("NX-RETIRE-ONTO file=" as *u8); ro_out(path) 438 ro_out(" fn=" as *u8); ro_out(fname) 439 ro_out(" verdict=" as *u8); ro_out(verdict) 440 ro_out("\n" as *u8) 441 } 442 return code 443} 444 445func ro_rt_eq(a: *u8, la: *i64, b: *u8, lb: *i64) -> i64 { 446 if la[RO_L_RSTART] < 0 { if lb[RO_L_RSTART] < 0 { return 1 } return 0 } 447 if lb[RO_L_RSTART] < 0 { return 0 } 448 return ro_span_eq(a, la[RO_L_RSTART], la[RO_L_REND] - la[RO_L_RSTART], b, lb[RO_L_RSTART], lb[RO_L_REND] - lb[RO_L_RSTART]) 449} 450 451// the probe module's basename, unique per (function, process): _ro_probe_<fname>_<pid> 452func ro_probe_name(out: *u8, fname: *u8) -> i64 { 453 var o: i64 = ro_emit(out, 0, "_ro_probe_" as *u8) 454 o = ro_emit(out, o, fname) 455 out[o] = 95 as u8; o = o + 1 456 o = ro_emit_num(out, o, __syscall(RO_SYS_GETPID, 0, 0, 0, 0, 0, 0)) 457 out[o] = 0 as u8 458 return o 459} 460 461// paths the probe needs, derived from the corpus root the gatekit already resolves (<X>/runtime/): 462// probe source <X>/runtime/<name>.nx, artifact <X>/_build/<name>.sov.elf, builder <X>/_offc/... with the 463// serving-root twin as the fallback. Returns 1, or 0 when no corpus root is reachable (REFUSED-no-root). 464func ro_probe_paths(name: *u8, src: *u8, elf: *u8, builder: *u8) -> i64 { 465 let root: *u8 = sys_mmap(RO_PROBE_PATH_CAP) 466 if gk_corpus_root(root) == 0 { return 0 } 467 let rl: i64 = ro_slen(root) 468 let x: i64 = rl - ro_slen("runtime/" as *u8) 469 if x < 0 { return 0 } 470 var i: i64 = 0 471 while i < rl { src[i] = root[i]; i = i + 1 } 472 var o: i64 = ro_emit(src, rl, name); o = ro_emit(src, o, ".nx" as *u8); src[o] = 0 as u8 473 i = 0 474 while i < x { elf[i] = root[i]; i = i + 1 } 475 o = ro_emit(elf, x, "_build/" as *u8); o = ro_emit(elf, o, name); o = ro_emit(elf, o, ".sov.elf" as *u8); elf[o] = 0 as u8 476 // the builder also leaves <name>.s and <name>.lock beside the artifact (measured in _build/ after the first 477 // gate runs); their paths share the elf prefix, so the caller derives them by suffix (ro_probe_side) 478 i = 0 479 while i < x { builder[i] = root[i]; i = i + 1 } 480 o = ro_emit(builder, x, "_offc/nx_sov_build_run.elf" as *u8); builder[o] = 0 as u8 481 if gk_exists(builder) == 1 { return 1 } 482 // serving-root twin: <X> is <root>/buildroot/ on the estate, and the tool lives one level up 483 let bl: i64 = ro_slen("buildroot/" as *u8) 484 if x >= bl { 485 i = 0 486 while i < x - bl { builder[i] = root[i]; i = i + 1 } 487 o = ro_emit(builder, x - bl, "nx_sov_build_run.elf" as *u8); builder[o] = 0 as u8 488 if gk_exists(builder) == 1 { return 1 } 489 } 490 return 0 491} 492 493// <elf path minus ".sov.elf"> + suffix -> out; used to name and remove the builder's side-files 494func ro_probe_side(elf: *u8, suffix: *u8, out: *u8) -> i64 { 495 let el: i64 = ro_slen(elf) 496 let sl: i64 = ro_slen(".sov.elf" as *u8) 497 if el <= sl { out[0] = 0 as u8; return 0 } 498 var i: i64 = 0 499 while i < el - sl { out[i] = elf[i]; i = i + 1 } 500 let o: i64 = ro_emit(out, el - sl, suffix) 501 out[o] = 0 as u8 502 return o 503} 504// remove every artifact a probe build leaves: the elf, the .s, the .lock 505func ro_probe_clean(elf: *u8) -> i64 { 506 let side: *u8 = sys_mmap(RO_PROBE_PATH_CAP) 507 gk_rm(elf) 508 ro_probe_side(elf, ".s" as *u8, side); gk_rm(side) 509 ro_probe_side(elf, ".lock" as *u8, side); gk_rm(side) 510 sys_munmap(side, RO_PROBE_PATH_CAP) 511 return 0 512} 513 514// emit the probe program: F = the private function, O = the owner, both unary i64 -> i64. 515func ro_probe_src(out: *u8, cand_base: *u8, owner_base: *u8, fname: *u8, owner_fn: *u8) -> i64 { 516 var o: i64 = 0 517 o = ro_emit(out, o, "// GENERATED by nx_retire_onto prove; transient, named per function and pid, removed after the run\n" as *u8) 518 o = ro_emit(out, o, "import \"" as *u8); o = ro_emit(out, o, cand_base); o = ro_emit(out, o, "\"\n" as *u8) 519 o = ro_emit(out, o, "import \"" as *u8); o = ro_emit(out, o, owner_base); o = ro_emit(out, o, "\"\n" as *u8) 520 o = ro_emit(out, o, "func main() -> i64 {\n var v: i64 = 0\n while v <= " as *u8) 521 o = ro_emit_num(out, o, RO_PROBE_DENSE) 522 o = ro_emit(out, o, " { if " as *u8); o = ro_emit(out, o, fname); o = ro_emit(out, o, "(v) != " as *u8); o = ro_emit(out, o, owner_fn) 523 o = ro_emit(out, o, "(v) { return 1 } v = v + 1 }\n var k: i64 = 20\n while k < 63 {\n let p: i64 = 1 << k\n" as *u8) 524 o = ro_emit(out, o, " if " as *u8); o = ro_emit(out, o, fname); o = ro_emit(out, o, "(p) != " as *u8); o = ro_emit(out, o, owner_fn); o = ro_emit(out, o, "(p) { return 1 }\n" as *u8) 525 o = ro_emit(out, o, " if " as *u8); o = ro_emit(out, o, fname); o = ro_emit(out, o, "(p - 1) != " as *u8); o = ro_emit(out, o, owner_fn); o = ro_emit(out, o, "(p - 1) { return 1 }\n" as *u8) 526 o = ro_emit(out, o, " if " as *u8); o = ro_emit(out, o, fname); o = ro_emit(out, o, "(p + 1) != " as *u8); o = ro_emit(out, o, owner_fn); o = ro_emit(out, o, "(p + 1) { return 1 }\n" as *u8) 527 // NEGATIVE inputs are outside an isqrt's domain, and that is exactly where two implementations may 528 // legitimately disagree (one returns 0, one loops, one returns the input). Behaviour-preserving means 529 // identical there too, so the owner must match the private body on -(2^k) as well; over-strict is the 530 // safe direction -- a DIFFER here is a named refusal, never a silent change. 531 o = ro_emit(out, o, " if " as *u8); o = ro_emit(out, o, fname); o = ro_emit(out, o, "(0 - p) != " as *u8); o = ro_emit(out, o, owner_fn); o = ro_emit(out, o, "(0 - p) { return 1 }\n k = k + 1\n }\n" as *u8) 532 o = ro_emit(out, o, " var m: i64 = 0 - 1\n while m > 0 - 1048577 { if " as *u8); o = ro_emit(out, o, fname); o = ro_emit(out, o, "(m) != " as *u8); o = ro_emit(out, o, owner_fn); o = ro_emit(out, o, "(m) { return 1 } m = m * 2 }\n" as *u8) 533 o = ro_emit(out, o, " var s: i64 = 1024\n while s < 3037000499 {\n let q: i64 = s * s\n" as *u8) 534 o = ro_emit(out, o, " if " as *u8); o = ro_emit(out, o, fname); o = ro_emit(out, o, "(q) != " as *u8); o = ro_emit(out, o, owner_fn); o = ro_emit(out, o, "(q) { return 1 }\n" as *u8) 535 o = ro_emit(out, o, " if " as *u8); o = ro_emit(out, o, fname); o = ro_emit(out, o, "(q - 1) != " as *u8); o = ro_emit(out, o, owner_fn); o = ro_emit(out, o, "(q - 1) { return 1 }\n s = s * 3 / 2 + 1\n }\n return 0\n}\n" as *u8) 536 out[o] = 0 as u8 537 return o 538} 539func ro_emit_num(out: *u8, o0: i64, v0: i64) -> i64 { 540 let b: *u8 = sys_mmap(32) 541 var v: i64 = v0 542 var neg: i64 = 0 543 if v < 0 { neg = 1; v = 0 - v } 544 var i: i64 = 31 545 b[i] = 0 as u8 546 if v == 0 { i = i - 1; b[i] = 48 as u8 } 547 while v > 0 { i = i - 1; b[i] = ((v % 10) + 48) as u8; v = v / 10 } 548 // a negative must never emit NOTHING: measured 2026-08-24, a wrong syscall number returned -EINVAL and the 549 // probe name silently lost its pid suffix while everything else read as if it had one 550 if neg == 1 { i = i - 1; b[i] = 45 as u8 } 551 let o: i64 = ro_emit(out, o0, b + i) 552 sys_munmap(b, 32) 553 return o 554} 555 556// classify a non-zero builder exit from the builder's OWN output: its admission governor prints VERDICT=QUEUE 557// when it declines to compile on a saturated box. A pure function of (output, rc) so the gate can plant both 558// shapes without needing a storm. Returns RO_PROVE_ADMISSION or RO_PROVE_UNBUILDABLE. 559func ro_build_rc_class(out: *u8, n: i64, rc: i64) -> i64 { 560 if rc == 0 { return RO_PROVE_PASS } 561 if ro_find(out, n, 0, "VERDICT=QUEUE" as *u8) >= 0 { return RO_PROVE_ADMISSION } 562 if ro_find(out, n, 0, "REFUSED-BUILD-ADMIT" as *u8) >= 0 { return RO_PROVE_ADMISSION } 563 return RO_PROVE_UNBUILDABLE 564} 565 566// the BINARY probe: F(a, b) vs O(a, b) over the cartesian square of a declared 49-value ladder 567// (0, +-1, +-2, +-3, +-7, +-2^4, +-2^7, ... +-2^61 in steps of three bits) = 2,401 pairs. The ladder is emitted 568// INTO the probe as a function so the probe carries its own declaration of what it examined. 569const RO_LADDER2_N: i64 = 49 570func ro_probe_src2(out: *u8, cand_base: *u8, owner_base: *u8, fname: *u8, owner_fn: *u8) -> i64 { 571 var o: i64 = 0 572 o = ro_emit(out, o, "// GENERATED by nx_retire_onto prove (binary); transient, named per function and pid, removed after the run\n" as *u8) 573 o = ro_emit(out, o, "import \"" as *u8); o = ro_emit(out, o, cand_base); o = ro_emit(out, o, "\"\n" as *u8) 574 o = ro_emit(out, o, "import \"" as *u8); o = ro_emit(out, o, owner_base); o = ro_emit(out, o, "\"\n" as *u8) 575 o = ro_emit(out, o, "func _ro_lad(k: i64) -> i64 {\n if k == 0 { return 0 }\n let s: i64 = k % 2\n let m: i64 = (k + 1) / 2\n var v: i64 = 0\n" as *u8) 576 o = ro_emit(out, o, " if m == 1 { v = 1 }\n if m == 2 { v = 2 }\n if m == 3 { v = 3 }\n if m == 4 { v = 7 }\n if m >= 5 { v = 1 << (4 + (m - 5) * 3) }\n if s == 1 { return 0 - v }\n return v\n}\n" as *u8) 577 o = ro_emit(out, o, "func main() -> i64 {\n var i: i64 = 0\n while i < " as *u8); o = ro_emit_num(out, o, RO_LADDER2_N) 578 o = ro_emit(out, o, " {\n var j: i64 = 0\n while j < " as *u8); o = ro_emit_num(out, o, RO_LADDER2_N) 579 o = ro_emit(out, o, " {\n let a: i64 = _ro_lad(i)\n let b: i64 = _ro_lad(j)\n if " as *u8) 580 o = ro_emit(out, o, fname); o = ro_emit(out, o, "(a, b) != " as *u8); o = ro_emit(out, o, owner_fn) 581 o = ro_emit(out, o, "(a, b) { return 1 }\n j = j + 1\n }\n i = i + 1\n }\n return 0\n}\n" as *u8) 582 out[o] = 0 as u8 583 return o 584} 585 586// prove <fname> in <path> is <owner_fn> on the declared ladder. Returns RO_PROVE_*. 587// Unary and binary i64 -> i64 are supported; every parameter must be i64 and the return type i64. 588func ro_prove(path: *u8, fname: *u8, lib: *u8, owner_fn: *u8, np: i64, buf: *u8, prm: *i64, loc: *i64) -> i64 { 589 if np < 1 { return RO_PROVE_UNSUPPORTED } 590 if np > 2 { return RO_PROVE_UNSUPPORTED } 591 var pi: i64 = 0 592 while pi < np { 593 if ro_span_eq(buf, prm[pi * RO_P_STRIDE + 2], prm[pi * RO_P_STRIDE + 3], "i64" as *u8, 0, 3) == 0 { return RO_PROVE_UNSUPPORTED } 594 pi = pi + 1 595 } 596 if loc[RO_L_RSTART] < 0 { return RO_PROVE_UNSUPPORTED } 597 if ro_span_eq(buf, loc[RO_L_RSTART], loc[RO_L_REND] - loc[RO_L_RSTART], "i64" as *u8, 0, 3) == 0 { return RO_PROVE_UNSUPPORTED } 598 let name: *u8 = sys_mmap(RO_PAT_CAP) 599 ro_probe_name(name, fname) 600 let src: *u8 = sys_mmap(RO_PROBE_PATH_CAP) 601 let elf: *u8 = sys_mmap(RO_PROBE_PATH_CAP) 602 let builder: *u8 = sys_mmap(RO_PROBE_PATH_CAP) 603 if ro_probe_paths(name, src, elf, builder) == 0 { return RO_PROVE_NOROOT } 604 let text: *u8 = sys_mmap(RO_PROBE_SRC_CAP) 605 if np == 2 { ro_probe_src2(text, ro_basename(path), ro_basename(lib), fname, owner_fn) } 606 else { ro_probe_src(text, ro_basename(path), ro_basename(lib), fname, owner_fn) } 607 if gk_write(src, text) < 0 { return RO_PROVE_NOROOT } 608 let out: *u8 = sys_mmap(RO_PROBE_OUTCAP) 609 let ol: *i64 = sys_mmap(16) as *i64 610 ro_probe_clean(elf) 611 let brc: i64 = gk_run_capture_ms(builder, name, "--build-only" as *u8, 0 as *u8, 0 as *u8, RO_BUILD_MS, out, RO_PROBE_OUTCAP, ol) 612 var verdict: i64 = ro_build_rc_class(out, ol[0], brc) 613 if verdict == RO_PROVE_PASS { verdict = RO_PROVE_UNBUILDABLE } 614 if brc == 0 { if gk_exists(elf) == 1 { 615 let rrc: i64 = gk_run_capture_ms(elf, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8, RO_PROBE_MS, out, RO_PROBE_OUTCAP, ol) 616 if rrc == 0 { verdict = RO_PROVE_PASS } else { verdict = RO_PROVE_DIFFER } 617 } } 618 gk_rm(src) 619 ro_probe_clean(elf) 620 return verdict 621} 622 623// retire <fname> in <path> onto <owner_fn> declared in <lib>. Returns an RO_* code and prints one line. 624// mode: RO_MODE_DRY (signature check only) / RO_MODE_PROVE (plus the differential probe, no write) / 625// RO_MODE_APPLY (probe, then write only on PASS). 626func ro_one(path: *u8, fname: *u8, lib: *u8, owner_fn: *u8, mode: i64, quiet: i64) -> i64 { 627 if ro_streq(ro_basename(path), ro_basename(lib)) == 1 { return ro_report(path, fname, "REFUSED-owner-is-self" as *u8, RO_REFUSED, quiet) } 628 let lp: *i64 = sys_mmap(16) as *i64 629 let buf: *u8 = sys_read_file(path, lp) 630 if (buf as i64) == 0 { return ro_report(path, fname, "REFUSED-unreadable-file" as *u8, RO_REFUSED, quiet) } 631 let n: i64 = lp[0] 632 let loc: *i64 = sys_mmap(RO_L_N * 8) as *i64 633 let lf: i64 = ro_locate(buf, n, fname, loc) 634 if lf == 0 { return ro_report(path, fname, "REFUSED-no-such-function" as *u8, RO_REFUSED, quiet) } 635 if lf == 0 - 2 { return ro_report(path, fname, "REFUSED-name-too-long" as *u8, RO_REFUSED, quiet) } 636 if lf < 0 { return ro_report(path, fname, "REFUSED-malformed-function" as *u8, RO_REFUSED, quiet) } 637 let prm: *i64 = sys_mmap(RO_MAX_PARAMS * RO_P_STRIDE * 8) as *i64 638 let np: i64 = ro_params(buf, loc[RO_L_PSTART], loc[RO_L_PEND], prm) 639 if np < 0 { return ro_report(path, fname, "REFUSED-params-unparsable-or-over-cap" as *u8, RO_REFUSED, quiet) } 640 let lp2: *i64 = sys_mmap(16) as *i64 641 let ob: *u8 = sys_read_file(lib, lp2) 642 if (ob as i64) == 0 { return ro_report(path, fname, "REFUSED-owner-lib-unreadable" as *u8, RO_REFUSED, quiet) } 643 let on: i64 = lp2[0] 644 let oloc: *i64 = sys_mmap(RO_L_N * 8) as *i64 645 if ro_locate(ob, on, owner_fn, oloc) != 1 { return ro_report(path, fname, "REFUSED-owner-fn-absent" as *u8, RO_REFUSED, quiet) } 646 let oprm: *i64 = sys_mmap(RO_MAX_PARAMS * RO_P_STRIDE * 8) as *i64 647 let onp: i64 = ro_params(ob, oloc[RO_L_PSTART], oloc[RO_L_PEND], oprm) 648 if onp != np { return ro_report(path, fname, "REFUSED-arity-mismatch" as *u8, RO_REFUSED, quiet) } 649 var p: i64 = 0 650 while p < np { 651 if ro_span_eq(buf, prm[p * RO_P_STRIDE + 2], prm[p * RO_P_STRIDE + 3], ob, oprm[p * RO_P_STRIDE + 2], oprm[p * RO_P_STRIDE + 3]) == 0 { 652 return ro_report(path, fname, "REFUSED-param-type-mismatch" as *u8, RO_REFUSED, quiet) 653 } 654 p = p + 1 655 } 656 if ro_rt_eq(buf, loc, ob, oloc) == 0 { return ro_report(path, fname, "REFUSED-return-type-mismatch" as *u8, RO_REFUSED, quiet) } 657 let out: *u8 = sys_mmap(n + RO_OUT_SLACK) 658 let ia: *i64 = sys_mmap(8) as *i64 659 let no: i64 = ro_compose(buf, n, loc, prm, np, owner_fn, ro_basename(lib), out, ia) 660 if no == n { if ro_span_eq(out, 0, no, buf, 0, n) == 1 { return ro_report(path, fname, "ALREADY-retired" as *u8, RO_ALREADY, quiet) } } 661 if mode == RO_MODE_DRY { 662 if quiet == 0 { 663 ro_out("NX-RETIRE-ONTO file=" as *u8); ro_out(path); ro_out(" fn=" as *u8); ro_out(fname) 664 ro_out(" onto=" as *u8); ro_out(owner_fn); ro_out(" arity=" as *u8); ro_num(np) 665 ro_out(" body_bytes=" as *u8); ro_num(loc[RO_L_BCLOSE] - loc[RO_L_BOPEN] - 1) 666 ro_out(" import=" as *u8); if ia[0] == 1 { ro_out("would-add" as *u8) } else { ro_out("present" as *u8) } 667 ro_out(" verdict=RETIRABLE-dry\n" as *u8) 668 } 669 return RO_RETIRABLE 670 } 671 let pv: i64 = ro_prove(path, fname, lib, owner_fn, np, buf, prm, loc) 672 if pv == RO_PROVE_UNSUPPORTED { return ro_report(path, fname, "REFUSED-prove-unsupported (unary or binary i64 -> i64 only; a PROGRAM's private helper cannot be imported by a probe -- lift it into a lib first)" as *u8, RO_REFUSED_UNSUPPORTED, quiet) } 673 if pv == RO_PROVE_NOROOT { return ro_report(path, fname, "REFUSED-prove-no-corpus-root-or-builder" as *u8, RO_REFUSED_UNBUILDABLE, quiet) } 674 if pv == RO_PROVE_ADMISSION { return ro_report(path, fname, "DEFERRED-builder-admission-refused (the BOX is saturated; nothing is known about this candidate -- re-run when the storm clears)" as *u8, RO_DEFERRED_ADMISSION, quiet) } 675 if pv == RO_PROVE_UNBUILDABLE { return ro_report(path, fname, "REFUSED-probe-does-not-build (the lib does not compile natively beside the owner)" as *u8, RO_REFUSED_UNBUILDABLE, quiet) } 676 if pv == RO_PROVE_DIFFER { return ro_report(path, fname, "REFUSED-semantics-differ (the private body is NOT the owner on the declared ladder)" as *u8, RO_REFUSED_DIFFER, quiet) } 677 if mode == RO_MODE_PROVE { 678 if quiet == 0 { 679 ro_out("NX-RETIRE-ONTO file=" as *u8); ro_out(path); ro_out(" fn=" as *u8); ro_out(fname) 680 ro_out(" onto=" as *u8); ro_out(owner_fn); ro_out(" ladder=0.." as *u8); ro_num(RO_PROBE_DENSE) 681 ro_out("+pow2+-1+squares verdict=PROVEN-equal (no write)\n" as *u8) 682 } 683 return RO_PROVEN 684 } 685 let fd: i64 = __syscall(RO_SYS_OPENAT, RO_AT_FDCWD, path, RO_O_WRONLY_CREAT_TRUNC, RO_MODE_644, 0, 0) 686 if fd < 0 { return ro_report(path, fname, "REFUSED-cannot-write" as *u8, RO_REFUSED, quiet) } 687 sys_write(fd, out, no) 688 sys_close(fd) 689 if quiet == 0 { 690 ro_out("NX-RETIRE-ONTO file=" as *u8); ro_out(path); ro_out(" fn=" as *u8); ro_out(fname) 691 ro_out(" onto=" as *u8); ro_out(owner_fn); ro_out(" bytes=" as *u8); ro_num(n); ro_out("->" as *u8); ro_num(no) 692 ro_out(" import=" as *u8); if ia[0] == 1 { ro_out("added" as *u8) } else { ro_out("present" as *u8) } 693 ro_out(" verdict=APPLIED (PROVEN equal on the declared ladder before the write; the consumer rebuild and its gates remain the behavioural referee)\n" as *u8) 694 } 695 return RO_APPLIED 696} 697 698// sweep the library plane: every symbol ending in <suffix> (and not the owner function itself, and not in the 699// owner lib) is a candidate; each is retired (or dry-checked). tally[RO_*] per code, tally[RO_T_CAND] = candidates. 700// Returns 0 when the plane was read, -2 when the plane is absent/unreadable (REFUSED, nothing examined). 701func ro_sweep(prefix: *u8, suffix: *u8, lib: *u8, owner_fn: *u8, mode: i64, tally: *i64) -> i64 { 702 let lp: *i64 = sys_mmap(16) as *i64 703 let b: *u8 = sts_load_fit(prefix, lp) 704 if (b as i64) == 0 { ro_out("NX-RETIRE-ONTO sweep REFUSED no-plane -- run `nx_libindex build` first\n" as *u8); return 0 - 2 } 705 let n: i64 = lp[0] 706 // MEASURED by this organ's own gate on its first run: sts_load_fit hands back an EMPTY buffer, not a null, 707 // for an unseeded plane, so a sweep over nothing would print candidates=0 partition=0/0 RECONCILES -- a 708 // clean-looking answer about a plane that does not exist. Zero rows is a refusal, never a census. 709 if n <= 0 { ro_out("NX-RETIRE-ONTO sweep REFUSED empty-or-absent-plane -- run `nx_libindex build` first\n" as *u8); return 0 - 2 } 710 let pathbuf: *u8 = sys_mmap(RO_PATH_CAP) 711 let namebuf: *u8 = sys_mmap(RO_PAT_CAP) 712 var t: i64 = 0 713 while t < RO_T_N { tally[t] = 0; t = t + 1 } 714 var ls: i64 = 0 715 var i: i64 = 0 716 while i <= n { 717 var eol: i64 = 0 718 if i == n { eol = 1 } 719 if i < n { if b[i] == (RO_NL as u8) { eol = 1 } } 720 if eol == 1 { 721 if i > ls { 722 // columns: name TAB path TAB title TAB syms 723 var t1: i64 = 0 - 1 724 var t2: i64 = 0 - 1 725 var t3: i64 = 0 - 1 726 var k: i64 = ls 727 while k < i { 728 if b[k] == (RO_TAB as u8) { 729 if t1 < 0 { t1 = k } else { if t2 < 0 { t2 = k } else { if t3 < 0 { t3 = k } } } 730 } 731 k = k + 1 732 } 733 if t3 >= 0 { 734 let plen: i64 = t2 - t1 - 1 735 if plen > 0 { if plen < RO_PATH_CAP - 1 { 736 var q: i64 = 0 737 while q < plen { pathbuf[q] = b[t1 + 1 + q]; q = q + 1 } 738 pathbuf[plen] = 0 as u8 739 if ro_streq(ro_basename(pathbuf), ro_basename(lib)) == 0 { 740 var ss: i64 = t3 + 1 741 var m: i64 = t3 + 1 742 while m <= i { 743 var tokend: i64 = 0 744 if m == i { tokend = 1 } 745 if m < i { if b[m] == (RO_SP as u8) { tokend = 1 } } 746 if tokend == 1 { 747 if m > ss { if m - ss < RO_PAT_CAP - 1 { 748 if ro_ends_with(b, ss, m, suffix) == 1 { 749 var r: i64 = 0 750 while r < m - ss { namebuf[r] = b[ss + r]; r = r + 1 } 751 namebuf[m - ss] = 0 as u8 752 if ro_streq(namebuf, owner_fn) == 0 { 753 tally[RO_T_CAND] = tally[RO_T_CAND] + 1 754 let code: i64 = ro_one(pathbuf, namebuf, lib, owner_fn, mode, 0) 755 tally[code] = tally[code] + 1 756 } 757 } 758 } } 759 ss = m + 1 760 } 761 m = m + 1 762 } 763 } 764 } } 765 } 766 } 767 ls = i + 1 768 } 769 i = i + 1 770 } 771 let sum: i64 = tally[RO_RETIRABLE] + tally[RO_ALREADY] + tally[RO_REFUSED] + tally[RO_APPLIED] + tally[RO_PROVEN] + tally[RO_REFUSED_DIFFER] + tally[RO_REFUSED_UNBUILDABLE] + tally[RO_REFUSED_UNSUPPORTED] + tally[RO_DEFERRED_ADMISSION] 772 ro_out("NX-RETIRE-ONTO sweep suffix=" as *u8); ro_out(suffix); ro_out(" onto=" as *u8); ro_out(owner_fn) 773 ro_out(" mode=" as *u8); ro_num(mode) 774 ro_out(" candidates=" as *u8); ro_num(tally[RO_T_CAND]) 775 ro_out(" retirable_dry=" as *u8); ro_num(tally[RO_RETIRABLE]) 776 ro_out(" proven=" as *u8); ro_num(tally[RO_PROVEN]) 777 ro_out(" already=" as *u8); ro_num(tally[RO_ALREADY]) 778 ro_out(" applied=" as *u8); ro_num(tally[RO_APPLIED]) 779 ro_out(" refused_signature=" as *u8); ro_num(tally[RO_REFUSED]) 780 ro_out(" refused_semantics_differ=" as *u8); ro_num(tally[RO_REFUSED_DIFFER]) 781 ro_out(" refused_unbuildable=" as *u8); ro_num(tally[RO_REFUSED_UNBUILDABLE]) 782 ro_out(" refused_unsupported=" as *u8); ro_num(tally[RO_REFUSED_UNSUPPORTED]) 783 ro_out(" deferred_admission=" as *u8); ro_num(tally[RO_DEFERRED_ADMISSION]) 784 ro_out(" partition=" as *u8); ro_num(sum); ro_out("/" as *u8); ro_num(tally[RO_T_CAND]) 785 if sum == tally[RO_T_CAND] { ro_out(" RECONCILES\n" as *u8) } else { ro_out(" LEAK\n" as *u8) } 786 return 0 787}