rsmt2/conf.rs
1//! Solver configuration, contains backend-solver-specific info.
2//!
3//! Do **NOT** use wildcards when matching over `SmtStyle`. We want the code to fail to compile
4//! whenever we add a solver. Likewise, do not use `if let` with `SmtStyle`.
5//!
6//! Note that the command for each solver can be passed through environment variables, see
7//! - [`Z3_ENV_VAR`],
8//! - [`CVC4_ENV_VAR`],
9//! - [`YICES_2_ENV_VAR`], and
10//! - the [`SmtConf::z3_or_env`], [`SmtConf::cvc4_or_env`], and [`SmtConf::yices_2_or_env`]
11//! constructors.
12
13use std::fmt;
14
15use crate::{SmtRes, Solver};
16
17use self::SmtStyle::*;
18
19/// A configuration item is either a keyword or unsupported.
20pub type ConfItem = Option<&'static str>;
21
22/// Value of an unsupported configuration item.
23#[inline]
24fn unsupported() -> ConfItem {
25 None
26}
27/// Keyword for a configuration item.
28#[inline]
29fn supported(keyword: &'static str) -> ConfItem {
30 Some(keyword)
31}
32
33/// Environment variable providing the command for z3.
34pub const Z3_ENV_VAR: &str = "RSMT2_Z3_CMD";
35/// Environment variable providing the command for CVC4.
36pub const CVC4_ENV_VAR: &str = "RSMT2_CVC4_CMD";
37/// Environment variable providing the command for Yices 2.
38pub const YICES_2_ENV_VAR: &str = "RSMT2_YICES_2_CMD";
39
40/// Retrieves the value of an environment variable.
41fn get_env_var(env_var: &str) -> SmtRes<Option<String>> {
42 match std::env::var(env_var) {
43 Ok(res) => Ok(Some(res)),
44 Err(std::env::VarError::NotPresent) => Ok(None),
45 Err(std::env::VarError::NotUnicode(cmd)) => bail!(
46 "value of environment variable `{}` is not legal unicode: `{}`",
47 env_var,
48 cmd.to_string_lossy(),
49 ),
50 }
51}
52
53/// Solver styles.
54///
55/// - [z3][z3]: full support
56/// - [cvc4][cvc4]: full support in theory, but only partially tested. Note that `get-value` is
57/// known to crash some versions of CVC4.
58/// - [yices 2][yices 2]: full support in theory, but only partially tested. Command `get-model`
59/// will only work on Yices 2 > `2.6.1`, and needs to be activated in [`SmtConf`] with
60/// [`SmtConf::models`]. To understand why, see <https://github.com/SRI-CSL/yices2/issues/162>.
61///
62/// [z3]: https://github.com/Z3Prover/z3 (z3 github repository)
63/// [cvc4]: https://cvc4.github.io/ (cvc4 github pages)
64/// [yices 2]: https://yices.csl.sri.com/ (yices 2 official page)
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
66#[allow(dead_code)]
67pub enum SmtStyle {
68 /// Z3-style smt solver.
69 Z3,
70 /// CVC4-style smt solver.
71 ///
72 /// **NB**: CVC4 has only been partially tested at this point.
73 CVC4,
74 /// Yices-2-style smt solver.
75 ///
76 /// **NB**: Yices 2 has only been partially tested at this point.
77 Yices2,
78}
79
80impl SmtStyle {
81 /// Configuration constructor.
82 pub fn new(self, cmd: impl Into<String>) -> SmtConf {
83 let cmd = cmd.into();
84 match self {
85 Z3 => SmtConf {
86 style: self,
87 cmd,
88 options: vec!["-in".into(), "-smt2".into()],
89 models: true,
90 incremental: true,
91 check_success: false,
92 unsat_cores: false,
93 interpolants: true,
94 check_sat_assuming: supported("check-sat-assuming"),
95 },
96 CVC4 => SmtConf {
97 style: self,
98 cmd,
99 options: vec![
100 "-q".into(),
101 "--no-interactive".into(),
102 "--lang".into(),
103 "smt2".into(),
104 ],
105 models: false,
106 incremental: false,
107 check_success: false,
108 unsat_cores: false,
109 interpolants: false,
110 check_sat_assuming: unsupported(),
111 },
112 Yices2 => SmtConf {
113 style: self,
114 cmd,
115 options: vec![],
116 models: false,
117 incremental: false,
118 check_success: false,
119 unsat_cores: false,
120 interpolants: false,
121 check_sat_assuming: supported("check-sat-assuming"),
122 },
123 }
124 }
125
126 /// Default configuration for a solver style.
127 ///
128 /// # Warning
129 ///
130 /// The command used to run a particular solver is up to the end-user. As such, it **does not
131 /// make sense** to use default commands for anything else than local testing. You should
132 /// explicitely pass the command to use with [`Self::new`] instead.
133 pub fn default(self) -> SmtConf {
134 self.new(self.cmd())
135 }
136
137 /// A solver style from a string.
138 #[allow(dead_code)]
139 pub fn of_str(s: &str) -> Option<Self> {
140 match s {
141 "z3" | "Z3" => Some(Z3),
142 "cvc4" | "CVC4" => Some(CVC4),
143 "Yices2" | "yices2" | "YICES2" | "Yices 2" | "yices 2" | "YICES 2" => Some(Yices2),
144 _ => None,
145 }
146 }
147 /// Legal string representations of solver styles.
148 #[allow(dead_code)]
149 pub fn str_keys() -> Vec<&'static str> {
150 vec![
151 "z3", "Z3", "cvc4", "CVC4", "Yices2", "yices2", "YICES2", "Yices 2", "yices 2",
152 "YICES 2",
153 ]
154 }
155
156 /// Solver style command from the corresponding environment variable.
157 ///
158 /// The environement variables scanned are [`Z3_ENV_VAR`], [`CVC4_ENV_VAR`] and
159 /// [`YICES_2_ENV_VAR`].
160 pub fn env_cmd(self) -> SmtRes<Option<String>> {
161 match self {
162 Z3 => get_env_var(Z3_ENV_VAR),
163 CVC4 => get_env_var(CVC4_ENV_VAR),
164 Yices2 => get_env_var(YICES_2_ENV_VAR),
165 }
166 }
167
168 /// Default command for a solver style.
169 #[cfg(not(windows))]
170 pub fn cmd(self) -> &'static str {
171 match self {
172 Z3 => "z3",
173 CVC4 => "cvc4",
174 Yices2 => "yices",
175 }
176 }
177 /// Default command for a solver style.
178 #[cfg(windows)]
179 pub fn cmd(self) -> &'static str {
180 match self {
181 Z3 => "z3.exe",
182 CVC4 => "cvc4.exe",
183 Yices2 => "yices.exe",
184 }
185 }
186
187 /// True if `self` is [`Self::Z3`].
188 pub fn is_z3(self) -> bool {
189 self == Self::Z3
190 }
191}
192
193impl fmt::Display for SmtStyle {
194 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
195 match *self {
196 Z3 => write!(fmt, "z3"),
197 CVC4 => write!(fmt, "cvc4"),
198 Yices2 => write!(fmt, "yices2"),
199 }
200 }
201}
202
203/// Configuration and solver specific info.
204///
205/// - [z3]: full support
206/// - [cvc4]: full support in theory, but only partially tested. Note that `get-value` is
207/// known to crash some versions of CVC4.
208/// - [yices 2]: full support in theory, but only partially tested. Command `get-model`
209/// will only work on Yices 2 > `2.6.1`, and needs to be activated with [`Self::models`]. To
210/// understand why, see <https://github.com/SRI-CSL/yices2/issues/162>.
211///
212/// [z3]: https://github.com/Z3Prover/z3 (z3 github repository)
213/// [cvc4]: https://cvc4.github.io/ (cvc4 github pages)
214/// [yices 2]: https://yices.csl.sri.com/ (yices 2 official page)
215#[derive(Debug, Clone)]
216pub struct SmtConf {
217 /// Solver style.
218 style: SmtStyle,
219 /// Solver command.
220 cmd: String,
221 /// Options to call the solver with.
222 options: Vec<String>,
223 /// Model production.
224 models: bool,
225 /// Incrementality.
226 incremental: bool,
227 /// Parse success.
228 check_success: bool,
229 /// Triggers unsat-core production.
230 unsat_cores: bool,
231 /// Triggers interpolant production.
232 interpolants: bool,
233 /// Keyword for check-sat with assumptions.
234 check_sat_assuming: ConfItem,
235}
236
237impl SmtConf {
238 /// Solver style accessor.
239 pub fn style(&self) -> SmtStyle {
240 self.style
241 }
242
243 /// Creates a new z3-like solver configuration.
244 ///
245 /// # Examples
246 ///
247 /// ```rust
248 /// # use rsmt2::SmtConf;
249 /// let conf = SmtConf::z3("my_z3_command");
250 /// assert!(conf.get_cmd() == "my_z3_command")
251 /// ```
252 #[inline]
253 pub fn z3(cmd: impl Into<String>) -> Self {
254 Z3.new(cmd)
255 }
256
257 /// Creates a new cvc4-like solver configuration.
258 ///
259 /// # Examples
260 ///
261 /// ```rust
262 /// # use rsmt2::SmtConf;
263 /// let conf = SmtConf::cvc4("my_cvc4_command");
264 /// assert!(conf.get_cmd() == "my_cvc4_command")
265 /// ```
266 #[inline]
267 pub fn cvc4(cmd: impl Into<String>) -> Self {
268 CVC4.new(cmd)
269 }
270
271 /// Creates a new yices-2-like solver configuration.
272 ///
273 /// # Examples
274 ///
275 /// ```rust
276 /// # use rsmt2::SmtConf;
277 /// let conf = SmtConf::yices_2("my_yices_2_command");
278 /// assert!(conf.get_cmd() == "my_yices_2_command")
279 /// ```
280 #[inline]
281 pub fn yices_2(cmd: impl Into<String>) -> Self {
282 Yices2.new(cmd)
283 }
284
285 /// Creates a z3-like solver configuration from an optional, or the value of the [`Z3_ENV_VAR`]
286 /// environment variable.
287 ///
288 /// Fails if `cmd.is_none()` and [`Z3_ENV_VAR`] is not set.
289 ///
290 /// ```rust
291 /// use rsmt2::conf::{SmtConf, Z3_ENV_VAR};
292 /// use std::env::{set_var, var_os};
293 ///
294 /// // Passes the command directly.
295 /// let cmd = "z3_explicit";
296 /// let explicit_cmd = SmtConf::z3_or_env(Some(cmd.into())).expect("explicit");
297 /// assert_eq!(explicit_cmd.get_cmd(), cmd);
298 ///
299 /// // Error if no command + environment variable not set.
300 /// assert_eq!(var_os(Z3_ENV_VAR), None);
301 /// let error = SmtConf::z3_or_env(None);
302 /// match error {
303 /// Ok(_) => panic!("expected error, got an SMT style"),
304 /// Err(e) => assert_eq!(
305 /// &e.to_string(),
306 /// "no command for z3 provided, \
307 /// and `RSMT2_Z3_CMD` environment variable not set; \
308 /// cannot spawn z3 solver"
309 /// ),
310 /// }
311 ///
312 /// // Retrieves the command from the environment.
313 /// let cmd = "z3_implicit";
314 /// assert_eq!(Z3_ENV_VAR, "RSMT2_Z3_CMD");
315 /// set_var(Z3_ENV_VAR, cmd);
316 /// let implicit_cmd = SmtConf::z3_or_env(None).expect("implicit");
317 /// assert_eq!(implicit_cmd.get_cmd(), cmd);
318 /// ```
319 #[inline]
320 pub fn z3_or_env(cmd: Option<String>) -> SmtRes<Self> {
321 if let Some(cmd) = cmd {
322 Ok(Self::z3(cmd))
323 } else {
324 let cmd = SmtStyle::Z3.env_cmd()?;
325 if let Some(cmd) = cmd {
326 Ok(Self::z3(cmd))
327 } else {
328 bail!(
329 "no command for z3 provided, \
330 and `{}` environment variable not set; cannot spawn z3 solver",
331 Z3_ENV_VAR,
332 )
333 }
334 }
335 }
336
337 /// Creates a CVC4-like solver configuration from an optional, or the value of the
338 /// [`CVC4_ENV_VAR`] environment variable.
339 ///
340 /// Fails if `cmd.is_none()` and [`CVC4_ENV_VAR`] is not set.
341 ///
342 /// ```rust
343 /// use rsmt2::conf::{SmtConf, CVC4_ENV_VAR};
344 /// use std::env::{set_var, var_os};
345 ///
346 /// // Passes the command directly.
347 /// let cmd = "cvc4_explicit";
348 /// let explicit_cmd = SmtConf::cvc4_or_env(Some(cmd.into())).expect("explicit");
349 /// assert_eq!(explicit_cmd.get_cmd(), cmd);
350 ///
351 /// // Error if no command + environment variable not set.
352 /// assert_eq!(var_os(CVC4_ENV_VAR), None);
353 /// let error = SmtConf::cvc4_or_env(None);
354 /// match error {
355 /// Ok(_) => panic!("expected error, got an SMT style"),
356 /// Err(e) => assert_eq!(
357 /// &e.to_string(),
358 /// "no command for CVC4 provided, \
359 /// and `RSMT2_CVC4_CMD` environment variable not set; \
360 /// cannot spawn CVC4 solver"
361 /// ),
362 /// }
363 ///
364 /// // Retrieves the command from the environment.
365 /// let cmd = "cvc4_implicit";
366 /// assert_eq!(CVC4_ENV_VAR, "RSMT2_CVC4_CMD");
367 /// set_var(CVC4_ENV_VAR, cmd);
368 /// let implicit_cmd = SmtConf::cvc4_or_env(None).expect("implicit");
369 /// assert_eq!(implicit_cmd.get_cmd(), cmd);
370 /// ```
371 #[inline]
372 pub fn cvc4_or_env(cmd: Option<String>) -> SmtRes<Self> {
373 if let Some(cmd) = cmd {
374 Ok(Self::cvc4(cmd))
375 } else {
376 let cmd = SmtStyle::CVC4.env_cmd()?;
377 if let Some(cmd) = cmd {
378 Ok(Self::cvc4(cmd))
379 } else {
380 bail!(
381 "no command for CVC4 provided, \
382 and `{}` environment variable not set; cannot spawn CVC4 solver",
383 CVC4_ENV_VAR,
384 )
385 }
386 }
387 }
388
389 /// Creates a Yices-2-like solver configuration from an optional, or the value of the
390 /// [`YICES_2_ENV_VAR`] environment variable.
391 ///
392 /// Fails if `cmd.is_none()` and [`YICES_2_ENV_VAR`] is not set.
393 ///
394 /// ```rust
395 /// use rsmt2::conf::{SmtConf, YICES_2_ENV_VAR};
396 /// use std::env::{set_var, var_os};
397 ///
398 /// // Passes the command directly.
399 /// let cmd = "yices_2_explicit";
400 /// let explicit_cmd = SmtConf::yices_2_or_env(Some(cmd.into())).expect("explicit");
401 /// assert_eq!(explicit_cmd.get_cmd(), cmd);
402 ///
403 /// // Error if no command + environment variable not set.
404 /// assert_eq!(var_os(YICES_2_ENV_VAR), None);
405 /// let error = SmtConf::yices_2_or_env(None);
406 /// match error {
407 /// Ok(_) => panic!("expected error, got an SMT style"),
408 /// Err(e) => assert_eq!(
409 /// &e.to_string(),
410 /// "no command for Yices 2 provided, \
411 /// and `RSMT2_YICES_2_CMD` environment variable not set; \
412 /// cannot spawn Yices 2 solver"
413 /// ),
414 /// }
415 ///
416 /// // Retrieves the command from the environment.
417 /// let cmd = "yices_2_implicit";
418 /// assert_eq!(YICES_2_ENV_VAR, "RSMT2_YICES_2_CMD");
419 /// set_var(YICES_2_ENV_VAR, cmd);
420 /// let implicit_cmd = SmtConf::yices_2_or_env(None).expect("implicit");
421 /// assert_eq!(implicit_cmd.get_cmd(), cmd);
422 /// ```
423 #[inline]
424 pub fn yices_2_or_env(cmd: Option<String>) -> SmtRes<Self> {
425 if let Some(cmd) = cmd {
426 Ok(Self::yices_2(cmd))
427 } else {
428 let cmd = SmtStyle::Yices2.env_cmd()?;
429 if let Some(cmd) = cmd {
430 Ok(Self::yices_2(cmd))
431 } else {
432 bail!(
433 "no command for Yices 2 provided, \
434 and `{}` environment variable not set; cannot spawn Yices 2 solver",
435 YICES_2_ENV_VAR,
436 )
437 }
438 }
439 }
440
441 /// Creates a new z3-like solver configuration and command.
442 ///
443 /// # Warning
444 ///
445 /// The command used to run a particular solver is up to the end-user. As such, it **does not
446 /// make sense** to use default commands for anything else than local testing. You should
447 /// explicitely pass the command to use with [`Self::z3`] instead.
448 ///
449 /// # Examples
450 ///
451 /// ```rust
452 /// # use rsmt2::SmtConf;
453 /// let conf = SmtConf::default_z3();
454 /// assert! {
455 /// conf.get_cmd() == "z3" || conf.get_cmd() == "z3.exe"
456 /// }
457 /// ```
458 #[inline]
459 pub fn default_z3() -> Self {
460 Z3.default()
461 }
462
463 /// Creates a new cvc4-like solver configuration and command.
464 ///
465 /// # Warning
466 ///
467 /// The command used to run a particular solver is up to the end-user. As such, it **does not
468 /// make sense** to use default commands for anything else than local testing. You should
469 /// explicitely pass the command to use with [`Self::cvc4`] instead.
470 ///
471 /// # Examples
472 ///
473 /// ```rust
474 /// # use rsmt2::SmtConf;
475 /// let conf = SmtConf::default_cvc4();
476 /// assert! {
477 /// conf.get_cmd() == "cvc4" || conf.get_cmd() == "cvc4.exe"
478 /// }
479 /// ```
480 #[inline]
481 pub fn default_cvc4() -> Self {
482 CVC4.default()
483 }
484
485 /// Creates a new yices-2-like solver configuration and command.
486 ///
487 /// # Warning
488 ///
489 /// The command used to run a particular solver is up to the end-user. As such, it **does not
490 /// make sense** to use default commands for anything else than local testing. You should
491 /// explicitely pass the command to use with [`Self::yices_2`] instead.
492 ///
493 /// # Examples
494 ///
495 /// ```rust
496 /// # use rsmt2::SmtConf;
497 /// let conf = SmtConf::default_yices_2();
498 /// assert! {
499 /// conf.get_cmd() == "yices" || conf.get_cmd() == "yices.exe"
500 /// }
501 /// ```
502 #[inline]
503 pub fn default_yices_2() -> Self {
504 Yices2.default()
505 }
506
507 /// Spawns the solver.
508 ///
509 /// # Examples
510 ///
511 /// ```rust
512 /// # use rsmt2::SmtConf;
513 /// let _solver = SmtConf::default_z3().spawn(()).unwrap();
514 /// ```
515 #[inline]
516 pub fn spawn<Parser>(self, parser: Parser) -> SmtRes<Solver<Parser>> {
517 Solver::new(self, parser)
518 }
519
520 /// Concise description of the underlying solver.
521 ///
522 /// # Examples
523 ///
524 /// ```rust
525 /// # use rsmt2::SmtConf;
526 /// assert_eq! { SmtConf::default_z3().desc(), "z3" }
527 /// ```
528 #[inline]
529 pub fn desc(&self) -> &str {
530 match self.style {
531 Z3 => "z3",
532 CVC4 => "cvc4",
533 Yices2 => "yices2",
534 }
535 }
536
537 /// Solver command.
538 ///
539 /// # Examples
540 ///
541 /// ```rust
542 /// # use rsmt2::SmtConf;
543 /// let conf = SmtConf::default_z3();
544 /// assert! {
545 /// conf.get_cmd() == "z3" || conf.get_cmd() == "z3.exe"
546 /// }
547 /// ```
548 #[inline]
549 pub fn get_cmd(&self) -> &str {
550 &self.cmd
551 }
552
553 /// Options of the configuration.
554 ///
555 /// # Examples
556 ///
557 /// ```rust
558 /// # use rsmt2::SmtConf;
559 /// assert_eq! {
560 /// SmtConf::default_z3().get_options(), & [ "-in", "-smt2" ]
561 /// }
562 /// ```
563 #[inline]
564 pub fn get_options(&self) -> &[String] {
565 &self.options
566 }
567
568 /// Adds an option to the configuration.
569 ///
570 /// # Examples
571 ///
572 /// ```rust
573 /// # use rsmt2::SmtConf;
574 /// let mut conf = SmtConf::default_z3();
575 /// conf.option("arith.euclidean_solver=true");
576 /// assert_eq! {
577 /// conf.get_options(),
578 /// & [ "-in", "-smt2", "arith.euclidean_solver=true" ]
579 /// }
580 /// ```
581 #[inline]
582 pub fn option<S: Into<String>>(&mut self, o: S) -> &mut Self {
583 self.options.push(o.into());
584 self
585 }
586
587 /// Sets the command for the solver.
588 ///
589 /// # Examples
590 ///
591 /// ```rust
592 /// # use rsmt2::SmtConf;
593 /// let mut conf = SmtConf::default_z3();
594 /// conf.cmd("my_custom_z3_command");
595 /// assert_eq! { conf.get_cmd(), "my_custom_z3_command" }
596 /// ```
597 #[inline]
598 pub fn cmd<S: Into<String>>(&mut self, cmd: S) -> &mut Self {
599 let cmd = cmd.into();
600 let mut iter = cmd.split(' ');
601
602 'set_cmd: while let Some(cmd) = iter.next() {
603 if !cmd.is_empty() {
604 self.cmd = cmd.into();
605 break 'set_cmd;
606 }
607 }
608
609 for option in iter {
610 if !option.is_empty() {
611 self.options.push(option.into())
612 }
613 }
614
615 self
616 }
617
618 /// Model production flag.
619 ///
620 /// # Examples
621 ///
622 /// ```rust
623 /// # use rsmt2::SmtConf;
624 /// assert!(SmtConf::default_z3().get_models());
625 /// ```
626 pub fn get_models(&self) -> bool {
627 self.models
628 }
629 /// Activates model production.
630 ///
631 /// # Examples
632 ///
633 /// ```rust
634 /// # use rsmt2::SmtConf;
635 /// let mut conf = SmtConf::default_z3();
636 /// conf.models();
637 /// assert!(conf.get_models());
638 /// ```
639 pub fn models(&mut self) {
640 self.set_models(true)
641 }
642 /// (De)activates model production.
643 ///
644 /// # Examples
645 ///
646 /// ```rust
647 /// # use rsmt2::SmtConf;
648 /// let mut conf = SmtConf::default_z3();
649 /// conf.set_models(false);
650 /// assert!(!conf.get_models());
651 /// ```
652 pub fn set_models(&mut self, val: bool) {
653 self.models = val;
654 if val {
655 match self.style {
656 CVC4 => self.options.push("--produce-models".into()),
657 Yices2 => self.options.push("--smt2-model-format".into()),
658 Z3 => (),
659 }
660 }
661 }
662
663 /// Incrementality.
664 ///
665 /// # Examples
666 ///
667 /// ```rust
668 /// # use rsmt2::SmtConf;
669 /// let mut conf = SmtConf::default_z3();
670 /// assert!(conf.get_incremental());
671 /// ```
672 pub fn get_incremental(&self) -> bool {
673 self.incremental
674 }
675 /// Activates incrementality (push/pop, check-sat-assuming).
676 ///
677 /// # Examples
678 ///
679 /// ```rust
680 /// # use rsmt2::SmtConf;
681 /// let mut conf = SmtConf::default_z3();
682 /// conf.incremental();
683 /// assert!(conf.get_incremental());
684 /// ```
685 pub fn incremental(&mut self) {
686 self.set_incremental(true)
687 }
688 /// Activates incrementality (push/pop, check-sat-assuming).
689 ///
690 /// # Examples
691 ///
692 /// ```rust
693 /// # use rsmt2::SmtConf;
694 /// let mut conf = SmtConf::default_z3();
695 /// conf.incremental();
696 /// assert!(conf.get_incremental());
697 /// ```
698 pub fn set_incremental(&mut self, val: bool) {
699 self.incremental = val;
700 if val {
701 match self.style {
702 CVC4 | Yices2 => self.options.push("--incremental".into()),
703 Z3 => (),
704 }
705 }
706 }
707
708 /// Indicates if unsat core production is active.
709 ///
710 /// # Examples
711 ///
712 /// ```rust
713 /// # use rsmt2::SmtConf;
714 /// assert!(! SmtConf::default_z3().get_unsat_cores());
715 /// ```
716 #[inline]
717 pub fn get_unsat_cores(&self) -> bool {
718 self.unsat_cores
719 }
720 /// Activates unsat core production.
721 ///
722 /// # Examples
723 ///
724 /// ```rust
725 /// # use rsmt2::SmtConf;
726 /// let mut conf = SmtConf::default_z3();
727 /// conf.unsat_cores();
728 /// assert!(conf.get_unsat_cores());
729 /// ```
730 #[inline]
731 pub fn unsat_cores(&mut self) {
732 self.set_unsat_cores(true)
733 }
734 /// (De)activates unsat core production.
735 ///
736 /// # Examples
737 ///
738 /// ```rust
739 /// # use rsmt2::SmtConf;
740 /// let mut conf = SmtConf::default_z3();
741 /// conf.set_unsat_cores(false);
742 /// assert!(!conf.get_unsat_cores());
743 /// ```
744 #[inline]
745 pub fn set_unsat_cores(&mut self, val: bool) {
746 self.unsat_cores = val
747 }
748
749 /// Keyword for check-sat with assumptions.
750 ///
751 /// # Examples
752 ///
753 /// ```rust
754 /// # use rsmt2::SmtConf;
755 /// assert_eq! {
756 /// SmtConf::default_z3().get_check_sat_assuming(), Some("check-sat-assuming")
757 /// }
758 /// ```
759 #[inline]
760 pub fn get_check_sat_assuming(&self) -> ConfItem {
761 self.check_sat_assuming.as_ref().map(|s| *s)
762 }
763
764 /// Indicates if success-checking is active, see [`Solver`](crate::Solver#check-success).
765 ///
766 /// # Examples
767 ///
768 /// ```rust
769 /// # use rsmt2::SmtConf;
770 /// assert!(! SmtConf::default_z3().get_check_success());
771 /// ```
772 #[inline]
773 pub fn get_check_success(&self) -> bool {
774 self.check_success
775 }
776 /// Activates success-checking, see [`Solver`](crate::Solver#check-success).
777 ///
778 /// # Examples
779 ///
780 /// ```rust
781 /// # use rsmt2::SmtConf;
782 /// let mut conf = SmtConf::default_z3();
783 /// conf.check_success();
784 /// assert!(conf.get_check_success());
785 /// ```
786 #[inline]
787 pub fn check_success(&mut self) {
788 self.set_check_success(true)
789 }
790 /// (De)activates sucess-checking, see [`Solver`](crate::Solver#check-success).
791 ///
792 /// # Examples
793 ///
794 /// ```rust
795 /// # use rsmt2::SmtConf;
796 /// let mut conf = SmtConf::default_z3();
797 /// conf.set_check_success(true);
798 /// assert!(conf.get_check_success());
799 /// ```
800 #[inline]
801 pub fn set_check_success(&mut self, val: bool) {
802 self.check_success = val
803 }
804
805 /// Indicates if interpolant production is active.
806 ///
807 /// # Examples
808 ///
809 /// ```rust
810 /// # use rsmt2::SmtConf;
811 /// assert!(SmtConf::default_z3().get_interpolants());
812 /// ```
813 #[inline]
814 pub fn get_interpolants(&self) -> bool {
815 self.interpolants
816 }
817 /// Activates interpolant production.
818 ///
819 /// # Examples
820 ///
821 /// ```rust
822 /// # use rsmt2::SmtConf;
823 /// let mut conf = SmtConf::default_z3();
824 /// conf.interpolants();
825 /// assert!(conf.get_interpolants());
826 /// ```
827 #[inline]
828 pub fn interpolants(&mut self) -> SmtRes<()> {
829 self.set_interpolants(true)
830 }
831 /// (De)activates interpolant production.
832 ///
833 /// # Examples
834 ///
835 /// ```rust
836 /// # use rsmt2::SmtConf;
837 /// let mut conf = SmtConf::default_z3();
838 /// conf.set_interpolants(false);
839 /// assert!(!conf.get_interpolants());
840 /// ```
841 #[inline]
842 pub fn set_interpolants(&mut self, val: bool) -> SmtRes<()> {
843 if self.style.is_z3() {
844 self.interpolants = val;
845 Ok(())
846 } else {
847 bail!(
848 "interpolant production is only supported by Z3, \
849 cannot activate interpolants for `{}`",
850 self.style,
851 )
852 }
853 }
854}
855
856/// ## Solver-specific error-handling
857impl SmtConf {
858 /// Adds information to a `get-value` error message if needed.
859 pub fn enrich_get_values_error(&self, e: crate::errors::Error) -> crate::errors::Error {
860 match self.style {
861 SmtStyle::CVC4 => e.chain_err(|| {
862 "some versions of CVC4 produce errors on `get-value` commands, \
863 consider using `get-model` instead"
864 }),
865 SmtStyle::Z3 | SmtStyle::Yices2 => e,
866 }
867 }
868}