1use std::{
2 collections::{HashMap, HashSet},
3 hash::Hash,
4};
5
6use derive_where::derive_where;
7use indexmap::IndexSet;
8
9use crate::{ThyFunc, Types};
10
11#[derive_where(Hash, Clone, Debug)]
12pub struct Bind<T: Types> {
13 pub name: T::Var,
14 pub sort: Sort<T>,
15 pub pred: Pred<T>,
16}
17
18#[derive_where(Hash, Clone, Debug)]
19pub enum Constraint<T: Types> {
20 Pred(Pred<T>, #[derive_where(skip)] Option<T::Tag>),
21 Conj(Vec<Self>),
22 ForAll(Bind<T>, Box<Self>),
23}
24
25impl<T: Types> Constraint<T> {
26 pub const TRUE: Self = Self::Pred(Pred::TRUE, None);
27
28 pub fn foralls(bindings: Vec<Bind<T>>, c: Self) -> Self {
29 bindings
30 .into_iter()
31 .rev()
32 .fold(c, |c, bind| Constraint::ForAll(bind, Box::new(c)))
33 }
34
35 pub fn conj(mut cstrs: Vec<Self>) -> Self {
36 if cstrs.len() == 1 { cstrs.remove(0) } else { Self::Conj(cstrs) }
37 }
38
39 fn variable_sorts_help(&self, acc: &mut HashMap<T::Var, Sort<T>>) {
40 match self {
41 Constraint::ForAll(bind, inner) => {
42 acc.insert(bind.name.clone(), bind.sort.clone());
43 inner.variable_sorts_help(acc);
44 }
45 Constraint::Conj(cstrs) => {
46 cstrs.iter().for_each(|cstr| cstr.variable_sorts_help(acc));
47 }
48 Constraint::Pred(..) => {}
49 }
50 }
51
52 pub fn variable_sorts(&self) -> HashMap<T::Var, Sort<T>> {
53 let mut res = HashMap::new();
54 self.variable_sorts_help(&mut res);
55 res
56 }
57
58 pub fn concrete_head_count(&self) -> usize {
62 fn go<T: Types>(c: &Constraint<T>, count: &mut usize) {
63 match c {
64 Constraint::Conj(cs) => cs.iter().for_each(|c| go(c, count)),
65 Constraint::ForAll(_, c) => go(c, count),
66 Constraint::Pred(p, _) => {
67 if p.is_concrete() && !p.is_trivially_true() {
68 *count += 1;
69 }
70 }
71 }
72 }
73 let mut count = 0;
74 go(self, &mut count);
75 count
76 }
77}
78
79#[derive_where(Hash, Clone, Debug)]
80pub struct DataDecl<T: Types> {
81 pub name: T::Sort,
82 pub vars: usize,
83 pub ctors: Vec<DataCtor<T>>,
84}
85
86impl<T: Types> DataDecl<T> {
87 pub fn deps(&self, acc: &mut Vec<T::Sort>) {
88 for ctor in &self.ctors {
89 for field in &ctor.fields {
90 field.sort.deps(acc);
91 }
92 }
93 }
94}
95
96#[derive_where(Hash, Clone, Debug)]
97pub struct SortDecl<T: Types> {
98 pub name: T::Sort,
99 pub vars: usize,
100}
101
102#[derive_where(Hash, Clone, Debug)]
103pub struct DataCtor<T: Types> {
104 pub name: T::Var,
105 pub fields: Vec<DataField<T>>,
106}
107
108#[derive_where(Hash, Clone, Debug)]
109pub struct DataField<T: Types> {
110 pub name: T::Var,
111 pub sort: Sort<T>,
112}
113
114#[derive_where(Hash, Clone, Debug)]
115pub enum Sort<T: Types> {
116 Int,
117 Bool,
118 Real,
119 Str,
120 BitVec(Box<Sort<T>>),
121 BvSize(u32),
122 Var(usize),
123 Func(Box<[Self; 2]>),
124 Abs(usize, Box<Self>),
125 App(SortCtor<T>, Vec<Self>),
126}
127
128impl<T: Types> Sort<T> {
129 pub fn deps(&self, acc: &mut Vec<T::Sort>) {
130 match self {
131 Sort::App(SortCtor::Data(dt_name), args) => {
132 acc.push(dt_name.clone());
133 for arg in args {
134 arg.deps(acc);
135 }
136 }
137 Sort::Func(input_and_output) => {
138 let [input, output] = &**input_and_output;
139 input.deps(acc);
140 output.deps(acc);
141 }
142 Sort::Abs(_, sort) => {
143 sort.deps(acc);
144 }
145 _ => {}
146 }
147 }
148
149 pub fn mk_func<I>(params: usize, inputs: I, output: Sort<T>) -> Sort<T>
150 where
151 I: IntoIterator<Item = Sort<T>>,
152 I::IntoIter: DoubleEndedIterator,
153 {
154 let sort = inputs
155 .into_iter()
156 .rev()
157 .fold(output, |output, input| Sort::Func(Box::new([input, output])));
158
159 (0..params)
160 .rev()
161 .fold(sort, |sort, i| Sort::Abs(i, Box::new(sort)))
162 }
163
164 pub(crate) fn peel_out_abs(&self) -> (usize, &Sort<T>) {
165 let mut n = 0;
166 let mut curr = self;
167 while let Sort::Abs(i, sort) = curr {
168 assert_eq!(*i, n);
169 n += 1;
170 curr = sort;
171 }
172 (n, curr)
173 }
174
175 fn free_var_sorts_to_int_help(&mut self, bound: &mut HashSet<usize>) {
176 match self {
177 Sort::Int
178 | Sort::Real
179 | Sort::Bool
180 | Sort::Str
181 | Sort::BvSize(..)
182 | Sort::BitVec(..) => {}
183 Sort::Abs(var, inner) => {
184 bound.insert(*var);
185 inner.free_var_sorts_to_int_help(bound);
186 bound.remove(var);
187 }
188 Sort::App(_, args) => {
189 for arg in args {
190 arg.free_var_sorts_to_int_help(bound);
191 }
192 }
193 Sort::Func(inner) => {
194 let [arg, out] = &mut **inner;
195 arg.free_var_sorts_to_int_help(bound);
196 out.free_var_sorts_to_int_help(bound);
197 }
198 Sort::Var(v) => {
199 if !bound.contains(v) {
200 *self = Sort::Int;
201 }
202 }
203 }
204 }
205
206 pub(crate) fn free_var_sorts_to_int(&mut self) {
207 let mut bound = HashSet::new();
208 self.free_var_sorts_to_int_help(&mut bound);
209 }
210}
211
212#[derive_where(Hash, Debug)]
213pub struct FunSort<T: Types> {
214 pub params: usize,
215 pub inputs: Vec<Sort<T>>,
216 pub output: Sort<T>,
217}
218
219impl<T: Types> FunSort<T> {
220 pub fn deps(&self, acc: &mut Vec<T::Sort>) {
221 for sort in &self.inputs {
222 sort.deps(acc);
223 }
224 self.output.deps(acc);
225 }
226
227 pub fn into_sort(self) -> Sort<T> {
228 Sort::mk_func(self.params, self.inputs, self.output)
229 }
230}
231
232#[derive_where(Hash, Clone, Debug)]
233pub enum SortCtor<T: Types> {
234 Set,
235 Map,
236 Data(T::Sort),
237}
238
239#[derive_where(Hash, Clone, Debug)]
240pub enum Pred<T: Types> {
241 And(Vec<Self>),
242 KVar(T::KVar, Vec<Expr<T>>),
243 Expr(Expr<T>),
244}
245
246impl<T: Types> Pred<T> {
247 pub const TRUE: Self = Pred::Expr(Expr::Constant(Constant::Boolean(true)));
248
249 pub fn and(mut preds: Vec<Self>) -> Self {
250 if preds.is_empty() {
251 Pred::TRUE
252 } else if preds.len() == 1 {
253 preds.remove(0)
254 } else {
255 Self::And(preds)
256 }
257 }
258
259 pub fn is_trivially_true(&self) -> bool {
260 match self {
261 Pred::Expr(Expr::Constant(Constant::Boolean(true))) => true,
262 Pred::And(ps) => ps.is_empty(),
263 _ => false,
264 }
265 }
266
267 pub fn is_concrete(&self) -> bool {
268 match self {
269 Pred::And(ps) => ps.iter().any(Pred::is_concrete),
270 Pred::KVar(_, _) => false,
271 Pred::Expr(_) => true,
272 }
273 }
274
275 #[cfg(feature = "rust-fixpoint")]
276 pub(crate) fn simplify(&mut self) {
277 if let Pred::And(conjuncts) = self {
278 if conjuncts.is_empty() {
279 *self = Pred::TRUE;
280 } else if conjuncts.len() == 1 {
281 *self = conjuncts[0].clone();
282 } else {
283 conjuncts.iter_mut().for_each(|pred| pred.simplify());
284 }
285 }
286 }
287}
288
289#[derive(Hash, Debug, Copy, Clone, PartialEq, Eq)]
290pub enum BinRel {
291 Eq,
292 Ne,
293 Gt,
294 Ge,
295 Lt,
296 Le,
297}
298
299impl BinRel {
300 pub const INEQUALITIES: [BinRel; 4] = [BinRel::Gt, BinRel::Ge, BinRel::Lt, BinRel::Le];
301}
302
303#[derive(Hash, Debug, Copy, Clone, PartialEq, Eq)]
304pub struct BoundVar {
305 pub level: usize,
306 pub idx: usize,
307}
308
309impl BoundVar {
310 pub fn new(level: usize, idx: usize) -> Self {
311 Self { level, idx }
312 }
313}
314
315#[derive_where(Hash, Clone, Debug)]
316pub enum Expr<T: Types> {
317 Constant(Constant<T>),
318 Var(T::Var),
319 App(Box<Self>, Option<Vec<Sort<T>>>, Vec<Self>, Option<Sort<T>>),
320 Neg(Box<Self>),
321 BinaryOp(BinOp, Box<[Self; 2]>),
322 IfThenElse(Box<[Self; 3]>),
323 And(Vec<Self>),
324 Or(Vec<Self>),
325 Not(Box<Self>),
326 Imp(Box<[Self; 2]>),
327 Iff(Box<[Self; 2]>),
328 Atom(BinRel, Box<[Self; 2]>),
329 Let(T::Var, Box<[Self; 2]>),
330 ThyFunc(ThyFunc),
331 IsCtor(T::Var, Box<Self>),
332 Exists(Vec<(T::Var, Sort<T>)>, Box<Self>),
333}
334
335impl<T: Types> From<Constant<T>> for Expr<T> {
336 fn from(v: Constant<T>) -> Self {
337 Self::Constant(v)
338 }
339}
340
341impl<T: Types> Expr<T> {
342 pub const fn int(val: u128) -> Expr<T> {
343 Expr::Constant(Constant::Numeral(val))
344 }
345
346 pub fn eq(self, other: Self) -> Self {
347 Expr::Atom(BinRel::Eq, Box::new([self, other]))
348 }
349
350 pub fn and(mut exprs: Vec<Self>) -> Self {
351 if exprs.len() == 1 { exprs.remove(0) } else { Self::And(exprs) }
352 }
353
354 pub fn var_sorts_to_int(&mut self) {
355 match self {
356 Expr::Constant(_) | Expr::ThyFunc(_) | Expr::Var(_) => {}
357 Expr::App(func, sort_args, args, out_sort) => {
358 func.var_sorts_to_int();
359 for arg in args {
360 arg.var_sorts_to_int();
361 }
362 if let Some(sort_args) = sort_args {
363 for sort_arg in sort_args {
364 sort_arg.free_var_sorts_to_int();
365 }
366 }
367 if let Some(out_sort) = out_sort {
368 out_sort.free_var_sorts_to_int();
369 }
370 }
371 Expr::Neg(e) | Expr::Not(e) => {
372 e.var_sorts_to_int();
373 }
374 Expr::BinaryOp(_, exprs)
375 | Expr::Imp(exprs)
376 | Expr::Iff(exprs)
377 | Expr::Atom(_, exprs) => {
378 let [e1, e2] = &mut **exprs;
379 e1.var_sorts_to_int();
380 e2.var_sorts_to_int();
381 }
382 Expr::IfThenElse(exprs) => {
383 let [p, e1, e2] = &mut **exprs;
384 p.var_sorts_to_int();
385 e1.var_sorts_to_int();
386 e2.var_sorts_to_int();
387 }
388 Expr::And(exprs) | Expr::Or(exprs) => {
389 for e in exprs {
390 e.var_sorts_to_int();
391 }
392 }
393 Expr::Let(_, exprs) => {
394 let [var_e, body_e] = &mut **exprs;
395 var_e.var_sorts_to_int();
396 body_e.var_sorts_to_int();
397 }
398 Expr::IsCtor(_v, expr) => {
399 expr.var_sorts_to_int();
400 }
401 Expr::Exists(binder, expr) => {
402 for (_, sort) in binder {
403 sort.free_var_sorts_to_int();
404 }
405 expr.var_sorts_to_int();
406 }
407 }
408 }
409
410 pub fn free_vars(&self) -> IndexSet<T::Var> {
411 let mut vars = IndexSet::new();
412 match self {
413 Expr::Constant(_) | Expr::ThyFunc(_) => {}
414 Expr::Var(x) => {
415 vars.insert(x.clone());
416 }
417 Expr::App(func, _sort_args, args, _out_sort) => {
418 vars.extend(func.free_vars());
419 for arg in args {
420 vars.extend(arg.free_vars());
421 }
422 }
423 Expr::Neg(e) | Expr::Not(e) => {
424 vars = e.free_vars();
425 }
426 Expr::BinaryOp(_, exprs)
427 | Expr::Imp(exprs)
428 | Expr::Iff(exprs)
429 | Expr::Atom(_, exprs) => {
430 let [e1, e2] = &**exprs;
431 vars.extend(e1.free_vars());
432 vars.extend(e2.free_vars());
433 }
434 Expr::IfThenElse(exprs) => {
435 let [p, e1, e2] = &**exprs;
436 vars.extend(p.free_vars());
437 vars.extend(e1.free_vars());
438 vars.extend(e2.free_vars());
439 }
440 Expr::And(exprs) | Expr::Or(exprs) => {
441 for e in exprs {
442 vars.extend(e.free_vars());
443 }
444 }
445 Expr::Let(name, exprs) => {
446 let [var_e, body_e] = &**exprs;
449 vars.extend(var_e.free_vars());
450 let mut body_vars = body_e.free_vars();
451 body_vars.swap_remove(name);
452 vars.extend(body_vars);
453 }
454 Expr::IsCtor(_v, expr) => {
455 vars.extend(expr.free_vars());
458 }
459 Expr::Exists(binder, expr) => {
460 let mut inner = expr.free_vars();
461 for (var, _sort) in binder {
462 inner.swap_remove(var);
463 }
464 vars.extend(inner);
465 }
466 };
467 vars
468 }
469}
470
471#[derive_where(Hash, Clone, Debug)]
472pub enum Constant<T: Types> {
473 Numeral(u128),
474 Real(u128),
480 Boolean(bool),
481 String(T::String),
482 BitVec(u128, u32),
483}
484
485#[derive_where(Debug, Clone, Hash)]
486pub struct Qualifier<T: Types> {
487 pub name: String,
488 pub args: Vec<(T::Var, Sort<T>)>,
489 pub body: Expr<T>,
490}
491
492#[derive(Clone, Copy, PartialEq, Eq, Hash)]
493pub enum BinOp {
494 Add,
495 Sub,
496 Mul,
497 Div,
498 Mod,
499}