#![allow(unknown_lints)]
use interface::{ATerm as ATermT, ATermFactory as ATermFactoryT,
SharedATermFactory as SharedATermFactoryT};
use utils::insert_or_get;
use rc::{ATerm, Term, TermPlaceholder};
use bad_idea::BrokenF32;
use std::collections::HashSet;
use std::hash::Hash;
use std::marker::PhantomData;
use std::hash::BuildHasher;
use std::borrow::Cow;
use std::cell::RefCell;
use std::rc::Rc;
use string_share::StringShare;
pub struct ATermFactory<'s, B: Hash + Eq, H: BuildHasher> {
string_cache: RefCell<StringShare<H>>,
arena: RefCell<HashSet<Rc<ATerm<'s, B>>, H>>,
_nothing: PhantomData<B>,
}
impl<'s, B: Hash + Eq, H: BuildHasher + Default> ATermFactory<'s, B, H> {
pub fn new() -> Self {
ATermFactory {
string_cache: RefCell::new(StringShare::new()),
arena: RefCell::new(HashSet::default()),
_nothing: PhantomData,
}
}
pub fn with_capacity(capacity: usize) -> Self {
ATermFactory {
string_cache: RefCell::new(StringShare::new()),
arena: RefCell::new(HashSet::with_capacity_and_hasher(
capacity,
Default::default(),
)),
_nothing: PhantomData,
}
}
}
impl<'s, B: Hash + Eq, H: BuildHasher + Default> Default for ATermFactory<'s, B, H> {
fn default() -> Self {
Self::new()
}
}
impl<'s, B: 's + Clone + Hash + Eq, H: 's + BuildHasher + Default> ATermFactoryT<'s>
for ATermFactory<'s, B, H> {
type ATerm = ATerm<'s, B>;
type ATermRef = Rc<ATerm<'s, B>>;
fn with_annos<A>(&'s self, term: Self::ATermRef, annos: A) -> Self::ATermRef
where
A: IntoIterator<Item = Self::ATermRef>,
{
insert_or_get(
&mut self.arena.borrow_mut(),
Rc::new(ATerm::with_annos(term.term.clone(), annos)),
).clone()
}
fn application<I, S>(&'s self, constructor: S, children: I) -> Self::ATermRef
where
I: IntoIterator<Item = Self::ATermRef>,
S: Into<Cow<'s, str>>,
{
use rc::Term::Application;
use utils::extend_lifetime_mut;
let mut string_cache = unsafe { extend_lifetime_mut(&mut self.string_cache.borrow_mut()) };
let cons = string_cache.insert(constructor.into().as_ref());
Rc::new(ATerm::no_annos(Application(
cons,
children.into_iter().collect::<Vec<_>>().into_boxed_slice(),
)))
}
fn int(&'s self, value: i32) -> Self::ATermRef {
Rc::new(ATerm::no_annos(Term::Int(value)))
}
fn string<S>(&'s self, value: S) -> Self::ATermRef
where
S: Into<Cow<'s, str>>,
{
self.application(::utils::string_escape(&value.into()), ::std::iter::empty())
}
fn tuple<I>(&'s self, children: I) -> Self::ATermRef
where
I: IntoIterator<Item = Self::ATermRef>,
{
self.application(String::new(), children)
}
fn real(&'s self, value: f32) -> Self::ATermRef {
Rc::new(ATerm::no_annos(Term::Real(BrokenF32(value))))
}
fn list<I>(&'s self, value: I) -> Self::ATermRef
where
I: IntoIterator<Item = Self::ATermRef>,
{
Rc::new(ATerm::no_annos(Term::List(
value.into_iter().collect::<Vec<_>>().into_boxed_slice(),
)))
}
fn placeholder(&'s self, value: TermPlaceholder<Self::ATermRef>) -> Self::ATermRef {
Rc::new(ATerm::no_annos(Term::Placeholder(value)))
}
fn blob(&'s self, value: <Self::ATerm as ATermT<'s>>::Blob) -> Self::ATermRef {
Rc::new(ATerm::no_annos(Term::Blob(value)))
}
fn long(&'s self, value: i64) -> Self::ATermRef {
Rc::new(ATerm::no_annos(Term::Long(value)))
}
}
impl<'s, B, H> SharedATermFactoryT<'s> for ATermFactory<'s, B, H>
where
B: 's + Clone + Hash + Eq,
H: 's + BuildHasher + Default,
{
fn get_shared(&'s self, value: Self::ATermRef) -> Self::ATermRef
where
Self::ATermRef: Clone,
{
insert_or_get(&mut self.arena.borrow_mut(), value.clone()).clone()
}
}