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