automatic_relations/
lib.rs

1#![feature(trait_alias)]
2
3extern crate terms;
4extern crate tree_automata as ta;
5
6use std::ops::Index;
7use std::cmp::{PartialOrd, Ord, Ordering};
8use std::slice::SliceIndex;
9use std::fmt;
10use terms::Term;
11use ta::Ranked;
12
13pub mod convolution;
14pub mod pattern;
15
16pub use convolution::Convolution;
17pub use pattern::ConvolutedPattern;
18
19#[derive(Debug, PartialEq, Eq, Clone, Hash)]
20pub struct Convoluted<T>(pub Vec<MaybeBottom<T>>);
21
22impl<T> Convoluted<T> {
23    pub fn iter(&self) -> std::slice::Iter<MaybeBottom<T>> {
24        self.0.iter()
25    }
26
27    pub fn len(&self) -> usize {
28        self.0.len()
29    }
30
31    pub fn signature(&self) -> u32 {
32        let mut signature: u32 = 0;
33        for t in &self.0 {
34            signature <<= 1;
35            if let MaybeBottom::Some(_) = t {
36                signature |= 1;
37            }
38        }
39
40        signature
41    }
42}
43
44impl<T, I> Index<I> for Convoluted<T> where I: SliceIndex<[MaybeBottom<T>]> {
45    type Output = I::Output;
46
47    fn index(&self, i: I) -> &I::Output {
48        self.0.index(i)
49    }
50}
51
52impl<T: Ord> Ord for Convoluted<T> {
53    fn cmp(&self, other: &Convoluted<T>) -> Ordering {
54        match self.0.len().cmp(&other.0.len()) {
55            Ordering::Equal => {
56                for (i, a) in self.0.iter().enumerate() {
57                    let b = &other.0[i];
58                    match a.cmp(b) {
59                        Ordering::Equal => (),
60                        ord => return ord
61                    }
62                }
63
64                Ordering::Equal
65            },
66            ord => ord
67        }
68    }
69}
70
71impl<T: Ord> PartialOrd for Convoluted<T> {
72    fn partial_cmp(&self, other: &Convoluted<T>) -> Option<Ordering> {
73        Some(self.cmp(other))
74    }
75}
76
77#[derive(Debug, PartialEq, Eq, Clone, Hash)]
78pub enum MaybeBottom<T> {
79    Bottom,
80    Some(T)
81}
82
83impl<T: PartialEq> PartialEq<T> for MaybeBottom<T> {
84    fn eq(&self, other: &T) -> bool {
85        match self {
86            MaybeBottom::Some(t) => t == other,
87            _ => false
88        }
89    }
90}
91
92impl<T: Ord> Ord for MaybeBottom<T> {
93    fn cmp(&self, other: &MaybeBottom<T>) -> Ordering {
94        match (self, other) {
95            (MaybeBottom::Some(a), MaybeBottom::Some(b)) => a.cmp(b),
96            (MaybeBottom::Some(_), _) => Ordering::Greater,
97            (MaybeBottom::Bottom, MaybeBottom::Bottom) => Ordering::Equal,
98            _ => Ordering::Less
99        }
100    }
101}
102
103impl<T: Ord> PartialOrd for MaybeBottom<T> {
104    fn partial_cmp(&self, other: &MaybeBottom<T>) -> Option<Ordering> {
105        Some(self.cmp(other))
106    }
107}
108
109pub trait Relation<F: Ranked> {
110    /// Check if the relation contains the given terms.
111    /// The number of term must be equal to the arity of the relation.
112    fn contains(&self, terms: &[&Term<F>]) -> bool;
113}
114
115impl<T: fmt::Display> fmt::Display for MaybeBottom<T> {
116    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
117        match self {
118            MaybeBottom::Bottom => write!(f, "⟘"),
119            MaybeBottom::Some(t) => t.fmt(f)
120        }
121    }
122}
123
124impl<T: fmt::Display> fmt::Display for Convoluted<T> {
125    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
126        match self.0.split_first() {
127            Some((head, tail)) => {
128                head.fmt(f)?;
129                for e in tail.iter() {
130                    write!(f, "⊗")?;
131                    e.fmt(f)?;
132                }
133                Ok(())
134            },
135            None => Ok(())
136        }
137    }
138}