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