code wiki / _hdl_build / nx_xlsx_pivot_gate.nx

nx_xlsx_pivot_gate.nx source

↩ module page · 169 lines · 9455 B

1// nx_xlsx_pivot_gate.nx -- gate for PIVOT v1 (office census OF-S5, native-first): group-by aggregation over 2// the RESOLVED sheet (formula cells participate at computed values), SUM/COUNT/AVG + TOTAL, and pivothtml = 3// the standard 0-JS preview (pivot table + auto bar chart of Sum per group). In-file pivotTable parts + 4// drag-drop UI = named follow-ups, NOT claimed. 5// Rows: 1 pivot-pins 2 formula-values-pivot 3 pivothtml(table+chart pins) 4 neg-bad-column 5 neg-no-numeric 6// 6 outputs-0js+determinism 7 loud-fail-missing[neg]. license_tier: ORIGINAL 7import "nx_syscalls.nx" 8import "nx_gate_verdict.nx" 9 10func vg_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8) { n=n+1 } return n } 11func vg_p(s: *u8) -> i64 { sys_write(1, s, vg_slen(s)); return 0 } 12func vg_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8) { dst[off+i]=s[i]; i=i+1 } return off+i } 13func vg_catn(dst: *u8, off: i64, v: i64) -> i64 { 14 var o: i64=off; var m: i64=v; if m<0 { dst[o]=45 as u8; o=o+1; m=0-m } 15 let t: *u8=sys_mmap(28); var k: i64=0; if m==0 { t[0]=48 as u8; k=1 } 16 while m>0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } 17 var i: i64=0; while i<k { dst[o+i]=t[k-1-i]; i=i+1 } return o+k 18} 19func vg_write(path: *u8, content: *u8) -> i64 { 20 let fd: i64=sys_openat_wr(path, 0x1a4); if fd<0 { return 0-1 } 21 sys_write(fd, content, vg_slen(content)); sys_close(fd); return 0 22} 23func vg_readall(path: *u8, szout: *i64) -> *u8 { 24 let fd: i64=sys_openat_rd(path); if fd<0 { szout[0]=0-1; return 0 as *u8 } 25 let buf: *u8=sys_mmap(4194304); var got: i64=0; var n: i64=1 26 while n>0 { n=sys_read(fd,(buf as i64+got) as *u8,131072); if n>0 { got=got+n } } 27 sys_close(fd); szout[0]=got; return buf 28} 29func vg_runv(elf: *u8, args: *i64, outpath: *u8) -> i64 { 30 let pid: i64=sys_fork() 31 if pid==0 { 32 if (outpath as i64)!=0 { let ofd: i64=sys_openat_wr(outpath,0x1a4); if ofd>=0 { sys_dup3(ofd,1,0); sys_dup3(ofd,2,0) } } 33 let argv: *i64=sys_mmap(128) as *i64 34 argv[0]=elf as i64; var i: i64=0; var go: i64=1 35 while go==1 { if args[i]==0 { go=0 } else { argv[i+1]=args[i]; i=i+1 } } 36 argv[i+1]=0 37 let envp: *i64=sys_mmap(16) as *i64; envp[0]=0 38 sys_execve(elf, argv, envp); sys_exit(127) 39 } 40 let st: *i64=sys_mmap(16) as *i64; sys_wait4(pid, st, 0) 41 let sig: i64=st[0]&0x7f; if sig!=0 { return 128+sig } 42 return (st[0]>>8)&0xff 43} 44func vg_has(path: *u8, needle: *u8) -> i64 { 45 let szp: *i64=sys_mmap(16) as *i64; let b: *u8=vg_readall(path, szp); let sz: i64=szp[0] 46 let n: i64=vg_slen(needle); if sz<n { return 0 } 47 var i: i64=0 48 while i+n<=sz { var ok: i64=1; var j: i64=0; while j<n { if b[i+j]!=needle[j] { ok=0; j=n } else { j=j+1 } } if ok==1 { return 1 } i=i+1 } 49 return 0 50} 51func vg_fileeq(p1: *u8, p2: *u8) -> i64 { 52 let s1: *i64=sys_mmap(16) as *i64 53 let s2: *i64=sys_mmap(16) as *i64 54 let b1: *u8=vg_readall(p1, s1) 55 let b2: *u8=vg_readall(p2, s2) 56 if s1[0] != s2[0] { return 0 } 57 if s1[0]<=0 { return 0 } 58 var i: i64=0 59 while i<s1[0] { if b1[i] != b2[i] { return 0 } i=i+1 } 60 return 1 61} 62func vg_args6(a1: *u8, a2: *u8, a3: *u8, a4: *u8, a5: *u8, a6: *u8) -> *i64 { 63 let a: *i64=sys_mmap(64) as *i64 64 a[0]=a1 as i64; a[1]=a2 as i64; a[2]=a3 as i64; a[3]=a4 as i64; a[4]=a5 as i64; a[5]=a6 as i64; a[6]=0 65 return a 66} 67func vg_row(name: *u8, pass: i64) -> i64 { 68 vg_p("ROW " as *u8); vg_p(name); if pass==1 { vg_p(" PASS\n" as *u8) } else { vg_p(" FAIL\n" as *u8) } return pass 69} 70 71func main(argc: i64, argv: *i64) -> i64 { 72 vg_p("=== XLSX PIVOT GATE (OF-S5 native-first): group-by SUM/COUNT/AVG + TOTAL over the resolved sheet; pivothtml w/ chart ===\n" as *u8) 73 let xl: *u8="buildroot/_build/nx_xlsx.sov.elf" as *u8 74 let pr: i64=sys_openat_rd(xl) 75 if pr>=0 { sys_close(pr) } else { 76 vg_p(" instrument missing -> rebuilding\n" as *u8) 77 vg_runv("_offc/nx_sov_build_run.elf" as *u8, vg_args6("nx_xlsx" as *u8, "--build-only" as *u8, 0 as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vg_rebuild.out" as *u8) 78 } 79 80 vg_write("/tmp/vg_exp.tsv" as *u8, "Item\x09Owner\x09Amount\nVenue\x09Alice\x09350\nCatering\x09Bob\x09480.25\nPhotos\x09Carol\x09300\nDecor\x09Alice\x09120\nMusic\x09Bob\x09200\n" as *u8) 81 vg_runv(xl, vg_args6("fromtsv" as *u8, "/tmp/vg_exp.tsv" as *u8, "/tmp/vg_exp.xlsx" as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vg_w.txt" as *u8) 82 83 var pass: i64=0 84 var r: i64=0 85 86 // row 1: pivot by Owner(B) over Amount(C) -- pinned sums/counts/avgs + TOTAL 87 let rc1: i64=vg_runv(xl, vg_args6("pivot" as *u8, "/tmp/vg_exp.xlsx" as *u8, "B" as *u8, "C" as *u8, 0 as *u8, 0 as *u8), "/tmp/vg_r1.txt" as *u8) 88 r=0 89 if rc1==0 { if vg_has("/tmp/vg_r1.txt" as *u8, "Alice\x09470\x092\x09235" as *u8)==1 { 90 if vg_has("/tmp/vg_r1.txt" as *u8, "Bob\x09680.25\x092\x09340.125" as *u8)==1 { 91 if vg_has("/tmp/vg_r1.txt" as *u8, "Carol\x09300\x091\x09300" as *u8)==1 { 92 if vg_has("/tmp/vg_r1.txt" as *u8, "TOTAL\x091450.25\x095\x09290.05" as *u8)==1 { r=1 } 93 } 94 } 95 } } 96 pass=pass+vg_row("pivot-pins" as *u8, r) 97 98 // row 2: FORMULA cells pivot at their computed values 99 vg_write("/tmp/vg_f.tsv" as *u8, "K\x09G\x09V\nx\x09Alice\x09=100+25\ny\x09Bob\x09=2*50\n" as *u8) 100 vg_runv(xl, vg_args6("fromtsv" as *u8, "/tmp/vg_f.tsv" as *u8, "/tmp/vg_f.xlsx" as *u8, 0 as *u8, 0 as *u8, 0 as *u8), "/tmp/vg_w2.txt" as *u8) 101 let rc2: i64=vg_runv(xl, vg_args6("pivot" as *u8, "/tmp/vg_f.xlsx" as *u8, "B" as *u8, "C" as *u8, 0 as *u8, 0 as *u8), "/tmp/vg_r2.txt" as *u8) 102 r=0 103 if rc2==0 { if vg_has("/tmp/vg_r2.txt" as *u8, "Alice\x09125\x091\x09125" as *u8)==1 { 104 if vg_has("/tmp/vg_r2.txt" as *u8, "TOTAL\x09225\x092\x09112.5" as *u8)==1 { r=1 } 105 } } 106 pass=pass+vg_row("formula-values-pivot" as *u8, r) 107 108 // row 3: pivothtml = pivot table + auto chart (Sum column; TOTAL is the 100% bar, Alice 470/1450.25 = 32%) 109 let rc3: i64=vg_runv(xl, vg_args6("pivothtml" as *u8, "/tmp/vg_exp.xlsx" as *u8, "B" as *u8, "C" as *u8, "/tmp/vg_p.html" as *u8, "/sample.xlsx" as *u8), "/tmp/vg_r3.txt" as *u8) 110 r=0 111 if rc3==0 { if vg_has("/tmp/vg_p.html" as *u8, "<th>Group</th>" as *u8)==1 { 112 if vg_has("/tmp/vg_p.html" as *u8, "<td>340.125</td>" as *u8)==1 { 113 if vg_has("/tmp/vg_p.html" as *u8, "style=\"width:32%\">470</div>" as *u8)==1 { 114 if vg_has("/tmp/vg_p.html" as *u8, "style=\"width:100%\">1450.25</div>" as *u8)==1 { r=1 } 115 } 116 } 117 } } 118 pass=pass+vg_row("pivothtml-table-chart" as *u8, r) 119 120 // row 4 (neg): bad column letter loud-fails 121 let rc4: i64=vg_runv(xl, vg_args6("pivot" as *u8, "/tmp/vg_exp.xlsx" as *u8, "7" as *u8, "C" as *u8, 0 as *u8, 0 as *u8), "/tmp/vg_r4.txt" as *u8) 122 r=0 123 if rc4==1 { if vg_has("/tmp/vg_r4.txt" as *u8, "XLSX-PIVOT-FAIL bad-group-column" as *u8)==1 { r=1 } } 124 pass=pass+vg_row("neg-bad-column" as *u8, r) 125 126 // row 5 (neg): pivoting a TEXT value column loud-fails (no numeric rows) 127 let rc5: i64=vg_runv(xl, vg_args6("pivot" as *u8, "/tmp/vg_exp.xlsx" as *u8, "B" as *u8, "A" as *u8, 0 as *u8, 0 as *u8), "/tmp/vg_r5.txt" as *u8) 128 r=0 129 if rc5==1 { if vg_has("/tmp/vg_r5.txt" as *u8, "XLSX-PIVOT-FAIL no-numeric-rows" as *u8)==1 { r=1 } } 130 pass=pass+vg_row("neg-no-numeric" as *u8, r) 131 132 // row 6: 0-JS + determinism 133 vg_runv(xl, vg_args6("pivothtml" as *u8, "/tmp/vg_exp.xlsx" as *u8, "B" as *u8, "C" as *u8, "/tmp/vg_p2.html" as *u8, "/sample.xlsx" as *u8), "/tmp/vg_r6.txt" as *u8) 134 r=0 135 if vg_has("/tmp/vg_p.html" as *u8, "<script" as *u8)==0 { if vg_fileeq("/tmp/vg_p.html" as *u8, "/tmp/vg_p2.html" as *u8)==1 { r=1 } } 136 pass=pass+vg_row("0js-determinism" as *u8, r) 137 138 // row 7 (neg): missing workbook loud-fails 139 let rc7: i64=vg_runv(xl, vg_args6("pivot" as *u8, "/tmp/vg_nope.xlsx" as *u8, "B" as *u8, "C" as *u8, 0 as *u8, 0 as *u8), "/tmp/vg_r7.txt" as *u8) 140 r=0 141 if rc7==1 { if vg_has("/tmp/vg_r7.txt" as *u8, "XLSX-PIVOT-FAIL cannot-read" as *u8)==1 { r=1 } } 142 pass=pass+vg_row("loud-fail-missing" as *u8, r) 143 144 let permil: i64=(pass*1000)/7 145 let logfd: i64=sys_openat_append("knowledge/status/vizsla_gate.log" as *u8, 0x1a4) 146 var fdi: i64=0 147 while fdi<2 { 148 var fd: i64=1; if fdi==1 { fd=logfd } 149 if fd>0 { 150 let line: *u8=sys_mmap(256); var o: i64=0 151 o=vg_cat(line,o,"XLSX-PIVOT-GATE epoch=" as *u8); o=vg_catn(line,o,sys_now_realtime_sec()) 152 o=vg_cat(line,o," rows=7 pass=" as *u8); o=vg_catn(line,o,pass) 153 o=vg_cat(line,o," permil=" as *u8); o=vg_catn(line,o,permil) 154 if pass==7 { o=vg_cat(line,o," verdict=GREEN\n" as *u8) } else { o=vg_cat(line,o," verdict=RED\n" as *u8) } 155 sys_write(fd, line, o) 156 } 157 fdi=fdi+1 158 } 159 if logfd>0 { sys_close(logfd) } 160 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 161 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 162 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 163 let ctr__dry: *i64 = gv_ctr() 164 ctr__dry[0] = pass 165 ctr__dry[1] = 7 166 let rc__dry: i64 = gv_verdict("XLSX-PIVOT-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 167 sys_exit(rc__dry) 168 return rc__dry 169}