logicaffeine_compile/codegen_sva/
verify_to_kernel.rs1use logicaffeine_kernel::{Term, Literal};
10use super::sva_to_verify::BoundedExpr;
11
12pub fn encode_bounded_expr(expr: &BoundedExpr) -> Term {
25 match expr {
26 BoundedExpr::Bool(true) => Term::Global("True".to_string()),
27 BoundedExpr::Bool(false) => Term::Global("False".to_string()),
28
29 BoundedExpr::Int(n) => Term::Lit(Literal::Int(*n)),
30
31 BoundedExpr::Var(name) => {
32 if let Some(at_pos) = name.find('@') {
33 let sig = &name[..at_pos];
34 let t: i64 = name[at_pos + 1..].parse().unwrap_or(0);
35 Term::App(
37 Box::new(Term::Global(sig.to_string())),
38 Box::new(Term::Lit(Literal::Int(t))),
39 )
40 } else {
41 Term::Var(name.clone())
42 }
43 }
44
45 BoundedExpr::And(left, right) => {
46 let l = encode_bounded_expr(left);
47 let r = encode_bounded_expr(right);
48 Term::App(
49 Box::new(Term::App(
50 Box::new(Term::Global("And".to_string())),
51 Box::new(l),
52 )),
53 Box::new(r),
54 )
55 }
56
57 BoundedExpr::Or(left, right) => {
58 let l = encode_bounded_expr(left);
59 let r = encode_bounded_expr(right);
60 Term::App(
61 Box::new(Term::App(
62 Box::new(Term::Global("Or".to_string())),
63 Box::new(l),
64 )),
65 Box::new(r),
66 )
67 }
68
69 BoundedExpr::Not(inner) => {
70 let e = encode_bounded_expr(inner);
71 Term::App(
72 Box::new(Term::Global("Not".to_string())),
73 Box::new(e),
74 )
75 }
76
77 BoundedExpr::Implies(left, right) => {
78 let l = encode_bounded_expr(left);
79 let r = encode_bounded_expr(right);
80 Term::Pi {
82 param: "_".to_string(),
83 param_type: Box::new(l),
84 body_type: Box::new(r),
85 }
86 }
87
88 BoundedExpr::Eq(left, right) => {
89 let l = encode_bounded_expr(left);
90 let r = encode_bounded_expr(right);
91 Term::App(
93 Box::new(Term::App(
94 Box::new(Term::App(
95 Box::new(Term::Global("Eq".to_string())),
96 Box::new(Term::Hole),
97 )),
98 Box::new(l),
99 )),
100 Box::new(r),
101 )
102 }
103
104 BoundedExpr::Lt(left, right) => {
105 let l = encode_bounded_expr(left);
106 let r = encode_bounded_expr(right);
107 Term::App(
108 Box::new(Term::App(
109 Box::new(Term::Global("lt".to_string())),
110 Box::new(l),
111 )),
112 Box::new(r),
113 )
114 }
115
116 BoundedExpr::Gt(left, right) => {
117 let l = encode_bounded_expr(left);
118 let r = encode_bounded_expr(right);
119 Term::App(
120 Box::new(Term::App(
121 Box::new(Term::Global("gt".to_string())),
122 Box::new(l),
123 )),
124 Box::new(r),
125 )
126 }
127
128 BoundedExpr::Lte(left, right) => {
129 let l = encode_bounded_expr(left);
130 let r = encode_bounded_expr(right);
131 Term::App(
132 Box::new(Term::App(
133 Box::new(Term::Global("le".to_string())),
134 Box::new(l),
135 )),
136 Box::new(r),
137 )
138 }
139
140 BoundedExpr::Gte(left, right) => {
141 let l = encode_bounded_expr(left);
142 let r = encode_bounded_expr(right);
143 Term::App(
144 Box::new(Term::App(
145 Box::new(Term::Global("ge".to_string())),
146 Box::new(l),
147 )),
148 Box::new(r),
149 )
150 }
151
152 BoundedExpr::Unsupported(msg) => {
153 let _ = msg;
155 Term::Global("False".to_string())
156 }
157
158 BoundedExpr::BitVecConst { value, .. } => Term::Lit(Literal::Int(*value as i64)),
160 BoundedExpr::BitVecVar(name, _) => Term::Var(name.clone()),
161 BoundedExpr::BitVecBinary { op, left, right } => {
162 let l = encode_bounded_expr(left);
163 let r = encode_bounded_expr(right);
164 let op_name = match op {
165 super::sva_to_verify::BitVecBoundedOp::And => "bit_and",
166 super::sva_to_verify::BitVecBoundedOp::Or => "bit_or",
167 super::sva_to_verify::BitVecBoundedOp::Xor => "bit_xor",
168 super::sva_to_verify::BitVecBoundedOp::Add => "bv_add",
169 super::sva_to_verify::BitVecBoundedOp::Sub => "bv_sub",
170 _ => "bv_op",
171 };
172 Term::App(
173 Box::new(Term::App(
174 Box::new(Term::Global(op_name.to_string())),
175 Box::new(l),
176 )),
177 Box::new(r),
178 )
179 }
180 BoundedExpr::BitVecExtract { operand, .. } => encode_bounded_expr(operand),
181 BoundedExpr::BitVecConcat(l, r) => {
182 let left = encode_bounded_expr(l);
183 let right = encode_bounded_expr(r);
184 Term::App(
185 Box::new(Term::App(
186 Box::new(Term::Global("bv_concat".to_string())),
187 Box::new(left),
188 )),
189 Box::new(right),
190 )
191 }
192 BoundedExpr::ArraySelect { array, index } => {
193 let a = encode_bounded_expr(array);
194 let i = encode_bounded_expr(index);
195 Term::App(
196 Box::new(Term::App(
197 Box::new(Term::Global("select".to_string())),
198 Box::new(a),
199 )),
200 Box::new(i),
201 )
202 }
203 BoundedExpr::ArrayStore { array, index, value } => {
204 let a = encode_bounded_expr(array);
205 let i = encode_bounded_expr(index);
206 let v = encode_bounded_expr(value);
207 Term::App(
208 Box::new(Term::App(
209 Box::new(Term::App(
210 Box::new(Term::Global("store".to_string())),
211 Box::new(a),
212 )),
213 Box::new(i),
214 )),
215 Box::new(v),
216 )
217 }
218 BoundedExpr::IntBinary { op, left, right } => {
219 let l = encode_bounded_expr(left);
220 let r = encode_bounded_expr(right);
221 let op_name = match op {
222 super::sva_to_verify::ArithBoundedOp::Add => "plus",
223 super::sva_to_verify::ArithBoundedOp::Sub => "minus",
224 super::sva_to_verify::ArithBoundedOp::Mul => "mult",
225 super::sva_to_verify::ArithBoundedOp::Div => "div",
226 };
227 Term::App(
228 Box::new(Term::App(
229 Box::new(Term::Global(op_name.to_string())),
230 Box::new(l),
231 )),
232 Box::new(r),
233 )
234 }
235 BoundedExpr::Comparison { op, left, right } => {
236 let l = encode_bounded_expr(left);
237 let r = encode_bounded_expr(right);
238 let op_name = match op {
239 super::sva_to_verify::CmpBoundedOp::Gt => "gt",
240 super::sva_to_verify::CmpBoundedOp::Lt => "lt",
241 super::sva_to_verify::CmpBoundedOp::Gte => "ge",
242 super::sva_to_verify::CmpBoundedOp::Lte => "le",
243 };
244 Term::App(
245 Box::new(Term::App(
246 Box::new(Term::Global(op_name.to_string())),
247 Box::new(l),
248 )),
249 Box::new(r),
250 )
251 }
252 BoundedExpr::ForAll { var, body, .. } => {
253 let b = encode_bounded_expr(body);
254 Term::Pi {
255 param: var.clone(),
256 param_type: Box::new(Term::Hole),
257 body_type: Box::new(b),
258 }
259 }
260 BoundedExpr::Exists { var, body, .. } => {
261 let b = encode_bounded_expr(body);
262 Term::App(
263 Box::new(Term::Global("Ex".to_string())),
264 Box::new(Term::Lambda {
265 param: var.clone(),
266 param_type: Box::new(Term::Hole),
267 body: Box::new(b),
268 }),
269 )
270 }
271 BoundedExpr::Apply { name, args } => {
272 let mut term = Term::Global(name.clone());
274 for arg in args {
275 term = Term::App(
276 Box::new(term),
277 Box::new(encode_bounded_expr(arg)),
278 );
279 }
280 term
281 }
282 }
283}
284
285#[allow(dead_code)]
287fn nat_literal(n: usize) -> Term {
288 let mut term = Term::Global("Zero".to_string());
289 for _ in 0..n {
290 term = Term::App(
291 Box::new(Term::Global("Succ".to_string())),
292 Box::new(term),
293 );
294 }
295 term
296}