1use std::{
2 collections::HashMap,
3 mem,
4 ops::{Index, IndexMut, Range, RangeInclusive},
5};
6
7use super::symbol_db::SymbolDB;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14#[repr(u8)]
15pub enum Tag {
16 Ref,
18 Arg,
20 Func,
22 Tup,
24 Set,
26 Lis,
28 ELis,
30 Con,
32 Int,
34 Flt,
36 Str,
38 Stri,
40}
41
42impl std::fmt::Display for Tag {
43 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44 write!(f, "{self:?}")
45 }
46}
47
48pub type Cell = (Tag, usize);
50
51use fsize::fsize;
52pub const _CON_PTR: usize = isize::MAX as usize;
53pub const _FALSE: Cell = (Tag::Con, _CON_PTR);
54pub const _TRUE: Cell = (Tag::Con, _CON_PTR + 1);
55pub const EMPTY_LIS: Cell = (Tag::ELis, 0);
56
57pub trait Heap: IndexMut<usize, Output = Cell> + Index<Range<usize>, Output = [Cell]> {
63 fn heap_push(&mut self, cell: Cell) -> usize;
64
65 fn heap_len(&self) -> usize;
66
67 fn truncate(&mut self, len: usize);
68
69 fn get_id(&self) -> usize {
70 0
71 }
72
73 fn _set_arg(&mut self, value: usize) -> usize {
74 self.heap_push((Tag::Arg, value));
76 return self.heap_len() - 1;
77 }
78
79 fn set_const(&mut self, id: usize) -> usize {
80 let h = self.heap_len();
81 self.heap_push((Tag::Con, id));
82 h
83 }
84
85 fn set_ref(&mut self, ref_addr: Option<usize>) -> usize {
86 let addr = match ref_addr {
88 Some(a) => a,
89 None => self.heap_len(),
90 };
91 self.heap_push((Tag::Ref, addr));
92 return self.heap_len() - 1;
93 }
94
95 fn deref_addr(&self, mut addr: usize) -> usize {
96 loop {
97 match self[addr] {
98 (Tag::Ref, pointer) if addr == pointer => return pointer,
99 (Tag::Ref, pointer) => addr = pointer,
100 _ => return addr,
102 }
103 }
104 }
105
106 fn bind(&mut self, binding: &[(usize, usize)]) {
110 for (src, target) in binding {
111 let pointer = &mut self[*src].1;
113 if *pointer != *src {
114 panic!("Tried to reset bound ref: {} \n Binding: {binding:?}", src)
115 }
116 *pointer = *target;
117 }
118 }
119
120 fn unbind(&mut self, binding: &[(usize, usize)]) {
124 for (src, _target) in binding {
125 if let (Tag::Ref, pointer) = &mut self[*src] {
126 *pointer = *src;
127 }
128 }
129 }
130
131 fn str_symbol_arity(&self, mut addr: usize) -> (usize, usize) {
133 addr = self.deref_addr(addr);
134 if let (Tag::Str, pointer) = self[addr] {
135 addr = pointer
136 }
137 if let (Tag::Func, arity) = self[addr] {
138 match self[self.deref_addr(addr + 1)] {
139 (Tag::Arg | Tag::Ref, _) => (0, arity - 1),
140 (Tag::Con, id) => (id, arity - 1),
141 _ => panic!("Functor of structure not constant of variable"),
142 }
143 } else if let (Tag::Con, symbol) = self[addr] {
144 (symbol, 0)
145 } else {
146 panic!(
147 "No str arity for {}, {:?}",
148 self.term_string(addr),
149 self[addr]
150 )
151 }
152 }
153
154 fn term_vars(&self, mut addr: usize, args: bool) -> Vec<usize> {
158 addr = self.deref_addr(addr);
159 match self[addr].0 {
160 Tag::Arg if args => vec![addr],
161 Tag::Ref if !args => vec![addr],
162 Tag::Lis => [
163 self.term_vars(self[addr].1, args),
164 self.term_vars(self[addr].1 + 1, args),
165 ]
166 .concat(),
167 Tag::Func => self
168 .str_iterator(addr)
169 .map(|addr| self.term_vars(addr, args))
170 .collect::<Vec<Vec<usize>>>()
171 .concat(),
172 _ => vec![],
173 }
174 }
175
176 fn str_iterator(&self, addr: usize) -> RangeInclusive<usize> {
178 addr + 1..=addr + self[addr].1
179 }
180
181 fn normalise_args(&mut self, addr: usize, args: &mut Vec<usize>) {
182 match self[addr] {
183 (Tag::Str, pointer) => self.normalise_args(pointer, args),
184 (Tag::Func, _) => {
185 for i in self.str_iterator(addr) {
186 self.normalise_args(i, args)
187 }
188 }
189 (Tag::Tup, _) => unimplemented!("_normalise_args for Tup"),
190 (Tag::Set, _) => unimplemented!("_normalise_args for Set"),
191 (Tag::Lis, pointer) => {
192 self.normalise_args(pointer, args);
193 self.normalise_args(pointer + 1, args);
194 }
195 (Tag::Arg, value) => {
196 if let Some(pos) = args.iter().position(|i| value == *i) {
197 self[addr].1 = pos;
198 } else {
199 let pos = args.len();
200 args.push(value);
201 self[addr].1 = pos;
202 }
203 }
204 _ => (),
205 }
206 }
207
208 fn _copy_complex(&mut self, other: &impl Heap, mut addr: usize, update_addr: &mut usize) {
209 addr = other.deref_addr(addr);
210 match other[addr] {
211 (Tag::Str, pointer) => *update_addr = self._copy_term(other, pointer),
212 (Tag::Lis, _) => *update_addr = self._copy_term(other, addr),
213 _ => (),
214 }
215 }
216
217 fn _copy_simple(&mut self, other: &impl Heap, mut addr: usize, update_addr: &usize) {
218 addr = other.deref_addr(addr);
219 match other[addr] {
220 (Tag::Lis, _) => self.heap_push((Tag::Lis, *update_addr)),
221 (Tag::Str, _) => self.heap_push((Tag::Str, *update_addr)),
222 (Tag::Ref, _) => self.heap_push((Tag::Ref, self.heap_len())),
223 (_, _) => self.heap_push(other[addr]),
224 };
225 }
226
227 fn _copy_term(&mut self, other: &impl Heap, addr: usize) -> usize {
228 let addr = other.deref_addr(addr);
230 match other[addr] {
231 (Tag::Str, mut pointer) => {
232 pointer = self._copy_term(other, pointer);
233 self.heap_push((Tag::Str, pointer));
234 self.heap_len() - 1
235 }
236 (Tag::Func, arity) => {
237 let mut update_addr: Vec<usize> = vec![0; arity];
238 for (i, a) in other.str_iterator(addr).enumerate() {
239 self._copy_complex(other, a, &mut update_addr[i])
240 }
241 let h = self.heap_len();
242 self.heap_push((Tag::Func, arity));
243 for (i, a) in other.str_iterator(addr).enumerate() {
244 self._copy_simple(other, a, &update_addr[i]);
245 }
246 h
247 }
248 (Tag::Lis, pointer) => {
249 let mut update_addr: Vec<usize> = vec![0; 2];
250 self._copy_complex(other, pointer, &mut update_addr[0]);
251 self._copy_complex(other, pointer + 1, &mut update_addr[1]);
252
253 let h = self.heap_len();
254 self._copy_simple(other, pointer, &mut update_addr[0]);
255 self._copy_simple(other, pointer + 1, &mut update_addr[1]);
256 h
257 }
258 (Tag::Tup, _len) => unimplemented!("_copy_term for Tup"),
259 (Tag::Set, _len) => unimplemented!("_copy_term for Set"),
260 (Tag::Ref, _pointer) => panic!(),
261 (Tag::Arg | Tag::Con | Tag::Int | Tag::Flt | Tag::Stri | Tag::ELis, _) => {
262 self.heap_push(other[addr]);
263 self.heap_len() - 1
264 }
265 }
266 }
267
268 fn copy_term_with_ref_map(
274 &mut self,
275 other: &impl Heap,
276 addr: usize,
277 ref_map: &mut HashMap<usize, usize>,
278 ) -> usize {
279 let addr = other.deref_addr(addr);
280 match other[addr] {
281 (Tag::Str, pointer) => {
282 let new_ptr = self.copy_term_with_ref_map(other, pointer, ref_map);
283 self.heap_push((Tag::Str, new_ptr));
284 self.heap_len() - 1
285 }
286 (Tag::Func | Tag::Tup | Tag::Set, length) => {
287 let mut pre: Vec<Option<Cell>> = Vec::with_capacity(length);
289 for i in 1..=length {
290 pre.push(self._copy_ref_map_complex(other, addr + i, ref_map));
291 }
292 let h = self.heap_len();
294 self.heap_push((other[addr].0, length));
295 for (i, pre_cell) in pre.into_iter().enumerate() {
296 match pre_cell {
297 Some(cell) => {
298 self.heap_push(cell);
299 }
300 None => self._copy_ref_map_simple(other, addr + 1 + i, ref_map),
301 }
302 }
303 h
304 }
305 (Tag::Lis, pointer) => {
306 let head = self._copy_ref_map_complex(other, pointer, ref_map);
307 let tail = self._copy_ref_map_complex(other, pointer + 1, ref_map);
308 let h = self.heap_len();
309 match head {
310 Some(cell) => {
311 self.heap_push(cell);
312 }
313 None => self._copy_ref_map_simple(other, pointer, ref_map),
314 }
315 match tail {
316 Some(cell) => {
317 self.heap_push(cell);
318 }
319 None => self._copy_ref_map_simple(other, pointer + 1, ref_map),
320 }
321 h
322 }
323 (Tag::Ref, r) if r == addr => {
324 if let Some(&mapped) = ref_map.get(&addr) {
326 mapped
327 } else {
328 let new_addr = self.heap_len();
329 self.heap_push((Tag::Ref, new_addr));
330 ref_map.insert(addr, new_addr);
331 new_addr
332 }
333 }
334 (Tag::Arg | Tag::Con | Tag::Int | Tag::Flt | Tag::Stri | Tag::ELis, _) => {
335 self.heap_push(other[addr]);
336 self.heap_len() - 1
337 }
338 (tag, val) => panic!("copy_term_with_ref_map: unhandled ({tag:?}, {val})"),
339 }
340 }
341
342 fn _copy_ref_map_complex(
345 &mut self,
346 other: &impl Heap,
347 addr: usize,
348 ref_map: &mut HashMap<usize, usize>,
349 ) -> Option<Cell> {
350 let addr = other.deref_addr(addr);
351 match other[addr] {
352 (Tag::Func | Tag::Tup | Tag::Set, _) => {
353 Some((Tag::Str, self.copy_term_with_ref_map(other, addr, ref_map)))
354 }
355 (Tag::Str, ptr) => Some((Tag::Str, self.copy_term_with_ref_map(other, ptr, ref_map))),
356 (Tag::Lis, _) => Some((Tag::Lis, self.copy_term_with_ref_map(other, addr, ref_map))),
357 _ => None,
358 }
359 }
360
361 fn _copy_ref_map_simple(
364 &mut self,
365 other: &impl Heap,
366 addr: usize,
367 ref_map: &mut HashMap<usize, usize>,
368 ) {
369 let addr = other.deref_addr(addr);
370 match other[addr] {
371 (Tag::Ref, r) if r == addr => {
372 if let Some(&mapped) = ref_map.get(&addr) {
373 self.heap_push((Tag::Ref, mapped));
374 } else {
375 let new_addr = self.heap_len();
376 self.heap_push((Tag::Ref, new_addr));
377 ref_map.insert(addr, new_addr);
378 }
379 }
380 cell => {
381 self.heap_push(cell);
382 }
383 }
384 }
385
386 fn _term_equal(&self, mut addr1: usize, mut addr2: usize) -> bool {
387 addr1 = self.deref_addr(addr1);
388 addr2 = self.deref_addr(addr2);
389 match (self[addr1], self[addr2]) {
390 (EMPTY_LIS, EMPTY_LIS) => true,
391 (EMPTY_LIS, _) => false,
392 (_, EMPTY_LIS) => false,
393 ((Tag::Func, a1), (Tag::Func, a2)) if a1 == a2 => self
394 .str_iterator(addr1)
395 .zip(self.str_iterator(addr2))
396 .all(|(addr1, addr2)| self._term_equal(addr1, addr2)),
397 ((Tag::Lis, p1), (Tag::Lis, p2)) => {
398 self._term_equal(p1, p2) && self._term_equal(p1 + 1, p2 + 1)
399 }
400 ((Tag::Str, p1), (Tag::Str, p2)) => self._term_equal(p1, p2),
401 ((Tag::Tup, _len1), (Tag::Tup, _len2)) => unimplemented!("_term_equal for Tup"),
402 ((Tag::Set, _len1), (Tag::Set, _len2)) => unimplemented!("_term_equal for Set"),
403 ((Tag::Stri, i1), (Tag::Stri, i2)) => {
404 SymbolDB::get_string(i1) == SymbolDB::get_string(i2)
405 }
406
407 _ => self[addr1] == self[addr2],
408 }
409 }
410
411 fn contains_args(&self, mut addr: usize) -> bool {
412 addr = self.deref_addr(addr);
413 match self[addr] {
414 (Tag::Arg, _) => true,
415 (Tag::Lis, ptr) => self.contains_args(ptr) || self.contains_args(ptr + 1),
416 (Tag::Str, ptr) => self.contains_args(ptr),
417 (Tag::Func | Tag::Set | Tag::Tup, length) => {
418 (addr + 1..addr + 1 + length).any(|addr| self.contains_args(addr))
419 }
420 _ => false,
421 }
422 }
423
424 fn _print_heap(&self) {
426 let w = 6;
427 for i in 0..self.heap_len() {
428 let (tag, value) = self[i];
429 match tag {
430 Tag::Con => {
431 println!("[{i:3}]|{tag:w$}|{:w$}|", SymbolDB::get_const(value))
432 }
433 Tag::Lis => {
434 if value == _CON_PTR {
435 println!("[{i:3}]|{tag:w$}|{:w$}|", "[]")
436 } else {
437 println!("[{i:3}]|{tag:w$}|{value:w$}|")
438 }
439 }
440 Tag::Ref | Tag::Arg => {
441 println!("[{i:3}]|{tag:w$?}|{value:w$}|:({})", self.term_string(i))
442 }
443 Tag::Int => {
444 let value: isize = unsafe { mem::transmute_copy(&value) };
445 println!("[{i:3}]|{tag:w$?}|{value:w$}|")
446 }
447 Tag::Flt => {
448 let value: fsize = unsafe { mem::transmute_copy(&value) };
449 println!("[{i:3}]|{tag:w$?}|{value:w$}|")
450 }
451 Tag::Tup => unimplemented!("_print_heap for Tup"),
452 Tag::Set => unimplemented!("_print_heap for Set"),
453 Tag::Stri => unimplemented!("_print_heap for Stri"),
454 _ => println!("[{i:3}]|{tag:w$?}|{value:w$}|"),
455 };
456 println!("{:-<w$}--------{:-<w$}", "", "");
457 }
458 }
459
460 fn list_string(&self, addr: usize) -> String {
462 let mut buffer = "[".to_string();
463 let mut pointer = self[addr].1;
464
465 loop {
466 buffer += &self.term_string(pointer);
467
468 match self[pointer + 1].0 {
469 Tag::Lis => {
470 buffer += ",";
471 pointer = self[pointer + 1].1
472 }
473 Tag::ELis => break,
474 _ => {
475 buffer += "|";
476 buffer += &self.term_string(pointer + 1);
477 break;
478 }
479 }
480 }
481 buffer += "]";
482 buffer
483 }
484
485 fn func_string(&self, addr: usize) -> String {
487 let mut buf = "".to_string();
488 let mut first = true;
489 for i in self.str_iterator(addr) {
490 buf += &self.term_string(i);
491 buf += if first { "(" } else { "," };
492 if first {
493 first = false
494 }
495 }
496 buf.pop();
497 buf += ")";
498 buf
499 }
500
501 fn tuple_string(&self, addr: usize) -> String {
503 let mut buf = String::from("(");
504 for i in 1..self[addr].1 + 1 {
505 buf += &self.term_string(addr + i);
506 buf += ",";
507 }
508 buf.pop();
509 buf += ")";
510 buf
511 }
512
513 fn set_string(&self, addr: usize) -> String {
515 let mut buf = String::from("{");
516 for i in 1..self[addr].1 + 1 {
517 buf += &self.term_string(addr + i);
518 buf += ",";
519 }
520 buf.pop();
521 buf += "}";
522 buf
523 }
524
525 fn term_string(&self, addr: usize) -> String {
527 let addr = self.deref_addr(addr);
529 match self[addr].0 {
530 Tag::Con => SymbolDB::get_const(self[addr].1).to_string(),
531 Tag::Func => self.func_string(addr),
532 Tag::Lis => self.list_string(addr),
533 Tag::ELis => "[]".into(),
534 Tag::Arg => match SymbolDB::get_var(addr, self.get_id()) {
535 Some(symbol) => symbol.to_string(),
536 None => format!("Arg_{}", self[addr].1),
537 },
538 Tag::Ref => match SymbolDB::get_var(self.deref_addr(addr), self.get_id()).to_owned() {
539 Some(symbol) => symbol.to_string(),
540 None => format!("Ref_{}", self[addr].1),
541 },
542 Tag::Int => {
543 let value: isize = unsafe { mem::transmute_copy(&self[addr].1) };
544 format!("{value}")
545 }
546 Tag::Flt => {
547 let value: fsize = unsafe { mem::transmute_copy(&self[addr].1) };
548 format!("{value}")
549 }
550 Tag::Tup => self.tuple_string(addr),
551 Tag::Set => self.set_string(addr),
552 Tag::Str => self.term_string(self[addr].1),
553 Tag::Stri => SymbolDB::get_string(self[addr].1).to_string(),
554 }
555 }
556}
557
558impl Heap for Vec<Cell> {
559 fn heap_push(&mut self, cell: Cell) -> usize {
560 let i = self.len();
561 self.push(cell);
562 i
563 }
564
565 fn heap_len(&self) -> usize {
566 self.len()
567 }
568
569 fn truncate(&mut self, len: usize) {
570 self.resize(len, (Tag::Ref, 0));
571 }
572}
573
574#[cfg(test)]
575mod tests {
576 use crate::heap::query_heap::QueryHeap;
577
578 use super::{
579 super::symbol_db::SymbolDB,
580 {Cell, Heap, Tag, EMPTY_LIS},
581 };
582
583 #[test]
584 fn encode_argument_variable() {
585 let mut heap = QueryHeap::new(&[], None);
586
587 let addr1 = heap._set_arg(0);
588 let addr2 = heap._set_arg(1);
589
590 assert_eq!(heap.term_string(addr1), "Arg_0");
591 assert_eq!(heap.term_string(addr2), "Arg_1");
592 }
593
594 #[test]
595 fn encode_ref_variable() {
596 let mut heap = QueryHeap::new(&[], None);
597
598 let addr1 = heap.set_ref(None);
599 let addr2 = heap.set_ref(Some(addr1));
600
601 assert_eq!(heap.term_string(addr1), "Ref_0");
602 assert_eq!(heap.term_string(addr2), "Ref_0");
603 }
604
605 #[test]
606 fn encode_constant() {
607 let mut heap = QueryHeap::new(&[], None);
608
609 let a = SymbolDB::set_const("a".into());
610 let b = SymbolDB::set_const("b".into());
611
612 let addr1 = heap.set_const(a);
613 let addr2 = heap.set_const(b);
614
615 assert_eq!(heap.term_string(addr1), "a");
616 assert_eq!(heap.term_string(addr2), "b");
617 }
618
619 #[test]
620 fn encode_functor() {
621 let p = SymbolDB::set_const("p".into());
622 let f = SymbolDB::set_const("f".into());
623 let a = SymbolDB::set_const("a".into());
624
625 let mut heap = QueryHeap::new(&[], None);
626 heap.cells.extend(vec![
627 (Tag::Str, 1),
628 (Tag::Func, 3),
629 (Tag::Con, p),
630 (Tag::Arg, 0),
631 (Tag::Con, a),
632 ]);
633
634 assert_eq!(heap.term_string(0), "p(Arg_0,a)");
635
636 let mut heap = QueryHeap::new(&[], None);
637 heap.cells.extend(vec![
638 (Tag::Str, 1),
639 (Tag::Func, 3),
640 (Tag::Con, p),
641 (Tag::Str, 5),
642 (Tag::Con, a),
643 (Tag::Func, 2),
644 (Tag::Con, f),
645 (Tag::Ref, 7),
646 ]);
647 assert_eq!(heap.term_string(0), "p(f(Ref_7),a)");
648
649 let mut heap = QueryHeap::new(&[], None);
650 heap.cells.extend(vec![
651 (Tag::Str, 1),
652 (Tag::Func, 3),
653 (Tag::Con, p),
654 (Tag::Str, 5),
655 (Tag::Con, a),
656 (Tag::Tup, 2),
657 (Tag::Con, f),
658 (Tag::Ref, 7),
659 ]);
660 assert_eq!(heap.term_string(0), "p((f,Ref_7),a)");
661
662 let mut heap = QueryHeap::new(&[], None);
663 heap.cells.extend(vec![
664 (Tag::Str, 1),
665 (Tag::Func, 3),
666 (Tag::Con, p),
667 (Tag::Str, 5),
668 (Tag::Con, a),
669 (Tag::Set, 2),
670 (Tag::Con, f),
671 (Tag::Ref, 7),
672 ]);
673
674 assert_eq!(heap.term_string(0), "p({f,Ref_7},a)");
675
676 let mut heap = QueryHeap::new(&[], None);
677 heap.cells.extend(vec![
678 (Tag::Str, 1),
679 (Tag::Func, 3),
680 (Tag::Con, p),
681 (Tag::Lis, 5),
682 (Tag::Con, a),
683 (Tag::Con, f),
684 (Tag::Lis, 7),
685 (Tag::Ref, 7),
686 EMPTY_LIS,
687 ]);
688 assert_eq!(heap.term_string(0), "p([f,Ref_7],a)");
689 }
690
691 #[test]
692 fn encode_tuple() {
693 let f = SymbolDB::set_const("f".into());
694 let a = SymbolDB::set_const("a".into());
695
696 let mut heap = QueryHeap::new(&[], None);
697 heap.cells.extend(vec![
698 (Tag::Str, 1),
699 (Tag::Tup, 2),
700 (Tag::Arg, 0),
701 (Tag::Con, a),
702 ]);
703 assert_eq!(heap.term_string(0), "(Arg_0,a)");
704
705 let mut heap = QueryHeap::new(&[], None);
706 heap.cells.extend(vec![
707 (Tag::Str, 1),
708 (Tag::Tup, 2),
709 (Tag::Str, 4),
710 (Tag::Con, a),
711 (Tag::Func, 2),
712 (Tag::Con, f),
713 (Tag::Ref, 6),
714 ]);
715 assert_eq!(heap.term_string(0), "(f(Ref_6),a)");
716
717 let mut heap = QueryHeap::new(&[], None);
718 heap.cells.extend(vec![
719 (Tag::Str, 1),
720 (Tag::Tup, 2),
721 (Tag::Str, 4),
722 (Tag::Con, a),
723 (Tag::Tup, 2),
724 (Tag::Con, f),
725 (Tag::Ref, 6),
726 ]);
727 assert_eq!(heap.term_string(0), "((f,Ref_6),a)");
728
729 let mut heap = QueryHeap::new(&[], None);
730 heap.cells.extend(vec![
731 (Tag::Str, 1),
732 (Tag::Tup, 2),
733 (Tag::Str, 4),
734 (Tag::Con, a),
735 (Tag::Set, 2),
736 (Tag::Con, f),
737 (Tag::Ref, 6),
738 ]);
739 assert_eq!(heap.term_string(0), "({f,Ref_6},a)");
740
741 let mut heap = QueryHeap::new(&[], None);
742 heap.cells.extend(vec![
743 (Tag::Str, 1),
744 (Tag::Tup, 2),
745 (Tag::Lis, 4),
746 (Tag::Con, a),
747 (Tag::Con, f),
748 (Tag::Lis, 6),
749 (Tag::Ref, 6),
750 EMPTY_LIS,
751 ]);
752 assert_eq!(heap.term_string(0), "([f,Ref_6],a)");
753 }
754
755 #[test]
756 fn encode_list() {
757 let f = SymbolDB::set_const("f".into());
758 let a = SymbolDB::set_const("a".into());
759
760 let mut heap = QueryHeap::new(&[], None);
761 heap.cells.extend(vec![
762 (Tag::Lis, 1),
763 (Tag::Arg, 0),
764 (Tag::Lis, 3),
765 (Tag::Con, a),
766 EMPTY_LIS,
767 ]);
768 assert_eq!(heap.term_string(0), "[Arg_0,a]");
769
770 let mut heap = QueryHeap::new(&[], None);
771 heap.cells.extend(vec![
772 (Tag::Lis, 1),
773 (Tag::Str, 5),
774 (Tag::Lis, 3),
775 (Tag::Con, a),
776 EMPTY_LIS,
777 (Tag::Func, 2),
778 (Tag::Con, f),
779 (Tag::Ref, 7),
780 ]);
781 assert_eq!(heap.term_string(0), "[f(Ref_7),a]");
782
783 let mut heap = QueryHeap::new(&[], None);
784 heap.cells.extend(vec![
785 (Tag::Lis, 1),
786 (Tag::Str, 5),
787 (Tag::Lis, 3),
788 (Tag::Con, a),
789 EMPTY_LIS,
790 (Tag::Tup, 2),
791 (Tag::Con, f),
792 (Tag::Ref, 7),
793 ]);
794 assert_eq!(heap.term_string(0), "[(f,Ref_7),a]");
795
796 let mut heap = QueryHeap::new(&[], None);
797 heap.cells.extend(vec![
798 (Tag::Lis, 1),
799 (Tag::Str, 5),
800 (Tag::Lis, 3),
801 (Tag::Con, a),
802 EMPTY_LIS,
803 (Tag::Set, 2),
804 (Tag::Con, f),
805 (Tag::Ref, 7),
806 ]);
807 assert_eq!(heap.term_string(0), "[{f,Ref_7},a]");
808
809 let mut heap = QueryHeap::new(&[], None);
810 heap.cells.extend(vec![
811 (Tag::Lis, 1),
812 (Tag::Lis, 5),
813 (Tag::Lis, 3),
814 (Tag::Con, a),
815 EMPTY_LIS,
816 (Tag::Con, f),
817 (Tag::Lis, 7),
818 (Tag::Ref, 7),
819 EMPTY_LIS,
820 ]);
821 assert_eq!(heap.term_string(0), "[[f,Ref_7],a]");
822 }
823
824 #[test]
825 fn encode_set() {
826 let f = SymbolDB::set_const("f".into());
827 let a = SymbolDB::set_const("a".into());
828
829 let mut heap = QueryHeap::new(&[], None);
830 heap.cells.extend(vec![
831 (Tag::Str, 1),
832 (Tag::Set, 2),
833 (Tag::Arg, 0),
834 (Tag::Con, a),
835 ]);
836 assert_eq!(heap.term_string(0), "{Arg_0,a}");
837
838 let mut heap = QueryHeap::new(&[], None);
839 heap.cells.extend(vec![
840 (Tag::Str, 1),
841 (Tag::Set, 2),
842 (Tag::Str, 4),
843 (Tag::Con, a),
844 (Tag::Func, 2),
845 (Tag::Con, f),
846 (Tag::Ref, 6),
847 ]);
848 assert_eq!(heap.term_string(0), "{f(Ref_6),a}");
849
850 let mut heap = QueryHeap::new(&[], None);
851 heap.cells.extend(vec![
852 (Tag::Str, 1),
853 (Tag::Set, 2),
854 (Tag::Str, 4),
855 (Tag::Con, a),
856 (Tag::Tup, 2),
857 (Tag::Con, f),
858 (Tag::Ref, 6),
859 ]);
860 assert_eq!(heap.term_string(0), "{(f,Ref_6),a}");
861
862 let mut heap = QueryHeap::new(&[], None);
863 heap.cells.extend(vec![
864 (Tag::Str, 1),
865 (Tag::Set, 2),
866 (Tag::Str, 4),
867 (Tag::Con, a),
868 (Tag::Set, 2),
869 (Tag::Con, f),
870 (Tag::Ref, 6),
871 ]);
872 assert_eq!(heap.term_string(0), "{{f,Ref_6},a}");
873
874 let mut heap = QueryHeap::new(&[], None);
875 heap.cells.extend(vec![
876 (Tag::Str, 1),
877 (Tag::Set, 2),
878 (Tag::Lis, 4),
879 (Tag::Con, a),
880 (Tag::Con, f),
881 (Tag::Lis, 6),
882 (Tag::Ref, 6),
883 EMPTY_LIS,
884 ]);
885 assert_eq!(heap.term_string(0), "{[f,Ref_6],a}");
886 }
887
888 #[test]
889 fn dereference() {
890 let f = SymbolDB::set_const("f".into());
891 let a = SymbolDB::set_const("a".into());
892
893 let mut heap = QueryHeap::new(&[], None);
894 heap.cells.extend(vec![
895 (Tag::Ref, 1),
896 (Tag::Ref, 2),
897 (Tag::Ref, 3),
898 (Tag::Ref, 3),
899 ]);
900 assert_eq!(heap.term_string(0), "Ref_3");
901
902 let mut heap = QueryHeap::new(&[], None);
903 heap.cells.extend(vec![
904 (Tag::Ref, 1),
905 (Tag::Ref, 2),
906 (Tag::Ref, 3),
907 (Tag::Arg, 0),
908 ]);
909 assert_eq!(heap.term_string(0), "Arg_0");
910
911 let mut heap = QueryHeap::new(&[], None);
912 heap.cells.extend(vec![
913 (Tag::Ref, 1),
914 (Tag::Ref, 2),
915 (Tag::Ref, 3),
916 (Tag::Con, a),
917 ]);
918 assert_eq!(heap.term_string(0), "a");
919
920 let mut heap = QueryHeap::new(&[], None);
921 heap.cells.extend(vec![
922 (Tag::Ref, 1),
923 (Tag::Ref, 2),
924 (Tag::Ref, 3),
925 (Tag::Str, 4),
926 (Tag::Func, 3),
927 (Tag::Con, f),
928 (Tag::Con, a),
929 (Tag::Ref, 7),
930 ]);
931 assert_eq!(heap.term_string(0), "f(a,Ref_7)");
932
933 let mut heap = QueryHeap::new(&[], None);
934 heap.cells.extend(vec![
935 (Tag::Ref, 1),
936 (Tag::Ref, 2),
937 (Tag::Ref, 3),
938 (Tag::Str, 4),
939 (Tag::Tup, 2),
940 (Tag::Con, a),
941 (Tag::Ref, 6),
942 ]);
943 assert_eq!(heap.term_string(0), "(a,Ref_6)");
944
945 let mut heap = QueryHeap::new(&[], None);
946 heap.cells.extend(vec![
947 (Tag::Ref, 1),
948 (Tag::Ref, 2),
949 (Tag::Ref, 3),
950 (Tag::Str, 4),
951 (Tag::Set, 2),
952 (Tag::Con, a),
953 (Tag::Ref, 6),
954 ]);
955 assert_eq!(heap.term_string(0), "{a,Ref_6}");
956
957 let mut heap = QueryHeap::new(&[], None);
958 heap.cells.extend(vec![
959 (Tag::Ref, 1),
960 (Tag::Ref, 2),
961 (Tag::Ref, 3),
962 (Tag::Lis, 4),
963 (Tag::Con, a),
964 (Tag::Lis, 6),
965 (Tag::Ref, 6),
966 EMPTY_LIS,
967 ]);
968 assert_eq!(heap.term_string(0), "[a,Ref_6]");
969 }
970}