rsmt2_zz/
solver.rs

1//! Wrapper around an SMT Lib 2 compliant solver.
2//!
3//! The underlying solver runs in a separate process, communication goes through system pipes.
4
5use std::fs::File;
6use std::io::{BufReader, BufWriter, Write};
7use std::process::{Child, ChildStdin, ChildStdout, Command, Stdio};
8
9use crate::{
10    common::*,
11    conf::SmtConf,
12    parse::{ExprParser, IdentParser, ModelParser, RSmtParser, ValueParser},
13};
14
15/// Prefix of an actlit identifier.
16#[allow(non_upper_case_globals)]
17pub static actlit_pref: &str = "|rsmt2 actlit ";
18/// Suffix of an actlit identifier.
19#[allow(non_upper_case_globals)]
20pub static actlit_suff: &str = "|";
21
22/// An activation literal is an opaque wrapper around a `usize`.
23///
24/// Obtained by a solver's [`get_actlit`][get actlit].
25///
26/// [get actlit]: ../trait.Solver.html#method.get_actlit (get_actlit documentation)
27#[derive(Debug)]
28pub struct Actlit {
29    /// ID of the actlit.
30    id: usize,
31}
32impl Actlit {
33    /// Unique number of this actlit.
34    pub fn uid(&self) -> usize {
35        self.id
36    }
37    /// Writes the actlit as an SMT-LIB 2 symbol.
38    pub fn write<W>(&self, w: &mut W) -> SmtRes<()>
39    where
40        W: Write,
41    {
42        write!(w, "{}{}{}", actlit_pref, self.id, actlit_suff)?;
43        Ok(())
44    }
45}
46impl Expr2Smt<()> for Actlit {
47    fn expr_to_smt2<Writer>(&self, w: &mut Writer, _: ()) -> SmtRes<()>
48    where
49        Writer: ::std::io::Write,
50    {
51        self.write(w)
52    }
53}
54impl ::std::ops::Deref for Actlit {
55    type Target = usize;
56    fn deref(&self) -> &usize {
57        &self.id
58    }
59}
60
61/// Promise for an asynchronous check-sat.
62pub struct FutureCheckSat {
63    _nothing: (),
64}
65fn future_check_sat() -> FutureCheckSat {
66    FutureCheckSat { _nothing: () }
67}
68
69/// Solver providing most of the SMT-LIB 2.5 commands.
70///
71/// Note the [`tee` function][tee fun], which takes a file writer to which it will write everything
72/// sent to the solver.
73///
74/// [tee fun]: #method.tee (tee function)
75pub struct Solver<Parser> {
76    /// Solver configuration.
77    conf: SmtConf,
78    /// Actual solver process.
79    kid: Child,
80    /// Solver's stdin.
81    stdin: BufWriter<ChildStdin>,
82    /// Tee file writer.
83    tee: Option<BufWriter<File>>,
84    /// Parser on the solver's stdout.
85    smt_parser: RSmtParser,
86    /// User-defined parser.
87    parser: Parser,
88    /// Actlit counter.
89    actlit: usize,
90}
91
92impl<Parser> Write for Solver<Parser> {
93    fn write(&mut self, buf: &[u8]) -> ::std::io::Result<usize> {
94        if let Some(tee) = self.tee.as_mut() {
95            let _ = tee.write(buf);
96        }
97        self.stdin.write(buf)
98    }
99    fn flush(&mut self) -> ::std::io::Result<()> {
100        if let Some(tee) = self.tee.as_mut() {
101            let _ = tee.flush();
102        }
103        self.stdin.flush()
104    }
105}
106
107/// Writes something in both the solver and the teed output.
108macro_rules! tee_write {
109  ($slf:expr, |$w:ident| $($tail:tt)*) => ({
110    if let Some(ref mut $w) = $slf.tee {
111      $($tail)* ;
112      writeln!($w) ? ;
113      $w.flush() ?
114    }
115    let $w = & mut $slf.stdin ;
116    $($tail)* ;
117    $w.flush() ?
118  }) ;
119}
120
121impl<Parser> ::std::ops::Drop for Solver<Parser> {
122    fn drop(&mut self) {
123        let _ = self.kill();
124        ()
125    }
126}
127
128/// # Basic functions, not related to SMT-LIB.
129impl<Parser> Solver<Parser> {
130    /// Spawns the solver kid.
131    fn spawn(conf: &SmtConf) -> SmtRes<(Child, BufWriter<ChildStdin>, BufReader<ChildStdout>)> {
132        let mut kid = Command::new(
133            // Command.
134            conf.get_cmd(),
135        )
136        .args(
137            // Options.
138            conf.get_options(),
139        )
140        .stdin(Stdio::piped())
141        .stdout(Stdio::piped())
142        .stderr(Stdio::piped())
143        .spawn()
144        .chain_err::<_, ErrorKind>(|| {
145            format!(
146                "While spawning child process with {}",
147                conf.get_cmd().to_string()
148            )
149            .into()
150        })?;
151
152        let mut stdin_opt = None;
153        ::std::mem::swap(&mut stdin_opt, &mut kid.stdin);
154
155        let stdin = if let Some(inner) = stdin_opt {
156            BufWriter::new(inner)
157        } else {
158            bail!("could not retrieve solver's stdin")
159        };
160
161        let mut stdout_opt = None;
162        ::std::mem::swap(&mut stdout_opt, &mut kid.stdout);
163
164        let stdout = if let Some(inner) = stdout_opt {
165            BufReader::new(inner)
166        } else {
167            bail!("could not retrieve solver's stdout")
168        };
169
170        Ok((kid, stdin, stdout))
171    }
172
173    /// Constructor.
174    pub fn new(conf: SmtConf, parser: Parser) -> SmtRes<Self> {
175        // Constructing command and spawning kid.
176        let (kid, stdin, stdout) = Self::spawn(&conf)?;
177
178        let smt_parser = RSmtParser::new(stdout);
179
180        let tee = None;
181        let actlit = 0;
182
183        Ok(Solver {
184            kid,
185            stdin,
186            tee,
187            conf,
188            smt_parser,
189            parser,
190            actlit,
191        })
192    }
193    /// Creates a solver kid with the default configuration.
194    ///
195    /// Mostly used in tests, same as `Self::new( SmtConf::z3(), parser )`.
196    pub fn default(parser: Parser) -> SmtRes<Self> {
197        Self::new(SmtConf::z3(), parser)
198    }
199    /// Creates a solver kid with the default z3 configuration.
200    ///
201    /// Mostly used in tests, same as `Self::new( SmtConf::z3(), parser )`.
202    pub fn default_z3(parser: Parser) -> SmtRes<Self> {
203        Self::new(SmtConf::z3(), parser)
204    }
205    /// Creates a solver kid with the default cvc4 configuration.
206    ///
207    /// Mostly used in tests, same as `Self::new( SmtConf::z3(), parser )`.
208    pub fn default_cvc4(parser: Parser) -> SmtRes<Self> {
209        Self::new(SmtConf::cvc4(), parser)
210    }
211    /// Creates a solver kid with the default yices 2 configuration.
212    ///
213    /// Mostly used in tests, same as `Self::new( SmtConf::yices_2(), parser )`.
214    pub fn default_yices_2(parser: Parser) -> SmtRes<Self> {
215        Self::new(SmtConf::yices_2(), parser)
216    }
217
218    /// Returns the configuration of the solver.
219    pub fn conf(&self) -> &SmtConf {
220        &self.conf
221    }
222
223    /// Forces the solver to write all communications to a file.
224    ///
225    /// Errors if the solver was already tee-ed.
226    pub fn tee(&mut self, file: File) -> SmtRes<()> {
227        if self.tee.is_some() {
228            bail!("Trying to tee a solver that's already tee-ed")
229        }
230        let mut tee = BufWriter::with_capacity(1000, file);
231        write!(tee, "; Command:\n; > {}", self.conf.get_cmd())?;
232        for option in self.conf.get_options() {
233            write!(tee, " {}", option)?
234        }
235        writeln!(tee, "\n")?;
236        self.tee = Some(tee);
237        Ok(())
238    }
239
240    /// Forces the solver to write all communications to a file.
241    ///
242    /// Opens `file` with `create` and `write`.
243    pub fn path_tee<P>(&mut self, path: P) -> SmtRes<()>
244    where
245        P: AsRef<::std::path::Path>,
246    {
247        use std::fs::OpenOptions;
248
249        let path: &::std::path::Path = path.as_ref();
250        let file = OpenOptions::new()
251            .create(true)
252            .write(true)
253            .truncate(true)
254            .open(path)
255            .chain_err(|| format!("while opening tee file `{}`", path.to_string_lossy()))?;
256        self.tee(file)
257    }
258
259    /// True if the solver is tee-ed.
260    pub fn is_teed(&self) -> bool {
261        self.tee.is_some()
262    }
263
264    /// Kills the solver kid.
265    ///
266    /// The windows version just prints `(exit)` on the kid's `stdin`. Anything else seems to cause
267    /// problems.
268    ///
269    /// This function is automatically called when the solver is dropped.
270    #[cfg(windows)]
271    pub fn kill(&mut self) -> SmtRes<()> {
272        let _ = writeln!(self.stdin, "(exit)");
273        let _ = self.stdin.flush();
274        let _ = self.kid.kill();
275        Ok(())
276    }
277    /// Kills the solver kid.
278    ///
279    /// The windows version just prints `(exit)` on the kid's `stdin`. Anything else seems to cause
280    /// problems.
281    ///
282    /// This function is automatically called when the solver is dropped.
283    #[cfg(not(windows))]
284    pub fn kill(&mut self) -> SmtRes<()> {
285        let _ = writeln!(self.stdin, "(exit)");
286        let _ = self.stdin.flush();
287        let _ = self.kid.kill();
288        let join = self
289            .kid
290            .try_wait()
291            .chain_err(|| "waiting for child process to exit")?;
292        if join.is_none() {
293            self.kid
294                .kill()
295                .chain_err::<_, ErrorKind>(|| "while killing child process".into())?
296        }
297        Ok(())
298    }
299
300    /// Internal comment function.
301    #[inline]
302    fn cmt(file: &mut BufWriter<File>, blah: &str) -> SmtRes<()> {
303        for line in blah.lines() {
304            writeln!(file, "; {}", line)?
305        }
306        file.flush()?;
307        Ok(())
308    }
309
310    /// Prints a comment in the tee-ed file if any.
311    #[inline]
312    pub fn comment_args(&mut self, args: ::std::fmt::Arguments) -> SmtRes<()> {
313        if let Some(ref mut file) = self.tee {
314            Self::cmt(file, &format!("{}", args))?
315        }
316        Ok(())
317    }
318
319    /// Prints a comment in the tee-ed file if any. String version.
320    #[inline]
321    pub fn comment(&mut self, blah: &str) -> SmtRes<()> {
322        if let Some(ref mut file) = self.tee {
323            Self::cmt(file, blah)?
324        }
325        Ok(())
326    }
327}
328
329/// # Basic SMT-LIB parser-agnostic commands.
330impl<Parser> Solver<Parser> {
331    /// Asserts an expression.
332    ///
333    /// # Examples
334    ///
335    /// ```
336    /// # use rsmt2::Solver ;
337    /// let mut solver = Solver::default(()).unwrap() ;
338    /// solver.assert("(= 0 1)").unwrap() ;
339    /// ```
340    #[inline]
341    pub fn assert<Expr>(&mut self, expr: &Expr) -> SmtRes<()>
342    where
343        Expr: ?Sized + Expr2Smt<()>,
344    {
345        self.assert_with(expr, ())
346    }
347
348    /// Check-sat command, turns `unknown` results into errors.
349    ///
350    /// # See also
351    ///
352    /// - [`print_check_sat`][print]
353    /// - [`parse_check_sat`][get]
354    ///
355    /// If you want a more natural way to handle unknown results, see `parse_check_sat_or_unk`.
356    ///
357    /// # Examples
358    ///
359    /// ```
360    /// # use rsmt2::Solver ;
361    /// # let mut solver = Solver::default(()).unwrap() ;
362    /// solver.declare_const("x", "Int").unwrap() ;
363    /// solver.declare_const("y", "Int").unwrap() ;
364    ///
365    /// solver.push(1).unwrap() ;
366    /// solver.assert("(= (+ x y) 0)").unwrap() ;
367    /// let maybe_sat = solver.check_sat().unwrap() ;
368    /// assert_eq! { maybe_sat, true }
369    /// solver.pop(1).unwrap() ;
370    ///
371    /// solver.assert("(= (+ (* x x y) (* y y x)) 7654321)").unwrap() ;
372    /// let sat_res = & solver.check_sat() ;
373    ///
374    /// match * sat_res {
375    ///     Err(ref e) => match * e.kind() {
376    ///         ::rsmt2::errors::ErrorKind::Unknown => (),
377    ///         _ => panic!("expected unknown"),
378    ///     },
379    ///     Ok(res) => panic!("expected error: {:?}", res),
380    /// }
381    /// ```
382    ///
383    /// [print]: #method.print_check_sat
384    /// (print_check_sat function)
385    /// [get]: #method.parse_check_sat
386    /// (parse_check_sat function)
387    pub fn check_sat(&mut self) -> SmtRes<bool> {
388        let future = self.print_check_sat()?;
389        self.parse_check_sat(future)
390    }
391
392    /// Check-sat command, turns `unknown` results in `None`.
393    ///
394    /// # See also
395    ///
396    /// - [`parse_check_sat_or_unk`][get]
397    ///
398    /// # Examples
399    ///
400    /// ```
401    /// # use rsmt2::Solver ;
402    /// # let mut solver = Solver::default(()).unwrap() ;
403    /// solver.declare_const("x", "Int").unwrap() ;
404    /// solver.declare_const("y", "Int").unwrap() ;
405    ///
406    /// solver.push(1).unwrap() ;
407    /// solver.assert("(= (+ x y) 0)").unwrap() ;
408    /// let maybe_sat = solver.check_sat_or_unk().unwrap() ;
409    /// assert_eq! { maybe_sat, Some(true) }
410    /// solver.pop(1).unwrap() ;
411    ///
412    /// solver.assert("(= (+ (* x x y) (* y y x)) 7654321)").unwrap() ;
413    /// let maybe_sat = solver.check_sat_or_unk().unwrap() ;
414    /// // Unknown ~~~~~~~~~~~~~vvvv
415    /// assert_eq! { maybe_sat, None }
416    /// ```
417    ///
418    /// [get]: #method.parse_check_sat_or_unk
419    /// (parse_check_sat_or_unk function)
420    pub fn check_sat_or_unk(&mut self) -> SmtRes<Option<bool>> {
421        let future = self.print_check_sat()?;
422        self.parse_check_sat_or_unk(future)
423    }
424
425    /// Resets the underlying solver. Restarts the kid process if no reset command is supported.
426    ///
427    /// # Examples
428    ///
429    /// ```
430    /// # use rsmt2::Solver ;
431    /// let mut solver = Solver::default(()).unwrap() ;
432    /// solver.assert("(= 0 1)").unwrap() ;
433    /// assert! { ! solver.check_sat().unwrap() }
434    /// solver.reset().unwrap() ;
435    /// assert! { solver.check_sat().unwrap() }
436    /// ```
437    #[inline]
438    pub fn reset(&mut self) -> SmtRes<()> {
439        self.actlit = 0;
440        tee_write! {
441          self, |w| write_str(w, "(reset)\n") ?
442        }
443        Ok(())
444    }
445
446    /// Declares a new constant.
447    ///
448    /// # Examples
449    ///
450    /// ```
451    /// # use rsmt2::Solver ;
452    /// let mut solver = Solver::default(()).unwrap() ;
453    /// solver.declare_const("x", "Int").unwrap()
454    /// ```
455    #[inline]
456    pub fn declare_const<Sym, Sort>(&mut self, symbol: &Sym, out_sort: &Sort) -> SmtRes<()>
457    where
458        Sym: ?Sized + Sym2Smt<()>,
459        Sort: ?Sized + Sort2Smt,
460    {
461        self.declare_const_with(symbol, out_sort, ())
462    }
463
464    /// Declares a new function symbol.
465    ///
466    /// ```
467    /// # use rsmt2::Solver ;
468    /// let mut solver = Solver::default(()).unwrap() ;
469    /// solver.declare_fun(
470    ///     "my_symbol", & [ "Int", "Real", "Bool" ], "Bool"
471    /// ).unwrap()
472    /// ```
473    #[inline]
474    pub fn declare_fun<'a, FunSym, ArgSort, Args, OutSort>(
475        &mut self,
476        symbol: &FunSym,
477        args: Args,
478        out: &OutSort,
479    ) -> SmtRes<()>
480    where
481        FunSym: ?Sized + Sym2Smt<()>,
482        ArgSort: ?Sized + Sort2Smt + 'a,
483        OutSort: ?Sized + Sort2Smt,
484        Args: IntoIterator<Item = &'a ArgSort>,
485    {
486        self.declare_fun_with(symbol, args, out, ())
487    }
488
489    /// Defines a new constant function symbol.
490    ///
491    /// # Examples
492    ///
493    /// ```
494    /// # use rsmt2::Solver ;
495    /// let mut solver = Solver::default(()).unwrap() ;
496    /// solver.define_const(
497    ///     "seven", "Int", "7"
498    /// ).unwrap()
499    /// ```
500    #[inline]
501    pub fn define_const<FunSym, OutSort, Body>(
502        &mut self,
503        symbol: &FunSym,
504        out: &OutSort,
505        body: &Body,
506    ) -> SmtRes<()>
507    where
508        OutSort: ?Sized + Sort2Smt,
509        FunSym: ?Sized + Sym2Smt<()>,
510        Body: ?Sized + Expr2Smt<()>,
511    {
512        self.define_const_with(symbol, out, body, ())
513    }
514
515    /// Defines a new function symbol.
516    ///
517    /// # Examples
518    ///
519    /// ```
520    /// # use rsmt2::Solver ;
521    /// let mut solver = Solver::default(()).unwrap() ;
522    /// solver.define_fun(
523    ///     "abs", & [ ("n", "Int") ], "Int", "(ite (< x 0) (- x) x)"
524    /// ).unwrap()
525    /// ```
526    #[inline]
527    pub fn define_fun<'a, FunSym, ArgSym, ArgSort, Args, OutSort, Body>(
528        &mut self,
529        symbol: &FunSym,
530        args: Args,
531        out: &OutSort,
532        body: &Body,
533    ) -> SmtRes<()>
534    where
535        ArgSort: Sort2Smt + 'a,
536        OutSort: ?Sized + Sort2Smt,
537        FunSym: ?Sized + Sym2Smt<()>,
538        ArgSym: Sym2Smt<()> + 'a,
539        Body: ?Sized + Expr2Smt<()>,
540        Args: IntoIterator<Item = &'a (ArgSym, ArgSort)>,
541    {
542        self.define_fun_with(symbol, args, out, body, ())
543    }
544
545    /// Pushes `n` layers on the assertion stack.
546    ///
547    /// # Examples
548    ///
549    /// ```
550    /// # use rsmt2::Solver ;
551    /// let mut solver = Solver::default(()).unwrap() ;
552    /// solver.declare_const("x", "Int").unwrap() ;
553    /// solver.declare_const("y", "Int").unwrap() ;
554    /// solver.assert("(= x y)").unwrap() ;
555    /// let sat = solver.check_sat().unwrap() ;
556    /// assert!(sat) ;
557    ///
558    /// solver.push(1).unwrap() ;
559    /// solver.assert("(= x (+ x 1))").unwrap() ;
560    /// let sat = solver.check_sat().unwrap() ;
561    /// assert!(! sat) ;
562    /// solver.pop(1).unwrap() ;
563    ///
564    /// let sat = solver.check_sat().unwrap() ;
565    /// assert!(sat) ;
566    /// ```
567    #[inline]
568    pub fn push(&mut self, n: u8) -> SmtRes<()> {
569        tee_write! {
570          self, |w| writeln!(w, "(push {})", n) ?
571        }
572        Ok(())
573    }
574
575    /// Pops `n` layers off the assertion stack.
576    ///
577    /// See [`push`][push] for examples.
578    ///
579    /// [push]: #method.push
580    /// (push function for solver)
581    #[inline]
582    pub fn pop(&mut self, n: u8) -> SmtRes<()> {
583        tee_write! {
584          self, |w| writeln!(w, "(pop {})", n) ?
585        }
586        Ok(())
587    }
588
589    /// Check-sat assuming command, turns `unknown` results into errors.
590    pub fn check_sat_assuming<'a, Ident, Idents>(&mut self, idents: Idents) -> SmtRes<bool>
591    where
592        Ident: ?Sized + Sym2Smt<()> + 'a,
593        Idents: IntoIterator<Item = &'a Ident>,
594    {
595        self.check_sat_assuming_with(idents, ())
596    }
597
598    /// Check-sat assuming command, turns `unknown` results into `None`.
599    pub fn check_sat_assuming_or_unk<'a, Ident, Idents>(
600        &mut self,
601        idents: Idents,
602    ) -> SmtRes<Option<bool>>
603    where
604        Ident: ?Sized + Sym2Smt<()> + 'a,
605        Idents: IntoIterator<Item = &'a Ident>,
606    {
607        self.check_sat_assuming_or_unk_with(idents, ())
608    }
609
610    /// Sets the logic.
611    ///
612    /// # Examples
613    ///
614    /// ```
615    /// # use rsmt2::{SmtConf, Solver};
616    /// let mut solver = Solver::default(()).unwrap() ;
617    /// solver.set_logic( ::rsmt2::Logic::QF_UF ).unwrap() ;
618    /// ```
619    #[inline]
620    pub fn set_logic(&mut self, logic: Logic) -> SmtRes<()> {
621        tee_write! {
622          self, |w| {
623            write_str(w, "(set-logic ") ? ;
624            logic.to_smt2(w, ()) ? ;
625            write_str(w, ")\n") ?
626          }
627        }
628        Ok(())
629    }
630
631    /// Defines a recursive function.
632    ///
633    /// # Examples
634    ///
635    /// ```
636    /// # use rsmt2::Solver ;
637    /// let mut solver = Solver::default(()).unwrap() ;
638    /// solver.define_fun_rec(
639    ///     "abs", & [ ("n", "Int") ], "Int", "(ite (< x 0) (abs (- x)) x)"
640    /// ).unwrap()
641    /// ```
642    #[inline]
643    pub fn define_fun_rec<'a, FunSym, ArgSym, ArgSort, Args, OutSort, Body>(
644        &mut self,
645        symbol: &FunSym,
646        args: Args,
647        out: &OutSort,
648        body: &Body,
649    ) -> SmtRes<()>
650    where
651        ArgSort: Sort2Smt + 'a,
652        OutSort: ?Sized + Sort2Smt,
653        FunSym: ?Sized + Sym2Smt<()>,
654        ArgSym: Sym2Smt<()> + 'a,
655        Body: ?Sized + Expr2Smt<()>,
656        Args: IntoIterator<Item = &'a (ArgSym, ArgSort)>,
657    {
658        self.define_fun_rec_with(symbol, args, out, body, ())
659    }
660
661    /// Defines some (possibily mutually) recursive functions.
662    ///
663    /// # Examples
664    ///
665    /// ```
666    /// # use rsmt2::Solver ;
667    /// let mut solver = Solver::default(()).unwrap() ;
668    /// solver.define_funs_rec( & [
669    ///     ("abs_1", & [ ("n", "Int") ], "Int", "(ite (< x 0) (abs_2 (- x)) x)"),
670    ///     ("abs_2", & [ ("n", "Int") ], "Int", "(ite (< x 0) (abs_3 (- x)) x)"),
671    ///     ("abs_3", & [ ("n", "Int") ], "Int", "(ite (< x 0) (abs_1 (- x)) x)"),
672    /// ] ).unwrap()
673    /// ```
674    #[inline]
675    pub fn define_funs_rec<'a, FunSym, ArgSym, ArgSort, Args, ArgsRef, OutSort, Body, Funs>(
676        &mut self,
677        funs: Funs,
678    ) -> SmtRes<()>
679    where
680        FunSym: Sym2Smt<()> + 'a,
681        ArgSym: Sym2Smt<()> + 'a,
682        ArgSort: Sort2Smt + 'a,
683        OutSort: Sort2Smt + 'a,
684        Body: Expr2Smt<()> + 'a,
685        &'a Args: IntoIterator<Item = &'a (ArgSym, ArgSort)> + 'a,
686        Args: ?Sized,
687        ArgsRef: 'a + AsRef<Args>,
688        Funs: IntoIterator<Item = &'a (FunSym, ArgsRef, OutSort, Body)>,
689        Funs::IntoIter: Clone,
690    {
691        self.define_funs_rec_with(funs, ())
692    }
693
694    /// Declares mutually recursive datatypes.
695    ///
696    /// A relatively recent version of z3 is recommended.
697    ///
698    /// # Examples
699    ///
700    /// ```norun
701    /// # use rsmt2::Solver ;
702    /// let mut solver = Solver::default(()).unwrap() ;
703    /// solver.declare_datatypes( & [
704    ///     ( "Tree", 1, ["T"],
705    ///         [ "leaf", "(node (value T) (children (TreeList T)))" ] ),
706    ///     ( "TreeList", 1, ["T"],
707    ///         [ "nil", "(cons (car (Tree T)) (cdr (TreeList T)))" ]),
708    /// ] ).unwrap() ;
709    ///
710    /// solver.declare_const( "t1", "(Tree Int)" ).unwrap() ;
711    /// solver.declare_const( "t2", "(Tree Bool)" ).unwrap() ;
712    ///
713    /// solver.assert("(> (value t1) 20)").unwrap() ;
714    /// solver.assert("(not (is-leaf t2))").unwrap() ;
715    /// solver.assert("(not (value t2))").unwrap() ;
716    ///
717    /// let sat = solver.check_sat().unwrap() ;
718    /// assert! { sat } panic! { "aaa" }
719    /// ```
720    pub fn declare_datatypes<'a, Sort, Param, ParamList, Def, DefList, All>(
721        &mut self,
722        defs: All,
723    ) -> SmtRes<()>
724    where
725        Sort: Sort2Smt + 'a,
726
727        Param: Sort2Smt + 'a,
728        &'a ParamList: IntoIterator<Item = &'a Param> + 'a,
729
730        Def: Sort2Smt + 'a,
731        &'a DefList: IntoIterator<Item = &'a Def> + 'a,
732        All: IntoIterator<Item = &'a (Sort, usize, ParamList, DefList)> + 'a,
733        All::IntoIter: Clone,
734    {
735        tee_write! {
736          self, |w| write!(w, "(declare-datatypes (") ?
737        }
738
739        let def_iter = defs.into_iter();
740
741        for &(ref sort, arity, _, _) in def_iter.clone() {
742            tee_write! {
743              self, |w| {
744                write!(w, " (") ? ;
745                sort.sort_to_smt2(w) ? ;
746                write!(w, " {})", arity) ?
747              }
748            }
749        }
750
751        tee_write! {
752          self, |w| write!(w, " ) (") ?
753        }
754
755        for &(_, arity, ref params, ref defs) in def_iter {
756            tee_write! {
757              self, |w| {
758                write!(w, " (") ? ;
759
760                if arity > 0 {
761                  write!(w, "par (") ? ;
762                  for param in params {
763                    write!(w, " ") ? ;
764                    param.sort_to_smt2(w) ? ;
765                  }
766                  write!(w, " ) (") ?
767                }
768              }
769            }
770
771            for def in defs {
772                tee_write! {
773                  self, |w| {
774                    write!(w, " ") ? ;
775                    def.sort_to_smt2(w) ?
776                  }
777                }
778            }
779
780            tee_write! {
781              self, |w| {
782                write!(w, " )") ? ;
783
784                if arity > 0 {
785                  write!(w, " )") ?
786                }
787              }
788            }
789        }
790
791        tee_write! {
792          self, |w| writeln!(w, " ) )") ?
793        }
794
795        Ok(())
796    }
797}
798
799/// # Basic SMT-LIB commands using the user's parser.
800impl<Parser> Solver<Parser> {
801    /// Get-model command.
802    pub fn get_model<Ident, Type, Value>(&mut self) -> SmtRes<Model<Ident, Type, Value>>
803    where
804        Parser: for<'a> IdentParser<Ident, Type, &'a mut RSmtParser>
805            + for<'a> ModelParser<Ident, Type, Value, &'a mut RSmtParser>,
806    {
807        self.print_get_model()?;
808        self.parse_get_model()
809    }
810
811    /// Get-model command when all the symbols are nullary.
812    pub fn get_model_const<Ident, Type, Value>(&mut self) -> SmtRes<Vec<(Ident, Type, Value)>>
813    where
814        Parser: for<'a> IdentParser<Ident, Type, &'a mut RSmtParser>
815            + for<'a> ModelParser<Ident, Type, Value, &'a mut RSmtParser>,
816    {
817        self.print_get_model()?;
818        self.parse_get_model_const()
819    }
820
821    /// Get-values command.
822    ///
823    /// Notice that the input expression type and the output one have no reason
824    /// to be the same.
825    pub fn get_values<'a, Expr, Exprs, PExpr, PValue>(
826        &mut self,
827        exprs: Exprs,
828    ) -> SmtRes<Vec<(PExpr, PValue)>>
829    where
830        Parser: for<'b> ExprParser<PExpr, (), &'b mut RSmtParser>
831            + for<'b> ValueParser<PValue, &'b mut RSmtParser>,
832        Expr: ?Sized + Expr2Smt<()> + 'a,
833        Exprs: IntoIterator<Item = &'a Expr>,
834    {
835        self.get_values_with(exprs, ())
836            .map_err(|e| self.conf.enrich_get_values_error(e))
837    }
838}
839
840/// # Actlit-related functions.
841///
842/// See the [`actlit`'s module doc][actlits] for more details.
843///
844/// [actlits]: actlit/index.html
845/// (actlit module documentation)
846impl<Parser> Solver<Parser> {
847    // |===| Actlit stuff.
848
849    /// True if no actlits have been created since the last reset.
850    ///
851    /// See the [`actlit`'s module doc][actlits] for more details.
852    ///
853    /// [actlits]: actlit/index.html
854    /// (actlit module documentation)
855    #[inline]
856    fn has_actlits(&self) -> bool {
857        self.actlit > 0
858    }
859
860    /// Introduces a new actlit.
861    ///
862    /// See the [`actlit`'s module doc][actlits] for more details.
863    ///
864    /// [actlits]: actlit/index.html
865    /// (actlit module documentation)
866    #[inline]
867    pub fn get_actlit(&mut self) -> SmtRes<Actlit> {
868        let id = self.actlit;
869        self.actlit += 1;
870        let next_actlit = Actlit { id };
871        tee_write! {
872          self, |w| writeln!(
873            w, "(declare-fun {}{}{} () Bool)",
874            actlit_pref, next_actlit.id, actlit_suff
875          ) ?
876        }
877        Ok(next_actlit)
878    }
879
880    /// Deactivates an activation literal, alias for `solver.set_actlit(actlit, false)`.
881    ///
882    /// See the [`actlit`'s module doc][actlits] for more details.
883    ///
884    /// [actlits]: actlit/index.html
885    /// (actlit module documentation)
886    #[inline]
887    pub fn de_actlit(&mut self, actlit: Actlit) -> SmtRes<()> {
888        self.set_actlit(actlit, false)
889    }
890
891    /// Forces the value of an actlit and consumes it.
892    ///
893    /// See the [`actlit`'s module doc][actlits] for more details.
894    ///
895    /// [actlits]: actlit/index.html
896    /// (actlit module documentation)
897    #[inline]
898    pub fn set_actlit(&mut self, actlit: Actlit, b: bool) -> SmtRes<()> {
899        tee_write! {
900          self, |w| {
901            if b {
902              write!(w, "(assert ") ?
903            } else {
904              write!(w, "(assert (not ") ?
905            }
906            actlit.write(w) ? ;
907            if b {
908              writeln!(w, ")") ?
909            } else {
910              writeln!(w, ") )") ?
911            }
912          }
913        }
914        ::std::mem::drop(actlit);
915        Ok(())
916    }
917
918    /// Asserts an expression without print information, guarded by an activation literal.
919    ///
920    /// See the [`actlit`'s module doc][actlits] for more details.
921    ///
922    /// [actlits]: actlit/index.html
923    /// (actlit module documentation)
924    #[inline]
925    pub fn assert_act<Expr>(&mut self, actlit: &Actlit, expr: &Expr) -> SmtRes<()>
926    where
927        Expr: ?Sized + Expr2Smt<()>,
928    {
929        self.assert_act_with(actlit, expr, ())
930    }
931
932    /// Check-sat command with activation literals, turns `unknown` results into
933    /// errors.
934    pub fn check_sat_act<'a, Actlits>(&mut self, actlits: Actlits) -> SmtRes<bool>
935    where
936        Actlits: IntoIterator<Item = &'a Actlit>,
937    {
938        let future = self.print_check_sat_act(actlits)?;
939        self.parse_check_sat(future)
940    }
941
942    /// Check-sat command with activation literals, turns `unknown` results in
943    /// `None`.
944    pub fn check_sat_act_or_unk<'a, Actlits>(&mut self, actlits: Actlits) -> SmtRes<Option<bool>>
945    where
946        Actlits: IntoIterator<Item = &'a Actlit>,
947    {
948        let future = self.print_check_sat_act(actlits)?;
949        self.parse_check_sat_or_unk(future)
950    }
951}
952
953/// # SMT-LIB asynchronous commands.
954impl<Parser> Solver<Parser> {
955    /// Prints a check-sat command.
956    ///
957    /// Allows to print the `check-sat` and get the result later, *e.g.* with
958    /// [`parse_check_sat`][parse].
959    ///
960    /// # Examples
961    ///
962    /// ```
963    /// use rsmt2::Solver ;
964    ///
965    /// let mut solver = Solver::default(()).unwrap() ;
966    ///
967    /// solver.declare_const("x", "Int").unwrap() ;
968    /// solver.declare_const("y", "Int").unwrap() ;
969    ///
970    /// solver.assert("(= (+ x y) 0)").unwrap() ;
971    ///
972    /// let future = solver.print_check_sat().unwrap() ;
973    /// // Do stuff while the solver works.
974    /// let sat = solver.parse_check_sat(future).unwrap() ;
975    /// assert! { sat }
976    /// ```
977    ///
978    /// [parse]: #method.parse_check_sat
979    /// (parse_check_sat function for Solver)
980    #[inline]
981    pub fn print_check_sat(&mut self) -> SmtRes<FutureCheckSat> {
982        tee_write! {
983          self, |w| write_str(w, "(check-sat)\n") ?
984        }
985        Ok(future_check_sat())
986    }
987
988    /// Check-sat command, with actlits.
989    ///
990    /// See the [`actlit`'s module doc][actlits] for more details.
991    ///
992    /// [actlits]: actlit/index.html
993    /// (actlit module documentation)
994    #[inline]
995    pub fn print_check_sat_act<'a, Actlits>(&mut self, actlits: Actlits) -> SmtRes<FutureCheckSat>
996    where
997        Actlits: IntoIterator<Item = &'a Actlit>,
998    {
999        match self.conf.get_check_sat_assuming() {
1000            Some(ref cmd) => {
1001                tee_write! {
1002                  self, |w| write!(w, "({} (", cmd) ?
1003                }
1004                for actlit in actlits {
1005                    tee_write! {
1006                      self, |w| {
1007                        write!(w, " ") ? ;
1008                        actlit.write(w) ?
1009                      }
1010                    }
1011                }
1012                tee_write! {
1013                  self, |w| write_str(w, ") )\n") ?
1014                }
1015                Ok(future_check_sat())
1016            }
1017            None => {
1018                let msg = format!("{} does not support check-sat-assuming", self.conf.desc());
1019                Err(msg.into())
1020            }
1021        }
1022    }
1023
1024    /// Parse the result of a check-sat, turns `unknown` results into errors.
1025    #[inline]
1026    pub fn parse_check_sat(&mut self, _: FutureCheckSat) -> SmtRes<bool> {
1027        if let Some(res) = self.smt_parser.check_sat()? {
1028            Ok(res)
1029        } else {
1030            Err(ErrorKind::Unknown.into())
1031        }
1032    }
1033
1034    /// Parse the result of a check-sat, turns `unknown` results into `None`.
1035    #[inline]
1036    pub fn parse_check_sat_or_unk(&mut self, _: FutureCheckSat) -> SmtRes<Option<bool>> {
1037        self.smt_parser.check_sat()
1038    }
1039
1040    /// Get-model command.
1041    #[inline]
1042    fn print_get_model(&mut self) -> SmtRes<()> {
1043        tee_write! {
1044          self, |w| write_str(w, "(get-model)\n") ?
1045        }
1046        Ok(())
1047    }
1048
1049    /// Get-assertions command.
1050    #[allow(dead_code)]
1051    fn print_get_assertions(&mut self) -> SmtRes<()> {
1052        tee_write! {
1053          self, |w| write_str(w, "(get-assertions)\n") ?
1054        }
1055        Ok(())
1056    }
1057    /// Get-assignment command.
1058    #[allow(dead_code)]
1059    fn print_get_assignment(&mut self) -> SmtRes<()> {
1060        tee_write! {
1061          self, |w| write_str(w, "(get-assignment)\n") ?
1062        }
1063        Ok(())
1064    }
1065    /// Get-unsat-assumptions command.
1066    #[allow(dead_code)]
1067    fn print_get_unsat_assumptions(&mut self) -> SmtRes<()> {
1068        tee_write! {
1069          self, |w| write_str(w, "(get-unsat-assumptions)\n") ?
1070        }
1071        Ok(())
1072    }
1073    /// Get-proof command.
1074    #[allow(dead_code)]
1075    fn print_get_proof(&mut self) -> SmtRes<()> {
1076        tee_write! {
1077          self, |w| write_str(w, "(get-proof)\n") ?
1078        }
1079        Ok(())
1080    }
1081    /// Get-unsat-core command.
1082    #[allow(dead_code)]
1083    fn print_get_unsat_core(&mut self) -> SmtRes<()> {
1084        tee_write! {
1085          self, |w| write_str(w, "(get-unsat-core)\n") ?
1086        }
1087        Ok(())
1088    }
1089
1090    /// Get-values command.
1091    fn print_get_values_with<'a, Info, Expr, Exprs>(
1092        &mut self,
1093        exprs: Exprs,
1094        info: Info,
1095    ) -> SmtRes<()>
1096    where
1097        Info: Copy,
1098        Expr: ?Sized + Expr2Smt<Info> + 'a,
1099        Exprs: IntoIterator<Item = &'a Expr>,
1100    {
1101        tee_write! {
1102          self, |w| write!(w, "(get-value (") ?
1103        }
1104        for e in exprs {
1105            tee_write! {
1106              self, |w| {
1107                write_str(w, "\n  ") ? ;
1108                e.expr_to_smt2(w, info) ?
1109              }
1110            }
1111        }
1112        tee_write! {
1113          self, |w| write_str(w, "\n) )\n") ?
1114        }
1115        Ok(())
1116    }
1117
1118    /// Check-sat with assumptions command with unit info.
1119    pub fn print_check_sat_assuming<'a, Ident, Idents>(
1120        &mut self,
1121        bool_vars: Idents,
1122    ) -> SmtRes<FutureCheckSat>
1123    where
1124        Ident: ?Sized + Sym2Smt<()> + 'a,
1125        Idents: IntoIterator<Item = &'a Ident>,
1126    {
1127        self.print_check_sat_assuming_with(bool_vars, ())
1128    }
1129
1130    /// Check-sat with assumptions command.
1131    pub fn print_check_sat_assuming_with<'a, Info, Ident, Idents>(
1132        &mut self,
1133        bool_vars: Idents,
1134        info: Info,
1135    ) -> SmtRes<FutureCheckSat>
1136    where
1137        Info: Copy,
1138        Ident: ?Sized + Sym2Smt<Info> + 'a,
1139        Idents: IntoIterator<Item = &'a Ident>,
1140    {
1141        match self.conf.get_check_sat_assuming() {
1142            Some(ref cmd) => {
1143                tee_write! {
1144                  self, |w| write!(w, "({} (\n ", cmd) ?
1145                }
1146                for sym in bool_vars {
1147                    tee_write! {
1148                      self, |w| {
1149                        write_str(w, "  ") ? ;
1150                        sym.sym_to_smt2(w, info) ?
1151                      }
1152                    }
1153                }
1154                tee_write! {
1155                  self, |w| write_str(w, "\n))\n") ?
1156                }
1157                Ok(future_check_sat())
1158            }
1159            None => {
1160                let msg = format!("{} does not support check-sat-assuming", self.conf.desc());
1161                Err(msg.into())
1162            }
1163        }
1164    }
1165
1166    /// Parse the result of a get-model.
1167    fn parse_get_model<Ident, Type, Value>(&mut self) -> SmtRes<Model<Ident, Type, Value>>
1168    where
1169        Parser: for<'a> IdentParser<Ident, Type, &'a mut RSmtParser>
1170            + for<'a> ModelParser<Ident, Type, Value, &'a mut RSmtParser>,
1171    {
1172        let has_actlits = self.has_actlits();
1173        let res = self.smt_parser.get_model(has_actlits, self.parser);
1174        if res.is_err() && !self.conf.get_models() {
1175            res.chain_err(|| {
1176                "\
1177                 Note: model production is not active \
1178                 for this SmtConf (`conf.models()`)\
1179                 "
1180            })
1181        } else {
1182            res
1183        }
1184    }
1185
1186    /// Parse the result of a get-model where all the symbols are nullary.
1187    fn parse_get_model_const<Ident, Type, Value>(&mut self) -> SmtRes<Vec<(Ident, Type, Value)>>
1188    where
1189        Parser: for<'a> IdentParser<Ident, Type, &'a mut RSmtParser>
1190            + for<'a> ModelParser<Ident, Type, Value, &'a mut RSmtParser>,
1191    {
1192        let has_actlits = self.has_actlits();
1193        let res = self.smt_parser.get_model_const(has_actlits, self.parser);
1194        if res.is_err() && !self.conf.get_models() {
1195            res.chain_err(|| {
1196                "\
1197                 Note: model production is not active \
1198                 for this SmtConf (`conf.models()`)\
1199                 "
1200            })
1201        } else {
1202            res
1203        }
1204    }
1205
1206    /// Parse the result of a get-values.
1207    fn parse_get_values_with<Info, Expr, Val>(&mut self, info: Info) -> SmtRes<Vec<(Expr, Val)>>
1208    where
1209        Info: Copy,
1210        Parser: for<'a> ExprParser<Expr, Info, &'a mut RSmtParser>
1211            + for<'a> ValueParser<Val, &'a mut RSmtParser>,
1212    {
1213        let res = self.smt_parser.get_values(self.parser, info);
1214        if res.is_err() && !self.conf.get_models() {
1215            res.chain_err(|| {
1216                "\
1217                 Note: model production is not active \
1218                 for this SmtConf (`conf.models()`)\
1219                 "
1220            })
1221        } else {
1222            res
1223        }
1224    }
1225
1226    /// Get-values command.
1227    ///
1228    /// Notice that the input expression type and the output one have no reason to be the same.
1229    fn get_values_with<'a, Info, Expr, Exprs, PExpr, PValue>(
1230        &mut self,
1231        exprs: Exprs,
1232        info: Info,
1233    ) -> SmtRes<Vec<(PExpr, PValue)>>
1234    where
1235        Info: Copy,
1236        Parser: for<'b> ExprParser<PExpr, Info, &'b mut RSmtParser>
1237            + for<'b> ValueParser<PValue, &'b mut RSmtParser>,
1238        Expr: ?Sized + Expr2Smt<Info> + 'a,
1239        Exprs: IntoIterator<Item = &'a Expr>,
1240    {
1241        self.print_get_values_with(exprs, info)?;
1242        self.parse_get_values_with(info)
1243    }
1244}
1245
1246/// # Sort-related SMT-LIB commands.
1247impl<Parser> Solver<Parser> {
1248    /// Declares a new sort.
1249    ///
1250    /// # Examples
1251    ///
1252    /// ```
1253    /// # use rsmt2::Solver ;
1254    /// let mut solver = Solver::default(()).unwrap() ;
1255    /// solver.declare_sort("A", 0).unwrap() ;
1256    /// solver.declare_const("x", "A").unwrap() ;
1257    /// solver.declare_const("y", "A").unwrap() ;
1258    /// solver.declare_fun("f", & [ "A" ], "A").unwrap() ;
1259    /// solver.assert("(= (f (f x)) x)").unwrap() ;
1260    /// solver.assert("(= (f x) y)").unwrap() ;
1261    /// solver.assert("(not (= x y))").unwrap() ;
1262    /// let sat = solver.check_sat().unwrap() ;
1263    /// ```
1264    #[inline]
1265    pub fn declare_sort<Sort>(&mut self, sort: &Sort, arity: u8) -> SmtRes<()>
1266    where
1267        Sort: ?Sized + Sort2Smt,
1268    {
1269        tee_write! {
1270          self, |w| {
1271            write_str(w, "(declare-sort ") ? ;
1272            sort.sort_to_smt2(w) ? ;
1273            writeln!(w, " {})", arity) ?
1274          }
1275        }
1276        Ok(())
1277    }
1278
1279    /// Defines a new sort.
1280    ///
1281    /// # Examples
1282    ///
1283    /// Note the use of [`define_null_sort`][def] to avoid problems with empty
1284    /// arguments.
1285    ///
1286    /// ```
1287    /// # use rsmt2::Solver ;
1288    /// let mut solver = Solver::default(()).unwrap() ;
1289    /// solver.define_sort("MySet", & ["T"], "(Array T Bool)").unwrap() ;
1290    /// solver.define_null_sort("IList", "(List Int)").unwrap() ;
1291    /// solver.define_sort(
1292    ///     "List-Set", & ["T"], "(Array (List T) Bool)"
1293    /// ).unwrap() ;
1294    /// solver.define_null_sort("I", "Int").unwrap() ;
1295    ///
1296    /// solver.declare_const("s1", "(MySet I)").unwrap() ;
1297    /// solver.declare_const("s2", "(List-Set Int)").unwrap() ;
1298    /// solver.declare_const("a", "I").unwrap() ;
1299    /// solver.declare_const("l", "IList").unwrap() ;
1300    ///
1301    /// solver.assert("(= (select s1 a) true)").unwrap() ;
1302    /// solver.assert("(= (select s2 l) false)").unwrap() ;
1303    /// let sat = solver.check_sat().unwrap() ;
1304    /// ```
1305    ///
1306    /// [def]: #method.define_null_sort
1307    /// (define_null_sort function)
1308    #[inline]
1309    pub fn define_sort<'a, Sort, Arg, Args, Body>(
1310        &mut self,
1311        sort: &Sort,
1312        args: Args,
1313        body: &Body,
1314    ) -> SmtRes<()>
1315    where
1316        Sort: ?Sized + Sort2Smt,
1317        Arg: ?Sized + Sort2Smt + 'a,
1318        Body: ?Sized + Sort2Smt,
1319        Args: IntoIterator<Item = &'a Arg>,
1320    {
1321        tee_write! {
1322          self, |w| {
1323            write_str(w, "( define-sort ") ? ;
1324            sort.sort_to_smt2(w) ? ;
1325            write_str(w, "\n   ( ") ? ;
1326          }
1327        }
1328        for arg in args {
1329            tee_write! {
1330              self, |w| {
1331                arg.sort_to_smt2(w) ? ;
1332                write_str(w, " ") ?
1333              }
1334            }
1335        }
1336        tee_write! {
1337          self, |w| {
1338            write_str(w, ")\n   ") ? ;
1339            body.sort_to_smt2(w) ? ;
1340            write_str(w, "\n)\n") ?
1341          }
1342        }
1343        Ok(())
1344    }
1345
1346    /// Defines a new nullary sort.
1347    ///
1348    /// When using [`define_sort`][def], rust complains because it does not know what the `Arg` type
1349    /// parameter is, since the `args` parameter is empty. So this function can be useful.
1350    ///
1351    /// This could be fixed with a default type for `Arg`, like `Body` for instance, but this is
1352    /// currently not possible in a function.
1353    ///
1354    /// [def]: #method.define_sort
1355    /// (define_sort function)
1356    #[inline]
1357    pub fn define_null_sort<Sort, Body>(&mut self, sort: &Sort, body: &Body) -> SmtRes<()>
1358    where
1359        Sort: ?Sized + Sort2Smt,
1360        Body: ?Sized + Sort2Smt,
1361    {
1362        self.define_sort::<Sort, Body, Option<&Body>, Body>(sort, None, body)
1363    }
1364}
1365
1366/// # SMT-LIB commands vehiculating user information.
1367impl<Parser> Solver<Parser> {
1368    /// Declares a new constant.
1369    #[inline]
1370    pub fn declare_const_with<Info, Sym, Sort>(
1371        &mut self,
1372        symbol: &Sym,
1373        out_sort: &Sort,
1374        info: Info,
1375    ) -> SmtRes<()>
1376    where
1377        Info: Copy,
1378        Sym: ?Sized + Sym2Smt<Info>,
1379        Sort: ?Sized + Sort2Smt,
1380    {
1381        tee_write! {
1382          self, |w| {
1383            write_str(w, "(declare-const ") ? ;
1384            symbol.sym_to_smt2(w, info) ? ;
1385            write_str(w, " ") ? ;
1386            out_sort.sort_to_smt2(w) ? ;
1387            write_str(w, ")\n") ?
1388          }
1389        }
1390        Ok(())
1391    }
1392
1393    /// Declares a new function symbol.
1394    #[inline]
1395    pub fn declare_fun_with<'a, Info, FunSym, ArgSort, Args, OutSort>(
1396        &mut self,
1397        symbol: &FunSym,
1398        args: Args,
1399        out: &OutSort,
1400        info: Info,
1401    ) -> SmtRes<()>
1402    where
1403        Info: Copy,
1404        FunSym: ?Sized + Sym2Smt<Info>,
1405        ArgSort: ?Sized + Sort2Smt + 'a,
1406        OutSort: ?Sized + Sort2Smt,
1407        Args: IntoIterator<Item = &'a ArgSort>,
1408    {
1409        tee_write! {
1410          self, |w| {
1411            write_str(w, "(declare-fun ") ? ;
1412            symbol.sym_to_smt2(w, info) ? ;
1413            write_str(w, " ( ") ?
1414          }
1415        }
1416        for arg in args {
1417            tee_write! {
1418              self, |w| {
1419                arg.sort_to_smt2(w) ? ;
1420                write_str(w, " ") ?
1421              }
1422            }
1423        }
1424        tee_write! {
1425          self, |w| {
1426            write_str(w, ") ") ? ;
1427            out.sort_to_smt2(w) ? ;
1428            write_str(w, ")\n") ?
1429          }
1430        }
1431        Ok(())
1432    }
1433
1434    /// Defines a new constant.
1435    #[inline]
1436    pub fn define_const_with<Info, Sym, Sort, Body>(
1437        &mut self,
1438        symbol: &Sym,
1439        out_sort: &Sort,
1440        body: &Body,
1441        info: Info,
1442    ) -> SmtRes<()>
1443    where
1444        Info: Copy,
1445        Sym: ?Sized + Sym2Smt<Info>,
1446        Sort: ?Sized + Sort2Smt,
1447        Body: ?Sized + Expr2Smt<Info>,
1448    {
1449        tee_write! {
1450          self, |w| {
1451            write_str(w, "(define-const ") ? ;
1452            symbol.sym_to_smt2(w, info) ? ;
1453            write_str(w, " ") ? ;
1454            out_sort.sort_to_smt2(w) ? ;
1455            write_str(w, " ") ? ;
1456            body.expr_to_smt2(w, info) ? ;
1457            write_str(w, ")\n") ?
1458          }
1459        }
1460        Ok(())
1461    }
1462
1463    /// Defines a new function symbol.
1464    #[inline]
1465    pub fn define_fun_with<'a, Info, FunSym, ArgSym, ArgSort, Args, OutSort, Body>(
1466        &mut self,
1467        symbol: &FunSym,
1468        args: Args,
1469        out: &OutSort,
1470        body: &Body,
1471        info: Info,
1472    ) -> SmtRes<()>
1473    where
1474        Info: Copy,
1475        ArgSort: Sort2Smt + 'a,
1476        OutSort: ?Sized + Sort2Smt,
1477        FunSym: ?Sized + Sym2Smt<Info>,
1478        ArgSym: Sym2Smt<Info> + 'a,
1479        Body: ?Sized + Expr2Smt<Info>,
1480        Args: IntoIterator<Item = &'a (ArgSym, ArgSort)>,
1481    {
1482        tee_write! {
1483          self, |w| {
1484            write_str(w, "(define-fun ") ? ;
1485            symbol.sym_to_smt2(w, info) ? ;
1486            write_str(w, " ( ") ?
1487          }
1488        }
1489        for arg in args {
1490            let (ref sym, ref sort) = *arg;
1491            tee_write! {
1492              self, |w| {
1493                write_str(w, "(") ? ;
1494                sym.sym_to_smt2(w, info) ? ;
1495                write_str(w, " ") ? ;
1496                sort.sort_to_smt2(w) ? ;
1497                write_str(w, ") ") ?
1498              }
1499            }
1500        }
1501        tee_write! {
1502          self, |w| {
1503            write_str(w, ") ") ? ;
1504            out.sort_to_smt2(w) ? ;
1505            write_str(w, "\n   ") ? ;
1506            body.expr_to_smt2(w, info) ? ;
1507            write_str(w, "\n)\n") ?
1508          }
1509        }
1510        Ok(())
1511    }
1512
1513    /// Defines some new (possibily mutually) recursive functions.
1514    #[inline]
1515    pub fn define_funs_rec_with<
1516        'a,
1517        Info,
1518        FunSym,
1519        ArgSym,
1520        ArgSort,
1521        Args,
1522        ArgsRef,
1523        OutSort,
1524        Body,
1525        Funs,
1526    >(
1527        &mut self,
1528        funs: Funs,
1529        info: Info,
1530    ) -> SmtRes<()>
1531    where
1532        Info: Copy,
1533        FunSym: Sym2Smt<Info> + 'a,
1534        ArgSym: Sym2Smt<Info> + 'a,
1535        ArgSort: Sort2Smt + 'a,
1536        OutSort: Sort2Smt + 'a,
1537        Body: Expr2Smt<Info> + 'a,
1538        &'a Args: IntoIterator<Item = &'a (ArgSym, ArgSort)> + 'a,
1539        Args: ?Sized,
1540        ArgsRef: 'a + AsRef<Args>,
1541        Funs: IntoIterator<Item = &'a (FunSym, ArgsRef, OutSort, Body)>,
1542        Funs::IntoIter: Clone,
1543    {
1544        // Header.
1545        tee_write! {
1546          self, |w| write_str(w, "(define-funs-rec (\n") ?
1547        }
1548
1549        let fun_iter = funs.into_iter();
1550
1551        // Signatures.
1552        for fun in fun_iter.clone() {
1553            let (ref sym, ref args, ref out, _) = *fun;
1554
1555            tee_write! {
1556              self, |w| {
1557                write_str(w, "   (") ? ;
1558                sym.sym_to_smt2(w, info) ? ;
1559                write_str(w, " ( ") ?
1560              }
1561            }
1562
1563            for arg in args.as_ref() {
1564                tee_write! {
1565                  self, |w| {
1566                    let (ref sym, ref sort) = * arg ;
1567                    write_str(w, "(") ? ;
1568                    sym.sym_to_smt2(w, info) ? ;
1569                    write_str(w, " ") ? ;
1570                    sort.sort_to_smt2(w) ? ;
1571                    write_str(w, ") ") ?
1572                  }
1573                }
1574            }
1575
1576            tee_write! {
1577              self, |w| {
1578                write_str(w, ") ") ? ;
1579                out.sort_to_smt2(w) ? ;
1580                write_str(w, ")\n") ?
1581              }
1582            }
1583        }
1584        tee_write! {
1585          self, |w| write_str(w, " ) (") ?
1586        }
1587
1588        // Bodies
1589        for fun in fun_iter {
1590            let (_, _, _, ref body) = *fun;
1591            tee_write! {
1592              self, |w| {
1593                write_str(w, "\n   ") ? ;
1594                body.expr_to_smt2(w, info) ?
1595              }
1596            }
1597        }
1598        tee_write! {
1599          self, |w| write_str(w, "\n )\n)\n") ?
1600        }
1601        Ok(())
1602    }
1603
1604    /// Defines a new recursive function.
1605    #[inline]
1606    pub fn define_fun_rec_with<'a, Info, FunSym, ArgSym, ArgSort, Args, OutSort, Body>(
1607        &mut self,
1608        symbol: &FunSym,
1609        args: Args,
1610        out: &OutSort,
1611        body: &Body,
1612        info: Info,
1613    ) -> SmtRes<()>
1614    where
1615        Info: Copy,
1616        ArgSort: Sort2Smt + 'a,
1617        OutSort: ?Sized + Sort2Smt,
1618        FunSym: ?Sized + Sym2Smt<Info>,
1619        ArgSym: Sym2Smt<Info> + 'a,
1620        Body: ?Sized + Expr2Smt<Info>,
1621        Args: IntoIterator<Item = &'a (ArgSym, ArgSort)>,
1622    {
1623        // Header.
1624        tee_write! {
1625          self, |w| write_str(w, "(define-fun-rec (\n") ?
1626        }
1627
1628        tee_write! {
1629          self, |w| {
1630            // Signature.
1631            write_str(w, "   (") ? ;
1632            symbol.sym_to_smt2(w, info) ? ;
1633            write_str(w, " ( ") ?
1634          }
1635        }
1636
1637        for arg in args {
1638            let (ref sym, ref sort) = *arg;
1639            tee_write! {
1640              self, |w| {
1641                write_str(w, "(") ? ;
1642                sym.sym_to_smt2(w, info) ? ;
1643                write_str(w, " ") ? ;
1644                sort.sort_to_smt2(w) ? ;
1645                write_str(w, ") ") ?
1646              }
1647            }
1648        }
1649
1650        tee_write! {
1651          self, |w| {
1652            write_str(w, ") ") ? ;
1653            out.sort_to_smt2(w) ? ;
1654            write_str(w, ")\n") ? ;
1655            write_str(w, " ) (") ? ;
1656
1657            // Body.
1658            write_str(w, "\n   ") ? ;
1659            body.expr_to_smt2(w, info) ? ;
1660            write_str(w, "\n )\n)\n") ?
1661          }
1662        }
1663        Ok(())
1664    }
1665
1666    /// Asserts an expression with some print information, guarded by an activation literal.
1667    ///
1668    /// See the [`actlit`'s module doc][actlits] for more details.
1669    ///
1670    /// [actlits]: actlit/index.html (actlit module documentation)
1671    #[inline]
1672    pub fn assert_act_with<Info, Expr>(
1673        &mut self,
1674        actlit: &Actlit,
1675        expr: &Expr,
1676        info: Info,
1677    ) -> SmtRes<()>
1678    where
1679        Info: Copy,
1680        Expr: ?Sized + Expr2Smt<Info>,
1681    {
1682        tee_write! {
1683          self, |w| {
1684            write_str(w, "(assert\n  (=>\n    ") ? ;
1685            actlit.write(w) ? ;
1686            write_str(w, "\n    ") ? ;
1687            expr.expr_to_smt2(w, info) ? ;
1688            write_str(w, "\n  )\n)\n") ?
1689          }
1690        }
1691        Ok(())
1692    }
1693
1694    /// Asserts an expression with some print information.
1695    #[inline]
1696    pub fn assert_with<Info, Expr>(&mut self, expr: &Expr, info: Info) -> SmtRes<()>
1697    where
1698        Info: Copy,
1699        Expr: ?Sized + Expr2Smt<Info>,
1700    {
1701        tee_write! {
1702          self, |w| {
1703            write_str(w, "(assert\n  ") ? ;
1704            expr.expr_to_smt2(w, info) ? ;
1705            write_str(w, "\n)\n") ?
1706          }
1707        }
1708        Ok(())
1709    }
1710
1711    /// Check-sat assuming command, turns `unknown` results into errors.
1712    pub fn check_sat_assuming_with<'a, Info, Ident, Idents>(
1713        &mut self,
1714        idents: Idents,
1715        info: Info,
1716    ) -> SmtRes<bool>
1717    where
1718        Info: Copy,
1719        Ident: ?Sized + Sym2Smt<Info> + 'a,
1720        Idents: IntoIterator<Item = &'a Ident>,
1721    {
1722        let future = self.print_check_sat_assuming_with(idents, info)?;
1723        self.parse_check_sat(future)
1724    }
1725
1726    /// Check-sat assuming command, turns `unknown` results into `None`.
1727    pub fn check_sat_assuming_or_unk_with<'a, Info, Ident, Idents>(
1728        &mut self,
1729        idents: Idents,
1730        info: Info,
1731    ) -> SmtRes<Option<bool>>
1732    where
1733        Info: Copy,
1734        Ident: ?Sized + Sym2Smt<Info> + 'a,
1735        Idents: IntoIterator<Item = &'a Ident>,
1736    {
1737        let future = self.print_check_sat_assuming_with(idents, info)?;
1738        self.parse_check_sat_or_unk(future)
1739    }
1740}
1741
1742/// # Other commands (either untested or not useful right now).
1743impl<Parser> Solver<Parser> {
1744    /// Set option command.
1745    #[inline]
1746    pub fn set_option<Value: ::std::fmt::Display>(
1747        &mut self,
1748        option: &str,
1749        value: Value,
1750    ) -> SmtRes<()> {
1751        match option {
1752            ":interactive_mode" => return Err("illegal set-option on interactive mode".into()),
1753            ":print_success" => {
1754                return Err("illegal set-option on print success, \
1755                            use `SmtConf` to activate it"
1756                    .into())
1757            }
1758            _ => (),
1759        };
1760        tee_write! {
1761          self, |w| writeln!(
1762            w, "(set-option {} {})", option, value
1763          ) ?
1764        }
1765        Ok(())
1766    }
1767
1768    /// Activates unsat core production.
1769    #[inline]
1770    pub fn produce_unsat_core(&mut self) -> SmtRes<()> {
1771        self.set_option(":produce-unsat-cores", "true")
1772    }
1773
1774    /// Resets the assertions in the solver.
1775    #[inline]
1776    pub fn reset_assertions(&mut self) -> SmtRes<()> {
1777        tee_write! {
1778          self, |w| write_str(w, "(reset-assertions)\n") ?
1779        }
1780        Ok(())
1781    }
1782
1783    // // |===| Inspecting settings.
1784
1785    /// Get info command.
1786    #[inline]
1787    pub fn get_info(&mut self, flag: &str) -> SmtRes<()> {
1788        tee_write! {
1789          self, |w| writeln!(w, "(get-info {})", flag) ?
1790        }
1791        Ok(())
1792    }
1793    /// Get option command.
1794    #[inline]
1795    pub fn get_option(&mut self, option: &str) -> SmtRes<()> {
1796        tee_write! {
1797          self, |w| writeln!(w, "(get-option {})", option) ?
1798        }
1799        Ok(())
1800    }
1801
1802    // |===| Script information.
1803
1804    /// Set info command.
1805    #[inline]
1806    pub fn set_info(&mut self, attribute: &str) -> SmtRes<()> {
1807        tee_write! {
1808          self, |w| writeln!(w, "(set-info {})", attribute) ?
1809        }
1810        Ok(())
1811    }
1812    /// Echo command.
1813    #[inline]
1814    pub fn echo(&mut self, text: &str) -> SmtRes<()> {
1815        tee_write! {
1816          self, |w| writeln!(w, "(echo \"{}\")", text) ?
1817        }
1818        Ok(())
1819    }
1820}