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}