code wiki / _hdl_build / nx_flip_lib.nx

nx_flip_lib.nx source

↩ module page · 244 lines · 8397 B

1// nx_flip_lib.nx -- THE BASE for the FlipOrgan family (rule #6 OO base, rule #15 DRY, rule #22). 2// 3// NishiLang has no classes, so the base-class contract is expressed as a shared library every organ 4// in the family imports and specialises. Before this, nx_flip_score / _real / _defl / _worklist / 5// _gate each carried their OWN copy of the SAME ~17 primitives under a private prefix (fl_ fr_ fd_ 6// fw_ fg_) -- five copies of column parsing, five of integer printing, five of the line-scan idiom. 7// A fix to any one of them fixed only one organ. That does not scale and it is how the family drifts. 8// 9// THE FAMILY CONTRACT every FlipOrgan honours (enforced by nx_flip_gate, 16 cases): 10// 1. summary + `verdict=` FIRST, detail buffered and flushed last (nx_plan_run caps snippets at 200B) 11// 2. FAIL-CLOSED on absent input -- an absent finding/component/observation is a FINDING, not a neutral 12// 3. every threshold read from a plane, never a literal in code (rule #11) 13// 4. integer-only arithmetic, basis points for ratios (no-float substrate) 14// 5. a `verdict=` anchor so the ecosystem judge can read the result (D001) 15// 16// TAB-separated, newline-terminated plane rows are the ONE wire format (rule: planes > tsv). 17// license_tier: ORIGINAL No hw writes (Rule 26). 18import "nx_store_seed_lib.nx" 19import "nx_seg_store.nx" 20import "nx_syscalls.nx" 21 22const FX_TAB: i64 = 9 23const FX_NL: i64 = 10 24const FX_MINUS: i64 = 45 25const FX_D0: i64 = 48 26const FX_D9: i64 = 57 27const FX_BPS: i64 = 10000 28const FX_BUF: i64 = 262144 29const FX_OUT: i64 = 1 30const FX_SCRATCH: i64 = 32 31const FX_PFXCAP: i64 = 256 32const FX_NUMCAP: i64 = 40 33const FX_TMPCAP: i64 = 32 34const FX_BASE10: i64 = 10 35const FX_EXIT_USAGE: i64 = 2 36const FX_EXIT_REFUSED: i64 = 4 37 38// ---- output ---- 39func fx_puts(s: *u8) -> i64 { 40 var n: i64 = 0 41 while s[n] != (0 as u8) { n = n + 1 } 42 return sys_write(FX_OUT, s, n) 43} 44func fx_putn(n: i64) -> i64 { 45 if n == 0 { return sys_write(FX_OUT, "0" as *u8, 1) } 46 var x: i64 = n 47 var neg: i64 = 0 48 if n < 0 { neg = 1; x = 0 - n } 49 let tmp: *u8 = sts_mm(FX_TMPCAP) 50 var t: i64 = 0 51 while x > 0 { tmp[t] = (FX_D0 + (x % FX_BASE10)) as u8; t = t + 1; x = x / FX_BASE10 } 52 let out: *u8 = sts_mm(FX_NUMCAP) 53 var i: i64 = 0 54 if neg == 1 { out[0] = FX_MINUS as u8; i = 1 } 55 var k: i64 = t - 1 56 while k >= 0 { out[i] = tmp[k]; i = i + 1; k = k - 1 } 57 return sys_write(FX_OUT, out, i) 58} 59func fx_kv(k: *u8, v: i64) -> i64 { 60 fx_puts(k) 61 fx_puts("=" as *u8) 62 fx_putn(v) 63 fx_puts("\n" as *u8) 64 return 0 65} 66func fx_putslice(b: *u8, a: i64, e: i64) -> i64 { 67 let base: i64 = b as i64 68 return sys_write(FX_OUT, (base + a) as *u8, e - a) 69} 70 71// ---- buffered detail (contract rule 1: verdict first, detail last) ---- 72func fx_bcat(b: *u8, o: i64, s: *u8) -> i64 { 73 var i: i64 = 0 74 var oo: i64 = o 75 while s[i] != (0 as u8) { b[oo] = s[i]; oo = oo + 1; i = i + 1 } 76 return oo 77} 78func fx_bcatn(b: *u8, o: i64, n: i64) -> i64 { 79 var oo: i64 = o 80 if n == 0 { b[oo] = FX_D0 as u8; return oo + 1 } 81 var x: i64 = n 82 if n < 0 { b[oo] = FX_MINUS as u8; oo = oo + 1; x = 0 - n } 83 let tmp: *u8 = sts_mm(FX_TMPCAP) 84 var t: i64 = 0 85 while x > 0 { tmp[t] = (FX_D0 + (x % FX_BASE10)) as u8; t = t + 1; x = x / FX_BASE10 } 86 var k: i64 = t - 1 87 while k >= 0 { b[oo] = tmp[k]; oo = oo + 1; k = k - 1 } 88 return oo 89} 90func fx_bcatsl(b: *u8, o: i64, src: *u8, a: i64, e: i64) -> i64 { 91 var oo: i64 = o 92 var i: i64 = a 93 while i < e { b[oo] = src[i]; oo = oo + 1; i = i + 1 } 94 return oo 95} 96 97// ---- parsing ---- 98func fx_atoi(s: *u8) -> i64 { 99 var i: i64 = 0 100 var neg: i64 = 0 101 if s[0] == (FX_MINUS as u8) { neg = 1; i = 1 } 102 var v: i64 = 0 103 var go: i64 = 1 104 while go == 1 { 105 let c: i64 = s[i] as i64 106 if c < FX_D0 { go = 0 } 107 if c > FX_D9 { go = 0 } 108 if go == 1 { v = v * FX_BASE10 + (c - FX_D0); i = i + 1 } 109 } 110 if neg == 1 { return 0 - v } 111 return v 112} 113// END of the line starting at `i` in b[0..n) -- the scan idiom that was copy-pasted everywhere 114func fx_line_end(b: *u8, n: i64, i: i64) -> i64 { 115 var le: i64 = i 116 var s: i64 = 1 117 while s == 1 { 118 if le >= n { s = 0 } else { if b[le] == (FX_NL as u8) { s = 0 } else { le = le + 1 } } 119 } 120 return le 121} 122func fx_col(b: *u8, ls: i64, le: i64, idx: i64, out: *i64) -> i64 { 123 var c: i64 = 0 124 var p: i64 = ls 125 var found: i64 = 0 126 var go: i64 = 1 127 while go == 1 { 128 var e: i64 = p 129 var s: i64 = 1 130 while s == 1 { 131 if e >= le { s = 0 } else { if b[e] == (FX_TAB as u8) { s = 0 } else { e = e + 1 } } 132 } 133 if c == idx { out[0] = p; out[1] = e; found = 1; go = 0 } 134 if go == 1 { 135 if e >= le { go = 0 } else { p = e + 1; c = c + 1 } 136 } 137 } 138 return found 139} 140func fx_slice_atoi(b: *u8, a: i64, e: i64) -> i64 { 141 var v: i64 = 0 142 var neg: i64 = 0 143 var i: i64 = a 144 if i < e { if b[i] == (FX_MINUS as u8) { neg = 1; i = i + 1 } } 145 var go: i64 = 1 146 while i < e { 147 if go == 1 { 148 let c: i64 = b[i] as i64 149 if c >= FX_D0 { 150 if c <= FX_D9 { v = v * FX_BASE10 + (c - FX_D0) } else { go = 0 } 151 } else { go = 0 } 152 } 153 i = i + 1 154 } 155 if neg == 1 { return 0 - v } 156 return v 157} 158func fx_col_atoi(b: *u8, ls: i64, le: i64, idx: i64, sp: *i64) -> i64 { 159 if fx_col(b, ls, le, idx, sp) == 0 { return 0 } 160 return fx_slice_atoi(b, sp[0], sp[1]) 161} 162func fx_slice_eqs(b: *u8, a: i64, e: i64, s: *u8) -> i64 { 163 var n: i64 = 0 164 while s[n] != (0 as u8) { n = n + 1 } 165 if e - a != n { return 0 } 166 var i: i64 = 0 167 while i < n { if b[a+i] != s[i] { return 0 } i = i + 1 } 168 return 1 169} 170func fx_slice_eq(a: *u8, a0: i64, a1: i64, b: *u8, b0: i64, b1: i64) -> i64 { 171 let n: i64 = a1 - a0 172 if b1 - b0 != n { return 0 } 173 var i: i64 = 0 174 while i < n { if a[a0+i] != b[b0+i] { return 0 } i = i + 1 } 175 return 1 176} 177 178// ---- plane row lookup ---- 179func fx_row_by_id(b: *u8, n: i64, key: *u8, out: *i64, sp: *i64) -> i64 { 180 var i: i64 = 0 181 var found: i64 = 0 182 while i < n { 183 let le: i64 = fx_line_end(b, n, i) 184 if le > i { if found == 0 { 185 if fx_col(b, i, le, 0, sp) == 1 { 186 if fx_slice_eqs(b, sp[0], sp[1], key) == 1 { out[0] = i; out[1] = le; found = 1 } 187 } 188 } } 189 i = le + 1 190 } 191 return found 192} 193func fx_row_by_slice(b: *u8, n: i64, kb: *u8, k0: i64, k1: i64, out: *i64, sp: *i64) -> i64 { 194 var i: i64 = 0 195 var found: i64 = 0 196 while i < n { 197 let le: i64 = fx_line_end(b, n, i) 198 if le > i { if found == 0 { 199 if fx_col(b, i, le, 0, sp) == 1 { 200 if fx_slice_eq(b, sp[0], sp[1], kb, k0, k1) == 1 { out[0] = i; out[1] = le; found = 1 } 201 } 202 } } 203 i = le + 1 204 } 205 return found 206} 207// COVERAGE (contract rule 2): does a finding exist for (deal, component)? Someone who never LOOKED at 208// a mandatory system must not be scored as if that system were fine. 209func fx_has_finding(bf: *u8, nf: i64, deal: *u8, dealcol: i64, compcol: i64, kb: *u8, k0: i64, k1: i64, sp: *i64) -> i64 { 210 var i: i64 = 0 211 var found: i64 = 0 212 while i < nf { 213 let le: i64 = fx_line_end(bf, nf, i) 214 if le > i { if found == 0 { 215 if fx_col(bf, i, le, dealcol, sp) == 1 { 216 if fx_slice_eqs(bf, sp[0], sp[1], deal) == 1 { 217 if fx_col(bf, i, le, compcol, sp) == 1 { 218 if fx_slice_eq(bf, sp[0], sp[1], kb, k0, k1) == 1 { found = 1 } 219 } 220 } 221 } 222 } } 223 i = le + 1 224 } 225 return found 226} 227 228// ---- plane prefix composition (rule #17: the prefix root is a PARAMETER, never baked) ---- 229func fx_cat2(root: *u8, tail: *u8) -> *u8 { 230 let out: *u8 = sts_mm(FX_PFXCAP) 231 var o: i64 = 0 232 var i: i64 = 0 233 while root[i] != (0 as u8) { out[o] = root[i]; o = o + 1; i = i + 1 } 234 i = 0 235 while tail[i] != (0 as u8) { out[o] = tail[i]; o = o + 1; i = i + 1 } 236 out[o] = 0 as u8 237 return out 238} 239// load a plane into a fresh buffer; nout[0] = bytes. Returns the buffer. 240func fx_plane(root: *u8, tail: *u8, nout: *i64) -> *u8 { 241 let b: *u8 = sts_mm(FX_BUF) 242 nout[0] = sts_load(fx_cat2(root, tail), b, FX_BUF) 243 return b 244}