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')?");
    }
}