use super::*;
pub trait TermMatcher {
type Term: Term + ?Sized;
fn matches<T2: Term + ?Sized>(&self, term: &T2) -> bool;
fn constant(&self) -> Option<&Self::Term> {
None
}
fn gn(self) -> TermMatcherGn<Self>
where
Self: Sized,
{
TermMatcherGn(self)
}
fn matcher_ref(&self) -> MatcherRef<'_, Self> {
MatcherRef(self)
}
}
impl<T> TermMatcher for Option<T>
where
T: Term,
{
type Term = T;
fn matches<T2: Term + ?Sized>(&self, term: &T2) -> bool {
match self {
Some(mine) => mine.eq(term.borrow_term()),
None => false,
}
}
fn constant(&self) -> Option<&Self::Term> {
self.as_ref()
}
}
impl<T, const N: usize> TermMatcher for [T; N]
where
T: Term,
{
type Term = T;
fn matches<T2: Term + ?Sized>(&self, term: &T2) -> bool {
self.iter().any(|mine| mine.eq(term.borrow_term()))
}
fn constant(&self) -> Option<&Self::Term> {
if N == 1 {
Some(&self[0])
} else {
None
}
}
}
impl<T> TermMatcher for &[T]
where
T: Term,
{
type Term = T;
fn matches<T2: Term + ?Sized>(&self, term: &T2) -> bool {
self.iter().any(|mine| mine.eq(term.borrow_term()))
}
fn constant(&self) -> Option<&Self::Term> {
if self.len() == 1 {
Some(&self[0])
} else {
None
}
}
}
impl<S, P, O> TermMatcher for (S, P, O)
where
S: TermMatcher,
P: TermMatcher,
O: TermMatcher,
{
type Term = S::Term;
fn matches<T2: Term + ?Sized>(&self, term: &T2) -> bool {
let (sm, pm, om) = self;
match term.triple() {
None => false,
Some(t) => t.matched_by(sm.matcher_ref(), pm.matcher_ref(), om.matcher_ref()),
}
}
}
impl TermMatcher for TermKind {
type Term = SimpleTerm<'static>;
fn matches<T2: Term + ?Sized>(&self, term: &T2) -> bool {
term.kind() == *self
}
}
impl<F> TermMatcher for F
where
F: Fn(SimpleTerm<'_>) -> bool + ?Sized,
{
type Term = SimpleTerm<'static>;
fn matches<T2: Term + ?Sized>(&self, term: &T2) -> bool {
(self)(term.as_simple())
}
}