code wiki / _hdl_build / nx_js_regex_gate.nx
nx_js_regex_gate.nx source
↩ module page · 81 lines · 6868 B
1import "nx_gate_gn.nx"
2import "nx_gate_base.nx"
3// nx_js_regex_gate.nx -- proves REGEX WORKS FROM JAVASCRIPT end-to-end: a regex literal /pat/flags lexes
4// (context-disambiguated), parses (ND_REGEX), evaluates to a VAL_REGEX (compiled via nx_rxfull), and its
5// methods run: re.test(str) -> bool, str.search(re) -> index. ABSOLUTE expected values (tree-walker; the VM
6// auto-declines ND_REGEX -> tree fallback, so this is the correctness oracle). license_tier: ORIGINAL expect_exit: 0
7import "nx_syscalls.nx"
8import "nx_js_eval.nx"
9
10func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
11" as *u8); return ok }
12func gsl(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
13
14// run `src` through the tree-walker; pass iff rc==0 AND result == [etag,epay].
15func rjs(src: *u8, etag: i64, epay: i64) -> i64 {
16 let out: *i64 = sys_mmap(16) as *i64
17 let rc: i64 = js_run_source(src, gsl(src), out)
18 if rc != 0 { return 0 }
19 if out[0] != etag { return 0 }
20 if out[1] != epay { return 0 }
21 return 1
22}
23
24// run `src`; pass iff rc==0 AND result is a STRING equal to `exp`.
25func rjs_str(src: *u8, exp: *u8) -> i64 {
26 let out: *i64 = sys_mmap(16) as *i64
27 if js_run_source(src, gsl(src), out) != 0 { return 0 }
28 if out[0] != VAL_STR { return 0 }
29 let srec: *i64 = (out[1]) as *i64
30 let sb: *u8 = ev_str_bytes(srec); let sl: i64 = ev_str_len(srec)
31 if sl != gsl(exp) { return 0 }
32 var i: i64 = 0
33 while i < sl { if sb[i] != exp[i] { return 0 } i = i + 1 }
34 return 1
35}
36
37func main() -> i64 {
38 gw("js-regex SOVEREIGN gate (regex literal -> VAL_REGEX -> re.test / str.search / match / replace)\n" as *u8)
39 var pass: i64 = 0
40 var ttl: i64 = 0
41
42 ttl=ttl+1; pass=pass+grow("X1 /ab+c/.test('xabbc') = true\x00" as *u8, rjs("var re=/ab+c/;re.test('xabbc')" as *u8, VAL_BOOL, 1))
43 ttl=ttl+1; pass=pass+grow("X2 /ab+c/.test('axc') = false\x00" as *u8, rjs("var re=/ab+c/;re.test('axc')" as *u8, VAL_BOOL, 0))
44 ttl=ttl+1; pass=pass+grow("X3 /[0-9]+/.test('abc123') = true\x00" as *u8, rjs("/[0-9]+/.test('abc123')" as *u8, VAL_BOOL, 1))
45 ttl=ttl+1; pass=pass+grow("X4 /^\\d+$/.test('456') = true\x00" as *u8, rjs("/^\\d+$/.test('456')" as *u8, VAL_BOOL, 1))
46 ttl=ttl+1; pass=pass+grow("X5 /^\\d+$/.test('45a') = false\x00" as *u8, rjs("/^\\d+$/.test('45a')" as *u8, VAL_BOOL, 0))
47 ttl=ttl+1; pass=pass+grow("X6 /foo/i.test('FOOBAR') = true (icase)\x00" as *u8, rjs("var re=/foo/i;re.test('FOOBAR')" as *u8, VAL_BOOL, 1))
48 ttl=ttl+1; pass=pass+grow("X7 /(a|b)+/.test('cccabx') = true (alt+group)\x00" as *u8, rjs("/(a|b)+/.test('cccabx')" as *u8, VAL_BOOL, 1))
49 ttl=ttl+1; pass=pass+grow("X8 /xyz/.test('cccabx') = false\x00" as *u8, rjs("/xyz/.test('cccabx')" as *u8, VAL_BOOL, 0))
50 ttl=ttl+1; pass=pass+grow("X9 'hello world'.search(/wor/) = 6\x00" as *u8, rjs("'hello world'.search(/wor/)" as *u8, VAL_NUM, 6))
51 ttl=ttl+1; pass=pass+grow("X10 'a1b2'.search(/[0-9]/) = 1\x00" as *u8, rjs("'a1b2'.search(/[0-9]/)" as *u8, VAL_NUM, 1))
52 ttl=ttl+1; pass=pass+grow("X11 'abc'.search(/z/) = -1\x00" as *u8, rjs("'abc'.search(/z/)" as *u8, VAL_NUM, 0-1))
53 ttl=ttl+1; pass=pass+grow("X12 'a / b' division still works (regex ctx safe)\x00" as *u8, rjs("var a=10;var b=2;a / b" as *u8, VAL_NUM, 5))
54 // --- .replace / .match (the workhorses) ---
55 ttl=ttl+1; pass=pass+grow("X13 replace global /[0-9]+/g -> 'aXbX'\x00" as *u8, rjs_str("'a12b34'.replace(/[0-9]+/g,'X')" as *u8, "aXbX\x00" as *u8))
56 ttl=ttl+1; pass=pass+grow("X14 replace non-global first only -> 'aXb34'\x00" as *u8, rjs_str("'a12b34'.replace(/[0-9]+/,'X')" as *u8, "aXb34\x00" as *u8))
57 ttl=ttl+1; pass=pass+grow("X15 replace groups '$3/$2/$1' date reformat\x00" as *u8, rjs_str("'2024-01-15'.replace(/(\\d+)-(\\d+)-(\\d+)/,'$3/$2/$1')" as *u8, "15/01/2024\x00" as *u8))
58 ttl=ttl+1; pass=pass+grow("X16 match(/[0-9]+/)[0] -> '12'\x00" as *u8, rjs_str("'a12b34'.match(/[0-9]+/)[0]" as *u8, "12\x00" as *u8))
59 ttl=ttl+1; pass=pass+grow("X17 match(/\\w+/g).length -> 3\x00" as *u8, rjs("'hello world foo'.match(/\\w+/g).length" as *u8, VAL_NUM, 3))
60 ttl=ttl+1; pass=pass+grow("X18 trim ^\\s+|\\s+$ global -> 'trim'\x00" as *u8, rjs_str("' trim '.replace(/^\\s+|\\s+$/g,'')" as *u8, "trim\x00" as *u8))
61 ttl=ttl+1; pass=pass+grow("X19 match(/z/) no match -> null\x00" as *u8, rjs("'no match'.match(/z/)" as *u8, VAL_NULL, 0))
62 ttl=ttl+1; pass=pass+grow("X20 replace $& whole-match wrap\x00" as *u8, rjs_str("'cat'.replace(/cat/,'[$&]')" as *u8, "[cat]\x00" as *u8))
63 // --- new RegExp(str,flags) + String.split(re) ---
64 ttl=ttl+1; pass=pass+grow("X21 new RegExp('[0-9]+').test('abc123') = true\x00" as *u8, rjs("new RegExp('[0-9]+').test('abc123')" as *u8, VAL_BOOL, 1))
65 ttl=ttl+1; pass=pass+grow("X22 new RegExp('a','i').test('XAY') = true (flag arg)\x00" as *u8, rjs("new RegExp('a','i').test('XAY')" as *u8, VAL_BOOL, 1))
66 ttl=ttl+1; pass=pass+grow("X23 new RegExp('[0-9]+','g') replace -> 'aXbXcX'\x00" as *u8, rjs_str("var re=new RegExp('[0-9]+','g');'a1b2c3'.replace(re,'X')" as *u8, "aXbXcX\x00" as *u8))
67 ttl=ttl+1; pass=pass+grow("X24 'a,b,c'.split(/,/).length = 3\x00" as *u8, rjs("'a,b,c'.split(/,/).length" as *u8, VAL_NUM, 3))
68 ttl=ttl+1; pass=pass+grow("X25 'a,b,c'.split(/,/)[1] = 'b'\x00" as *u8, rjs_str("'a,b,c'.split(/,/)[1]" as *u8, "b\x00" as *u8))
69 ttl=ttl+1; pass=pass+grow("X26 'one two three'.split(/\\s+/).length = 3\x00" as *u8, rjs("'one two three'.split(/\\s+/).length" as *u8, VAL_NUM, 3))
70 ttl=ttl+1; pass=pass+grow("X27 RegExp('a').test('bab') = true (no-new)\x00" as *u8, rjs("RegExp('a').test('bab')" as *u8, VAL_BOOL, 1))
71 ttl=ttl+1; pass=pass+grow("X28 'a,,b'.split(/,/).length = 3 (empty piece)\x00" as *u8, rjs("'a,,b'.split(/,/).length" as *u8, VAL_NUM, 3))
72 // --- re.exec + lastIndex: the while((m=re.exec(s))) idiom ---
73 ttl=ttl+1; pass=pass+grow("X29 while(m=re.exec) g-flag walks all -> '12,345,6,'\x00" as *u8, rjs_str("var re=/\\d+/g;var m;var out='';while(m=re.exec('a12b345c6')){out=out+m[0]+',';}out" as *u8, "12,345,6,\x00" as *u8))
74 ttl=ttl+1; pass=pass+grow("X30 /(\\d)(\\d)/.exec('x42')[2] = '2' (captures)\x00" as *u8, rjs_str("/(\\d)(\\d)/.exec('x42')[2]" as *u8, "2\x00" as *u8))
75 ttl=ttl+1; pass=pass+grow("X31 /z/.exec('abc') = null\x00" as *u8, rjs("/z/.exec('abc')" as *u8, VAL_NULL, 0))
76 ttl=ttl+1; pass=pass+grow("X32 exec-loop counts 3 matches\x00" as *u8, rjs("var re=/[a-z]/g;var m;var c=0;while(m=re.exec('a1b2c3')){c=c+1;}c" as *u8, VAL_NUM, 3))
77
78 gw("pass=" as *u8); gn(pass); gw("/" as *u8); gn(ttl); gw("\n" as *u8)
79 if pass == ttl { gw("verdict=GREEN (regex runs from JS: literal->VAL_REGEX->test/search, division unbroken)\n" as *u8); sys_exit(0); return 0 }
80 gw("verdict=RED\n" as *u8); sys_exit(1); return 1
81}