]> Repositorios git - scryer-prolog.git/commitdiff
expand remaining tests.
authorMark Thom <[email protected]>
Wed, 17 Jan 2018 02:53:49 +0000 (19:53 -0700)
committerMark Thom <[email protected]>
Wed, 17 Jan 2018 02:53:49 +0000 (19:53 -0700)
src/main.rs
src/tests.rs

index 1a9671add92e600e4642b1dd8aa6f76845314d47..32ef1d884549461cf2aef06096989623968a4287 100644 (file)
@@ -9,773 +9,7 @@ use prolog::machine::*;
 use prolog::parser::toplevel::*;
 
 #[cfg(test)]
-mod tests;    
-    /*
-    #[test]
-    fn test_queries_on_facts() {
-        let mut wam = Machine::new();
-
-        submit(&mut wam, "p(Z, Z).");
-        submit(&mut wam, "clouds(are, nice).");
-
-        // submit returns false on failure, true on success.
-        assert_eq!(submit(&mut wam, "?- p(Z, Z)."), true);
-        assert_eq!(submit(&mut wam, "?- p(Z, z)."), true);
-        assert_eq!(submit(&mut wam, "?- p(Z, w)."), true);
-        assert_eq!(submit(&mut wam, "?- p(z, w)."), false);
-        assert_eq!(submit(&mut wam, "?- p(w, w)."), true);
-        assert_eq!(submit(&mut wam, "?- clouds(Z, Z)."), false);
-        assert_eq!(submit(&mut wam, "?- clouds(are, Z)."), true);
-        assert_eq!(submit(&mut wam, "?- clouds(Z, nice)."), true);
-
-        assert_eq!(submit(&mut wam, "?- p(Z, h(Z, W), f(W))."), false);
-
-        submit(&mut wam, "p(Z, h(Z, W), f(W)).");
-
-        assert_eq!(submit(&mut wam, "?- p(z, h(z, z), f(w))."), false);
-        assert_eq!(submit(&mut wam, "?- p(z, h(z, w), f(w))."), true);
-        assert_eq!(submit(&mut wam, "?- p(z, h(z, W), f(w))."), true);
-        assert_eq!(submit(&mut wam, "?- p(Z, h(Z, w), f(Z))."), true);
-        assert_eq!(submit(&mut wam, "?- p(z, h(Z, w), f(Z))."), false);
-
-        submit(&mut wam, "p(f(X), h(Y, f(a)), Y).");
-
-        assert_eq!(submit(&mut wam, "?- p(Z, h(Z, W), f(W))."), true);
-    }
-
-    #[test]
-    fn test_queries_on_rules() {
-        let mut wam = Machine::new();
-
-        submit(&mut wam, "p(X, Y) :- q(X, Z), r(Z, Y).");
-        submit(&mut wam, "q(q, s).");
-        submit(&mut wam, "r(s, t).");
-
-        assert_eq!(submit(&mut wam, "?- p(X, Y)."), true);
-        assert_eq!(submit(&mut wam, "?- p(q, t)."), true);
-        assert_eq!(submit(&mut wam, "?- p(t, q)."), false);
-        assert_eq!(submit(&mut wam, "?- p(q, T)."), true);
-        assert_eq!(submit(&mut wam, "?- p(Q, t)."), true);
-        assert_eq!(submit(&mut wam, "?- p(t, t)."), false);
-
-        submit(&mut wam, "p(X, Y) :- q(f(f(X)), R), r(S, T).");
-        submit(&mut wam, "q(f(f(X)), r).");
-
-        assert_eq!(submit(&mut wam, "?- p(X, Y)."), true);
-
-        submit(&mut wam, "q(f(f(x)), r).");
-
-        assert_eq!(submit(&mut wam, "?- p(X, Y)."), true);
-
-        submit(&mut wam, "p(X, Y) :- q(X, Y), r(X, Y).");
-        submit(&mut wam, "q(s, t).");
-        submit(&mut wam, "r(X, Y) :- r(a).");
-        submit(&mut wam, "r(a).");
-
-        assert_eq!(submit(&mut wam, "?- p(X, Y)."), true);
-        assert_eq!(submit(&mut wam, "?- p(t, S)."), false);
-        assert_eq!(submit(&mut wam, "?- p(t, s)."), false);
-        assert_eq!(submit(&mut wam, "?- p(s, T)."), true);
-        assert_eq!(submit(&mut wam, "?- p(S, t)."), true);
-
-        submit(&mut wam, "p(f(f(a), g(b), X), g(b), h) :- q(X, Y).");
-        submit(&mut wam, "q(X, Y).");
-
-        assert_eq!(submit(&mut wam, "?- p(f(X, Y, Z), g(b), h)."), true);
-        assert_eq!(submit(&mut wam, "?- p(f(X, g(Y), Z), g(Z), X)."), false);
-        assert_eq!(submit(&mut wam, "?- p(f(X, g(Y), Z), g(Z), h)."), true);
-        assert_eq!(submit(&mut wam, "?- p(Z, Y, X)."), true);
-        assert_eq!(submit(&mut wam, "?- p(f(X, Y, Z), Y, h)."), true);
-
-        submit(&mut wam, "p(_, f(_, Y, _)) :- h(Y).");
-        submit(&mut wam, "h(y).");
-
-        assert_eq!(submit(&mut wam, "?- p(_, f(_, Y, _))."), true);
-        assert_eq!(submit(&mut wam, "?- p(_, f(_, y, _))."), true);
-        assert_eq!(submit(&mut wam, "?- p(_, f(_, z, _))."), false);
-    }
-
-    #[test]
-    fn test_queries_on_predicates() {
-        let mut wam = Machine::new();
-
-        submit(&mut wam, "p(X, a). p(b, X).");
-
-        assert_eq!(submit(&mut wam, "?- p(x, Y)."), true);
-        assert_eq!(submit(&mut wam, "?- p(X, a)."), true);
-        assert_eq!(submit(&mut wam, "?- p(b, X)."), true);
-        assert_eq!(submit(&mut wam, "?- p(X, X)."), true);
-        assert_eq!(submit(&mut wam, "?- p(b, a)."), true);
-        assert_eq!(submit(&mut wam, "?- p(a, b)."), false);
-
-        submit(&mut wam, "p(X, Y, a). p(X, a, Y). p(X, Y, a).");
-
-        assert_eq!(submit(&mut wam, "?- p(c, d, X)."), true);
-        assert_eq!(submit(&mut wam, "?- p(a, a, a)."), true);
-        assert_eq!(submit(&mut wam, "?- p(b, c, d)."), false);
-
-        submit(&mut wam, "p(X, a). p(X, Y) :- q(Z), p(X, X).");
-
-        assert_eq!(submit(&mut wam, "?- p(X, Y)."), true);
-        assert_eq!(submit(&mut wam, "?- p(x, a)."), true);
-        assert_eq!(submit(&mut wam, "?- p(X, a)."), true);
-        assert_eq!(submit(&mut wam, "?- p(X, b)."), false);
-
-        submit(&mut wam, "q(z).");
-
-        assert_eq!(submit(&mut wam, "?- p(X, b)."), true);
-        assert_eq!(submit(&mut wam, "?- p(x, a)."), true);
-        assert_eq!(submit(&mut wam, "?- p(X, Y)."), true);
-
-        submit(&mut wam, "p(X, a). p(X, Y) :- q(Y), p(X, X).");
-
-        assert_eq!(submit(&mut wam, "?- p(X, Y)."), true);  // infinite.
-        assert_eq!(submit(&mut wam, "?- p(X, b)."), false); .
-
-        submit(&mut wam, "p(a, z). p(X, Y) :- q(Y), p(X, Y).");
-
-        assert_eq!(submit(&mut wam, "?- p(X, Y)."), true); // infinite.
-        assert_eq!(submit(&mut wam, "?- p(X, z)."), true); // infinite.
-        assert_eq!(submit(&mut wam, "?- p(a, z)."), true);
-        assert_eq!(submit(&mut wam, "?- p(a, X)."), true); // infinite.
-        assert_eq!(submit(&mut wam, "?- p(b, a)."), false);
-
-        submit(&mut wam, "p(X, Y, Z) :- q(X), r(Y), s(Z).
-                          p(a, b, Z) :- q(Z).");
-
-        submit(&mut wam, "q(x).");
-        submit(&mut wam, "r(y).");
-        submit(&mut wam, "s(z).");
-
-        assert_eq!(submit(&mut wam, "?- p(X, Y, Z)."), true);
-        assert_eq!(submit(&mut wam, "?- p(a, b, c)."), false);
-        assert_eq!(submit(&mut wam, "?- p(a, b, C)."), true);
-
-        submit(&mut wam, "p(X) :- q(X). p(X) :- r(X).");
-        submit(&mut wam, "q(X) :- a.");
-        submit(&mut wam, "r(X) :- s(X, t). r(X) :- t(X, u).");
-
-        submit(&mut wam, "s(x, t).");
-        submit(&mut wam, "t(y, u).");
-
-        assert_eq!(submit(&mut wam, "?- p(X)."), true);
-        assert_eq!(submit(&mut wam, "?- p(x)."), true);
-        assert_eq!(submit(&mut wam, "?- p(y)."), true);
-        assert_eq!(submit(&mut wam, "?- p(z)."), false);
-
-        submit(&mut wam, "p(f(f(X)), h(W), Y) :- g(W), h(W), f(X).
-                          p(X, Y, Z) :- h(Y), g(W), z(Z).");
-        submit(&mut wam, "g(f(X)) :- z(X). g(X) :- h(X).");
-        submit(&mut wam, "h(w). h(x). h(z).");
-        submit(&mut wam, "f(s).");
-        submit(&mut wam, "z(Z).");
-
-        assert_eq!(submit(&mut wam, "?- p(X, Y, Z)."), true);
-        assert_eq!(submit(&mut wam, "?- p(X, X, Z)."), true);
-        assert_eq!(submit(&mut wam, "?- p(f(f(Z)), Y, Z)."), true);
-        assert_eq!(submit(&mut wam, "?- p(X, X, X)."), true);
-        assert_eq!(submit(&mut wam, "?- p(X, Y, X)."), true);
-        assert_eq!(submit(&mut wam, "?- p(f(f(X)), h(f(X)), Y)."), false);
-
-        submit(&mut wam, "p(X) :- f(Y), g(Y), i(X, Y).");
-        submit(&mut wam, "g(f(a)). g(f(b)). g(f(c)).");
-        submit(&mut wam, "f(f(a)). f(f(b)). f(f(c)).");
-        submit(&mut wam, "i(X, X).");
-
-        assert_eq!(submit(&mut wam, "?- p(X)."), true);
-
-        submit(&mut wam, "p(X) :- f(f(Y)), g(Y, f(Y)), i(X, f(Y)).");
-        submit(&mut wam, "g(Y, f(Y)) :- g(f(Y)).");
-
-        assert_eq!(submit(&mut wam, "?- p(X)."), true);
-    }
-
-    #[test]
-    fn test_queries_on_cuts() {
-        let mut wam = Machine::new();
-
-        // test shallow cuts.
-        submit(&mut wam, "memberchk(X, [X|_]) :- !.
-                          memberchk(X, [_|Xs]) :- memberchk(X, Xs).");
-
-        assert_eq!(submit(&mut wam, "?- memberchk(X, [a,b,c])."), true);
-        assert_eq!(submit(&mut wam, "?- memberchk([X,X], [a,b,c,[d,e],[d,d]])."), true);
-        assert_eq!(submit(&mut wam, "?- memberchk([X,X], [a,b,c,[D,d],[e,e]])."), true);
-        assert_eq!(submit(&mut wam, "?- memberchk([X,X], [a,b,c,[e,d],[f,e]])."), false);
-        assert_eq!(submit(&mut wam, "?- memberchk([X,X,Y], [a,b,c,[e,d],[f,e]])."), false);
-        assert_eq!(submit(&mut wam, "?- memberchk([X,X,Y], [a,b,c,[e,e,d],[f,e]])."), true);
-
-        // test deep cuts.
-        submit(&mut wam, "commit :- a, !.");
-
-        assert_eq!(submit(&mut wam, "?- commit."), false);
-
-        submit(&mut wam, "a.");
-
-        assert_eq!(submit(&mut wam, "?- commit."), true);
-
-        submit(&mut wam, "commit(X) :- a(X), !.");
-
-        assert_eq!(submit(&mut wam, "?- commit(X)."), false);
-
-        submit(&mut wam, "a(x).");
-
-        assert_eq!(submit(&mut wam, "?- commit(X)."), true);
-
-        submit(&mut wam, "a :- b, !, c. a :- d.");
-
-        assert_eq!(submit(&mut wam, "?- a."), false);
-
-        submit(&mut wam, "b.");
-
-        assert_eq!(submit(&mut wam, "?- a."), false);
-
-        submit(&mut wam, "d.");
-
-        // we've committed to the first clause since the query on b
-        // succeeds, so we expect failure here.
-        assert_eq!(submit(&mut wam, "?- a."), false);
-
-        submit(&mut wam, "c.");
-
-        assert_eq!(submit(&mut wam, "?- a."), true);
-
-        submit(&mut wam, "a(X) :- b, !, c(X). a(X) :- d(X).");
-
-        assert_eq!(submit(&mut wam, "?- a(X)."), false);
-
-        submit(&mut wam, "c(c).");
-        submit(&mut wam, "d(d).");
-
-        assert_eq!(submit(&mut wam, "?- a(X)."), true);
-
-        submit(&mut wam, "b.");
-
-        assert_eq!(submit(&mut wam, "?- a(X)."), true);
-
-        wam.clear();
-
-        assert_eq!(submit(&mut wam, "?- c(X)."), false);
-
-        submit(&mut wam, "a(X) :- b, c(X), !. a(X) :- d(X).");
-        submit(&mut wam, "b.");
-
-        assert_eq!(submit(&mut wam, "?- a(X)."), false);
-
-        submit(&mut wam, "d(d).");
-
-        assert_eq!(submit(&mut wam, "?- a(X)."), true);
-
-        submit(&mut wam, "c(c).");
-
-        assert_eq!(submit(&mut wam, "?- a(X)."), true);
-    }
-
-    #[test]
-    fn test_queries_on_lists() {
-        let mut wam = Machine::new();
-
-        submit(&mut wam, "p([Z, W]).");
-
-        assert_eq!(submit(&mut wam, "?- p([Z, Z])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Z, W, Y])."), false);
-        assert_eq!(submit(&mut wam, "?- p([Z | W])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Z | [Z]])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Z | [W]])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Z | []])."), false);
-
-        submit(&mut wam, "p([Z, Z]).");
-
-        assert_eq!(submit(&mut wam, "?- p([Z, Z])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Z, W, Y])."), false);
-        assert_eq!(submit(&mut wam, "?- p([Z | W])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Z | [Z]])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Z | [W]])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Z | []])."), false);
-
-        submit(&mut wam, "p([Z]).");
-
-        assert_eq!(submit(&mut wam, "?- p([Z, Z])."), false);
-        assert_eq!(submit(&mut wam, "?- p([Z, W, Y])."), false);
-        assert_eq!(submit(&mut wam, "?- p([Z | W])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Z | [Z]])."), false);
-        assert_eq!(submit(&mut wam, "?- p([Z | [W]])."), false);
-        assert_eq!(submit(&mut wam, "?- p([Z | []])."), true);
-
-        submit(&mut wam, "member(X, [X|Xs]).
-                          member(X, [Y|Xs]) :- member(X, Xs).");
-
-        assert_eq!(submit(&mut wam, "?- member(a, [c, [X, Y]])."), false);
-        assert_eq!(submit(&mut wam, "?- member(c, [a, [X, Y]])."), false);
-        assert_eq!(submit(&mut wam, "?- member(a, [a, [X, Y]])."), true);
-        assert_eq!(submit(&mut wam, "?- member(a, [X, Y, Z])."), true);
-        assert_eq!(submit(&mut wam, "?- member([X, X], [a, [X, Y]])."), true);
-        assert_eq!(submit(&mut wam, "?- member([X, X], [a, [b, c], [b, b], [Z, x], [d, f]])."), true);
-        assert_eq!(submit(&mut wam, "?- member([X, X], [a, [b, c], [b, d], [foo, x], [d, f]])."), false);
-        assert_eq!(submit(&mut wam, "?- member([X, Y], [a, [b, c], [b, b], [Z, x], [d, f]])."), true);
-        assert_eq!(submit(&mut wam, "?- member([X, Y, Y], [a, [b, c], [b, b], [Z, x], [d, f]])."), false);
-        assert_eq!(submit(&mut wam, "?- member([X, Y, Z], [a, [b, c], [b, b], [Z, x], [d, f]])."), false);
-    }
-
-    #[test]
-    fn test_queries_on_indexed_predicates() {
-        let mut wam = Machine::new();
-
-        submit(&mut wam, "p(a) :- a.
-                          p(b) :- b, f(X).
-                          p(c) :- c, g(X).
-                          p(f(a)) :- a.
-                          p(g(b, c)) :- b.
-                          p(g(b)) :- b.
-                          p([a|b]) :- a.
-                          p([]).
-                          p(X) :- x.
-                          p([c, d, e]).");
-
-        assert_eq!(submit(&mut wam, "?- p(a)."), false);
-        assert_eq!(submit(&mut wam, "?- p(b)."), false);
-        assert_eq!(submit(&mut wam, "?- p(c)."), false);
-        assert_eq!(submit(&mut wam, "?- p(f(a))."), false);
-        assert_eq!(submit(&mut wam, "?- p(g(b, X))."), false);
-        assert_eq!(submit(&mut wam, "?- p(g(Y, X))."), false);
-        assert_eq!(submit(&mut wam, "?- p(g(Y, c))."), false);
-        assert_eq!(submit(&mut wam, "?- p(g(b))."), false);
-        assert_eq!(submit(&mut wam, "?- p([])."), true);
-        assert_eq!(submit(&mut wam, "?- p([c, d, e])."), true);
-        assert_eq!(submit(&mut wam, "?- p([c, d | X])."), true);
-        assert_eq!(submit(&mut wam, "?- p([c|X])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Y|X])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Y|[d|Xs]])."), true);
-
-        submit(&mut wam, "a.");
-
-        assert_eq!(submit(&mut wam, "?- p(a)."), true);
-        assert_eq!(submit(&mut wam, "?- p(b)."), false);
-        assert_eq!(submit(&mut wam, "?- p(c)."), false);
-        assert_eq!(submit(&mut wam, "?- p(f(a))."), true);
-        assert_eq!(submit(&mut wam, "?- p(g(b, X))."), false);
-        assert_eq!(submit(&mut wam, "?- p(g(Y, X))."), false);
-        assert_eq!(submit(&mut wam, "?- p(g(Y, c))."), false);
-        assert_eq!(submit(&mut wam, "?- p(g(b))."), false);
-        assert_eq!(submit(&mut wam, "?- p([])."), true);
-        assert_eq!(submit(&mut wam, "?- p([c, d, e])."), true);
-        assert_eq!(submit(&mut wam, "?- p([c, d | X])."), true);
-        assert_eq!(submit(&mut wam, "?- p([c|X])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Y|X])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Y|[d|Xs]])."), true);
-
-        submit(&mut wam, "b.");
-        submit(&mut wam, "f(x).");
-
-        assert_eq!(submit(&mut wam, "?- p(a)."), true);
-        assert_eq!(submit(&mut wam, "?- p(b)."), true);
-        assert_eq!(submit(&mut wam, "?- p(c)."), false);
-        assert_eq!(submit(&mut wam, "?- p(f(a))."), true);
-        assert_eq!(submit(&mut wam, "?- p(g(b, X))."), true);
-        assert_eq!(submit(&mut wam, "?- p(g(Y, X))."), true);
-        assert_eq!(submit(&mut wam, "?- p(g(Y, c))."), true);
-        assert_eq!(submit(&mut wam, "?- p(g(b))."), true);
-        assert_eq!(submit(&mut wam, "?- p([])."), true);
-        assert_eq!(submit(&mut wam, "?- p([c, d, e])."), true);
-        assert_eq!(submit(&mut wam, "?- p([c, d | X])."), true);
-        assert_eq!(submit(&mut wam, "?- p([c|X])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Y|X])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Y|[d|Xs]])."), true);
-
-        submit(&mut wam, "c.");
-        submit(&mut wam, "g(X).");
-
-        assert_eq!(submit(&mut wam, "?- p(a)."), true);
-        assert_eq!(submit(&mut wam, "?- p(b)."), true);
-        assert_eq!(submit(&mut wam, "?- p(c)."), true);
-        assert_eq!(submit(&mut wam, "?- p(f(a))."), true);
-        assert_eq!(submit(&mut wam, "?- p(g(b, X))."), true);
-        assert_eq!(submit(&mut wam, "?- p(g(Y, X))."), true);
-        assert_eq!(submit(&mut wam, "?- p(g(Y, c))."), true);
-        assert_eq!(submit(&mut wam, "?- p(g(b))."), true);
-        assert_eq!(submit(&mut wam, "?- p([])."), true);
-        assert_eq!(submit(&mut wam, "?- p([c, d, e])."), true);
-        assert_eq!(submit(&mut wam, "?- p([c, d | X])."), true);
-        assert_eq!(submit(&mut wam, "?- p([c|X])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Y|X])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Y|[d|Xs]])."), true);
-        assert_eq!(submit(&mut wam, "?- p(blah)."), false);
-
-        submit(&mut wam, "x.");
-
-        assert_eq!(submit(&mut wam, "?- p(a)."), true);
-        assert_eq!(submit(&mut wam, "?- p(b)."), true);
-        assert_eq!(submit(&mut wam, "?- p(c)."), true);
-        assert_eq!(submit(&mut wam, "?- p(true(a))."), true);
-        assert_eq!(submit(&mut wam, "?- p(g(b, X))."), true);
-        assert_eq!(submit(&mut wam, "?- p(g(Y, X))."), true);
-        assert_eq!(submit(&mut wam, "?- p(g(Y, c))."), true);
-        assert_eq!(submit(&mut wam, "?- p(g(b))."), true);
-        assert_eq!(submit(&mut wam, "?- p([])."), true);
-        assert_eq!(submit(&mut wam, "?- p([c, d, e])."), true);
-        assert_eq!(submit(&mut wam, "?- p([c, d | X])."), true);
-        assert_eq!(submit(&mut wam, "?- p([c|X])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Y|X])."), true);
-        assert_eq!(submit(&mut wam, "?- p([Y|[d|Xs]])."), true);
-        assert_eq!(submit(&mut wam, "?- p(blah)."), true);
-
-        submit(&mut wam, "ind_call(or(X, Y)) :- ind_call(X).
-                          ind_call(trace) :- trace.
-                          ind_call(or(X, Y)) :- ind_call(Y).
-                          ind_call(notrace) :- notrace.
-                          ind_call(nl) :- nl.
-                          ind_call(X) :- builtin(X).
-                          ind_call(X) :- extern(X).
-                          ind_call(ind_call(X)) :- ind_call(X).
-                          ind_call(repeat).
-                          ind_call(repeat) :- ind_call(repeat).
-                          ind_call(false).");
-
-        assert_eq!(submit(&mut wam, "?- ind_call(repeat)."), true);
-        assert_eq!(submit(&mut wam, "?- ind_call(false)."), true);
-        assert_eq!(submit(&mut wam, "?- ind_call(ind_call(repeat))."), true);
-        assert_eq!(submit(&mut wam, "?- ind_call(ind_call(false))."), true);
-        assert_eq!(submit(&mut wam, "?- ind_call(notrace)."), false);
-        assert_eq!(submit(&mut wam, "?- ind_call(nl)."), false);
-        assert_eq!(submit(&mut wam, "?- ind_call(builtin(X))."), false);
-        assert_eq!(submit(&mut wam, "?- ind_call(extern(X))."), false);
-
-        submit(&mut wam, "notrace.");
-        submit(&mut wam, "nl.");
-
-        assert_eq!(submit(&mut wam, "?- ind_call(repeat)."), true);
-        assert_eq!(submit(&mut wam, "?- ind_call(false)."), true);
-        assert_eq!(submit(&mut wam, "?- ind_call(ind_call(repeat))."), true);
-        assert_eq!(submit(&mut wam, "?- ind_call(ind_call(false))."), true);
-        assert_eq!(submit(&mut wam, "?- ind_call(notrace)."), true);
-        assert_eq!(submit(&mut wam, "?- ind_call(nl)."), true);
-        assert_eq!(submit(&mut wam, "?- ind_call(builtin(X))."), false);
-        assert_eq!(submit(&mut wam, "?- ind_call(extern(X))."), false);
-
-        submit(&mut wam, "builtin(X).");
-        submit(&mut wam, "extern(x).");
-
-        assert_eq!(submit(&mut wam, "?- ind_call(repeat)."), true);
-        assert_eq!(submit(&mut wam, "?- ind_call(false)."), true);
-        assert_eq!(submit(&mut wam, "?- ind_call(ind_call(repeat))."), true);
-        assert_eq!(submit(&mut wam, "?- ind_call(ind_call(false))."), true);
-        assert_eq!(submit(&mut wam, "?- ind_call(notrace)."), true);
-        assert_eq!(submit(&mut wam, "?- ind_call(nl)."), true);
-        assert_eq!(submit(&mut wam, "?- ind_call(builtin(X))."), true);
-        assert_eq!(submit(&mut wam, "?- ind_call(extern(X))."), true);
-    }
-
-    #[test]
-    fn test_queries_on_conjuctive_queries() {
-        let mut wam = Machine::new();
-
-        submit(&mut wam, "p(a, b).");
-        submit(&mut wam, "q(b, c).");
-
-        assert_eq!(submit(&mut wam, "?- p(X, Y), q(Y, Z)."), true);
-        assert_eq!(submit(&mut wam, "?- p(X, Y), q(Y, X)."), false);
-
-        submit(&mut wam, "p(a, [f(g(X))]).");
-        submit(&mut wam, "q(Y, c).");
-
-        assert_eq!(submit(&mut wam, "?- p(X, Y), q(Y, Z)."), true);
-        assert_eq!(submit(&mut wam, "?- p(X, Y), q(Y, X)."), false);
-
-        submit(&mut wam, "member(X, [X|_]).
-                          member(X, [_|Xs]) :- member(X, Xs).");
-
-        assert_eq!(submit(&mut wam, "?- member(X, [a,b,c]), member(X, [a,b,c])."), true);
-        assert_eq!(submit(&mut wam, "?- member(X, [a,b,c]), member(X, [b,c])."), true);
-        assert_eq!(submit(&mut wam, "?- member(X, [a,c]), member(X, [b,c])."), true);
-        assert_eq!(submit(&mut wam, "?- member(X, [a,b,c,d]), !, member(X, [a,d])."), true);
-        assert_eq!(submit(&mut wam, "?- member(X, [a,b,c,d]), !, member(X, [e])."), false);
-        assert_eq!(submit(&mut wam, "?- member([X,X],[a,b,c,[d,d],[e,d]]),
-                                        member(X, [a,b,c,d,e,f,g]),
-                                        member(Y, [X, a, b, c, d])."),
-                          true);
-        assert_eq!(submit(&mut wam, "?- member([X,X],[a,b,c,[d,d],[e,d]]),
-                                        member(X, [a,b,c,d,e,f,g]),
-                                        !,
-                                        member(Y, [X, a, b, c, d])."),
-                          true);
-
-        submit(&mut wam, "p(a, [f(g(X))]).");
-        submit(&mut wam, "q(Y, c).");
-
-        assert_eq!(submit(&mut wam, "?- p(X, Y), q(Y, Z)."), true);
-        assert_eq!(submit(&mut wam, "?- p(X, Y), q(Y, X)."), false);
-
-        submit(&mut wam, "p(a, [f(g(X))]). p(X, c) :- c.");
-        submit(&mut wam, "c.");
-        submit(&mut wam, "q(Y, c).");
-
-        assert_eq!(submit(&mut wam, "?- p(X, Y), q(Y, Z)."), true);
-        assert_eq!(submit(&mut wam, "?- p(X, Y), !, q(Y, Z)."), true);
-
-        submit(&mut wam, "q([f(g(x))], Z). q([f(g(y))], Y). q([f(g(z))], a).");
-
-        assert_eq!(submit(&mut wam, "?- p(X, Y), q(Y, Z)."), true);
-        assert_eq!(submit(&mut wam, "?- p(X, Y), !, q(Y, Z)."), true);
-        assert_eq!(submit(&mut wam, "?- p(X, Y), !, q(Y, X)."), true);
-
-        submit(&mut wam, "p(X, [f(g(x))]). p(X, [f(g(y))]). p(X, [f(g(z))]).");
-
-        assert_eq!(submit(&mut wam, "?- q(f(X), Y), p(X, Y)."), false);
-        assert_eq!(submit(&mut wam, "?- q(X, Y), p(X, Y)."), true);
-        assert_eq!(submit(&mut wam, "?- p(X, Y), q(X, Y)."), true);
-        assert_eq!(submit(&mut wam, "?- p(X, Y), q(Y, X)."), true);
-        assert_eq!(submit(&mut wam, "?- q(X, Y), p(Y, X)."), true);
-    }
-
-    #[test]
-    fn test_queries_on_call_n()
-    {
-        let mut wam = Machine::new();
-
-        submit(&mut wam, "maplist(Pred, []).
-                          maplist(Pred, [X|Xs]) :- call(Pred, X), maplist(Pred, Xs).");
-        submit(&mut wam, "f(a). f(b). f(c).");
-
-        assert_eq!(submit(&mut wam, "?- maplist(f, [X,Y,Z])."), true);
-        assert_eq!(submit(&mut wam, "?- maplist(f, [a,Y,Z])."), true);
-        assert_eq!(submit(&mut wam, "?- maplist(f, [X,a,b])."), true);
-        assert_eq!(submit(&mut wam, "?- maplist(f, [c,a,b])."), true);
-        assert_eq!(submit(&mut wam, "?- maplist(f, [d,e,f])."), false);
-        assert_eq!(submit(&mut wam, "?- maplist(f, [])."), true);
-        assert_eq!(submit(&mut wam, "?- maplist(f(X), [a,b,c])."), false);
-
-        submit(&mut wam, "f(X) :- call(X), call(X).");
-        submit(&mut wam, "p(x). p(y).");
-
-        assert_eq!(submit(&mut wam, "?- f(p)."), false);
-        assert_eq!(submit(&mut wam, "?- f(p(X))."), true);
-        assert_eq!(submit(&mut wam, "?- f(p(x))."), true);
-        assert_eq!(submit(&mut wam, "?- f(p(w))."), false);
-        assert_eq!(submit(&mut wam, "?- f(p(X, Y))."), false);
-
-        submit(&mut wam, "f(P) :- call(P, X), call(P, Y).");
-
-        assert_eq!(submit(&mut wam, "?- f(p)."), true);
-        assert_eq!(submit(&mut wam, "?- f(non_existent)."), false);
-
-        submit(&mut wam, "f(P, X, Y) :- call(P, X), call(P, Y).");
-
-        assert_eq!(submit(&mut wam, "?- f(p, X, Y)."), true);
-        assert_eq!(submit(&mut wam, "?- f(p, x, Y)."), true);
-        assert_eq!(submit(&mut wam, "?- f(p, X, y)."), true);
-        assert_eq!(submit(&mut wam, "?- f(p, x, y)."), true);
-        assert_eq!(submit(&mut wam, "?- f(p, X, z)."), false);
-        assert_eq!(submit(&mut wam, "?- f(p, z, Y)."), false);
-
-        assert_eq!(submit(&mut wam, "?- call(p, X)."), true);
-        assert_eq!(submit(&mut wam, "?- call(p, x)."), true);
-        assert_eq!(submit(&mut wam, "?- call(p, y)."), true);
-        assert_eq!(submit(&mut wam, "?- call(p, z)."), false);
-
-        submit(&mut wam, "r(f(X)) :- p(X). r(g(Y)) :- p(Y).");
-
-        assert_eq!(submit(&mut wam, "?- f(r, X, Y)."), true);
-        assert_eq!(submit(&mut wam, "?- f(r, X, X)."), true);
-        assert_eq!(submit(&mut wam, "?- f(r, f(X), g(Y))."), true);
-        assert_eq!(submit(&mut wam, "?- f(r, j(X), h(Y))."), false);
-
-        submit(&mut wam, "p(one, one). p(one, two). p(two, two).");
-
-        assert_eq!(submit(&mut wam, "?- f(p(one), X, Y)."), true);
-        assert_eq!(submit(&mut wam, "?- f(p(one), X, X)."), true);
-        assert_eq!(submit(&mut wam, "?- f(p(one), one, Y)."), true);
-        assert_eq!(submit(&mut wam, "?- f(p(one), one, two)."), true);
-        assert_eq!(submit(&mut wam, "?- f(p(one), one, three)."), false);
-
-        assert_eq!(submit(&mut wam, "?- f(p(two), one, two)."), false);
-        assert_eq!(submit(&mut wam, "?- f(p(two), two, one)."), false);
-        assert_eq!(submit(&mut wam, "?- f(p(two), two, two)."), true);
-        assert_eq!(submit(&mut wam, "?- f(p(two), two, three)."), false);
-
-        assert_eq!(submit(&mut wam, "?- f(p(three), X, Y)."), false);
-        assert_eq!(submit(&mut wam, "?- f(p(three), X, X)."), false);
-        assert_eq!(submit(&mut wam, "?- f(p(three), one, Y)."), false);
-        assert_eq!(submit(&mut wam, "?- f(p(three), one, two)."), false);
-        assert_eq!(submit(&mut wam, "?- f(p(three), one, three)."), false);
-
-        submit(&mut wam, "f(P, X) :- call(P, X).");
-
-        assert_eq!(submit(&mut wam, "?- f(p(one), one)."), true);
-        assert_eq!(submit(&mut wam, "?- f(p(two), two)."), true);
-        assert_eq!(submit(&mut wam, "?- f(p(two), one)."), false);
-        assert_eq!(submit(&mut wam, "?- f(p(three), one)."), false);
-        assert_eq!(submit(&mut wam, "?- f(p(one), three)."), false);
-        assert_eq!(submit(&mut wam, "?- f(p(two), three)."), false);
-
-        submit(&mut wam, "p(f(g(X)), compound, [lists,are,good]).");
-
-        assert_eq!(submit(&mut wam, "?- call(p(f(g(X))), Y, Z)."), true);
-
-        submit(&mut wam, "david_lynch(coffee).
-                          david_lynch(pie).
-                          david_lynch(kyle(Film)) :- kyle(Film).");
-
-        submit(&mut wam, "kyle(dune).
-                          kyle(blue_velvet).
-                          kyle(showgirls).
-                          kyle(flintstones).");
-
-        assert_eq!(submit(&mut wam, "?- call(david_lynch, X)."), true);
-        assert_eq!(submit(&mut wam, "?- call(david_lynch, kyle(Film))."), true);
-        assert_eq!(submit(&mut wam, "?- call(david_lynch, kyle(Film), _)."), false);
-
-        submit(&mut wam, "call_mult(P, X) :- call(call(P), X).");
-
-        assert_eq!(submit(&mut wam, "?- call_mult(p(X), Y)."), true);
-        assert_eq!(submit(&mut wam, "?- call_mult(p(X), X)."), true);
-        assert_eq!(submit(&mut wam, "?- call_mult(p(one), X)."), true);
-        assert_eq!(submit(&mut wam, "?- call_mult(p(X), one)."), true);
-        assert_eq!(submit(&mut wam, "?- call_mult(p(two), one)."), false);
-        assert_eq!(submit(&mut wam, "?- call_mult(p(two), two)."), true);
-
-        assert_eq!(submit(&mut wam, "?- call(call(p(one)), X), call(call(p(two)), two)."), true);
-        assert_eq!(submit(&mut wam, "?- call(call(p(one, X))), call(call(p(two, two)))."), true);
-        assert_eq!(submit(&mut wam, "?- call(call(p(one)), X), call(call(p(two)), one)."), false);
-        assert_eq!(submit(&mut wam, "?- call(call(p(X)), X), call(call(p(Y)), Y)."), true);
-        assert_eq!(submit(&mut wam, "?- call(call(p(X)), Y), call(call(p(Y)), X)."), true);
-        assert_eq!(submit(&mut wam, "?- call(call(p), X, Y), call(call(call(p)), X, Y)."), true);
-        assert_eq!(submit(&mut wam, "?- call(call(p), X, Y), call(call(call(p(X))), Y)."), true);
-        assert_eq!(submit(&mut wam, "?- call(call(p), X, Y), call(call(call(p(X))), X, Y)."), false);
-        assert_eq!(submit(&mut wam, "?- call(call(p), X, Y), call(call(call(p(X))), X)."), true);
-
-        submit(&mut wam, "f(call(f, undefined)). f(undefined).");
-        submit(&mut wam, "call_var(P) :- P.");
-
-        assert_eq!(submit(&mut wam, "?- f(X), call_var(X)."), true);
-        assert_eq!(submit(&mut wam, "?- f(call(f, Q)), call_var(call(f, Q))."), true);
-        assert_eq!(submit(&mut wam, "?- call_var(call(undefined, Q))."), false);
-
-        assert_eq!(submit(&mut wam, "?- call(call)."), false);
-        assert_eq!(submit(&mut wam, "?- call(call(call))."), false);
-        assert_eq!(submit(&mut wam, "?- call(call(call(call)))."), false);
-        assert_eq!(submit(&mut wam, "?- call(call(call(call(call))))."), false);
-        assert_eq!(submit(&mut wam, "?- call(call(call(call(call(call)))))."), false);
-        assert_eq!(submit(&mut wam, "?- call(call(call(call(call(call(p(X)))))))."), true);
-    }
-
-    #[test]
-    fn test_queries_on_exceptions()
-    {
-        let mut wam = Machine::new();
-
-        submit(&mut wam, "f(a). f(_) :- throw(stuff).");
-        submit(&mut wam, "handle(stuff).");
-
-        assert_eq!(submit(&mut wam, "?- catch(f(X), Exception, handle(Exception))."), true);
-
-        submit(&mut wam, "f(a). f(X) :- g(X).");
-        submit(&mut wam, "g(x). g(y). g(z).");
-        submit(&mut wam, "handle(x). handle(y).");
-
-        assert_eq!(submit(&mut wam, "?- catch(f(X), X, handle(X))."), true);
-        assert_eq!(submit(&mut wam, "?- catch(f(a), _, handle(X))."), true);
-        assert_eq!(submit(&mut wam, "?- catch(f(b), _, handle(X))."), false);
-
-        submit(&mut wam, "g(x). g(X) :- throw(x).");
-
-        assert_eq!(submit(&mut wam, "?- catch(f(X), x, handle(X))."), true);
-        assert_eq!(submit(&mut wam, "?- catch(f(X), x, handle(z))."), true);
-        assert_eq!(submit(&mut wam, "?- catch(f(z), x, handle(x))."), true);
-        assert_eq!(submit(&mut wam, "?- catch(f(z), x, handle(y))."), true);
-        assert_eq!(submit(&mut wam, "?- catch(f(z), x, handle(z))."), false);
-
-        submit(&mut wam, "f(X) :- throw(stuff).");
-        submit(&mut wam, "handle(stuff). handle(other_stuff).");
-
-        // the first 3 cases should deterministically succeed.
-        assert_eq!(submit(&mut wam, "?- catch(f(X), Exception, handle(Exception))."), true);
-        assert_eq!(submit(&mut wam, "?- catch(f(X), Exception, handle(stuff))."), true);
-        assert_eq!(submit(&mut wam, "?- catch(f(X), Exception, handle(other_stuff))."), true);
-        assert_eq!(submit(&mut wam, "?- catch(f(X), Exception, handle(not_stuff))."), false);
-
-        submit(&mut wam, "f(success). f(X) :- catch(g(X), E, handle(E)).");
-        submit(&mut wam, "g(g_success). g(g_success_2). g(X) :- throw(X).");
-        submit(&mut wam, "handle(x). handle(y). handle(z).");
-
-        assert_eq!(submit(&mut wam, "?- catch(f(X), E, E)."), true);
-        assert_eq!(submit(&mut wam, "?- catch(f(fail), _, _)."), false);
-        assert_eq!(submit(&mut wam, "?- catch(f(x), _, _)."), true);
-        assert_eq!(submit(&mut wam, "?- catch(f(y), _, _)."), true);
-        assert_eq!(submit(&mut wam, "?- catch(f(z), _, _)."), true);
-
-        submit(&mut wam, "f(success). f(E) :- catch(g(E), E, handle(E)).");
-        submit(&mut wam, "g(g_success). g(g_success_2). g(X) :- throw(X).");
-        submit(&mut wam, "handle(x). handle(y). handle(z). handle(v) :- throw(X).");
-
-        assert_eq!(submit(&mut wam, "?- catch(f(X), E, E)."), true);
-
-        submit(&mut wam, "handle(x). handle(y). handle(z). handle(v) :- throw(handle_top(X)).");
-        submit(&mut wam, "handle_top(an_error_1). handle_top(an_error_2).");
-
-        assert_eq!(submit(&mut wam, "?- catch(f(X), E, E)."), true);
-
-        submit(&mut wam, "handle(x). handle(y). handle(z). handle(v) :- throw(X).");
-
-        assert_eq!(submit(&mut wam, "?- catch(f(X), E, handle_top(E))."), true);
-    }
-    
-    #[test]
-    fn test_queries_on_arithmetic()
-    {
-        let mut wam = Machine::new();
-
-        assert_eq!(submit(&mut wam, "?- X is 1, X is X."), true);
-        assert_eq!(submit(&mut wam, "?- X is 1, X is X + 1."), false);
-        assert_eq!(submit(&mut wam, "?- X is 1, X is X + 0."), true);
-        assert_eq!(submit(&mut wam, "?- X is 1, X is X * 1."), true);
-        assert_eq!(submit(&mut wam, "?- X is 1, X is X * 2."), false);
-
-        assert_eq!(submit(&mut wam, "?- X is 1 + a."), false);
-        assert_eq!(submit(&mut wam, "?- X is 1 + Y."), false);
-        assert_eq!(submit(&mut wam, "?- Y is 2 + 2 - 2, X is 1 + Y, X = 3."), true);
-        assert_eq!(submit(&mut wam, "?- Y is 2 + 2 - 2, X is 1 + Y, X = 2."), false);
-
-        assert_eq!(submit(&mut wam, "?- 6 is 6."), true);
-        assert_eq!(submit(&mut wam, "?- 6 is 3 + 3."), true);
-        assert_eq!(submit(&mut wam, "?- 6 is 3 * 2."), true);
-        assert_eq!(submit(&mut wam, "?- 7 is 3 * 2."), false);
-        assert_eq!(submit(&mut wam, "?- 7 is 3.5 * 2."), false);
-        assert_eq!(submit(&mut wam, "?- 7.0 is 3.5 * 2."), true);
-        assert_eq!(submit(&mut wam, "?- 7.0 is 14 / 2."), true);
-        assert_eq!(submit(&mut wam, "?- 4.666 is 14.0 / 3."), false);
-        assert_eq!(submit(&mut wam, "?- 4.0 is 8.0 / 2."), true);
-
-        submit(&mut wam, "f(X) :- X is 5 // 0.");
-
-        assert_eq!(submit(&mut wam, "?- catch(f(X), evaluation_error(E), true), E = zero_divisor."),
-                   true);
-        
-        submit(&mut wam, "f(X) :- X is (5 rdiv 1) / 0.");
-
-        assert_eq!(submit(&mut wam, "?- catch(f(X), evaluation_error(E), true), E = zero_divisor."),
-                   true);
-        
-        submit(&mut wam, "f(X) :- X is 5.0 / 0.");
-
-        assert_eq!(submit(&mut wam, "?- catch(f(X), evaluation_error(E), true), E = zero_divisor."),
-                   true);
-        
-        assert_eq!(submit(&mut wam, "?- X is ((3 + 4) // 2) + 2 - 1 // 1, Y is 2+2, Z is X+Y."),
-                   true);
-
-        assert_eq!(submit(&mut wam, "?- X is ((3 + 4) // 2) + 2 - 1 // 1, Y is 2+2, Z = 8, Y is 4."),
-                   true);
-
-        assert_eq!(submit(&mut wam, "?- X is (3 rdiv 4) / 2, Y is 3 rdiv 8, X = Y."), true);
-
-        assert_eq!(submit(&mut wam, "?- X is 10 xor -4, X is -10."), true);
-        assert_eq!(submit(&mut wam, "?- X is 4 xor -7, X is -3."), true);
-        assert_eq!(submit(&mut wam, "?- X is 10 xor 5 + 55, X = 70."), true);
-        
-        assert_eq!(submit(&mut wam, "?- X is 10 rem -3, X = 1."), true);
-        assert_eq!(submit(&mut wam, "?- X is 10 mod -3, X is -2."), true);
-    }
-} */
+mod tests;
 
 fn process_buffer(wam: &mut Machine, buffer: &str)
 {
index 4594963bb9277fb5902908e0bafc45cda837caf5..dba7b0b0a24a0f8b96770dad10ce7cbb918c7f9b 100644 (file)
@@ -407,3 +407,675 @@ fn test_queries_on_lists()
     assert_prolog_failure!(&mut wam, "?- member([X, Y, Y], [a, [b, c], [b, b], [Z, x], [d, f]]).");
     assert_prolog_failure!(&mut wam, "?- member([X, Y, Z], [a, [b, c], [b, b], [Z, x], [d, f]]).");
 }
+
+#[test]
+fn test_queries_on_indexed_predicates()
+{
+    let mut wam = Machine::new();
+
+    submit(&mut wam, "p(a) :- a.
+                      p(b) :- b, f(X).
+                      p(c) :- c, g(X).
+                      p(f(a)) :- a.
+                      p(g(b, c)) :- b.
+                      p(g(b)) :- b.
+                      p([a|b]) :- a.
+                      p([]).
+                      p(X) :- x.
+                      p([c, d, e]).");
+
+    assert_prolog_failure!(&mut wam, "?- p(a).");
+    assert_prolog_failure!(&mut wam, "?- p(b).");
+    assert_prolog_failure!(&mut wam, "?- p(c).");
+    assert_prolog_failure!(&mut wam, "?- p(f(a)).");
+    assert_prolog_failure!(&mut wam, "?- p(g(b, X)).");
+    assert_prolog_failure!(&mut wam, "?- p(g(Y, X)).");
+    assert_prolog_failure!(&mut wam, "?- p(g(Y, c)).");
+    assert_prolog_failure!(&mut wam, "?- p(g(b)).");
+    assert_prolog_success!(&mut wam, "?- p([]).");
+    assert_prolog_success!(&mut wam, "?- p([c, d, e]).");
+    assert_prolog_success!(&mut wam, "?- p([c, d | X]).", ["X = [e]"]);
+    assert_prolog_success!(&mut wam, "?- p([c|X]).", ["X = [d, e]"]);
+    assert_prolog_success!(&mut wam, "?- p([Y|X]).", ["Y = c", "X = [d, e]"]);
+    assert_prolog_success!(&mut wam, "?- p([Y|[d|Xs]]).", ["Xs = [e]", "Y = c"]);
+
+    submit(&mut wam, "a.");
+
+    assert_prolog_success!(&mut wam, "?- p(a).");
+    assert_prolog_failure!(&mut wam, "?- p(b).");
+    assert_prolog_failure!(&mut wam, "?- p(c).");
+    assert_prolog_success!(&mut wam, "?- p(f(a)).");
+    assert_prolog_failure!(&mut wam, "?- p(g(b, X)).");
+    assert_prolog_failure!(&mut wam, "?- p(g(Y, X)).");
+    assert_prolog_failure!(&mut wam, "?- p(g(Y, c)).");
+    assert_prolog_failure!(&mut wam, "?- p(g(b)).");
+    assert_prolog_success!(&mut wam, "?- p([]).");
+    assert_prolog_success!(&mut wam, "?- p([c, d, e]).");
+    assert_prolog_success!(&mut wam, "?- p([c, d | X]).", ["X = [e]"]);
+    assert_prolog_success!(&mut wam, "?- p([c|X]).", ["X = [d, e]"]);
+    assert_prolog_success!(&mut wam, "?- p([Y|X]).", ["X = b", "Y = a",
+                                                      "Y = c", "X = [d, e]"]);
+    assert_prolog_success!(&mut wam, "?- p([Y|[d|Xs]]).", ["Xs = [e]", "Y = c"]);
+
+    submit(&mut wam, "b.");
+    submit(&mut wam, "f(x).");
+
+    assert_prolog_success!(&mut wam, "?- p(a).");
+    assert_prolog_success!(&mut wam, "?- p(b).");
+    assert_prolog_failure!(&mut wam, "?- p(c).");
+    assert_prolog_success!(&mut wam, "?- p(f(a)).");
+    assert_prolog_success!(&mut wam, "?- p(g(b, X)).", ["X = c"]);
+    assert_prolog_success!(&mut wam, "?- p(g(Y, X)).", ["X = c", "Y = b"]);
+    assert_prolog_success!(&mut wam, "?- p(g(Y, c)).", ["Y = b"]);    
+    assert_prolog_success!(&mut wam, "?- p(g(b)).");
+    assert_prolog_success!(&mut wam, "?- p([]).");
+    assert_prolog_success!(&mut wam, "?- p([c, d, e]).");
+    assert_prolog_success!(&mut wam, "?- p([c, d | X]).", ["X = [e]"]);
+    assert_prolog_success!(&mut wam, "?- p([c|X]).", ["X = [d, e]"]);
+    assert_prolog_success!(&mut wam, "?- p([Y|X]).", ["X = b", "Y = a",
+                                                      "Y = c", "X = [d, e]"]);
+    assert_prolog_success!(&mut wam, "?- p([Y|[d|Xs]]).", ["Xs = [e]", "Y = c"]);
+
+    submit(&mut wam, "c.");
+    submit(&mut wam, "g(X).");
+
+    assert_eq!(submit(&mut wam, "?- p(a)."), true);
+    assert_eq!(submit(&mut wam, "?- p(b)."), true);
+    assert_eq!(submit(&mut wam, "?- p(c)."), true);
+    assert_eq!(submit(&mut wam, "?- p(f(a))."), true);
+    assert_prolog_success!(&mut wam, "?- p(g(b, X)).", ["X = c"]);
+    assert_prolog_success!(&mut wam, "?- p(g(Y, X)).", ["X = c", "Y = b"]);
+    assert_prolog_success!(&mut wam, "?- p(g(Y, c)).", ["Y = b"]);
+    assert_eq!(submit(&mut wam, "?- p(g(b))."), true);
+    assert_eq!(submit(&mut wam, "?- p([])."), true);
+    assert_eq!(submit(&mut wam, "?- p([c, d, e])."), true);
+    assert_prolog_success!(&mut wam, "?- p([c, d | X]).", ["X = [e]"]);
+    assert_prolog_success!(&mut wam, "?- p([c|X]).", ["X = [d, e]"]);
+    assert_prolog_success!(&mut wam, "?- p([Y|X]).", ["X = b", "Y = a",
+                                                      "Y = c", "X = [d, e]"]);
+    assert_prolog_success!(&mut wam, "?- p([Y|[d|Xs]]).", ["Xs = [e]", "Y = c"]);
+    assert_eq!(submit(&mut wam, "?- p(blah)."), false);
+
+    submit(&mut wam, "x.");
+
+    assert_eq!(submit(&mut wam, "?- p(a)."), true);
+    assert_eq!(submit(&mut wam, "?- p(b)."), true);
+    assert_eq!(submit(&mut wam, "?- p(c)."), true);
+    assert_eq!(submit(&mut wam, "?- p(true(a))."), true);
+    
+    assert_prolog_success!(&mut wam, "?- p(g(b, X)).", ["X = c",
+                                                        "X = _2"]);
+    assert_prolog_success!(&mut wam, "?- p(g(Y, X)).", ["X = c", "Y = b",
+                                                        "X = _2", "Y = _1"]);
+    assert_prolog_success!(&mut wam, "?- p(g(Y, c)).", ["Y = b",
+                                                        "Y = _1"]);
+    
+    assert_eq!(submit(&mut wam, "?- p(g(b))."), true);
+    assert_eq!(submit(&mut wam, "?- p([])."), true);
+    assert_eq!(submit(&mut wam, "?- p([c, d, e])."), true);
+    
+    assert_prolog_success!(&mut wam, "?- p([c, d | X]).", ["X = _1",
+                                                           "X = [e]"]);
+    assert_prolog_success!(&mut wam, "?- p([c|X]).", ["X = [d, e]",
+                                                      "X = _1"]);
+    assert_prolog_success!(&mut wam, "?- p([Y|X]).", ["X = b", "Y = a",
+                                                      "Y = c", "X = [d, e]",
+                                                      "X = _1", "Y = _0"]);
+    assert_prolog_success!(&mut wam, "?- p([Y|[d|Xs]]).", ["Xs = [e]", "Y = c",
+                                                           "Xs = _1", "Y = _2"]);
+    
+    assert_prolog_success!(&mut wam, "?- p(blah).");
+
+    submit(&mut wam, "ind_call(or(X, Y)) :- ind_call(X).
+                      ind_call(trace) :- trace.
+                      ind_call(or(X, Y)) :- ind_call(Y).
+                      ind_call(notrace) :- notrace.
+                      ind_call(nl) :- nl.
+                      ind_call(X) :- builtin(X).
+                      ind_call(X) :- extern(X).
+                      ind_call(ind_call(X)) :- ind_call(X).
+                      ind_call(repeat).
+                      ind_call(repeat) :- ind_call(repeat).
+                      ind_call(false).");
+
+    assert_eq!(submit(&mut wam, "?- ind_call(repeat)."), true);
+    assert_eq!(submit(&mut wam, "?- ind_call(false)."), true);
+    assert_eq!(submit(&mut wam, "?- ind_call(ind_call(repeat))."), true);
+    assert_eq!(submit(&mut wam, "?- ind_call(ind_call(false))."), true);
+    assert_eq!(submit(&mut wam, "?- ind_call(notrace)."), false);
+    assert_eq!(submit(&mut wam, "?- ind_call(nl)."), false);
+    assert_eq!(submit(&mut wam, "?- ind_call(builtin(X))."), false);
+    assert_eq!(submit(&mut wam, "?- ind_call(extern(X))."), false);
+
+    submit(&mut wam, "notrace.");
+    submit(&mut wam, "nl.");
+
+    assert_eq!(submit(&mut wam, "?- ind_call(repeat)."), true);
+    assert_eq!(submit(&mut wam, "?- ind_call(false)."), true);
+    assert_eq!(submit(&mut wam, "?- ind_call(ind_call(repeat))."), true);
+    assert_eq!(submit(&mut wam, "?- ind_call(ind_call(false))."), true);
+    assert_eq!(submit(&mut wam, "?- ind_call(notrace)."), true);
+    assert_eq!(submit(&mut wam, "?- ind_call(nl)."), true);
+    assert_eq!(submit(&mut wam, "?- ind_call(builtin(X))."), false);
+    assert_eq!(submit(&mut wam, "?- ind_call(extern(X))."), false);
+
+    submit(&mut wam, "builtin(X).");
+    submit(&mut wam, "extern(x).");
+
+    assert_eq!(submit(&mut wam, "?- ind_call(repeat)."), true);
+    assert_eq!(submit(&mut wam, "?- ind_call(false)."), true);
+    assert_eq!(submit(&mut wam, "?- ind_call(ind_call(repeat))."), true);
+    assert_eq!(submit(&mut wam, "?- ind_call(ind_call(false))."), true);
+    assert_eq!(submit(&mut wam, "?- ind_call(notrace)."), true);
+    assert_eq!(submit(&mut wam, "?- ind_call(nl)."), true);
+    assert_prolog_success!(&mut wam, "?- ind_call(builtin(X)).", ["X = _1"]);
+    assert_prolog_success!(&mut wam, "?- ind_call(extern(X)).", ["X = _1"]);
+}
+
+#[test]
+fn test_queries_on_conjuctive_queries() {
+    let mut wam = Machine::new();
+
+    submit(&mut wam, "p(a, b).");
+    submit(&mut wam, "q(b, c).");
+
+    assert_prolog_success!(&mut wam, "?- p(X, Y), q(Y, Z).", ["X = a", "Z = c", "Y = b"]);
+    assert_prolog_failure!(&mut wam, "?- p(X, Y), q(Y, X).");
+
+    submit(&mut wam, "p(a, [f(g(X))]).");
+    submit(&mut wam, "q(Y, c).");
+
+    assert_prolog_success!(&mut wam, "?- p(X, Y), q(Y, Z).", ["Y = f(g(_9))", "X = a", "Z = c"]);
+    assert_prolog_failure!(&mut wam, "?- p(X, Y), q(Y, X).");
+
+    submit(&mut wam, "member(X, [X|_]).
+                      member(X, [_|Xs]) :- member(X, Xs).");
+
+    assert_prolog_success!(&mut wam, "?- member(X, [a,b,c]), member(X, [a,b,c]).",
+                           ["X = a",
+                            "X = b",
+                            "X = c"]);
+    assert_prolog_success!(&mut wam, "?- member(X, [a,b,c]), member(X, [b,c]).",
+                           ["X = b",
+                            "X = c"]);
+    assert_prolog_success!(&mut wam, "?- member(X, [a,c]), member(X, [b,c]).",
+                           ["X = c"]);    
+    assert_prolog_success!(&mut wam, "?- member(X, [a,b,c,d]), !, member(X, [a,d]).",
+                           ["X = a"]);
+    assert_prolog_failure!(&mut wam, "?- member(X, [a,b,c,d]), !, member(X, [e]).");
+    assert_prolog_success!(&mut wam, "?- member([X,X],[a,b,c,[d,d],[e,d]]),
+                                         member(X, [a,b,c,d,e,f,g]),
+                                         member(Y, [X, a, b, c, d]).",
+                           ["X = d", "Y = d",
+                            "X = d", "Y = a",
+                            "X = d", "Y = b",
+                            "X = d", "Y = c",
+                            "X = d", "Y = d"]);
+
+    submit(&mut wam, "p(a, [f(g(X))]). p(X, c) :- c.");
+    submit(&mut wam, "c.");
+    submit(&mut wam, "q(Y, c).");
+
+    assert_prolog_success!(&mut wam, "?- p(X, Y), q(Y, Z).",
+                           ["X = a",  "Z = c", "Y = f(g(_9))",
+                            "X = _0", "Z = c", "Y = c"]);
+    assert_prolog_success!(&mut wam, "?- p(X, Y), !, q(Y, Z).",
+                           ["Z = c", "Y = f(g(_9))", "X = a"]);
+
+    submit(&mut wam, "q([f(g(x))], Z). q([f(g(y))], Y). q([f(g(z))], a).");
+
+    assert_prolog_success!(&mut wam, "?- p(X, Y), q(Y, Z).",
+                           ["Z = _10", "X = a", "Y = f(g(x))",
+                            "Z = _10", "X = a", "Y = f(g(y))",
+                            "Z = a", "X = a", "Y = f(g(z))"]);
+    assert_prolog_success!(&mut wam, "?- p(X, Y), !, q(Y, Z).",
+                           ["X = a", "Y = f(g(x))", "Z = _10",
+                            "X = a", "Y = f(g(y))", "Z = _10",
+                            "X = a", "Y = f(g(z))", "Z = a"]);
+    assert_prolog_success!(&mut wam, "?- p(X, Y), !, q(Y, X).",
+                           ["X = a", "Y = f(g(x))",
+                            "X = a", "Y = f(g(y))",
+                            "X = a", "Y = f(g(z))"]);
+
+    submit(&mut wam, "p(X, [f(g(x))]). p(X, [f(g(y))]). p(X, [f(g(z))]).");
+
+    assert_prolog_failure!(&mut wam, "?- q(f(X), Y), p(X, Y).");
+    assert_prolog_success!(&mut wam, "?- q(X, Y), p(X, Y).",
+                           ["Y = [f(g(x))]", "X = f(g(x))",
+                            "Y = [f(g(y))]", "X = f(g(x))",
+                            "Y = [f(g(z))]", "X = f(g(x))",
+                            "Y = [f(g(x))]", "X = f(g(y))",
+                            "Y = [f(g(y))]", "X = f(g(y))",
+                            "Y = [f(g(z))]", "X = f(g(y))"]);
+    assert_prolog_success!(&mut wam, "?- p(X, Y), q(X, Y).",
+                           ["Y = f(g(x))", "X = [f(g(x))]",
+                            "Y = f(g(x))", "X = [f(g(y))]",
+                            "Y = f(g(y))", "X = [f(g(x))]",
+                            "Y = f(g(y))", "X = [f(g(y))]",
+                            "Y = f(g(z))", "X = [f(g(x))]",
+                            "Y = f(g(z))", "X = [f(g(y))]"]);
+    assert_prolog_success!(&mut wam, "?- p(X, Y), q(Y, X).",
+                           ["Y = f(g(x))", "X = s_0_2",
+                            "Y = f(g(y))", "X = s_0_2",
+                            "Y = f(g(z))", "X = a"]);
+    assert_prolog_success!(&mut wam, "?- q(X, Y), p(Y, X).",
+                           ["Y = s_0_1", "X = f(g(x))",
+                            "Y = s_0_1", "X = f(g(y))",
+                            "Y = a"    , "X = f(g(z))"]);
+}
+
+#[test]
+fn test_queries_on_call_n()
+{
+    let mut wam = Machine::new();
+
+    submit(&mut wam, "maplist(Pred, []).
+                      maplist(Pred, [X|Xs]) :- call(Pred, X), maplist(Pred, Xs).");
+    submit(&mut wam, "f(a). f(b). f(c).");
+
+    assert_prolog_success!(&mut wam, "?- maplist(f, [X,Y,Z]).",
+                           ["X = a", "Y = a", "Z = a",
+                            "X = a", "Y = a", "Z = b",
+                            "X = a", "Y = a", "Z = c",
+                            "X = a", "Y = b", "Z = a",
+                            "X = a", "Y = b", "Z = b",
+                            "X = a", "Y = b", "Z = c",
+                            "X = a", "Y = c", "Z = a",
+                            "X = a", "Y = c", "Z = b",
+                            "X = a", "Y = c", "Z = c",
+                            "X = b", "Y = a", "Z = a",
+                            "X = b", "Y = a", "Z = b",
+                            "X = b", "Y = a", "Z = c",
+                            "X = b", "Y = b", "Z = a",
+                            "X = b", "Y = b", "Z = b",
+                            "X = b", "Y = b", "Z = c",
+                            "X = b", "Y = c", "Z = a",
+                            "X = b", "Y = c", "Z = b",
+                            "X = b", "Y = c", "Z = c",
+                            "X = c", "Y = a", "Z = a",
+                            "X = c", "Y = a", "Z = b",
+                            "X = c", "Y = a", "Z = c",
+                            "X = c", "Y = b", "Z = a",
+                            "X = c", "Y = b", "Z = b",
+                            "X = c", "Y = b", "Z = c",
+                            "X = c", "Y = c", "Z = a",
+                            "X = c", "Y = c", "Z = b",
+                            "X = c", "Y = c", "Z = c"]);
+                            
+    assert_prolog_success!(&mut wam, "?- maplist(f, [a,Y,Z]).",
+                           ["Z = a", "Y = a",
+                            "Z = a", "Y = b",
+                            "Z = a", "Y = c",
+                            "Z = b", "Y = a",
+                            "Z = b", "Y = b",
+                            "Z = b", "Y = c",
+                            "Z = c", "Y = a",
+                            "Z = c", "Y = b",
+                            "Z = c", "Y = c"]);
+                            
+    assert_prolog_success!(&mut wam, "?- maplist(f, [X,a,b]).",
+                           ["X = a",
+                            "X = b",
+                            "X = c"]);
+    assert_eq!(submit(&mut wam, "?- maplist(f, [c,a,b])."), true);
+    assert_eq!(submit(&mut wam, "?- maplist(f, [d,e,f])."), false);
+    assert_eq!(submit(&mut wam, "?- maplist(f, [])."), true);
+    assert_eq!(submit(&mut wam, "?- maplist(f(X), [a,b,c])."), false);
+
+    submit(&mut wam, "f(X) :- call(X), call(X).");
+    submit(&mut wam, "p(x). p(y).");
+
+    assert_eq!(submit(&mut wam, "?- f(p)."), false);
+    assert_prolog_success!(&mut wam, "?- f(p(X)).", ["X = x",
+                                                     "X = y"]);
+    assert_eq!(submit(&mut wam, "?- f(p(x))."), true);
+    assert_eq!(submit(&mut wam, "?- f(p(w))."), false);
+    assert_eq!(submit(&mut wam, "?- f(p(X, Y))."), false);
+
+    submit(&mut wam, "f(P) :- call(P, X), call(P, Y).");
+
+    assert_eq!(submit(&mut wam, "?- f(p)."), true);
+    assert_eq!(submit(&mut wam, "?- f(non_existent)."), false);
+
+    submit(&mut wam, "f(P, X, Y) :- call(P, X), call(P, Y).");
+
+    assert_prolog_success!(&mut wam, "?- f(p, X, Y).", ["X = x", "Y = x",
+                                                        "X = y", "Y = x",
+                                                        "X = x", "Y = y",
+                                                        "X = y", "Y = y"]);
+    assert_prolog_success!(&mut wam, "?- f(p, x, Y).", ["Y = x",
+                                                        "Y = y"]);
+    assert_prolog_success!(&mut wam, "?- f(p, X, y).", ["X = x",
+                                                        "X = y"]);
+    assert_eq!(submit(&mut wam, "?- f(p, x, y)."), true);
+    assert_eq!(submit(&mut wam, "?- f(p, X, z)."), false);
+    assert_eq!(submit(&mut wam, "?- f(p, z, Y)."), false);
+
+    assert_prolog_success!(&mut wam, "?- call(p, X).", ["X = x",
+                                                        "X = y"]);
+    assert_eq!(submit(&mut wam, "?- call(p, x)."), true);
+    assert_eq!(submit(&mut wam, "?- call(p, y)."), true);
+    assert_eq!(submit(&mut wam, "?- call(p, z)."), false);
+
+    submit(&mut wam, "r(f(X)) :- p(X). r(g(Y)) :- p(Y).");
+
+    assert_prolog_success!(&mut wam, "?- f(r, X, Y).",
+                           ["X = f(x)", "Y = f(x)", 
+                            "X = f(x)", "Y = f(y)", 
+                            "X = f(x)", "Y = g(x)", 
+                            "X = f(x)", "Y = g(y)", 
+                            "X = f(y)", "Y = f(x)", 
+                            "X = f(y)", "Y = f(y)", 
+                            "X = f(y)", "Y = g(x)", 
+                            "X = f(y)", "Y = g(y)", 
+                            "X = g(x)", "Y = f(x)", 
+                            "X = g(x)", "Y = f(y)", 
+                            "X = g(x)", "Y = g(x)", 
+                            "X = g(x)", "Y = g(y)", 
+                            "X = g(y)", "Y = f(x)",                            
+                            "X = g(y)", "Y = f(y)",                            
+                            "X = g(y)", "Y = g(x)",                             
+                            "X = g(y)", "Y = g(y)"]);
+    assert_prolog_success!(&mut wam, "?- f(r, X, X).",
+                           ["X = f(x)",
+                            "X = f(y)",
+                            "X = g(x)",
+                            "X = g(y)"]);
+    assert_prolog_success!(&mut wam, "?- f(r, f(X), g(Y)).",
+                           ["X = x", "Y = x",
+                            "X = x", "Y = y",
+                            "X = y", "Y = x",
+                            "X = y", "Y = y"]);
+    assert_eq!(submit(&mut wam, "?- f(r, j(X), h(Y))."), false);
+
+    submit(&mut wam, "p(one, one). p(one, two). p(two, two).");
+
+    assert_prolog_success!(&mut wam, "?- f(p(one), X, Y).",
+                           ["X = one", "Y = one",
+                            "X = one", "Y = two",
+                            "X = two", "Y = two",
+                            "X = two", "Y = one"]);
+    assert_prolog_success!(&mut wam, "?- f(p(one), X, X).",
+                           ["X = one",
+                            "X = two"]);
+    assert_prolog_success!(&mut wam, "?- f(p(one), one, Y).",
+                           ["Y = one",
+                            "Y = two"]);
+    assert_eq!(submit(&mut wam, "?- f(p(one), one, two)."), true);
+    assert_eq!(submit(&mut wam, "?- f(p(one), one, three)."), false);
+
+    assert_eq!(submit(&mut wam, "?- f(p(two), one, two)."), false);
+    assert_eq!(submit(&mut wam, "?- f(p(two), two, one)."), false);
+    assert_eq!(submit(&mut wam, "?- f(p(two), two, two)."), true);
+    assert_eq!(submit(&mut wam, "?- f(p(two), two, three)."), false);
+
+    assert_eq!(submit(&mut wam, "?- f(p(three), X, Y)."), false);
+    assert_eq!(submit(&mut wam, "?- f(p(three), X, X)."), false);
+    assert_eq!(submit(&mut wam, "?- f(p(three), one, Y)."), false);
+    assert_eq!(submit(&mut wam, "?- f(p(three), one, two)."), false);
+    assert_eq!(submit(&mut wam, "?- f(p(three), one, three)."), false);
+
+    submit(&mut wam, "f(P, X) :- call(P, X).");
+
+    assert_eq!(submit(&mut wam, "?- f(p(one), one)."), true);
+    assert_eq!(submit(&mut wam, "?- f(p(two), two)."), true);
+    assert_eq!(submit(&mut wam, "?- f(p(two), one)."), false);
+    assert_eq!(submit(&mut wam, "?- f(p(three), one)."), false);
+    assert_eq!(submit(&mut wam, "?- f(p(one), three)."), false);
+    assert_eq!(submit(&mut wam, "?- f(p(two), three)."), false);
+
+    submit(&mut wam, "p(f(g(X)), compound, [lists,are,good]).");
+
+    assert_prolog_success!(&mut wam, "?- call(p(f(g(X))), Y, Z).",
+                           ["Y = compound", "Z = [lists, are, good]", "X = _3"]);
+
+    submit(&mut wam, "david_lynch(coffee).
+                      david_lynch(pie).
+                      david_lynch(kyle(Film)) :- kyle(Film).");
+
+    submit(&mut wam, "kyle(dune).
+                      kyle(blue_velvet).
+                      kyle(showgirls).
+                      kyle(flintstones).");
+
+    assert_prolog_success!(&mut wam, "?- call(david_lynch, X).",
+                           ["X = coffee",
+                            "X = pie",
+                            "X = kyle(dune)",
+                            "X = kyle(blue_velvet)",
+                            "X = kyle(showgirls)",
+                            "X = kyle(flintstones)"]);
+    assert_prolog_success!(&mut wam, "?- call(david_lynch, kyle(Film)).",
+                           ["Film = dune",
+                            "Film = blue_velvet",
+                            "Film = showgirls",
+                            "Film = flintstones"]);
+    assert_eq!(submit(&mut wam, "?- call(david_lynch, kyle(Film), _)."), false);
+
+    submit(&mut wam, "call_mult(P, X) :- call(call(P), X).");
+
+    assert_prolog_success!(&mut wam, "?- call_mult(p(X), Y).",
+                           ["Y = one", "X = one",
+                            "Y = two", "X = one",
+                            "Y = two", "X = two"]);
+    assert_prolog_success!(&mut wam, "?- call_mult(p(X), X).",
+                           ["X = one",
+                            "X = two"]);
+    assert_prolog_success!(&mut wam, "?- call_mult(p(one), X).",
+                           ["X = one",
+                            "X = two"]);
+    assert_prolog_success!(&mut wam, "?- call_mult(p(X), one).", ["X = one"]);
+    assert_eq!(submit(&mut wam, "?- call_mult(p(two), one)."), false);
+    assert_eq!(submit(&mut wam, "?- call_mult(p(two), two)."), true);
+
+    assert_prolog_success!(&mut wam, "?- call(call(p(one)), X), call(call(p(two)), two).",
+                           ["X = one",
+                            "X = two"]);
+    assert_prolog_success!(&mut wam, "?- call(call(p(one, X))), call(call(p(two, two))).",
+                           ["X = one",
+                            "X = two"]);
+    assert_eq!(submit(&mut wam, "?- call(call(p(one)), X), call(call(p(two)), one)."), false);
+    assert_prolog_success!(&mut wam, "?- call(call(p(X)), X), call(call(p(Y)), Y).",
+                           ["X = one", "Y = one",
+                            "X = one", "Y = two",
+                            "X = two", "Y = two",
+                            "X = two", "Y = one"]);
+    assert_prolog_success!(&mut wam, "?- call(call(p(X)), Y), call(call(p(Y)), X).",
+                           ["X = one", "Y = one",
+                            "X = two", "Y = two"]);
+    assert_prolog_success!(&mut wam, "?- call(call(p), X, Y), call(call(call(p)), X, Y).",
+                           ["X = one", "Y = one",
+                            "Y = two", "X = one",
+                            "Y = two", "X = two"]);
+    assert_prolog_success!(&mut wam, "?- call(call(p), X, Y), call(call(call(p(X))), Y).",
+                           ["X = one", "Y = one",
+                            "Y = two", "X = one",
+                            "Y = two", "X = two"]);
+    assert_eq!(submit(&mut wam, "?- call(call(p), X, Y), call(call(call(p(X))), X, Y)."), false);
+    assert_prolog_success!(&mut wam, "?- call(call(p), X, Y), call(call(call(p(X))), X).",
+                           ["X = one", "Y = one",
+                            "Y = two", "X = one",
+                            "Y = two", "X = two"]);
+
+    submit(&mut wam, "f(call(f, undefined)). f(undefined).");
+    submit(&mut wam, "call_var(P) :- P.");
+
+    assert_prolog_success!(&mut wam, "?- f(X), call_var(X).",
+                           ["X = call(f, undefined)"]);
+    assert_prolog_success!(&mut wam, "?- f(call(f, Q)), call_var(call(f, Q)).",
+                           ["Q = undefined"]);
+    assert_eq!(submit(&mut wam, "?- call_var(call(undefined, Q))."), false);
+
+    assert_eq!(submit(&mut wam, "?- call(call)."), false);
+    assert_eq!(submit(&mut wam, "?- call(call(call))."), false);
+    assert_eq!(submit(&mut wam, "?- call(call(call(call)))."), false);
+    assert_eq!(submit(&mut wam, "?- call(call(call(call(call))))."), false);
+    assert_eq!(submit(&mut wam, "?- call(call(call(call(call(call)))))."), false);
+    assert_prolog_success!(&mut wam, "?- call(call(call(call(call(call(p(X))))))).",
+                           ["X = x",
+                            "X = y"]);
+}
+
+#[test]
+fn test_queries_on_exceptions()
+{
+    let mut wam = Machine::new();
+
+    submit(&mut wam, "f(a). f(_) :- throw(stuff).");
+    submit(&mut wam, "handle(stuff).");
+
+    assert_prolog_success!(&mut wam, "?- catch(f(X), E, handle(E)).",
+                           ["E = _2", "X = a",
+                            "E = stuff", "X = _1"]);
+
+    submit(&mut wam, "f(a). f(X) :- g(X).");
+    submit(&mut wam, "g(x). g(y). g(z).");
+    submit(&mut wam, "handle(x). handle(y).");
+
+    assert_prolog_success!(&mut wam, "?- catch(f(X), X, handle(X)).",
+                           ["X = a",
+                            "X = x",
+                            "X = y",
+                            "X = z"]);
+    assert_prolog_success!(&mut wam, "?- catch(f(a), _, handle(X)).",
+                           ["X = _4"]);
+    assert_eq!(submit(&mut wam, "?- catch(f(b), _, handle(X))."), false);
+
+    submit(&mut wam, "g(x). g(X) :- throw(x).");
+
+    assert_prolog_success!(&mut wam, "?- catch(f(X), x, handle(X)).",
+                           ["X = a",
+                            "X = x",
+                            "X = x",
+                            "X = y"]);
+    assert_prolog_success!(&mut wam, "?- catch(f(X), x, handle(z)).",
+                           ["X = a",
+                            "X = x"]);
+    assert_eq!(submit(&mut wam, "?- catch(f(z), x, handle(x))."), true);
+    assert_eq!(submit(&mut wam, "?- catch(f(z), x, handle(y))."), true);
+    assert_eq!(submit(&mut wam, "?- catch(f(z), x, handle(z))."), false);
+
+    submit(&mut wam, "f(X) :- throw(stuff).");
+    submit(&mut wam, "handle(stuff). handle(other_stuff).");
+
+    // the first 3 cases should deterministically succeed.
+    assert_prolog_success!(&mut wam, "?- catch(f(X), E, handle(E)).",
+                           ["X = _1", "E = stuff"]);
+    assert_prolog_success!(&mut wam, "?- catch(f(X), E, handle(stuff)).",
+                           ["X = _1", "E = stuff"]);
+    assert_prolog_success!(&mut wam, "?- catch(f(X), E, handle(other_stuff)).",
+                           ["X = _1", "E = stuff"]);
+    assert_eq!(submit(&mut wam, "?- catch(f(X), E, handle(not_stuff))."), false);
+
+    submit(&mut wam, "f(success). f(X) :- catch(g(X), E, handle(E)).");
+    submit(&mut wam, "g(g_success). g(g_success_2). g(X) :- throw(X).");
+    submit(&mut wam, "handle(x). handle(y). handle(z).");
+
+    assert_prolog_success!(&mut wam, "?- catch(f(X), E, E).",
+                           ["X = success", "E = _2",
+                            "X = g_success", "E = _2",
+                            "X = g_success_2", "E = _2",
+                            "X = _1", "E = _2",
+                            "X = _1", "E = _2",
+                            "X = _1", "E = _2"]);
+    assert_eq!(submit(&mut wam, "?- catch(f(fail), _, _)."), false);
+    assert_eq!(submit(&mut wam, "?- catch(f(x), _, _)."), true);
+    assert_eq!(submit(&mut wam, "?- catch(f(y), _, _)."), true);
+    assert_eq!(submit(&mut wam, "?- catch(f(z), _, _)."), true);
+
+    submit(&mut wam, "f(success). f(E) :- catch(g(E), E, handle(E)).");
+    submit(&mut wam, "g(g_success). g(g_success_2). g(X) :- throw(X).");
+    submit(&mut wam, "handle(x). handle(y). handle(z). handle(v) :- throw(X).");
+
+    assert_prolog_success!(&mut wam, "?- catch(f(X), E, E).",
+                           ["X = success", "E = _2",
+                            "X = g_success", "E = _2",
+                            "X = g_success_2", "E = _2",
+                            "X = x", "E = _2",
+                            "X = y", "E = _2",
+                            "X = z", "E = _2"]);
+
+    submit(&mut wam, "handle(x). handle(y). handle(z). handle(v) :- throw(handle_top(X)).");
+    submit(&mut wam, "handle_top(an_error_1). handle_top(an_error_2).");
+
+    assert_prolog_success!(&mut wam, "?- catch(f(X), E, E).",
+                           ["X = success", "E = _2",
+                            "X = g_success", "E = _2",
+                            "X = g_success_2", "E = _2",
+                            "X = x", "E = _2",
+                            "X = y", "E = _2",
+                            "X = z", "E = _2",
+                            "X = _1", "E = handle_top(an_error_1)",
+                            "X = _1", "E = handle_top(an_error_2)"]);    
+
+    submit(&mut wam, "handle(x). handle(y). handle(z). handle(v) :- throw(X).");
+
+    assert_prolog_success!(&mut wam, "?- catch(f(X), E, handle_top(E)).",
+                           ["X = success", "E = _2",
+                            "X = g_success", "E = _2",
+                            "X = g_success_2", "E = _2",
+                            "X = x", "E = _2",
+                            "X = y", "E = _2",
+                            "X = z", "E = _2",
+                            "E = an_error_1", "X = _1",
+                            "E = an_error_2", "X = _1"]);
+}
+
+#[test]
+fn test_queries_on_arithmetic()
+{
+    let mut wam = Machine::new();
+
+    assert_prolog_success!(&mut wam, "?- X is 1, X is X.", ["X = 1"]);
+    assert_eq!(submit(&mut wam, "?- X is 1, X is X + 1."), false);
+    assert_prolog_success!(&mut wam, "?- X is 1, X is X + 0.", ["X = 1"]);
+    assert_prolog_success!(&mut wam, "?- X is 1, X is X * 1.", ["X = 1"]);
+    assert_eq!(submit(&mut wam, "?- X is 1, X is X * 2."), false);
+
+    assert_eq!(submit(&mut wam, "?- X is 1 + a."), false);
+    assert_eq!(submit(&mut wam, "?- X is 1 + Y."), false);
+    assert_prolog_success!(&mut wam, "?- Y is 2 + 2 - 2, X is 1 + Y, X = 3.",
+                           ["X = 3", "Y = 2"]);
+    assert_eq!(submit(&mut wam, "?- Y is 2 + 2 - 2, X is 1 + Y, X = 2."), false);
+
+    assert_eq!(submit(&mut wam, "?- 6 is 6."), true);
+    assert_eq!(submit(&mut wam, "?- 6 is 3 + 3."), true);
+    assert_eq!(submit(&mut wam, "?- 6 is 3 * 2."), true);
+    assert_eq!(submit(&mut wam, "?- 7 is 3 * 2."), false);
+    assert_eq!(submit(&mut wam, "?- 7 is 3.5 * 2."), false);
+    assert_eq!(submit(&mut wam, "?- 7.0 is 3.5 * 2."), true);
+    assert_eq!(submit(&mut wam, "?- 7.0 is 14 / 2."), true);
+    assert_eq!(submit(&mut wam, "?- 4.666 is 14.0 / 3."), false);
+    assert_eq!(submit(&mut wam, "?- 4.0 is 8.0 / 2."), true);
+
+    submit(&mut wam, "f(X) :- X is 5 // 0.");
+
+    assert_prolog_success!(&mut wam, "?- catch(f(X), evaluation_error(E), true), E = zero_divisor.",
+                           ["E = zero_divisor", "X = _1"]);
+    
+    submit(&mut wam, "f(X) :- X is (5 rdiv 1) / 0.");
+
+    assert_prolog_success!(&mut wam, "?- catch(f(X), evaluation_error(E), true), E = zero_divisor.",
+                           ["E = zero_divisor", "X = _1"]);
+    
+    submit(&mut wam, "f(X) :- X is 5.0 / 0.");
+
+    assert_prolog_success!(&mut wam, "?- catch(f(X), evaluation_error(E), true), E = zero_divisor.",
+                           ["E = zero_divisor", "X = _1"]);
+    
+    assert_prolog_success!(&mut wam, "?- X is ((3 + 4) // 2) + 2 - 1 // 1, Y is 2+2, Z is X+Y.",
+                           ["Y = 4", "X = 4", "Z = 8"]);
+
+    assert_prolog_success!(&mut wam, "?- X is ((3 + 4) // 2) + 2 - 1 // 1, Y is 2+2, Z = 8, Y is 4.",
+                           ["Y = 4", "X = 4", "Z = 8"]);
+
+    assert_prolog_success!(&mut wam, "?- X is (3 rdiv 4) / 2, Y is 3 rdiv 8, X = Y.",
+                           ["X = 3/8", "Y = 3/8"]);
+
+    assert_prolog_success!(&mut wam, "?- X is 10 xor -4, X is -10.", ["X = -10"]);
+    assert_prolog_success!(&mut wam, "?- X is 4 xor -7, X is -3.", ["X = -3"]);
+    assert_prolog_success!(&mut wam, "?- X is 10 xor 5 + 55, X = 70.", ["X = 70"]);
+    
+    assert_prolog_success!(&mut wam, "?- X is 10 rem -3, X = 1.", ["X = 1"]);
+    assert_prolog_success!(&mut wam, "?- X is 10 mod -3, X is -2.", ["X = -2"]);
+}