use std::cmp::Ordering;
use std::collections::Bound;
use std::fmt::{Display, Formatter, Result};
use std::iter::Iterator;
#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub enum E {
I(i32),
D(f64),
S(String),
T(Tuple),
Any,
None,
}
impl Eq for E {}
impl Ord for E {
fn cmp(&self, other: &E) -> Ordering {
match (self, other) {
(&E::Any, &E::Any) => Ordering::Equal,
(&E::Any, _) => Ordering::Less,
(_, &E::Any) => Ordering::Greater,
(&E::None, &E::None) => Ordering::Equal,
(&E::None, _) => Ordering::Greater,
(_, &E::None) => Ordering::Less,
(&E::I(ref a), &E::I(ref b)) => a.cmp(b),
(&E::I(_), _) => Ordering::Less,
(_, &E::I(_)) => Ordering::Greater,
(&E::D(ref a), &E::D(ref b)) => {
if a < b {
Ordering::Less
} else if a > b {
Ordering::Greater
} else {
Ordering::Equal
}
}
(&E::D(_), _) => Ordering::Less,
(_, &E::D(_)) => Ordering::Greater,
(&E::S(ref a), &E::S(ref b)) => a.cmp(b),
(&E::S(_), _) => Ordering::Less,
(_, &E::S(_)) => Ordering::Greater,
(&E::T(ref a), &E::T(ref b)) => a.cmp(b),
}
}
}
impl Display for E {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
write!(
f,
"{}",
match self {
E::I(ref i) => i.to_string(),
E::D(ref d) => d.to_string(),
E::S(ref s) => s.to_string(),
E::T(ref t) => t.to_string(),
E::Any => "_".to_string(),
E::None => "nil".to_string(),
}
)
}
}
impl E {
pub fn str<S: Into<String>>(s: S) -> E {
E::S(s.into())
}
pub fn is_defined(&self) -> bool {
match self {
E::I(_) => true,
E::D(_) => true,
E::S(_) => true,
E::Any => false,
E::None => false,
E::T(ref t) => t.is_defined(),
}
}
pub fn matches(&self, other: &E) -> bool {
let error = 0.001;
match (self, other) {
(&E::I(ref a), &E::I(ref b)) => a == b,
(&E::D(ref a), &E::D(ref b)) => (a - b).abs() < error,
(&E::S(ref a), &E::S(ref b)) => a == b,
(&E::T(ref a), &E::T(ref b)) => a.matches(b),
(&E::Any, &E::Any) => false,
(&E::Any, &E::None) => false,
(&E::Any, _) => true,
(&E::None, _) => false,
(_, &E::Any) => true,
_ => false,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Tuple(Vec<E>);
impl Display for Tuple {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
write!(
f,
"({})",
self.0
.iter()
.map(|x| x.to_string())
.collect::<Vec<String>>()
.join(",")
)
}
}
impl Tuple {
pub fn new(elements: &[E]) -> Tuple {
Tuple(elements.to_vec())
}
pub fn from_vec(v: Vec<E>) -> Tuple {
Tuple(v)
}
pub fn first(&self) -> &E {
&self.0[0]
}
pub fn rest(&self) -> Tuple {
Tuple::new(&self.0[1..])
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn is_defined(&self) -> bool {
self.0.iter().all(|ref x| x.is_defined())
}
pub fn matches(&self, other: &Tuple) -> bool {
(self.is_empty() == other.is_empty())
&& self
.0
.iter()
.zip(other.0.iter())
.all(|(ref x, ref y): (&E, &E)| x.matches(y))
}
pub fn range(&self) -> (Bound<Tuple>, Bound<Tuple>) {
if self.is_defined() {
(Bound::Included(self.clone()), Bound::Excluded(self.clone()))
} else {
(
Bound::Excluded(self.clone()),
Bound::Excluded(self.terminator()),
)
}
}
fn terminator(&self) -> Tuple {
Tuple(
self.0
.iter()
.map(|x| match x {
&E::Any => E::None,
&E::T(ref t) => E::T(t.terminator()),
e => e.clone(),
})
.collect::<Vec<E>>(),
)
}
}
#[macro_export]
macro_rules! tuple {
($($x:expr),*) => (
$crate::tuple::Tuple::new(&[$($x), *])
);
($($x:expr,)*) => (tuple![$($x),*])
}