1#![doc = concat!("```ignore\n", include_str!("./Ints.smt2"), "```")]
2
3use smtlib_lowlevel::{
4 ast::{self, SpecConstant, Term},
5 lexicon::Numeral,
6 Storage,
7};
8
9use crate::{
10 impl_op,
11 sorts::Sort,
12 terms::{app, Const, Dynamic, IntoWithStorage, STerm, Sorted, StaticSorted},
13 Bool,
14};
15
16#[derive(Debug, Clone, Copy)]
20pub struct Int<'st>(STerm<'st>);
21impl<'st> From<Const<'st, Int<'st>>> for Int<'st> {
22 fn from(c: Const<'st, Int<'st>>) -> Self {
23 c.1
24 }
25}
26impl<'st> IntoWithStorage<'st, Int<'st>> for Const<'st, Int<'st>> {
27 fn into_with_storage(self, _st: &'st Storage) -> Int<'st> {
28 self.1
29 }
30}
31impl std::fmt::Display for Int<'_> {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 STerm::from(*self).term().fmt(f)
34 }
35}
36
37impl<'st> From<Int<'st>> for Dynamic<'st> {
38 fn from(i: Int<'st>) -> Self {
39 i.into_dynamic()
40 }
41}
42
43impl<'st> From<Int<'st>> for STerm<'st> {
44 fn from(i: Int<'st>) -> Self {
45 i.0
46 }
47}
48impl<'st> From<STerm<'st>> for Int<'st> {
49 fn from(t: STerm<'st>) -> Self {
50 Int(t)
51 }
52}
53impl<'st> From<(STerm<'st>, Sort<'st>)> for Int<'st> {
54 fn from((t, _): (STerm<'st>, Sort<'st>)) -> Self {
55 t.into()
56 }
57}
58impl<'st> StaticSorted<'st> for Int<'st> {
59 type Inner = Self;
60 const AST_SORT: ast::Sort<'static> = ast::Sort::new_simple("Int");
61
62 fn static_st(&self) -> &'st Storage {
63 self.0.st()
64 }
65}
66impl<'st> IntoWithStorage<'st, Int<'st>> for i64 {
67 fn into_with_storage(self, st: &'st Storage) -> Int<'st> {
68 let term = if self < 0 {
69 app(
70 st,
71 "-",
72 Term::SpecConstant(SpecConstant::Numeral(Numeral::from_usize(
73 self.unsigned_abs() as _,
74 ))),
75 )
76 } else {
77 STerm::new(
78 st,
79 Term::SpecConstant(SpecConstant::Numeral(Numeral::from_usize(self as _))),
80 )
81 };
82 term.into()
83 }
84}
85impl<'st> Int<'st> {
86 pub fn sort() -> Sort<'st> {
88 Self::AST_SORT.into()
89 }
90 pub fn new(st: &'st Storage, value: impl IntoWithStorage<'st, Int<'st>>) -> Int<'st> {
92 value.into_with_storage(st)
93 }
94 fn binop<T: From<STerm<'st>>>(self, op: &'st str, other: Int<'st>) -> T {
95 app(self.static_st(), op, (self.term(), other.term())).into()
96 }
97 pub fn gt(self, other: impl IntoWithStorage<'st, Self>) -> Bool<'st> {
99 self.binop(">", other.into_with_storage(self.st()))
100 }
101 pub fn ge(self, other: impl IntoWithStorage<'st, Self>) -> Bool<'st> {
103 self.binop(">=", other.into_with_storage(self.st()))
104 }
105 pub fn lt(self, other: impl IntoWithStorage<'st, Self>) -> Bool<'st> {
107 self.binop("<", other.into_with_storage(self.st()))
108 }
109 pub fn le(self, other: impl IntoWithStorage<'st, Self>) -> Bool<'st> {
111 self.binop("<=", other.into_with_storage(self.st()))
112 }
113 pub fn abs(self) -> Int<'st> {
116 app(self.st(), "abs", self.term()).into()
117 }
118}
119
120impl std::ops::Neg for Int<'_> {
121 type Output = Self;
122 fn neg(self) -> Self::Output {
123 app(self.st(), "-", self.term()).into()
124 }
125}
126
127impl_op!(Int<'st>, i64, Add, add, "+", AddAssign, add_assign, +);
128impl_op!(Int<'st>, i64, Sub, sub, "-", SubAssign, sub_assign, -);
129impl_op!(Int<'st>, i64, Mul, mul, "*", MulAssign, mul_assign, *);
130impl_op!(Int<'st>, i64, Div, div, "div", DivAssign, div_assign, /);
131impl_op!(Int<'st>, i64, Rem, rem, "rem", RemAssign, rem_assign, %);
132impl_op!(Int<'st>, i64, Shl, shl, "hsl", ShlAssign, shl_assign, <<);
133impl_op!(Int<'st>, i64, Shr, shr, "hsr", ShrAssign, shr_assign, >>);