code wiki / _hdl_build / nx_magic_lib.nx

nx_magic_lib.nx source

↩ module page · 598 lines · 31098 B

1// nx_magic_lib.nx -- THE RULE-11 LITERAL SCANNER. Extracted out of nx_magic.nx on 2026-08-25 for two 2// reasons, and the second is the one that mattered. 3// 4// (1) IT COULD NEVER BE MUTATION-PROVEN WHERE IT WAS. mg_scan lived inside a program with main(), so the 5// only way to exercise it was to fork the deployed elf -- and every mutant of a fork/exec'd subject comes 6// back NOT-REACHED. The estate's most widely-consumed text scanner (it decides what /api/build calls a 7// rule-11 breach) had therefore never had a single tooth on it. In a lib it sits inside the gate's own 8// build closure and nx_gate_bite can kill mutants in it. 9// 10// (2) IT WAS BLIND TO HEXADECIMAL, AND THE BLINDNESS WAS DECLARED RATHER THAN FIXED. nx_magic's header 11// said "Decimal only -- hex is DECLARED out of envelope (nearly all hex here is < 1024)" and the map 12// envelope printed decimal_only:1, hex_out_of_envelope:1 on every call. A declaration does not make a 13// count mean what its name says. MEASURED 2026-08-25 on buildroot/runtime/_hdl_build/nx_activities_gate.nx 14// at floor 2: 41 sites / 26 distinct, one of which is the decimal literal 420 -- while the FOUR `0x1ed` 15// literals on lines 123/124/127/128 of the same file, which are THE SAME NUMBER, were not sites at all. 16// The mechanism was mechanical and total: at `0x1ed` the scanner read the digit run `0`, saw that the next 17// byte `x` is an identifier character, and discarded the whole token as identifier-digits. So the value it 18// would have carried was not merely mis-scaled, it was 0. 19// A file written entirely in 0x notation read as magic:0. 20// The estate had ALREADY banked the law -- "THE SAME CONSTANT IN TWO BASES IS TWO CONSTANTS TO EVERY 21// SCANNER", earned when a 39-site MODE_0644 sweep matched decimal 420 and missed a raw 0x1a4 -- and then 22// never taught the ruler the second base. A LAW BANKED IN PROSE AND ABSENT FROM THE INSTRUMENT IS A LAW 23// THE NEXT SWEEP WILL BREAK AGAIN. 24// 25// SCOPE OF THE FIX, STATED SO IT IS NOT OVERREAD: this closes the blind spot in nx_magic's scanner, which 26// produces the WORKLIST and the FLOOR VIEW. It does NOT change the number nx_magicratchet gates builds on: 27// that count comes from `nx_law_warden countfile` -> lw_line_lits, which is hex-blind by exactly the same 28// mechanism and is deliberately left alone here, because raising a count that already has 911 stored 29// baselines is the one edit that can refuse real builds estate-wide. Named, measured, not done blind. 30// 31// SKIPPED BY CONSTRUCTION (the false-positive controls, unchanged except where noted): whole-line comments, 32// TRAILING comments after code, const/static DECLARATION lines, bytes inside string literals, digits that 33// continue an identifier (x2048, and now also a hex body that runs into a letter), named-index table writes 34// `a[NAME] = literal`, any value below the threshold, and NEW: a hex literal too wide to represent exactly 35// (see MG_HEX_SAFE_DIGITS -- it is COUNTED and REPORTED, never silently dropped, and never recorded as a 36// site because a site authorises `nx_magic apply` to REWRITE THAT TEXT and a wrong value there is source 37// corruption). A HEURISTIC THAT GATES A DESTRUCTIVE ACTION MUST BE WRONG IN THE DIRECTION OF DOING NOTHING. 38// 39// 100% sovereign. No hardware writes (Rule 26). license_tier: ORIGINAL 40import "nx_syscalls.nx" 41 42const MG_CAP: i64 = 1048576 43const MG_NL: i64 = 10 44const MG_QU: i64 = 34 45const MG_BSL: i64 = 92 46const MG_SLASH: i64 = 47 47const MG_US: i64 = 95 48const MG_SP: i64 = 32 49const MG_TAB: i64 = 9 50const MG_LSQ: i64 = 91 51const MG_RSQ: i64 = 93 52const MG_EQ: i64 = 61 53const MG_MAXSITES: i64 = 4096 54const MG_MAXVALS: i64 = 256 55// The FLOOR view's bar. `threshold` is a GUESSED CEILING and the estate's rule-11 law is explicit 56// that a ceiling which must be guessed is a defect generator in BOTH directions -- raising it only 57// moves the guess. So this organ does not move it; it REPORTS WHAT THE BAR HIDES, at a floor low 58// enough that essentially nothing hides under it. 2, not 1 or 0, because 0/1 are structural (loop 59// bounds, flags, sign) and carry no policy. 60const MG_FLOOR: i64 = 2 61 62// ---- numeric-literal notation ---- 63const MG_ZERO: i64 = 48 64const MG_NINE: i64 = 57 65const MG_LC_A: i64 = 97 66const MG_LC_F: i64 = 102 67const MG_LC_X: i64 = 120 68const MG_LC_Z: i64 = 122 69const MG_UC_A: i64 = 65 70const MG_UC_F: i64 = 70 71const MG_UC_X: i64 = 88 72const MG_UC_Z: i64 = 90 73const MG_BASE_DEC: i64 = 10 74const MG_BASE_HEX: i64 = 16 75const MG_HEXDIG_OFF: i64 = 10 76// DERIVED, NOT PICKED: the widest hex body whose value is exactly representable in the i64 this scanner 77// and every consumer of `value` use. 16 hex digits is 64 bits, which overflows a SIGNED i64; 15 hex digits 78// is 60 bits and cannot. A literal wider than this is counted in the oversize stat and REFUSED as a site, 79// because a site is a licence for `nx_magic apply` to replace that text with a const of the parsed value. 80const MG_HEX_SAFE_DIGITS: i64 = 15 81 82// ---- mg_scan's out-of-band stat channel (indices into the caller's sstat array) ---- 83// These are COUNTS OF THINGS THAT DID NOT BECOME SITES, or that became sites in a second notation. They 84// are a separate array rather than extra return values because a count that has nowhere to go is a count 85// that gets dropped, and the whole reason this file exists is a number that was dropped at the next hop. 86const MG_STAT_HEX: i64 = 0 87const MG_STAT_HEX_OVERSIZE: i64 = 1 88const MG_STAT_N: i64 = 2 89const MG_I64_BYTES: i64 = 8 90 91func mg_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 92func mg_is_ident(c: i64) -> i64 { 93 if c >= MG_ZERO { if c <= MG_NINE { return 1 } } 94 if c >= MG_UC_A { if c <= MG_UC_Z { return 1 } } 95 if c >= MG_LC_A { if c <= MG_LC_Z { return 1 } } 96 if c == MG_US { return 1 } 97 return 0 98} 99func mg_is_digit(c: i64) -> i64 { if c >= MG_ZERO { if c <= MG_NINE { return 1 } } return 0 } 100// A HEX DIGIT IS NOT AN IDENTIFIER CHARACTER MINUS SOME LETTERS -- it is 0-9 a-f A-F and nothing else. 101// Spelling it as its own predicate (rather than reusing mg_is_ident and subtracting) is what makes the 102// run terminate correctly at `g`..`z`, so `0x1edge` stays an identifier and never becomes the value 493. 103func mg_is_hexdigit(c: i64) -> i64 { 104 if c >= MG_ZERO { if c <= MG_NINE { return 1 } } 105 if c >= MG_LC_A { if c <= MG_LC_F { return 1 } } 106 if c >= MG_UC_A { if c <= MG_UC_F { return 1 } } 107 return 0 108} 109// -1 for a non-hex byte. The caller only ever asks after mg_is_hexdigit said yes, but the sentinel is 110// real rather than a silent 0: a 0 would be indistinguishable from the digit '0' and would parse garbage 111// into a value that `apply` then writes into somebody's source. 112func mg_hexval(c: i64) -> i64 { 113 if c >= MG_ZERO { if c <= MG_NINE { return c - MG_ZERO } } 114 if c >= MG_LC_A { if c <= MG_LC_F { return c - MG_LC_A + MG_HEXDIG_OFF } } 115 if c >= MG_UC_A { if c <= MG_UC_F { return c - MG_UC_A + MG_HEXDIG_OFF } } 116 return 0 - 1 117} 118// first non-space index of line [ls,le) 119func mg_first_ns(q: *u8, ls: i64, le: i64) -> i64 { 120 var i: i64 = ls 121 var go: i64 = 1 122 while go == 1 { 123 go = 0 124 if i < le { if q[i] == (MG_SP as u8) { i = i + 1; go = 1 } else { if q[i] == (MG_TAB as u8) { i = i + 1; go = 1 } } } 125 } 126 return i 127} 128// does line [ls,le) start (after indent) with the c-string lit? 129func mg_starts(q: *u8, ls: i64, le: i64, lit: *u8) -> i64 { 130 let s: i64 = mg_first_ns(q, ls, le) 131 let n: i64 = mg_slen(lit) 132 if s + n > le { return 0 } 133 var i: i64 = 0 134 while i < n { if q[s+i] != lit[i] { return 0 } i = i + 1 } 135 return 1 136} 137// a line we must NOT touch: comment, or a const/static DECLARATION (its literal is already named) 138func mg_skip_line(q: *u8, ls: i64, le: i64) -> i64 { 139 if mg_starts(q, ls, le, "//" as *u8) == 1 { return 1 } 140 if mg_starts(q, ls, le, "const " as *u8) == 1 { return 1 } 141 if mg_starts(q, ls, le, "static " as *u8) == 1 { return 1 } 142 return 0 143} 144func mg_read(path: *u8, b: *u8, cap: i64) -> i64 { 145 let fd: i64 = sys_openat_rd(path) 146 if fd < 0 { return 0 - 1 } 147 var n: i64 = 0 148 var go: i64 = 1 149 while go == 1 { 150 let r: i64 = sys_read(fd, (b as i64 + n) as *u8, cap - n) 151 if r > 0 { n = n + r } else { go = 0 } 152 if n >= cap { go = 0 } 153 } 154 sys_close(fd) 155 return n 156} 157 158// ONE DISTINCT-VALUE COUNTER FOR THE WHOLE RULE-11 LANE. It lives here because nx_magic and 159// nx_magicratchet both need it and two copies of a counting loop is how two organs come to disagree 160// about one population. Fills tbl (insertion-ordered) and returns the distinct count. A return equal to 161// cap means the table FILLED -- the caller must publish that as a floor, not as a total. 162func mg_distinct(sval: *i64, sites: i64, tbl: *i64, cap: i64) -> i64 { 163 var nd: i64 = 0 164 var i: i64 = 0 165 while i < sites { 166 var found: i64 = 0 167 var j: i64 = 0 168 while j < nd { if tbl[j] == sval[i] { found = 1; j = nd } else { j = j + 1 } } 169 if found == 0 { if nd < cap { tbl[nd] = sval[i]; nd = nd + 1 } } 170 i = i + 1 171 } 172 return nd 173} 174 175// THE SCANNER. Walks the file once and records every offending literal site into the parallel 176// arrays (line, col, len, value, base). Returns the site count. Honest about its own bound: stops at 177// MG_MAXSITES and the caller DECLARES truncation rather than silently under-reporting. 178// sbase carries 10 or 16 per site -- a consumer that prints a value without its notation reproduces 179// the very ambiguity this scanner was just taught to see through. 180// sstat must have at least MG_STAT_N words and is expected zero-filled (sys_mmap is). 181func mg_scan(q: *u8, n: i64, thr: i64, sline: *i64, scol: *i64, slen: *i64, sval: *i64, sls: *i64, sle: *i64, sbase: *i64, sstat: *i64) -> i64 { 182 var sites: i64 = 0 183 var lineno: i64 = 1 184 var i: i64 = 0 185 while i < n { 186 var le: i64 = i 187 var s: i64 = 1 188 while s == 1 { if le >= n { s = 0 } else { if q[le] == (MG_NL as u8) { s = 0 } else { le = le + 1 } } } 189 if mg_skip_line(q, i, le) == 0 { 190 var instr: i64 = 0 191 var p: i64 = i 192 while p < le { 193 let c: i64 = q[p] as i64 194 // TRAILING COMMENTS (fixed 2026-08-14). This loop tracked STRINGS but never 195 // COMMENTS, and mg_skip_line only excludes a WHOLE comment line -- so a `//` 196 // comment sitting after CODE was scanned as code. The header above has promised 197 // "comment lines" were skipped since day one, and that word `lines` was the bug. 198 // MEASURED: nx_skullsdf line 20 is 199 // import "nx_memfloor.nx" // ... (2026-07-30 incident) 200 // and map reported the DATE 2026 as a site at col 86, while nx_law_warden 201 // countfile -- which the ratchet's COUNT uses -- correctly returned 0. The two 202 // instruments disagreeing by exactly one is what located this. 203 // Setting p = le is sufficient and needs no restructuring: c is '/', so the 204 // chain below falls through to its final `p = p + 1`, making p = le + 1 and 205 // ending the loop without recording a site. 206 if instr == 0 { if c == MG_SLASH { if p + 1 < le { if q[p+1] == (MG_SLASH as u8) { p = le } } } } 207 if instr == 1 { 208 if c == MG_BSL { p = p + 1 } else { if c == MG_QU { instr = 0 } } 209 p = p + 1 210 } else { 211 if c == MG_QU { instr = 1; p = p + 1 } else { 212 if mg_is_digit(c) == 1 { 213 // a digit run only counts if it does NOT continue an identifier 214 var prev_ident: i64 = 0 215 if p > i { if mg_is_ident(q[p-1] as i64) == 1 { prev_ident = 1 } } 216 // NAMED-INDEX TABLE WRITE (2026-08-14). `P[P_OR]=8` is NOT a magic number: 217 // the INDEX IS THE NAME and the array IS the data, which is what rule 11 218 // asks for. MEASURED: 106 of nx_skullsdf's 942 sites are `ss_defaults`, 219 // whose own header reads "FITTED, NOT TYPED -- the output of `tune`, 220 // coordinate descent that took mean surface error 8.37mm -> 5.06mm against 221 // a 171k-triangle scan". Counting them inflated the population AND aimed a 222 // drain at the most dangerous class in the organ: a conf migration there 223 // would have moved a tuner's output away from its tuner. Some are not even 224 // typed (`P[P_UY]=P[P_MY]-24`, derived from the parent bone). 225 // Skip only the exact shape `<ident>[<non-numeric-index>] = <literal>`; 226 // a numeric index (`buf[0]=4096`) still counts, so a real buffer constant 227 // is not lost. 228 var tbl: i64 = 0 229 var w: i64 = p - 1 230 var ws: i64 = 1 231 while ws == 1 { ws = 0; if w > i { if q[w] == (MG_SP as u8) { w = w - 1; ws = 1 } } } 232 if w > i { if q[w] == (MG_EQ as u8) { 233 var w2: i64 = w - 1 234 var ws2: i64 = 1 235 while ws2 == 1 { ws2 = 0; if w2 > i { if q[w2] == (MG_SP as u8) { w2 = w2 - 1; ws2 = 1 } } } 236 if w2 > i { if q[w2] == (MG_RSQ as u8) { 237 var w3: i64 = w2 - 1 238 var idn: i64 = 0 239 var g3: i64 = 1 240 while g3 == 1 { g3 = 0 241 if w3 > i { if q[w3] != (MG_LSQ as u8) { 242 if mg_is_digit(q[w3] as i64) == 0 { idn = 1 } 243 w3 = w3 - 1 244 g3 = 1 245 } } 246 } 247 if idn == 1 { tbl = 1 } 248 } } 249 } } 250 // ---- BASE DETECTION (2026-08-25). See the header: this is the half that 251 // was declared out of envelope for a year and reported as a count anyway. 252 // `0x` or `0X` followed by AT LEAST ONE hex digit is a hex literal. The 253 // "at least one" matters: a bare `0x` with nothing after it is not a 254 // number in any dialect, and treating it as one would invent a value of 0. 255 var base: i64 = MG_BASE_DEC 256 var e: i64 = p 257 var v: i64 = 0 258 var oversize: i64 = 0 259 if c == MG_ZERO { if p + 2 < le { 260 if q[p+1] == (MG_LC_X as u8) { if mg_is_hexdigit(q[p+2] as i64) == 1 { base = MG_BASE_HEX } } 261 if q[p+1] == (MG_UC_X as u8) { if mg_is_hexdigit(q[p+2] as i64) == 1 { base = MG_BASE_HEX } } 262 } } 263 if base == MG_BASE_HEX { 264 let hs: i64 = p + 2 265 e = hs 266 var gh: i64 = 1 267 while gh == 1 { gh = 0; if e < le { if mg_is_hexdigit(q[e] as i64) == 1 { e = e + 1; gh = 1 } } } 268 if e - hs > MG_HEX_SAFE_DIGITS { oversize = 1 } 269 if oversize == 0 { 270 var kh: i64 = hs 271 while kh < e { v = v * MG_BASE_HEX + mg_hexval(q[kh] as i64); kh = kh + 1 } 272 } 273 } else { 274 var g2: i64 = 1 275 while g2 == 1 { g2 = 0; if e < le { if mg_is_digit(q[e] as i64) == 1 { e = e + 1; g2 = 1 } } } 276 var kd: i64 = p 277 while kd < e { v = v * MG_BASE_DEC + ((q[kd] as i64) - MG_ZERO); kd = kd + 1 } 278 } 279 var trail_ident: i64 = 0 280 if e < le { if mg_is_ident(q[e] as i64) == 1 { trail_ident = 1 } } 281 if prev_ident == 0 { if trail_ident == 0 { if tbl == 0 { 282 if oversize == 1 { 283 // NOT a site, and NOT invisible either. `apply` rewrites site text, 284 // so a value we cannot represent exactly must never authorise an 285 // edit -- but a silent drop would recreate the blind spot this 286 // whole change exists to close, one notation deeper. 287 sstat[MG_STAT_HEX_OVERSIZE] = sstat[MG_STAT_HEX_OVERSIZE] + 1 288 } else { 289 if v >= thr { if sites < MG_MAXSITES { 290 sline[sites] = lineno 291 scol[sites] = p - i 292 slen[sites] = e - p 293 sval[sites] = v 294 sls[sites] = i 295 sle[sites] = le 296 sbase[sites] = base 297 if base == MG_BASE_HEX { sstat[MG_STAT_HEX] = sstat[MG_STAT_HEX] + 1 } 298 sites = sites + 1 299 } } 300 } 301 } } } 302 p = e 303 } else { p = p + 1 } 304 } 305 } 306 } 307 } 308 lineno = lineno + 1 309 i = le + 1 310 } 311 return sites 312} 313 314// ---- PURPOSE NAMES (rule 11, 2026-09-05): the table that turns <PFX>_MAGIC_<v> into a name that says WHY ---- 315// knowledge/magic_names.conf rows: value|needle|name|why. A row CLAIMS a site when the literal equals value and the 316// needle (a literal substring, or * for any) occurs in the site's context window -- the same line-centred window 317// `map` prints, so what a reader can SEE is exactly what decided the name. Rows are tried in file order and the first 318// match wins (put the specific needle above the general one). A site no row claims keeps the mechanical name, and 319// every verb says which is which, so a guessed meaning can never wear a domain term. The organ prefix is prepended 320// by the caller (<PFX>_<name>), so two organs naming the same byte never share one symbol. One value with two 321// meanings (8 as bytes-per-i64 beside 8 as bits-per-byte) becomes TWO consts when two rows discriminate by needle -- 322// which is why the name is resolved per SITE and the consts are deduped by NAME, never by value. 323const MG_NAMES_CONF: *u8 = "knowledge/magic_names.conf" 324const MG_NAMES_MAX: i64 = 512 325const MG_NAMES_FIELD: i64 = 96 // a needle or a name; the why column is read and not stored 326const MG_NAMES_COL_VALUE: i64 = 0 327const MG_NAMES_COL_NEEDLE: i64 = 1 328const MG_NAMES_COL_NAME: i64 = 2 329const MG_NAME_W: i64 = 256 // one resolved name: prefix, underscore, name -- or the mechanical form 330const MG_NAME_ANY: i64 = 42 // the * needle: any context 331const MG_PIPE: i64 = 124 332const MG_HASH: i64 = 35 // a comment row in the conf 333const MG_CR: i64 = 13 // a CRLF conf reads the same as an LF one 334const MG_CTX: i64 = 60 // the context window `map` prints and the resolver reads 335// How much of the window sits BEFORE the site. The operator that gives a literal its meaning is almost always 336// immediately to its left (`/100` is a unit, ` 100` is a clamp or a coordinate), so the lead only has to carry the 337// enclosing expression, not the whole line. 338const MG_CTX_LEAD: i64 = 24 339static mg_nm_val: *i64 340static mg_nm_needle: *i64 341static mg_nm_name: *i64 342static mg_nm_arena: *u8 343static mg_nm_n: i64 344static mg_nm_src: i64 // 0 = conf absent or empty (mechanical names only), 1 = conf read 345 346// non-negative decimal in a field (the scanner records literals, never signs); stops at the first non-digit 347func mg_nm_int(s: *u8) -> i64 { 348 var i: i64 = 0 349 var v: i64 = 0 350 while mg_is_digit(s[i] as i64) == 1 { v = v * MG_BASE_DEC + ((s[i] as i64) - MG_ZERO); i = i + 1 } 351 return v 352} 353// pipe field idx of the row [s,e) into out (CR stripped); its length 354func mg_nm_field(b: *u8, s: i64, e: i64, idx: i64, out: *u8, cap: i64) -> i64 { 355 var p: i64 = s 356 var f: i64 = 0 357 var k: i64 = 0 358 while p < e { 359 let c: i64 = b[p] as i64 360 if c == MG_PIPE { f = f + 1; if f > idx { p = e } } else { 361 if f == idx { if c != MG_CR { if k < cap - 1 { out[k] = c as u8; k = k + 1 } } } 362 } 363 p = p + 1 364 } 365 out[k] = 0 as u8 366 return k 367} 368func mg_names_load(path: *u8) -> i64 { 369 mg_nm_val = sys_mmap(MG_NAMES_MAX * MG_I64_BYTES) as *i64 370 mg_nm_needle = sys_mmap(MG_NAMES_MAX * MG_I64_BYTES) as *i64 371 mg_nm_name = sys_mmap(MG_NAMES_MAX * MG_I64_BYTES) as *i64 372 mg_nm_arena = sys_mmap(MG_NAMES_MAX * MG_NAMES_FIELD * 2) 373 mg_nm_n = 0 374 mg_nm_src = 0 375 let b: *u8 = sys_mmap(MG_CAP) 376 let n: i64 = mg_read(path, b, MG_CAP - 1) 377 if n <= 0 { return 0 - 1 } 378 mg_nm_src = 1 379 let fld: *u8 = sys_mmap(MG_NAMES_FIELD) 380 var ao: i64 = 0 381 var i: i64 = 0 382 while i < n { 383 var le: i64 = i 384 var s: i64 = 1 385 while s == 1 { if le >= n { s = 0 } else { if b[le] == (MG_NL as u8) { s = 0 } else { le = le + 1 } } } 386 if le > i { if b[i] != (MG_HASH as u8) { if mg_nm_n < MG_NAMES_MAX { 387 let vl: i64 = mg_nm_field(b, i, le, MG_NAMES_COL_VALUE, fld, MG_NAMES_FIELD) 388 let nl: i64 = mg_nm_field(b, i, le, MG_NAMES_COL_NEEDLE, (mg_nm_arena as i64 + ao) as *u8, MG_NAMES_FIELD) 389 let ml: i64 = mg_nm_field(b, i, le, MG_NAMES_COL_NAME, (mg_nm_arena as i64 + ao + MG_NAMES_FIELD) as *u8, MG_NAMES_FIELD) 390 if vl > 0 { if nl > 0 { if ml > 0 { 391 mg_nm_val[mg_nm_n] = mg_nm_int(fld) 392 mg_nm_needle[mg_nm_n] = ao 393 mg_nm_name[mg_nm_n] = ao + MG_NAMES_FIELD 394 ao = ao + MG_NAMES_FIELD * 2 395 mg_nm_n = mg_nm_n + 1 396 } } } 397 } } } 398 i = le + 1 399 } 400 return mg_nm_n 401} 402func mg_names_src() -> i64 { return mg_nm_src } 403func mg_names_count() -> i64 { return mg_nm_n } 404func mg_nm_name_at(row: i64) -> *u8 { return (mg_nm_arena as i64 + mg_nm_name[row]) as *u8 } 405func mg_nm_needle_at(row: i64) -> *u8 { return (mg_nm_arena as i64 + mg_nm_needle[row]) as *u8 } 406// the window `map` prints for a site: the whole line when it fits, else MG_CTX bytes centred on the site 407func mg_ctx_window(ls: i64, le: i64, col: i64, csp: *i64, cep: *i64) -> i64 { 408 var cs: i64 = ls 409 var ce: i64 = le 410 if ce - cs > MG_CTX { 411 if col > MG_CTX_LEAD { cs = ls + col - MG_CTX_LEAD } 412 ce = cs + MG_CTX 413 if ce > le { ce = le } 414 } 415 csp[0] = cs 416 cep[0] = ce 417 return 0 418} 419// literal substring inside [cs,ce); an empty needle claims nothing 420func mg_ctx_has(q: *u8, cs: i64, ce: i64, needle: *u8) -> i64 { 421 let nl: i64 = mg_slen(needle) 422 if nl == 0 { return 0 } 423 var i: i64 = cs 424 while i + nl <= ce { 425 var k: i64 = 0 426 var ok: i64 = 1 427 while k < nl { if q[i + k] != needle[k] { ok = 0; k = nl } else { k = k + 1 } } 428 if ok == 1 { return 1 } 429 i = i + 1 430 } 431 return 0 432} 433// the first row that claims (value, window); -1 when none does (the caller then uses the mechanical name) 434func mg_name_lookup(v: i64, q: *u8, cs: i64, ce: i64) -> i64 { 435 var r: i64 = 0 436 while r < mg_nm_n { 437 if mg_nm_val[r] == v { 438 let nd: *u8 = mg_nm_needle_at(r) 439 if (nd[0] as i64) == MG_NAME_ANY { if (nd[1] as i64) == 0 { return r } } 440 if mg_ctx_has(q, cs, ce, nd) == 1 { return r } 441 } 442 r = r + 1 443 } 444 return 0 - 1 445} 446 447// ---- KIND AND DERIVATION (operator standing order 2026-09-17) ----------------------------------------------------------- 448// "from the first byte up we should have derived numbers that are intelligent based on resource, not literals replaced 449// with constants ... that should be estate wide and how the magic number ratchet works with you and everything else." 450// A literal hoisted into a named const is a RENAME: a person still typed the number. What a number IS decides where it 451// should COME FROM, and that is DATA (knowledge/magic_kinds.conf): unit rows name the values a constant is right for, 452// kind rows class a site by the company the literal keeps on its line, derive rows say where a number of that kind comes 453// from. A gate source is FIXTURE before any needle is tried; a site no row claims is UNKNOWN and says so. 454const MG_KIND_CONF: *u8 = "knowledge/magic_kinds.conf" 455const MG_KROW_UNIT: *u8 = "unit" 456const MG_KROW_KIND: *u8 = "kind" 457const MG_KROW_DERIVE: *u8 = "derive" 458const MG_KIND_UNIT: *u8 = "UNIT" 459const MG_KIND_FIXTURE: *u8 = "FIXTURE" 460const MG_KIND_UNKNOWN: *u8 = "UNKNOWN" 461const MG_GATE_SFX: *u8 = "_gate.nx" 462const MG_PLACEHOLDER: *u8 = "_MAGIC_" 463const MG_CONST_KW: *u8 = "const " 464const MG_KCOL_TAG: i64 = 0 465const MG_KCOL_KEY: i64 = 1 466const MG_KCOL_VAL: i64 = 2 467const MG_KD_COLON: i64 = 58 468static mg_kd_buf: *u8 469static mg_kd_n: i64 470 471// the kinds table, read WHOLE (sys_read_file sizes from the file); returns its bytes, 0 when absent 472func mg_kinds_load(path: *u8) -> i64 { 473 let lenp: *i64 = sys_mmap(MG_I64_BYTES) as *i64 474 lenp[0] = 0 475 mg_kd_buf = sys_read_file(path, lenp) 476 mg_kd_n = lenp[0] 477 if mg_kd_n < 0 { mg_kd_n = 0 } 478 return mg_kd_n 479} 480// no sentence of the table is longer than the table: a caller sizes its derive buffer from this, never from a guess 481func mg_kinds_bytes() -> i64 { return mg_kd_n } 482 483func mg_line_end(b: *u8, n: i64, i: i64) -> i64 { 484 var le: i64 = i 485 var s: i64 = 1 486 while s == 1 { if le >= n { s = 0 } else { if b[le] == (MG_NL as u8) { s = 0 } else { le = le + 1 } } } 487 return le 488} 489func mg_str_eq(a: *u8, b: *u8) -> i64 { 490 var i: i64 = 0 491 var s: i64 = 1 492 while s == 1 { if a[i] != b[i] { return 0 } if a[i] == (0 as u8) { s = 0 } else { i = i + 1 } } 493 return 1 494} 495func mg_copy(dst: *u8, src: *u8, cap: i64) -> i64 { 496 var k: i64 = 0 497 while src[k] != (0 as u8) { if k < cap - 1 { dst[k] = src[k] } k = k + 1 } 498 if k > cap - 1 { k = cap - 1 } 499 dst[k] = 0 as u8 500 return k 501} 502func mg_ends(s: *u8, sfx: *u8) -> i64 { 503 let sl: i64 = mg_slen(s) 504 let xl: i64 = mg_slen(sfx) 505 if xl > sl { return 0 } 506 var k: i64 = 0 507 while k < xl { if s[sl - xl + k] != sfx[k] { return 0 } k = k + 1 } 508 return 1 509} 510 511// the KIND of a site, the word into out; returns its length. path is the source file, v the literal's value, [cs,ce) the 512// site's context window (the same window nx_magic map prints). 513func mg_kind_of(path: *u8, v: i64, q: *u8, cs: i64, ce: i64, out: *u8, cap: i64) -> i64 { 514 if mg_ends(path, MG_GATE_SFX) == 1 { return mg_copy(out, MG_KIND_FIXTURE, cap) } 515 let tag: *u8 = sys_mmap(MG_NAMES_FIELD) 516 let key: *u8 = sys_mmap(MG_NAMES_FIELD) 517 // a value the table names as a unit is a unit wherever it stands 518 var i: i64 = 0 519 while i < mg_kd_n { 520 let le: i64 = mg_line_end(mg_kd_buf, mg_kd_n, i) 521 if le > i { if mg_kd_buf[i] != (MG_HASH as u8) { 522 mg_nm_field(mg_kd_buf, i, le, MG_KCOL_TAG, tag, MG_NAMES_FIELD) 523 if mg_str_eq(tag, MG_KROW_UNIT) == 1 { 524 let kl: i64 = mg_nm_field(mg_kd_buf, i, le, MG_KCOL_KEY, key, MG_NAMES_FIELD) 525 if kl > 0 { if mg_nm_int(key) == v { return mg_copy(out, MG_KIND_UNIT, cap) } } 526 } 527 } } 528 i = le + 1 529 } 530 // then the company it keeps: the first needle found in the window wins 531 i = 0 532 while i < mg_kd_n { 533 let le2: i64 = mg_line_end(mg_kd_buf, mg_kd_n, i) 534 if le2 > i { if mg_kd_buf[i] != (MG_HASH as u8) { 535 mg_nm_field(mg_kd_buf, i, le2, MG_KCOL_TAG, tag, MG_NAMES_FIELD) 536 if mg_str_eq(tag, MG_KROW_KIND) == 1 { 537 mg_nm_field(mg_kd_buf, i, le2, MG_KCOL_KEY, key, MG_NAMES_FIELD) 538 if mg_ctx_has(q, cs, ce, key) == 1 { return mg_nm_field(mg_kd_buf, i, le2, MG_KCOL_VAL, out, cap) } 539 } 540 } } 541 i = le2 + 1 542 } 543 return mg_copy(out, MG_KIND_UNKNOWN, cap) 544} 545 546// where a number of that kind comes from: the sentence into out (size it from mg_kinds_bytes() + 1); 0 when no row says 547func mg_kind_derive(kind: *u8, out: *u8, cap: i64) -> i64 { 548 let tag: *u8 = sys_mmap(MG_NAMES_FIELD) 549 let key: *u8 = sys_mmap(MG_NAMES_FIELD) 550 var i: i64 = 0 551 while i < mg_kd_n { 552 let le: i64 = mg_line_end(mg_kd_buf, mg_kd_n, i) 553 if le > i { if mg_kd_buf[i] != (MG_HASH as u8) { 554 mg_nm_field(mg_kd_buf, i, le, MG_KCOL_TAG, tag, MG_NAMES_FIELD) 555 if mg_str_eq(tag, MG_KROW_DERIVE) == 1 { 556 mg_nm_field(mg_kd_buf, i, le, MG_KCOL_KEY, key, MG_NAMES_FIELD) 557 if mg_str_eq(key, kind) == 1 { return mg_nm_field(mg_kd_buf, i, le, MG_KCOL_VAL, out, cap) } 558 } 559 } } 560 i = le + 1 561 } 562 out[0] = 0 as u8 563 return 0 564} 565 566// the kinds a report has SEEN, as NUL-separated words in seen[0..so): add w when it is not there yet; returns the new fill. 567// Size seen from mg_kinds_bytes() plus one name width: every kind word comes from the table (or is one of the three built in). 568func mg_seen_add(seen: *u8, so: i64, w: *u8) -> i64 { 569 var p: i64 = 0 570 while p < so { 571 if mg_str_eq((seen as i64 + p) as *u8, w) == 1 { return so } 572 p = p + mg_slen((seen as i64 + p) as *u8) + 1 573 } 574 var k: i64 = 0 575 while w[k] != (0 as u8) { seen[so + k] = w[k]; k = k + 1 } 576 seen[so + k] = 0 as u8 577 return so + k + 1 578} 579 580// a DECLARATION whose NAME carries the mechanical placeholder: const <PFX>_MAGIC_<digits>. It is a literal wearing a name. 581// The name ends at the first colon, so a placeholder mentioned in a trailing comment is prose and is not counted. 582func mg_placeholder_decl(q: *u8, ls: i64, le: i64) -> i64 { 583 if mg_starts(q, ls, le, MG_CONST_KW) == 0 { return 0 } 584 var c: i64 = ls 585 var go: i64 = 1 586 while go == 1 { if c >= le { go = 0 } else { if (q[c] as i64) == MG_KD_COLON { go = 0 } else { c = c + 1 } } } 587 return mg_ctx_has(q, ls, c, MG_PLACEHOLDER) 588} 589func mg_placeholder_count(q: *u8, n: i64) -> i64 { 590 var k: i64 = 0 591 var i: i64 = 0 592 while i < n { 593 let le: i64 = mg_line_end(q, n, i) 594 k = k + mg_placeholder_decl(q, i, le) 595 i = le + 1 596 } 597 return k 598}