Skip to main content

theorem_prover/
lang.rs

1use std::{
2    fmt::Display,
3    sync::atomic::{AtomicUsize, Ordering},
4};
5
6use derivative::Derivative;
7
8#[derive(Debug, Clone, PartialEq, Eq, Hash)]
9pub enum Formula {
10    Pred(Pred),
11    True,
12    False,
13    And(Box<Formula>, Box<Formula>),
14    Or(Box<Formula>, Box<Formula>),
15    Neg(Box<Formula>),
16    Imply(Box<Formula>, Box<Formula>),
17    Iff(Box<Formula>, Box<Formula>),
18    Forall(Var, Box<Formula>),
19    Exists(Var, Box<Formula>),
20}
21
22#[derive(Debug, Clone, PartialEq, Eq, Hash)]
23pub struct Pred {
24    id: String,
25    args: Box<Vec<Term>>,
26}
27
28#[derive(Debug, Clone, PartialEq, Eq, Hash)]
29pub enum Term {
30    Obj(Obj),
31    Var(Var),
32    Fun(Fun),
33}
34
35#[derive(Debug, Clone, PartialEq, Eq, Hash)]
36pub struct Obj {
37    id: String,
38}
39
40#[derive(Debug, Clone, Hash, PartialEq, Eq)]
41pub struct Var {
42    id: String,
43}
44
45#[derive(Debug, Clone, PartialEq, Eq, Hash)]
46pub struct Fun {
47    id: String,
48    args: Box<Vec<Term>>,
49}
50
51#[derive(Derivative)]
52#[derivative(Debug, PartialEq)]
53pub struct Clause {
54    #[derivative(PartialEq = "ignore")] // ignore field id for comparison
55    id: usize,
56    formulas: Vec<Formula>,
57}
58
59impl Pred {
60    pub fn new(id: &str, args: Box<Vec<Term>>) -> Self {
61        Self {
62            id: id.to_string(),
63            args,
64        }
65    }
66
67    pub fn get_id(&self) -> &String {
68        &self.id
69    }
70
71    pub fn get_args(&self) -> &Box<Vec<Term>> {
72        &self.args
73    }
74}
75
76impl Obj {
77    pub fn new(id: &str) -> Self {
78        Self { id: id.to_string() }
79    }
80}
81
82impl Var {
83    pub fn new(id: &str) -> Self {
84        Self { id: id.to_string() }
85    }
86}
87
88impl Fun {
89    pub fn new(id: &str, args: Box<Vec<Term>>) -> Self {
90        Self {
91            id: id.to_string(),
92            args,
93        }
94    }
95
96    pub fn get_id(&self) -> &String {
97        &self.id
98    }
99
100    pub fn get_args(&self) -> &Box<Vec<Term>> {
101        &self.args
102    }
103}
104
105static CLAUSE_COUNTER: AtomicUsize = AtomicUsize::new(0);
106
107impl Clause {
108    pub fn new(formulas: Vec<Formula>) -> Self {
109        Self {
110            id: CLAUSE_COUNTER.fetch_add(1, Ordering::SeqCst),
111            formulas,
112        }
113    }
114
115    pub fn get_id(&self) -> usize {
116        self.id
117    }
118
119    pub fn get_formulas(&self) -> &Vec<Formula> {
120        &self.formulas
121    }
122}
123
124impl Display for Formula {
125    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126        match &self {
127            Formula::Pred(pred) => write!(f, "{pred}"),
128            Formula::True => write!(f, "true"),
129            Formula::False => write!(f, "false"),
130            Formula::And(l, r) => write!(f, "({l}) /\\ ({r})"),
131            Formula::Or(l, r) => write!(f, "({l}) \\/ ({r})"),
132            Formula::Neg(l) => write!(f, "~({l})"),
133            Formula::Imply(l, r) => write!(f, "({l}) -> ({r})"),
134            Formula::Iff(l, r) => write!(f, "({l}) <-> ({r})"),
135            Formula::Forall(v, l) => write!(f, "forall {v}.({l})"),
136            Formula::Exists(v, l) => write!(f, "exists {v}.({l})"),
137        }
138    }
139}
140
141impl Display for Pred {
142    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143        write!(f, "{}(", self.id)?;
144        for (index, arg) in self.args.iter().enumerate() {
145            write!(f, "{arg}")?;
146            if index != self.args.len() - 1 {
147                write!(f, ", ")?;
148            }
149        }
150        write!(f, ")")
151    }
152}
153
154impl Display for Term {
155    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
156        match &self {
157            Term::Obj(Obj { id }) => write!(f, "{id}"),
158            Term::Var(Var { id }) => write!(f, "{id}"),
159            Term::Fun(func) => write!(f, "{func}"),
160        }
161    }
162}
163
164impl Display for Obj {
165    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
166        write!(f, "{}", self.id)
167    }
168}
169
170impl Display for Var {
171    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172        write!(f, "{}", self.id)
173    }
174}
175
176impl Display for Fun {
177    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
178        write!(f, "{}(", self.id)?;
179        for (index, arg) in self.args.iter().enumerate() {
180            write!(f, "{arg}")?;
181            if index != self.args.len() - 1 {
182                write!(f, ", ")?;
183            }
184        }
185        write!(f, ")")
186    }
187}
188
189impl Display for Clause {
190    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
191        write!(f, "C{}: {{", self.id)?;
192        for (index, arg) in self.formulas.iter().enumerate() {
193            write!(f, "{arg}")?;
194            if index != self.formulas.len() - 1 {
195                write!(f, ", ")?;
196            }
197        }
198        write!(f, "}}")
199    }
200}
201
202#[macro_export]
203macro_rules! And {
204    ($left:expr, $right:expr) => {
205        Formula::And(Box::new($left), Box::new($right))
206    };
207}
208
209#[macro_export]
210macro_rules! Or {
211    ($left:expr, $right:expr) => {
212        Formula::Or(Box::new($left), Box::new($right))
213    };
214}
215
216#[macro_export]
217macro_rules! Imply {
218    ($left:expr, $right:expr) => {
219        Formula::Imply(Box::new($left), Box::new($right))
220    };
221}
222
223#[macro_export]
224macro_rules! Iff {
225    ($left:expr, $right:expr) => {
226        Formula::Iff(Box::new($left), Box::new($right))
227    };
228}
229
230#[macro_export]
231macro_rules! Neg {
232    ($subformula:expr) => {
233        Formula::Neg(Box::new($subformula))
234    };
235}
236
237#[macro_export]
238macro_rules! Forall {
239    ($var:expr, $subformula:expr) => {
240        Formula::Forall(Var::new($var), Box::new($subformula))
241    };
242}
243
244#[macro_export]
245macro_rules! Exists {
246    ($var:expr, $subformula:expr) => {
247        Formula::Exists(Var::new($var), Box::new($subformula))
248    };
249}
250
251#[macro_export]
252macro_rules! Pred {
253    ($id:expr, [$($arg:expr),*]) => {
254        Formula::Pred(Pred::new($id, Box::new(vec![$($arg),*])))
255    };
256}
257
258#[macro_export]
259macro_rules! Obj {
260    ($name:expr) => {
261        Term::Obj(Obj::new($name))
262    };
263}
264
265#[macro_export]
266macro_rules! Var {
267    ($name:expr) => {
268        Term::Var(Var::new($name))
269    };
270}
271
272#[macro_export]
273macro_rules! Fun {
274    ($id:expr, [$($arg:expr),*]) => {
275        Term::Fun(Fun::new($id, Box::new(vec![$($arg),*])))
276    };
277}