1extern crate rand;
2
3use std::sync::Arc;
5use std::hash::{Hash, Hasher};
6use std::cmp::{PartialOrd, Ord, Ordering};
7use std::collections::hash_map::DefaultHasher;
8use std::sync::atomic::{self, AtomicU64};
9use std::fmt;
10
11pub mod pattern;
12pub mod variable;
13pub mod macros;
14mod index;
15
16pub use pattern::{Pattern, PatternKind, PatternLike, PatternLikeKind};
17pub use variable::Var;
18pub use index::*;
19
20pub trait Ranked {
21 fn arity(&self) -> usize;
22}
23
24pub struct Term<F> {
28 f: F,
29 subs: Arc<Vec<Self>>,
30 hash: AtomicU64
31}
32
33impl<F: fmt::Debug> fmt::Debug for Term<F> {
34 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35 write!(f, "{:?}({:?})", self.f, self.subs)
36 }
37}
38
39impl<F: fmt::Display> fmt::Display for Term<F> {
40 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
41 self.f.fmt(f)?;
42 match self.subs.split_first() {
43 Some((head, tail)) => {
44 write!(f, "(")?;
45 head.fmt(f)?;
46 for e in tail.iter() {
47 write!(f, ", ")?;
48 e.fmt(f)?;
49 }
50 write!(f, ")")
51 },
52 None => Ok(())
53 }
54 }
55}
56
57impl<F> Term<F> {
58 pub fn new(f: F, subs: Vec<Self>) -> Self where F: Clone {
59 Term {
60 f: f,
61 subs: Arc::new(subs),
62 hash: AtomicU64::new(0)
63 }
64 }
65
66 pub fn from_slice(f: F, subs: &[Self]) -> Self where F: Clone {
67 Term {
68 f: f,
69 subs: Arc::new(subs.iter().map(|p| p.clone()).collect()),
70 hash: AtomicU64::new(0)
71 }
72 }
73
74 pub fn symbol(&self) -> &F {
75 &self.f
76 }
77
78 pub fn sub_terms(&self) -> &Vec<Self> {
88 &self.subs
89 }
90
91 pub fn depth(&self) -> u64 {
98 let mut depth = 0;
99 for sub in self.subs.iter() {
100 let d = sub.depth() + 1;
101 if d > depth {
102 depth = d
103 }
104 }
105
106 depth
107 }
108
109 fn random_with_zeros(zero_alphabet: &[F], alphabet: &[F], max_depth: u64) -> Term<F> where F: Clone + Ranked {
110 let i: usize = rand::random();
111 let (f, arity, next_depth) = if max_depth == 0 {
112 let f: &F = &zero_alphabet[i%zero_alphabet.len()];
113 (f.clone(), 0, 0)
114 } else {
115 let f: &F = &alphabet[i%alphabet.len()];
116 (f.clone(), f.arity(), max_depth-1)
117 };
118
119 let mut subs = Vec::with_capacity(arity);
120 for _ in 0..arity {
121 subs.push(Self::random_with_zeros(zero_alphabet, alphabet, next_depth))
122 }
123
124 Term {
125 f: f,
126 subs: Arc::new(subs),
127 hash: AtomicU64::new(0)
128 }
129 }
130
131 pub fn random(alphabet: &[F], max_depth: u64) -> Term<F> where F: Clone + Ranked {
134 let mut zeros = Vec::with_capacity(alphabet.len());
135 for f in alphabet.iter() {
136 if f.arity() == 0 {
137 zeros.push(f.clone())
138 }
139 }
140
141 assert!(!zeros.is_empty());
142 Self::random_with_zeros(&zeros, alphabet, max_depth)
143 }
144}
145
146impl<F, X> PatternLike<F, X> for Term<F> {
147 fn kind(&self) -> PatternLikeKind<F, X, Self> {
148 PatternLikeKind::Cons(&self.f, &self.subs)
149 }
150}
151
152impl<F: Clone> Clone for Term<F> {
153 fn clone(&self) -> Term<F> {
154 Term {
155 f: self.f.clone(),
156 subs: self.subs.clone(),
157 hash: AtomicU64::new(self.hash.load(atomic::Ordering::Relaxed)),
158 }
159 }
160}
161
162impl<F: PartialEq> PartialEq for Term<F> {
163 fn eq(&self, other: &Term<F>) -> bool {
164 self.f == other.f && self.subs == other.subs
165 }
166}
167
168impl<F: PartialEq + Eq> Eq for Term<F> {}
169
170impl<F: Hash> Hash for Term<F> {
171 fn hash<H: Hasher>(&self, state: &mut H) {
172 let mut h = self.hash.load(atomic::Ordering::Relaxed);
173 if h == 1 { loop {
175 h = self.hash.load(atomic::Ordering::Relaxed);
176 if h != 1 {
177 break;
178 }
179 }
180 }
181 if h == 0 {
182 self.hash.store(1, atomic::Ordering::Relaxed);
184
185 let mut hasher = DefaultHasher::new();
186 self.f.hash(&mut hasher);
187 for sub in self.subs.iter() {
188 Term::<F>::hash(sub, &mut hasher)
189 }
190 h = hasher.finish();
191 if h <= 1 { h = 2;
193 }
194 self.hash.store(h, atomic::Ordering::Relaxed);
195 }
196 h.hash(state)
197 }
198}
199
200impl<F: Ord> PartialOrd for Term<F> {
201 fn partial_cmp(&self, other: &Term<F>) -> Option<Ordering> {
202 Some(self.cmp(other))
203 }
204}
205
206impl<F: Ord> Ord for Term<F> {
207 fn cmp(&self, other: &Term<F>) -> Ordering {
208 match self.depth().cmp(&other.depth()) {
209 Ordering::Equal => {
210 match self.f.cmp(&other.f) {
211 Ordering::Equal => {
212 match self.subs.len().cmp(&other.subs.len()) {
213 Ordering::Equal => {
214 for (i, a) in self.subs.iter().enumerate() {
215 let b = &other.subs[i];
216 match a.cmp(b) {
217 Ordering::Equal => (),
218 ord => return ord
219 }
220 }
221
222 Ordering::Equal
223 },
224 ord => ord
225 }
226 },
227 ord => ord
228 }
229 },
230 ord => ord
231 }
232 }
233}