prolog2/heap/
query_heap.rs1use crate::heap::{heap::Tag, symbol_db::SymbolDB};
2use fsize::fsize;
3use std::{
4 mem,
5 ops::{Index, IndexMut, Range},
6 sync::{
7 atomic::{AtomicUsize, Ordering::Acquire},
8 Arc,
9 },
10};
11
12use super::heap::{Cell, Heap};
13
14static HEAP_ID_COUNTER: AtomicUsize = AtomicUsize::new(1);
15
16pub struct QueryHeap {
22 id: usize,
23 pub(crate) cells: Vec<Cell>,
24 prog_cells: Arc<Vec<Cell>>,
25 root: Option<*const QueryHeap>,
27}
28
29impl QueryHeap {
30 pub fn new(prog_cells: Arc<Vec<Cell>>, root: Option<*const QueryHeap>) -> QueryHeap {
31 let id = HEAP_ID_COUNTER.fetch_add(1, Acquire);
32 QueryHeap {
33 id,
34 cells: Vec::new(),
35 prog_cells,
36 root,
37 }
38 }
39
40 pub fn branch(&self, count: usize) -> Vec<QueryHeap> {
41 let mut branch_heap = Vec::with_capacity(count);
42 for _ in 0..count {
43 branch_heap.push(QueryHeap::new(self.prog_cells.clone(), Some(self)));
44 }
45 branch_heap
46 }
47
48 fn get_symbol_db_id(&self, addr: usize) -> usize {
49 if addr < self.prog_cells.len() {
50 0
51 } else {
52 self.id
53 }
54 }
55}
56
57impl Heap for QueryHeap {
58 fn heap_push(&mut self, cell: Cell) -> usize {
59 let i = self.heap_len();
60 self.cells.push(cell);
61 i
62 }
63
64 fn heap_len(&self) -> usize {
65 match self.root {
66 Some(root) => unsafe { &*root }.heap_len() + self.cells.len(),
67 None => self.prog_cells.len() + self.cells.len(),
68 }
69 }
70
71 fn get_id(&self) -> usize {
72 self.id
73 }
74
75 fn term_string(&self, addr: usize) -> String {
77 let addr = self.deref_addr(addr);
79 match self[addr].0 {
80 Tag::Con => SymbolDB::get_const(self[addr].1).to_string(),
81 Tag::Func => self.func_string(addr),
82 Tag::Lis => self.list_string(addr),
83 Tag::ELis => "[]".into(),
84 Tag::Arg => match SymbolDB::get_var(addr, self.get_symbol_db_id(addr)) {
85 Some(symbol) => symbol.to_string(),
86 None => format!("Arg_{}", self[addr].1),
87 },
88 Tag::Ref => match SymbolDB::get_var(self.deref_addr(addr), self.get_symbol_db_id(addr))
89 .to_owned()
90 {
91 Some(symbol) => symbol.to_string(),
92 None => format!("Ref_{}", self[addr].1),
93 },
94 Tag::Int => {
95 let value: isize = unsafe { mem::transmute_copy(&self[addr].1) };
96 format!("{value}")
97 }
98 Tag::Flt => {
99 let value: fsize = unsafe { mem::transmute_copy(&self[addr].1) };
100 format!("{value}")
101 }
102 Tag::Tup => self.tuple_string(addr),
103 Tag::Set => self.set_string(addr),
104 Tag::Str => self.term_string(self[addr].1),
105 Tag::Stri => SymbolDB::get_string(self[addr].1).to_string(),
106 }
107 }
108
109 fn truncate(&mut self, mut len: usize) {
110 if len < self.prog_cells.len(){
111 panic!("Can't truncate to prog cells")
112 }
113 len -= self.prog_cells.len();
114 self.cells.resize(len, (Tag::Ref,0));
115 }
116}
117
118impl Index<usize> for QueryHeap {
119 type Output = Cell;
120
121 fn index(&self, index: usize) -> &Self::Output {
122 if index < self.prog_cells.len() {
123 &self.prog_cells[index]
124 } else {
125 if let Some(root) = self.root {
126 let root = unsafe { &*root };
127 if index < root.heap_len() {
128 &root[index]
130 } else {
131 &self.cells[index - root.heap_len()]
133 }
134 } else {
135 &self.cells[index - self.prog_cells.len()]
136 }
137 }
138 }
139}
140
141impl IndexMut<usize> for QueryHeap {
142 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
143 if index < self.prog_cells.len() {
144 panic!("Can't get mutable reference to program heap cell");
145 } else {
146 if let Some(root) = self.root {
147 let root = unsafe { &*root };
148 let root_heap_len = root.heap_len(); if index < root_heap_len {
150 panic!("Can't get mutable reference to root heap cell");
152 } else {
153 &mut self.cells[index - root_heap_len]
155 }
156 } else {
157 &mut self.cells[index - self.prog_cells.len()]
158 }
159 }
160 }
161}
162
163impl Index<Range<usize>> for QueryHeap {
164 type Output = [Cell];
165
166 fn index(&self, index: Range<usize>) -> &Self::Output {
167 let len = self.prog_cells.len();
168
169 if index.start < len && index.end < len {
170 &self.prog_cells[index]
171 } else if index.start >= len && self.root.is_none() {
172 &self.cells[index.start - len..index.end - len]
173 } else {
174 panic!("Range splits static and mutable heap")
175 }
176 }
177}