1use std::{collections::HashSet, hash::Hash};
2
3use derive_where::derive_where;
4
5use crate::{ThyFunc, Types};
6
7#[derive_where(Hash, Clone, Debug)]
8pub struct Bind<T: Types> {
9 pub name: T::Var,
10 pub sort: Sort<T>,
11 pub pred: Pred<T>,
12}
13
14#[derive_where(Hash, Clone, Debug)]
15pub enum Constraint<T: Types> {
16 Pred(Pred<T>, #[derive_where(skip)] Option<T::Tag>),
17 Conj(Vec<Self>),
18 ForAll(Bind<T>, Box<Self>),
19}
20
21impl<T: Types> Constraint<T> {
22 pub const TRUE: Self = Self::Pred(Pred::TRUE, None);
23
24 pub fn foralls(bindings: Vec<Bind<T>>, c: Self) -> Self {
25 bindings
26 .into_iter()
27 .rev()
28 .fold(c, |c, bind| Constraint::ForAll(bind, Box::new(c)))
29 }
30
31 pub fn conj(mut cstrs: Vec<Self>) -> Self {
32 if cstrs.len() == 1 { cstrs.remove(0) } else { Self::Conj(cstrs) }
33 }
34
35 pub fn concrete_head_count(&self) -> usize {
39 fn go<T: Types>(c: &Constraint<T>, count: &mut usize) {
40 match c {
41 Constraint::Conj(cs) => cs.iter().for_each(|c| go(c, count)),
42 Constraint::ForAll(_, c) => go(c, count),
43 Constraint::Pred(p, _) => {
44 if p.is_concrete() && !p.is_trivially_true() {
45 *count += 1;
46 }
47 }
48 }
49 }
50 let mut count = 0;
51 go(self, &mut count);
52 count
53 }
54}
55
56#[derive_where(Hash, Clone, Debug)]
57pub struct DataDecl<T: Types> {
58 pub name: T::Sort,
59 pub vars: usize,
60 pub ctors: Vec<DataCtor<T>>,
61}
62
63impl<T: Types> DataDecl<T> {
64 pub fn deps(&self, acc: &mut Vec<T::Sort>) {
65 for ctor in &self.ctors {
66 for field in &ctor.fields {
67 field.sort.deps(acc);
68 }
69 }
70 }
71}
72
73#[derive_where(Hash, Clone, Debug)]
74pub struct SortDecl<T: Types> {
75 pub name: T::Sort,
76 pub vars: usize,
77}
78
79#[derive_where(Hash, Clone, Debug)]
80pub struct DataCtor<T: Types> {
81 pub name: T::Var,
82 pub fields: Vec<DataField<T>>,
83}
84
85#[derive_where(Hash, Clone, Debug)]
86pub struct DataField<T: Types> {
87 pub name: T::Var,
88 pub sort: Sort<T>,
89}
90
91#[derive_where(Hash, Clone, Debug)]
92pub enum Sort<T: Types> {
93 Int,
94 Bool,
95 Real,
96 Str,
97 BitVec(Box<Sort<T>>),
98 BvSize(u32),
99 Var(usize),
100 Func(Box<[Self; 2]>),
101 Abs(usize, Box<Self>),
102 App(SortCtor<T>, Vec<Self>),
103}
104
105impl<T: Types> Sort<T> {
106 pub fn deps(&self, acc: &mut Vec<T::Sort>) {
107 match self {
108 Sort::App(SortCtor::Data(dt_name), args) => {
109 acc.push(dt_name.clone());
110 for arg in args {
111 arg.deps(acc);
112 }
113 }
114 Sort::Func(input_and_output) => {
115 let [input, output] = &**input_and_output;
116 input.deps(acc);
117 output.deps(acc);
118 }
119 Sort::Abs(_, sort) => {
120 sort.deps(acc);
121 }
122 _ => {}
123 }
124 }
125
126 pub fn mk_func<I>(params: usize, inputs: I, output: Sort<T>) -> Sort<T>
127 where
128 I: IntoIterator<Item = Sort<T>>,
129 I::IntoIter: DoubleEndedIterator,
130 {
131 let sort = inputs
132 .into_iter()
133 .rev()
134 .fold(output, |output, input| Sort::Func(Box::new([input, output])));
135
136 (0..params)
137 .rev()
138 .fold(sort, |sort, i| Sort::Abs(i, Box::new(sort)))
139 }
140
141 pub(crate) fn peel_out_abs(&self) -> (usize, &Sort<T>) {
142 let mut n = 0;
143 let mut curr = self;
144 while let Sort::Abs(i, sort) = curr {
145 assert_eq!(*i, n);
146 n += 1;
147 curr = sort;
148 }
149 (n, curr)
150 }
151}
152
153#[derive_where(Hash, Clone, Debug)]
154pub enum SortCtor<T: Types> {
155 Set,
156 Map,
157 Data(T::Sort),
158}
159
160#[derive_where(Hash, Clone, Debug)]
161pub enum Pred<T: Types> {
162 And(Vec<Self>),
163 KVar(T::KVar, Vec<Expr<T>>),
165 Expr(Expr<T>),
166}
167
168impl<T: Types> Pred<T> {
169 pub const TRUE: Self = Pred::Expr(Expr::Constant(Constant::Boolean(true)));
170
171 pub fn and(mut preds: Vec<Self>) -> Self {
172 if preds.is_empty() {
173 Pred::TRUE
174 } else if preds.len() == 1 {
175 preds.remove(0)
176 } else {
177 Self::And(preds)
178 }
179 }
180
181 pub fn is_trivially_true(&self) -> bool {
182 match self {
183 Pred::Expr(Expr::Constant(Constant::Boolean(true))) => true,
184 Pred::And(ps) => ps.is_empty(),
185 _ => false,
186 }
187 }
188
189 pub fn is_concrete(&self) -> bool {
190 match self {
191 Pred::And(ps) => ps.iter().any(Pred::is_concrete),
192 Pred::KVar(_, _) => false,
193 Pred::Expr(_) => true,
194 }
195 }
196
197 #[cfg(feature = "rust-fixpoint")]
198 pub(crate) fn simplify(&mut self) {
199 if let Pred::And(conjuncts) = self {
200 if conjuncts.is_empty() {
201 *self = Pred::TRUE;
202 } else if conjuncts.len() == 1 {
203 *self = conjuncts[0].clone();
204 } else {
205 conjuncts.iter_mut().for_each(|pred| pred.simplify());
206 }
207 }
208 }
209}
210
211#[derive(Hash, Debug, Copy, Clone, PartialEq, Eq)]
212pub enum BinRel {
213 Eq,
214 Ne,
215 Gt,
216 Ge,
217 Lt,
218 Le,
219}
220
221impl BinRel {
222 pub const INEQUALITIES: [BinRel; 4] = [BinRel::Gt, BinRel::Ge, BinRel::Lt, BinRel::Le];
223}
224
225#[derive(Hash, Debug, Copy, Clone, PartialEq, Eq)]
226pub struct BoundVar {
227 pub level: usize,
228 pub idx: usize,
229}
230
231impl BoundVar {
232 pub fn new(level: usize, idx: usize) -> Self {
233 Self { level, idx }
234 }
235}
236
237#[derive_where(Hash, Clone, Debug)]
238pub enum Expr<T: Types> {
239 Constant(Constant<T>),
240 Var(T::Var),
241 App(Box<Self>, Option<Vec<Sort<T>>>, Vec<Self>),
242 Neg(Box<Self>),
243 BinaryOp(BinOp, Box<[Self; 2]>),
244 IfThenElse(Box<[Self; 3]>),
245 And(Vec<Self>),
246 Or(Vec<Self>),
247 Not(Box<Self>),
248 Imp(Box<[Self; 2]>),
249 Iff(Box<[Self; 2]>),
250 Atom(BinRel, Box<[Self; 2]>),
251 Let(T::Var, Box<[Self; 2]>),
252 ThyFunc(ThyFunc),
253 IsCtor(T::Var, Box<Self>),
254 Exists(Vec<(T::Var, Sort<T>)>, Box<Self>),
255}
256
257impl<T: Types> From<Constant<T>> for Expr<T> {
258 fn from(v: Constant<T>) -> Self {
259 Self::Constant(v)
260 }
261}
262
263impl<T: Types> Expr<T> {
264 pub const fn int(val: u128) -> Expr<T> {
265 Expr::Constant(Constant::Numeral(val))
266 }
267
268 pub fn eq(self, other: Self) -> Self {
269 Expr::Atom(BinRel::Eq, Box::new([self, other]))
270 }
271
272 pub fn and(mut exprs: Vec<Self>) -> Self {
273 if exprs.len() == 1 { exprs.remove(0) } else { Self::And(exprs) }
274 }
275
276 pub fn free_vars(&self) -> HashSet<T::Var> {
277 let mut vars = HashSet::new();
278 match self {
279 Expr::Constant(_) | Expr::ThyFunc(_) => {}
280 Expr::Var(x) => {
281 vars.insert(x.clone());
282 }
283 Expr::App(func, _sort_args, args) => {
284 vars.extend(func.free_vars());
285 for arg in args {
286 vars.extend(arg.free_vars());
287 }
288 }
289 Expr::Neg(e) | Expr::Not(e) => {
290 vars = e.free_vars();
291 }
292 Expr::BinaryOp(_, exprs)
293 | Expr::Imp(exprs)
294 | Expr::Iff(exprs)
295 | Expr::Atom(_, exprs) => {
296 let [e1, e2] = &**exprs;
297 vars.extend(e1.free_vars());
298 vars.extend(e2.free_vars());
299 }
300 Expr::IfThenElse(exprs) => {
301 let [p, e1, e2] = &**exprs;
302 vars.extend(p.free_vars());
303 vars.extend(e1.free_vars());
304 vars.extend(e2.free_vars());
305 }
306 Expr::And(exprs) | Expr::Or(exprs) => {
307 for e in exprs {
308 vars.extend(e.free_vars());
309 }
310 }
311 Expr::Let(name, exprs) => {
312 let [var_e, body_e] = &**exprs;
315 vars.extend(var_e.free_vars());
316 let mut body_vars = body_e.free_vars();
317 body_vars.remove(name);
318 vars.extend(body_vars);
319 }
320 Expr::IsCtor(_v, expr) => {
321 vars.extend(expr.free_vars());
324 }
325 Expr::Exists(binder, expr) => {
326 let mut inner = expr.free_vars();
327 for (var, _sort) in binder {
328 inner.remove(var);
329 }
330 vars.extend(inner);
331 }
332 };
333 vars
334 }
335}
336
337#[derive_where(Hash, Clone, Debug)]
338pub enum Constant<T: Types> {
339 Numeral(u128),
340 Real(u128),
346 Boolean(bool),
347 String(T::String),
348 BitVec(u128, u32),
349}
350
351#[derive_where(Debug, Clone, Hash)]
352pub struct Qualifier<T: Types> {
353 pub name: String,
354 pub args: Vec<(T::Var, Sort<T>)>,
355 pub body: Expr<T>,
356}
357
358#[derive(Clone, Copy, PartialEq, Eq, Hash)]
359pub enum BinOp {
360 Add,
361 Sub,
362 Mul,
363 Div,
364 Mod,
365}