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