1use std::{
2 fmt::{self, Write},
3 iter,
4};
5
6use itertools::Itertools;
7
8use crate::{
9 BinOp, BinRel, ConstDecl, Constant, Constraint, DataCtor, DataDecl, DataField, Expr,
10 FixpointFmt, FunDef, FunSort, Identifier, KVarDecl, Pred, Qualifier, Sort, SortCtor, Task,
11 Types,
12};
13
14pub(crate) fn fmt_constraint<T: Types>(
15 cstr: &Constraint<T>,
16 f: &mut fmt::Formatter<'_>,
17) -> fmt::Result {
18 let mut cx = ConstraintFormatter::default();
19 write!(f, "(constraint")?;
20 cx.incr();
21 cx.newline(f)?;
22 cx.fmt_constraint(f, cstr)?;
23 cx.decr();
24 writeln!(f, ")")
25}
26
27impl<T: Types> fmt::Display for Constraint<T> {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 fmt_constraint(self, f)
30 }
31}
32
33impl<T: Types> fmt::Display for Task<T> {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 if self.scrape_quals {
36 writeln!(f, "(fixpoint \"--scrape=both\")")?;
37 }
38 for line in &self.comments {
39 writeln!(f, ";; {line}")?;
40 }
41 writeln!(f)?;
42
43 for data_decl in &self.data_decls {
44 writeln!(f, "{data_decl}")?;
45 }
46
47 for qualif in &self.qualifiers {
48 writeln!(f, "{qualif}")?;
49 }
50
51 for cinfo in &self.constants {
52 writeln!(f, "{cinfo}")?;
53 }
54
55 for fun_decl in &self.define_funs {
56 writeln!(f, "{fun_decl}")?;
57 }
58
59 for kvar in &self.kvars {
60 writeln!(f, "{kvar}")?;
61 }
62
63 writeln!(f)?;
64 fmt_constraint(&self.constraint, f)
65 }
66}
67
68impl<T: Types> fmt::Display for KVarDecl<T> {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 write!(
71 f,
72 "(var ${} ({})) ;; {}",
73 self.kvid.display(),
74 self.sorts.iter().format(" "),
75 self.comment
76 )
77 }
78}
79
80impl<T: Types> fmt::Display for ConstDecl<T> {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 write!(f, "(constant {} {})", self.name.display(), self.sort)?;
83 if let Some(comment) = &self.comment {
84 write!(f, " ;; {comment}")?;
85 }
86 Ok(())
87 }
88}
89
90impl<T: Types> fmt::Debug for Task<T> {
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 fmt::Display::fmt(self, f)
93 }
94}
95
96#[derive(Default)]
97struct ConstraintFormatter {
98 level: u32,
99}
100
101impl ConstraintFormatter {
102 fn fmt_constraint<T: Types>(
103 &mut self,
104 f: &mut fmt::Formatter<'_>,
105 cstr: &Constraint<T>,
106 ) -> fmt::Result {
107 match cstr {
108 Constraint::Pred(pred, tag) => self.fmt_pred_in_head_position(pred, tag.as_ref(), f),
109 Constraint::Conj(cstrs) => {
110 match &cstrs[..] {
111 [] => write!(f, "((true))"),
112 [cstr] => self.fmt_constraint(f, cstr),
113 cstrs => {
114 write!(f, "(and")?;
115 for cstr in cstrs {
116 self.incr();
117 self.newline(f)?;
118 self.fmt_constraint(f, cstr)?;
119 self.decr();
120 }
121 f.write_char(')')
122 }
123 }
124 }
125 Constraint::ForAll(bind, head) => {
126 write!(f, "(forall (({} {}) {})", bind.name.display(), bind.sort, bind.pred)?;
127
128 self.incr();
129 self.newline(f)?;
130 self.fmt_constraint(f, head)?;
131 self.decr();
132
133 f.write_str(")")
134 }
135 }
136 }
137
138 fn fmt_pred_in_head_position<T: Types>(
139 &mut self,
140 pred: &Pred<T>,
141 tag: Option<&T::Tag>,
142 f: &mut fmt::Formatter<'_>,
143 ) -> fmt::Result {
144 match pred {
145 Pred::And(preds) => {
146 match &preds[..] {
147 [] => write!(f, "((true))"),
148 [pred] => self.fmt_pred_in_head_position(pred, tag, f),
149 _ => {
150 write!(f, "(and")?;
151 for pred in preds {
152 self.incr();
153 self.newline(f)?;
154 self.fmt_pred_in_head_position(pred, tag, f)?;
155 self.decr();
156 }
157 write!(f, ")")
158 }
159 }
160 }
161 Pred::Expr(_) | Pred::KVar(..) => {
162 if let Some(tag) = tag {
163 write!(f, "(tag {pred} \"{tag}\")")
164 } else {
165 write!(f, "{pred}")
166 }
167 }
168 }
169 }
170
171 fn incr(&mut self) {
172 self.level += 1;
173 }
174
175 fn decr(&mut self) {
176 self.level -= 1;
177 }
178
179 fn newline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 f.write_char('\n')?;
181 self.padding(f)
182 }
183
184 fn padding(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185 for _ in 0..self.level {
186 f.write_str(" ")?;
187 }
188 Ok(())
189 }
190}
191
192impl<T: Types> fmt::Display for DataDecl<T> {
193 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194 write!(
195 f,
196 "(datatype ({} {}) ({}))",
197 self.name.display(),
198 self.vars,
199 self.ctors.iter().format(" ")
200 )
201 }
202}
203
204impl<T: Types> fmt::Display for DataCtor<T> {
205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206 write!(f, "({} ({}))", self.name.display(), self.fields.iter().format(" "))
207 }
208}
209
210impl<T: Types> fmt::Display for DataField<T> {
211 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
212 write!(f, "({} {})", self.name.display(), self.sort)
213 }
214}
215
216impl<T: Types> fmt::Display for SortCtor<T> {
217 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218 match self {
219 SortCtor::Set => write!(f, "Set_Set"),
220 SortCtor::Map => write!(f, "Map_t"),
221 SortCtor::Data(name) => write!(f, "{}", name.display()),
222 }
223 }
224}
225
226impl<T: Types> fmt::Display for Sort<T> {
227 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
228 match self {
229 Sort::Int => write!(f, "int"),
230 Sort::Bool => write!(f, "bool"),
231 Sort::Real => write!(f, "real"),
232 Sort::Str => write!(f, "Str"),
233 Sort::Var(i) => write!(f, "@({i})"),
234 Sort::BitVec(size) => write!(f, "(BitVec {size})"),
235 Sort::BvSize(size) => write!(f, "Size{size}"),
236 Sort::Abs(..) => {
237 let (params, sort) = self.peel_out_abs();
238 fmt_func(params, sort, f)
239 }
240 Sort::Func(..) => fmt_func(0, self, f),
241 Sort::App(ctor, args) => {
242 write!(f, "({ctor}")?;
243 for arg in args {
244 write!(f, " {arg}")?;
245 }
246 write!(f, ")")
247 }
248 }
249 }
250}
251
252fn fmt_func<T: Types>(params: usize, sort: &Sort<T>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
253 write!(f, "(func {params} (")?;
254 let mut curr = sort;
255 while let Sort::Func(input_and_output) = curr {
256 let [input, output] = &**input_and_output;
257 write!(f, "{input} ")?;
258 curr = output;
259 }
260 write!(f, ") {curr})")
261}
262
263impl<T: Types> fmt::Display for Pred<T> {
264 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265 match self {
266 Pred::And(preds) => {
267 match &preds[..] {
268 [] => write!(f, "((true))"),
269 [pred] => write!(f, "{pred}"),
270 preds => write!(f, "(and {})", preds.iter().join(" ")),
271 }
272 }
273 Pred::KVar(kvid, args) => {
274 write!(f, "(${} {})", kvid.display(), args.iter().join(" "),)
275 }
276 Pred::Expr(expr) => write!(f, "({expr})"),
277 }
278 }
279}
280
281impl<T: Types> fmt::Display for Expr<T> {
282 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
283 match self {
284 Expr::Constant(c) => write!(f, "{c}"),
285 Expr::Var(x) => write!(f, "{}", x.display()),
286 Expr::App(func, _sort_args, args, _out_sort) => {
287 write!(f, "({func} {})", args.iter().format(" "))
288 }
289 Expr::Neg(e) => {
290 write!(f, "(- {e})")
291 }
292 Expr::BinaryOp(op, exprs) => {
293 let [e1, e2] = &**exprs;
294 write!(f, "({op} {e1} {e2})")
295 }
296 Expr::IfThenElse(exprs) => {
297 let [p, e1, e2] = &**exprs;
298 write!(f, "(if {p} {e1} {e2})")
299 }
300 Expr::And(exprs) => {
301 write!(f, "(and {})", exprs.iter().format(" "))
302 }
303 Expr::Or(exprs) => {
304 write!(f, "(or {})", exprs.iter().format(" "))
305 }
306 Expr::Not(e) => {
307 write!(f, "(not {e})")
308 }
309 Expr::Imp(exprs) => {
310 let [e1, e2] = &**exprs;
311 write!(f, "(=> {e1} {e2})")
312 }
313 Expr::Iff(exprs) => {
314 let [e1, e2] = &**exprs;
315 write!(f, "(<=> {e1} {e2})")
316 }
317 Expr::Atom(rel, exprs) => {
318 let [e1, e2] = &**exprs;
319 write!(f, "({rel} {e1} {e2})")
320 }
321 Expr::Let(name, exprs) => {
322 let [e1, e2] = &**exprs;
325 write!(f, "(let (({} {e1})) {e2})", name.display())
326 }
327 Expr::ThyFunc(thy_func) => write!(f, "{}", thy_func),
328 Expr::IsCtor(ctor, e) => {
329 write!(f, "(is${} {})", ctor.display(), e)
330 }
331 Expr::Exists(sorts, body) => {
332 write!(
333 f,
334 "(exists ({}) {})",
335 sorts.iter().map(|binder| &binder.1).format(" "),
336 body
337 )
338 }
339 }
340 }
341}
342
343impl<T: Types> fmt::Display for Constant<T> {
344 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
345 match self {
346 Constant::Numeral(n) => write!(f, "{n}"),
347 Constant::Real(n) => write!(f, "{n}.0"),
348 Constant::Boolean(b) => write!(f, "{b}"),
349 Constant::String(s) => write!(f, "{}", s.display()),
350 Constant::BitVec(i, sz) => {
351 if sz.is_multiple_of(4) {
352 write!(f, "(lit \"#x{i:00$x}\" (BitVec Size{sz}))", (sz / 4) as usize)
353 } else {
354 write!(f, "(lit \"#b{i:00$x}\" (BitVec Size{sz}))", *sz as usize)
355 }
356 }
357 }
358 }
359}
360
361impl<T: Types> fmt::Display for Qualifier<T> {
362 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
363 write!(
364 f,
365 "(qualif {} ({}) ({}))",
366 self.name,
367 self.args.iter().format_with(" ", |(name, sort), f| {
368 f(&format_args!("({} {sort})", name.display()))
369 }),
370 self.body
371 )
372 }
373}
374
375impl<T: Types> fmt::Display for FunDef<T> {
376 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
377 if let Some(body) = &self.body {
378 write!(
379 f,
380 "(define_fun {} ({}) {} ({}))",
381 self.name.display(),
382 iter::zip(&body.args, &self.sort.inputs).format_with(" ", |(name, sort), f| {
383 f(&format_args!("({} {sort})", name.display()))
384 }),
385 self.sort.output,
386 body.expr
387 )?;
388 } else {
389 write!(f, "(constant {} {})", self.name.display(), self.sort)?;
390 }
391 if let Some(comment) = &self.comment {
392 write!(f, " ;; {comment}")?;
393 }
394 Ok(())
395 }
396}
397
398impl<T: Types> fmt::Display for FunSort<T> {
399 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
400 write!(f, "(func {} ({}) {})", self.params, self.inputs.iter().format(" "), self.output)
401 }
402}
403
404impl fmt::Display for BinOp {
405 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
406 match self {
407 BinOp::Add => write!(f, "+"),
408 BinOp::Sub => write!(f, "-"),
409 BinOp::Mul => write!(f, "*"),
410 BinOp::Div => write!(f, "/"),
411 BinOp::Mod => write!(f, "mod"),
412 }
413 }
414}
415
416impl fmt::Display for BinRel {
417 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
418 match self {
419 BinRel::Eq => write!(f, "="),
420 BinRel::Ne => write!(f, "!="),
421 BinRel::Gt => write!(f, ">"),
422 BinRel::Ge => write!(f, ">="),
423 BinRel::Lt => write!(f, "<"),
424 BinRel::Le => write!(f, "<="),
425 }
426 }
427}
428
429impl fmt::Debug for BinOp {
430 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
431 fmt::Display::fmt(self, f)
432 }
433}