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