1use crate::formally;
26use dashmap::DashSet;
27use formally::{
28 smt::*,
29 support::{Identifier, Nominal},
30};
31use std::{borrow::Borrow, cell::RefCell, collections::HashSet, fmt::Debug, sync::Arc};
32
33pub trait TermPool {
49 fn shared(&self, kind: TermKind) -> Term;
51
52 fn shared_ref(&self, kind: &TermKind) -> Term;
55}
56
57#[derive(Debug, Hash, PartialEq, Eq)]
58struct Lookup<T>(T);
59
60impl Borrow<TermKind> for Lookup<Arc<TermInner>> {
61 fn borrow(&self) -> &TermKind {
62 &self.0.kind
63 }
64}
65
66#[derive(Debug, Default)]
74pub struct HashPool {
75 pool: RefCell<HashSet<Lookup<Arc<TermInner>>>>,
76}
77
78impl HashPool {
79 pub fn new() -> HashPool {
80 HashPool::default()
81 }
82}
83
84#[derive(Debug, Default)]
93pub struct DashPool {
94 pool: DashSet<Lookup<Arc<TermInner>>>,
95}
96
97impl DashPool {
98 pub fn new() -> DashPool {
99 DashPool::default()
100 }
101}
102
103impl TermPool for DashPool {
104 fn shared(&self, kind: TermKind) -> Term {
105 if let Some(kind) = self.pool.get(&kind) {
106 Term(Nominal(kind.0.clone()))
107 } else {
108 let arc = Arc::new(TermInner::new(kind));
109 let term = Term(Nominal(arc.clone()));
110 self.pool.insert(Lookup(arc));
111
112 term
113 }
114 }
115
116 fn shared_ref(&self, kind: &TermKind) -> Term {
117 if let Some(kind) = self.pool.get(kind) {
118 Term(Nominal(kind.0.clone()))
119 } else {
120 let arc = Arc::new(TermInner::new(kind.clone()));
121 let term = Term(Nominal(arc.clone()));
122 self.pool.insert(Lookup(arc));
123
124 term
125 }
126 }
127}
128
129impl TermPool for HashPool {
130 fn shared(&self, kind: TermKind) -> Term {
131 if let Some(kind) = self.pool.borrow().get(&kind) {
132 Term(Nominal(kind.0.clone()))
133 } else {
134 let arc = Arc::new(TermInner::new(kind));
135 let term = Term(Nominal(arc.clone()));
136 self.pool.borrow_mut().insert(Lookup(arc));
137
138 term
139 }
140 }
141
142 fn shared_ref(&self, kind: &TermKind) -> Term {
143 if let Some(kind) = self.pool.borrow().get(kind) {
144 Term(Nominal(kind.0.clone()))
145 } else {
146 let arc = Arc::new(TermInner::new(kind.clone()));
147 let term = Term(Nominal(arc.clone()));
148 self.pool.borrow_mut().insert(Lookup(arc));
149
150 term
151 }
152 }
153}
154
155pub trait ToTerm: Debug {
167 fn into_term_in(self, pool: &dyn TermPool) -> Term;
169
170 fn to_term_in(&self, pool: &dyn TermPool) -> Term;
172}
173
174impl<T: ToTerm> ToTerm for &T {
175 fn into_term_in(self, pool: &dyn TermPool) -> Term {
176 self.to_term_in(pool)
177 }
178
179 fn to_term_in(&self, pool: &dyn TermPool) -> Term {
180 (*self).to_term_in(pool)
181 }
182}
183
184impl ToTerm for Term {
185 fn into_term_in(self, _pool: &dyn TermPool) -> Term {
186 self
187 }
188
189 fn to_term_in(&self, _pool: &dyn TermPool) -> Term {
190 self.clone()
191 }
192}
193
194impl ToTerm for TermKind {
195 fn into_term_in(self, pool: &dyn TermPool) -> Term {
196 pool.shared(self)
197 }
198
199 fn to_term_in(&self, pool: &dyn TermPool) -> Term {
200 pool.shared_ref(self)
201 }
202}
203
204impl ToTerm for Constant {
205 fn into_term_in(self, pool: &dyn TermPool) -> Term {
206 TermKind::Constant(self).into_term_in(pool)
207 }
208
209 fn to_term_in(&self, pool: &dyn TermPool) -> Term {
210 TermKind::Constant(self.clone()).into_term_in(pool)
211 }
212}
213
214impl ToTerm for Atom {
215 fn into_term_in(self, pool: &dyn TermPool) -> Term {
216 TermKind::Atom(self).into_term_in(pool)
217 }
218
219 fn to_term_in(&self, pool: &dyn TermPool) -> Term {
220 TermKind::Atom(self.clone()).into_term_in(pool)
221 }
222}
223
224impl ToTerm for FunctionRef {
225 fn into_term_in(self, pool: &dyn TermPool) -> Term {
226 TermKind::Atom(Atom::from(self)).into_term_in(pool)
227 }
228
229 fn to_term_in(&self, pool: &dyn TermPool) -> Term {
230 TermKind::Atom(Atom::from(self.clone())).into_term_in(pool)
231 }
232}
233
234impl ToTerm for BoundRef {
235 fn into_term_in(self, pool: &dyn TermPool) -> Term {
236 TermKind::Atom(Atom::from(self)).into_term_in(pool)
237 }
238
239 fn to_term_in(&self, pool: &dyn TermPool) -> Term {
240 TermKind::Atom(Atom::from(self.clone())).into_term_in(pool)
241 }
242}
243
244impl ToTerm for Function {
245 fn into_term_in(self, pool: &dyn TermPool) -> Term {
246 TermKind::Atom(Atom::from(self)).into_term_in(pool)
247 }
248
249 fn to_term_in(&self, pool: &dyn TermPool) -> Term {
250 TermKind::Atom(Atom::from(self.clone())).into_term_in(pool)
251 }
252}
253
254impl ToTerm for Variable {
255 fn into_term_in(self, pool: &dyn TermPool) -> Term {
256 TermKind::Atom(Atom::from(self)).into_term_in(pool)
257 }
258
259 fn to_term_in(&self, pool: &dyn TermPool) -> Term {
260 TermKind::Atom(Atom::from(self.clone())).into_term_in(pool)
261 }
262}
263
264impl ToTerm for Primitive {
265 fn into_term_in(self, pool: &dyn TermPool) -> Term {
266 TermKind::Atom(Atom::from(self)).into_term_in(pool)
267 }
268
269 fn to_term_in(&self, pool: &dyn TermPool) -> Term {
270 TermKind::Atom(Atom::from(self.clone())).into_term_in(pool)
271 }
272}
273
274impl ToTerm for UserFunction {
275 fn into_term_in(self, pool: &dyn TermPool) -> Term {
276 TermKind::Atom(Atom::from(self)).into_term_in(pool)
277 }
278
279 fn to_term_in(&self, pool: &dyn TermPool) -> Term {
280 TermKind::Atom(Atom::from(self.clone())).into_term_in(pool)
281 }
282}
283
284impl ToTerm for Declared {
285 fn into_term_in(self, pool: &dyn TermPool) -> Term {
286 TermKind::Atom(Atom::from(self)).into_term_in(pool)
287 }
288
289 fn to_term_in(&self, pool: &dyn TermPool) -> Term {
290 TermKind::Atom(Atom::from(self.clone())).into_term_in(pool)
291 }
292}
293
294impl ToTerm for Defined {
295 fn into_term_in(self, pool: &dyn TermPool) -> Term {
296 TermKind::Atom(Atom::from(self)).into_term_in(pool)
297 }
298
299 fn to_term_in(&self, pool: &dyn TermPool) -> Term {
300 TermKind::Atom(Atom::from(self.clone())).into_term_in(pool)
301 }
302}
303
304impl ToTerm for Identifier<'_> {
305 fn into_term_in(self, pool: &dyn TermPool) -> Term {
306 TermKind::Atom(Atom::from(self.into_owned())).into_term_in(pool)
307 }
308
309 fn to_term_in(&self, pool: &dyn TermPool) -> Term {
310 TermKind::Atom(Atom::from(self.clone().into_owned())).into_term_in(pool)
311 }
312}
313
314impl ToTerm for Quantified {
315 fn into_term_in(self, pool: &dyn TermPool) -> Term {
316 TermKind::Quantified(self).into_term_in(pool)
317 }
318
319 fn to_term_in(&self, pool: &dyn TermPool) -> Term {
320 TermKind::Quantified(self.clone()).into_term_in(pool)
321 }
322}
323
324impl ToTerm for Let {
325 fn into_term_in(self, pool: &dyn TermPool) -> Term {
326 TermKind::Let(self).into_term_in(pool)
327 }
328
329 fn to_term_in(&self, pool: &dyn TermPool) -> Term {
330 TermKind::Let(self.clone()).into_term_in(pool)
331 }
332}
333
334impl ToTerm for Sort {
335 fn into_term_in(self, pool: &dyn TermPool) -> Term {
336 let mut arguments = Vec::with_capacity(self.arguments.len());
337 for arg in &*self.arguments {
338 match arg {
339 SortArgument::Value(c) => arguments.push(
340 Constant::Integer {
341 value: c.clone(),
342 span: None,
343 }
344 .to_term_in(pool),
345 ),
346 SortArgument::Sort(s) => arguments.push(s.to_term_in(pool)),
347 }
348 }
349
350 Atom {
351 head: FunctionRef::from(self.head.clone()),
352 arguments: Arc::from(arguments.into_boxed_slice()),
353 span: None,
354 }
355 .into_term_in(pool)
356 }
357
358 fn to_term_in(&self, pool: &dyn TermPool) -> Term {
359 self.clone().into_term_in(pool)
360 }
361}