1use state::{Unif, Var, State, PossibleStates};
6use std::marker::PhantomData;
7
8pub trait Goal<T> where T: PartialEq + Unif<T> {
11 fn eval(&self, state: &State<T>) -> PossibleStates<T>;
12}
13
14
15pub struct Fail<T> where T: PartialEq + Unif<T> {
17 _m: PhantomData<T>,
18}
19
20impl<T> Goal<T> for Fail<T> where T: PartialEq + Unif<T> {
21 fn eval(&self, _: &State<T>) -> PossibleStates<T> {
22 Vec::with_capacity(0)
23 }
24}
25
26pub fn fail<T>() -> Fail<T> where T: PartialEq + Unif<T> {
28 Fail { _m: PhantomData }
29}
30
31
32pub struct UnifyVal<T> where T: PartialEq + Unif<T> {
34 var: Var,
35 val: T,
36}
37
38impl<T> Goal<T> for UnifyVal<T> where T: Clone + Eq + Unif<T> {
39 fn eval(&self, state: &State<T>) -> PossibleStates<T> {
40 state.unify_val(&self.var, self.val.clone())
41 }
42}
43
44pub fn unify_val<T>(var: &Var, val: T) -> UnifyVal<T> where T: PartialEq + Unif<T> {
46 UnifyVal { var: *var, val: val }
47}
48
49
50pub struct UnifyVar<T> where T: PartialEq + Unif<T> {
52 v1: Var,
53 v2: Var,
54 _m: PhantomData<T>,
55}
56
57impl<T> Goal<T> for UnifyVar<T> where T: PartialEq + Unif<T> {
58 fn eval(&self, state: &State<T>) -> PossibleStates<T> {
59 state.unify_var(&self.v1, &self.v2)
60 }
61}
62
63pub fn unify_vars<T>(v1: &Var, v2: &Var) -> UnifyVar<T> where T: PartialEq + Unif<T> {
65 UnifyVar { v1: *v1, v2: *v2, _m: PhantomData }
66}
67
68
69pub struct Conjunction<T, A, B> where T: PartialEq + Unif<T>, A: Goal<T>, B: Goal<T> {
72 a: A,
73 b: B,
74 _m: PhantomData<T>,
75}
76
77impl<T, A, B> Goal<T> for Conjunction<T, A, B> where T: PartialEq + Unif<T>, A: Goal<T>, B: Goal<T> {
78 fn eval(&self, state: &State<T>) -> PossibleStates<T> {
79 let ra = self.a.eval(state);
80 let mut result : Vec<State<T>> = Vec::with_capacity(0);
81 for s in ra {
82 let mut rb = self.b.eval(&s);
83 result.append(&mut rb);
84 }
85 result
86 }
87}
88
89pub fn conj<T, A, B>(a: A, b: B) -> Conjunction<T, A, B> where T: PartialEq + Unif<T>, A: Goal<T>, B: Goal<T> {
91 Conjunction { a: a, b: b, _m: PhantomData }
92}
93
94
95pub struct Disjunction<T, A, B> where T: PartialEq + Unif<T>, A: Goal<T>, B: Goal<T> {
97 a: A,
98 b: B,
99 _m: PhantomData<T>,
100}
101
102impl<T, A, B> Goal<T> for Disjunction<T, A, B> where T: PartialEq + Unif<T>, A: Goal<T>, B: Goal<T> {
103 fn eval(&self, state: &State<T>) -> PossibleStates<T> {
104 let mut da = self.a.eval(state).into_iter();
105 let mut db = self.b.eval(state).into_iter();
106 let mut result: Vec<State<T>> = Vec::with_capacity(0);
107 loop {
108 let sa = da.next();
109 let sb = db.next();
110
111 let mut found = false;
112 if let Some(state) = sa { result.push(state); found = true; }
113 if let Some(state) = sb { result.push(state); found = true; }
114
115 if !found { break; }
116 }
117 result
118 }
119}
120
121pub fn disj<T, A, B>(a: A, b: B) -> Disjunction<T, A, B> where T: PartialEq + Unif<T>, A: Goal<T>, B: Goal<T> {
123 Disjunction { a: a, b: b, _m: PhantomData }
124}
125
126
127pub struct Predicate<'a, T, F> where T: PartialEq + Unif<T>, F: Fn(&State<T>) -> bool + 'a {
129 f: &'a F,
130 _m: PhantomData<T>,
131}
132
133impl<'a, T, F> Goal<T> for Predicate<'a, T, F> where T: PartialEq + Unif<T>, F: Fn(&State<T>) -> bool {
134 fn eval(&self, state: &State<T>) -> PossibleStates<T> {
135 let f = self.f;
136 if f(state) {
137 vec![state.clone()]
138 } else {
139 Vec::with_capacity(0)
140 }
141 }
142}
143
144pub fn pred<'a, T, F>(f: &'a F) -> Predicate<'a, T, F> where T: PartialEq + Unif<T>, F: Fn(&State<T>) -> bool {
146 Predicate { f: f, _m: PhantomData }
147}
148
149
150macro_rules! unif_prim {
151 ( $t:ty ) => {
152 impl Unif<$t> for $t {
153 fn unify(&self, other: &$t, prev: &State<$t>) -> PossibleStates<$t> {
154 if self.eq(other) { vec![prev.clone()] } else { PossibleStates::new() }
155 }
156 }
157 }
158}
159
160unif_prim!(bool);
161unif_prim!(char);
162unif_prim!(f32);
163unif_prim!(f64);
164unif_prim!(i16);
165unif_prim!(i32);
166unif_prim!(i64);
167unif_prim!(i8);
168unif_prim!(isize);
169unif_prim!(u16);
170unif_prim!(u32);
171unif_prim!(u64);
172unif_prim!(u8);
173unif_prim!(usize);
174unif_prim!(String);
175
176
177#[cfg(test)]
178mod tests {
179 use state::{State};
180 use super::{Goal, fail, unify_val, unify_vars, conj, disj, pred};
181
182 #[test]
183 fn test_bind_val() {
184 let s = State::<i32>::empty();
185 let (v, s) = s.make_var();
186
187 let n: i32 = 34;
188 let g = unify_val(&v, n);
189
190 let results = g.eval(&s);
191 assert_eq!(results.len(), 1);
192
193 let val = results[0].get(&v).unwrap();
194 assert_eq!(val, &n);
195 }
196
197 #[test]
198 fn test_bind_var() {
199 let s = State::<i32>::empty();
200 let (a, s) = s.make_var();
201 let (b, s) = s.make_var();
202
203 let n: i32 = 12;
204 let g1 = unify_vars(&a, &b);
205 let g2 = unify_val(&b, n);
206 let g = conj(g1, g2);
207
208 let results = g.eval(&s);
209 assert_eq!(results.len(), 1);
210
211 let val = results[0].get(&a).unwrap();
212 assert_eq!(val, &n);
213 }
214
215 #[test]
216 fn test_conj_fail() {
217 let s = State::<i32>::empty();
218 let (v, s) = s.make_var();
219 let g1 = unify_val(&v, 56);
220 let g2 = fail::<i32>();
221 let g = conj(g1, g2);
222
223 let results = g.eval(&s);
224 assert_eq!(results.len(), 0);
225 }
226
227 #[test]
228 fn test_disj_fail() {
229 let s = State::<i32>::empty();
230 let (v, s) = s.make_var();
231 let g1 = fail::<i32>();
232 let g2 = unify_val(&v, 43);
233 let g = disj(g1, g2);
234
235 let results = g.eval(&s);
236 assert_eq!(results.len(), 1);
237
238 let val = results[0].get(&v).unwrap();
239 assert_eq!(val, &43);
240 }
241
242 #[test]
243 fn test_disj() {
244 let s = State::<i32>::empty();
245 let (a, s) = s.make_var();
246
247 let g1 = unify_val(&a, 123);
248 let g2 = unify_val(&a, 456);
249 let g = disj(g1, g2);
250
251 let results = g.eval(&s);
252 assert_eq!(results.len(), 2);
253
254 let val = results[0].get(&a).unwrap();
255 assert_eq!(val, &123);
256
257 let val = results[1].get(&a).unwrap();
258 assert_eq!(val, &456);
259 }
260
261 #[test]
262 fn test_pred() {
263 let s = State::<i32>::empty();
264 let (a, s) = s.make_var();
265
266 let d = disj(unify_val(&a, 123), unify_val(&a, 987));
267 let f = |s: &State<i32>| match s.get(&a) { Some(n) => *n == 987, None => false };
268 let p = pred(&f);
269 let g = conj(d, p);
270
271 let results = g.eval(&s);
272 assert_eq!(results.len(), 1);
273
274 let val = results[0].get(&a).unwrap();
275 assert_eq!(val, &987);
276 }
277}