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 solver<P>(&mut self, program: P) -> &mut Self
93 where
94 P: Into<ffi::OsString>,
95 {
96 self.solver = Some(program.into());
97 self
98 }
99
100 pub fn solver_args<A>(&mut self, args: A) -> &mut Self
104 where
105 A: IntoIterator,
106 A::Item: Into<ffi::OsString>,
107 {
108 self.solver_args = args.into_iter().map(|a| a.into()).collect();
109 self
110 }
111
112 pub fn without_solver(&mut self) -> &mut Self {
118 self.solver = None;
119 self.solver_args.clear();
120 self
121 }
122
123 pub fn replay_file<W>(&mut self, replay_file: Option<W>) -> &mut Self
133 where
134 W: 'static + io::Write + Send,
135 {
136 self.replay_file = replay_file.map(|w| Box::new(w) as _);
137 self
138 }
139
140 pub fn build(&mut self) -> io::Result<Context> {
142 let arena = Arena::new();
143 let atoms = KnownAtoms::new(&arena);
144
145 let solver = if let Some(program) = self.solver.take() {
146 Some(Solver::new(
147 program,
148 mem::take(&mut self.solver_args),
149 self.replay_file
150 .take()
151 .unwrap_or_else(|| Box::new(io::sink())),
152 )?)
153 } else {
154 None
155 };
156
157 let mut ctx = Context {
158 solver,
159 arena,
160 atoms,
161 };
162
163 if ctx.solver.is_some() {
164 ctx.set_option(":print-success", ctx.true_())?;
165 ctx.set_option(":produce-models", ctx.true_())?;
166 }
167
168 Ok(ctx)
169 }
170}
171
172pub struct Context {
176 solver: Option<Solver>,
177 arena: Arena,
178 atoms: KnownAtoms,
179}
180
181impl Context {
193 pub fn set_option<K>(&mut self, name: K, value: SExpr) -> io::Result<()>
194 where
195 K: Into<String> + AsRef<str>,
196 {
197 let solver = self
198 .solver
199 .as_mut()
200 .expect("set_option requires a running solver");
201 solver.ack_command(
202 &self.arena,
203 self.atoms.success,
204 self.arena
205 .list(vec![self.atoms.set_option, self.arena.atom(name), value]),
206 )
207 }
208
209 pub fn check_assuming(
211 &mut self,
212 props: impl IntoIterator<Item = SExpr>,
213 ) -> io::Result<Response> {
214 let solver = self
215 .solver
216 .as_mut()
217 .expect("check requires a running solver");
218 let args = self.arena.list(props.into_iter().collect());
219 solver.send(
220 &self.arena,
221 self.arena.list(vec![self.atoms.check_sat_assuming, args]),
222 )?;
223 let resp = solver.recv(&self.arena)?;
224 if resp == self.atoms.sat {
225 Ok(Response::Sat)
226 } else if resp == self.atoms.unsat {
227 Ok(Response::Unsat)
228 } else if resp == self.atoms.unknown {
229 Ok(Response::Unknown)
230 } else {
231 Err(io::Error::new(
232 io::ErrorKind::Other,
233 format!("Unexpected result from solver: {}", self.display(resp)),
234 ))
235 }
236 }
237
238 pub fn check(&mut self) -> io::Result<Response> {
240 let solver = self
241 .solver
242 .as_mut()
243 .expect("check requires a running solver");
244 solver.send(&self.arena, self.arena.list(vec![self.atoms.check_sat]))?;
245 let resp = solver.recv(&self.arena)?;
246 if resp == self.atoms.sat {
247 Ok(Response::Sat)
248 } else if resp == self.atoms.unsat {
249 Ok(Response::Unsat)
250 } else if resp == self.atoms.unknown {
251 Ok(Response::Unknown)
252 } else {
253 Err(io::Error::new(
254 io::ErrorKind::Other,
255 format!("Unexpected result from solver: {}", self.display(resp)),
256 ))
257 }
258 }
259
260 pub fn declare_const<S: Into<String> + AsRef<str>>(
262 &mut self,
263 name: S,
264 sort: SExpr,
265 ) -> io::Result<SExpr> {
266 let name = self.atom(name);
267 let solver = self
268 .solver
269 .as_mut()
270 .expect("declare_const requires a running solver");
271 solver.ack_command(
272 &self.arena,
273 self.atoms.success,
274 self.arena.list(vec![self.atoms.declare_const, name, sort]),
275 )?;
276 Ok(name)
277 }
278
279 pub fn declare_datatype<S: Into<String> + AsRef<str>>(
280 &mut self,
281 name: S,
282 decl: SExpr,
283 ) -> io::Result<SExpr> {
284 let name = self.atom(name);
285 let solver = self
286 .solver
287 .as_mut()
288 .expect("declare_datatype requires a running solver");
289 solver.ack_command(
290 &self.arena,
291 self.atoms.success,
292 self.arena
293 .list(vec![self.atoms.declare_datatype, name, decl]),
294 )?;
295 Ok(name)
296 }
297
298 pub fn declare_datatypes<N, S, D>(&mut self, sorts: S, decls: D) -> io::Result<()>
299 where
300 N: Into<String> + AsRef<str>,
301 S: IntoIterator<Item = (N, i32)>,
302 D: IntoIterator<Item = SExpr>,
303 {
304 let sorts = sorts
305 .into_iter()
306 .map(|(n, i)| self.list(vec![self.atom(n), self.numeral(i)]))
307 .collect();
308 let decls = decls.into_iter().collect();
309
310 let solver = self
311 .solver
312 .as_mut()
313 .expect("declare_datatype requires a running solver");
314 solver.ack_command(
315 &self.arena,
316 self.atoms.success,
317 self.arena.list(vec![
318 self.atoms.declare_datatypes,
319 self.arena.list(sorts),
320 self.arena.list(decls),
321 ]),
322 )
323 }
324
325 pub fn declare_fun<S: Into<String> + AsRef<str>>(
327 &mut self,
328 name: S,
329 args: Vec<SExpr>,
330 out: SExpr,
331 ) -> io::Result<SExpr> {
332 let name = self.atom(name);
333 let solver = self
334 .solver
335 .as_mut()
336 .expect("declare_fun requires a running solver");
337 solver.ack_command(
338 &self.arena,
339 self.atoms.success,
340 self.arena.list(vec![
341 self.atoms.declare_fun,
342 name,
343 self.arena.list(args),
344 out,
345 ]),
346 )?;
347 Ok(name)
348 }
349
350 pub fn define_fun<S: Into<String> + AsRef<str>>(
352 &mut self,
353 name: S,
354 args: Vec<(S, SExpr)>,
355 out: SExpr,
356 body: SExpr,
357 ) -> io::Result<SExpr> {
358 let name = self.atom(name);
359 let args = args
360 .into_iter()
361 .map(|(n, s)| self.list(vec![self.atom(n), s]))
362 .collect();
363 let solver = self
364 .solver
365 .as_mut()
366 .expect("define_fun requires a running solver");
367 solver.ack_command(
368 &self.arena,
369 self.atoms.success,
370 self.arena.list(vec![
371 self.atoms.define_fun,
372 name,
373 self.arena.list(args),
374 out,
375 body,
376 ]),
377 )?;
378 Ok(name)
379 }
380
381 pub fn define_const<S: Into<String> + AsRef<str>>(
385 &mut self,
386 name: S,
387 out: SExpr,
388 body: SExpr,
389 ) -> io::Result<SExpr> {
390 self.define_fun(name, vec![], out, body)
391 }
392
393 pub fn declare_sort<S: Into<String> + AsRef<str>>(
394 &mut self,
395 symbol: S,
396 arity: i32,
397 ) -> io::Result<SExpr> {
398 let symbol = self.atom(symbol);
399 let arity = self.numeral(arity);
400 let solver = self
401 .solver
402 .as_mut()
403 .expect("declare_sort requires a running solver");
404 solver.ack_command(
405 &self.arena,
406 self.atoms.success,
407 self.arena
408 .list(vec![self.atoms.declare_sort, symbol, arity]),
409 )?;
410 Ok(symbol)
411 }
412
413 pub fn assert(&mut self, expr: SExpr) -> io::Result<()> {
414 let solver = self
415 .solver
416 .as_mut()
417 .expect("assert requires a running solver");
418 solver.ack_command(
419 &self.arena,
420 self.atoms.success,
421 self.arena.list(vec![self.atoms.assert, expr]),
422 )
423 }
424
425 pub fn get_model(&mut self) -> io::Result<SExpr> {
427 let solver = self
428 .solver
429 .as_mut()
430 .expect("get_model requires a running solver");
431 solver.send(&self.arena, self.arena.list(vec![self.atoms.get_model]))?;
432 solver.recv(&self.arena)
433 }
434
435 pub fn get_value(&mut self, vals: Vec<SExpr>) -> io::Result<Vec<(SExpr, SExpr)>> {
437 if vals.is_empty() {
438 return Ok(vec![]);
439 }
440
441 let solver = self
442 .solver
443 .as_mut()
444 .expect("get_value requires a running solver");
445 solver.send(
446 &self.arena,
447 self.arena
448 .list(vec![self.atoms.get_value, self.arena.list(vals)]),
449 )?;
450
451 let resp = solver.recv(&self.arena)?;
452 match self.arena.get(resp) {
453 SExprData::List(pairs) => {
454 let mut res = Vec::with_capacity(pairs.len());
455 for expr in pairs {
456 match self.arena.get(*expr) {
457 SExprData::List(pair) => {
458 assert_eq!(2, pair.len());
459 res.push((pair[0], pair[1]));
460 }
461 _ => unreachable!(),
462 }
463 }
464 Ok(res)
465 }
466
467 _ => Err(io::Error::new(
468 io::ErrorKind::Other,
469 "Failed to parse solver output",
470 )),
471 }
472 }
473
474 pub fn get_unsat_core(&mut self) -> io::Result<SExpr> {
476 let solver = self
477 .solver
478 .as_mut()
479 .expect("get_unsat_core requires a running solver");
480 solver.send(
481 &self.arena,
482 self.arena.list(vec![self.atoms.get_unsat_core]),
483 )?;
484 solver.recv(&self.arena)
485 }
486
487 pub fn set_logic<L: Into<String> + AsRef<str>>(&mut self, logic: L) -> io::Result<()> {
488 let solver = self
489 .solver
490 .as_mut()
491 .expect("set_logic requires a running solver");
492 solver.ack_command(
493 &self.arena,
494 self.atoms.success,
495 self.arena
496 .list(vec![self.atoms.set_logic, self.arena.atom(logic)]),
497 )
498 }
499
500 pub fn exit(&mut self) -> io::Result<()> {
502 let solver = self
503 .solver
504 .as_mut()
505 .expect("exit requires a running solver");
506 solver.ack_command(
507 &self.arena,
508 self.atoms.success,
509 self.arena.list(vec![self.atoms.exit]),
510 )
511 }
512
513 pub fn push(&mut self) -> io::Result<()> {
515 let solver = self
516 .solver
517 .as_mut()
518 .expect("push requires a running solver");
519 solver.ack_command(
520 &self.arena,
521 self.atoms.success,
522 self.arena.list(vec![self.atoms.push]),
523 )
524 }
525
526 pub fn push_many(&mut self, n: usize) -> io::Result<()> {
527 let solver = self
528 .solver
529 .as_mut()
530 .expect("push_many requires a running solver");
531 solver.ack_command(
532 &self.arena,
533 self.atoms.success,
534 self.arena
535 .list(vec![self.atoms.push, self.arena.atom(n.to_string())]),
536 )
537 }
538
539 pub fn pop(&mut self) -> io::Result<()> {
541 let solver = self.solver.as_mut().expect("pop requires a running solver");
542 solver.ack_command(
543 &self.arena,
544 self.atoms.success,
545 self.arena.list(vec![self.atoms.pop]),
546 )
547 }
548
549 pub fn pop_many(&mut self, n: usize) -> io::Result<()> {
550 let solver = self
551 .solver
552 .as_mut()
553 .expect("pop_many requires a running solver");
554 solver.ack_command(
555 &self.arena,
556 self.atoms.success,
557 self.arena
558 .list(vec![self.atoms.pop, self.arena.atom(n.to_string())]),
559 )
560 }
561
562 pub fn raw_send(&mut self, cmd: SExpr) -> io::Result<()> {
577 let solver = self
578 .solver
579 .as_mut()
580 .expect("send requires a running solver");
581 solver.send(&self.arena, cmd)
582 }
583
584 pub fn raw_recv(&mut self) -> io::Result<SExpr> {
599 let solver = self
600 .solver
601 .as_mut()
602 .expect("recv requires a running solver");
603 solver.recv(&self.arena)
604 }
605}
606
607impl Context {
613 pub fn atom(&self, name: impl Into<String> + AsRef<str>) -> SExpr {
615 self.arena.atom(name)
616 }
617
618 pub fn list(&self, list: Vec<SExpr>) -> SExpr {
620 self.arena.list(list)
621 }
622
623 pub fn numeral(&self, val: impl IntoNumeral) -> SExpr {
625 self.arena.atom(val.to_string())
626 }
627
628 pub fn decimal(&self, val: impl IntoDecimal) -> SExpr {
630 self.arena.atom(val.to_string())
631 }
632
633 pub fn binary(&self, bit_width: usize, val: impl IntoBinary) -> SExpr {
635 let val = format!("#b{val:0>bit_width$b}");
636 self.arena.atom(val)
637 }
638
639 pub fn display(&self, expr: SExpr) -> DisplayExpr {
648 self.arena.display(expr)
649 }
650
651 pub fn get(&self, expr: SExpr) -> SExprData {
659 self.arena.get(expr)
660 }
661
662 pub fn atoms(&self) -> &KnownAtoms {
667 &self.atoms
668 }
669}
670
671impl Context {
675 pub fn par<N, S, D>(&self, symbols: S, decls: D) -> SExpr
676 where
677 N: Into<String> + AsRef<str>,
678 S: IntoIterator<Item = N>,
679 D: IntoIterator<Item = SExpr>,
680 {
681 self.list(vec![
682 self.atoms.par,
683 self.list(symbols.into_iter().map(|n| self.atom(n)).collect()),
684 self.list(decls.into_iter().collect()),
685 ])
686 }
687
688 pub fn attr(&self, expr: SExpr, name: impl Into<String> + AsRef<str>, val: SExpr) -> SExpr {
689 self.list(vec![self.atoms.bang, expr, self.atom(name), val])
690 }
691
692 pub fn named(&self, name: impl Into<String> + AsRef<str>, expr: SExpr) -> SExpr {
693 self.attr(expr, ":named", self.atom(name))
694 }
695
696 pub fn let_<N: Into<String> + AsRef<str>>(&self, name: N, e: SExpr, body: SExpr) -> SExpr {
698 self.list(vec![
699 self.atoms.let_,
700 self.list(vec![self.list(vec![self.atom(name), e])]),
701 body,
702 ])
703 }
704
705 pub fn let_many<N, I>(&self, bindings: I, body: SExpr) -> SExpr
707 where
708 I: IntoIterator<Item = (N, SExpr)>,
709 N: Into<String> + AsRef<str>,
710 {
711 self.list(vec![
712 self.atoms.let_,
713 self.list(Vec::from_iter(
714 bindings
715 .into_iter()
716 .map(|(n, v)| self.list(vec![self.atom(n), v])),
717 )),
718 body,
719 ])
720 }
721
722 pub fn forall<N, I>(&self, vars: I, body: SExpr) -> SExpr
724 where
725 I: IntoIterator<Item = (N, SExpr)>,
726 N: Into<String> + AsRef<str>,
727 {
728 let vars_iter = vars
729 .into_iter()
730 .map(|(n, s)| self.list(vec![self.atom(n), s]));
731 self.list(vec![
732 self.atoms.forall,
733 self.list(vars_iter.collect()),
734 body,
735 ])
736 }
737
738 pub fn exists<N, I>(&self, vars: I, body: SExpr) -> SExpr
740 where
741 I: IntoIterator<Item = (N, SExpr)>,
742 N: Into<String> + AsRef<str>,
743 {
744 let vars_iter = vars
745 .into_iter()
746 .map(|(n, s)| self.list(vec![self.atom(n), s]));
747 self.list(vec![
748 self.atoms.exists,
749 self.list(vars_iter.collect()),
750 body,
751 ])
752 }
753
754 pub fn match_<I: IntoIterator<Item = (SExpr, SExpr)>>(&self, term: SExpr, arms: I) -> SExpr {
756 let args: Vec<_> = std::iter::once(self.atoms.match_)
757 .chain(std::iter::once(term))
758 .chain(arms.into_iter().map(|(p, v)| self.list(vec![p, v])))
759 .collect();
760 assert!(args.len() >= 3);
761 self.list(args)
762 }
763
764 pub fn ite(&self, c: SExpr, t: SExpr, e: SExpr) -> SExpr {
766 self.list(vec![self.atoms.ite, c, t, e])
767 }
768}
769
770impl Context {
774 pub fn bool_sort(&self) -> SExpr {
776 self.atoms.bool
777 }
778
779 pub fn true_(&self) -> SExpr {
781 self.atoms.t
782 }
783
784 pub fn false_(&self) -> SExpr {
786 self.atoms.f
787 }
788
789 unary!(not, not);
790 right_assoc!(imp, imp_many, imp);
791 left_assoc!(and, and_many, and);
792 left_assoc!(or, or_many, or);
793 left_assoc!(xor, xor_many, xor);
794 chainable!(eq, eq_many, eq);
795 pairwise!(distinct, distinct_many, distinct);
796}
797
798impl Context {
802 pub fn int_sort(&self) -> SExpr {
804 self.atoms.int
805 }
806
807 unary!(negate, minus);
808 left_assoc!(sub, sub_many, minus);
809 left_assoc!(plus, plus_many, plus);
810 left_assoc!(times, times_many, times);
811 left_assoc!(div, div_many, div);
812 left_assoc!(modulo, modulo_many, modulo);
813 left_assoc!(rem, rem_many, rem);
814 chainable!(lte, lte_many, lte);
815 chainable!(lt, lt_many, lt);
816 chainable!(gt, gt_many, gt);
817 chainable!(gte, gte_many, gte);
818}
819
820impl Context {
824 pub fn array_sort(&self, index: SExpr, element: SExpr) -> SExpr {
826 self.list(vec![self.atoms.array, index, element])
827 }
828
829 pub fn select(&self, ary: SExpr, index: SExpr) -> SExpr {
831 self.list(vec![self.atoms.select, ary, index])
832 }
833
834 pub fn store(&self, ary: SExpr, index: SExpr, value: SExpr) -> SExpr {
836 self.list(vec![self.atoms.store, ary, index, value])
837 }
838}
839
840impl Context {
845 pub fn bit_vec_sort(&self, width: SExpr) -> SExpr {
847 self.list(vec![self.atoms.und, self.atoms.bit_vec, width])
848 }
849
850 pub fn concat(&self, lhs: SExpr, rhs: SExpr) -> SExpr {
852 self.list(vec![self.atoms.concat, lhs, rhs])
853 }
854
855 pub fn extract(&self, i: i32, j: i32, bv: SExpr) -> SExpr {
857 self.list(vec![
858 self.list(vec![
859 self.atoms.und,
860 self.atoms.extract,
861 self.numeral(i),
862 self.numeral(j),
863 ]),
864 bv,
865 ])
866 }
867
868 unary!(bvnot, bvnot);
869 left_assoc!(bvor, bvor_many, bvor);
870 left_assoc!(bvand, bvand_many, bvand);
871 left_assoc!(bvnand, bvnand_many, bvnand);
872 left_assoc!(bvxor, bvxor_many, bvxor);
873 left_assoc!(bvxnor, bvxnor_many, bvxnor);
874 unary!(bvneg, bvneg);
875 left_assoc!(bvadd, bvadd_many, bvadd);
876 binop!(bvsub, bvsub);
877 left_assoc!(bvmul, bvmul_many, bvmul);
878 binop!(bvudiv, bvudiv);
879 binop!(bvurem, bvurem);
880 binop!(bvsdiv, bvsdiv);
881 binop!(bvsrem, bvsrem);
882 binop!(bvsmod, bvsmod);
883 binop!(bvshl, bvshl);
884 binop!(bvlshr, bvlshr);
885 binop!(bvashr, bvashr);
886 binop!(bvule, bvule);
887 binop!(bvult, bvult);
888 binop!(bvuge, bvuge);
889 binop!(bvugt, bvugt);
890 binop!(bvsle, bvsle);
891 binop!(bvslt, bvslt);
892 binop!(bvsge, bvsge);
893 binop!(bvsgt, bvsgt);
894 binop!(bvcomp, bvcomp);
895}
896
897#[derive(Clone, Copy, Debug, PartialEq, Eq)]
898pub enum Response {
899 Sat,
900 Unsat,
901 Unknown,
902}
903
904mod private {
905 pub trait IntoNumeral: IntoNumeralSealed {}
907 pub trait IntoNumeralSealed: std::fmt::Display {}
908
909 pub trait IntoBinary: IntoBinarySealed {}
911 pub trait IntoBinarySealed: std::fmt::Binary {}
912
913 impl IntoNumeralSealed for i8 {}
914 impl IntoNumeral for i8 {}
915 impl IntoBinarySealed for i8 {}
916 impl IntoBinary for i8 {}
917 impl IntoNumeralSealed for i16 {}
918 impl IntoNumeral for i16 {}
919 impl IntoBinarySealed for i16 {}
920 impl IntoBinary for i16 {}
921 impl IntoNumeralSealed for i32 {}
922 impl IntoNumeral for i32 {}
923 impl IntoBinarySealed for i32 {}
924 impl IntoBinary for i32 {}
925 impl IntoNumeralSealed for i64 {}
926 impl IntoNumeral for i64 {}
927 impl IntoBinarySealed for i64 {}
928 impl IntoBinary for i64 {}
929 impl IntoNumeralSealed for i128 {}
930 impl IntoNumeral for i128 {}
931 impl IntoBinarySealed for i128 {}
932 impl IntoBinary for i128 {}
933 impl IntoNumeralSealed for isize {}
934 impl IntoNumeral for isize {}
935 impl IntoBinarySealed for isize {}
936 impl IntoBinary for isize {}
937 impl IntoNumeralSealed for u8 {}
938 impl IntoNumeral for u8 {}
939 impl IntoBinarySealed for u8 {}
940 impl IntoBinary for u8 {}
941 impl IntoNumeralSealed for u16 {}
942 impl IntoNumeral for u16 {}
943 impl IntoBinarySealed for u16 {}
944 impl IntoBinary for u16 {}
945 impl IntoNumeralSealed for u32 {}
946 impl IntoNumeral for u32 {}
947 impl IntoBinarySealed for u32 {}
948 impl IntoBinary for u32 {}
949 impl IntoNumeralSealed for u64 {}
950 impl IntoNumeral for u64 {}
951 impl IntoBinarySealed for u64 {}
952 impl IntoBinary for u64 {}
953 impl IntoNumeralSealed for u128 {}
954 impl IntoNumeral for u128 {}
955 impl IntoBinarySealed for u128 {}
956 impl IntoBinary for u128 {}
957 impl IntoNumeralSealed for usize {}
958 impl IntoNumeral for usize {}
959 impl IntoBinarySealed for usize {}
960 impl IntoBinary for usize {}
961
962 pub trait IntoDecimal: IntoDecimalSealed {}
964 pub trait IntoDecimalSealed: std::fmt::Display {}
965
966 impl IntoDecimal for f32 {}
967 impl IntoDecimalSealed for f32 {}
968 impl IntoDecimal for f64 {}
969 impl IntoDecimalSealed for f64 {}
970}
971pub use private::{IntoBinary, IntoDecimal, IntoNumeral};
972
973#[cfg(test)]
974mod tests {
975 use super::*;
976
977 macro_rules! check_expr {
978 ($ctx:expr, $expr:expr, $expected:expr) => {
979 let actual = $ctx.display($expr).to_string();
980 assert_eq!(actual, $expected);
981 };
982 }
983
984 #[test]
985 fn test_variadic_ops() {
986 let ctx = ContextBuilder::new().build().unwrap();
987
988 check_expr!(ctx, ctx.imp_many([ctx.true_()]), "true");
991 check_expr!(
992 ctx,
993 ctx.imp_many([ctx.true_(), ctx.false_()]),
994 "(=> true false)"
995 );
996 }
997
998 #[cfg(debug_assertions)]
999 #[test]
1000 #[should_panic]
1001 fn sexpr_with_wrong_context() {
1002 let ctx1 = ContextBuilder::new().build().unwrap();
1003 let ctx2 = ContextBuilder::new().build().unwrap();
1004
1005 let pizza1 = ctx1.atom("pizza");
1006 let _pizza2 = ctx2.atom("pizza");
1007
1008 let _ = ctx2.get(pizza1);
1010 }
1011}