add support for conjunctive queries.

This commit is contained in:
Mark Thom
2017-05-07 15:26:36 -06:00
parent 9687878219
commit f155b5b2c2
17 changed files with 2109 additions and 1475 deletions

2
Cargo.lock generated
View File

@@ -1,6 +1,6 @@
[root]
name = "rusty-wam"
version = "0.6.0"
version = "0.6.1"
dependencies = [
"lalrpop 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)",
"lalrpop-util 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@@ -1,6 +1,6 @@
[package]
name = "rusty-wam"
version = "0.6.0"
version = "0.6.1"
authors = ["Mark Thom"]
build = "build.rs"

View File

@@ -8,11 +8,11 @@ pure Prolog.
## Progress
Prolog is implemented as a simple REPL. It is without without meta- or
Prolog is implemented as a simple REPL. It is without meta- or
extra-logical operators, or side effects of any kind, with the lone
exception of cut. In terms of the tutorial pacing, the work covers in
some form all of the WAM book, including lists, cuts, Debray
allocation, and indexing.
allocation, indexing, and conjunctive queries.
## Tutorial
To enter a multi-clause predicate, the brackets ":{" and "}:" are used
@@ -76,6 +76,29 @@ Press ; to continue or . to abort.
;
no
```
and so do conjunctive queries:
```
prolog> ?- 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]).
yes
Y = d
X = d
Press ; to continue or . to abort.
Y = a
X = d
Press ; to continue or . to abort.
Y = b
X = d
Press ; to continue or . to abort.
Y = c
X = d
Press ; to continue or . to abort.
Y = d
X = d
Press ; to continue or . to abort.
no
prolog>
```
Note that the values of variables belonging to successful queries are
printed out, on one line each. Uninstantiated variables are denoted by

View File

@@ -3,16 +3,27 @@ mod prolog;
use prolog::io::*;
use prolog::machine::*;
use prolog::prolog_parser::*;
#[cfg(test)]
mod tests {
use super::*;
use prolog::ast::*;
use prolog::codegen::*;
fn submit(wam: &mut Machine, buffer: &str) -> EvalResult {
let result = eval(wam, buffer);
fn submit(wam: &mut Machine, buffer: &str) -> bool {
wam.reset();
result
match parse_TopLevel(buffer.trim()) {
Ok(tl) =>
match eval(wam, &tl) {
EvalResult::InitialQuerySuccess(_, _) |
EvalResult::EntrySuccess |
EvalResult::SubsequentQuerySuccess =>
true,
_ => false
},
Err(_) => panic!("Bad parse in test case!")
}
}
#[test]
@@ -23,28 +34,28 @@ mod tests {
submit(&mut wam, "clouds(are, nice).");
// submit returns true on failure, false on success.
assert_eq!(submit(&mut wam, "?- p(Z, Z).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(Z, z).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(Z, w).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(z, w).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(w, w).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- clouds(Z, Z).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- clouds(are, Z).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- clouds(Z, nice).").failed_query(), false);
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)).").failed_query(), 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)).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(z, h(z, w), f(w)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(z, h(z, W), f(w)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(Z, h(Z, w), f(Z)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(z, h(Z, w), f(Z)).").failed_query(), true);
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)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(Z, h(Z, W), f(W))."), true);
}
#[test]
@@ -55,48 +66,48 @@ mod tests {
submit(&mut wam, "q(q, s).");
submit(&mut wam, "r(s, t).");
assert_eq!(submit(&mut wam, "?- p(X, Y).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(q, t).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(t, q).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(q, T).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(Q, t).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(t, t).").failed_query(), true);
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).").failed_query(), false);
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).").failed_query(), false);
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).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(t, S).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(t, s).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(s, T).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(S, t).").failed_query(), false);
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).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(f(X, g(Y), Z), g(Z), X).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(f(X, g(Y), Z), g(Z), h).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(Z, Y, X).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(f(X, Y, Z), Y, h).").failed_query(), false);
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, _)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(_, f(_, y, _)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(_, f(_, z, _)).").failed_query(), true);
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]
@@ -105,55 +116,55 @@ mod tests {
submit(&mut wam, "p(X, a). p(b, X).");
assert_eq!(submit(&mut wam, "?- p(x, Y).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(X, a).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(b, X).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(X, X).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(b, a).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(a, b).").failed_query(), true);
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).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(a, a, a).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(b, c, d).").failed_query(), true);
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).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(x, a).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(X, a).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(X, b).").failed_query(), true);
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).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(x, a).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(X, Y).").failed_query(), false);
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).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(X, b).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(X, Y)."), true);
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).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(X, z).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(a, z).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(a, X).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(b, a).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(X, Y)."), true);
assert_eq!(submit(&mut wam, "?- p(X, z)."), true);
assert_eq!(submit(&mut wam, "?- p(a, z)."), true);
assert_eq!(submit(&mut wam, "?- p(a, X)."), true);
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).");
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).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(a, b, c).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(a, b, C).").failed_query(), false);
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.");
@@ -162,10 +173,10 @@ mod tests {
submit(&mut wam, "s(x, t).");
submit(&mut wam, "t(y, u).");
assert_eq!(submit(&mut wam, "?- p(X).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(x).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(y).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(z).").failed_query(), true);
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).");
@@ -174,24 +185,24 @@ mod tests {
submit(&mut wam, "f(s).");
submit(&mut wam, "z(Z).");
assert_eq!(submit(&mut wam, "?- p(X, Y, Z).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(X, X, Z).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(f(f(Z)), Y, Z).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(X, X, X).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(X, Y, X).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(f(f(X)), h(f(X)), Y).").failed_query(), true);
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).").failed_query(), false);
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).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(X)."), true);
}
#[test]
@@ -202,77 +213,77 @@ mod tests {
submit(&mut wam, "memberchk(X, [X|_]) :- !.
memberchk(X, [_|Xs]) :- memberchk(X, Xs).");
assert_eq!(submit(&mut wam, "?- memberchk(X, [a,b,c]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- memberchk([X,X], [a,b,c,[d,e],[d,d]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- memberchk([X,X], [a,b,c,[D,d],[e,e]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- memberchk([X,X], [a,b,c,[e,d],[f,e]]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- memberchk([X,X,Y], [a,b,c,[e,d],[f,e]]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- memberchk([X,X,Y], [a,b,c,[e,e,d],[f,e]]).").failed_query(), false);
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.").failed_query(), true);
assert_eq!(submit(&mut wam, "?- commit."), false);
submit(&mut wam, "a.");
assert_eq!(submit(&mut wam, "?- commit.").failed_query(), false);
assert_eq!(submit(&mut wam, "?- commit."), true);
submit(&mut wam, "commit(X) :- a(X), !.");
assert_eq!(submit(&mut wam, "?- commit(X).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- commit(X)."), false);
submit(&mut wam, "a(x).");
assert_eq!(submit(&mut wam, "?- commit(X).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- commit(X)."), true);
submit(&mut wam, "a :- b, !, c. a :- d.");
assert_eq!(submit(&mut wam, "?- a.").failed_query(), true);
assert_eq!(submit(&mut wam, "?- a."), false);
submit(&mut wam, "b.");
assert_eq!(submit(&mut wam, "?- a.").failed_query(), true);
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.").failed_query(), true);
assert_eq!(submit(&mut wam, "?- a."), false);
submit(&mut wam, "c.");
assert_eq!(submit(&mut wam, "?- a.").failed_query(), false);
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).").failed_query(), true);
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).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- a(X)."), true);
submit(&mut wam, "b.");
assert_eq!(submit(&mut wam, "?- a(X).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- a(X)."), true);
wam.clear();
assert_eq!(submit(&mut wam, "?- c(X).").failed_query(), true);
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).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- a(X)."), false);
submit(&mut wam, "d(d).");
assert_eq!(submit(&mut wam, "?- a(X).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- a(X)."), true);
submit(&mut wam, "c(c).");
assert_eq!(submit(&mut wam, "?- a(X).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- a(X)."), true);
}
#[test]
@@ -281,44 +292,44 @@ mod tests {
submit(&mut wam, "p([Z, W]).");
assert_eq!(submit(&mut wam, "?- p([Z, Z]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z, W, Y]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p([Z | W]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z | [Z]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z | [W]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z | []]).").failed_query(), true);
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]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z, W, Y]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p([Z | W]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z | [Z]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z | [W]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z | []]).").failed_query(), true);
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]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p([Z, W, Y]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p([Z | W]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Z | [Z]]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p([Z | [W]]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p([Z | []]).").failed_query(), false);
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]]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- member(c, [a, [X, Y]]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- member(a, [a, [X, Y]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- member(a, [X, Y, Z]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- member([X, X], [a, [X, Y]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- member([X, X], [a, [b, c], [b, b], [Z, x], [d, f]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- member([X, X], [a, [b, c], [b, d], [foo, x], [d, f]]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- member([X, Y], [a, [b, c], [b, b], [Z, x], [d, f]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- member([X, Y, Y], [a, [b, c], [b, b], [Z, x], [d, f]]).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- member([X, Y, Z], [a, [b, c], [b, b], [Z, x], [d, f]]).").failed_query(), true);
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]
@@ -336,92 +347,92 @@ mod tests {
p(X) :- x.
p([c, d, e]).");
assert_eq!(submit(&mut wam, "?- p(a).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(b).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(c).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(f(a)).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(g(b, X)).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(g(Y, X)).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(g(Y, c)).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(g(b)).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p([]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([c, d, e]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([c, d | X]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([c|X]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Y|X]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Y|[d|Xs]]).").failed_query(), false);
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).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(b).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(c).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(f(a)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(g(b, X)).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(g(Y, X)).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(g(Y, c)).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(g(b)).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p([]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([c, d, e]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([c, d | X]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([c|X]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Y|X]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Y|[d|Xs]]).").failed_query(), false);
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).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(b).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(c).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- p(f(a)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(g(b, X)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(g(Y, X)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(g(Y, c)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(g(b)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([c, d, e]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([c, d | X]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([c|X]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Y|X]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Y|[d|Xs]]).").failed_query(), false);
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).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(b).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(c).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(f(a)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(g(b, X)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(g(Y, X)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(g(Y, c)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(g(b)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([c, d, e]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([c, d | X]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([c|X]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Y|X]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Y|[d|Xs]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(blah).").failed_query(), true);
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).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(b).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(c).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(f(a)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(g(b, X)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(g(Y, X)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(g(Y, c)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(g(b)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([c, d, e]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([c, d | X]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([c|X]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Y|X]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p([Y|[d|Xs]]).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- p(blah).").failed_query(), false);
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, "call(or(X, Y)) :- call(X).
call(trace) :- trace.
@@ -433,41 +444,116 @@ mod tests {
call(call(X)) :- call(X).
call(repeat).
call(repeat) :- call(repeat).
call(true).");
call(false).");
assert_eq!(submit(&mut wam, "?- call(repeat).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(true).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(call(repeat)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(call(true)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(notrace).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- call(nl).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- call(builtin(X)).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- call(extern(X)).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- call(repeat)."), true);
assert_eq!(submit(&mut wam, "?- call(false)."), true);
assert_eq!(submit(&mut wam, "?- call(call(repeat))."), true);
assert_eq!(submit(&mut wam, "?- call(call(false))."), true);
assert_eq!(submit(&mut wam, "?- call(notrace)."), false);
assert_eq!(submit(&mut wam, "?- call(nl)."), false);
assert_eq!(submit(&mut wam, "?- call(builtin(X))."), false);
assert_eq!(submit(&mut wam, "?- call(extern(X))."), false);
submit(&mut wam, "notrace.");
submit(&mut wam, "nl.");
assert_eq!(submit(&mut wam, "?- call(repeat).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(true).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(call(repeat)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(call(true)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(notrace).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(nl).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(builtin(X)).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- call(extern(X)).").failed_query(), true);
assert_eq!(submit(&mut wam, "?- call(repeat)."), true);
assert_eq!(submit(&mut wam, "?- call(false)."), true);
assert_eq!(submit(&mut wam, "?- call(call(repeat))."), true);
assert_eq!(submit(&mut wam, "?- call(call(false))."), true);
assert_eq!(submit(&mut wam, "?- call(notrace)."), true);
assert_eq!(submit(&mut wam, "?- call(nl)."), true);
assert_eq!(submit(&mut wam, "?- call(builtin(X))."), false);
assert_eq!(submit(&mut wam, "?- call(extern(X))."), false);
submit(&mut wam, "builtin(X).");
submit(&mut wam, "extern(x).");
assert_eq!(submit(&mut wam, "?- call(repeat).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(true).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(call(repeat)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(call(true)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(notrace).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(nl).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(builtin(X)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(extern(X)).").failed_query(), false);
assert_eq!(submit(&mut wam, "?- call(repeat)."), true);
assert_eq!(submit(&mut wam, "?- call(false)."), true);
assert_eq!(submit(&mut wam, "?- call(call(repeat))."), true);
assert_eq!(submit(&mut wam, "?- call(call(false))."), true);
assert_eq!(submit(&mut wam, "?- call(notrace)."), true);
assert_eq!(submit(&mut wam, "?- call(nl)."), true);
assert_eq!(submit(&mut wam, "?- call(builtin(X))."), true);
assert_eq!(submit(&mut wam, "?- 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);
}
}
fn process_buffer(wam: &mut Machine, buffer: &str)
{
match parse_TopLevel(buffer.trim()) {
Ok(tl) => {
let result = eval(wam, &tl);
print(wam, result);
},
Err(_) => {
println!("Grammatical error of some kind!");
}
};
}
fn prolog_repl() {
@@ -481,13 +567,11 @@ fn prolog_repl() {
if buffer == "quit\n" {
break;
} else if buffer == "clear\n" {
wam = Machine::new();
wam.clear();
continue;
}
let result = eval(&mut wam, buffer.trim());
print(&mut wam, result);
process_buffer(&mut wam, buffer.trim());
wam.reset();
}
}

58
src/prolog/allocator.rs Normal file
View File

@@ -0,0 +1,58 @@
use prolog::ast::*;
use prolog::fixtures::*;
use prolog::targets::*;
use std::cell::Cell;
pub trait Allocator<'a>
{
fn new() -> Self;
fn mark_anon_var<Target>(&mut self, Level, &mut Vec<Target>)
where Target: CompilationTarget<'a>;
fn mark_non_var<Target>(&mut self, Level, GenContext, &'a Cell<RegType>, &mut Vec<Target>)
where Target: CompilationTarget<'a>;
fn mark_var<Target>(&mut self, &'a Var, Level, &'a Cell<VarReg>, GenContext, &mut Vec<Target>)
where Target: CompilationTarget<'a>;
fn reset(&mut self);
fn reset_contents(&mut self) {}
fn advance(&mut self, GenContext, &'a Term);
fn advance_arg(&mut self);
fn bindings(&self) -> &AllocVarDict<'a>;
fn bindings_mut(&mut self) -> &mut AllocVarDict<'a>;
fn take_bindings(self) -> AllocVarDict<'a>;
fn drain_var_data(&mut self, vs: VariableFixtures<'a>) -> VariableFixtures<'a>
{
let mut perm_vs = VariableFixtures::new();
for (var, (var_status, cells)) in vs.into_iter() {
match var_status {
VarStatus::Temp(chunk_num, tvd) => {
self.bindings_mut().insert(var, VarData::Temp(chunk_num, 0, tvd));
},
VarStatus::Perm(_) => {
self.bindings_mut().insert(var, VarData::Perm(0));
perm_vs.insert(var, (var_status, cells));
}
};
}
perm_vs
}
fn get(&self, var: &'a Var) -> RegType {
self.bindings().get(var).unwrap().as_reg_type()
}
fn record_register(&mut self, var: &'a Var, r: RegType) {
match self.bindings_mut().get_mut(var).unwrap() {
&mut VarData::Temp(_, ref mut s, _) => *s = r.reg_num(),
&mut VarData::Perm(ref mut s) => *s = r.reg_num()
}
}
}

View File

@@ -1,4 +1,5 @@
use std::cell::Cell;
use std::cmp::Ordering;
use std::collections::{HashMap, VecDeque};
use std::ops::{Add, AddAssign};
use std::vec::Vec;
@@ -43,7 +44,7 @@ impl PredicateClause {
pub enum TopLevel {
Fact(Term),
Predicate(Vec<PredicateClause>),
Query(Term),
Query(Vec<TermOrCut>),
Rule(Rule)
}
@@ -266,17 +267,6 @@ pub enum Line {
Query(CompiledQuery)
}
pub enum LineOrCodeOffset<'a> {
Instruction(&'a Line),
Offset(usize)
}
impl<'a> From<&'a Line> for LineOrCodeOffset<'a> {
fn from(line: &'a Line) -> Self {
LineOrCodeOffset::Instruction(line)
}
}
pub type ThirdLevelIndex = Vec<IndexedChoiceInstruction>;
pub type Code = Vec<Line>;
@@ -369,15 +359,29 @@ impl HeapCellValue {
}
}
#[derive(Clone, Copy)]
#[derive(Clone, Copy, PartialEq)]
pub enum CodePtr {
DirEntry(usize),
TopLevel
TopLevel(usize, usize, usize) // chunk_num, e, offset.
}
impl PartialOrd<CodePtr> for CodePtr {
fn partial_cmp(&self, other: &CodePtr) -> Option<Ordering> {
match (self, other) {
(&CodePtr::DirEntry(p1), &CodePtr::DirEntry(ref p2)) =>
p1.partial_cmp(p2),
(&CodePtr::DirEntry(_), &CodePtr::TopLevel(_, _, _)) =>
Some(Ordering::Less),
(&CodePtr::TopLevel(_, _, p1), &CodePtr::TopLevel(_, _, ref p2)) =>
p1.partial_cmp(p2),
_ => Some(Ordering::Greater)
}
}
}
impl Default for CodePtr {
fn default() -> Self {
CodePtr::TopLevel
CodePtr::TopLevel(0, 0, 0)
}
}
@@ -387,7 +391,7 @@ impl Add<usize> for CodePtr {
fn add(self, rhs: usize) -> Self::Output {
match self {
CodePtr::DirEntry(p) => CodePtr::DirEntry(p + rhs),
CodePtr::TopLevel => CodePtr::TopLevel
CodePtr::TopLevel(cn, e, p) => CodePtr::TopLevel(cn, e, p + rhs)
}
}
}
@@ -395,8 +399,8 @@ impl Add<usize> for CodePtr {
impl AddAssign<usize> for CodePtr {
fn add_assign(&mut self, rhs: usize) {
match self {
&mut CodePtr::DirEntry(ref mut p) => *p += rhs,
_ => {}
&mut CodePtr::DirEntry(ref mut p) |
&mut CodePtr::TopLevel(_, _, ref mut p) => *p += rhs
}
}
}
@@ -430,6 +434,13 @@ impl Term {
}
}
pub fn subterms(&self) -> usize {
match self {
&Term::Clause(_, _, ref terms) => terms.len(),
_ => 1
}
}
pub fn name(&self) -> Option<&Atom> {
match self {
&Term::Constant(_, Constant::Atom(ref atom))
@@ -445,24 +456,3 @@ impl Term {
}
}
}
pub type HeapVarDict = HashMap<Var, Addr>;
pub enum EvalResult {
EntryFailure,
EntrySuccess,
InitialQuerySuccess(HeapVarDict),
QueryFailure,
SubsequentQuerySuccess,
}
impl EvalResult {
#[allow(dead_code)]
pub fn failed_query(&self) -> bool {
if let &EvalResult::QueryFailure = self {
true
} else {
false
}
}
}

View File

@@ -1,5 +1,5 @@
use prolog::allocator::*;
use prolog::ast::*;
use prolog::debray_allocator::*;
use prolog::fixtures::*;
use prolog::indexing::*;
use prolog::iterators::*;
@@ -9,19 +9,38 @@ use std::cell::Cell;
use std::collections::HashMap;
use std::vec::Vec;
pub struct CodeGenerator<'a> {
marker: TermMarker<'a>,
pub struct CodeGenerator<'a, TermMarker> {
marker: TermMarker,
var_count: HashMap<&'a Var, usize>
}
impl<'a> CodeGenerator<'a> {
pub enum EvalResult<'a> {
EntryFailure,
EntrySuccess,
InitialQuerySuccess(AllocVarDict<'a>, HeapVarDict<'a>),
QueryFailure,
SubsequentQuerySuccess,
}
impl<'a> EvalResult<'a> {
#[allow(dead_code)]
pub fn failed_query(&self) -> bool {
if let &EvalResult::QueryFailure = self {
true
} else {
false
}
}
}
impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> {
pub fn new() -> Self {
CodeGenerator { marker: TermMarker::new(),
CodeGenerator { marker: Allocator::new(),
var_count: HashMap::new() }
}
pub fn vars(&self) -> &HashMap<&Var, VarData> {
&self.marker.bindings
pub fn take_vars(self) -> AllocVarDict<'a> {
self.marker.take_bindings()
}
fn update_var_count<Iter>(&mut self, iter: Iter)
@@ -232,76 +251,30 @@ impl<'a> CodeGenerator<'a> {
}
}
fn lco(body: &mut Code, rule: &'a Rule) -> usize
fn lco(body: &mut Code, toc: &TermOrCut) -> usize
{
let last_arity = rule.last_clause().arity();
let last_arity = toc.arity();
let mut dealloc_index = body.len() - 1;
match rule.last_clause() {
&TermOrCut::Term(Term::Clause(_, ref name, _))
| &TermOrCut::Term(Term::Constant(_, Constant::Atom(ref name))) => {
if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() {
*ctrl = ControlInstruction::Execute(name.clone(), last_arity);
}
},
match toc {
&TermOrCut::Term(Term::Clause(_, ref name, _))
| &TermOrCut::Term(Term::Constant(_, Constant::Atom(ref name))) => {
if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() {
*ctrl = ControlInstruction::Execute(name.clone(), last_arity);
}
},
_ => dealloc_index = body.len()
};
dealloc_index
}
pub fn compile_rule(&mut self, rule: &'a Rule) -> Code
fn compile_seq(&mut self,
clauses: &'a [TermOrCut],
vs: &VariableFixtures<'a>,
body: &mut Code,
is_exposed: bool)
{
let iter = ChunkedIterator::from_rule(rule);
let (mut vs, deep_cuts) = self.collect_var_data(iter);
vs = self.marker.drain_var_data(vs);
let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
self.marker.advance(p0);
let perm_vars = vs.vars_above_threshold(0) + deep_cuts as usize;
let mut body = Vec::new();
if clauses.len() > 0 {
body.push(Line::Control(ControlInstruction::Allocate(perm_vars)));
if deep_cuts {
body.push(Line::Cut(CutInstruction::GetLevel));
}
}
if p0.is_clause() {
body.push(Line::Fact(self.compile_target(p0, GenContext::Head, false)));
}
match p1 {
&TermOrCut::Cut => {
let term = if clauses.is_empty() {
Terminal::Terminal
} else {
Terminal::Non
};
body.push(Line::Cut(CutInstruction::NeckCut(term)));
},
&TermOrCut::Term(ref p1) => {
self.marker.advance(p1);
if p1.is_clause() {
let term_loc = if p1.is_callable() {
GenContext::Last(0)
} else {
GenContext::Mid(0)
};
body.push(Line::Query(self.compile_target(p1, term_loc, false)));
}
Self::add_conditional_call(&mut body, p1, perm_vars);
}
};
let iter = ChunkedIterator::from_term_sequence(clauses);
for (chunk_num, (_, terms)) in iter.enumerate() {
@@ -315,17 +288,114 @@ impl<'a> CodeGenerator<'a> {
vec![Line::Cut(CutInstruction::Cut(Terminal::Terminal))],
&TermOrCutRef::Term(term) if i + 1 < terms.len() => {
let num_vars = vs.vars_above_threshold(i + 1);
self.compile_internal_query(term, GenContext::Mid(chunk_num), num_vars)
self.compile_internal_query(term,
GenContext::Mid(chunk_num),
num_vars,
is_exposed)
},
&TermOrCutRef::Term(term) => {
let num_vars = vs.vars_above_threshold(i + 1);
self.compile_internal_query(term, GenContext::Last(chunk_num), num_vars)
self.compile_internal_query(term,
GenContext::Last(chunk_num),
num_vars,
is_exposed)
}
};
body.append(&mut body_appendage);
}
}
}
fn compile_seq_prelude(&mut self,
num_clauses: usize,
vs: &VariableFixtures<'a>,
deep_cuts: bool,
body: &mut Code)
-> usize
{
let perm_vars = vs.vars_above_threshold(0) + deep_cuts as usize;
if num_clauses > 0 {
body.push(Line::Control(ControlInstruction::Allocate(perm_vars)));
if deep_cuts {
body.push(Line::Cut(CutInstruction::GetLevel));
}
}
perm_vars
}
fn compile_neck_cut_or(&mut self,
p1: &'a TermOrCut,
clauses: &'a [TermOrCut],
body: &mut Code,
perm_vars: usize,
is_exposed: bool)
{
match p1 {
&TermOrCut::Cut => {
let term = if clauses.is_empty() {
Terminal::Terminal
} else {
Terminal::Non
};
body.push(Line::Cut(CutInstruction::NeckCut(term)));
},
&TermOrCut::Term(ref p1) => {
self.marker.advance(GenContext::Head, p1);
if p1.is_clause() {
let term_loc = if p1.is_callable() {
GenContext::Last(0)
} else {
GenContext::Mid(0)
};
body.push(Line::Query(self.compile_target(p1, term_loc, is_exposed)));
}
Self::add_conditional_call(body, p1, perm_vars);
}
};
}
fn compile_cleanup(body: &mut Code, num_clauses: usize, toc: &TermOrCut)
{
let dealloc_index = Self::lco(body, toc);
if num_clauses > 0 {
body.insert(dealloc_index, Line::Control(ControlInstruction::Deallocate));
}
}
pub fn compile_rule<'b: 'a>(&mut self, rule: &'b Rule) -> Code
{
let iter = ChunkedIterator::from_rule(rule);
let (mut vs, deep_cuts) = self.collect_var_data(iter);
vs = self.marker.drain_var_data(vs);
let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
let mut body = Vec::new();
self.marker.advance(GenContext::Head, p0);
let perm_vars = self.compile_seq_prelude(clauses.len(), &vs, deep_cuts, &mut body);
if p0.is_clause() {
body.push(Line::Fact(self.compile_target(p0, GenContext::Head, false)));
}
let clauses_slice = if clauses.len() > 1 {
&clauses[1 .. ]
} else {
&[]
};
self.compile_neck_cut_or(p1, clauses_slice, &mut body, perm_vars, false);
self.compile_seq(clauses, &vs, &mut body, false);
if clauses.len() > 0 {
let mut index = body.len() - 1;
@@ -335,15 +405,11 @@ impl<'a> CodeGenerator<'a> {
}
if let &mut Line::Query(ref mut query) = &mut body[index] {
vs.mark_unsafe_query_vars(p0, query);
vs.mark_unsafe_vars_in_rule(p0, query);
}
}
let dealloc_index = Self::lco(&mut body, &rule);
if clauses.len() > 0 {
body.insert(dealloc_index, Line::Control(ControlInstruction::Deallocate));
}
Self::compile_cleanup(&mut body, clauses.len(), rule.last_clause());
body
}
@@ -352,7 +418,7 @@ impl<'a> CodeGenerator<'a> {
{
let mut unsafe_vars = HashMap::new();
for var_status in self.marker.bindings.values() {
for var_status in self.marker.bindings().values() {
unsafe_vars.insert(var_status.as_reg_type(), false);
}
@@ -375,13 +441,13 @@ impl<'a> CodeGenerator<'a> {
}
}
pub fn compile_fact(&mut self, term: &'a Term) -> Code
pub fn compile_fact<'b: 'a>(&mut self, term: &'b Term) -> Code
{
let iter = ChunkedIterator::from_term(term, true);
let (vs, _) = self.collect_var_data(iter);
self.marker.drain_var_data(vs);
self.marker.advance(term);
self.marker.advance(GenContext::Head, term);
let mut code = Vec::new();
@@ -397,14 +463,19 @@ impl<'a> CodeGenerator<'a> {
code
}
fn compile_internal_query(&mut self, term: &'a Term, term_loc: GenContext, index: usize) -> Code
fn compile_internal_query(&mut self,
term: &'a Term,
term_loc: GenContext,
index: usize,
is_exposed: bool)
-> Code
{
self.marker.advance(term);
self.marker.advance(term_loc, term);
let mut code = Vec::new();
if term.is_clause() {
let compiled_query = Line::Query(self.compile_target(term, term_loc, false));
let compiled_query = Line::Query(self.compile_target(term, term_loc, is_exposed));
code.push(compiled_query);
}
@@ -413,22 +484,38 @@ impl<'a> CodeGenerator<'a> {
code
}
pub fn compile_query(&mut self, term: &'a Term) -> Code
pub fn compile_query(&mut self, query: &'a Vec<TermOrCut>) -> Code
{
let iter = ChunkedIterator::from_term(term, true);
let (vs, _) = self.collect_var_data(iter);
let iter = ChunkedIterator::from_term_sequence(query);
let (mut vs, deep_cuts) = self.collect_var_data(iter);
let p1 = query.first().unwrap();
self.marker.drain_var_data(vs);
self.marker.advance(term);
vs = self.marker.drain_var_data(vs);
let mut code = Vec::new();
let mut code = Vec::new();
let perm_vars = self.compile_seq_prelude(query.len() - 1,
&vs,
deep_cuts,
&mut code);
if term.is_clause() {
let compiled_query = self.compile_target(term, GenContext::Last(0), true);
code.push(Line::Query(compiled_query));
let query_slice = if query.len() > 1 {
&query[1 .. ]
} else {
&[]
};
self.compile_neck_cut_or(p1, query_slice, &mut code, perm_vars, true);
self.compile_seq(query_slice, &vs, &mut code, true);
for line in code.iter_mut() {
match line {
&mut Line::Query(ref mut query) =>
vs.mark_unsafe_vars_in_query(query),
_ => {}
};
}
Self::add_conditional_call(&mut code, term, 0);
Self::compile_cleanup(&mut code, query.len() - 1, query.last().unwrap());
code
}
@@ -456,12 +543,12 @@ impl<'a> CodeGenerator<'a> {
subseqs
}
fn compile_pred_subseq(&mut self, clauses: &'a [PredicateClause]) -> Code
fn compile_pred_subseq<'b: 'a>(&mut self, clauses: &'b [PredicateClause]) -> Code
{
let mut code_body = Vec::new();
let mut code_offsets = CodeOffsets::new();
let multi_clause = clauses.len() > 1;
let num_clauses = clauses.len();
for (i, clause) in clauses.iter().enumerate() {
self.marker.reset();
@@ -473,10 +560,10 @@ impl<'a> CodeGenerator<'a> {
self.compile_rule(rule)
};
if multi_clause {
if num_clauses > 1 {
let choice = match i {
0 => ChoiceInstruction::TryMeElse(clause_code.len() + 1),
_ if i == clauses.len() - 1 => ChoiceInstruction::TrustMe,
_ if i == num_clauses - 1 => ChoiceInstruction::TrustMe,
_ => ChoiceInstruction::RetryMeElse(clause_code.len() + 1)
};
@@ -497,10 +584,10 @@ impl<'a> CodeGenerator<'a> {
code
}
pub fn compile_predicate(&mut self, clauses: &'a Vec<PredicateClause>) -> Code
pub fn compile_predicate<'b: 'a>(&mut self, clauses: &'b Vec<PredicateClause>) -> Code
{
let mut code = Vec::new();
let split_pred = Self::split_predicate(clauses);
let split_pred = Self::split_predicate(&clauses);
let multi_seq = split_pred.len() > 1;
for (l, r) in split_pred {

View File

@@ -1,3 +1,4 @@
use prolog::allocator::*;
use prolog::ast::*;
use prolog::fixtures::*;
use prolog::targets::*;
@@ -5,25 +6,15 @@ use prolog::targets::*;
use std::cell::Cell;
use std::collections::{BTreeSet, HashMap};
pub struct TermMarker<'a> {
pub bindings: HashMap<&'a Var, VarData>,
pub struct DebrayAllocator<'a> {
bindings: HashMap<&'a Var, VarData>,
arg_c: usize,
temp_lb: usize,
contents: HashMap<usize, &'a Var>,
in_use: BTreeSet<usize>,
}
impl<'a> TermMarker<'a> {
pub fn new() -> TermMarker<'a> {
TermMarker {
arg_c: 1,
temp_lb: 1,
bindings: HashMap::new(),
contents: HashMap::new(),
in_use: BTreeSet::new()
}
}
impl<'a> DebrayAllocator<'a> {
fn occurs_shallowly_in_head(&self, var: &'a Var, r: usize) -> bool
{
match self.bindings.get(var).unwrap() {
@@ -33,25 +24,6 @@ impl<'a> TermMarker<'a> {
}
}
pub fn drain_var_data(&mut self, vs: VariableFixtures<'a>) -> VariableFixtures<'a>
{
let mut perm_vs = VariableFixtures::new();
for (var, (var_status, cells)) in vs.into_iter() {
match var_status {
VarStatus::Temp(chunk_num, tvd) => {
self.bindings.insert(var, VarData::Temp(chunk_num, 0, tvd));
},
VarStatus::Perm(_) => {
self.bindings.insert(var, VarData::Perm(0));
perm_vs.insert(var, (var_status, cells));
}
};
}
perm_vs
}
fn alloc_with_cr(&self, var: &'a Var) -> usize
{
match self.bindings.get(var) {
@@ -186,38 +158,6 @@ impl<'a> TermMarker<'a> {
}
}
fn get(&self, var: &'a Var) -> RegType {
self.bindings.get(var).unwrap().as_reg_type()
}
fn in_place(&self, var: &'a Var, term_loc: GenContext, r: RegType, k: usize) -> bool
{
match term_loc {
GenContext::Head if !r.is_perm() => r.reg_num() == k,
_ => match self.bindings.get(var).unwrap() {
&VarData::Temp(_, o, _) if r.reg_num() == k => o == k,
_ => false
}
}
}
pub fn mark_anon_var<Target>(&mut self, lvl: Level, target: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
let r = RegType::Temp(self.alloc_reg_to_non_var());
match lvl {
Level::Shallow => {
let k = self.arg_c;
self.arg_c += 1;
target.push(Target::argument_to_variable(r, k));
},
Level::Deep =>
target.push(Target::subterm_to_variable(r))
};
}
fn alloc_reg_to_non_var(&mut self) -> usize
{
let mut final_index = 0;
@@ -234,11 +174,51 @@ impl<'a> TermMarker<'a> {
final_index
}
pub fn mark_non_var<Target>(&mut self,
lvl: Level,
term_loc: GenContext,
cell: &Cell<RegType>,
target: &mut Vec<Target>)
fn in_place(&self, var: &'a Var, term_loc: GenContext, r: RegType, k: usize) -> bool
{
match term_loc {
GenContext::Head if !r.is_perm() => r.reg_num() == k,
_ => match self.bindings().get(var).unwrap() {
&VarData::Temp(_, o, _) if r.reg_num() == k => o == k,
_ => false
}
}
}
}
impl<'a> Allocator<'a> for DebrayAllocator<'a>
{
fn new() -> DebrayAllocator<'a> {
DebrayAllocator {
arg_c: 1,
temp_lb: 1,
bindings: HashMap::new(),
contents: HashMap::new(),
in_use: BTreeSet::new()
}
}
fn mark_anon_var<Target>(&mut self, lvl: Level, target: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
let r = RegType::Temp(self.alloc_reg_to_non_var());
match lvl {
Level::Deep => target.push(Target::subterm_to_variable(r)),
Level::Shallow => {
let k = self.arg_c;
self.arg_c += 1;
target.push(Target::argument_to_variable(r, k));
}
};
}
fn mark_non_var<Target>(&mut self,
lvl: Level,
term_loc: GenContext,
cell: &Cell<RegType>,
target: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
let r = cell.get();
@@ -262,12 +242,12 @@ impl<'a> TermMarker<'a> {
}
}
pub fn mark_var<Target>(&mut self,
var: &'a Var,
lvl: Level,
cell: &'a Cell<VarReg>,
term_loc: GenContext,
target: &mut Vec<Target>)
fn mark_var<Target>(&mut self,
var: &'a Var,
lvl: Level,
cell: &'a Cell<VarReg>,
term_loc: GenContext,
target: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
let (r, is_new_var) = match self.get(var) {
@@ -325,30 +305,35 @@ impl<'a> TermMarker<'a> {
}
}
fn record_register(&mut self, var: &'a Var, r: RegType) {
match self.bindings.get_mut(var).unwrap() {
&mut VarData::Temp(_, ref mut s, _) => *s = r.reg_num(),
&mut VarData::Perm(ref mut s) => *s = r.reg_num()
}
}
pub fn advance_arg(&mut self) {
self.arg_c += 1;
}
pub fn advance(&mut self, term: &'a Term) {
self.arg_c = 1;
self.temp_lb = term.arity() + 1;
}
pub fn reset(&mut self) {
fn reset(&mut self) {
self.bindings.clear();
self.contents.clear();
self.in_use.clear();
}
pub fn reset_contents(&mut self) {
fn reset_contents(&mut self) {
self.contents.clear();
self.in_use.clear();
}
fn advance_arg(&mut self) {
self.arg_c += 1;
}
fn bindings(&self) -> &AllocVarDict<'a> {
&self.bindings
}
fn bindings_mut(&mut self) -> &mut AllocVarDict<'a> {
&mut self.bindings
}
fn take_bindings(self) -> AllocVarDict<'a> {
self.bindings
}
fn advance(&mut self, _: GenContext, term: &'a Term) {
self.arg_c = 1;
self.temp_lb = term.arity() + 1;
}
}

View File

@@ -8,6 +8,9 @@ use std::vec::Vec;
pub type OccurrenceSet = BTreeSet<(GenContext, usize)>;
pub type HeapVarDict<'a> = HashMap<&'a Var, Addr>;
pub type AllocVarDict<'a> = HashMap<&'a Var, VarData>;
pub struct TempVarData {
last_term_arity: usize,
pub use_set: OccurrenceSet,
@@ -232,26 +235,8 @@ impl<'a> VariableFixtures<'a>
}
}
pub fn mark_unsafe_query_vars(&self, head: &Term, query: &mut CompiledQuery)
fn mark_unsafe_vars(&self, unsafe_vars: &mut HashMap<RegType, bool>, query: &mut CompiledQuery)
{
let mut unsafe_vars = HashMap::new();
for &(_, ref cb) in self.values() {
if !cb.is_empty() {
let index = cb.first().unwrap().get().norm();
unsafe_vars.insert(index, false);
}
}
for term_ref in head.breadth_first_iter() {
match term_ref {
TermRef::Var(_, cell, _) => {
unsafe_vars.remove(&cell.get().norm());
},
_ => {}
};
}
for query_instr in query.iter_mut() {
match query_instr {
&mut QueryInstruction::PutValue(RegType::Perm(i), arg) =>
@@ -262,7 +247,7 @@ impl<'a> VariableFixtures<'a>
}
},
&mut QueryInstruction::SetVariable(reg)
| &mut QueryInstruction::PutVariable(reg, _) =>
| &mut QueryInstruction::PutVariable(reg, _) =>
if let Some(found) = unsafe_vars.get_mut(&reg) {
*found = true;
},
@@ -277,4 +262,43 @@ impl<'a> VariableFixtures<'a>
};
}
}
fn record_unsafe_vars(&self, unsafe_vars: &mut HashMap<RegType, bool>) {
for &(_, ref cb) in self.values() {
match cb.first() {
Some(index) => {
unsafe_vars.insert(index.get().norm(), false);
},
None => {}
};
}
}
fn mark_head_vars_as_safe(&self, head: &Term, unsafe_vars: &mut HashMap<RegType, bool>)
{
for term_ref in head.breadth_first_iter() {
match term_ref {
TermRef::Var(_, cell, _) => {
unsafe_vars.remove(&cell.get().norm());
},
_ => {}
};
}
}
pub fn mark_unsafe_vars_in_query(&self, query: &mut CompiledQuery) {
let mut unsafe_vars = HashMap::new();
self.record_unsafe_vars(&mut unsafe_vars);
self.mark_unsafe_vars(&mut unsafe_vars, query);
}
pub fn mark_unsafe_vars_in_rule(&self, head: &Term, query: &mut CompiledQuery)
{
let mut unsafe_vars = HashMap::new();
self.record_unsafe_vars(&mut unsafe_vars);
self.mark_head_vars_as_safe(head, &mut unsafe_vars);
self.mark_unsafe_vars(&mut unsafe_vars, query);
}
}

View File

@@ -30,6 +30,7 @@ impl TToken {
#[derive(Clone, Copy)]
enum CellRef<'a> {
Lis(usize),
View(CellView<'a>),
Redirect(usize),
TToken(TToken)
@@ -56,7 +57,9 @@ impl<'a> HeapCellViewer<'a> {
match focus {
&Addr::Con(ref c) =>
return CellRef::View(CellView::Con(c)),
&Addr::Lis(hc) | &Addr::HeapCell(hc) | &Addr::Str(hc) =>
&Addr::Lis(hc) =>
return CellRef::Lis(hc),
&Addr::HeapCell(hc) | &Addr::Str(hc) =>
return CellRef::Redirect(hc),
&Addr::StackCell(fr, sc) => {
match &self.and_stack[fr][sc] {
@@ -108,22 +111,25 @@ impl<'a> HeapCellViewer<'a> {
}
}
fn handle_list(&mut self, focus: usize) -> CellView<'a> {
self.state_stack.push(CellRef::TToken(TToken::RSBracket));
self.state_stack.push(CellRef::Redirect(focus + 1));
self.state_stack.push(CellRef::TToken(TToken::Bar));
self.state_stack.push(CellRef::Redirect(focus));
let len = self.state_stack.len() - 4;
return CellView::TToken(TToken::LSBracket(len));
}
fn from_heap(&mut self, mut focus: usize) -> CellView<'a> {
loop {
match &self.heap[focus] {
&HeapCellValue::Con(ref c) =>
return CellView::Con(c),
&HeapCellValue::Lis(a) => {
self.state_stack.push(CellRef::TToken(TToken::RSBracket));
self.state_stack.push(CellRef::Redirect(a + 1));
self.state_stack.push(CellRef::TToken(TToken::Bar));
self.state_stack.push(CellRef::Redirect(a));
let len = self.state_stack.len() - 4;
return CellView::TToken(TToken::LSBracket(len));
},
&HeapCellValue::Lis(a) =>
return self.handle_list(a),
&HeapCellValue::NamedStr(arity, ref name) => {
self.state_stack.push(CellRef::TToken(TToken::RRBracket));
@@ -146,6 +152,7 @@ impl<'a> HeapCellViewer<'a> {
},
&HeapCellValue::Ref(Ref::StackCell(fr, sc)) => {
match self.cell_ref_from_addr(&self.and_stack[fr][sc]) {
CellRef::Lis(hc) => return self.handle_list(hc),
CellRef::View(cell_view) => return cell_view,
CellRef::Redirect(hc) => focus = hc,
CellRef::TToken(token) => return CellView::TToken(token)
@@ -160,6 +167,8 @@ impl<'a> HeapCellViewer<'a> {
fn follow(&mut self, cell_ref: CellRef<'a>) -> CellView<'a>
{
match cell_ref {
CellRef::Lis(hc) =>
self.handle_list(hc),
CellRef::Redirect(hc) =>
self.from_heap(hc),
CellRef::View(cell_view) =>

View File

@@ -1,6 +1,6 @@
use prolog::ast::*;
use prolog::codegen::*;
use prolog::prolog_parser::*;
use prolog::debray_allocator::*;
use prolog::machine::*;
use termion::raw::IntoRawMode;
@@ -257,13 +257,12 @@ pub fn read() -> String {
result
}
pub fn eval(wam: &mut Machine, buffer: &str) -> EvalResult
pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalResult<'b>
{
let result = parse_TopLevel(buffer);
let mut cg = CodeGenerator::new();
match tl {
&TopLevel::Predicate(ref clauses) => {
let mut cg = CodeGenerator::<DebrayAllocator>::new();
match &result {
&Ok(TopLevel::Predicate(ref clauses)) => {
if is_consistent(clauses) {
let compiled_pred = cg.compile_predicate(clauses);
wam.add_predicate(clauses, compiled_pred);
@@ -277,30 +276,34 @@ Each predicate must have the same name and arity.";
EvalResult::EntryFailure
}
},
&Ok(TopLevel::Fact(ref fact)) => {
let compiled_fact = cg.compile_fact(&fact);
&TopLevel::Fact(ref fact) => {
let mut cg = CodeGenerator::<DebrayAllocator>::new();
let compiled_fact = cg.compile_fact(fact);
wam.add_fact(fact, compiled_fact);
EvalResult::EntrySuccess
},
&Ok(TopLevel::Rule(ref rule)) => {
let compiled_rule = cg.compile_rule(&rule);
&TopLevel::Rule(ref rule) => {
let mut cg = CodeGenerator::<DebrayAllocator>::new();
let compiled_rule = cg.compile_rule(rule);
wam.add_rule(rule, compiled_rule);
EvalResult::EntrySuccess
},
&Ok(TopLevel::Query(ref query)) => {
let compiled_query = cg.compile_query(&query);
wam.run_query(compiled_query, &cg)
},
&Err(_) => {
println!("Grammatical error of some kind!");
EvalResult::EntryFailure
&TopLevel::Query(ref query) => {
let mut cg = CodeGenerator::<DebrayAllocator>::new();
let compiled_query = cg.compile_query(query);
wam.submit_query(compiled_query, cg.take_vars())
}
}
}
pub fn print(wam: &mut Machine, result: EvalResult) {
match result {
EvalResult::InitialQuerySuccess(heap_locs) => {
EvalResult::InitialQuerySuccess(alloc_locs, mut heap_locs) => {
println!("yes");
if heap_locs.is_empty() {
@@ -324,14 +327,14 @@ pub fn print(wam: &mut Machine, result: EvalResult) {
for c in stdin.keys() {
match c.unwrap() {
Key::Char(';') => {
result = wam.continue_query();
result = wam.continue_query(&alloc_locs, &mut heap_locs);
break;
},
Key::Char('.') =>
break 'outer,
_ => {}
}
};
}
if let &EvalResult::QueryFailure = &result {
write!(stdout, "no\n\r").unwrap();

View File

@@ -230,7 +230,7 @@ impl<'a> ChunkedIterator<'a>
}
}
pub fn from_term_sequence(terms: &'a Vec<TermOrCut>) -> Self
pub fn from_term_sequence(terms: &'a [TermOrCut]) -> Self
{
let iter = terms.iter().map(|c| {
match c {

View File

@@ -3,6 +3,7 @@ use prolog::codegen::*;
use prolog::heapview::*;
use prolog::and_stack::*;
use prolog::or_stack::*;
use prolog::fixtures::*;
use std::collections::HashMap;
use std::ops::{Index, IndexMut};
@@ -31,7 +32,7 @@ struct MachineState {
registers: Registers,
trail: Vec<Ref>,
tr: usize,
hb: usize
hb: usize,
}
type CodeDir = HashMap<(Atom, usize), usize>;
@@ -39,7 +40,8 @@ type CodeDir = HashMap<(Atom, usize), usize>;
pub struct Machine {
ms: MachineState,
code: Code,
code_dir: CodeDir
code_dir: CodeDir,
cached_query: Option<Code>
}
impl Index<RegType> for MachineState {
@@ -68,12 +70,29 @@ impl IndexMut<RegType> for MachineState {
}
}
impl Index<CodePtr> for Machine {
type Output = Line;
fn index(&self, ptr: CodePtr) -> &Self::Output {
match ptr {
CodePtr::TopLevel(_, _, p) => {
match &self.cached_query {
&Some(ref cq) => &cq[p],
&None => panic!("Out-of-bounds top level index.")
}
},
CodePtr::DirEntry(p) => &self.code[p]
}
}
}
impl Machine {
pub fn new() -> Self {
Machine {
ms: MachineState::new(),
code: Vec::new(),
code_dir: HashMap::new()
code_dir: HashMap::new(),
cached_query: None
}
}
@@ -84,105 +103,239 @@ impl Machine {
pub fn add_fact(&mut self, fact: &Term, mut code: Code) {
if let Some(name) = fact.name() {
let p = self.code.len();
let name = name.clone();
let arity = fact.arity();
self.code.append(&mut code);
self.code_dir.insert((name.clone(), arity), p);
self.code_dir.insert((name, arity), p);
}
}
pub fn add_rule(&mut self, rule: &Rule, mut code: Code) {
if let Some(name) = rule.head.0.name() {
let p = self.code.len();
let name = name.clone();
let arity = rule.head.0.arity();
self.code.append(&mut code);
self.code_dir.insert((name.clone(), arity), p);
self.code_dir.insert((name, arity), p);
}
}
pub fn add_predicate(&mut self, pred: &Vec<PredicateClause>, mut code: Code)
pub fn add_predicate(&mut self, clauses: &Vec<PredicateClause>, mut code: Code)
{
let p = self.code.len();
let name = pred.first().unwrap().name().clone();
let arity = pred.first().unwrap().arity();
let arity = clauses.first().unwrap().arity();
let name = clauses.first().unwrap().name().clone();
self.code.append(&mut code);
self.code_dir.insert((name, arity), p);
}
fn execute_instr<'a>(&mut self, instr_src: LineOrCodeOffset<'a>) -> bool
fn cached_query_size(&self) -> usize {
match &self.cached_query {
&Some(ref query) => query.len(),
_ => 0
}
}
fn execute_instr(&mut self, ptr: CodePtr)
{
let mut instr = match instr_src {
LineOrCodeOffset::Instruction(instr) => instr,
LineOrCodeOffset::Offset(p) => &self.code[p]
// can't use self[ptr] or self.index(ptr) to set the value of
// instr! instr is then typed as Line, not &Line. WHY????
// This is a compiler bug. Has to be.
let instr = match ptr {
CodePtr::TopLevel(_, _, p) => {
match &self.cached_query {
&Some(ref cq) => &cq[p],
&None => return
}
},
CodePtr::DirEntry(p) => &self.code[p]
};
loop {
match instr {
&Line::Choice(ref choice_instr) =>
self.ms.execute_choice_instr(choice_instr),
&Line::Cut(ref cut_instr) =>
self.ms.execute_cut_instr(cut_instr),
&Line::Control(ref control_instr) =>
self.ms.execute_ctrl_instr(&self.code_dir, control_instr),
&Line::Fact(ref fact) => {
for fact_instr in fact {
if self.failed() {
break;
}
self.ms.execute_fact_instr(&fact_instr);
match instr {
&Line::Choice(ref choice_instr) =>
self.ms.execute_choice_instr(choice_instr),
&Line::Cut(ref cut_instr) =>
self.ms.execute_cut_instr(cut_instr),
&Line::Control(ref control_instr) =>
self.ms.execute_ctrl_instr(&self.code_dir, control_instr),
&Line::Fact(ref fact) => {
for fact_instr in fact {
if self.failed() {
break;
}
self.ms.p += 1;
},
&Line::Indexing(ref indexing_instr) =>
self.ms.execute_indexing_instr(&indexing_instr),
&Line::IndexedChoice(ref choice_instr) =>
self.ms.execute_indexed_choice_instr(choice_instr),
&Line::Query(ref query) => {
for query_instr in query {
if self.failed() {
break;
}
self.ms.execute_query_instr(&query_instr);
}
self.ms.p += 1;
self.ms.execute_fact_instr(&fact_instr);
}
self.ms.p += 1;
},
&Line::Indexing(ref indexing_instr) =>
self.ms.execute_indexing_instr(&indexing_instr),
&Line::IndexedChoice(ref choice_instr) =>
self.ms.execute_indexed_choice_instr(choice_instr),
&Line::Query(ref query) => {
for query_instr in query {
if self.failed() {
break;
}
self.ms.execute_query_instr(&query_instr);
}
self.ms.p += 1;
}
}
}
fn backtrack(&mut self)
{
let b0 = self.ms
.or_stack
.top()
.map(|fr| fr.b0)
.unwrap_or(0);
let p = if self.ms.b > 0 {
let b = self.ms.b - 1;
self.ms.or_stack[b].bp
} else {
self.ms.p = CodePtr::TopLevel(0, 0, 0);
return;
};
self.ms.p = p;
if let CodePtr::TopLevel(_, _, p) = p {
self.ms.fail = p == 0;
self.ms.b0 = b0;
return;
} else {
self.ms.fail = false;
}
}
fn query_stepper<'a>(&mut self, mut ptr: CodePtr)
{
loop
{
self.execute_instr(ptr);
if self.failed() {
let b0 = self.ms
.or_stack
.top()
.map(|fr| fr.b0)
.unwrap_or(0);
let p = if self.ms.b > 0 {
let b = self.ms.b - 1;
self.ms.or_stack[b].bp
} else {
CodePtr::TopLevel
};
if let CodePtr::TopLevel = p {
return false;
} else {
self.ms.fail = false;
self.ms.p = p;
self.ms.b0 = b0;
}
self.backtrack();
}
match self.ms.p {
CodePtr::DirEntry(p) if p < self.code.len() =>
instr = &self.code[p],
ptr = self.ms.p,
_ => break
};
}
}
fn record_var_places<'a>(&self,
chunk_num: usize,
e: usize,
alloc_locs: &AllocVarDict<'a>,
heap_locs: &mut HeapVarDict<'a>)
{
for (var, var_data) in alloc_locs {
match var_data {
&VarData::Perm(_) => {
let r = var_data.as_reg_type().reg_num();
let addr = self.ms.and_stack[e][r].clone();
heap_locs.insert(var, addr);
},
&VarData::Temp(cn, _, _) if cn == chunk_num => {
let r = var_data.as_reg_type();
let addr = self.ms[r].clone();
heap_locs.insert(var, addr);
},
_ => {}
}
}
}
true
fn run_query<'a>(&mut self, alloc_locs: &AllocVarDict<'a>, heap_locs: &mut HeapVarDict<'a>)
{
let end_ptr = CodePtr::TopLevel(0, 0, self.cached_query_size());
let mut tl_ptr = self.ms.p;
while tl_ptr < end_ptr {
self.query_stepper(tl_ptr);
tl_ptr = self.ms.p;
if let &mut CodePtr::TopLevel(ref mut cn, ref mut e, p) = &mut tl_ptr {
if p == 0 {
break;
}
match &self[CodePtr::TopLevel(*cn, *e, p)] {
&Line::Control(ControlInstruction::Call(_, _, _))
| &Line::Control(ControlInstruction::Execute(_, _)) => {
self.record_var_places(*cn, *e, alloc_locs, heap_locs);
*cn += 1;
},
&Line::Control(ControlInstruction::Allocate(_)) =>
*e = self.ms.e,
_ => {}
};
self.ms.p = CodePtr::TopLevel(*cn, *e, p);
} else {
break;
}
}
}
pub fn submit_query<'a>(&mut self, code: Code, alloc_locs: AllocVarDict<'a>) -> EvalResult<'a>
{
let mut heap_locs = HashMap::new();
self.cached_query = Some(code);
self.run_query(&alloc_locs, &mut heap_locs);
if self.failed() {
EvalResult::QueryFailure
} else {
EvalResult::InitialQuerySuccess(alloc_locs, heap_locs)
}
}
pub fn continue_query<'a>(&mut self,
alloc_locs: &AllocVarDict<'a>,
heap_locs: &mut HeapVarDict<'a>)
-> EvalResult
{
if !self.or_stack_is_empty() {
if self.ms.b == 0 {
return EvalResult::QueryFailure;
}
let b = self.ms.b - 1;
self.ms.p = self.ms.or_stack[b].bp;
if let CodePtr::TopLevel(_, _, 0) = self.ms.p {
return EvalResult::QueryFailure
}
self.run_query(alloc_locs, heap_locs);
if self.failed() {
EvalResult::QueryFailure
} else {
EvalResult::SubsequentQuerySuccess
}
} else {
EvalResult::QueryFailure
}
}
pub fn heap_view(&self, var_dir: &HeapVarDict) -> String {
@@ -241,69 +394,10 @@ impl Machine {
result
}
pub fn run_query(&mut self, code: Code, cg: &CodeGenerator) -> EvalResult
{
let mut succeeded = true;
let mut heap_locs = HashMap::new();
for instr in code.iter().take(1) {
succeeded = self.execute_instr(LineOrCodeOffset::from(instr));
}
if succeeded {
for (var, var_data) in cg.vars() {
let r = var_data.as_reg_type();
let addr = self.ms[r].clone();
heap_locs.insert((*var).clone(), addr);
}
for instr in code.iter().skip(1) {
succeeded = self.execute_instr(LineOrCodeOffset::from(instr));
if !succeeded {
break;
}
}
}
if succeeded {
EvalResult::InitialQuerySuccess(heap_locs)
} else {
EvalResult::QueryFailure
}
}
pub fn or_stack_is_empty(&self) -> bool {
self.ms.or_stack.is_empty()
}
pub fn continue_query(&mut self) -> EvalResult
{
if !self.or_stack_is_empty() {
if self.ms.b == 0 {
return EvalResult::QueryFailure;
}
let b = self.ms.b - 1;
self.ms.p = self.ms.or_stack[b].bp;
let succeeded = if let CodePtr::DirEntry(p) = self.ms.p {
self.execute_instr(LineOrCodeOffset::Offset(p))
} else {
false
};
if succeeded {
EvalResult::SubsequentQuerySuccess
} else {
EvalResult::QueryFailure
}
} else {
EvalResult::QueryFailure
}
}
#[allow(dead_code)]
pub fn clear(&mut self) {
self.reset();
self.code.clear();
@@ -319,12 +413,12 @@ impl MachineState {
fn new() -> MachineState {
MachineState { h: 0,
s: 0,
p: CodePtr::TopLevel,
p: CodePtr::default(),
b: 0,
b0: 0,
e: 0,
num_of_args: 0,
cp: CodePtr::TopLevel,
cp: CodePtr::default(),
fail: false,
heap: Vec::with_capacity(256),
mode: MachineMode::Write,
@@ -1112,7 +1206,7 @@ impl MachineState {
}
if let &Terminal::Terminal = term {
self.p = CodePtr::TopLevel;
self.p = CodePtr::default();
} else {
self.p += 1;
}
@@ -1134,7 +1228,7 @@ impl MachineState {
}
if let &Terminal::Terminal = term {
self.p = CodePtr::TopLevel;
self.p = CodePtr::default();
} else {
self.p += 1;
}
@@ -1150,8 +1244,8 @@ impl MachineState {
self.b0 = 0;
self.s = 0;
self.tr = 0;
self.p = CodePtr::TopLevel;
self.cp = CodePtr::TopLevel;
self.p = CodePtr::default();
self.cp = CodePtr::default();
self.num_of_args = 0;
self.fail = false;

View File

@@ -1,3 +1,4 @@
pub mod allocator;
pub mod and_stack;
pub mod ast;
pub mod codegen;
@@ -7,6 +8,7 @@ pub mod heapview;
pub mod indexing;
pub mod io;
pub mod iterators;
pub mod naive_allocator;
pub mod prolog_parser;
pub mod machine;
pub mod or_stack;

View File

@@ -1,163 +1,157 @@
use prolog::allocator::*;
use prolog::ast::*;
use prolog::fixtures::*;
use prolog::targets::*;
use std::cell::Cell;
use std::cmp::max;
use std::collections::{BTreeSet, HashMap};
use std::collections::HashMap;
pub struct TermMarker<'a> {
pub bindings: HashMap<&'a Var, VarData>,
pub struct NaiveAllocator<'a> {
bindings: AllocVarDict<'a>,
arg_c: usize,
temp_c: usize,
contents: HashMap<usize, &'a Var>,
in_use: BTreeSet<usize>,
}
impl<'a> TermMarker<'a> {
pub fn new() -> TermMarker<'a> {
TermMarker {
impl<'a> Allocator<'a> for NaiveAllocator<'a>
{
fn new() -> Self {
NaiveAllocator {
arg_c: 1,
temp_c: 1,
bindings: HashMap::new(),
contents: HashMap::new(),
in_use: BTreeSet::new()
}
}
pub fn drain_var_data(&mut self, vs: VariableFixtures<'a>) -> VariableFixtures<'a>
fn mark_anon_var<Target>(&mut self, lvl: Level, target: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
let mut perm_vs = VariableFixtures::new();
let r = {
let temp = self.temp_c;
self.temp_c += 1;
RegType::Temp(temp)
};
for (var, (var_status, cells)) in vs.into_iter() {
match var_status {
VarStatus::Temp(chunk_num, tvd) => {
self.bindings.insert(var, VarData::Temp(chunk_num, 0, tvd));
match lvl {
Level::Deep => target.push(Target::subterm_to_variable(r)),
Level::Shallow => {
let k = self.arg_c;
self.arg_c += 1;
target.push(Target::argument_to_variable(r, k));
}
}
}
fn mark_non_var<Target>(&mut self,
lvl: Level,
_: GenContext,
cell: &Cell<RegType>,
_: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
let r = cell.get();
if r.reg_num() == 0 {
let r = match lvl {
Level::Shallow => {
let k = self.arg_c;
self.arg_c += 1;
RegType::Temp(k)
},
VarStatus::Perm(_) => {
self.bindings.insert(var, VarData::Perm(0));
perm_vs.insert(var, (var_status, cells));
}
};
}
perm_vs
}
fn get(&self, var: &'a Var) -> RegType {
self.bindings.get(var).unwrap().as_reg_type()
}
pub fn contains_var(&self, var: &'a Var) -> bool {
self.bindings.contains_key(var)
}
pub fn marked_var(&self, var: &'a Var) -> bool {
self.get(var).reg_num() != 0
}
fn record_register(&mut self, var: &'a Var, r: RegType) {
match self.bindings.get_mut(var).unwrap() {
&mut VarData::Temp(_, ref mut s, _) => *s = r.reg_num(),
&mut VarData::Perm(ref mut s) => *s = r.reg_num()
}
}
pub fn mark_non_var(&mut self, lvl: Level, cell: &Cell<RegType>) {
let reg_type = cell.get();
if reg_type.reg_num() == 0 {
match lvl {
Level::Deep if !reg_type.is_perm() => {
_ => {
let temp = self.temp_c;
self.temp_c += 1;
cell.set(RegType::Temp(temp));
},
Level::Shallow if !reg_type.is_perm() => {
let arg = self.arg_c;
self.arg_c += 1;
cell.set(RegType::Temp(arg));
},
_ => {}
RegType::Temp(temp)
}
};
cell.set(r);
}
}
pub fn mark_old_var(&mut self, lvl: Level, var: &'a Var) -> VarReg
fn mark_var<Target>(&mut self,
var: &'a Var,
lvl: Level,
cell: &'a Cell<VarReg>,
_: GenContext,
target: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
let inner_reg = self.get(var);
let (r, is_new_var) = match self.get(var) {
RegType::Temp(0) => {
let o = self.temp_c;
self.temp_c += 1;
(RegType::Temp(o), true)
},
RegType::Perm(0) => {
let pr = cell.get().norm();
self.record_register(var, pr);
(pr, true)
},
r => (r, false)
};
match lvl {
Level::Deep => VarReg::Norm(inner_reg),
Level::Shallow => {
let reg = VarReg::ArgAndNorm(inner_reg, self.arg_c);
let k = self.arg_c;
self.arg_c += 1;
reg
cell.set(VarReg::ArgAndNorm(r, k));
if is_new_var {
target.push(Target::argument_to_variable(r, k));
} else {
target.push(Target::argument_to_value(r, k));
}
},
Level::Deep => {
cell.set(VarReg::Norm(r));
if is_new_var {
target.push(Target::subterm_to_variable(r));
} else {
target.push(Target::subterm_to_value(r));
}
}
};
if !r.is_perm() {
self.record_register(var, r);
}
}
pub fn mark_new_var(&mut self, lvl: Level, var: &'a Var, reg: RegType) -> VarReg
{
let inner_reg = if !reg.is_perm() {
let temp = self.temp_c;
self.temp_c += 1;
RegType::Temp(temp)
fn reset(&mut self) {
self.bindings.clear();
}
fn advance(&mut self, term_loc: GenContext, term: &'a Term) {
if let GenContext::Head = term_loc {
self.arg_c = 1;
self.temp_c = max(term.subterms() + 1, self.temp_c);
} else {
reg
};
let reg = match lvl {
Level::Deep => VarReg::Norm(inner_reg),
Level::Shallow => {
let reg = VarReg::ArgAndNorm(inner_reg, self.arg_c);
self.arg_c += 1;
reg
}
};
self.record_register(var, inner_reg);
reg
}
pub fn mark_anon_var(&mut self, lvl: Level) -> VarReg {
let inner_reg = {
let temp = self.temp_c;
self.temp_c += 1;
RegType::Temp(temp)
};
match lvl {
Level::Deep => VarReg::Norm(inner_reg),
Level::Shallow => {
let reg = VarReg::ArgAndNorm(inner_reg, self.arg_c);
self.arg_c += 1;
reg
}
self.arg_c = 1;
self.temp_c = term.subterms() + 1;
}
}
pub fn advance_arg(&mut self) {
fn advance_arg(&mut self) {
self.arg_c += 1;
}
pub fn advance_at_head(&mut self, term: &'a Term) {
self.arg_c = 1;
self.temp_c = max(term.subterms() + 1, self.temp_c);
fn bindings(&self) -> &AllocVarDict<'a> {
&self.bindings
}
pub fn advance(&mut self, term: &'a Term) {
self.arg_c = 1;
self.temp_c = term.subterms() + 1;
fn bindings_mut(&mut self) -> &mut AllocVarDict<'a> {
&mut self.bindings
}
pub fn reset(&mut self) {
self.bindings.clear();
self.contents.clear();
self.in_use.clear();
}
pub fn reset_contents(&mut self) {
self.contents.clear();
self.in_use.clear();
fn take_bindings(self) -> AllocVarDict<'a> {
self.bindings
}
}

View File

@@ -5,7 +5,7 @@ use std::cell::Cell;
grammar;
pub TopLevel: TopLevel = {
"?-" <t:Term> "." => TopLevel::Query(t),
"?-" <q:Query> "." => TopLevel::Query(q),
<Predicate> => TopLevel::Predicate(<>),
<Rule> "." => TopLevel::Rule(<>),
<Term> "." => TopLevel::Fact(<>)
@@ -56,6 +56,14 @@ PredicateClause : PredicateClause = {
<Term> "." => PredicateClause::Fact(<>)
};
Query : Vec<TermOrCut> = {
<tcs: (<TermOrCut> ",")*> <tc: TermOrCut> => {
let mut tcs = tcs;
tcs.push(tc);
tcs
}
};
Rule : Rule = {
<c:Clause> ":-" <h:TermOrCut> <cs: ("," <TermOrCut>)*> =>
Rule { head: (c, h), clauses: cs },

File diff suppressed because it is too large Load Diff