code wiki / _hdl_build / nx_js_evalorder_gate.nx
nx_js_evalorder_gate.nx source
↩ module page · 49 lines · 3135 B
1import "nx_gate_gn.nx"
2// nx_js_evalorder_gate.nx -- JS-SPEC EVALUATION-ORDER + FLOAT-UNARY teeth (expectations pinned from V8 node
3// v22 on this box). Guards the two bugs that silently no-op'd Octane NavierStokes' fluid solver:
4// (1) assignment target base/index must evaluate ONCE, BEFORE the rhs (store slot uses the OLD index when
5// the rhs pre-increments it: `a[i] = 100 + a[++i]` stores into a[1], not a[2]);
6// compound `a[++i] -= e` increments i exactly once (read and write the SAME slot);
7// (2) unary -x / +x on a FLOAT stays float (-0.5 must NOT int-truncate to 0 -- it zeroed h in project()).
8// Both the tree-walker AND the VM/JIT must agree with V8. expect_exit: 0
9// license_tier: ORIGINAL
10import "nx_js_vm.nx"
11func gw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
12// run src on BOTH tiers; pass iff both rc=0 AND both equal `want` (V8-pinned).
13func chk2(label: *u8, src: *u8, want: i64) -> i64 {
14 let ov: *i64 = sys_mmap(16) as *i64
15 let ot: *i64 = sys_mmap(16) as *i64
16 let rv: i64 = compile_run(src, ov)
17 let rt: i64 = js_run_source(src, bsl(src), ot)
18 gw(" " as *u8); gw(label); gw(": vm=" as *u8); gn(ov[1]); gw(" tree=" as *u8); gn(ot[1]); gw(" want=" as *u8); gn(want)
19 if rv == 0 { if rt == 0 { if ov[0] == VAL_NUM { if ov[1] == want { if ot[1] == want { gw(" ok\n" as *u8); return 1 } } } } }
20 gw(" FAIL\n" as *u8)
21 return 0
22}
23func main(argc: i64, argv: *i64) -> i64 {
24 gw("=== nx_js_evalorder_gate: JS-spec assignment order + float unary (V8-pinned) ===\n" as *u8)
25 var pass: i64 = 0
26 var tot: i64 = 0
27 // (1a) plain assign: store index is the PRE-increment value
28 tot = tot + 1
29 pass = pass + chk2("store-index-before-rhs" as *u8, "var a=[10,20,30,40];var i=1;a[i]=100+a[++i];a[1]*10000+a[2]*10+i" as *u8, 1300302)
30 // (1b) compound assign: index evaluated ONCE
31 tot = tot + 1
32 pass = pass + chk2("compound-index-once" as *u8, "var a=[1,2,3,4];var i=0;a[++i]-=10;(a[1]+100)*1000+a[2]*10+i" as *u8, 92031)
33 // (1c) the exact NavierStokes lin_solve row shape (checksum of the row after 3 relaxed cells)
34 tot = tot + 1
35 pass = pass + chk2("linsolve-row-shape" as *u8, "var X=[0,1,2,3,4,0];var X0=[9,8,7,6,5,9];var cur=1;var lastX=X[cur];++cur;var ii=1;while(ii<=3){lastX=X[cur]=(X0[cur]+0.25*(lastX+X[++cur]+11+13))*0.5;ii=ii+1;}(X[2]*1000+X[1]*100+cur)|0" as *u8, 7105)
36 // (2a) unary minus on float
37 tot = tot + 1
38 pass = pass + chk2("neg-float" as *u8, "var f=1.5;var g=-f;(g*10)|0" as *u8, 0 - 15)
39 // (2b) the project() h formula that was zeroed
40 tot = tot + 1
41 pass = pass + chk2("neg-float-h" as *u8, "var h=-0.5/Math.sqrt(4*4);(h*1000)|0" as *u8, 0 - 125)
42 // (2c) unary plus passes floats through
43 tot = tot + 1
44 pass = pass + chk2("pos-float" as *u8, "var f=2.5;var g=+f;(g*10)|0" as *u8, 25)
45 gw(" --- " as *u8); gn(pass); gw("/" as *u8); gn(tot); gw(" ---\n" as *u8)
46 if pass == tot { gw("=== GREEN: assignment order + float unary match V8 on both tiers ===\n" as *u8); return 0 }
47 gw("=== RED ===\n" as *u8)
48 return 1
49}