1use crate::{Var, Var_};
2
3#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
4pub struct PackedPtr(u32);
5
6impl PackedPtr {
7 pub fn expr(e: u32) -> PackedPtr {
8 PackedPtr(e << 2)
9 }
10
11 pub fn as_expr(self) -> Option<Ptr> {
12 if self.0 & 0x3 == 0x0 {
13 Some(self.into())
14 } else {
15 None
16 }
17 }
18
19 pub fn proof(e: u32) -> PackedPtr {
20 PackedPtr((e << 2) | 0x01)
21 }
22
23 pub fn as_proof(self) -> Option<Ptr> {
24 if self.0 & 0x03 == 0x01 {
25 Some(self.into())
26 } else {
27 None
28 }
29 }
30
31 pub fn conv(e: u32) -> PackedPtr {
32 PackedPtr((e << 2) | 0x02)
33 }
34
35 pub fn as_conv(self) -> Option<Ptr> {
36 if self.0 & 0x03 == 0x02 {
37 Some(self.into())
38 } else {
39 None
40 }
41 }
42
43 pub fn co_conv(e: u32) -> PackedPtr {
44 PackedPtr((e << 2) | 0x03)
45 }
46
47 pub fn as_co_conv(self) -> Option<Ptr> {
48 if self.0 & 0x03 == 0x03 {
49 Some(self.into())
50 } else {
51 None
52 }
53 }
54
55 pub fn to_display<'a, S: Store>(&self, store: &'a S) -> DisplayPackedPtr<'a, S> {
56 DisplayPackedPtr(*self, store)
57 }
58}
59
60impl From<&PackedPtr> for Ptr {
61 fn from(ptr: &PackedPtr) -> Ptr {
62 Ptr(ptr.0 >> 2)
63 }
64}
65
66impl From<PackedPtr> for Ptr {
67 fn from(ptr: PackedPtr) -> Ptr {
68 Ptr(ptr.0 >> 2)
69 }
70}
71
72use core::fmt::{self, Display, Formatter};
73
74pub struct DisplayPackedPtr<'a, S: Store>(PackedPtr, &'a S);
75
76impl<'a, S: Store> Display for DisplayPackedPtr<'a, S> {
77 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
78 write!(f, "{}", Into::<Ptr>::into(self.0).0)
79 }
80}
81
82impl Display for PackedPtr {
83 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
84 match self.0 & 0x03 {
85 0x00 => write!(f, "expr"),
86 0x01 => write!(f, "proof"),
87 0x02 => write!(f, "conv"),
88 0x03 => write!(f, "co-conv"),
89 _ => Ok(()),
90 }
91 }
92}
93
94#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
95pub struct Ptr(pub u32);
96
97impl Ptr {
98 #[inline(always)]
99 pub fn to_proof(self) -> PackedPtr {
100 PackedPtr::proof(self.0)
101 }
102
103 #[inline(always)]
104 pub fn to_expr(self) -> PackedPtr {
105 PackedPtr::expr(self.0)
106 }
107
108 #[inline(always)]
109 pub fn to_co_conv(self) -> PackedPtr {
110 PackedPtr::co_conv(self.0)
111 }
112
113 #[inline(always)]
114 pub fn to_conv(self) -> PackedPtr {
115 PackedPtr::conv(self.0)
116 }
117
118 #[inline(always)]
119 pub fn get_idx(self) -> usize {
120 self.0 as usize
121 }
122}
123
124#[derive(Debug)]
125pub enum ElementRef<'a, Ty> {
126 Variable {
127 ty: &'a Ty,
128 var: &'a u16,
129 },
130 Term {
131 ty: &'a Ty,
132 id: &'a u32,
133 args: &'a [PackedPtr],
134 },
135 Conv {
137 e1: &'a PackedPtr,
138 e2: &'a PackedPtr,
139 },
140}
141
142impl<'a, Ty: Var> ElementRef<'a, Ty> {
143 pub fn to_display<'b, S: Store<Var = Ty>>(
144 &'b self,
145 store: &'b S,
146 ) -> DisplayElement<'a, 'b, Ty, S> {
147 DisplayElement(self, store)
148 }
149}
150
151pub struct DisplayElement<'a, 'b, Ty: Var, S: Store<Var = Ty>>(
152 pub &'b ElementRef<'a, Ty>,
153 pub &'b S,
154);
155
156impl<'a, 'b, Ty: Var, S: Store<Var = Ty>> Display for DisplayElement<'a, 'b, Ty, S> {
157 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
158 match self.0 {
159 ElementRef::Variable { var, .. } => {
160 write!(f, "v{}", var)
161 }
163 ElementRef::Term { id, args, .. } => {
164 write!(f, "t{} (", id)?;
165
166 for i in *args {
167 match self.1.get_element(i.into()) {
168 Some(el) => write!(f, "{} ", el.to_display(self.1))?,
169 None => write!(f, "invalid_ptr")?,
170 }
171 }
172
173 write!(f, ")")
174 }
175 ElementRef::Conv { e1, e2 } => write!(f, "conv: {:?} {:?}", e1, e2),
176 }
177 }
178}
179
180#[derive(Debug)]
181pub struct Term<'a, Ty> {
182 pub ty: &'a Ty,
183 pub id: &'a u32,
184 pub args: &'a [PackedPtr],
185}
186
187use core::convert::TryFrom;
188use core::convert::TryInto;
189
190impl<'a, Ty> TryFrom<ElementRef<'a, Ty>> for Term<'a, Ty> {
191 type Error = Kind;
192
193 fn try_from(element: ElementRef<'a, Ty>) -> Result<Self, Self::Error> {
194 if let ElementRef::Term { ty, id, args } = element {
195 Ok(Term { ty, id, args })
196 } else {
197 Err(Kind::InvalidStoreType)
198 }
199 }
200}
201
202#[derive(Debug)]
203pub struct Conv {
204 pub e1: PackedPtr,
205 pub e2: PackedPtr,
206}
207
208impl<'a, Ty> TryFrom<ElementRef<'a, Ty>> for Conv {
209 type Error = Kind;
210
211 fn try_from(element: ElementRef<'a, Ty>) -> Result<Self, Self::Error> {
212 if let ElementRef::Conv { e1, e2 } = element {
213 Ok(Conv { e1: *e1, e2: *e2 })
214 } else {
215 Err(Kind::InvalidStoreType)
216 }
217 }
218}
219
220#[derive(Debug)]
221pub struct Variable<Ty> {
222 pub ty: Ty,
223 pub var: u16,
224}
225
226impl<'a, Ty: Copy> TryFrom<ElementRef<'a, Ty>> for Variable<Ty> {
227 type Error = Kind;
228
229 fn try_from(element: ElementRef<'a, Ty>) -> Result<Self, Self::Error> {
230 if let ElementRef::Variable { ty, var } = element {
231 Ok(Variable { ty: *ty, var: *var })
232 } else {
233 Err(Kind::InvalidStoreType)
234 }
235 }
236}
237
238#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
239enum InternalStoreElement {
240 Variable {
241 ty: Var_,
242 var: u16,
243 },
244 Term {
245 ty: Var_,
246 num_args: u16,
247 id: u32,
248 ptr_args: usize,
249 },
250 Conv {
251 e1: PackedPtr,
252 e2: PackedPtr,
253 },
254}
255
256#[derive(Debug, Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
257pub struct Store_ {
258 data: Vec<InternalStoreElement>,
259 args: Vec<PackedPtr>,
260}
261
262use crate::error::Kind;
263use crate::KResult;
264
265pub trait Store {
266 type Var: Var;
267
268 fn create_term<T>(
269 &mut self,
270 id: u32,
271 args: T,
272 types: &[Self::Var],
273 ret_type: &Self::Var,
274 sort: u8,
275 def: bool,
276 ) -> KResult<PackedPtr>
277 where
278 T: IntoIterator<Item = PackedPtr>,
279 T: Clone;
280
281 fn alloc_var(&mut self, ty: Self::Var, idx: u16) -> PackedPtr;
282
283 fn alloc_conv(&mut self, l: PackedPtr, r: PackedPtr) -> PackedPtr;
284
285 fn clear(&mut self);
286
287 fn get_type_of_expr(&self, ptr: Ptr) -> Option<&Self::Var>;
288
289 fn get_element(&self, ptr: Ptr) -> Option<ElementRef<Self::Var>>;
290
291 fn get<'a, T: TryFrom<ElementRef<'a, Self::Var>, Error = Kind>>(
292 &'a self,
293 ptr: Ptr,
294 ) -> KResult<T>;
295}
296
297impl Store for Store_ {
298 type Var = Var_;
299
300 fn create_term<T>(
301 &mut self,
302 id: u32,
303 args: T,
304 types: &[Self::Var],
305 ret_type: &Self::Var,
306 sort: u8,
307 def: bool,
308 ) -> KResult<PackedPtr>
309 where
310 T: IntoIterator<Item = PackedPtr>,
311 T: Clone,
312 {
313 let offset = self.args.len();
314 let mut accum = 0;
315 let mut g_deps = [0; 256];
316 let mut bound = 0;
317
318 for (arg, &target_type) in args.clone().into_iter().zip(types.iter()) {
319 let arg = arg.as_expr().ok_or(Kind::InvalidStoreType)?;
320
321 let ty = self.get_type_of_expr(arg).ok_or(Kind::InvalidStoreExpr)?;
322
323 if !ty.is_compatible_to(&target_type) {
324 return Err(Kind::IncompatibleTypes);
325 }
326
327 let mut deps = ty.dependencies();
328
329 if target_type.is_bound() {
330 *g_deps
331 .get_mut(bound as usize)
332 .ok_or(Kind::DependencyOverflow)? = deps;
333
334 bound += 1;
335 } else {
336 if def {
337 for (_, &j) in g_deps
338 .get(..(bound as usize))
339 .ok_or(Kind::DependencyOverflow)?
340 .iter()
341 .enumerate()
342 .filter(|(i, _)| target_type.depends_on(*i as u8))
343 {
344 deps &= !j;
345 }
346 }
347
348 accum |= deps;
349 }
350 }
351
352 if def && ret_type.dependencies() != 0 {
353 for (_, &j) in g_deps
354 .get(..(bound as usize))
355 .ok_or(Kind::DependencyOverflow)?
356 .iter()
357 .enumerate()
358 .filter(|(i, _)| ret_type.depends_on(*i as u8))
359 {
360 accum |= j;
361 }
362 }
363
364 self.args.extend(args);
365
366 let ise = InternalStoreElement::Term {
367 ty: Var::new(sort, accum, false),
368 num_args: types.len() as u16,
369 id,
370 ptr_args: offset,
371 };
372
373 let size = self.data.len() as u32;
374
375 self.data.push(ise);
376
377 Ok(PackedPtr::expr(size))
378 }
379
380 fn alloc_var(&mut self, ty: Self::Var, idx: u16) -> PackedPtr {
381 let size = self.data.len() as u32;
382
383 self.data
384 .push(InternalStoreElement::Variable { ty, var: idx });
385
386 PackedPtr::expr(size)
387 }
388
389 fn alloc_conv(&mut self, l: PackedPtr, r: PackedPtr) -> PackedPtr {
390 let size = self.data.len() as u32;
391
392 self.data.push(InternalStoreElement::Conv { e1: l, e2: r });
393
394 PackedPtr::conv(size)
395 }
396
397 fn clear(&mut self) {
398 self.data.clear();
399 self.args.clear();
400 }
401
402 fn get_type_of_expr(&self, ptr: Ptr) -> Option<&Self::Var> {
403 let element = self.data.get(ptr.get_idx())?;
404
405 match element {
406 InternalStoreElement::Variable { ty, .. } => Some(ty),
407 InternalStoreElement::Term { ty, .. } => Some(ty),
408 _ => None,
409 }
410 }
411
412 fn get_element(&self, ptr: Ptr) -> Option<ElementRef<Self::Var>> {
413 let element = self.data.get(ptr.get_idx())?;
414
415 match element {
416 InternalStoreElement::Variable { ty, var } => Some(ElementRef::Variable { ty, var }),
417 InternalStoreElement::Term {
418 ty,
419 num_args,
420 id,
421 ptr_args,
422 } => {
423 let ptr_args = *ptr_args as usize;
424 let args = self
425 .args
426 .as_slice()
427 .get(ptr_args..(ptr_args + *num_args as usize))?;
428
429 Some(ElementRef::Term { ty, id, args })
430 }
431 InternalStoreElement::Conv { e1, e2 } => Some(ElementRef::Conv { e1, e2 }),
432 }
433 }
434
435 fn get<'a, T: TryFrom<ElementRef<'a, Self::Var>, Error = Kind>>(
436 &'a self,
437 ptr: Ptr,
438 ) -> KResult<T> {
439 let element = self.get_element(ptr).ok_or(Kind::InvalidStoreIndex)?;
440
441 element.try_into()
442 }
443}
444
445impl Display for Store_ {
446 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
447 for i in 0..self.data.len() {
448 match self.get_element(Ptr(i as u32)) {
449 Some(el) => writeln!(f, "> {}", el.to_display(self))?,
450 None => writeln!(f, "> Invalid ptr")?,
451 }
452 }
453 Ok(())
454 }
455}