rsmt2/
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, Read, Write};
7use std::process::{Child, ChildStdin, ChildStdout, Command, Stdio};
8
9use crate::{actlit::Actlit, parse::*, prelude::*, print::*};
10
11/// Promise for an asynchronous check-sat.
12pub struct FutureCheckSat {
13    _nothing: (),
14}
15fn future_check_sat() -> FutureCheckSat {
16    FutureCheckSat { _nothing: () }
17}
18
19/// Solver providing most of the SMT-LIB 2.5 commands.
20///
21/// Note the [`Self::tee`] function, which takes a file writer to which it will write
22/// everything sent to the solver.
23///
24/// # Check Success
25///
26/// By default, SMT-LIB 2 commands such as `declare-...`, `define-...`, `assert`, *etc.* are
27/// **silent** in the sense that, if successful, they do not cause the solver output anything. As a
28/// consequence, rmst2 does not check for errors after these commands are issued: since the command
29/// does not produce anything on success, how long should we wait for an error before deciding the
30/// command seems to have succeeded?
31///
32/// The problem is that when an error-producing command is issued, the actual error will only be
33/// seen by rsmt2 when it parses a result ---typically for a later `check-sat` or a `get-model`.
34/// This can be an issue when debugging, or when passing unchecked expressions or commands from
35/// downstream users.
36///
37/// ```rust
38/// # use rsmt2::Solver;
39/// let mut solver = Solver::default_z3(()).unwrap();
40/// //               vvvvvvvvvvvvvvvvvvvvvv~~~~ probably gonna cause an error
41/// solver.assert(r#"(> "not an integer" 7)"#).unwrap();
42/// solver.assert("(= 0 1)").unwrap();
43/// solver.assert("(= 0 2)").unwrap();
44/// solver.assert("(= 0 3)").unwrap();
45/// solver.assert("(= 0 4)").unwrap();
46/// solver.assert("(= 0 5)").unwrap();
47/// // zero error so far
48/// let e = solver.check_sat().unwrap_err();
49/// # println!("{}", e);
50/// assert_eq!(
51///     &e.to_string(),
52///     "\
53///         solver error: \"line 3 column 25: \
54///         Sort mismatch at argument #1 for function (declare-fun > (Int Int) Bool) \
55///         supplied sort is String\"\
56///     ",
57/// );
58/// ```
59///
60/// SMT-LIB 2 has a `:print-success` option that forces all commands that do not produce a result
61/// to issue `success` on the solver's `stdout` when it's done handling them. This allows rsmt2 to
62/// notice and handle errors as soon as they happen, since it must check for `success` every time.
63///
64/// ```rust
65/// # use rsmt2::{Solver, SmtConf};
66/// let mut conf = SmtConf::default_z3();
67/// // activates `success`-printing
68/// conf.check_success();
69///
70/// let mut solver = Solver::new(conf, ()).unwrap();
71///
72/// //                         vvvvvvvvvvvvvvvvvvvvvv~~~~ probably gonna cause an error
73/// let res = solver.assert(r#"(> "not an integer" 7)"#);
74/// // did it?
75/// let e = res.unwrap_err();
76/// # println!("{}", e);
77/// assert_eq!(
78///     &e.to_string(),
79///     "\
80///         solver error: \"line 4 column 25: \
81///         Sort mismatch at argument #1 for function (declare-fun > (Int Int) Bool) \
82///         supplied sort is String\"\
83///     ",
84/// );
85/// solver.assert("(= 0 1)").unwrap();
86/// solver.assert("(= 0 2)").unwrap();
87/// solver.assert("(= 0 3)").unwrap();
88/// solver.assert("(= 0 4)").unwrap();
89/// solver.assert("(= 0 5)").unwrap();
90/// let is_sat = solver.check_sat().unwrap();
91/// ```
92///
93/// We can also activate `success`-checking at solver level.
94///
95/// ```rust
96/// # use rsmt2::{Solver};
97/// let mut solver = Solver::default_z3(()).unwrap();
98/// // activates `success` printing and checking.
99/// solver.print_success().unwrap();
100///
101/// //                         vvvvvvvvvvvvvvvvvvvvvv~~~~ probably gonna cause an error
102/// let res = solver.assert(r#"(> "not an integer" 7)"#);
103/// // did it?
104/// let e = res.unwrap_err();
105/// # println!("{}", e);
106/// assert_eq!(
107///     &e.to_string(),
108///     "\
109///         solver error: \"line 4 column 25: \
110///         Sort mismatch at argument #1 for function (declare-fun > (Int Int) Bool) \
111///         supplied sort is String\"\
112///     ",
113/// );
114/// ```
115///
116/// The downside is that rsmt2 will not parse `success` on all commands that do not produce
117/// results. This workflow is usually considered acceptable as parsing `success` is expected to be
118/// very, very cheap compared to whatever SMT check(s) the solver performs. This might not apply to
119/// users performing a lot of small, very fast checks; especially if you declare/define/assert a
120/// lot of things, as each declaration/definition/assertion causes to parse `success`.
121pub struct Solver<Parser> {
122    /// Solver configuration.
123    conf: SmtConf,
124    /// Actual solver process.
125    kid: Child,
126    /// Solver's stdin.
127    stdin: BufWriter<ChildStdin>,
128    /// Tee file writer.
129    tee: Option<BufWriter<File>>,
130    /// Parser on the solver's stdout.
131    smt_parser: RSmtParser,
132    /// User-defined parser.
133    parser: Parser,
134    /// Actlit counter.
135    actlit: usize,
136    /// If true, check for `success` every time.
137    check_success: bool,
138}
139
140impl<Parser> Write for Solver<Parser> {
141    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
142        if let Some(tee) = self.tee.as_mut() {
143            let _ = tee.write(buf);
144        }
145        self.stdin.write(buf)
146    }
147    fn flush(&mut self) -> ::std::io::Result<()> {
148        if let Some(tee) = self.tee.as_mut() {
149            let _ = tee.flush();
150        }
151        self.stdin.flush()
152    }
153}
154
155impl<Parser> Read for Solver<Parser> {
156    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
157        self.smt_parser.read(buf)
158    }
159}
160
161/// Writes something in both the solver and the tee-ed output.
162macro_rules! tee_write {
163  ($slf:expr, no_check |$w:ident| $($tail:tt)*) => ({
164    if let Some(ref mut $w) = $slf.tee {
165      $($tail)*;
166      writeln!($w)?;
167      $w.flush() ?
168    }
169    let $w = & mut $slf.stdin;
170    $($tail)*;
171    $w.flush()?;
172  });
173  ($slf:expr, |$w:ident| $($tail:tt)*) => ({
174    tee_write! { $slf, no_check |$w| $($tail)* }
175    if $slf.check_success {
176        $slf.check_success()?
177    }
178  });
179}
180
181impl<Parser> ::std::ops::Drop for Solver<Parser> {
182    fn drop(&mut self) {
183        let _ = self.kill();
184        ()
185    }
186}
187
188/// # Basic functions, not related to SMT-LIB.
189impl<Parser> Solver<Parser> {
190    /// Spawns the solver kid.
191    fn spawn(conf: &SmtConf) -> SmtRes<(Child, BufWriter<ChildStdin>, BufReader<ChildStdout>)> {
192        let mut kid = Command::new(
193            // Command.
194            conf.get_cmd(),
195        )
196        .args(
197            // Options.
198            conf.get_options(),
199        )
200        .stdin(Stdio::piped())
201        .stdout(Stdio::piped())
202        .stderr(Stdio::piped())
203        .spawn()
204        .chain_err::<_, ErrorKind>(|| {
205            format!(
206                "While spawning child process with {}",
207                conf.get_cmd().to_string()
208            )
209            .into()
210        })?;
211
212        let mut stdin_opt = None;
213        ::std::mem::swap(&mut stdin_opt, &mut kid.stdin);
214
215        let stdin = if let Some(inner) = stdin_opt {
216            BufWriter::new(inner)
217        } else {
218            bail!("could not retrieve solver's stdin")
219        };
220
221        let mut stdout_opt = None;
222        ::std::mem::swap(&mut stdout_opt, &mut kid.stdout);
223
224        let stdout = if let Some(inner) = stdout_opt {
225            BufReader::new(inner)
226        } else {
227            bail!("could not retrieve solver's stdout")
228        };
229
230        Ok((kid, stdin, stdout))
231    }
232
233    /// Constructor.
234    pub fn new(conf: SmtConf, parser: Parser) -> SmtRes<Self> {
235        // Constructing command and spawning kid.
236        let (kid, stdin, stdout) = Self::spawn(&conf)?;
237
238        let smt_parser = RSmtParser::new(stdout);
239
240        let tee = None;
241        let actlit = 0;
242
243        let mut slf = Solver {
244            kid,
245            stdin,
246            tee,
247            conf,
248            smt_parser,
249            parser,
250            actlit,
251            check_success: false,
252        };
253
254        if slf.conf.get_check_success() {
255            slf.print_success()?;
256        }
257        if slf.conf.get_models() {
258            slf.produce_models()?;
259        }
260        if slf.conf.get_unsat_cores() {
261            slf.produce_unsat_cores()?;
262        }
263
264        Ok(slf)
265    }
266
267    /// Creates a solver kid with the default z3 configuration.
268    ///
269    /// Mostly used in tests, same as `Self::new( SmtConf::z3(), parser )`.
270    pub fn z3(parser: Parser, cmd: impl Into<String>) -> SmtRes<Self> {
271        Self::new(SmtConf::z3(cmd), parser)
272    }
273    /// Creates a solver kid with the default cvc4 configuration.
274    ///
275    /// Mostly used in tests, same as `Self::new( SmtConf::z3(), parser )`.
276    pub fn cvc4(parser: Parser, cmd: impl Into<String>) -> SmtRes<Self> {
277        Self::new(SmtConf::cvc4(cmd), parser)
278    }
279    /// Creates a solver kid with the default yices 2 configuration.
280    ///
281    /// Mostly used in tests, same as `Self::new( SmtConf::yices_2(), parser )`.
282    pub fn yices_2(parser: Parser, cmd: impl Into<String>) -> SmtRes<Self> {
283        Self::new(SmtConf::yices_2(cmd), parser)
284    }
285
286    /// Creates a solver kid with the default z3 configuration and command.
287    ///
288    /// Mostly used in tests, same as `Self::new( SmtConf::default_z3(), parser )`.
289    ///
290    /// # Warning
291    ///
292    /// The command used to run a particular solver is up to the end-user. As such, it **does not
293    /// make sense** to use default commands for anything else than local testing. You should
294    /// explicitely pass the command to use with [`Self::z3`] instead.
295    pub fn default_z3(parser: Parser) -> SmtRes<Self> {
296        Self::new(SmtConf::default_z3(), parser)
297    }
298
299    /// Creates a solver kid with the default cvc4 configuration and
300    /// command.
301    ///
302    /// Mostly used in tests, same as `Self::new( SmtConf::default_z3(), parser )`.
303    ///
304    /// # Warning
305    ///
306    /// The command used to run a particular solver is up to the end-user. As such, it **does not
307    /// make sense** to use default commands for anything else than local testing. You should
308    /// explicitely pass the command to use with [`Self::cvc4`] instead.
309    pub fn default_cvc4(parser: Parser) -> SmtRes<Self> {
310        Self::new(SmtConf::default_cvc4(), parser)
311    }
312
313    /// Creates a solver kid with the default yices 2 configuration and
314    /// command.
315    ///
316    /// Mostly used in tests, same as `Self::new( SmtConf::default_yices_2(), parser )`.
317    ///
318    /// # Warning
319    ///
320    /// The command used to run a particular solver is up to the end-user. As such, it **does not
321    /// make sense** to use default commands for anything else than local testing. You should
322    /// explicitely pass the command to use with [`Self::yices_2`] instead.
323    pub fn default_yices_2(parser: Parser) -> SmtRes<Self> {
324        Self::new(SmtConf::default_yices_2(), parser)
325    }
326
327    /// Returns the configuration of the solver.
328    pub fn conf(&self) -> &SmtConf {
329        &self.conf
330    }
331
332    /// Forces the solver to write all communications to a file.
333    ///
334    /// - fails if the solver is already tee-ed;
335    /// - see also [`Self::path_tee`].
336    pub fn tee(&mut self, file: File) -> SmtRes<()> {
337        if self.tee.is_some() {
338            bail!("Trying to tee a solver that's already tee-ed")
339        }
340        let mut tee = BufWriter::with_capacity(1000, file);
341        write!(tee, "; Command:\n; > {}", self.conf.get_cmd())?;
342        for option in self.conf.get_options() {
343            write!(tee, " {}", option)?
344        }
345        writeln!(tee, "\n")?;
346        self.tee = Some(tee);
347        Ok(())
348    }
349
350    /// Forces the solver to write all communications to a file.
351    ///
352    /// - opens `file` with `create` and `write`;
353    /// - fails if the solver is already tee-ed;
354    /// - see also [`Self::tee`].
355    pub fn path_tee<P>(&mut self, path: P) -> SmtRes<()>
356    where
357        P: AsRef<::std::path::Path>,
358    {
359        use std::fs::OpenOptions;
360
361        let path: &::std::path::Path = path.as_ref();
362        let file = OpenOptions::new()
363            .create(true)
364            .write(true)
365            .truncate(true)
366            .open(path)
367            .chain_err(|| format!("while opening tee file `{}`", path.to_string_lossy()))?;
368        self.tee(file)
369    }
370
371    /// True if the solver is tee-ed.
372    pub fn is_teed(&self) -> bool {
373        self.tee.is_some()
374    }
375
376    /// Kills the solver kid.
377    ///
378    /// The windows version just prints `(exit)` on the kid's `stdin`. Anything else seems to cause
379    /// problems.
380    ///
381    /// This function is automatically called when the solver is dropped.
382    #[cfg(windows)]
383    pub fn kill(&mut self) -> SmtRes<()> {
384        let _ = writeln!(self.stdin, "(exit)");
385        let _ = self.stdin.flush();
386        let _ = self.kid.kill();
387        Ok(())
388    }
389    /// Kills the solver kid.
390    ///
391    /// The windows version just prints `(exit)` on the kid's `stdin`. Anything else seems to cause
392    /// problems.
393    ///
394    /// This function is automatically called when the solver is dropped.
395    #[cfg(not(windows))]
396    pub fn kill(&mut self) -> SmtRes<()> {
397        let _ = writeln!(self.stdin, "(exit)");
398        let _ = self.stdin.flush();
399        let _ = self.kid.kill();
400        let wait_time = std::time::Duration::from_millis(10);
401        for _ in 0..100 {
402            let join = self
403                .kid
404                .try_wait()
405                .chain_err(|| "waiting for child process to exit")?;
406            if join.is_some() {
407                return Ok(());
408            }
409            std::thread::sleep(wait_time);
410        }
411        bail!("failed to wait for child process to properly terminate")
412    }
413
414    /// Internal comment function.
415    #[inline]
416    fn cmt(file: &mut BufWriter<File>, blah: &str) -> SmtRes<()> {
417        for line in blah.lines() {
418            writeln!(file, "; {}", line)?
419        }
420        file.flush()?;
421        Ok(())
422    }
423
424    /// Prints a comment in the tee-ed file, if any.
425    #[inline]
426    pub fn comment_args(&mut self, args: std::fmt::Arguments) -> SmtRes<()> {
427        if let Some(ref mut file) = self.tee {
428            Self::cmt(file, &format!("{}", args))?
429        }
430        Ok(())
431    }
432
433    /// Prints a comment in the tee-ed file, if any (string version).
434    #[inline]
435    pub fn comment(&mut self, blah: &str) -> SmtRes<()> {
436        if let Some(ref mut file) = self.tee {
437            Self::cmt(file, blah)?
438        }
439        Ok(())
440    }
441}
442
443/// # Basic SMT-LIB parser-agnostic commands.
444impl<Parser> Solver<Parser> {
445    /// Activates print-success, see [here](Self#check-success).
446    #[inline]
447    pub fn print_success(&mut self) -> SmtRes<()> {
448        self.check_success = true;
449        self.set_option(":print-success", "true")
450    }
451    /// Parses a `success`, see [here](Self#check-success).
452    #[inline]
453    pub fn check_success(&mut self) -> SmtRes<()> {
454        self.smt_parser.success()
455    }
456    /// Activates unsat core production.
457    #[inline]
458    pub fn produce_unsat_cores(&mut self) -> SmtRes<()> {
459        self.set_option(":produce-unsat-cores", "true")
460    }
461    /// Activates model production.
462    #[inline]
463    pub fn produce_models(&mut self) -> SmtRes<()> {
464        self.set_option(":produce-models", "true")
465    }
466
467    /// Asserts an expression.
468    ///
469    /// # Examples
470    ///
471    /// ```rust
472    /// # use rsmt2::Solver;
473    /// let mut solver = Solver::default_z3(()).unwrap();
474    /// solver.assert("(= 0 1)").unwrap();
475    /// ```
476    #[inline]
477    pub fn assert(&mut self, expr: impl Expr2Smt) -> SmtRes<()> {
478        self.assert_with(expr, ())
479    }
480
481    /// Check-sat command, turns `unknown` results into errors.
482    ///
483    /// # See also
484    ///
485    /// - [`Self::print_check_sat`]
486    /// - [`Self::parse_check_sat`]
487    ///
488    /// If you want a more natural way to handle unknown results, see `parse_check_sat_or_unk`.
489    ///
490    /// # Examples
491    ///
492    /// ```rust
493    /// # use rsmt2::prelude::*;
494    /// let mut conf = SmtConf::default_z3();
495    /// conf.option("-t:10");
496    /// let mut solver = Solver::new(conf, ()).unwrap();
497    /// solver.declare_const("x", "Int").unwrap();
498    /// solver.declare_const("y", "Int").unwrap();
499    ///
500    /// solver.push(1).unwrap();
501    /// solver.assert("(= (+ x y) 0)").unwrap();
502    /// let maybe_sat = solver.check_sat().unwrap();
503    /// assert_eq! { maybe_sat, true }
504    /// solver.pop(1).unwrap();
505    ///
506    /// solver.assert("(= (+ (* x x y) (* y y x)) 7654321)").unwrap();
507    /// let sat_res = & solver.check_sat();
508    ///
509    /// match * sat_res {
510    ///     Err(ref e) => match * e.kind() {
511    ///         ::rsmt2::errors::ErrorKind::Unknown => (),
512    ///         _ => panic!("expected unknown"),
513    ///     },
514    ///     Ok(res) => panic!("expected error: {:?}", res),
515    /// }
516    /// ```
517    pub fn check_sat(&mut self) -> SmtRes<bool> {
518        let future = self.print_check_sat()?;
519        self.parse_check_sat(future)
520    }
521
522    /// Check-sat command, turns `unknown` results in `None`.
523    ///
524    /// # See also
525    ///
526    /// - [`Self::parse_check_sat_or_unk`]
527    ///
528    /// # Examples
529    ///
530    /// ```rust
531    /// # use rsmt2::prelude::*;
532    /// let mut conf = SmtConf::default_z3();
533    /// conf.option("-t:10");
534    /// # let mut solver = Solver::new(conf, ()).unwrap();
535    /// solver.declare_const("x", "Int").unwrap();
536    /// solver.declare_const("y", "Int").unwrap();
537    ///
538    /// solver.push(1).unwrap();
539    /// solver.assert("(= (+ x y) 0)").unwrap();
540    /// let maybe_sat = solver.check_sat_or_unk().unwrap();
541    /// assert_eq! { maybe_sat, Some(true) }
542    /// solver.pop(1).unwrap();
543    ///
544    /// solver.assert("(= (+ (* x x y) (* y y x)) 7654321)").unwrap();
545    /// let maybe_sat = solver.check_sat_or_unk().unwrap();
546    /// // Unknown ~~~~~~~~~~~~~vvvv
547    /// assert_eq! { maybe_sat, None }
548    /// ```
549    pub fn check_sat_or_unk(&mut self) -> SmtRes<Option<bool>> {
550        let future = self.print_check_sat()?;
551        self.parse_check_sat_or_unk(future)
552    }
553
554    /// Resets the underlying solver. Restarts the kid process if no reset command is supported.
555    ///
556    /// # Examples
557    ///
558    /// ```rust
559    /// # use rsmt2::Solver;
560    /// let mut solver = Solver::default_z3(()).unwrap();
561    /// solver.assert("(= 0 1)").unwrap();
562    /// assert!(! solver.check_sat().unwrap());
563    /// solver.reset().unwrap();
564    /// assert!(solver.check_sat().unwrap());
565    /// ```
566    #[inline]
567    pub fn reset(&mut self) -> SmtRes<()> {
568        self.actlit = 0;
569        tee_write! {
570          self, |w| write_str(w, "(reset)\n") ?
571        }
572        Ok(())
573    }
574
575    /// Declares a new constant.
576    ///
577    /// # Examples
578    ///
579    /// ```rust
580    /// # use rsmt2::Solver;
581    /// let mut solver = Solver::default_z3(()).unwrap();
582    /// solver.declare_const("x", "Int").unwrap()
583    /// ```
584    #[inline]
585    pub fn declare_const(&mut self, symbol: impl Sym2Smt, out_sort: impl Sort2Smt) -> SmtRes<()> {
586        self.declare_const_with(symbol, out_sort, ())
587    }
588
589    /// Declares a new function symbol.
590    ///
591    /// ```rust
592    /// # use rsmt2::Solver;
593    /// let mut solver = Solver::default_z3(()).unwrap();
594    /// solver.declare_fun(
595    ///     "my_symbol", & [ "Int", "Real", "Bool" ], "Bool"
596    /// ).unwrap()
597    /// ```
598    #[inline]
599    pub fn declare_fun<FunSym, Args, OutSort>(
600        &mut self,
601        symbol: FunSym,
602        args: Args,
603        out: OutSort,
604    ) -> SmtRes<()>
605    where
606        FunSym: Sym2Smt<()>,
607        OutSort: Sort2Smt,
608        Args: IntoIterator,
609        Args::Item: Sort2Smt,
610    {
611        self.declare_fun_with(symbol, args, out, ())
612    }
613
614    /// Defines a new constant function symbol.
615    ///
616    /// # Examples
617    ///
618    /// ```rust
619    /// # use rsmt2::Solver;
620    /// let mut solver = Solver::default_z3(()).unwrap();
621    /// solver.define_const(
622    ///     "seven", "Int", "7"
623    /// ).unwrap()
624    /// ```
625    #[inline]
626    pub fn define_const(
627        &mut self,
628        symbol: impl Sym2Smt,
629        out: impl Sort2Smt,
630        body: impl Expr2Smt,
631    ) -> SmtRes<()> {
632        self.define_const_with(symbol, out, body, ())
633    }
634
635    /// Defines a new function symbol.
636    ///
637    /// # Examples
638    ///
639    /// ```rust
640    /// # use rsmt2::Solver;
641    /// let mut solver = Solver::default_z3(()).unwrap();
642    /// solver.define_fun(
643    ///     "abs", & [ ("n", "Int") ], "Int", "(ite (< x 0) (- x) x)"
644    /// ).unwrap()
645    /// ```
646    #[inline]
647    pub fn define_fun<Args>(
648        &mut self,
649        symbol: impl Sym2Smt,
650        args: Args,
651        out: impl Sort2Smt,
652        body: impl Expr2Smt,
653    ) -> SmtRes<()>
654    where
655        Args: IntoIterator,
656        Args::Item: SymAndSort,
657    {
658        self.define_fun_with(symbol, args, out, body, ())
659    }
660
661    /// Pushes `n` layers on the assertion stack.
662    ///
663    /// - see also [`Self::pop`].
664    ///
665    /// Note that using [actlits][crate::actlit] is more efficient than push/pop, and is useable for
666    /// most push/pop use-cases.
667    ///
668    /// # Examples
669    ///
670    /// ```rust
671    /// # use rsmt2::Solver;
672    /// let mut solver = Solver::default_z3(()).unwrap();
673    /// solver.declare_const("x", "Int").unwrap();
674    /// solver.declare_const("y", "Int").unwrap();
675    /// solver.assert("(= x y)").unwrap();
676    /// let sat = solver.check_sat().unwrap();
677    /// assert!(sat);
678    ///
679    /// solver.push(1).unwrap();
680    /// solver.assert("(= x (+ x 1))").unwrap();
681    /// let sat = solver.check_sat().unwrap();
682    /// assert!(! sat);
683    /// solver.pop(1).unwrap();
684    ///
685    /// let sat = solver.check_sat().unwrap();
686    /// assert!(sat);
687    /// ```
688    #[inline]
689    pub fn push(&mut self, n: u8) -> SmtRes<()> {
690        tee_write! {
691          self, |w| writeln!(w, "(push {})", n) ?
692        }
693        Ok(())
694    }
695
696    /// Pops `n` layers off the assertion stack.
697    ///
698    /// - see also [`Self::push`].
699    ///
700    /// Note that using [actlits][crate::actlit] is more efficient than push/pop, and is useable for
701    /// most push/pop use-cases.
702    #[inline]
703    pub fn pop(&mut self, n: u8) -> SmtRes<()> {
704        tee_write! {
705          self, |w| writeln!(w, "(pop {})", n) ?
706        }
707        Ok(())
708    }
709
710    /// Check-sat assuming command, turns `unknown` results into errors.
711    ///
712    /// - see also [actlits][crate::actlit].
713    pub fn check_sat_assuming<Idents>(&mut self, idents: Idents) -> SmtRes<bool>
714    where
715        Idents: IntoIterator,
716        Idents::Item: Sym2Smt,
717    {
718        self.check_sat_assuming_with(idents, ())
719    }
720
721    /// Check-sat assuming command, turns `unknown` results into `None`.
722    ///
723    /// - see also [actlits][crate::actlit].
724    pub fn check_sat_assuming_or_unk<Ident, Idents>(
725        &mut self,
726        idents: Idents,
727    ) -> SmtRes<Option<bool>>
728    where
729        Idents: IntoIterator,
730        Idents::Item: Sym2Smt,
731    {
732        self.check_sat_assuming_or_unk_with(idents, ())
733    }
734
735    /// Sets the logic.
736    ///
737    /// # Examples
738    ///
739    /// ```rust
740    /// # use rsmt2::{SmtConf, Solver};
741    /// let mut solver = Solver::default_z3(()).unwrap();
742    /// solver.set_logic( ::rsmt2::Logic::QF_UF ).unwrap();
743    /// ```
744    #[inline]
745    pub fn set_logic(&mut self, logic: Logic) -> SmtRes<()> {
746        tee_write! {
747          self, |w| {
748            write_str(w, "(set-logic ")?;
749            logic.to_smt2(w, ())?;
750            write_str(w, ")\n") ?
751          }
752        }
753        Ok(())
754    }
755
756    /// Sets a custom logic.
757    ///
758    /// # Examples
759    ///
760    /// ```rust
761    /// # use rsmt2::{SmtConf, Solver};
762    /// let mut solver = Solver::default_z3(()).unwrap();
763    /// solver.set_custom_logic("QF_UFBV").unwrap();
764    /// ```
765    #[inline]
766    pub fn set_custom_logic(&mut self, logic: impl AsRef<str>) -> SmtRes<()> {
767        tee_write! {
768          self, |w| {
769            write_str(w, "(set-logic ")?;
770            write_str(w, logic.as_ref())?;
771            write_str(w, ")\n") ?
772          }
773        }
774        Ok(())
775    }
776
777    /// Defines a recursive function.
778    ///
779    /// # Examples
780    ///
781    /// ```rust
782    /// # use rsmt2::Solver;
783    /// let mut solver = Solver::default_z3(()).unwrap();
784    /// solver.define_fun_rec(
785    ///     "abs", & [ ("n", "Int") ], "Int", "(ite (< x 0) (abs (- x)) x)"
786    /// ).unwrap()
787    /// ```
788    #[inline]
789    pub fn define_fun_rec<Args>(
790        &mut self,
791        symbol: impl Sym2Smt,
792        args: Args,
793        out: impl Sort2Smt,
794        body: impl Expr2Smt,
795    ) -> SmtRes<()>
796    where
797        Args: IntoIterator,
798        Args::Item: SymAndSort,
799    {
800        self.define_fun_rec_with(symbol, args, out, body, ())
801    }
802
803    /// Defines some (possibily mutually) recursive functions.
804    ///
805    /// # Examples
806    ///
807    /// ```rust
808    /// # use rsmt2::Solver;
809    /// let mut solver = Solver::default_z3(()).unwrap();
810    /// solver.define_funs_rec( & [
811    ///     ("abs_1", [ ("n", "Int") ], "Int", "(ite (< x 0) (abs_2 (- x)) x)"),
812    ///     ("abs_2", [ ("n", "Int") ], "Int", "(ite (< x 0) (abs_3 (- x)) x)"),
813    ///     ("abs_3", [ ("n", "Int") ], "Int", "(ite (< x 0) (abs_1 (- x)) x)"),
814    /// ] ).unwrap()
815    /// ```
816    #[inline]
817    pub fn define_funs_rec<Defs>(&mut self, funs: Defs) -> SmtRes<()>
818    where
819        Defs: IntoIterator + Clone,
820        Defs::Item: FunDef,
821    {
822        self.define_funs_rec_with(funs, ())
823    }
824
825    /// Declares mutually recursive datatypes.
826    ///
827    /// A relatively recent version of z3 is recommended. Sort definition is a relatively expert
828    /// action, this function is a bit complex. The example below goes over how it works.
829    ///
830    /// # Examples
831    ///
832    /// ```rust
833    /// use rsmt2::print::{AdtDecl, AdtVariantField, AdtVariant};
834    ///
835    /// // Alright, so we're going to declare two mutually recursive sorts. It is easier to pack the
836    /// // sort-declaration data in custom types. If you want to declare a sort, you most likely
837    /// // already have a representation for it, so working on custom types is reasonable.
838    ///
839    /// // Notice that the `AdtDecl`, `AdtVariantField` and `AdtVariant` traits from `rsmt2::print::_`
840    /// // are in scope. This is what our custom types will need to generate to declare the sort.
841    ///
842    /// // We'll use static string slices for simplicity as `&str` implements all printing traits.
843    /// type Sym = &'static str;
844    /// type Sort = &'static str;
845    ///
846    /// // Let's start with the top-level sort type.
847    /// struct MySort {
848    ///     // Name of the sort, for instance `List`.
849    ///     sym: Sym,
850    ///     // Symbol(s) for the type parameter(s), for instance `T` for `List<T>`. Must be a collection
851    ///     // of known length, because rsmt2 needs to access the arity (number of type parameters).
852    ///     args: Vec<Sym>,
853    ///     // Body of the sort: its variants. For instance the `nil` and `cons` variants for `List<T>`.
854    ///     variants: Vec<Variant>,
855    /// }
856    /// impl MySort {
857    ///     // This thing build the actual definition expected by rsmt2. Its output is something that
858    ///     // implements `AdtDecl` and can only live as long as the input ref to `self`.
859    ///     fn as_decl<'me>(&'me self) -> impl AdtDecl + 'me {
860    ///         // Check out rsmt2's documentation and you'll see that `AdtDecl` is already implemented for
861    ///         // certain triplets.
862    ///         (
863    ///             // Symbol.
864    ///             &self.sym,
865    ///             // Sized collection of type-parameter symbols.
866    ///             &self.args,
867    ///             // Variant, collection of iterator over `impl AdtVariant` (see below).
868    ///             self.variants.iter().map(Variant::as_decl),
869    ///         )
870    ///     }
871    ///
872    ///     fn tree() -> Self {
873    ///         Self {
874    ///             sym: "Tree",
875    ///             args: vec!["T"],
876    ///             variants: vec![Variant::tree_leaf(), Variant::tree_node()],
877    ///         }
878    ///     }
879    /// }
880    ///
881    /// // Next up, variants. A variant is a symbol (*e.g.* `nil` or `cons` for `List<T>`) and some
882    /// // fields which describe the data stored in the variant.
883    /// struct Variant {
884    ///     sym: Sym,
885    ///     fields: Vec<Field>,
886    /// }
887    /// impl Variant {
888    ///     // Variant declaration; again, `AdtVariant` is implemented for certain types of pairs.
889    ///     fn as_decl<'me>(&'me self) -> impl AdtVariant + 'me {
890    ///         (
891    ///             // Symbol.
892    ///             self.sym,
893    ///             // Iterator over field declarations.
894    ///             self.fields.iter().map(Field::as_decl),
895    ///         )
896    ///     }
897    ///
898    ///     fn tree_leaf() -> Self {
899    ///         Self {
900    ///             sym: "leaf",
901    ///             fields: vec![],
902    ///         }
903    ///     }
904    ///     fn tree_node() -> Self {
905    ///         Self {
906    ///             sym: "node",
907    ///             fields: vec![Field::tree_node_value(), Field::tree_node_children()],
908    ///         }
909    ///     }
910    /// }
911    ///
912    /// // A symbol and a sort: describes a piece of data in a variant with a symbol to retrieve it,
913    /// // *i.e.* the name of the field.
914    /// struct Field {
915    ///     sym: Sym,
916    ///     sort: Sort,
917    /// }
918    /// impl Field {
919    ///     // As usual, `AdtVariantField` is implemented for certain pairs.
920    ///     fn as_decl(&self) -> impl AdtVariantField {
921    ///         (self.sym, self.sort)
922    ///     }
923    ///
924    ///     fn tree_node_value() -> Self {
925    ///         Self {
926    ///             sym: "value",
927    ///             sort: "T",
928    ///         }
929    ///     }
930    ///     fn tree_node_children() -> Self {
931    ///         Self {
932    ///             sym: "children",
933    ///             sort: "(TreeList T)",
934    ///         }
935    ///     }
936    /// }
937    ///
938    /// let tree = MySort::tree();
939    ///
940    /// // Now this `tree` uses an non-existing `(TreeList T)` sort to store its children, let's declare
941    /// // it now.
942    ///
943    /// let nil = Variant {
944    ///     sym: "nil",
945    ///     fields: vec![],
946    /// };
947    /// let cons = Variant {
948    ///     sym: "cons",
949    ///     fields: vec![
950    ///         Field {
951    ///             sym: "car",
952    ///             sort: "(Tree T)",
953    ///         },
954    ///         Field {
955    ///             sym: "cdr",
956    ///             sort: "(TreeList T)",
957    ///         },
958    ///     ],
959    /// };
960    /// let tree_list = MySort {
961    ///     sym: "TreeList",
962    ///     args: vec!["T"],
963    ///     variants: vec![nil, cons],
964    /// };
965    ///
966    /// let mut solver = rsmt2::Solver::default_z3(()).unwrap();
967    ///
968    /// solver
969    ///     // These sort are mutually recursive, `Solver::declare_datatypes` needs to declare them at the
970    ///     // same time.
971    ///     .declare_datatypes(&[tree.as_decl(), tree_list.as_decl()])
972    ///     .unwrap();
973    ///
974    /// // That's it! Solver now knows these sorts and we can use them.
975    ///
976    /// solver.declare_const("t1", "(Tree Int)").unwrap();
977    /// solver.declare_const("t2", "(Tree Bool)").unwrap();
978    ///
979    /// solver.assert("(> (value t1) 20)").unwrap();
980    /// solver.assert("(not (is-leaf t2))").unwrap();
981    /// solver.assert("(not (value t2))").unwrap();
982    ///
983    /// let sat = solver.check_sat().unwrap();
984    /// assert!(sat);
985    /// ```
986    pub fn declare_datatypes<Defs>(&mut self, defs: Defs) -> SmtRes<()>
987    where
988        Defs: IntoIterator + Clone,
989        Defs::Item: AdtDecl,
990    {
991        tee_write! {
992          self, no_check |w| write!(w, "(declare-datatypes (") ?
993        }
994
995        for def in defs.clone() {
996            let sort_sym = def.adt_sym();
997            let arity = def.arity();
998            tee_write! {
999              self, no_check |w| {
1000                write!(w, " (")?;
1001                sort_sym.sym_to_smt2(w, ())?;
1002                write!(w, " {})", arity) ?
1003              }
1004            }
1005        }
1006
1007        tee_write! {
1008          self, no_check |w| write!(w, " ) (") ?
1009        }
1010
1011        for def in defs {
1012            let arity = def.arity();
1013            let args = def.adt_sort_args();
1014            let variants = def.adt_variants();
1015            tee_write! { self, |w| write!(w, " (")? };
1016            if arity > 0 {
1017                tee_write! { self, no_check |w| write!(w, "par (")? };
1018                for param in args {
1019                    tee_write! { self, no_check |w| {
1020                        write!(w, " ")?;
1021                        param.sym_to_smt2(w, ())?;
1022                    }}
1023                }
1024                tee_write! { self, no_check |w| write!(w, " ) (")? };
1025            }
1026
1027            for variant in variants {
1028                let sym = variant.sym();
1029                let mut fields = variant.fields();
1030                let first_field = fields.next();
1031
1032                tee_write! { self, no_check |w| write!(w, " ")? };
1033
1034                if first_field.is_some() {
1035                    tee_write! { self, no_check |w| write!(w, "(")? };
1036                }
1037
1038                tee_write! { self, no_check |w| sym.sym_to_smt2(w, ())? };
1039
1040                if let Some(first) = first_field {
1041                    for field in Some(first).into_iter().chain(fields) {
1042                        let sym = field.field_sym();
1043                        let sort = field.field_sort();
1044                        tee_write! {
1045                            self, no_check |w| {
1046                                write!(w, " (")?;
1047                                sym.sym_to_smt2(w, ())?;
1048                                write!(w, " ")?;
1049                                sort.sort_to_smt2(w)?;
1050                                write!(w, ")")?;
1051                            }
1052                        }
1053                    }
1054
1055                    tee_write! { self, no_check |w| write!(w, ")")? };
1056                }
1057            }
1058
1059            tee_write! {
1060              self, no_check |w| {
1061                write!(w, " )")?;
1062
1063                if arity > 0 {
1064                  write!(w, " )") ?
1065                }
1066              }
1067            }
1068        }
1069
1070        tee_write! {
1071          self, |w| writeln!(w, " ) )") ?
1072        }
1073
1074        Ok(())
1075    }
1076}
1077
1078/// # Basic SMT-LIB commands using the user's parser.
1079impl<Parser> Solver<Parser> {
1080    /// Get-model command.
1081    ///
1082    /// - See also [`Self::get_model_const`].
1083    ///
1084    /// # Examples
1085    ///
1086    /// ```rust
1087    /// use rsmt2::Solver;
1088    ///
1089    /// let mut solver = Solver::default_z3(()).unwrap();
1090    ///
1091    /// solver.declare_const("x", "Int").unwrap();
1092    /// solver.declare_const("y", "Int").unwrap();
1093    ///
1094    /// solver.assert("(= (+ x y) 0)").unwrap();
1095    ///
1096    /// let is_sat = solver.check_sat().unwrap();
1097    /// assert!(is_sat);
1098    /// let model = solver.get_model().unwrap();
1099    /// # println!("model: {:?}", model);
1100    ///
1101    /// let (mut x, mut y) = (None, None);
1102    /// // `x` and `y` are constants, *i.e.* functions taking no arguments. In general however,
1103    /// // `get_model` can yield functions. Hence the list of arguments
1104    /// //          vvvv
1105    /// for (ident, args, sort, value) in model {
1106    ///     assert!(args.is_empty());
1107    ///     if ident == "x" {
1108    ///         x = Some(isize::from_str_radix(&value, 10).expect("while parsing `x` value"))
1109    ///     } else if ident == "y" {
1110    ///         y = Some(isize::from_str_radix(&value, 10).expect("while parsing `y` value"))
1111    ///     } else {
1112    ///         panic!("unexpected ident `{}` in model", ident)
1113    ///     }
1114    /// }
1115    ///
1116    /// let (x, y) = (x.expect("`x` not found in model"), y.expect("`y` not found in model"));
1117    /// assert_eq!(x + y, 0)
1118    /// ```
1119    pub fn get_model<Ident, Type, Value>(&mut self) -> SmtRes<Model<Ident, Type, Value>>
1120    where
1121        Parser: for<'p> IdentParser<Ident, Type, &'p mut RSmtParser>
1122            + for<'p> ModelParser<Ident, Type, Value, &'p mut RSmtParser>,
1123    {
1124        self.print_get_model()?;
1125        self.parse_get_model()
1126    }
1127
1128    /// Get-model command when all the symbols are nullary.
1129    ///
1130    /// - See also [`Self::get_model`].
1131    ///
1132    /// # Examples
1133    ///
1134    /// ```rust
1135    /// use rsmt2::Solver;
1136    ///
1137    /// let mut solver = Solver::default_z3(()).unwrap();
1138    ///
1139    /// solver.declare_const("x", "Int").unwrap();
1140    /// solver.declare_const("y", "Int").unwrap();
1141    ///
1142    /// solver.assert("(= (+ x y) 0)").unwrap();
1143    ///
1144    /// let is_sat = solver.check_sat().unwrap();
1145    /// assert!(is_sat);
1146    /// // We only have `x` and `y` which are constant symbols (functions with no arguments).
1147    /// // Using `get_model_const` instead of `get_model` will generate a model where symbols
1148    /// // have no arguments.
1149    /// let model = solver.get_model_const().unwrap();
1150    /// # println!("model: {:?}", model);
1151    ///
1152    /// let (mut x, mut y) = (None, None);
1153    /// // No list of arguments in the model, as opposed to models from `get_model`.
1154    /// //   vvvvvvvvvvvvvvvvvv
1155    /// for (ident, sort, value) in model {
1156    ///     if ident == "x" {
1157    ///         x = Some(isize::from_str_radix(&value, 10).expect("while parsing `x` value"))
1158    ///     } else if ident == "y" {
1159    ///         y = Some(isize::from_str_radix(&value, 10).expect("while parsing `y` value"))
1160    ///     } else {
1161    ///         panic!("unexpected ident `{}` in model", ident)
1162    ///     }
1163    /// }
1164    ///
1165    /// let (x, y) = (x.expect("`x` not found in model"), y.expect("`y` not found in model"));
1166    /// assert_eq!(x + y, 0)
1167    /// ```
1168    pub fn get_model_const<Ident, Type, Value>(&mut self) -> SmtRes<Vec<(Ident, Type, Value)>>
1169    where
1170        Parser: for<'p> IdentParser<Ident, Type, &'p mut RSmtParser>
1171            + for<'p> ModelParser<Ident, Type, Value, &'p mut RSmtParser>,
1172    {
1173        self.print_get_model()?;
1174        self.parse_get_model_const()
1175    }
1176
1177    /// Get-values command.
1178    ///
1179    /// - See also [`Self::get_values_with`].
1180    ///
1181    /// Notice that the input expression type and the output one have no reason
1182    /// to be the same.
1183    ///
1184    /// # Examples
1185    ///
1186    /// ```rust
1187    /// use rsmt2::Solver;
1188    ///
1189    /// let mut solver = Solver::default_z3(()).unwrap();
1190    ///
1191    /// solver.declare_const("x", "Int").unwrap();
1192    /// solver.declare_const("y", "Int").unwrap();
1193    ///
1194    /// solver.assert("(= (+ x y) 0)").unwrap();
1195    ///
1196    /// let is_sat = solver.check_sat().unwrap();
1197    /// assert!(is_sat);
1198    ///
1199    /// let vars = ["x", "y"];
1200    /// let values = solver.get_values(&vars).unwrap();
1201    /// # println!("values: {:?}", values);
1202    /// assert_eq!(vars.len(), values.len());
1203    ///
1204    /// let mut sum = 0;
1205    /// let mut values = values.into_iter();
1206    ///
1207    /// let (var, val) = values.next().unwrap();
1208    /// assert_eq!(var, "x");
1209    /// let val = isize::from_str_radix(&val, 10).expect("while parsing `x` value");
1210    /// sum += val;
1211    ///
1212    /// let (var, val) = values.next().unwrap();
1213    /// assert_eq!(var, "y");
1214    /// let val = isize::from_str_radix(&val, 10).expect("while parsing `y` value");
1215    /// sum += val;
1216    ///
1217    /// assert_eq!(values.next(), None);
1218    /// assert_eq!(sum, 0);
1219    /// ```
1220    pub fn get_values<Exprs, PExpr, PValue>(&mut self, exprs: Exprs) -> SmtRes<Vec<(PExpr, PValue)>>
1221    where
1222        Parser: for<'p> ExprParser<PExpr, (), &'p mut RSmtParser>
1223            + for<'p> ValueParser<PValue, &'p mut RSmtParser>,
1224        Exprs: IntoIterator,
1225        Exprs::Item: Expr2Smt,
1226    {
1227        self.get_values_with(exprs, ())
1228            .map_err(|e| self.conf.enrich_get_values_error(e))
1229    }
1230
1231    /// Get-values command.
1232    ///
1233    /// - See also [`Self::get_values`].
1234    ///
1235    /// Notice that the input expression type and the output one have no reason to be the same.
1236    pub fn get_values_with<Exprs, PExpr, PValue, Info>(
1237        &mut self,
1238        exprs: Exprs,
1239        info: Info,
1240    ) -> SmtRes<Vec<(PExpr, PValue)>>
1241    where
1242        Info: Copy,
1243        Parser: for<'p> ExprParser<PExpr, Info, &'p mut RSmtParser>
1244            + for<'p> ValueParser<PValue, &'p mut RSmtParser>,
1245        Exprs: IntoIterator,
1246        Exprs::Item: Expr2Smt<Info>,
1247    {
1248        self.print_get_values_with(exprs, info)?;
1249        self.parse_get_values_with(info)
1250    }
1251
1252    /// Get-unsat-core command.
1253    ///
1254    /// See also
1255    ///
1256    /// - [`NamedExpr`]: a convenient wrapper around any expression that gives it a name.
1257    ///
1258    /// # Examples
1259    ///
1260    /// ```rust
1261    /// use rsmt2::prelude::*;
1262    /// let mut conf = SmtConf::default_z3();
1263    /// conf.unsat_cores();
1264    /// # println!("unsat_cores: {}", conf.get_unsat_cores());
1265    ///
1266    /// let mut solver = Solver::new(conf, ()).unwrap();
1267    /// solver.declare_const("n", "Int").unwrap();
1268    /// solver.declare_const("m", "Int").unwrap();
1269    ///
1270    /// solver.assert("true").unwrap();
1271    ///
1272    /// let e_1 = "(> n 7)";
1273    /// let label_e_1 = "e_1";
1274    /// let named = NamedExpr::new(label_e_1, e_1);
1275    /// solver.assert(&named).unwrap();
1276    ///
1277    /// let e_2 = "(> m 0)";
1278    /// let label_e_2 = "e_2";
1279    /// let named = NamedExpr::new(label_e_2, e_2);
1280    /// solver.assert(&named).unwrap();
1281    ///
1282    /// let e_3 = "(< n 3)";
1283    /// let label_e_3 = "e_3";
1284    /// let named = NamedExpr::new(label_e_3, e_3);
1285    /// solver.assert(&named).unwrap();
1286    ///
1287    /// assert!(!solver.check_sat().unwrap());
1288    /// let core: Vec<String> = solver.get_unsat_core().unwrap();
1289    /// assert_eq!(core, vec![label_e_1, label_e_3]);
1290    /// ```
1291    pub fn get_unsat_core<Sym>(&mut self) -> SmtRes<Vec<Sym>>
1292    where
1293        Parser: for<'p> SymParser<Sym, &'p mut RSmtParser>,
1294    {
1295        self.print_get_unsat_core()?;
1296        self.parse_get_unsat_core()
1297    }
1298
1299    /// Get-interpolant command.
1300    ///
1301    /// - See [`Solver::get_interpolant_with`].
1302    pub fn get_interpolant<Expr>(
1303        &mut self,
1304        sym_1: impl Sym2Smt,
1305        sym_2: impl Sym2Smt,
1306    ) -> SmtRes<Expr>
1307    where
1308        Parser: for<'p> ExprParser<Expr, (), &'p mut RSmtParser>,
1309    {
1310        self.get_interpolant_with(sym_1, sym_2, ())
1311    }
1312
1313    /// Get-interpolant command.
1314    ///
1315    /// - See [Craig interpolation].
1316    /// - Only supported by recent versions of Z3.
1317    /// - This command is only legal after an `unsat` result.
1318    /// - The order of the two inputs symbols *matters*.
1319    ///
1320    /// Typically, you should assert two **named** formulas `f_1` and `f_2` (example
1321    /// [below](#examples)). Assuming you issue `check-sat` and get `unsat` (meaning `f_1 ⇒ ¬f_2`),
1322    /// then `get_interpolant(f_1, f_2)` produces a formula `I` such that
1323    /// - `f_1 ⇒ I`, *i.e.* `f_1 ∧ ¬I` is unsat,
1324    /// - `I ⇒ ¬f_2`, *i.e.* `I ∧ f_2` is unsat, and
1325    /// - `I` only mentions variables (constant symbols) that appear in both `f_1` and `f_2`.
1326    ///
1327    /// One way to think about interpolation is that `I` captures the reason for `f_1 ∧ f_2` being
1328    /// unsat from the *point of view of `f_1`*, in the sense that `I` does not contain variables
1329    /// that do not appear in `f_1`.
1330    ///
1331    /// # Examples
1332    ///
1333    /// ```rust
1334    /// use rsmt2::prelude::*;
1335    ///
1336    /// let mut solver = Solver::default_z3(()).unwrap();
1337    ///
1338    /// let (n, m) = ("n", "m");
1339    /// solver.declare_const(n, "Int").expect("declaring n");
1340    /// solver.declare_const(m, "Int").expect("declaring m");
1341    ///
1342    /// let f_1 = "(or (= (mod n 2) 0) (> n 42))";
1343    /// solver.assert(f_1.to_smt_named("f_1")).expect("assert f_1");
1344    ///
1345    /// let f_2 = "(and (< n m) (< m 9) (= (mod n 2) 1))";
1346    /// solver.assert(f_2.to_smt_named("f_2")).expect("assert f_2");
1347    ///
1348    /// let is_sat = solver.check_sat().unwrap();
1349    /// assert!(!is_sat);
1350    ///
1351    /// let interpolant: String = solver.get_interpolant("f_1", "f_2").unwrap();
1352    /// # println!("interpolant 1: {:?}", interpolant);
1353    /// assert_eq!(&interpolant, "(or (not (<= n 42)) (= (mod n 2) 0))");
1354    ///
1355    /// // Let's try again, but this time we switch the arguments of `get_interpolant`.
1356    /// let interpolant: String = solver.get_interpolant("f_2", "f_1").unwrap();
1357    /// # println!("interpolant 2: {:?}", interpolant);
1358    /// assert_eq!(&interpolant, "(and (= (mod (+ n 0) 2) 1) (<= n 7))");
1359    /// ```
1360    ///
1361    /// [Craig interpolation]: https://en.wikipedia.org/wiki/Craig_interpolation
1362    pub fn get_interpolant_with<Info, Expr>(
1363        &mut self,
1364        sym_1: impl Sym2Smt,
1365        sym_2: impl Sym2Smt,
1366        info: Info,
1367    ) -> SmtRes<Expr>
1368    where
1369        Parser: for<'p> ExprParser<Expr, Info, &'p mut RSmtParser>,
1370    {
1371        self.print_get_interpolant(sym_1, sym_2)?;
1372        let res = self.parse_get_interpolant(info);
1373        if res.is_err() && self.conf.style().is_z3() {
1374            res.chain_err(|| {
1375                format!(
1376                    "`get-interpolant` is not legal for {} solvers",
1377                    self.conf.style()
1378                )
1379            })
1380            .chain_err(|| format!("only Z3 supports `get-interpolant`"))
1381        } else {
1382            res
1383        }
1384    }
1385}
1386
1387/// # Actlit-Related Functions.
1388///
1389/// See the [`actlit` module][crate::actlit] for more details.
1390impl<Parser> Solver<Parser> {
1391    /// True if no actlits have been created since the last reset.
1392    ///
1393    /// See the [`actlit` module][crate::actlit] for more details.
1394    #[inline]
1395    fn has_actlits(&self) -> bool {
1396        self.actlit > 0
1397    }
1398
1399    /// Introduces a new actlit.
1400    ///
1401    /// See the [`actlit` module][crate::actlit] for more details.
1402    #[inline]
1403    pub fn get_actlit(&mut self) -> SmtRes<crate::actlit::Actlit> {
1404        let id = self.actlit;
1405        self.actlit += 1;
1406        let next_actlit = crate::actlit::Actlit::new(id);
1407        tee_write! {
1408          self, |w|
1409            write!(w, "(declare-fun ")?;
1410            next_actlit.write(w)?;
1411            writeln!(w, " () Bool)")?
1412        }
1413        Ok(next_actlit)
1414    }
1415
1416    /// Deactivates an activation literal, alias for `solver.set_actlit(actlit, false)`.
1417    ///
1418    /// See the [`actlit` module][crate::actlit] for more details.
1419    #[inline]
1420    pub fn de_actlit(&mut self, actlit: Actlit) -> SmtRes<()> {
1421        self.set_actlit(actlit, false)
1422    }
1423
1424    /// Forces the value of an actlit and consumes it.
1425    ///
1426    /// See the [`actlit` module][crate::actlit] for more details.
1427    #[inline]
1428    pub fn set_actlit(&mut self, actlit: Actlit, b: bool) -> SmtRes<()> {
1429        tee_write! {
1430          self, |w| {
1431            if b {
1432              write!(w, "(assert ") ?
1433            } else {
1434              write!(w, "(assert (not ") ?
1435            }
1436            actlit.write(w)?;
1437            if b {
1438              writeln!(w, ")") ?
1439            } else {
1440              writeln!(w, ") )") ?
1441            }
1442          }
1443        }
1444        ::std::mem::drop(actlit);
1445        Ok(())
1446    }
1447
1448    /// Asserts an expression without print information, guarded by an activation literal.
1449    ///
1450    /// See the [`actlit` module][crate::actlit] for more details.
1451    #[inline]
1452    pub fn assert_act(&mut self, actlit: &Actlit, expr: impl Expr2Smt) -> SmtRes<()> {
1453        self.assert_act_with(actlit, expr, ())
1454    }
1455
1456    /// Check-sat command with activation literals, turns `unknown` results into
1457    /// errors.
1458    pub fn check_sat_act<Actlits>(&mut self, actlits: Actlits) -> SmtRes<bool>
1459    where
1460        Actlits: IntoIterator,
1461        Actlits::Item: Sym2Smt,
1462    {
1463        let future = self.print_check_sat_act(actlits)?;
1464        self.parse_check_sat(future)
1465    }
1466
1467    /// Check-sat command with activation literals, turns `unknown` results in
1468    /// `None`.
1469    pub fn check_sat_act_or_unk<Actlits>(&mut self, actlits: Actlits) -> SmtRes<Option<bool>>
1470    where
1471        Actlits: IntoIterator,
1472        Actlits::Item: Sym2Smt,
1473    {
1474        let future = self.print_check_sat_act(actlits)?;
1475        self.parse_check_sat_or_unk(future)
1476    }
1477}
1478
1479/// # SMT-LIB asynchronous commands.
1480impl<Parser> Solver<Parser> {
1481    /// Prints a check-sat command.
1482    ///
1483    /// Allows to print the `check-sat` and get the result later, *e.g.* with
1484    /// [`Self::parse_check_sat`].
1485    ///
1486    /// # Examples
1487    ///
1488    /// ```rust
1489    /// use rsmt2::Solver;
1490    ///
1491    /// let mut solver = Solver::default_z3(()).unwrap();
1492    ///
1493    /// solver.declare_const("x", "Int").unwrap();
1494    /// solver.declare_const("y", "Int").unwrap();
1495    ///
1496    /// solver.assert("(= (+ x y) 0)").unwrap();
1497    ///
1498    /// let future = solver.print_check_sat().unwrap();
1499    /// // Do stuff while the solver works.
1500    /// let sat = solver.parse_check_sat(future).unwrap();
1501    /// assert!(sat);
1502    /// ```
1503    #[inline]
1504    pub fn print_check_sat(&mut self) -> SmtRes<FutureCheckSat> {
1505        tee_write! {
1506          self, no_check |w| write_str(w, "(check-sat)\n") ?
1507        }
1508        Ok(future_check_sat())
1509    }
1510
1511    /// Check-sat command, with actlits.
1512    ///
1513    /// See the [`actlit` module][crate::actlit] for more details.
1514    #[inline]
1515    pub fn print_check_sat_act<Actlits>(&mut self, actlits: Actlits) -> SmtRes<FutureCheckSat>
1516    where
1517        Actlits: IntoIterator,
1518        Actlits::Item: Sym2Smt,
1519    {
1520        match self.conf.get_check_sat_assuming() {
1521            Some(ref cmd) => {
1522                tee_write! {
1523                  self, no_check |w| write!(w, "({} (", cmd) ?
1524                }
1525                for actlit in actlits {
1526                    tee_write! {
1527                      self, no_check |w| {
1528                        write!(w, " ")?;
1529                        actlit.sym_to_smt2(w, ()) ?
1530                      }
1531                    }
1532                }
1533                tee_write! {
1534                  self, |w| write_str(w, ") )\n") ?
1535                }
1536                Ok(future_check_sat())
1537            }
1538            None => {
1539                let msg = format!("{} does not support check-sat-assuming", self.conf.desc());
1540                Err(msg.into())
1541            }
1542        }
1543    }
1544
1545    /// Parse the result of a check-sat, turns `unknown` results into errors.
1546    #[inline]
1547    pub fn parse_check_sat(&mut self, _: FutureCheckSat) -> SmtRes<bool> {
1548        if let Some(res) = self.smt_parser.check_sat()? {
1549            Ok(res)
1550        } else {
1551            Err(ErrorKind::Unknown.into())
1552        }
1553    }
1554
1555    /// Parse the result of a check-sat, turns `unknown` results into `None`.
1556    #[inline]
1557    pub fn parse_check_sat_or_unk(&mut self, _: FutureCheckSat) -> SmtRes<Option<bool>> {
1558        self.smt_parser.check_sat()
1559    }
1560
1561    /// Get-interpolant command.
1562    ///
1563    /// At the time of writing, only Z3 supports this command.
1564    #[inline]
1565    pub fn print_get_interpolant(
1566        &mut self,
1567        sym_1: impl Sym2Smt<()>,
1568        sym_2: impl Sym2Smt<()>,
1569    ) -> SmtRes<()> {
1570        tee_write! {
1571            self, no_check |w|
1572                write_str(w, "(get-interpolant ")?;
1573                sym_1.sym_to_smt2(w, ())?;
1574                write_str(w, " ")?;
1575                sym_2.sym_to_smt2(w, ())?;
1576                write_str(w, ")\n")?
1577        }
1578        Ok(())
1579    }
1580
1581    /// Get-model command.
1582    #[inline]
1583    fn print_get_model(&mut self) -> SmtRes<()> {
1584        tee_write! {
1585          self, no_check |w| write_str(w, "(get-model)\n") ?
1586        }
1587        Ok(())
1588    }
1589
1590    /// Get-assertions command.
1591    #[allow(dead_code)]
1592    fn print_get_assertions(&mut self) -> SmtRes<()> {
1593        tee_write! {
1594          self, no_check |w| write_str(w, "(get-assertions)\n") ?
1595        }
1596        Ok(())
1597    }
1598    /// Get-assignment command.
1599    #[allow(dead_code)]
1600    fn print_get_assignment(&mut self) -> SmtRes<()> {
1601        tee_write! {
1602          self, no_check |w| write_str(w, "(get-assignment)\n") ?
1603        }
1604        Ok(())
1605    }
1606    /// Get-unsat-assumptions command.
1607    #[allow(dead_code)]
1608    fn print_get_unsat_assumptions(&mut self) -> SmtRes<()> {
1609        tee_write! {
1610          self, no_check |w| write_str(w, "(get-unsat-assumptions)\n") ?
1611        }
1612        Ok(())
1613    }
1614    /// Get-proof command.
1615    #[allow(dead_code)]
1616    fn print_get_proof(&mut self) -> SmtRes<()> {
1617        tee_write! {
1618          self, no_check |w| write_str(w, "(get-proof)\n") ?
1619        }
1620        Ok(())
1621    }
1622    /// Get-unsat-core command.
1623    #[allow(dead_code)]
1624    fn print_get_unsat_core(&mut self) -> SmtRes<()> {
1625        tee_write! {
1626          self, no_check |w| write_str(w, "(get-unsat-core)\n") ?
1627        }
1628        Ok(())
1629    }
1630
1631    /// Get-values command.
1632    fn print_get_values_with<Exprs, Info>(&mut self, exprs: Exprs, info: Info) -> SmtRes<()>
1633    where
1634        Info: Copy,
1635        Exprs: IntoIterator,
1636        Exprs::Item: Expr2Smt<Info>,
1637    {
1638        tee_write! {
1639          self, no_check |w| write!(w, "(get-value (") ?
1640        }
1641        for e in exprs {
1642            tee_write! {
1643              self, no_check |w| {
1644                write_str(w, "\n  ")?;
1645                e.expr_to_smt2(w, info) ?
1646              }
1647            }
1648        }
1649        tee_write! {
1650          self, no_check |w| write_str(w, "\n) )\n") ?
1651        }
1652        Ok(())
1653    }
1654
1655    /// Check-sat with assumptions command with unit info.
1656    pub fn print_check_sat_assuming<Idents>(&mut self, bool_vars: Idents) -> SmtRes<FutureCheckSat>
1657    where
1658        Idents: IntoIterator,
1659        Idents::Item: Sym2Smt,
1660    {
1661        self.print_check_sat_assuming_with(bool_vars, ())
1662    }
1663
1664    /// Check-sat with assumptions command.
1665    pub fn print_check_sat_assuming_with<Idents, Info>(
1666        &mut self,
1667        bool_vars: Idents,
1668        info: Info,
1669    ) -> SmtRes<FutureCheckSat>
1670    where
1671        Info: Copy,
1672        Idents: IntoIterator,
1673        Idents::Item: Sym2Smt<Info>,
1674    {
1675        match self.conf.get_check_sat_assuming() {
1676            Some(ref cmd) => {
1677                tee_write! {
1678                  self, no_check |w| write!(w, "({} (\n ", cmd) ?
1679                }
1680                for sym in bool_vars {
1681                    tee_write! {
1682                      self, no_check |w| {
1683                        write_str(w, "  ")?;
1684                        sym.sym_to_smt2(w, info) ?
1685                      }
1686                    }
1687                }
1688                tee_write! {
1689                  self, no_check |w| write_str(w, "\n))\n") ?
1690                }
1691                Ok(future_check_sat())
1692            }
1693            None => {
1694                let msg = format!("{} does not support check-sat-assuming", self.conf.desc());
1695                Err(msg.into())
1696            }
1697        }
1698    }
1699
1700    /// Parse the result of a `get-model`.
1701    fn parse_get_model<Ident, Type, Value>(&mut self) -> SmtRes<Model<Ident, Type, Value>>
1702    where
1703        Parser: for<'p> IdentParser<Ident, Type, &'p mut RSmtParser>
1704            + for<'p> ModelParser<Ident, Type, Value, &'p mut RSmtParser>,
1705    {
1706        let has_actlits = self.has_actlits();
1707        let res = self.smt_parser.get_model(has_actlits, self.parser);
1708        if res.is_err() && !self.conf.get_models() {
1709            res.chain_err(|| {
1710                "\
1711                 Note: model production is not active \
1712                 for this SmtConf, see [`SmtConf::models`]\
1713                 "
1714            })
1715        } else {
1716            res
1717        }
1718    }
1719
1720    /// Parses the result of a `get-unsat-core`.
1721    fn parse_get_unsat_core<Sym>(&mut self) -> SmtRes<Vec<Sym>>
1722    where
1723        Parser: for<'p> SymParser<Sym, &'p mut RSmtParser>,
1724    {
1725        self.smt_parser.get_unsat_core(self.parser)
1726    }
1727
1728    /// Parse the result of a `get-model` where all the symbols are nullary.
1729    fn parse_get_model_const<Ident, Type, Value>(&mut self) -> SmtRes<Vec<(Ident, Type, Value)>>
1730    where
1731        Parser: for<'p> IdentParser<Ident, Type, &'p mut RSmtParser>
1732            + for<'p> ModelParser<Ident, Type, Value, &'p mut RSmtParser>,
1733    {
1734        let has_actlits = self.has_actlits();
1735        let res = self.smt_parser.get_model_const(has_actlits, self.parser);
1736        if res.is_err() && !self.conf.get_models() {
1737            res.chain_err(|| {
1738                "\
1739                 Note: model production is not active \
1740                 for this SmtConf (`conf.models()`)\
1741                 "
1742            })
1743        } else {
1744            res
1745        }
1746    }
1747
1748    /// Parse the result of a get-values.
1749    fn parse_get_values_with<Info, Expr, Val>(&mut self, info: Info) -> SmtRes<Vec<(Expr, Val)>>
1750    where
1751        Info: Copy,
1752        Parser: for<'p> ExprParser<Expr, Info, &'p mut RSmtParser>
1753            + for<'p> ValueParser<Val, &'p mut RSmtParser>,
1754    {
1755        let res = self.smt_parser.get_values(self.parser, info);
1756        if res.is_err() && !self.conf.get_models() {
1757            res.chain_err(|| {
1758                "Note: model production is not active \
1759                for this SmtConf (`conf.models()`)"
1760            })
1761        } else {
1762            res
1763        }
1764    }
1765
1766    /// Parses the result of a `get-interpolant`.
1767    fn parse_get_interpolant<Expr, Info>(&mut self, info: Info) -> SmtRes<Expr>
1768    where
1769        Parser: for<'p> ExprParser<Expr, Info, &'p mut RSmtParser>,
1770    {
1771        let mut res = self.smt_parser.get_interpolant(self.parser, info);
1772        if res.is_err() {
1773            if !self.conf.style().is_z3() {
1774                res = res.chain_err(|| {
1775                    format!(
1776                        "`{}` does not support interpolant production, only Z3 does",
1777                        self.conf.style()
1778                    )
1779                })
1780            } else if !self.conf.get_interpolants() {
1781                res = res.chain_err(|| format!("interpolant production is not active"))
1782            }
1783        }
1784        res
1785    }
1786}
1787
1788/// # Non-blocking commands.
1789impl<Parser: Send + 'static> Solver<Parser> {
1790    /// Asynchronous check-sat, see the [`asynch` module][crate::asynch] for details.
1791    ///
1792    /// This function is not `unsafe` in the sense that it **cannot** create undefined behavior.
1793    /// However, it is *unsafe* because the asynchronous check might end up running forever in the
1794    /// background, burning 100% CPU.
1795    pub unsafe fn async_check_sat_or_unk(&mut self) -> crate::asynch::CheckSatFuture<Parser> {
1796        crate::asynch::CheckSatFuture::new(self)
1797    }
1798}
1799
1800/// # Sort-related SMT-LIB commands.
1801impl<Parser> Solver<Parser> {
1802    /// Declares a new sort.
1803    ///
1804    /// # Examples
1805    ///
1806    /// ```rust
1807    /// # use rsmt2::Solver;
1808    /// let mut solver = Solver::default_z3(()).unwrap();
1809    /// solver.declare_sort("A", 0).unwrap();
1810    /// solver.declare_const("x", "A").unwrap();
1811    /// solver.declare_const("y", "A").unwrap();
1812    /// solver.declare_fun("f", & [ "A" ], "A").unwrap();
1813    /// solver.assert("(= (f (f x)) x)").unwrap();
1814    /// solver.assert("(= (f x) y)").unwrap();
1815    /// solver.assert("(not (= x y))").unwrap();
1816    /// let sat = solver.check_sat().unwrap();
1817    /// ```
1818    #[inline]
1819    pub fn declare_sort(&mut self, sort: impl Sort2Smt, arity: u8) -> SmtRes<()> {
1820        tee_write! {
1821          self, |w| {
1822            write_str(w, "(declare-sort ")?;
1823            sort.sort_to_smt2(w)?;
1824            writeln!(w, " {})", arity) ?
1825          }
1826        }
1827        Ok(())
1828    }
1829
1830    /// Defines a new sort.
1831    ///
1832    /// # Examples
1833    ///
1834    /// Note the use of [`Self::define_null_sort`] to avoid problems with empty arguments.
1835    ///
1836    /// ```rust
1837    /// # use rsmt2::Solver;
1838    /// let mut solver = Solver::default_z3(()).unwrap();
1839    /// solver.define_sort("MySet", & ["T"], "(Array T Bool)").unwrap();
1840    /// solver.define_null_sort("IList", "(List Int)").unwrap();
1841    /// solver.define_sort(
1842    ///     "List-Set", & ["T"], "(Array (List T) Bool)"
1843    /// ).unwrap();
1844    /// solver.define_null_sort("I", "Int").unwrap();
1845    ///
1846    /// solver.declare_const("s1", "(MySet I)").unwrap();
1847    /// solver.declare_const("s2", "(List-Set Int)").unwrap();
1848    /// solver.declare_const("a", "I").unwrap();
1849    /// solver.declare_const("l", "IList").unwrap();
1850    ///
1851    /// solver.assert("(= (select s1 a) true)").unwrap();
1852    /// solver.assert("(= (select s2 l) false)").unwrap();
1853    /// let sat = solver.check_sat().unwrap();
1854    /// ```
1855    #[inline]
1856    pub fn define_sort<Args>(
1857        &mut self,
1858        sort_sym: impl Sym2Smt,
1859        args: Args,
1860        body: impl Sort2Smt,
1861    ) -> SmtRes<()>
1862    where
1863        Args: IntoIterator,
1864        Args::Item: Sort2Smt,
1865    {
1866        tee_write! {
1867          self, no_check |w| {
1868            write_str(w, "( define-sort ")?;
1869            sort_sym.sym_to_smt2(w, ())?;
1870            write_str(w, "\n   ( ")?;
1871          }
1872        }
1873        for arg in args {
1874            tee_write! {
1875              self, no_check |w| {
1876                arg.sort_to_smt2(w)?;
1877                write_str(w, " ") ?
1878              }
1879            }
1880        }
1881        tee_write! {
1882          self, |w| {
1883            write_str(w, ")\n   ")?;
1884            body.sort_to_smt2(w)?;
1885            write_str(w, "\n)\n") ?
1886          }
1887        }
1888        Ok(())
1889    }
1890
1891    /// Defines a new nullary sort.
1892    ///
1893    /// When using [`Self::define_sort`] with empty `args`, rust complains because it does not know
1894    /// what the `Arg` type parameter is. This function addresses this problem by not having
1895    /// arguments.
1896    #[inline]
1897    pub fn define_null_sort(&mut self, sym: impl Sym2Smt, body: impl Sort2Smt) -> SmtRes<()> {
1898        // Does not matter, just needs to implement `Sort2Smt`
1899        //                                                vvvv
1900        self.define_sort(sym, None as Option<&str>, body)
1901    }
1902}
1903
1904/// # SMT-LIB commands vehiculating user information.
1905impl<Parser> Solver<Parser> {
1906    /// Declares a new constant.
1907    #[inline]
1908    pub fn declare_const_with<Info>(
1909        &mut self,
1910        symbol: impl Sym2Smt<Info>,
1911        out_sort: impl Sort2Smt,
1912        info: Info,
1913    ) -> SmtRes<()>
1914    where
1915        Info: Copy,
1916    {
1917        tee_write! {
1918          self, |w| {
1919            write_str(w, "(declare-const ")?;
1920            symbol.sym_to_smt2(w, info)?;
1921            write_str(w, " ")?;
1922            out_sort.sort_to_smt2(w)?;
1923            write_str(w, ")\n") ?
1924          }
1925        }
1926        Ok(())
1927    }
1928
1929    /// Declares a new function symbol.
1930    #[inline]
1931    pub fn declare_fun_with<Args, Info>(
1932        &mut self,
1933        symbol: impl Sym2Smt<Info>,
1934        args: Args,
1935        out: impl Sort2Smt,
1936        info: Info,
1937    ) -> SmtRes<()>
1938    where
1939        Info: Copy,
1940        Args: IntoIterator,
1941        Args::Item: Sort2Smt,
1942    {
1943        tee_write! {
1944          self, no_check |w| {
1945            write_str(w, "(declare-fun ")?;
1946            symbol.sym_to_smt2(w, info)?;
1947            write_str(w, " ( ") ?
1948          }
1949        }
1950        for arg in args {
1951            tee_write! {
1952              self, no_check |w| {
1953                arg.sort_to_smt2(w)?;
1954                write_str(w, " ") ?
1955              }
1956            }
1957        }
1958        tee_write! {
1959          self, |w| {
1960            write_str(w, ") ")?;
1961            out.sort_to_smt2(w)?;
1962            write_str(w, ")\n") ?
1963          }
1964        }
1965        Ok(())
1966    }
1967
1968    /// Defines a new constant.
1969    #[inline]
1970    pub fn define_const_with<Info>(
1971        &mut self,
1972        symbol: impl Sym2Smt<Info>,
1973        out_sort: impl Sort2Smt,
1974        body: impl Expr2Smt<Info>,
1975        info: Info,
1976    ) -> SmtRes<()>
1977    where
1978        Info: Copy,
1979    {
1980        tee_write! {
1981          self, |w| {
1982            write_str(w, "(define-const ")?;
1983            symbol.sym_to_smt2(w, info)?;
1984            write_str(w, " ")?;
1985            out_sort.sort_to_smt2(w)?;
1986            write_str(w, " ")?;
1987            body.expr_to_smt2(w, info)?;
1988            write_str(w, ")\n") ?
1989          }
1990        }
1991        Ok(())
1992    }
1993
1994    /// Defines a new function symbol.
1995    #[inline]
1996    pub fn define_fun_with<Args, Info>(
1997        &mut self,
1998        symbol: impl Sym2Smt<Info>,
1999        args: Args,
2000        out: impl Sort2Smt,
2001        body: impl Expr2Smt<Info>,
2002        info: Info,
2003    ) -> SmtRes<()>
2004    where
2005        Info: Copy,
2006        Args: IntoIterator,
2007        Args::Item: SymAndSort<Info>,
2008    {
2009        tee_write! {
2010          self, no_check |w| {
2011            write_str(w, "(define-fun ")?;
2012            symbol.sym_to_smt2(w, info)?;
2013            write_str(w, " ( ") ?
2014          }
2015        }
2016        for arg in args {
2017            let sym = arg.sym();
2018            let sort = arg.sort();
2019            tee_write! {
2020              self, no_check |w| {
2021                write_str(w, "(")?;
2022                sym.sym_to_smt2(w, info)?;
2023                write_str(w, " ")?;
2024                sort.sort_to_smt2(w)?;
2025                write_str(w, ") ") ?
2026              }
2027            }
2028        }
2029        tee_write! {
2030          self, |w| {
2031            write_str(w, ") ")?;
2032            out.sort_to_smt2(w)?;
2033            write_str(w, "\n   ")?;
2034            body.expr_to_smt2(w, info)?;
2035            write_str(w, "\n)\n") ?
2036          }
2037        }
2038        Ok(())
2039    }
2040
2041    /// Defines some new (possibily mutually) recursive functions.
2042    pub fn define_funs_rec_with<Defs, Info>(&mut self, funs: Defs, info: Info) -> SmtRes<()>
2043    where
2044        Info: Copy,
2045        Defs: IntoIterator + Clone,
2046        Defs::Item: FunDef<Info>,
2047    {
2048        // Header.
2049        tee_write! {
2050          self, no_check |w| write_str(w, "(define-funs-rec (\n") ?
2051        }
2052
2053        // Signatures.
2054        for fun in funs.clone() {
2055            let sym = fun.fun_sym();
2056            let args = fun.args();
2057            let out = fun.out_sort();
2058
2059            tee_write! {
2060                self, no_check |w| {
2061                    write_str(w, "   (")?;
2062                    sym.sym_to_smt2(w, info)?;
2063                    write_str(w, " ( ") ?
2064                }
2065            }
2066
2067            for arg in args {
2068                tee_write! {
2069                    self, no_check |w| {
2070                        let sym = arg.sym();
2071                        let sort = arg.sort();
2072                        write_str(w, "(")?;
2073                        sym.sym_to_smt2(w, info)?;
2074                        write_str(w, " ")?;
2075                        sort.sort_to_smt2(w)?;
2076                        write_str(w, ") ") ?
2077                    }
2078                }
2079            }
2080
2081            tee_write! {
2082              self, no_check |w| {
2083                write_str(w, ") ")?;
2084                out.sort_to_smt2(w)?;
2085                write_str(w, ")\n") ?
2086              }
2087            }
2088        }
2089        tee_write! {
2090          self, no_check |w| write_str(w, " ) (") ?
2091        }
2092
2093        // Bodies
2094        for fun in funs {
2095            let body = fun.body();
2096            tee_write! {
2097              self, no_check |w| {
2098                write_str(w, "\n   ")?;
2099                body.expr_to_smt2(w, info) ?
2100              }
2101            }
2102        }
2103        tee_write! {
2104          self, |w| write_str(w, "\n )\n)\n") ?
2105        }
2106        Ok(())
2107    }
2108
2109    /// Defines a new recursive function.
2110    #[inline]
2111    pub fn define_fun_rec_with<Args, Info>(
2112        &mut self,
2113        symbol: impl Sym2Smt<Info>,
2114        args: Args,
2115        out: impl Sort2Smt,
2116        body: impl Expr2Smt<Info>,
2117        info: Info,
2118    ) -> SmtRes<()>
2119    where
2120        Info: Copy,
2121        Args: IntoIterator,
2122        Args::Item: SymAndSort<Info>,
2123    {
2124        // Header.
2125        tee_write! {
2126          self, no_check |w| write_str(w, "(define-fun-rec (\n") ?
2127        }
2128
2129        tee_write! {
2130          self, no_check |w| {
2131            // Signature.
2132            write_str(w, "   (")?;
2133            symbol.sym_to_smt2(w, info)?;
2134            write_str(w, " ( ") ?
2135          }
2136        }
2137
2138        for arg in args {
2139            let sym = arg.sym();
2140            let sort = arg.sort();
2141            tee_write! {
2142              self, no_check |w| {
2143                write_str(w, "(")?;
2144                sym.sym_to_smt2(w, info)?;
2145                write_str(w, " ")?;
2146                sort.sort_to_smt2(w)?;
2147                write_str(w, ") ") ?
2148              }
2149            }
2150        }
2151
2152        tee_write! {
2153          self, |w| {
2154            write_str(w, ") ")?;
2155            out.sort_to_smt2(w)?;
2156            write_str(w, ")\n")?;
2157            write_str(w, " ) (")?;
2158
2159            // Body.
2160            write_str(w, "\n   ")?;
2161            body.expr_to_smt2(w, info)?;
2162            write_str(w, "\n )\n)\n") ?
2163          }
2164        }
2165        Ok(())
2166    }
2167
2168    /// Asserts an expression with info, optional actlit and optional name.
2169    #[inline]
2170    pub fn full_assert<Act, Name, Info>(
2171        &mut self,
2172        actlit: Option<Act>,
2173        name: Option<Name>,
2174        expr: impl Expr2Smt<Info>,
2175        info: Info,
2176    ) -> SmtRes<()>
2177    where
2178        Info: Copy,
2179        Name: Sym2Smt,
2180        Act: Sym2Smt,
2181    {
2182        tee_write! {
2183            self, |w| {
2184                write_str(w, "(assert")?;
2185                if name.is_some() {
2186                    write_str(w, " (!")?;
2187                }
2188                if let Some(actlit) = actlit.as_ref() {
2189                    write_str(w, " (=> ")?;
2190                    actlit.sym_to_smt2(w, ())?;
2191                }
2192                write_str(w, "\n    ")?;
2193                expr.expr_to_smt2(w, info)?;
2194                write_str(w, "\n")?;
2195                if actlit.is_some() {
2196                    write_str(w, ")")?;
2197                }
2198                if let Some(name) = name.as_ref() {
2199                    write_str(w, " :named ")?;
2200                    name.sym_to_smt2(w, ())?;
2201                    write_str(w, ")")?;
2202                }
2203                write_str(w, ")\n")?;
2204            }
2205        }
2206        Ok(())
2207    }
2208
2209    /// Asserts an expression with an activation literal, a name and some print info.
2210    #[inline]
2211    pub fn named_assert_act_with<Info>(
2212        &mut self,
2213        actlit: &Actlit,
2214        name: impl Sym2Smt,
2215        expr: impl Expr2Smt<Info>,
2216        info: Info,
2217    ) -> SmtRes<()>
2218    where
2219        Info: Copy,
2220    {
2221        self.full_assert(Some(actlit), Some(name), expr, info)
2222    }
2223
2224    /// Asserts an expression with some print information, guarded by an activation literal.
2225    ///
2226    /// See the [`actlit` module][crate::actlit] for more details.
2227    #[inline]
2228    pub fn assert_act_with<Info>(
2229        &mut self,
2230        actlit: &Actlit,
2231        expr: impl Expr2Smt<Info>,
2232        info: Info,
2233    ) -> SmtRes<()>
2234    where
2235        Info: Copy,
2236    {
2237        let name: Option<&str> = None;
2238        self.full_assert(Some(actlit.as_ref()), name, expr, info)
2239    }
2240
2241    /// Asserts an expression with some print information.
2242    #[inline]
2243    pub fn assert_with<Info, Expr>(&mut self, expr: Expr, info: Info) -> SmtRes<()>
2244    where
2245        Info: Copy,
2246        Expr: Expr2Smt<Info>,
2247    {
2248        let name: Option<&str> = None;
2249        let act: Option<Actlit> = None;
2250        self.full_assert(act, name, expr, info)
2251    }
2252
2253    /// Asserts a named expression.
2254    #[inline]
2255    pub fn named_assert<Expr, Name>(&mut self, name: Name, expr: Expr) -> SmtRes<()>
2256    where
2257        Name: Sym2Smt,
2258        Expr: Expr2Smt,
2259    {
2260        let act: Option<Actlit> = None;
2261        self.full_assert(act, Some(name), expr, ())
2262    }
2263
2264    /// Asserts an expression with a name and some print info.
2265    #[inline]
2266    pub fn named_assert_with<Name, Info, Expr>(
2267        &mut self,
2268        name: Name,
2269        expr: Expr,
2270        info: Info,
2271    ) -> SmtRes<()>
2272    where
2273        Info: Copy,
2274        Expr: Expr2Smt<Info>,
2275        Name: Sym2Smt,
2276    {
2277        let act: Option<Actlit> = None;
2278        self.full_assert(act, Some(name), expr, info)
2279    }
2280
2281    /// Check-sat assuming command, turns `unknown` results into errors.
2282    pub fn check_sat_assuming_with<Info, Syms>(&mut self, idents: Syms, info: Info) -> SmtRes<bool>
2283    where
2284        Info: Copy,
2285        Syms: IntoIterator,
2286        Syms::Item: Sym2Smt<Info>,
2287    {
2288        let future = self.print_check_sat_assuming_with(idents, info)?;
2289        self.parse_check_sat(future)
2290    }
2291
2292    /// Check-sat assuming command, turns `unknown` results into `None`.
2293    pub fn check_sat_assuming_or_unk_with<Idents, Info>(
2294        &mut self,
2295        idents: Idents,
2296        info: Info,
2297    ) -> SmtRes<Option<bool>>
2298    where
2299        Info: Copy,
2300        Idents: IntoIterator,
2301        Idents::Item: Sym2Smt<Info>,
2302    {
2303        let future = self.print_check_sat_assuming_with(idents, info)?;
2304        self.parse_check_sat_or_unk(future)
2305    }
2306}
2307
2308/// # Other commands.
2309impl<Parser> Solver<Parser> {
2310    /// Set option command.
2311    #[inline]
2312    pub fn set_option<Value: ::std::fmt::Display>(
2313        &mut self,
2314        option: &str,
2315        value: Value,
2316    ) -> SmtRes<()> {
2317        match option {
2318            ":interactive_mode" => return Err("illegal set-option on interactive mode".into()),
2319            _ => (),
2320        };
2321        tee_write! {
2322          self, |w| writeln!(
2323            w, "(set-option {} {})", option, value
2324          ) ?
2325        }
2326        Ok(())
2327    }
2328
2329    /// Resets the assertions in the solver.
2330    #[inline]
2331    pub fn reset_assertions(&mut self) -> SmtRes<()> {
2332        tee_write! {
2333          self, |w| write_str(w, "(reset-assertions)\n") ?
2334        }
2335        Ok(())
2336    }
2337
2338    // // |===| Inspecting settings.
2339
2340    /// Get info command.
2341    #[inline]
2342    pub fn get_info(&mut self, flag: &str) -> SmtRes<()> {
2343        tee_write! {
2344          self, no_check |w| writeln!(w, "(get-info {})", flag) ?
2345        }
2346        Ok(())
2347    }
2348    /// Get option command.
2349    #[inline]
2350    pub fn get_option(&mut self, option: &str) -> SmtRes<()> {
2351        tee_write! {
2352          self, no_check |w| writeln!(w, "(get-option {})", option) ?
2353        }
2354        Ok(())
2355    }
2356
2357    // |===| Script information.
2358
2359    /// Set info command.
2360    #[inline]
2361    pub fn set_info(&mut self, attribute: &str) -> SmtRes<()> {
2362        tee_write! {
2363          self, |w| writeln!(w, "(set-info {})", attribute) ?
2364        }
2365        Ok(())
2366    }
2367    /// Echo command.
2368    #[inline]
2369    pub fn echo(&mut self, text: &str) -> SmtRes<()> {
2370        tee_write! {
2371          self, no_check |w| writeln!(w, "(echo \"{}\")", text) ?
2372        }
2373        Ok(())
2374    }
2375}