1use crate::{
4 heap::heap::{Cell, Heap, Tag},
5 program::clause::BitFlag64,
6 resolution::unification::Substitution,
7};
8
9pub fn re_build_bound_arg_terms(heap: &mut impl Heap, substitution: &mut Substitution) {
13 for i in 0..substitution.len() {
14 if let (_, bound_addr, true) = substitution[i] {
15 if heap.contains_args(bound_addr) {
16 let new_bound_addr = build(heap, substitution, None, bound_addr);
19 substitution[i].1 = new_bound_addr;
20 }
21 }
22 }
23}
24
25pub fn build(
30 heap: &mut impl Heap,
31 substitution: &mut Substitution,
32 meta_vars: Option<BitFlag64>,
33 src_addr: usize,
34) -> usize {
35 match heap[heap.deref_addr(src_addr)] {
36 (tag @ (Tag::Con | Tag::Flt | Tag::Int | Tag::Stri | Tag::ELis | Tag::Ref), value) => {
37 heap.heap_push((tag, value))
38 }
39 (Tag::Arg, _arg_id) => build_arg(heap, substitution, meta_vars, src_addr),
40 (Tag::Func | Tag::Tup | Tag::Set, _) => build_str(heap, substitution, meta_vars, src_addr),
41 (Tag::Lis, ptr) => {
42 let new_ptr = build_list(heap, substitution, meta_vars, ptr);
43 heap.heap_push((Tag::Lis, new_ptr))
44 }
45 cell => unimplemented!("build: unhandled cell type {cell:?}"),
46 }
47}
48
49fn build_arg(
50 heap: &mut impl Heap,
51 substitution: &mut Substitution,
52 meta_vars: Option<BitFlag64>,
53 src_addr: usize,
54) -> usize {
55 let arg_id = heap[src_addr].1;
56 match meta_vars {
57 Some(bit_flags) if !bit_flags.get(arg_id) => heap.heap_push(heap[src_addr]),
58 _ => match substitution.get_arg(arg_id) {
59 Some(bound_addr) => heap.set_ref(Some(bound_addr)),
60 None => {
61 let ref_addr = heap.set_ref(None);
62 substitution.set_arg(arg_id, ref_addr);
63 ref_addr
64 }
65 },
66 }
67}
68
69fn build_str(
70 heap: &mut impl Heap,
71 substitution: &mut Substitution,
72 meta_vars: Option<BitFlag64>,
73 src_addr: usize,
74) -> usize {
75 let (tag, length) = heap[src_addr];
76 let mut complex_terms: Vec<Option<Cell>> = Vec::with_capacity(length);
77 for i in 1..length + 1 {
78 complex_terms.push(build_complex_term(
79 heap,
80 substitution,
81 meta_vars,
82 src_addr + i,
83 ));
84 }
85 let addr = heap.heap_push((tag, length));
86 let mut i = 1;
87 for complex_term in complex_terms {
88 match complex_term {
89 Some(cell) => heap.heap_push(cell),
90 None => build(heap, substitution, meta_vars, src_addr + i),
91 };
92 i += 1;
93 }
94
95 addr
96}
97
98fn build_list(
99 heap: &mut impl Heap,
100 substitution: &mut Substitution,
101 meta_vars: Option<BitFlag64>,
102 src_addr: usize,
103) -> usize {
104 let head = build_complex_term(heap, substitution, meta_vars, src_addr);
105 let tail = build_complex_term(heap, substitution, meta_vars, src_addr + 1);
106 let ptr = match head {
107 Some(cell) => heap.heap_push(cell),
108 None => build(heap, substitution, meta_vars, src_addr),
109 };
110 match tail {
111 Some(cell) => heap.heap_push(cell),
112 None => build(heap, substitution, meta_vars, src_addr + 1),
113 };
114 ptr
115}
116
117fn build_complex_term(
118 heap: &mut impl Heap,
119 substitution: &mut Substitution,
120 meta_vars: Option<BitFlag64>,
121 src_addr: usize,
122) -> Option<Cell> {
123 match heap[heap.deref_addr(src_addr)] {
124 (Tag::Func | Tag::Tup | Tag::Set, _) => {
125 Some((Tag::Str, build_str(heap, substitution, meta_vars, src_addr)))
126 }
127 (Tag::Str, ptr) => Some((Tag::Str, build_str(heap, substitution, meta_vars, ptr))),
128 (Tag::Lis, ptr) => Some((Tag::Lis, build_list(heap, substitution, meta_vars, ptr))),
129 (Tag::Arg, id) => match meta_vars {
130 Some(bitflags) if !bitflags.get(id) => None,
131 _ => match substitution.get_arg(id) {
132 Some(addr) => build_complex_term(heap, substitution, meta_vars, addr),
133 None => None,
134 },
135 },
136 (Tag::Ref, ref_addr) if ref_addr == src_addr => {
137 if let Some(bound_addr) = substitution.bound(ref_addr) {
138 build_complex_term(heap, substitution, meta_vars, bound_addr)
139 } else {
140 None
141 }
142 }
143 _ => None,
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use crate::{
150 heap::{
151 heap::{Heap, Tag},
152 symbol_db::SymbolDB,
153 },
154 program::clause::BitFlag64,
155 resolution::{
156 build::{build, re_build_bound_arg_terms},
157 unification::{unify, Substitution},
158 },
159 };
160
161 #[test]
162 fn args() {
163 let p = SymbolDB::set_const("p".into());
164 let f = SymbolDB::set_const("f".into());
165
166 let mut heap = vec![
167 (Tag::Func, 4),
168 (Tag::Con, p),
169 (Tag::Arg, 0),
170 (Tag::Arg, 0),
171 (Tag::Arg, 1),
172 ];
173 let mut substitution = Substitution::default();
174 let addr = build(&mut heap, &mut substitution, None, 0);
175 assert_eq!(
176 heap[addr..(addr + 4)],
177 [
178 (Tag::Func, 4),
179 (Tag::Con, p),
180 (Tag::Ref, addr + 2),
181 (Tag::Ref, addr + 2),
182 ]
183 );
184
185 let mut substitution = Substitution::default();
186 let mut meta_vars = BitFlag64::default();
187 meta_vars.set(0);
188 let addr = build(&mut heap, &mut substitution, Some(meta_vars), 0);
189 heap._print_heap();
190 assert_eq!(
191 heap[addr..(addr + 5)],
192 [
193 (Tag::Func, 4),
194 (Tag::Con, p),
195 (Tag::Ref, addr + 2),
196 (Tag::Ref, addr + 2),
197 (Tag::Arg, 1)
198 ]
199 );
200
201 heap = vec![
202 (Tag::Func, 2),
203 (Tag::Con, f),
204 (Tag::Ref, 2),
205 (Tag::Func, 2),
206 (Tag::Con, p),
207 (Tag::Arg, 0),
208 ];
209 substitution = Substitution::default();
210 substitution.set_arg(0, 0);
211 let addr = build(&mut heap, &mut substitution, None, 3);
212 assert_eq!(
213 heap[addr - 3..(addr + 3)],
214 [
215 (Tag::Func, 2),
216 (Tag::Con, f),
217 (Tag::Ref, 2),
218 (Tag::Func, 2),
219 (Tag::Con, p),
220 (Tag::Str, addr - 3),
221 ]
222 );
223 }
224
225 #[test]
226 fn lists() {
227 let p = SymbolDB::set_const("p".into());
228 let a = SymbolDB::set_const("a".into());
229 let b = SymbolDB::set_const("b".into());
230 let c = SymbolDB::set_const("c".into());
231
232 let mut heap = vec![
233 (Tag::Con, a), (Tag::Lis, 2), (Tag::Con, b), (Tag::Arg, 0), (Tag::Func, 2), (Tag::Con, p), (Tag::Lis, 0), (Tag::Con, a), (Tag::Lis, 9), (Tag::Con, b), (Tag::Lis, 11), (Tag::Con, c), (Tag::ELis, 0), (Tag::Func, 2), (Tag::Con, p), (Tag::Lis, 7), ];
250 let mut substitution = Substitution::default();
251 substitution.set_arg(0, 10);
252 let addr = build(&mut heap, &mut substitution, None, 4);
253 assert_eq!(heap.term_string(addr), "p([a,b,c])");
254
255 let mut heap = vec![
256 (Tag::Con, a), (Tag::Lis, 2), (Tag::Con, b), (Tag::Ref, 3), (Tag::Func, 2), (Tag::Con, p), (Tag::Lis, 0), (Tag::Con, a), (Tag::Lis, 9), (Tag::Con, b), (Tag::Lis, 11), (Tag::Arg, 0), (Tag::ELis, 0), (Tag::Func, 2), (Tag::Con, p), (Tag::Lis, 7), ];
273 let mut substitution = Substitution::default();
274 substitution = substitution.push((3, 10, true));
275 re_build_bound_arg_terms(&mut heap, &mut substitution);
276 let new_term = build(&mut heap, &mut substitution, None, 13);
277 println!("{}", heap.term_string(new_term));
278 }
279
280 #[test]
281 fn meta_vars() {}
282
283 #[test]
284 fn test1() {
285 let p = SymbolDB::set_const("p".into());
286 let mut heap = vec![
287 (Tag::Ref, 0), (Tag::Lis, 2), (Tag::Ref, 2), (Tag::ELis, 0), (Tag::Func, 3), (Tag::Con, p), (Tag::Ref, 6), (Tag::Lis, 0), (Tag::Func, 3), (Tag::Con, p), (Tag::Arg, 0), (Tag::Arg, 0), ];
300
301 let mut sub = unify(&heap, 8, 4).unwrap();
302 re_build_bound_arg_terms(&mut heap, &mut sub);
303
304 heap._print_heap();
305 println!("{:?}", sub.bound(6))
306 }
307
308 #[test]
309 fn test2() {
310 let p = SymbolDB::set_const("p".into());
311 let mut heap = vec![
312 (Tag::Ref, 0), (Tag::Lis, 2), (Tag::Ref, 2), (Tag::ELis, 0), (Tag::Func, 3), (Tag::Con, p), (Tag::Ref, 6), (Tag::Lis, 0), (Tag::Func, 3), (Tag::Con, p), (Tag::Arg, 0), (Tag::Arg, 0), ];
325
326 let mut sub = unify(&heap, 8, 4).unwrap();
327 re_build_bound_arg_terms(&mut heap, &mut sub);
328
329 heap._print_heap();
330 println!("{:?}", sub.bound(6))
331 }
332}