code wiki / (root) / nx_disctree_test.nx

nx_disctree_test.nx source

↩ module page · 132 lines · 6567 B

1// nx_disctree_test.nx -- discrimination tree smoke. 2 3import "nx_syscalls.nx" 4import "nx_runtime.nx" 5import "nx_tier.nx" 6import "nx_result.nx" 7import "nx_unify.nx" 8import "nx_disctree.nx" 9 10const SYM_A: nx_int = 100 11const SYM_B: nx_int = 101 12const SYM_F: nx_int = 200 13const SYM_G: nx_int = 201 14const SYM_H: nx_int = 250 15const VAR_X: nx_int = 0 16 17func mk_unary(sym: nx_int, child: *Term) -> *Term { 18 let buf: *Term = (sys_mmap(NX_TERM_BYTES as i64)) as *Term 19 buf.kind = child.kind; buf.sym = child.sym 20 buf.n_args = child.n_args; buf.args = child.args 21 return nx_term_app(sym, 1, buf) 22} 23 24func mk_binary(sym: nx_int, c0: *Term, c1: *Term) -> *Term { 25 let args: *Term = (sys_mmap((2 * NX_TERM_BYTES) as i64)) as *Term 26 let a0: *Term = args 27 a0.kind = c0.kind; a0.sym = c0.sym; a0.n_args = c0.n_args; a0.args = c0.args 28 let a1: *Term = ((args as nx_int) + NX_TERM_BYTES) as *Term 29 a1.kind = c1.kind; a1.sym = c1.sym; a1.n_args = c1.n_args; a1.args = c1.args 30 return nx_term_app(sym, 2, args) 31} 32 33func main() -> nx_exit { 34 println("=== Discrimination tree smoke ===" as *u8) 35 var fails: nx_int = 0 36 37 let res: *nx_int = (sys_mmap((NX_DT_MAX_RESULTS * 8) as i64)) as *nx_int 38 let n_res: *nx_int = sys_mmap(8) as *nx_int 39 40 // ---------- Test 1: empty tree returns nothing -------------- 41 let t1: *DiscTree = nx_dt_new() 42 nx_dt_find_generalizations(t1, nx_term_const(SYM_A), res, n_res) 43 print(" 1. empty tree -> n_results=" as *u8); print_i64(n_res[0]); println("" as *u8) 44 if n_res[0] == 0 { println(" PASS" as *u8) } 45 else { println(" FAIL" as *u8); fails = fails + 1 } 46 47 // ---------- Test 2: exact match ----------------------------- 48 // Insert f(a) with value 42; lookup f(a) -> [42] 49 let t2: *DiscTree = nx_dt_new() 50 nx_dt_insert(t2, mk_unary(SYM_F, nx_term_const(SYM_A)), 42) 51 nx_dt_find_generalizations(t2, mk_unary(SYM_F, nx_term_const(SYM_A)), res, n_res) 52 print(" 2. insert+lookup f(a) -> n=" as *u8); print_i64(n_res[0]) 53 print(" first=" as *u8); print_i64(res[0]); println("" as *u8) 54 if n_res[0] == 1 { 55 if res[0] == 42 { println(" PASS" as *u8) } 56 else { println(" wrong value FAIL" as *u8); fails = fails + 1 } 57 } else { println(" wrong count FAIL" as *u8); fails = fails + 1 } 58 59 // ---------- Test 3: wildcard matches constant --------------- 60 // Insert f(X) with value 7; lookup f(a) -> [7] 61 let t3: *DiscTree = nx_dt_new() 62 nx_dt_insert(t3, mk_unary(SYM_F, nx_term_var(VAR_X)), 7) 63 nx_dt_find_generalizations(t3, mk_unary(SYM_F, nx_term_const(SYM_A)), res, n_res) 64 print(" 3. insert f(X), lookup f(a) -> n=" as *u8); print_i64(n_res[0]); println("" as *u8) 65 if n_res[0] == 1 { 66 if res[0] == 7 { println(" wildcard matched constant PASS" as *u8) } 67 else { println(" wrong value FAIL" as *u8); fails = fails + 1 } 68 } else { println(" wrong count FAIL" as *u8); fails = fails + 1 } 69 70 // ---------- Test 4: wildcard skips multi-arg subterm -------- 71 // Insert f(X) with value 11; lookup f(g(b)) -> [11] 72 let t4: *DiscTree = nx_dt_new() 73 nx_dt_insert(t4, mk_unary(SYM_F, nx_term_var(VAR_X)), 11) 74 nx_dt_find_generalizations(t4, 75 mk_unary(SYM_F, mk_unary(SYM_G, nx_term_const(SYM_B))), res, n_res) 76 print(" 4. insert f(X), lookup f(g(b)) -> n=" as *u8); print_i64(n_res[0]); println("" as *u8) 77 if n_res[0] == 1 { 78 if res[0] == 11 { println(" wildcard skipped g(b) subterm PASS" as *u8) } 79 else { println(" wrong value FAIL" as *u8); fails = fails + 1 } 80 } else { println(" wrong count FAIL" as *u8); fails = fails + 1 } 81 82 // ---------- Test 5: head mismatch returns nothing ----------- 83 // Insert g(a); lookup f(a) -> 0 results 84 let t5: *DiscTree = nx_dt_new() 85 nx_dt_insert(t5, mk_unary(SYM_G, nx_term_const(SYM_A)), 5) 86 nx_dt_find_generalizations(t5, mk_unary(SYM_F, nx_term_const(SYM_A)), res, n_res) 87 print(" 5. insert g(a), lookup f(a) -> n=" as *u8); print_i64(n_res[0]); println("" as *u8) 88 if n_res[0] == 0 { println(" no match PASS" as *u8) } 89 else { println(" spurious match FAIL" as *u8); fails = fails + 1 } 90 91 // ---------- Test 6: multiple candidates --------------------- 92 // Insert f(X) with value 1, AND f(a) with value 2. 93 // Lookup f(a) -> 2 results (both match: f(X) via wildcard, f(a) exact) 94 let t6: *DiscTree = nx_dt_new() 95 nx_dt_insert(t6, mk_unary(SYM_F, nx_term_var(VAR_X)), 1) 96 nx_dt_insert(t6, mk_unary(SYM_F, nx_term_const(SYM_A)), 2) 97 nx_dt_find_generalizations(t6, mk_unary(SYM_F, nx_term_const(SYM_A)), res, n_res) 98 print(" 6. insert f(X)+f(a), lookup f(a) -> n=" as *u8); print_i64(n_res[0]); println("" as *u8) 99 if n_res[0] == 2 { println(" both matched PASS" as *u8) } 100 else { println(" wrong count FAIL" as *u8); fails = fails + 1 } 101 102 // ---------- Test 7: binary head wrong-arity rejected -------- 103 // Insert h(a, b); lookup h(a) -- query has different arity 104 // (treated as APP of h with 1 arg, so head-arity mismatch). 105 let t7: *DiscTree = nx_dt_new() 106 nx_dt_insert(t7, mk_binary(SYM_H, nx_term_const(SYM_A), nx_term_const(SYM_B)), 99) 107 nx_dt_find_generalizations(t7, mk_unary(SYM_H, nx_term_const(SYM_A)), res, n_res) 108 print(" 7. insert h(a,b), lookup h(a) [arity mismatch] -> n=" as *u8); print_i64(n_res[0]); println("" as *u8) 109 if n_res[0] == 0 { println(" arity mismatch rejected PASS" as *u8) } 110 else { println(" spurious match FAIL" as *u8); fails = fails + 1 } 111 112 // ---------- Test 8: nested wildcard scenario ----------------- 113 // Insert h(X, b); lookup h(g(a), b) -> [val] (X matches g(a)) 114 let t8: *DiscTree = nx_dt_new() 115 nx_dt_insert(t8, mk_binary(SYM_H, nx_term_var(VAR_X), nx_term_const(SYM_B)), 88) 116 nx_dt_find_generalizations(t8, 117 mk_binary(SYM_H, mk_unary(SYM_G, nx_term_const(SYM_A)), nx_term_const(SYM_B)), 118 res, n_res) 119 print(" 8. insert h(X,b), lookup h(g(a),b) -> n=" as *u8); print_i64(n_res[0]); println("" as *u8) 120 if n_res[0] == 1 { 121 if res[0] == 88 { println(" wildcard skipped g(a), matched b PASS" as *u8) } 122 else { println(" wrong value FAIL" as *u8); fails = fails + 1 } 123 } else { println(" wrong count FAIL" as *u8); fails = fails + 1 } 124 125 println("" as *u8) 126 if fails == 0 { 127 println("=== ALL 8 discrim-tree tests PASS ===" as *u8) 128 return 0 129 } 130 print("=== " as *u8); print_i64(fails); println(" tests FAILED ===" as *u8) 131 return 1 132}