1use crate::{
2 known_atoms::KnownAtoms,
3 sexpr::{Arena, DisplayExpr, SExpr, SExprData},
4 solver::Solver,
5};
6use std::{ffi, io, mem};
7
8macro_rules! variadic {
9 ($name:ident, $op:ident) => {
10 pub fn $name<I: IntoIterator<Item = SExpr>>(&self, items: I) -> SExpr {
11 let mut iter = items.into_iter().peekable();
12 let first = iter.next().expect("At least one argument is expected");
13
14 if iter.peek().is_some() {
15 let args = std::iter::once(self.atoms.$op)
16 .chain(std::iter::once(first))
17 .chain(iter)
18 .collect();
19 self.list(args)
20 } else {
21 first
22 }
23 }
24 };
25}
26
27macro_rules! unary {
28 ($name:ident, $op:ident) => {
29 pub fn $name(&self, val: SExpr) -> SExpr {
30 self.list(vec![self.atoms.$op, val])
31 }
32 };
33}
34
35macro_rules! binop {
36 ($name:ident, $op:ident) => {
37 pub fn $name(&self, lhs: SExpr, rhs: SExpr) -> SExpr {
38 self.list(vec![self.atoms.$op, lhs, rhs])
39 }
40 };
41}
42
43macro_rules! right_assoc {
44 ($name:ident, $many:ident, $op:ident) => {
45 binop!($name, $op);
46 variadic!($many, $op);
47 };
48}
49
50macro_rules! left_assoc {
51 ($name:ident, $many:ident, $op:ident) => {
52 binop!($name, $op);
53 variadic!($many, $op);
54 };
55}
56
57macro_rules! chainable {
58 ($name:ident, $many:ident, $op:ident) => {
59 binop!($name, $op);
60 variadic!($many, $op);
61 };
62}
63
64macro_rules! pairwise {
65 ($name:ident, $many:ident, $op:ident) => {
66 binop!($name, $op);
67 variadic!($many, $op);
68 };
69}
70
71#[derive(Default)]
72pub struct ContextBuilder {
73 solver: Option<ffi::OsString>,
74 solver_args: Vec<ffi::OsString>,
75 replay_file: Option<Box<dyn io::Write + Send>>,
76}
77
78impl ContextBuilder {
79 pub fn new() -> Self {
81 Self::default()
82 }
83
84 pub fn with_z3_defaults(&mut self) -> &mut Self {
86 self.solver("z3").solver_args(["-smt2", "-in", "-v:0"])
87 }
88
89 pub fn with_cvc5_defaults(&mut self) -> &mut Self {
91 self.solver("cvc5").solver_args(["--quiet", "--lang=smt2", "--incremental"])
92 }
93
94 pub fn solver<P>(&mut self, program: P) -> &mut Self
103 where
104 P: Into<ffi::OsString>,
105 {
106 self.solver = Some(program.into());
107 self
108 }
109
110 pub fn solver_args<A>(&mut self, args: A) -> &mut Self
114 where
115 A: IntoIterator,
116 A::Item: Into<ffi::OsString>,
117 {
118 self.solver_args = args.into_iter().map(|a| a.into()).collect();
119 self
120 }
121
122 pub fn without_solver(&mut self) -> &mut Self {
128 self.solver = None;
129 self.solver_args.clear();
130 self
131 }
132
133 pub fn replay_file<W>(&mut self, replay_file: Option<W>) -> &mut Self
143 where
144 W: 'static + io::Write + Send,
145 {
146 self.replay_file = replay_file.map(|w| Box::new(w) as _);
147 self
148 }
149
150 pub fn build(&mut self) -> io::Result<Context> {
152 let arena = Arena::new();
153 let atoms = KnownAtoms::new(&arena);
154
155 let solver = if let Some(program) = self.solver.take() {
156 Some(Solver::new(
157 program,
158 mem::take(&mut self.solver_args),
159 self.replay_file
160 .take()
161 .unwrap_or_else(|| Box::new(io::sink())),
162 )?)
163 } else {
164 None
165 };
166
167 let mut ctx = Context {
168 solver,
169 arena,
170 atoms,
171 };
172
173 if ctx.solver.is_some() {
174 ctx.set_option(":print-success", ctx.true_())?;
175 ctx.set_option(":produce-models", ctx.true_())?;
176 }
177
178 Ok(ctx)
179 }
180}
181
182pub struct Context {
186 solver: Option<Solver>,
187 arena: Arena,
188 atoms: KnownAtoms,
189}
190
191impl Context {
203 pub fn set_option<K>(&mut self, name: K, value: SExpr) -> io::Result<()>
204 where
205 K: Into<String> + AsRef<str>,
206 {
207 let solver = self
208 .solver
209 .as_mut()
210 .expect("set_option requires a running solver");
211 solver.ack_command(
212 &self.arena,
213 self.atoms.success,
214 self.arena
215 .list(vec![self.atoms.set_option, self.arena.atom(name), value]),
216 )
217 }
218
219 pub fn check_assuming(
221 &mut self,
222 props: impl IntoIterator<Item = SExpr>,
223 ) -> io::Result<Response> {
224 let solver = self
225 .solver
226 .as_mut()
227 .expect("check requires a running solver");
228 let args = self.arena.list(props.into_iter().collect());
229 solver.send(
230 &self.arena,
231 self.arena.list(vec![self.atoms.check_sat_assuming, args]),
232 )?;
233 let resp = solver.recv(&self.arena)?;
234 if resp == self.atoms.sat {
235 Ok(Response::Sat)
236 } else if resp == self.atoms.unsat {
237 Ok(Response::Unsat)
238 } else if resp == self.atoms.unknown {
239 Ok(Response::Unknown)
240 } else {
241 Err(io::Error::new(
242 io::ErrorKind::Other,
243 format!("Unexpected result from solver: {}", self.display(resp)),
244 ))
245 }
246 }
247
248 pub fn check(&mut self) -> io::Result<Response> {
250 let solver = self
251 .solver
252 .as_mut()
253 .expect("check requires a running solver");
254 solver.send(&self.arena, self.arena.list(vec![self.atoms.check_sat]))?;
255 let resp = solver.recv(&self.arena)?;
256 if resp == self.atoms.sat {
257 Ok(Response::Sat)
258 } else if resp == self.atoms.unsat {
259 Ok(Response::Unsat)
260 } else if resp == self.atoms.unknown {
261 Ok(Response::Unknown)
262 } else {
263 Err(io::Error::new(
264 io::ErrorKind::Other,
265 format!("Unexpected result from solver: {}", self.display(resp)),
266 ))
267 }
268 }
269
270 pub fn declare_const<S: Into<String> + AsRef<str>>(
272 &mut self,
273 name: S,
274 sort: SExpr,
275 ) -> io::Result<SExpr> {
276 let name = self.atom(name);
277 let solver = self
278 .solver
279 .as_mut()
280 .expect("declare_const requires a running solver");
281 solver.ack_command(
282 &self.arena,
283 self.atoms.success,
284 self.arena.list(vec![self.atoms.declare_const, name, sort]),
285 )?;
286 Ok(name)
287 }
288
289 pub fn declare_datatype<S: Into<String> + AsRef<str>>(
290 &mut self,
291 name: S,
292 decl: SExpr,
293 ) -> io::Result<SExpr> {
294 let name = self.atom(name);
295 let solver = self
296 .solver
297 .as_mut()
298 .expect("declare_datatype requires a running solver");
299 solver.ack_command(
300 &self.arena,
301 self.atoms.success,
302 self.arena
303 .list(vec![self.atoms.declare_datatype, name, decl]),
304 )?;
305 Ok(name)
306 }
307
308 pub fn declare_datatypes<N, S, D>(&mut self, sorts: S, decls: D) -> io::Result<()>
309 where
310 N: Into<String> + AsRef<str>,
311 S: IntoIterator<Item = (N, i32)>,
312 D: IntoIterator<Item = SExpr>,
313 {
314 let sorts = sorts
315 .into_iter()
316 .map(|(n, i)| self.list(vec![self.atom(n), self.numeral(i)]))
317 .collect();
318 let decls = decls.into_iter().collect();
319
320 let solver = self
321 .solver
322 .as_mut()
323 .expect("declare_datatype requires a running solver");
324 solver.ack_command(
325 &self.arena,
326 self.atoms.success,
327 self.arena.list(vec![
328 self.atoms.declare_datatypes,
329 self.arena.list(sorts),
330 self.arena.list(decls),
331 ]),
332 )
333 }
334
335 pub fn declare_fun<S: Into<String> + AsRef<str>>(
337 &mut self,
338 name: S,
339 args: Vec<SExpr>,
340 out: SExpr,
341 ) -> io::Result<SExpr> {
342 let name = self.atom(name);
343 let solver = self
344 .solver
345 .as_mut()
346 .expect("declare_fun requires a running solver");
347 solver.ack_command(
348 &self.arena,
349 self.atoms.success,
350 self.arena.list(vec![
351 self.atoms.declare_fun,
352 name,
353 self.arena.list(args),
354 out,
355 ]),
356 )?;
357 Ok(name)
358 }
359
360 pub fn define_fun<S: Into<String> + AsRef<str>>(
362 &mut self,
363 name: S,
364 args: Vec<(S, SExpr)>,
365 out: SExpr,
366 body: SExpr,
367 ) -> io::Result<SExpr> {
368 let name = self.atom(name);
369 let args = args
370 .into_iter()
371 .map(|(n, s)| self.list(vec![self.atom(n), s]))
372 .collect();
373 let solver = self
374 .solver
375 .as_mut()
376 .expect("define_fun requires a running solver");
377 solver.ack_command(
378 &self.arena,
379 self.atoms.success,
380 self.arena.list(vec![
381 self.atoms.define_fun,
382 name,
383 self.arena.list(args),
384 out,
385 body,
386 ]),
387 )?;
388 Ok(name)
389 }
390
391 pub fn define_const<S: Into<String> + AsRef<str>>(
395 &mut self,
396 name: S,
397 out: SExpr,
398 body: SExpr,
399 ) -> io::Result<SExpr> {
400 self.define_fun(name, vec![], out, body)
401 }
402
403 pub fn declare_sort<S: Into<String> + AsRef<str>>(
404 &mut self,
405 symbol: S,
406 arity: i32,
407 ) -> io::Result<SExpr> {
408 let symbol = self.atom(symbol);
409 let arity = self.numeral(arity);
410 let solver = self
411 .solver
412 .as_mut()
413 .expect("declare_sort requires a running solver");
414 solver.ack_command(
415 &self.arena,
416 self.atoms.success,
417 self.arena
418 .list(vec![self.atoms.declare_sort, symbol, arity]),
419 )?;
420 Ok(symbol)
421 }
422
423 pub fn assert(&mut self, expr: SExpr) -> io::Result<()> {
424 let solver = self
425 .solver
426 .as_mut()
427 .expect("assert requires a running solver");
428 solver.ack_command(
429 &self.arena,
430 self.atoms.success,
431 self.arena.list(vec![self.atoms.assert, expr]),
432 )
433 }
434
435 pub fn get_model(&mut self) -> io::Result<SExpr> {
437 let solver = self
438 .solver
439 .as_mut()
440 .expect("get_model requires a running solver");
441 solver.send(&self.arena, self.arena.list(vec![self.atoms.get_model]))?;
442 solver.recv(&self.arena)
443 }
444
445 pub fn get_value(&mut self, vals: Vec<SExpr>) -> io::Result<Vec<(SExpr, SExpr)>> {
447 if vals.is_empty() {
448 return Ok(vec![]);
449 }
450
451 let solver = self
452 .solver
453 .as_mut()
454 .expect("get_value requires a running solver");
455 solver.send(
456 &self.arena,
457 self.arena
458 .list(vec![self.atoms.get_value, self.arena.list(vals)]),
459 )?;
460
461 let resp = solver.recv(&self.arena)?;
462 match self.arena.get(resp) {
463 SExprData::List(pairs) => {
464 let mut res = Vec::with_capacity(pairs.len());
465 for expr in pairs {
466 match self.arena.get(*expr) {
467 SExprData::List(pair) => {
468 assert_eq!(2, pair.len());
469 res.push((pair[0], pair[1]));
470 }
471 _ => unreachable!(),
472 }
473 }
474 Ok(res)
475 }
476
477 _ => Err(io::Error::new(
478 io::ErrorKind::Other,
479 "Failed to parse solver output",
480 )),
481 }
482 }
483
484 pub fn get_unsat_core(&mut self) -> io::Result<SExpr> {
486 let solver = self
487 .solver
488 .as_mut()
489 .expect("get_unsat_core requires a running solver");
490 solver.send(
491 &self.arena,
492 self.arena.list(vec![self.atoms.get_unsat_core]),
493 )?;
494 solver.recv(&self.arena)
495 }
496
497 pub fn set_logic<L: Into<String> + AsRef<str>>(&mut self, logic: L) -> io::Result<()> {
498 let solver = self
499 .solver
500 .as_mut()
501 .expect("set_logic requires a running solver");
502 solver.ack_command(
503 &self.arena,
504 self.atoms.success,
505 self.arena
506 .list(vec![self.atoms.set_logic, self.arena.atom(logic)]),
507 )
508 }
509
510 pub fn exit(&mut self) -> io::Result<()> {
512 let solver = self
513 .solver
514 .as_mut()
515 .expect("exit requires a running solver");
516 solver.ack_command(
517 &self.arena,
518 self.atoms.success,
519 self.arena.list(vec![self.atoms.exit]),
520 )
521 }
522
523 pub fn push(&mut self) -> io::Result<()> {
525 let solver = self
526 .solver
527 .as_mut()
528 .expect("push requires a running solver");
529 solver.ack_command(
530 &self.arena,
531 self.atoms.success,
532 self.arena.list(vec![self.atoms.push]),
533 )
534 }
535
536 pub fn push_many(&mut self, n: usize) -> io::Result<()> {
537 let solver = self
538 .solver
539 .as_mut()
540 .expect("push_many requires a running solver");
541 solver.ack_command(
542 &self.arena,
543 self.atoms.success,
544 self.arena
545 .list(vec![self.atoms.push, self.arena.atom(n.to_string())]),
546 )
547 }
548
549 pub fn pop(&mut self) -> io::Result<()> {
551 let solver = self.solver.as_mut().expect("pop requires a running solver");
552 solver.ack_command(
553 &self.arena,
554 self.atoms.success,
555 self.arena.list(vec![self.atoms.pop]),
556 )
557 }
558
559 pub fn pop_many(&mut self, n: usize) -> io::Result<()> {
560 let solver = self
561 .solver
562 .as_mut()
563 .expect("pop_many requires a running solver");
564 solver.ack_command(
565 &self.arena,
566 self.atoms.success,
567 self.arena
568 .list(vec![self.atoms.pop, self.arena.atom(n.to_string())]),
569 )
570 }
571
572 pub fn raw_send(&mut self, cmd: SExpr) -> io::Result<()> {
587 let solver = self
588 .solver
589 .as_mut()
590 .expect("send requires a running solver");
591 solver.send(&self.arena, cmd)
592 }
593
594 pub fn raw_recv(&mut self) -> io::Result<SExpr> {
609 let solver = self
610 .solver
611 .as_mut()
612 .expect("recv requires a running solver");
613 solver.recv(&self.arena)
614 }
615}
616
617impl Context {
623 pub fn atom(&self, name: impl Into<String> + AsRef<str>) -> SExpr {
625 self.arena.atom(name)
626 }
627
628 pub fn list(&self, list: Vec<SExpr>) -> SExpr {
630 self.arena.list(list)
631 }
632
633 pub fn numeral(&self, val: impl IntoNumeral) -> SExpr {
635 self.arena.atom(val.to_string())
636 }
637
638 pub fn decimal(&self, val: impl IntoDecimal) -> SExpr {
640 self.arena.atom(val.to_string())
641 }
642
643 pub fn binary(&self, bit_width: usize, val: impl IntoBinary) -> SExpr {
645 let val = format!("#b{val:0>bit_width$b}");
646 self.arena.atom(val)
647 }
648
649 pub fn display(&self, expr: SExpr) -> DisplayExpr {
658 self.arena.display(expr)
659 }
660
661 pub fn get(&self, expr: SExpr) -> SExprData {
669 self.arena.get(expr)
670 }
671
672 pub fn get_atom(&self, expr: SExpr) -> Option<&str> {
681 self.arena.get_atom(expr)
682 }
683
684 pub fn get_str(&self, expr: SExpr) -> Option<&str> {
693 self.arena.get_str(expr)
694 }
695
696 pub fn get_list(&self, expr: SExpr) -> Option<&[SExpr]> {
705 self.arena.get_list(expr)
706 }
707
708 pub fn get_u8(&self, expr: SExpr) -> Option<u8> {
717 self.arena.get_i(expr)
718 }
719
720 pub fn get_u16(&self, expr: SExpr) -> Option<u16> {
729 self.arena.get_i(expr)
730 }
731
732 pub fn get_u32(&self, expr: SExpr) -> Option<u32> {
741 self.arena.get_i(expr)
742 }
743
744 pub fn get_u64(&self, expr: SExpr) -> Option<u64> {
753 self.arena.get_i(expr)
754 }
755
756 pub fn get_u128(&self, expr: SExpr) -> Option<u128> {
765 self.arena.get_i(expr)
766 }
767
768 pub fn get_usize(&self, expr: SExpr) -> Option<usize> {
777 self.arena.get_i(expr)
778 }
779
780 pub fn get_i8(&self, expr: SExpr) -> Option<i8> {
789 self.arena.get_i(expr)
790 }
791
792 pub fn get_i16(&self, expr: SExpr) -> Option<i16> {
801 self.arena.get_i(expr)
802 }
803
804 pub fn get_i32(&self, expr: SExpr) -> Option<i32> {
813 self.arena.get_i(expr)
814 }
815
816 pub fn get_i64(&self, expr: SExpr) -> Option<i64> {
825 self.arena.get_i(expr)
826 }
827
828 pub fn get_i128(&self, expr: SExpr) -> Option<i128> {
837 self.arena.get_i(expr)
838 }
839
840 pub fn get_isize(&self, expr: SExpr) -> Option<isize> {
849 self.arena.get_i(expr)
850 }
851
852 pub fn get_f32(&self, expr: SExpr) -> Option<f32> {
861 self.arena.get_f(expr)
862 }
863
864 pub fn get_f64(&self, expr: SExpr) -> Option<f64> {
872 self.arena.get_f(expr)
873 }
874
875 pub fn atoms(&self) -> &KnownAtoms {
880 &self.atoms
881 }
882}
883
884impl Context {
888 pub fn par<N, S, D>(&self, symbols: S, decls: D) -> SExpr
889 where
890 N: Into<String> + AsRef<str>,
891 S: IntoIterator<Item = N>,
892 D: IntoIterator<Item = SExpr>,
893 {
894 self.list(vec![
895 self.atoms.par,
896 self.list(symbols.into_iter().map(|n| self.atom(n)).collect()),
897 self.list(decls.into_iter().collect()),
898 ])
899 }
900
901 pub fn attr(&self, expr: SExpr, name: impl Into<String> + AsRef<str>, val: SExpr) -> SExpr {
902 self.list(vec![self.atoms.bang, expr, self.atom(name), val])
903 }
904
905 pub fn named(&self, name: impl Into<String> + AsRef<str>, expr: SExpr) -> SExpr {
906 self.attr(expr, ":named", self.atom(name))
907 }
908
909 pub fn let_<N: Into<String> + AsRef<str>>(&self, name: N, e: SExpr, body: SExpr) -> SExpr {
911 self.list(vec![
912 self.atoms.let_,
913 self.list(vec![self.list(vec![self.atom(name), e])]),
914 body,
915 ])
916 }
917
918 pub fn let_many<N, I>(&self, bindings: I, body: SExpr) -> SExpr
920 where
921 I: IntoIterator<Item = (N, SExpr)>,
922 N: Into<String> + AsRef<str>,
923 {
924 self.list(vec![
925 self.atoms.let_,
926 self.list(Vec::from_iter(
927 bindings
928 .into_iter()
929 .map(|(n, v)| self.list(vec![self.atom(n), v])),
930 )),
931 body,
932 ])
933 }
934
935 pub fn forall<N, I>(&self, vars: I, body: SExpr) -> SExpr
937 where
938 I: IntoIterator<Item = (N, SExpr)>,
939 N: Into<String> + AsRef<str>,
940 {
941 let vars_iter = vars
942 .into_iter()
943 .map(|(n, s)| self.list(vec![self.atom(n), s]));
944 self.list(vec![
945 self.atoms.forall,
946 self.list(vars_iter.collect()),
947 body,
948 ])
949 }
950
951 pub fn exists<N, I>(&self, vars: I, body: SExpr) -> SExpr
953 where
954 I: IntoIterator<Item = (N, SExpr)>,
955 N: Into<String> + AsRef<str>,
956 {
957 let vars_iter = vars
958 .into_iter()
959 .map(|(n, s)| self.list(vec![self.atom(n), s]));
960 self.list(vec![
961 self.atoms.exists,
962 self.list(vars_iter.collect()),
963 body,
964 ])
965 }
966
967 pub fn match_<I: IntoIterator<Item = (SExpr, SExpr)>>(&self, term: SExpr, arms: I) -> SExpr {
969 let args: Vec<_> = std::iter::once(self.atoms.match_)
970 .chain(std::iter::once(term))
971 .chain(arms.into_iter().map(|(p, v)| self.list(vec![p, v])))
972 .collect();
973 assert!(args.len() >= 3);
974 self.list(args)
975 }
976
977 pub fn ite(&self, c: SExpr, t: SExpr, e: SExpr) -> SExpr {
979 self.list(vec![self.atoms.ite, c, t, e])
980 }
981}
982
983impl Context {
987 pub fn bool_sort(&self) -> SExpr {
989 self.atoms.bool
990 }
991
992 pub fn true_(&self) -> SExpr {
994 self.atoms.t
995 }
996
997 pub fn false_(&self) -> SExpr {
999 self.atoms.f
1000 }
1001
1002 unary!(not, not);
1003 right_assoc!(imp, imp_many, imp);
1004 left_assoc!(and, and_many, and);
1005 left_assoc!(or, or_many, or);
1006 left_assoc!(xor, xor_many, xor);
1007 chainable!(eq, eq_many, eq);
1008 pairwise!(distinct, distinct_many, distinct);
1009}
1010
1011impl Context {
1015 pub fn int_sort(&self) -> SExpr {
1017 self.atoms.int
1018 }
1019
1020 unary!(negate, minus);
1021 left_assoc!(sub, sub_many, minus);
1022 left_assoc!(plus, plus_many, plus);
1023 left_assoc!(times, times_many, times);
1024 left_assoc!(div, div_many, div);
1025 left_assoc!(modulo, modulo_many, modulo);
1026 left_assoc!(rem, rem_many, rem);
1027 chainable!(lte, lte_many, lte);
1028 chainable!(lt, lt_many, lt);
1029 chainable!(gt, gt_many, gt);
1030 chainable!(gte, gte_many, gte);
1031}
1032
1033impl Context {
1037 pub fn real_sort(&self) -> SExpr {
1039 self.atoms.real
1040 }
1041
1042 left_assoc!(rdiv, rdiv_many, slash);
1043 unary!(conv_to_real, to_real);
1044}
1045
1046impl Context {
1050 pub fn array_sort(&self, index: SExpr, element: SExpr) -> SExpr {
1052 self.list(vec![self.atoms.array, index, element])
1053 }
1054
1055 pub fn select(&self, ary: SExpr, index: SExpr) -> SExpr {
1057 self.list(vec![self.atoms.select, ary, index])
1058 }
1059
1060 pub fn store(&self, ary: SExpr, index: SExpr, value: SExpr) -> SExpr {
1062 self.list(vec![self.atoms.store, ary, index, value])
1063 }
1064}
1065
1066impl Context {
1071 pub fn bit_vec_sort(&self, width: SExpr) -> SExpr {
1073 self.list(vec![self.atoms.und, self.atoms.bit_vec, width])
1074 }
1075
1076 pub fn concat(&self, lhs: SExpr, rhs: SExpr) -> SExpr {
1078 self.list(vec![self.atoms.concat, lhs, rhs])
1079 }
1080
1081 pub fn extract(&self, i: i32, j: i32, bv: SExpr) -> SExpr {
1083 self.list(vec![
1084 self.list(vec![
1085 self.atoms.und,
1086 self.atoms.extract,
1087 self.numeral(i),
1088 self.numeral(j),
1089 ]),
1090 bv,
1091 ])
1092 }
1093
1094 unary!(bvnot, bvnot);
1095 left_assoc!(bvor, bvor_many, bvor);
1096 left_assoc!(bvand, bvand_many, bvand);
1097 left_assoc!(bvnand, bvnand_many, bvnand);
1098 left_assoc!(bvxor, bvxor_many, bvxor);
1099 left_assoc!(bvxnor, bvxnor_many, bvxnor);
1100 unary!(bvneg, bvneg);
1101 left_assoc!(bvadd, bvadd_many, bvadd);
1102 binop!(bvsub, bvsub);
1103 left_assoc!(bvmul, bvmul_many, bvmul);
1104 binop!(bvudiv, bvudiv);
1105 binop!(bvurem, bvurem);
1106 binop!(bvsdiv, bvsdiv);
1107 binop!(bvsrem, bvsrem);
1108 binop!(bvsmod, bvsmod);
1109 binop!(bvshl, bvshl);
1110 binop!(bvlshr, bvlshr);
1111 binop!(bvashr, bvashr);
1112 binop!(bvule, bvule);
1113 binop!(bvult, bvult);
1114 binop!(bvuge, bvuge);
1115 binop!(bvugt, bvugt);
1116 binop!(bvsle, bvsle);
1117 binop!(bvslt, bvslt);
1118 binop!(bvsge, bvsge);
1119 binop!(bvsgt, bvsgt);
1120 binop!(bvcomp, bvcomp);
1121}
1122
1123#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1124pub enum Response {
1125 Sat,
1126 Unsat,
1127 Unknown,
1128}
1129
1130mod private {
1131 pub trait IntoNumeral: IntoNumeralSealed {}
1133 pub trait IntoNumeralSealed: std::fmt::Display {}
1134
1135 pub trait IntoBinary: IntoBinarySealed {}
1137 pub trait IntoBinarySealed: std::fmt::Binary {}
1138
1139 impl IntoNumeralSealed for i8 {}
1140 impl IntoNumeral for i8 {}
1141 impl IntoBinarySealed for i8 {}
1142 impl IntoBinary for i8 {}
1143 impl IntoNumeralSealed for i16 {}
1144 impl IntoNumeral for i16 {}
1145 impl IntoBinarySealed for i16 {}
1146 impl IntoBinary for i16 {}
1147 impl IntoNumeralSealed for i32 {}
1148 impl IntoNumeral for i32 {}
1149 impl IntoBinarySealed for i32 {}
1150 impl IntoBinary for i32 {}
1151 impl IntoNumeralSealed for i64 {}
1152 impl IntoNumeral for i64 {}
1153 impl IntoBinarySealed for i64 {}
1154 impl IntoBinary for i64 {}
1155 impl IntoNumeralSealed for i128 {}
1156 impl IntoNumeral for i128 {}
1157 impl IntoBinarySealed for i128 {}
1158 impl IntoBinary for i128 {}
1159 impl IntoNumeralSealed for isize {}
1160 impl IntoNumeral for isize {}
1161 impl IntoBinarySealed for isize {}
1162 impl IntoBinary for isize {}
1163 impl IntoNumeralSealed for u8 {}
1164 impl IntoNumeral for u8 {}
1165 impl IntoBinarySealed for u8 {}
1166 impl IntoBinary for u8 {}
1167 impl IntoNumeralSealed for u16 {}
1168 impl IntoNumeral for u16 {}
1169 impl IntoBinarySealed for u16 {}
1170 impl IntoBinary for u16 {}
1171 impl IntoNumeralSealed for u32 {}
1172 impl IntoNumeral for u32 {}
1173 impl IntoBinarySealed for u32 {}
1174 impl IntoBinary for u32 {}
1175 impl IntoNumeralSealed for u64 {}
1176 impl IntoNumeral for u64 {}
1177 impl IntoBinarySealed for u64 {}
1178 impl IntoBinary for u64 {}
1179 impl IntoNumeralSealed for u128 {}
1180 impl IntoNumeral for u128 {}
1181 impl IntoBinarySealed for u128 {}
1182 impl IntoBinary for u128 {}
1183 impl IntoNumeralSealed for usize {}
1184 impl IntoNumeral for usize {}
1185 impl IntoBinarySealed for usize {}
1186 impl IntoBinary for usize {}
1187
1188 pub trait IntoDecimal: IntoDecimalSealed {}
1190 pub trait IntoDecimalSealed: std::fmt::Display {}
1191
1192 impl IntoDecimal for f32 {}
1193 impl IntoDecimalSealed for f32 {}
1194 impl IntoDecimal for f64 {}
1195 impl IntoDecimalSealed for f64 {}
1196}
1197pub use private::{IntoBinary, IntoDecimal, IntoNumeral};
1198
1199#[cfg(test)]
1200mod tests {
1201 use super::*;
1202
1203 macro_rules! check_expr {
1204 ($ctx:expr, $expr:expr, $expected:expr) => {
1205 let actual = $ctx.display($expr).to_string();
1206 assert_eq!(actual, $expected);
1207 };
1208 }
1209
1210 #[test]
1211 fn test_variadic_ops() {
1212 let ctx = ContextBuilder::new().build().unwrap();
1213
1214 check_expr!(ctx, ctx.imp_many([ctx.true_()]), "true");
1217 check_expr!(
1218 ctx,
1219 ctx.imp_many([ctx.true_(), ctx.false_()]),
1220 "(=> true false)"
1221 );
1222 }
1223
1224 #[cfg(debug_assertions)]
1225 #[test]
1226 #[should_panic]
1227 fn sexpr_with_wrong_context() {
1228 let ctx1 = ContextBuilder::new().build().unwrap();
1229 let ctx2 = ContextBuilder::new().build().unwrap();
1230
1231 let pizza1 = ctx1.atom("pizza");
1232 let _pizza2 = ctx2.atom("pizza");
1233
1234 let _ = ctx2.get(pizza1);
1236 }
1237}