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}