use std::iter;
use std::borrow::Borrow;
use std::fmt;
pub use bad_idea::BrokenF32;
use print::*;
pub trait ATermFactory<B> {
type ATerm: ATerm<Blob = B, Rec = Self::ATermRef>;
type ATermRef: Borrow<Self::ATerm>;
fn int(&self, value: i32) -> Self::ATermRef {
self.no_annos(self.t_int(value))
}
fn string(&self, value: String) -> Self::ATermRef {
self.application(format!("{:?}", value), iter::empty())
}
fn tuple<I>(&self, children: I) -> Self::ATermRef
where I: IntoIterator<Item = Self::ATermRef>
{
self.application(String::new(), children)
}
fn real(&self, value: f32) -> Self::ATermRef {
self.no_annos(self.t_real(value))
}
fn application<I>(&self, constructor: String, children: I) -> Self::ATermRef
where I: IntoIterator<Item = Self::ATermRef>
{
self.no_annos(self.t_application(constructor, children))
}
fn list<I>(&self, value: I) -> Self::ATermRef
where I: IntoIterator<Item = Self::ATermRef>
{
self.no_annos(self.t_list(value))
}
fn placeholder(&self, value: TermPlaceholder<Self::ATermRef>) -> Self::ATermRef {
self.no_annos(self.t_placeholder(value))
}
fn blob(&self, value: B) -> Self::ATermRef {
self.no_annos(self.t_blob(value))
}
fn long(&self, value: i64) -> Self::ATermRef {
self.no_annos(self.t_long(value))
}
fn t_int(&self, value: i32) -> Term<Self::ATermRef, B> {
Term::Int(value)
}
fn t_string(&self, value: String) -> Term<Self::ATermRef, B> {
self.t_application(format!("{:?}", value), iter::empty())
}
fn t_tuple<I>(&self, children: I) -> Term<Self::ATermRef, B>
where I: IntoIterator<Item = Self::ATermRef>
{
self.t_application(String::new(), children)
}
fn t_real(&self, value: f32) -> Term<Self::ATermRef, B> {
Term::Real(BrokenF32(value))
}
fn t_application<I>(&self, constructor: String, children: I) -> Term<Self::ATermRef, B>
where I: IntoIterator<Item = Self::ATermRef>
{
Term::Application(constructor,
children
.into_iter()
.collect::<Vec<_>>()
.into_boxed_slice())
}
fn t_list<I>(&self, value: I) -> Term<Self::ATermRef, B>
where I: IntoIterator<Item = Self::ATermRef>
{
Term::List(value.into_iter().collect::<Vec<_>>().into_boxed_slice())
}
fn t_placeholder(&self, value: TermPlaceholder<Self::ATermRef>) -> Term<Self::ATermRef, B> {
Term::Placeholder(value)
}
fn t_blob(&self, value: B) -> Term<Self::ATermRef, B> {
Term::Blob(value)
}
fn t_long(&self, value: i64) -> Term<Self::ATermRef, B> {
Term::Long(value)
}
fn no_annos(&self, term: Term<Self::ATermRef, B>) -> Self::ATermRef;
fn with_annos<A>(&self, term: Term<Self::ATermRef, B>, annos: A) -> Self::ATermRef
where A: IntoIterator<Item = Self::ATermRef>;
}
pub trait SharedATermFactory<B>: ATermFactory<B> {
fn get_shared(&self, value: Self::ATermRef) -> Self::ATermRef
where Self::ATermRef: Clone,
B: Clone;
}
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub enum Term<Rec, Blob> {
Int(i32),
Long(i64),
Real(BrokenF32),
Application(String, Box<[Rec]>),
List(Box<[Rec]>),
Placeholder(TermPlaceholder<Rec>),
Blob(Blob),
}
impl<Rec, B> fmt::Display for Term<Rec, B>
where Rec: ATermWrite,
B: ATermWrite
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.to_ascii(f)
}
}
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub enum TermPlaceholder<Rec> {
Int,
String,
Real,
Term,
Application(Box<[Rec]>),
List,
Placeholder,
Blob,
Long,
}
impl<Rec> fmt::Display for TermPlaceholder<Rec>
where Rec: ATermWrite
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.to_ascii(f)
}
}
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct ATermInner<ATerm, B> {
pub term: Term<ATerm, B>,
pub annotations: Box<[ATerm]>,
}
impl<ATerm, B> ATermInner<ATerm, B> {
pub fn no_annos(term: Term<ATerm, B>) -> Self {
ATermInner {
term: term,
annotations: Box::new([]),
}
}
pub fn with_annos<A>(term: Term<ATerm, B>, annos: A) -> Self
where A: IntoIterator<Item =ATerm>
{
ATermInner {
term: term,
annotations: annos.into_iter().collect::<Vec<_>>().into_boxed_slice(),
}
}
}
pub trait ATerm {
type Rec: Borrow<Self>;
type Blob;
fn into_inner(self) -> ATermInner<Self::Rec, Self::Blob>;
fn as_inner(&self) -> &ATermInner<Self::Rec, Self::Blob>;
fn get_int(&self) -> Option<i32> {
match self.as_inner().term {
Term::Int(i) => Some(i),
_ => None,
}
}
fn get_long(&self) -> Option<i64> {
match self.as_inner().term {
Term::Long(l) => Some(l),
_ => None,
}
}
fn get_real(&self) -> Option<f32> {
match self.as_inner().term {
Term::Real(BrokenF32(r)) => Some(r),
_ => None,
}
}
fn get_application(&self) -> Option<(&str, &[Self::Rec])> {
match self.as_inner().term {
Term::Application(ref c, ref r) => Some((c, r)),
_ => None,
}
}
fn get_list(&self) -> Option<&[Self::Rec]> {
match self.as_inner().term {
Term::List(ref r) => Some(r),
_ => None,
}
}
fn get_placeholder(&self) -> Option<&TermPlaceholder<Self::Rec>> {
match self.as_inner().term {
Term::Placeholder(ref tp) => Some(tp),
_ => None,
}
}
fn get_blob(&self) -> Option<&Self::Blob> {
match self.as_inner().term {
Term::Blob(ref b) => Some(b),
_ => None,
}
}
fn get_string(&self) -> Option<String> {
use utils::string_unescape;
match self.as_inner().term {
Term::Application(ref c, ref r) if r.is_empty() && c.starts_with('"') &&
c.ends_with('"') => Some(string_unescape(c)),
_ => None,
}
}
fn get_tuple(&self) -> Option<&[Self::Rec]> {
match self.as_inner().term {
Term::Application(ref c, ref r) if c.is_empty() => Some(r),
_ => None,
}
}
}
impl<Rec, B> ATerm for ATermInner<Rec, B>
where Rec: Borrow<ATermInner<Rec, B>>
{
type Rec = Rec;
type Blob = B;
#[inline]
fn into_inner(self) -> ATermInner<Rec, B> {
self
}
#[inline]
fn as_inner(&self) -> &ATermInner<Self::Rec, Self::Blob> {
self
}
}
impl<ATerm, B> fmt::Display for ATermInner<ATerm, B>
where ATerm: ATermWrite,
B: ATermWrite
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.to_ascii(f)
}
}