fall 0.1.2

An easily embeddable, futures-friendly logic engine.
Documentation
use std::collections::HashSet;
use std::sync::Arc;

use futures::prelude::*;

use ast::{Lit, Rules, Term};
use cst;
use eval::Env;
use util::gensym;

#[test]
fn execution() {
    let rules = r#"
        taught(socrates, plato).
        taught(plato, aristotle).
        taught(aristotle, alexander).

        path(X, X).
        path(X, Z) :- taught(X, Y), path(Y, Z).
    "#;
    let rules = rules.parse::<Rules>().unwrap();

    let ans_var = gensym();
    let mut scope = vec![("X".to_string(), ans_var)].into_iter().collect();
    let query = "path(plato, X)"
        .parse::<cst::Lit>()
        .unwrap()
        .to_ast(&mut HashSet::new(), &mut scope);

    let env = Env::new_self_contained::<()>(&rules);
    let mut results = env
        .solve(query, 10)
        .map(|s| s.get(ans_var).cloned().unwrap())
        .collect()
        .wait()
        .unwrap();
    results.sort();

    let expected = vec!["alexander", "aristotle", "plato"]
        .into_iter()
        .map(|s| Arc::new(Term::Lit(Lit(s.into(), vec![]))))
        .collect::<Vec<_>>();
    assert_eq!(results, expected);
}

#[test]
fn parse_terms() {
    assert_eq!(
        "foo".parse::<cst::Term>().unwrap(),
        cst::Term::Lit(cst::Lit("foo".to_string(), vec![]))
    );
    assert_eq!(
        "Bar".parse::<cst::Term>().unwrap(),
        cst::Term::Var("Bar".to_string())
    );
    assert_eq!("_".parse::<cst::Term>().unwrap(), cst::Term::Any);
    assert_eq!(
        "baz(1, 'Quux')".parse::<cst::Term>().unwrap(),
        cst::Term::Lit(cst::Lit(
            "baz".to_string(),
            vec![
                cst::Term::Num(1),
                cst::Term::Lit(cst::Lit("Quux".to_string(), vec![])),
            ]
        ))
    );
}