1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
use std::fmt::{Display, Formatter}; use std::fmt::Error; pub trait Predicate<T>: Display where T: Display { fn name(&self) -> &str; fn len(&self) -> usize; fn ids(&self) -> &Vec<T>; } pub struct Pred<'a, T> { name: &'a str, ids: Vec<T>, } pub enum ID<'a> { Literal(&'a str), Variable(&'a str), } pub enum Stmt<'a> { Fact(Pred<'a, &'a str>), Rule(Pred<'a, ID<'a>>, Vec<Pred<'a, ID<'a>>>), Query(Pred<'a, ID<'a>>), } impl<'a> Display for Stmt<'a> { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { match *self { Stmt::Fact(ref pred) => write!(f, "{}.", pred), Stmt::Rule(ref head, ref tail) => { write!(f, "{} :- ", head).unwrap(); tail.iter().fold(true, |first, elem| { if !first { write!(f, ", ").unwrap(); } write!(f, "{}", elem).unwrap(); false }); write!(f, ".") } Stmt::Query(ref pred) => write!(f, "{}?", pred), } } } impl<'a, T> Display for Pred<'a, T> where T: Display { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { write!(f, "{}(", self.name).unwrap(); for (i, ch) in self.ids.iter().enumerate() { if i == 0 { write!(f, "{}", ch).unwrap(); } else { write!(f, ",{}", ch).unwrap(); } } write!(f, ")") } } impl<'a> Display for ID<'a> { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { match *self { ID::Literal(ref x) => write!(f, "'{}'", x), ID::Variable(ref x) => write!(f, "{}", x), } } } impl<'a, T> Predicate<T> for Pred<'a, T> where T: Display { fn len(&self) -> usize { self.ids.len() } fn name(&self) -> &str { self.name } fn ids(&self) -> &Vec<T> { &self.ids } } #[cfg(test)] mod tests { use super::{Stmt, ID, Pred}; #[test] fn it_works() { let test = Stmt::Query(Pred { name: "foo", ids: vec![ID::Literal("bar"), ID::Literal("baz")], }); let string = format!("{}", test); assert_eq!(string, "foo('bar','baz')?"); } }