]> Repositorios git - scryer-prolog.git/commitdiff
transition to l3
authorMark Thom <[email protected]>
Sun, 5 Mar 2017 02:22:43 +0000 (19:22 -0700)
committerMark Thom <[email protected]>
Sun, 5 Mar 2017 02:22:43 +0000 (19:22 -0700)
15 files changed:
Cargo.lock
Cargo.toml
README.md
src/l3/and_stack.rs [new file with mode: 0644]
src/l3/ast.rs [new file with mode: 0644]
src/l3/codegen.rs [new file with mode: 0644]
src/l3/heapview.rs [new file with mode: 0644]
src/l3/io.rs [new file with mode: 0644]
src/l3/iterators.rs [new file with mode: 0644]
src/l3/l3_parser.lalrpop [new file with mode: 0644]
src/l3/l3_parser.rs [new file with mode: 0644]
src/l3/machine.rs [new file with mode: 0644]
src/l3/mod.rs [new file with mode: 0644]
src/l3/or_stack.rs [new file with mode: 0644]
src/main.rs

index c38c995f512fcb57933e95b80a1f0edd012db216..bac78161372f13424ede2775f156ef719c2365b5 100644 (file)
@@ -1,9 +1,10 @@
 [root]
 name = "rusty-wam"
-version = "0.3.5"
+version = "0.4.0"
 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)",
+ "termion 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -197,6 +198,14 @@ dependencies = [
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "termion"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "thread-id"
 version = "2.0.0"
@@ -259,6 +268,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b"
 "checksum strsim 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "50c069df92e4b01425a8bf3576d5d417943a6a7272fbabaf5bd80b1aaa76442e"
 "checksum term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3deff8a2b3b6607d6d7cc32ac25c0b33709453ca9cceac006caac51e963cf94a"
+"checksum termion 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e710c59ecea168019486885ade43ea5329bb9a08a117410052fb81b250f40ae"
 "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
 "checksum thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "55dd963dbaeadc08aa7266bf7f91c3154a7805e32bb94b820b769d2ef3b4744d"
 "checksum unicode-xid 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f69506a2561962651710609304bbb961fa3da598c812f877975a82e48ee144f9"
index f79cd5aeb0db2f89a3e9ba1ec253942e83be105a..30fe64b1df0edb6b0fbeb5e11cd4fe54bf9b1998 100644 (file)
@@ -1,14 +1,16 @@
 [package]
 name = "rusty-wam"
-version = "0.3.5"
+version = "0.4.0"
 authors = ["Mark Thom"]
 
 build = "build.rs"
 
-[dependencies]
+[dependencies.termion]
+version = "1.2.0"
 
 [dependencies.lalrpop-util]
 version = "0.12.5"
 
 [build-dependencies.lalrpop]
-version = "0.12.5"
\ No newline at end of file
+version = "0.12.5"
+
index c47c5a321b72520ad8f8291e89d34f6aad778993..ba933921df39f62aa21e9db805b15ccbdf7c7e23 100644 (file)
--- a/README.md
+++ b/README.md
@@ -8,135 +8,56 @@ pure Prolog.
 
 ## Progress
 
-The language L2 is implemented as a simple REPL. It supports
-unification on queries without backtracking, where rules and facts are
-limited to a single name/arity pairing, in the familiar Prolog
-syntax. No data types apart from atoms are currently supported.
+The language L3 is implemented as a simple REPL. L3 is pure Prolog --
+Prolog without cuts, meta- or extra-logical operators, or side effects
+of any kind. No data types apart from atoms are currently supported.
 
-An example of the level of interaction currently supported is:
+## Tutorial
+To enter a multi-clause predicate, the brackets ":{" and "}:" are used
+as delimiters. They must be entirely contained with their own lines.
 
+For example,
 ```
-l2> p(Z, Z).
-l2> ?- p(Z, Z).
-yes
-Z = _0
-l2> ?- p(Z, z).
-yes
-Z = z
-l2> ?- p(Z, w).
-yes
-Z = w
-l2> clouds(are, nice).
-l2> ?- p(z, w).
-no
-l2> ?- p(w, w).
-yes
-l2> ?- clouds(Z, Z).
-no
-l2> ?- clouds(are, W).
-yes
-W = nice
-l2> ?- clouds(W, nice).
-yes
-W = are
-l2> ?- p(Z, h(Z, W), f(W)).
-no
-l2> p(Z, h(Z, W), f(W)).
-l2> ?- p(z, h(z, z), f(w)).
-no
-l2> ?- p(z, h(z, w), f(w)).
-yes
-l2> ?- p(z, h(z, W), f(w)).
-yes
-W = w
-l2> ?- p(Z, h(Z, w), f(Z)).
-yes
-Z = w
-l2> ?- p(z, h(Z, w), f(Z)).
-no
-l2> p(f(X), h(Y, f(a)), Y).
-l2> ?- p(Z, h(Z, W), f(W)).
-yes
-Z = f(f(a))
-W = f(a)
-l2> p(X, Y) :- q(X, Z), r(Z, Y).
-l2> q(q, s).
-l2> r(s, t).
-l2> ?- p(X, Y).
-yes
-X = q
-Y = t
-l2> ?- p(q, t).
-yes
-l2> ?- p(t, q).
-no
-l2> ?- p(q, T).
-yes
-T = t
-l2> ?- p(Q, t).
-yes
-Q = q
-l2> ?- p(t, t).
-no
-l2> p(X, Y) :- q(f(f(X)), R), r(S, T).
-l2> q(f(f(X)), r).
-l2> ?- p(X, Y).
+l3> :{
+p(f(f(X)), h(W), Y) :- g(W), h(W), f(X).
+p(X, Y, Z) :- h(Y), z(Z).
+}:
+l3> :{
+h(x).
+h(y).
+h(z).
+}:
+```
+
+Single clause predicates can entered without brackets, as in
+```
+l3> p(X) :- q(X).
+l3> f(s).
+l3> z(Z).
+```
+
+Queries are issued as
+```
+l3> ?- p(X, Y, Z).
+```
+
+Given the above work, the result of the query will be
+```
+l3> ?- p(X, Y, Z).
 yes
-Y = _1
 X = _0
-l2> q(f(f(x)), r).
-l2> ?- p(X, Y).
-yes
-Y = _1
-X = x
-l2> p(X, Y) :- q(X, Y), r(X, Y).
-l2> q(s, t).
-l2> r(X, Y) :- r(a).
-l2> r(a).
-l2> ?- p(X, Y).
-yes
-Y = t
-X = s
-l2> ?- p(t, S).
-no
-l2> ?- p(t, s).
-no
-l2> ?- p(s, T).
-yes
-T = t
-l2> ?- p(S, t).
-yes
-S = s
-l2> p(f(f(a), g(b), X), g(b), h) :- q(X, Y).
-l2> q(X, Y).
-l2> ?- p(f(X, Y, Z), g(b), h).
-yes
-Z = _4
-X = f(a)
-Y = g(b)
-l2> ?- p(f(X, g(Y), c), g(Z), X).
-no
-l2> ?- p(f(X, g(Y), c), g(Z), h).
-yes
-Z = b
-Y = b
-X = f(a)
-l2> ?- p(Z, Y, X).
-yes
-X = h
-Z = f(f(a), g(b), _7)
-Y = g(b)
-l2> ?- p(f(X, Y, Z), Y, h).
-yes
-X = f(a)
-Z = _4
-Y = g(b)
-l2> quit
+Y = x
+Z = _2
+Press ; to continue or A to abort.
 ```
 
+Pressing ; will backtrack through other possible answers, if any exist.
+Pressing A will abort the search and return to the prompt.
+
 Note that the values of variables belonging to successful queries are
 printed out, on one line each. Uninstantiated variables are denoted by
-a number preceded by an underscore.
+a number preceded by an underscore (X = _0 is an example in the
+above).
 
 ## Occurs check
 
diff --git a/src/l3/and_stack.rs b/src/l3/and_stack.rs
new file mode 100644 (file)
index 0000000..5e05ead
--- /dev/null
@@ -0,0 +1,80 @@
+use l3::ast::*;
+
+use std::ops::{Index, IndexMut};
+use std::vec::Vec;
+
+pub struct Frame {
+    pub global_index: usize,
+    pub e: usize,
+    pub cp: CodePtr,
+    perms: Vec<Addr>
+}
+
+impl Frame {
+    fn new(global_index: usize, e: usize, cp: CodePtr, n: usize) -> Self {
+        Frame {
+            global_index: global_index,
+            e: e,
+            cp: cp,
+            perms: vec![Addr::HeapCell(0); n]
+        }
+    }
+}
+
+pub struct AndStack(Vec<Frame>);
+
+impl AndStack {
+    pub fn new() -> Self {
+        AndStack(Vec::new())
+    }
+
+    pub fn push(&mut self, global_index: usize, e: usize, cp: CodePtr, n: usize) {
+        self.0.push(Frame::new(global_index, e, cp, n));
+    }
+
+    pub fn top(&self) -> Option<&Frame> {
+        self.0.last()
+    }
+
+    pub fn len(&self) -> usize {
+        self.0.len()
+    }
+
+    pub fn clear(&mut self) {
+        self.0.clear()
+    }
+
+    // drop the last n frames.
+    pub fn drop_frames(&mut self, n: usize) {
+        let len = self.0.len();
+        self.0.truncate(len - n);
+    }
+}
+
+impl Index<usize> for AndStack {
+    type Output = Frame;
+
+    fn index(&self, index: usize) -> &Self::Output {
+        self.0.index(index)
+    }
+}
+
+impl IndexMut<usize> for AndStack {
+    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+        self.0.index_mut(index)
+    }
+}
+
+impl Index<usize> for Frame {
+    type Output = Addr;
+
+    fn index(&self, index: usize) -> &Self::Output {
+        self.perms.index(index - 1)
+    }
+}
+
+impl IndexMut<usize> for Frame {
+    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+        self.perms.index_mut(index - 1)
+    }
+}
diff --git a/src/l3/ast.rs b/src/l3/ast.rs
new file mode 100644 (file)
index 0000000..693be9d
--- /dev/null
@@ -0,0 +1,303 @@
+use std::cell::Cell;
+use std::collections::HashMap;
+use std::ops::{Add, AddAssign};
+use std::vec::Vec;
+
+pub type Var = String;
+
+pub type Atom = String;
+
+pub enum PredicateClause {
+    Fact(Term),
+    Rule(Rule)
+}
+
+impl PredicateClause {
+    pub fn name(&self) -> &Atom {
+        match self {
+            &PredicateClause::Fact(ref t) => t.name(),
+            &PredicateClause::Rule(ref rule) => rule.head.0.name()
+        }
+    }
+
+    pub fn arity(&self) -> usize {
+        match self {
+            &PredicateClause::Fact(ref t) => t.arity(),
+            &PredicateClause::Rule(ref rule) => rule.head.0.arity()
+        }
+    }
+}
+
+pub enum TopLevel {
+    Fact(Term),
+    Predicate(Vec<PredicateClause>),
+    Query(Term),
+    Rule(Rule)
+}
+
+#[derive(Clone, Copy)]
+pub enum Level {
+    Deep, Shallow
+}
+
+#[derive(Clone, Copy)]
+pub enum RegType {
+    Perm(usize),
+    Temp(usize)
+}
+
+impl RegType {
+    pub fn reg_num(self) -> usize {
+        match self {
+            RegType::Perm(reg_num) | RegType::Temp(reg_num) => reg_num
+        }
+    }
+
+    pub fn is_perm(self) -> bool {
+        match self {
+            RegType::Perm(_) => true,
+            _ => false
+        }
+    }
+}
+
+#[derive(Clone, Copy)]
+pub enum VarReg {
+    ArgAndNorm(RegType, usize),
+    Norm(RegType)
+}
+
+impl VarReg {
+    pub fn norm(self) -> RegType {
+        match self {
+            VarReg::ArgAndNorm(reg, _) | VarReg::Norm(reg) => reg
+        }
+    }
+
+    pub fn root_register(self) -> usize {
+        match self {
+            VarReg::ArgAndNorm(_, root) => root,
+            VarReg::Norm(root) => root.reg_num()
+        }
+    }
+}
+
+pub enum Term {
+    Atom(Cell<RegType>, Atom),
+    Clause(Cell<RegType>, Atom, Vec<Box<Term>>),
+    Var(Cell<VarReg>, Var)
+}
+
+pub struct Rule {
+    pub head: (Term, Term),
+    pub clauses: Vec<Term>
+}
+
+pub enum TermRef<'a> {
+    Atom(Level, &'a Cell<RegType>, &'a Atom),
+    Clause(Level, &'a Cell<RegType>, &'a Atom, &'a Vec<Box<Term>>),
+    Var(Level, &'a Cell<VarReg>, &'a Var)
+}
+
+pub enum FactInstruction {
+    GetStructure(Level, Atom, usize, RegType),
+    GetValue(RegType, usize),
+    GetVariable(RegType, usize),
+    UnifyVariable(RegType),
+    UnifyValue(RegType)
+}
+
+pub enum QueryInstruction {
+    PutStructure(Level, Atom, usize, RegType),
+    PutValue(RegType, usize),
+    PutVariable(RegType, usize),
+    SetVariable(RegType),
+    SetValue(RegType)
+}
+
+pub enum ChoiceInstruction {
+    RetryMeElse(usize),
+    TrustMe,
+    TryMeElse(usize)
+}
+
+pub enum ControlInstruction {
+    Allocate(usize),
+    Call(Atom, usize),
+    Deallocate,
+    Proceed
+}
+
+pub type CompiledFact = Vec<FactInstruction>;
+
+pub type CompiledQuery = Vec<QueryInstruction>;
+
+pub enum Line {
+    Choice(ChoiceInstruction),
+    Control(ControlInstruction),
+    Fact(CompiledFact),
+    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 Code = Vec<Line>;
+
+#[derive(Clone, Copy, PartialEq)]
+pub enum Addr {
+    HeapCell(usize),
+    StackCell(usize, usize),
+    Str(usize)
+}
+
+impl Addr {
+    pub fn is_ref(self) -> bool {
+        match self {
+            Addr::HeapCell(_) | Addr::StackCell(_, _) => true,
+            _ => false
+        }
+    }
+
+    pub fn as_ref(self) -> Option<Ref> {
+        match self {
+            Addr::HeapCell(hc) => Some(Ref::HeapCell(hc)),
+            Addr::StackCell(fr, sc) => Some(Ref::StackCell(fr, sc)),
+            _ => None
+        }
+    }
+}
+
+impl From<Ref> for Addr {
+    fn from(r: Ref) -> Self {
+        match r {
+            Ref::HeapCell(hc) => Addr::HeapCell(hc),
+            Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc)
+        }
+    }
+}
+
+#[derive(Clone, Copy, PartialEq)]
+pub enum Ref {
+    HeapCell(usize),
+    StackCell(usize, usize)
+}
+
+#[derive(Clone, PartialEq)]
+pub enum HeapCellValue {
+    NamedStr(usize, Atom),
+    Ref(Ref),
+    Str(usize)
+}
+
+impl From<Addr> for HeapCellValue {
+    fn from(addr: Addr) -> HeapCellValue {
+        match addr {
+            Addr::HeapCell(hc) =>
+                HeapCellValue::Ref(Ref::HeapCell(hc)),
+            Addr::StackCell(fr, sc) =>
+                HeapCellValue::Ref(Ref::StackCell(fr, sc)),
+            Addr::Str(hc) =>
+                HeapCellValue::Str(hc)
+        }
+    }
+}
+
+impl HeapCellValue {
+    pub fn as_addr(&self, focus: usize) -> Addr {
+        match self {           
+            &HeapCellValue::Ref(r) => Addr::from(r),
+            &HeapCellValue::Str(s) => Addr::Str(s),
+            &HeapCellValue::NamedStr(_, _) => Addr::Str(focus)
+        }
+    }
+}
+
+#[derive(Clone, Copy)]
+pub enum CodePtr {
+    DirEntry(usize),
+    TopLevel
+}
+
+impl Default for CodePtr {
+    fn default() -> Self {
+        CodePtr::TopLevel
+    }
+}
+
+impl Add<usize> for CodePtr {
+    type Output = CodePtr;
+
+    fn add(self, rhs: usize) -> Self::Output {
+        match self {
+            CodePtr::DirEntry(p) => CodePtr::DirEntry(p + rhs),
+            CodePtr::TopLevel => CodePtr::TopLevel
+        }
+    }
+}
+
+impl AddAssign<usize> for CodePtr {
+    fn add_assign(&mut self, rhs: usize) {
+        match self {
+            &mut CodePtr::DirEntry(ref mut p) => *p += rhs,
+            _ => {}
+        }
+    }
+}
+
+pub type Heap = Vec<HeapCellValue>;
+
+pub type Registers = Vec<Addr>;
+
+impl Term {
+    pub fn subterms(&self) -> usize {
+        match self {
+            &Term::Clause(_, _, ref terms) => terms.len(),
+            _ => 1
+        }
+    }
+
+    pub fn name(&self) -> &Atom {
+        match self {
+            &Term::Atom(_, ref atom)
+            | &Term::Var(_, ref atom)
+            | &Term::Clause(_, ref atom, _) => atom
+        }
+    }
+
+    pub fn arity(&self) -> usize {
+        match self {
+            &Term::Atom(_, _) | &Term::Var(_, _) => 0,
+            &Term::Clause(_, _, ref child_terms) => child_terms.len()
+        }
+    }
+}
+
+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
+        }
+    }
+}
diff --git a/src/l3/codegen.rs b/src/l3/codegen.rs
new file mode 100644 (file)
index 0000000..2106570
--- /dev/null
@@ -0,0 +1,447 @@
+use l3::ast::*;
+use l3::iterators::{FactIterator, QueryIterator};
+
+use std::cell::Cell;
+use std::cmp::max;
+use std::collections::HashMap;
+use std::vec::Vec;
+
+trait CompilationTarget<'a> {
+    type Iterator : Iterator<Item=TermRef<'a>>;
+
+    fn iter(&'a Term) -> Self::Iterator;
+
+    fn to_structure(Level, Atom, usize, RegType) -> Self;
+
+    fn argument_to_variable(RegType, usize) -> Self;
+    fn argument_to_value(RegType, usize) -> Self;
+    fn subterm_to_variable(RegType) -> Self;
+    fn subterm_to_value(RegType) -> Self;
+
+    fn clause_arg_to_instr(RegType) -> Self;
+}
+
+impl<'a> CompilationTarget<'a> for FactInstruction {
+    type Iterator = FactIterator<'a>;
+
+    fn iter(term: &'a Term) -> Self::Iterator {
+        term.breadth_first_iter()
+    }
+
+    fn to_structure(lvl: Level, atom: Atom, arity: usize, reg: RegType) -> Self {
+        FactInstruction::GetStructure(lvl, atom, arity, reg)
+    }
+
+    fn argument_to_variable(arg: RegType, val: usize) -> Self {
+        FactInstruction::GetVariable(arg, val)
+    }
+
+    fn argument_to_value(arg: RegType, val: usize) -> Self {
+        FactInstruction::GetValue(arg, val)
+    }
+
+    fn subterm_to_variable(val: RegType) -> Self {
+        FactInstruction::UnifyVariable(val)
+    }
+
+    fn subterm_to_value(val: RegType) -> Self {
+        FactInstruction::UnifyValue(val)
+    }
+
+    fn clause_arg_to_instr(val: RegType) -> Self {
+        FactInstruction::UnifyVariable(val)
+    }
+}
+
+impl<'a> CompilationTarget<'a> for QueryInstruction {
+    type Iterator = QueryIterator<'a>;
+
+    fn iter(term: &'a Term) -> Self::Iterator {
+        term.post_order_iter()
+    }
+
+    fn to_structure(lvl: Level, atom: Atom, arity: usize, reg: RegType) -> Self {
+        QueryInstruction::PutStructure(lvl, atom, arity, reg)
+    }
+
+    fn argument_to_variable(arg: RegType, val: usize) -> Self {
+        QueryInstruction::PutVariable(arg, val)
+    }
+
+    fn argument_to_value(arg: RegType, val: usize) -> Self {
+        QueryInstruction::PutValue(arg, val)
+    }
+
+    fn subterm_to_variable(val: RegType) -> Self {
+        QueryInstruction::SetVariable(val)
+    }
+
+    fn subterm_to_value(val: RegType) -> Self {
+        QueryInstruction::SetValue(val)
+    }
+
+    fn clause_arg_to_instr(val: RegType) -> Self {
+        QueryInstruction::SetValue(val)
+    }
+}
+
+struct TermMarker<'a> {
+    bindings: HashMap<&'a Var, VarReg>,
+    arg_c:    usize,
+    perm_c:   usize,
+    temp_c:   usize
+}
+
+impl<'a> TermMarker<'a> {
+    fn new() -> TermMarker<'a> {
+        TermMarker { bindings: HashMap::new(),
+                     arg_c:    1,
+                     perm_c:   1,
+                     temp_c:   1 }
+    }
+
+    fn reset(&mut self) {
+        self.bindings.clear();
+        self.perm_c = 1;
+    }
+    
+    fn contains_var(&self, var: &'a Var) -> bool {
+        self.bindings.contains_key(var)
+    }
+
+    fn get(&self, var: &'a Var) -> VarReg {
+        *self.bindings.get(var).unwrap()
+    }
+
+    fn insert(&mut self, var: &'a Var, r: VarReg) {
+        self.bindings.insert(var, r);
+    }
+
+    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 perm = self.perm_c;
+                    self.perm_c += 1;
+                    cell.set(RegType::Perm(perm));
+                },
+                Level::Deep => {
+                    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::Perm(arg));
+                },
+                Level::Shallow => {
+                    let arg = self.arg_c;
+                    self.arg_c += 1;
+                    cell.set(RegType::Temp(arg));
+                }
+            };
+        }
+    }
+
+    fn mark_old_var(&mut self, lvl: Level, var: &'a Var) -> VarReg
+    {
+        let reg = self.get(var);
+
+        match lvl {
+            Level::Deep => VarReg::Norm(reg.norm()),
+            Level::Shallow => {
+                let reg = VarReg::ArgAndNorm(reg.norm(), self.arg_c);
+
+                self.arg_c += 1;
+                self.insert(var, reg);
+
+                reg
+            }
+        }
+    }
+
+    fn mark_new_var(&mut self, lvl: Level, var: &'a Var, reg: RegType) -> VarReg
+    {
+        let inner_reg = if reg.is_perm() {
+            let perm = self.perm_c;
+            self.perm_c += 1;
+            RegType::Perm(perm)
+        } else {
+            let temp = self.temp_c;
+            self.temp_c += 1;
+            RegType::Temp(temp)
+        };
+
+        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.insert(var, reg);
+        reg
+    }
+
+    fn advance_at_head(&mut self, term: &'a Term) {
+        self.arg_c = 1;
+        self.temp_c = max(term.subterms(), self.temp_c) + 1;
+    }
+
+    fn advance(&mut self, term: &'a Term) {
+        self.arg_c = 1;
+        self.temp_c = term.subterms() + 1;
+    }
+}
+
+#[derive(Copy, Clone)]
+enum TermStatus {
+    New, Old, Recurrent
+}
+
+pub struct CodeGenerator<'a> {
+    marker: TermMarker<'a>
+}
+
+type VariableFixture<'a>  = (TermStatus, Vec<&'a Cell<VarReg>>);
+type VariableFixtures<'a> = HashMap<&'a Var, VariableFixture<'a>>;
+
+impl<'a> CodeGenerator<'a> {
+    pub fn new() -> Self {
+        CodeGenerator { marker: TermMarker::new() }
+    }
+
+    pub fn vars(&self) -> &HashMap<&Var, VarReg> {
+        &self.marker.bindings
+    }
+
+    fn to_structure<Target>(&mut self,
+                            lvl: Level,
+                            name: &'a Atom,
+                            cell: &'a Cell<RegType>,
+                            arity: usize)
+                            -> Target
+        where Target: CompilationTarget<'a>
+    {
+        self.marker.mark_non_var(lvl, cell);
+        Target::to_structure(lvl, name.clone(), arity, cell.get())
+    }
+
+    fn var_term<Target>(&mut self,
+                        lvl: Level,
+                        cell: &'a Cell<VarReg>,
+                        var: &'a Var)
+                        -> Target
+        where Target: CompilationTarget<'a>
+    {
+        if !self.marker.contains_var(var) {
+            let reg = self.marker.mark_new_var(lvl, var, cell.get().norm());
+            cell.set(reg);
+
+            match reg {
+                VarReg::ArgAndNorm(arg, norm) =>
+                    Target::argument_to_variable(arg, norm),
+                VarReg::Norm(norm) =>
+                    Target::subterm_to_variable(norm)
+            }
+        } else {
+            let reg = self.marker.mark_old_var(lvl, var);
+            cell.set(reg);
+
+            match reg {
+                VarReg::ArgAndNorm(arg, norm) =>
+                    Target::argument_to_value(arg, norm),
+                VarReg::Norm(norm) =>
+                    Target::subterm_to_value(norm)
+            }
+        }
+    }
+
+    fn non_var_subterm<Target>(&mut self, cell: &'a Cell<RegType>) -> Target
+        where Target: CompilationTarget<'a>
+    {
+        self.marker.mark_non_var(Level::Deep, cell);
+        Target::clause_arg_to_instr(cell.get())
+    }
+
+    fn subterm_to_instr<Target>(&mut self, subterm: &'a Term) -> Target
+        where Target: CompilationTarget<'a>
+    {
+        match subterm {
+            &Term::Atom(ref cell, _) | &Term::Clause(ref cell, _, _) =>
+                self.non_var_subterm(cell),
+            &Term::Var(ref cell, ref var) =>
+                self.var_term(Level::Deep, cell, var)
+        }
+    }
+
+    fn compile_target<Target>(&mut self, term: &'a Term) -> Vec<Target>
+        where Target: CompilationTarget<'a>
+    {
+        let iter       = Target::iter(term);
+        let mut target = Vec::new();
+
+        for term in iter {
+            match term {
+                TermRef::Atom(lvl, term, atom) =>
+                    target.push(self.to_structure(lvl, atom, term, 0)),
+                TermRef::Clause(lvl, term, atom, terms) => {
+                    target.push(self.to_structure(lvl, atom, term, terms.len()));
+
+                    for subterm in terms {
+                        target.push(self.subterm_to_instr(subterm.as_ref()));
+                    }
+                },
+                TermRef::Var(lvl @ Level::Shallow, ref cell, ref var) =>
+                    target.push(self.var_term(lvl, cell, var)),
+                _ => {}
+            };
+        }
+
+        target
+    }
+
+    fn mark_vars_in_term<Iter>(iter: Iter, vs: &mut VariableFixtures<'a>)
+        where Iter : Iterator<Item=TermRef<'a>>
+    {
+        for term in iter {
+            if let TermRef::Var(_, reg_cell, var) = term {
+                let mut status = vs.entry(var)
+                                   .or_insert((TermStatus::New, Vec::new()));
+
+                status.1.push(reg_cell);
+
+                match status.0 {
+                    TermStatus::Old => status.0 = TermStatus::Recurrent,
+                    _ => {}
+                };
+            }
+        }
+
+        for &mut (ref mut term_status, ref mut cb) in vs.values_mut() {
+            match *term_status {
+                TermStatus::New => *term_status = TermStatus::Old,
+                TermStatus::Recurrent => {
+                    for cell_reg in cb.drain(0..) {
+                        cell_reg.set(VarReg::Norm(RegType::Perm(0)));
+                    }
+                },
+                _ => {}
+            }
+        }
+    }
+
+    fn mark_perm_vars(rule: &'a Rule) -> VariableFixtures {
+        let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
+        let mut vfs = HashMap::new();
+
+        let iter = p0.breadth_first_iter().chain(p1.breadth_first_iter());
+
+        Self::mark_vars_in_term(iter, &mut vfs);
+
+        for term in clauses {
+            Self::mark_vars_in_term(term.breadth_first_iter(), &mut vfs);
+        }
+
+        vfs
+    }
+
+    fn add_conditional_call(compiled_query: &mut Code, term: &Term) {
+        match term {
+            &Term::Atom(_, ref atom) => {
+                let call = ControlInstruction::Call(atom.clone(), 0);
+                compiled_query.push(Line::Control(call));
+            },
+            &Term::Clause(_, ref atom, ref terms) => {
+                let call = ControlInstruction::Call(atom.clone(), terms.len());
+                compiled_query.push(Line::Control(call));
+            },
+            _ => {}
+        }
+    }
+
+    pub fn compile_rule(&mut self, rule: &'a Rule) -> Code {
+        let vfs = Self::mark_perm_vars(&rule);
+        let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
+        let mut perm_vars = 0;
+
+        for &(term_status, _) in vfs.values() {
+            if let TermStatus::Recurrent = term_status {
+                perm_vars += 1;
+            }
+        }
+
+        let mut body = Vec::new();
+
+        body.push(Line::Control(ControlInstruction::Allocate(perm_vars)));
+
+        self.marker.advance(p0);
+        body.push(Line::Fact(self.compile_target(p0)));
+
+        self.marker.advance_at_head(p1);
+        body.push(Line::Query(self.compile_target(p1)));
+        
+        Self::add_conditional_call(&mut body, p1);
+
+        body = clauses.iter()
+            .map(|ref term| self.compile_query(term))
+            .fold(body, |mut body, ref mut cqs| {
+                body.append(cqs);
+                body
+            });
+
+        body.push(Line::Control(ControlInstruction::Deallocate));
+        body
+    }
+
+    pub fn compile_fact(&mut self, term: &'a Term) -> Code {
+        self.marker.advance(term);
+
+        let mut compiled_fact = vec![Line::Fact(self.compile_target(term))];
+        let proceed = Line::Control(ControlInstruction::Proceed);
+
+        compiled_fact.push(proceed);
+        compiled_fact
+    }
+
+    pub fn compile_query(&mut self, term: &'a Term) -> Code {
+        self.marker.advance(term);
+
+        let mut compiled_query = vec![Line::Query(self.compile_target(term))];
+        Self::add_conditional_call(&mut compiled_query, term);
+
+        compiled_query
+    }
+
+    pub fn compile_predicate(&mut self, clauses: &'a Vec<PredicateClause>) -> Code
+    {
+        let mut code = Vec::new();
+        
+        for (i, clause) in clauses.iter().enumerate() {
+            self.marker.reset();
+            
+            let mut clause_code = match clause {
+                &PredicateClause::Fact(ref fact) =>
+                    self.compile_fact(fact),
+                &PredicateClause::Rule(ref rule) =>
+                    self.compile_rule(rule)
+            };
+
+            let choice = match i {
+                0 => ChoiceInstruction::TryMeElse(clause_code.len() + 1),
+                _ if i == clauses.len() - 1 => ChoiceInstruction::TrustMe,
+                _ => ChoiceInstruction::RetryMeElse(clause_code.len() + 1)
+            };
+
+            code.push(Line::Choice(choice));
+            code.append(&mut clause_code);
+        }
+
+        code
+    }
+}
diff --git a/src/l3/heapview.rs b/src/l3/heapview.rs
new file mode 100644 (file)
index 0000000..d25040a
--- /dev/null
@@ -0,0 +1,86 @@
+use l3::and_stack::*;
+use l3::ast::*;
+
+use std::vec::Vec;
+
+#[derive(Clone, Copy)]
+pub enum HeapCellView<'a> {
+    Str(usize, &'a Atom),
+    HeapVar(usize),
+    StackVar(usize, usize)
+}
+
+pub struct HeapCellViewer<'a> {
+    heap: &'a Heap,
+    and_stack: &'a AndStack,
+    state_stack: Vec<Addr>
+}
+
+impl<'a> HeapCellViewer<'a> {
+    pub fn new(heap: &'a Heap, and_stack: &'a AndStack, focus: Addr) -> Self {
+        HeapCellViewer {
+            heap: heap,
+            and_stack: and_stack,
+            state_stack: vec![focus]
+        }
+    }
+
+    fn follow_stack_ref(&mut self, mut fr: usize, mut sc: usize) -> HeapCellView<'a>
+    {
+        loop {
+            match self.and_stack[fr][sc] {
+                Addr::HeapCell(hc) | Addr::Str(hc) =>
+                    return self.follow_heap_ref(hc),
+                Addr::StackCell(fr1, sc1) => {
+                    if fr1 == fr && sc1 == sc {
+                        return HeapCellView::StackVar(fr, sc);
+                    }
+
+                    fr = fr1; sc = sc1;
+                }
+            }
+        }
+    }
+
+    fn follow_heap_ref(&mut self, mut focus: usize) -> HeapCellView<'a> {
+        loop {
+            match &self.heap[focus] {
+                &HeapCellValue::NamedStr(arity, ref name) => {
+                    for i in (1 .. arity + 1).rev() {
+                        self.state_stack.push(Addr::HeapCell(focus + i));
+                    }
+
+                    return HeapCellView::Str(arity, name);
+                },
+                &HeapCellValue::Ref(Ref::HeapCell(hc)) => {
+                    if focus == hc {
+                        return HeapCellView::HeapVar(hc);
+                    } else {
+                        focus = hc;
+                    }
+                },
+                &HeapCellValue::Ref(Ref::StackCell(fr, sc)) =>
+                    return self.follow_stack_ref(fr, sc),
+                &HeapCellValue::Str(cell_num) =>
+                    focus = cell_num,
+            }
+        }
+    }
+}
+
+impl<'a> Iterator for HeapCellViewer<'a> {
+    type Item = HeapCellView<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if let Some(addr) = self.state_stack.pop() {
+            match addr {
+                Addr::HeapCell(hc) | Addr::Str(hc) =>
+                    return Some(self.follow_heap_ref(hc)),
+                Addr::StackCell(fr, sc) =>
+                    return Some(self.follow_stack_ref(fr, sc))
+            }
+        }
+
+        None
+    }
+}
diff --git a/src/l3/io.rs b/src/l3/io.rs
new file mode 100644 (file)
index 0000000..ad5be2b
--- /dev/null
@@ -0,0 +1,255 @@
+use l3::ast::*;
+use l3::codegen::*;
+use l3::l3_parser::*;
+use l3::machine::*;
+
+use termion::raw::IntoRawMode;
+use termion::input::TermRead;
+use termion::event::Key;
+
+use std::io::{Write, stdin, stdout};
+use std::fmt;
+
+impl fmt::Display for FactInstruction {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            &FactInstruction::GetStructure(Level::Deep, ref name, ref arity, ref r) =>
+                write!(f, "get_structure {}/{}, {}", name, arity, r),
+            &FactInstruction::GetStructure(Level::Shallow, ref name, ref arity, ref r) =>
+                write!(f, "get_structure {}/{}, A{}", name, arity, r.reg_num()),
+            &FactInstruction::GetValue(ref x, ref a) =>
+                write!(f, "get_value {}, A{}", x, a),
+            &FactInstruction::GetVariable(ref x, ref a) =>
+                write!(f, "get_variable {}, A{}", x, a),
+            &FactInstruction::UnifyVariable(ref r) =>
+                write!(f, "unify_variable {}", r),
+            &FactInstruction::UnifyValue(ref r) =>
+                write!(f, "unify_value {}", r)
+        }
+    }
+}
+
+impl fmt::Display for QueryInstruction {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            &QueryInstruction::PutStructure(Level::Deep, ref name, ref arity, ref r) =>
+                write!(f, "put_structure {}/{}, {}", name, arity, r.reg_num()),
+            &QueryInstruction::PutStructure(Level::Shallow, ref name, ref arity, ref r) =>
+                write!(f, "put_structure {}/{}, A{}", name, arity, r.reg_num()),
+            &QueryInstruction::PutValue(ref x, ref a) =>
+                write!(f, "put_value {}, A{}", x, a),
+            &QueryInstruction::PutVariable(ref x, ref a) =>
+                write!(f, "put_variable {}, A{}", x, a),
+            &QueryInstruction::SetVariable(ref r) =>
+                write!(f, "set_variable {}", r),
+            &QueryInstruction::SetValue(ref r) =>
+                write!(f, "set_value {}", r),
+        }
+    }
+}
+
+impl fmt::Display for ControlInstruction {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            &ControlInstruction::Allocate(num_cells) =>
+                write!(f, "allocate {}", num_cells),
+            &ControlInstruction::Call(ref name, ref arity) =>
+                write!(f, "call {}/{}", name, arity),
+            &ControlInstruction::Deallocate =>
+                write!(f, "deallocate"),
+            &ControlInstruction::Proceed =>
+                write!(f, "proceed")
+        }
+    }
+}
+
+impl fmt::Display for ChoiceInstruction {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            &ChoiceInstruction::TryMeElse(offset) =>
+                write!(f, "try_me_else {}", offset),
+            &ChoiceInstruction::RetryMeElse(offset) =>
+                write!(f, "retry_me_else {}", offset),
+            &ChoiceInstruction::TrustMe =>
+                write!(f, "trust_me")
+        }
+    }
+}
+
+impl fmt::Display for Level {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            &Level::Shallow => write!(f, "A"),
+            &Level::Deep => write!(f, "X")
+        }
+    }
+}
+
+impl fmt::Display for VarReg {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            &VarReg::Norm(RegType::Perm(reg)) => write!(f, "Y{}", reg),
+            &VarReg::Norm(RegType::Temp(reg)) => write!(f, "X{}", reg),
+            &VarReg::ArgAndNorm(RegType::Perm(reg), arg) =>
+                write!(f, "Y{} A{}", reg, arg),
+            &VarReg::ArgAndNorm(RegType::Temp(reg), arg) =>
+                write!(f, "X{} A{}", reg, arg)
+        }
+    }
+}
+
+impl fmt::Display for RegType {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            &RegType::Perm(val) => write!(f, "Y{}", val),
+            &RegType::Temp(val) => write!(f, "X{}", val)
+        }
+    }
+}
+
+
+fn is_consistent(predicate: &Vec<PredicateClause>) -> bool {
+    let name  = predicate.first().unwrap().name();
+    let arity = predicate.first().unwrap().arity();
+
+    for clause in predicate.iter().skip(1) {
+        if !(name == clause.name() && arity == clause.arity()) {
+            return false;
+        }
+    }
+
+    true
+}
+
+#[allow(dead_code)]
+pub fn print_code(code: &Code) {
+    for clause in code {
+        match clause {
+            &Line::Fact(ref fact) =>
+                for fact_instr in fact {
+                    println!("{}", fact_instr);
+                },
+            &Line::Choice(ref choice) =>
+                println!("{}", choice),
+            &Line::Control(ref control) =>
+                println!("{}", control),
+            &Line::Query(ref query) =>
+                for query_instr in query {
+                    println!("{}", query_instr);
+                }
+        }
+    }
+}
+
+pub fn read() -> String {
+    let _ = stdout().flush();
+
+    let mut buffer = String::new();
+    let mut result = String::new();
+
+    let stdin = stdin();
+    stdin.read_line(&mut buffer).unwrap();
+
+    if &*buffer.trim() == ":{" {
+        buffer.clear();
+
+        stdin.read_line(&mut buffer).unwrap();
+
+        while &*buffer.trim() != "}:" {
+            result += buffer.as_str();
+            buffer.clear();
+            stdin.read_line(&mut buffer).unwrap();
+        }
+    } else {
+        result = buffer;
+    }
+
+    result
+}
+
+pub fn eval(wam: &mut Machine, buffer: &str) -> EvalResult
+{
+    let result = parse_TopLevel(buffer);
+    let mut cg = CodeGenerator::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);
+
+                EvalResult::EntrySuccess
+            } else {
+                let msg = r"Error: predicate is inconsistent.
+Each predicate must have the same name and arity.";
+
+                println!("{}", msg);
+                EvalResult::EntryFailure
+            }
+        },
+        &Ok(TopLevel::Fact(ref fact)) => {
+            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);
+            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
+        }
+    }
+}
+
+pub fn print(wam: &mut Machine, result: EvalResult) {
+    match result {
+        EvalResult::InitialQuerySuccess(heap_locs) => {
+            println!("yes");
+
+            'outer: loop {
+                let mut result = EvalResult::QueryFailure;
+                let bindings = wam.heap_view(&heap_locs);
+
+                let stdin  = stdin();
+                let mut stdout = stdout().into_raw_mode().unwrap();
+
+                write!(stdout, "{}\n\r", bindings).unwrap();
+                stdout.flush().unwrap();
+
+                if !wam.or_stack_is_empty() {
+                    write!(stdout, "Press ; to continue or A to abort.\n\r").unwrap();
+                    stdout.flush().unwrap();
+
+                    for c in stdin.keys() {
+                        match c.unwrap() {
+                            Key::Char(';') => {
+                                result = wam.continue_query();
+                                break;
+                            },
+                            Key::Char('a') | Key::Char('A') =>
+                                break 'outer,
+                            _ => {}
+                        }
+                    };
+
+                    if let &EvalResult::QueryFailure = &result {
+                        write!(stdout, "no\n\r").unwrap();
+                        stdout.flush().unwrap();
+                        break;
+                    }
+                } else {
+                    break;
+                }
+            }
+        },
+        EvalResult::QueryFailure => println!("no"),
+        _ => {}
+    };
+}
diff --git a/src/l3/iterators.rs b/src/l3/iterators.rs
new file mode 100644 (file)
index 0000000..729f8be
--- /dev/null
@@ -0,0 +1,175 @@
+use l3::ast::*;
+
+use std::cell::Cell;
+use std::collections::VecDeque;
+use std::vec::Vec;
+
+enum IteratorState<'a> {
+    Atom(Level, &'a Cell<RegType>, &'a Atom),
+    Clause(Level, usize, &'a Cell<RegType>, &'a Atom, &'a Vec<Box<Term>>),
+    IsolatedAtom(&'a Cell<RegType>, &'a Atom),
+    IsolatedVar(&'a Cell<VarReg>, &'a Var),
+    RootClause(usize, &'a Vec<Box<Term>>),
+    Var(Level, &'a Cell<VarReg>, &'a Var)
+}
+
+impl<'a> IteratorState<'a> {
+    fn to_state(lvl: Level, term: &'a Term) -> IteratorState<'a>
+    {
+        match term {
+            &Term::Atom(ref cell, ref atom) =>
+                IteratorState::Atom(lvl, cell, atom),
+            &Term::Clause(ref cell, ref atom, ref child_terms) =>
+                IteratorState::Clause(lvl, 0, cell, atom, child_terms),
+            &Term::Var(ref cell, ref var) =>
+                IteratorState::Var(lvl, cell, var)
+        }
+    }
+}
+
+pub struct QueryIterator<'a> {
+    state_stack: Vec<IteratorState<'a>>
+}
+
+impl<'a> QueryIterator<'a> {
+    fn push_clause(&mut self,
+                   lvl: Level,
+                   child_num: usize,
+                   cell: &'a Cell<RegType>,
+                   name: &'a Atom,
+                   child_terms: &'a Vec<Box<Term>>)
+    {
+        self.state_stack.push(IteratorState::Clause(lvl,
+                                                    child_num,
+                                                    cell,
+                                                    name,
+                                                    child_terms));
+    }
+
+    fn push_root_clause(&mut self,
+                        child_num: usize,
+                        child_terms: &'a Vec<Box<Term>>)
+    {
+        self.state_stack.push(IteratorState::RootClause(child_num, child_terms));
+    }
+
+    fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
+        self.state_stack.push(IteratorState::to_state(lvl, term));
+    }
+
+    fn new(term: &'a Term) -> QueryIterator<'a> {
+        let state = match term {
+            &Term::Atom(ref cell, ref atom) =>
+                IteratorState::IsolatedAtom(cell, atom),
+            &Term::Clause(_, _, ref terms) =>
+                IteratorState::RootClause(0, terms),
+            &Term::Var(ref cell, ref var) =>
+                IteratorState::IsolatedVar(cell, var)
+        };
+
+        QueryIterator { state_stack: vec![state] }
+    }
+}
+
+impl<'a> Iterator for QueryIterator<'a> {
+    type Item = TermRef<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        while let Some(iter_state) = self.state_stack.pop() {
+            match iter_state {
+                IteratorState::Atom(lvl, cell, atom) =>
+                    return Some(TermRef::Atom(lvl, cell, atom)),
+                IteratorState::Clause(lvl, child_num, cell, atom, child_terms) => {
+                    if child_num == child_terms.len() {
+                        return Some(TermRef::Clause(lvl, cell, atom, child_terms));
+                    } else {
+                        self.push_clause(lvl, child_num + 1, cell, atom, child_terms);
+                        self.push_subterm(Level::Deep, child_terms[child_num].as_ref());
+                    }
+                },
+                IteratorState::IsolatedAtom(cell, atom) =>
+                    return Some(TermRef::Atom(Level::Shallow, cell, atom)),
+                IteratorState::IsolatedVar(cell, var) =>
+                    return Some(TermRef::Var(Level::Shallow, cell, var)),
+                IteratorState::RootClause(child_num, child_terms) => {
+                    if child_num == child_terms.len() {
+                        return None;
+                    } else {
+                        self.push_root_clause(child_num + 1, child_terms);
+                        self.push_subterm(Level::Shallow, child_terms[child_num].as_ref());
+                    }
+                },
+                IteratorState::Var(lvl, cell, var) =>
+                    return Some(TermRef::Var(lvl, cell, var))
+            };
+        }
+
+        None
+    }
+}
+
+pub struct FactIterator<'a> {
+    state_queue: VecDeque<IteratorState<'a>>,
+}
+
+impl<'a> FactIterator<'a> {
+    fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
+        self.state_queue.push_back(IteratorState::to_state(lvl, term));
+    }
+
+    fn new(term: &'a Term) -> FactIterator<'a> {
+        let states = match term {
+            &Term::Atom(ref cell, ref atom) =>
+                vec![IteratorState::IsolatedAtom(cell, atom)],
+            &Term::Clause(_, _, ref terms) =>
+                vec![IteratorState::RootClause(0, terms)],
+            &Term::Var(ref cell, ref var) =>
+                vec![IteratorState::IsolatedVar(cell, var)]
+        };
+
+        FactIterator { state_queue:  VecDeque::from(states) }
+    }
+}
+
+impl<'a> Iterator for FactIterator<'a> {
+    type Item = TermRef<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        while let Some(state) = self.state_queue.pop_front() {
+            match state {
+                IteratorState::Atom(lvl, cell, atom) =>
+                    return Some(TermRef::Atom(lvl, cell, atom)),
+                IteratorState::Clause(lvl, _, cell, atom, child_terms) => {
+                    for child_term in child_terms {
+                        self.push_subterm(Level::Deep, child_term);
+                    }
+
+                    return Some(TermRef::Clause(lvl, cell, atom, child_terms));
+                },
+                IteratorState::IsolatedAtom(cell, atom) =>
+                    return Some(TermRef::Atom(Level::Shallow, cell, atom)),
+                IteratorState::IsolatedVar(cell, var) =>
+                    return Some(TermRef::Var(Level::Shallow, cell, var)),
+                IteratorState::RootClause(_, child_terms) => {
+                    for child_term in child_terms {
+                        self.push_subterm(Level::Shallow, child_term);
+                    }
+                },
+                IteratorState::Var(lvl, cell, var) =>
+                    return Some(TermRef::Var(lvl, cell, var))
+            }
+        }
+
+        None
+    }
+}
+
+impl Term {
+    pub fn post_order_iter(&self) -> QueryIterator {
+        QueryIterator::new(self)
+    }
+
+    pub fn breadth_first_iter(&self) -> FactIterator {
+        FactIterator::new(self)
+    }
+}
diff --git a/src/l3/l3_parser.lalrpop b/src/l3/l3_parser.lalrpop
new file mode 100644 (file)
index 0000000..7d97375
--- /dev/null
@@ -0,0 +1,59 @@
+use l3::ast::*;
+
+use std::cell::Cell;
+
+grammar;
+
+pub TopLevel: TopLevel = {
+    "?-" <t:Term> "." => TopLevel::Query(t),
+    <Predicate> => TopLevel::Predicate(<>),
+    <Rule>  "." => TopLevel::Rule(<>),
+    <Term>  "." => TopLevel::Fact(<>)    
+};
+
+Atom : Atom = {
+    r"[a-z][a-z0-9_]*" => <>.trim().to_string(),
+};
+
+BoxedTerm : Box<Term> = {
+    <t:Term> => Box::new(t)
+};
+
+Clause : Term = {
+    <a:Atom> "(" <ts: (<BoxedTerm> ",")*> <t:BoxedTerm> ")" => {
+       let mut ts = ts;
+       ts.push(t);
+       Term::Clause(Cell::new(RegType::Temp(0)), a, ts)
+    }
+};
+
+Predicate : Vec<PredicateClause> = {
+    <pcs: (<PredicateClause>)+> <pc: PredicateClause> => {
+        let mut pcs = pcs;
+       pcs.push(pc);
+       pcs
+    }  
+};
+
+PredicateClause : PredicateClause = {
+    <Rule> "." => PredicateClause::Rule(<>),
+    <Term> "." => PredicateClause::Fact(<>)
+};
+
+Rule : Rule = {
+    <c:Clause> ":-" <h:Term> <cs: ("," <Term>)*> =>
+         Rule { head: (c, h), clauses: cs },
+    <a:Atom> ":-" <h:Term> <cs: ("," <Term>)*> =>
+         Rule { head: (Term::Atom(Cell::new(RegType::Temp(0)), a), h),
+               clauses: cs }
+};
+
+Term : Term = {
+    <Clause> => <>,
+    <Atom>   => Term::Atom(Cell::new(RegType::Temp(0)), <>),
+    <Var>    => Term::Var(Cell::new(VarReg::Norm(RegType::Temp(0))), <>)
+};
+
+Var : Var = {
+    r"[A-Z][a-z0-9_]*" => <>.trim().to_string(),
+};
\ No newline at end of file
diff --git a/src/l3/l3_parser.rs b/src/l3/l3_parser.rs
new file mode 100644 (file)
index 0000000..dad3ada
--- /dev/null
@@ -0,0 +1,2177 @@
+use l3::ast::*;
+use std::cell::Cell;
+extern crate lalrpop_util as __lalrpop_util;
+
+mod __parse__TopLevel {
+    #![allow(non_snake_case, non_camel_case_types, unused_mut, unused_variables, unused_imports)]
+
+    use l3::ast::*;
+    use std::cell::Cell;
+    extern crate lalrpop_util as __lalrpop_util;
+    #[allow(dead_code)]
+    pub enum __Symbol<'input> {
+        Term_22_28_22(&'input str),
+        Term_22_29_22(&'input str),
+        Term_22_2c_22(&'input str),
+        Term_22_2e_22(&'input str),
+        Term_22_3a_2d_22(&'input str),
+        Term_22_3f_2d_22(&'input str),
+        Termr_23_22_5bA_2dZ_5d_5ba_2dz0_2d9___5d_2a_22_23(&'input str),
+        Termr_23_22_5ba_2dz_5d_5ba_2dz0_2d9___5d_2a_22_23(&'input str),
+        Termerror(__lalrpop_util::ErrorRecovery<usize, (usize, &'input str), ()>),
+        Nt_28_22_2c_22_20_3cTerm_3e_29(Term),
+        Nt_28_22_2c_22_20_3cTerm_3e_29_2a(::std::vec::Vec<Term>),
+        Nt_28_22_2c_22_20_3cTerm_3e_29_2b(::std::vec::Vec<Term>),
+        Nt_28_3cBoxedTerm_3e_20_22_2c_22_29(Box<Term>),
+        Nt_28_3cBoxedTerm_3e_20_22_2c_22_29_2a(::std::vec::Vec<Box<Term>>),
+        Nt_28_3cBoxedTerm_3e_20_22_2c_22_29_2b(::std::vec::Vec<Box<Term>>),
+        Nt_28_3cPredicateClause_3e_29(PredicateClause),
+        Nt_28_3cPredicateClause_3e_29_2b(::std::vec::Vec<PredicateClause>),
+        NtAtom(Atom),
+        NtBoxedTerm(Box<Term>),
+        NtClause(Term),
+        NtPredicate(Vec<PredicateClause>),
+        NtPredicateClause(PredicateClause),
+        NtRule(Rule),
+        NtTerm(Term),
+        NtTopLevel(TopLevel),
+        NtVar(Var),
+        Nt____TopLevel(TopLevel),
+    }
+    const __ACTION: &'static [i32] = &[
+        // State 0
+        0, 0, 0, 0, 0, 11, 12, 13, 0,
+        // State 1
+        0, 0, 0, 0, 0, 0, 12, 13, 0,
+        // State 2
+        17, 0, 0, -26, 18, 0, 0, 0, 0,
+        // State 3
+        0, 0, 0, -25, 19, 0, 0, 0, 0,
+        // State 4
+        0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 5
+        0, 0, 0, 0, 0, 0, -12, -12, 0,
+        // State 6
+        0, 0, 0, 20, 0, 0, 0, 0, 0,
+        // State 7
+        0, 0, 0, 21, 0, 0, 0, 0, 0,
+        // State 8
+        0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 9
+        0, 0, 0, -27, 0, 0, 0, 0, 0,
+        // State 10
+        0, 0, 0, 0, 0, 0, 12, 25, 0,
+        // State 11
+        0, 0, 0, -32, 0, 0, 0, 0, 0,
+        // State 12
+        -14, 0, 0, -14, -14, 0, 0, 0, 0,
+        // State 13
+        0, 0, 0, 0, 0, 0, -13, -13, 0,
+        // State 14
+        0, 0, 0, 26, 0, 0, 0, 0, 0,
+        // State 15
+        0, 0, 0, 27, 0, 0, 0, 0, 0,
+        // State 16
+        0, 0, 0, 0, 0, 0, 34, 35, 0,
+        // State 17
+        0, 0, 0, 0, 0, 0, 40, 41, 0,
+        // State 18
+        0, 0, 0, 0, 0, 0, 40, 41, 0,
+        // State 19
+        0, 0, 0, 0, 0, 0, -19, -19, 0,
+        // State 20
+        0, 0, 0, 0, 0, 0, -20, -20, 0,
+        // State 21
+        43, 0, 0, -26, 0, 0, 0, 0, 0,
+        // State 22
+        0, 0, 0, -25, 0, 0, 0, 0, 0,
+        // State 23
+        0, 0, 0, 44, 0, 0, 0, 0, 0,
+        // State 24
+        -14, 0, 0, -14, 0, 0, 0, 0, 0,
+        // State 25
+        0, 0, 0, 0, 0, 0, -19, -19, 0,
+        // State 26
+        0, 0, 0, 0, 0, 0, -20, -20, 0,
+        // State 27
+        0, 0, 0, 0, 0, 0, 34, 35, 0,
+        // State 28
+        46, -26, -26, 0, 0, 0, 0, 0, 0,
+        // State 29
+        0, 47, 48, 0, 0, 0, 0, 0, 0,
+        // State 30
+        0, -25, -25, 0, 0, 0, 0, 0, 0,
+        // State 31
+        0, -15, -15, 0, 0, 0, 0, 0, 0,
+        // State 32
+        0, -27, -27, 0, 0, 0, 0, 0, 0,
+        // State 33
+        0, -32, -32, 0, 0, 0, 0, 0, 0,
+        // State 34
+        -14, -14, -14, 0, 0, 0, 0, 0, 0,
+        // State 35
+        49, 0, -26, -26, 0, 0, 0, 0, 0,
+        // State 36
+        0, 0, -25, -25, 0, 0, 0, 0, 0,
+        // State 37
+        0, 0, 51, -23, 0, 0, 0, 0, 0,
+        // State 38
+        0, 0, -27, -27, 0, 0, 0, 0, 0,
+        // State 39
+        0, 0, -32, -32, 0, 0, 0, 0, 0,
+        // State 40
+        -14, 0, -14, -14, 0, 0, 0, 0, 0,
+        // State 41
+        0, 0, 51, -21, 0, 0, 0, 0, 0,
+        // State 42
+        0, 0, 0, 0, 0, 0, 34, 35, 0,
+        // State 43
+        0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 44
+        0, 55, 56, 0, 0, 0, 0, 0, 0,
+        // State 45
+        0, 0, 0, 0, 0, 0, 34, 35, 0,
+        // State 46
+        0, 0, 0, -16, -16, 0, 0, 0, 0,
+        // State 47
+        0, 0, 0, 0, 0, 0, -9, -9, 0,
+        // State 48
+        0, 0, 0, 0, 0, 0, 34, 35, 0,
+        // State 49
+        0, 0, 61, -24, 0, 0, 0, 0, 0,
+        // State 50
+        0, 0, 0, 0, 0, 0, 40, 41, 0,
+        // State 51
+        0, 0, 61, -22, 0, 0, 0, 0, 0,
+        // State 52
+        0, 0, 0, 0, 0, 0, 34, 35, 0,
+        // State 53
+        0, 64, 48, 0, 0, 0, 0, 0, 0,
+        // State 54
+        0, 0, 0, -17, -17, 0, 0, 0, 0,
+        // State 55
+        0, 0, 0, 0, 0, 0, -10, -10, 0,
+        // State 56
+        0, 0, 0, 0, 0, 0, 34, 35, 0,
+        // State 57
+        0, 66, 48, 0, 0, 0, 0, 0, 0,
+        // State 58
+        0, 0, 0, 0, 0, 0, 34, 35, 0,
+        // State 59
+        0, 68, 48, 0, 0, 0, 0, 0, 0,
+        // State 60
+        0, 0, 0, 0, 0, 0, 40, 41, 0,
+        // State 61
+        0, 0, -4, -4, 0, 0, 0, 0, 0,
+        // State 62
+        0, 70, 56, 0, 0, 0, 0, 0, 0,
+        // State 63
+        0, 0, 0, -16, 0, 0, 0, 0, 0,
+        // State 64
+        0, 71, 56, 0, 0, 0, 0, 0, 0,
+        // State 65
+        0, -16, -16, 0, 0, 0, 0, 0, 0,
+        // State 66
+        0, 72, 56, 0, 0, 0, 0, 0, 0,
+        // State 67
+        0, 0, -16, -16, 0, 0, 0, 0, 0,
+        // State 68
+        0, 0, -5, -5, 0, 0, 0, 0, 0,
+        // State 69
+        0, 0, 0, -17, 0, 0, 0, 0, 0,
+        // State 70
+        0, -17, -17, 0, 0, 0, 0, 0, 0,
+        // State 71
+        0, 0, -17, -17, 0, 0, 0, 0, 0,
+    ];
+    const __EOF_ACTION: &'static [i32] = &[
+        0,
+        0,
+        0,
+        0,
+        -29,
+        0,
+        0,
+        0,
+        -33,
+        0,
+        0,
+        0,
+        0,
+        -18,
+        0,
+        0,
+        0,
+        0,
+        0,
+        -30,
+        -31,
+        0,
+        0,
+        0,
+        0,
+        -19,
+        -20,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        -28,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+    ];
+    const __GOTO: &'static [i32] = &[
+        // State 0
+        0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 4, 5, 6, 7, 8, 9, 10, 0,
+        // State 1
+        0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 4, 0, 14, 15, 16, 0, 10, 0,
+        // State 2
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 3
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 4
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 5
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 6
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 7
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 8
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 9
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 10
+        0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 23, 0, 0, 0, 24, 0, 10, 0,
+        // State 11
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 12
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 13
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 14
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 15
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 16
+        0, 0, 0, 0, 0, 28, 0, 0, 29, 30, 31, 0, 0, 0, 32, 0, 33, 0,
+        // State 17
+        0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 37, 0, 0, 0, 38, 0, 39, 0,
+        // State 18
+        0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 37, 0, 0, 0, 42, 0, 39, 0,
+        // State 19
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 20
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 21
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 22
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 23
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 24
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 25
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 26
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 27
+        0, 0, 0, 0, 0, 0, 0, 0, 29, 45, 31, 0, 0, 0, 32, 0, 33, 0,
+        // State 28
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 29
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 30
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 31
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 32
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 33
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 34
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 35
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 36
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 37
+        0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 38
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 39
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 40
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 41
+        0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 42
+        0, 0, 0, 0, 0, 53, 0, 0, 29, 54, 31, 0, 0, 0, 32, 0, 33, 0,
+        // State 43
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 44
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 45
+        0, 0, 0, 0, 0, 57, 0, 0, 29, 58, 31, 0, 0, 0, 32, 0, 33, 0,
+        // State 46
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 47
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 48
+        0, 0, 0, 0, 0, 59, 0, 0, 29, 60, 31, 0, 0, 0, 32, 0, 33, 0,
+        // State 49
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 50
+        0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 37, 0, 0, 0, 62, 0, 39, 0,
+        // State 51
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 52
+        0, 0, 0, 0, 0, 0, 0, 0, 29, 63, 31, 0, 0, 0, 32, 0, 33, 0,
+        // State 53
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 54
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 55
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 56
+        0, 0, 0, 0, 0, 0, 0, 0, 29, 65, 31, 0, 0, 0, 32, 0, 33, 0,
+        // State 57
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 58
+        0, 0, 0, 0, 0, 0, 0, 0, 29, 67, 31, 0, 0, 0, 32, 0, 33, 0,
+        // State 59
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 60
+        0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 37, 0, 0, 0, 69, 0, 39, 0,
+        // State 61
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 62
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 63
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 64
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 65
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 66
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 67
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 68
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 69
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 70
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        // State 71
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    ];
+    fn __expected_tokens(__state: usize) -> Vec<::std::string::String> {
+        const __TERMINAL: &'static [&'static str] = &[
+            r###""(""###,
+            r###"")""###,
+            r###"",""###,
+            r###"".""###,
+            r###"":-""###,
+            r###""?-""###,
+            r###"r#"[A-Z][a-z0-9_]*"#"###,
+            r###"r#"[a-z][a-z0-9_]*"#"###,
+        ];
+        __ACTION[(__state * 9)..].iter().zip(__TERMINAL).filter_map(|(&state, terminal)| {
+            if state == 0 {
+                None
+            } else {
+                Some(terminal.to_string())
+            }
+        }).collect()
+    }
+    pub fn parse_TopLevel<
+        'input,
+    >(
+        input: &'input str,
+    ) -> Result<TopLevel, __lalrpop_util::ParseError<usize, (usize, &'input str), ()>>
+    {
+        let mut __tokens = super::__intern_token::__Matcher::new(input);
+        let mut __states = vec![0_i32];
+        let mut __symbols = vec![];
+        let mut __integer;
+        let mut __lookahead;
+        let mut __last_location = Default::default();
+        '__shift: loop {
+            __lookahead = match __tokens.next() {
+                Some(Ok(v)) => v,
+                None => break '__shift,
+                Some(Err(e)) => return Err(e),
+            };
+            __last_location = __lookahead.2.clone();
+            __integer = match __lookahead.1 {
+                (0, _) if true => 0,
+                (1, _) if true => 1,
+                (2, _) if true => 2,
+                (3, _) if true => 3,
+                (4, _) if true => 4,
+                (5, _) if true => 5,
+                (6, _) if true => 6,
+                (7, _) if true => 7,
+                _ => {
+                    let __state = *__states.last().unwrap() as usize;
+                    let __error = __lalrpop_util::ParseError::UnrecognizedToken {
+                        token: Some(__lookahead),
+                        expected: __expected_tokens(__state),
+                    };
+                    return Err(__error);
+                }
+            };
+            '__inner: loop {
+                let __state = *__states.last().unwrap() as usize;
+                let __action = __ACTION[__state * 9 + __integer];
+                if __action > 0 {
+                    let __symbol = match __integer {
+                        0 => match __lookahead.1 {
+                            (0, __tok0) => __Symbol::Term_22_28_22(__tok0),
+                            _ => unreachable!(),
+                        },
+                        1 => match __lookahead.1 {
+                            (1, __tok0) => __Symbol::Term_22_29_22(__tok0),
+                            _ => unreachable!(),
+                        },
+                        2 => match __lookahead.1 {
+                            (2, __tok0) => __Symbol::Term_22_2c_22(__tok0),
+                            _ => unreachable!(),
+                        },
+                        3 => match __lookahead.1 {
+                            (3, __tok0) => __Symbol::Term_22_2e_22(__tok0),
+                            _ => unreachable!(),
+                        },
+                        4 => match __lookahead.1 {
+                            (4, __tok0) => __Symbol::Term_22_3a_2d_22(__tok0),
+                            _ => unreachable!(),
+                        },
+                        5 => match __lookahead.1 {
+                            (5, __tok0) => __Symbol::Term_22_3f_2d_22(__tok0),
+                            _ => unreachable!(),
+                        },
+                        6 => match __lookahead.1 {
+                            (6, __tok0) => __Symbol::Termr_23_22_5bA_2dZ_5d_5ba_2dz0_2d9___5d_2a_22_23(__tok0),
+                            _ => unreachable!(),
+                        },
+                        7 => match __lookahead.1 {
+                            (7, __tok0) => __Symbol::Termr_23_22_5ba_2dz_5d_5ba_2dz0_2d9___5d_2a_22_23(__tok0),
+                            _ => unreachable!(),
+                        },
+                        _ => unreachable!(),
+                    };
+                    __states.push(__action - 1);
+                    __symbols.push((__lookahead.0, __symbol, __lookahead.2));
+                    continue '__shift;
+                } else if __action < 0 {
+                    if let Some(r) = __reduce(input, __action, Some(&__lookahead.0), &mut __states, &mut __symbols, ::std::marker::PhantomData::<()>) {
+                        return r;
+                    }
+                } else {
+                    let __state = *__states.last().unwrap() as usize;
+                    let __error = __lalrpop_util::ParseError::UnrecognizedToken {
+                        token: Some(__lookahead),
+                        expected: __expected_tokens(__state),
+                    };
+                    return Err(__error)
+                }
+            }
+        }
+        loop {
+            let __state = *__states.last().unwrap() as usize;
+            let __action = __EOF_ACTION[__state];
+            if __action < 0 {
+                if let Some(r) = __reduce(input, __action, None, &mut __states, &mut __symbols, ::std::marker::PhantomData::<()>) {
+                    return r;
+                }
+            } else {
+                let __state = *__states.last().unwrap() as usize;
+                let __error = __lalrpop_util::ParseError::UnrecognizedToken {
+                    token: None,
+                    expected: __expected_tokens(__state),
+                };
+                return Err(__error);
+            }
+        }
+    }
+    pub fn __reduce<
+        'input,
+    >(
+        input: &'input str,
+        __action: i32,
+        __lookahead_start: Option<&usize>,
+        __states: &mut ::std::vec::Vec<i32>,
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>,
+        _: ::std::marker::PhantomData<()>,
+    ) -> Option<Result<TopLevel,__lalrpop_util::ParseError<usize, (usize, &'input str), ()>>>
+    {
+        let __nonterminal = match -__action {
+            1 => {
+                // ("," <Term>) = ",", Term => ActionFn(19);
+                let __sym1 = __pop_NtTerm(__symbols);
+                let __sym0 = __pop_Term_22_2c_22(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym1.2.clone();
+                let __nt = super::__action19::<>(input, __sym0, __sym1);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 2);
+                __symbols.push((__start, __Symbol::Nt_28_22_2c_22_20_3cTerm_3e_29(__nt), __end));
+                0
+            }
+            2 => {
+                // ("," <Term>)* =  => ActionFn(17);
+                let __start = __symbols.last().map(|s| s.2.clone()).unwrap_or_default();
+                let __end = __lookahead_start.cloned().unwrap_or_else(|| __start.clone());
+                let __nt = super::__action17::<>(input, &__start, &__end);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 0);
+                __symbols.push((__start, __Symbol::Nt_28_22_2c_22_20_3cTerm_3e_29_2a(__nt), __end));
+                1
+            }
+            3 => {
+                // ("," <Term>)* = ("," <Term>)+ => ActionFn(18);
+                let __sym0 = __pop_Nt_28_22_2c_22_20_3cTerm_3e_29_2b(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym0.2.clone();
+                let __nt = super::__action18::<>(input, __sym0);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 1);
+                __symbols.push((__start, __Symbol::Nt_28_22_2c_22_20_3cTerm_3e_29_2a(__nt), __end));
+                1
+            }
+            4 => {
+                // ("," <Term>)+ = ",", Term => ActionFn(30);
+                let __sym1 = __pop_NtTerm(__symbols);
+                let __sym0 = __pop_Term_22_2c_22(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym1.2.clone();
+                let __nt = super::__action30::<>(input, __sym0, __sym1);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 2);
+                __symbols.push((__start, __Symbol::Nt_28_22_2c_22_20_3cTerm_3e_29_2b(__nt), __end));
+                2
+            }
+            5 => {
+                // ("," <Term>)+ = ("," <Term>)+, ",", Term => ActionFn(31);
+                let __sym2 = __pop_NtTerm(__symbols);
+                let __sym1 = __pop_Term_22_2c_22(__symbols);
+                let __sym0 = __pop_Nt_28_22_2c_22_20_3cTerm_3e_29_2b(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym2.2.clone();
+                let __nt = super::__action31::<>(input, __sym0, __sym1, __sym2);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 3);
+                __symbols.push((__start, __Symbol::Nt_28_22_2c_22_20_3cTerm_3e_29_2b(__nt), __end));
+                2
+            }
+            6 => {
+                // (<BoxedTerm> ",") = BoxedTerm, "," => ActionFn(25);
+                let __sym1 = __pop_Term_22_2c_22(__symbols);
+                let __sym0 = __pop_NtBoxedTerm(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym1.2.clone();
+                let __nt = super::__action25::<>(input, __sym0, __sym1);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 2);
+                __symbols.push((__start, __Symbol::Nt_28_3cBoxedTerm_3e_20_22_2c_22_29(__nt), __end));
+                3
+            }
+            7 => {
+                // (<BoxedTerm> ",")* =  => ActionFn(23);
+                let __start = __symbols.last().map(|s| s.2.clone()).unwrap_or_default();
+                let __end = __lookahead_start.cloned().unwrap_or_else(|| __start.clone());
+                let __nt = super::__action23::<>(input, &__start, &__end);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 0);
+                __symbols.push((__start, __Symbol::Nt_28_3cBoxedTerm_3e_20_22_2c_22_29_2a(__nt), __end));
+                4
+            }
+            8 => {
+                // (<BoxedTerm> ",")* = (<BoxedTerm> ",")+ => ActionFn(24);
+                let __sym0 = __pop_Nt_28_3cBoxedTerm_3e_20_22_2c_22_29_2b(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym0.2.clone();
+                let __nt = super::__action24::<>(input, __sym0);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 1);
+                __symbols.push((__start, __Symbol::Nt_28_3cBoxedTerm_3e_20_22_2c_22_29_2a(__nt), __end));
+                4
+            }
+            9 => {
+                // (<BoxedTerm> ",")+ = BoxedTerm, "," => ActionFn(36);
+                let __sym1 = __pop_Term_22_2c_22(__symbols);
+                let __sym0 = __pop_NtBoxedTerm(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym1.2.clone();
+                let __nt = super::__action36::<>(input, __sym0, __sym1);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 2);
+                __symbols.push((__start, __Symbol::Nt_28_3cBoxedTerm_3e_20_22_2c_22_29_2b(__nt), __end));
+                5
+            }
+            10 => {
+                // (<BoxedTerm> ",")+ = (<BoxedTerm> ",")+, BoxedTerm, "," => ActionFn(37);
+                let __sym2 = __pop_Term_22_2c_22(__symbols);
+                let __sym1 = __pop_NtBoxedTerm(__symbols);
+                let __sym0 = __pop_Nt_28_3cBoxedTerm_3e_20_22_2c_22_29_2b(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym2.2.clone();
+                let __nt = super::__action37::<>(input, __sym0, __sym1, __sym2);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 3);
+                __symbols.push((__start, __Symbol::Nt_28_3cBoxedTerm_3e_20_22_2c_22_29_2b(__nt), __end));
+                5
+            }
+            11 => {
+                // (<PredicateClause>) = PredicateClause => ActionFn(22);
+                let __sym0 = __pop_NtPredicateClause(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym0.2.clone();
+                let __nt = super::__action22::<>(input, __sym0);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 1);
+                __symbols.push((__start, __Symbol::Nt_28_3cPredicateClause_3e_29(__nt), __end));
+                6
+            }
+            12 => {
+                // (<PredicateClause>)+ = PredicateClause => ActionFn(40);
+                let __sym0 = __pop_NtPredicateClause(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym0.2.clone();
+                let __nt = super::__action40::<>(input, __sym0);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 1);
+                __symbols.push((__start, __Symbol::Nt_28_3cPredicateClause_3e_29_2b(__nt), __end));
+                7
+            }
+            13 => {
+                // (<PredicateClause>)+ = (<PredicateClause>)+, PredicateClause => ActionFn(41);
+                let __sym1 = __pop_NtPredicateClause(__symbols);
+                let __sym0 = __pop_Nt_28_3cPredicateClause_3e_29_2b(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym1.2.clone();
+                let __nt = super::__action41::<>(input, __sym0, __sym1);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 2);
+                __symbols.push((__start, __Symbol::Nt_28_3cPredicateClause_3e_29_2b(__nt), __end));
+                7
+            }
+            14 => {
+                // Atom = r#"[a-z][a-z0-9_]*"# => ActionFn(5);
+                let __sym0 = __pop_Termr_23_22_5ba_2dz_5d_5ba_2dz0_2d9___5d_2a_22_23(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym0.2.clone();
+                let __nt = super::__action5::<>(input, __sym0);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 1);
+                __symbols.push((__start, __Symbol::NtAtom(__nt), __end));
+                8
+            }
+            15 => {
+                // BoxedTerm = Term => ActionFn(6);
+                let __sym0 = __pop_NtTerm(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym0.2.clone();
+                let __nt = super::__action6::<>(input, __sym0);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 1);
+                __symbols.push((__start, __Symbol::NtBoxedTerm(__nt), __end));
+                9
+            }
+            16 => {
+                // Clause = Atom, "(", BoxedTerm, ")" => ActionFn(38);
+                let __sym3 = __pop_Term_22_29_22(__symbols);
+                let __sym2 = __pop_NtBoxedTerm(__symbols);
+                let __sym1 = __pop_Term_22_28_22(__symbols);
+                let __sym0 = __pop_NtAtom(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym3.2.clone();
+                let __nt = super::__action38::<>(input, __sym0, __sym1, __sym2, __sym3);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 4);
+                __symbols.push((__start, __Symbol::NtClause(__nt), __end));
+                10
+            }
+            17 => {
+                // Clause = Atom, "(", (<BoxedTerm> ",")+, BoxedTerm, ")" => ActionFn(39);
+                let __sym4 = __pop_Term_22_29_22(__symbols);
+                let __sym3 = __pop_NtBoxedTerm(__symbols);
+                let __sym2 = __pop_Nt_28_3cBoxedTerm_3e_20_22_2c_22_29_2b(__symbols);
+                let __sym1 = __pop_Term_22_28_22(__symbols);
+                let __sym0 = __pop_NtAtom(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym4.2.clone();
+                let __nt = super::__action39::<>(input, __sym0, __sym1, __sym2, __sym3, __sym4);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 5);
+                __symbols.push((__start, __Symbol::NtClause(__nt), __end));
+                10
+            }
+            18 => {
+                // Predicate = (<PredicateClause>)+, PredicateClause => ActionFn(8);
+                let __sym1 = __pop_NtPredicateClause(__symbols);
+                let __sym0 = __pop_Nt_28_3cPredicateClause_3e_29_2b(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym1.2.clone();
+                let __nt = super::__action8::<>(input, __sym0, __sym1);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 2);
+                __symbols.push((__start, __Symbol::NtPredicate(__nt), __end));
+                11
+            }
+            19 => {
+                // PredicateClause = Rule, "." => ActionFn(9);
+                let __sym1 = __pop_Term_22_2e_22(__symbols);
+                let __sym0 = __pop_NtRule(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym1.2.clone();
+                let __nt = super::__action9::<>(input, __sym0, __sym1);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 2);
+                __symbols.push((__start, __Symbol::NtPredicateClause(__nt), __end));
+                12
+            }
+            20 => {
+                // PredicateClause = Term, "." => ActionFn(10);
+                let __sym1 = __pop_Term_22_2e_22(__symbols);
+                let __sym0 = __pop_NtTerm(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym1.2.clone();
+                let __nt = super::__action10::<>(input, __sym0, __sym1);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 2);
+                __symbols.push((__start, __Symbol::NtPredicateClause(__nt), __end));
+                12
+            }
+            21 => {
+                // Rule = Clause, ":-", Term => ActionFn(32);
+                let __sym2 = __pop_NtTerm(__symbols);
+                let __sym1 = __pop_Term_22_3a_2d_22(__symbols);
+                let __sym0 = __pop_NtClause(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym2.2.clone();
+                let __nt = super::__action32::<>(input, __sym0, __sym1, __sym2);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 3);
+                __symbols.push((__start, __Symbol::NtRule(__nt), __end));
+                13
+            }
+            22 => {
+                // Rule = Clause, ":-", Term, ("," <Term>)+ => ActionFn(33);
+                let __sym3 = __pop_Nt_28_22_2c_22_20_3cTerm_3e_29_2b(__symbols);
+                let __sym2 = __pop_NtTerm(__symbols);
+                let __sym1 = __pop_Term_22_3a_2d_22(__symbols);
+                let __sym0 = __pop_NtClause(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym3.2.clone();
+                let __nt = super::__action33::<>(input, __sym0, __sym1, __sym2, __sym3);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 4);
+                __symbols.push((__start, __Symbol::NtRule(__nt), __end));
+                13
+            }
+            23 => {
+                // Rule = Atom, ":-", Term => ActionFn(34);
+                let __sym2 = __pop_NtTerm(__symbols);
+                let __sym1 = __pop_Term_22_3a_2d_22(__symbols);
+                let __sym0 = __pop_NtAtom(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym2.2.clone();
+                let __nt = super::__action34::<>(input, __sym0, __sym1, __sym2);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 3);
+                __symbols.push((__start, __Symbol::NtRule(__nt), __end));
+                13
+            }
+            24 => {
+                // Rule = Atom, ":-", Term, ("," <Term>)+ => ActionFn(35);
+                let __sym3 = __pop_Nt_28_22_2c_22_20_3cTerm_3e_29_2b(__symbols);
+                let __sym2 = __pop_NtTerm(__symbols);
+                let __sym1 = __pop_Term_22_3a_2d_22(__symbols);
+                let __sym0 = __pop_NtAtom(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym3.2.clone();
+                let __nt = super::__action35::<>(input, __sym0, __sym1, __sym2, __sym3);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 4);
+                __symbols.push((__start, __Symbol::NtRule(__nt), __end));
+                13
+            }
+            25 => {
+                // Term = Clause => ActionFn(13);
+                let __sym0 = __pop_NtClause(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym0.2.clone();
+                let __nt = super::__action13::<>(input, __sym0);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 1);
+                __symbols.push((__start, __Symbol::NtTerm(__nt), __end));
+                14
+            }
+            26 => {
+                // Term = Atom => ActionFn(14);
+                let __sym0 = __pop_NtAtom(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym0.2.clone();
+                let __nt = super::__action14::<>(input, __sym0);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 1);
+                __symbols.push((__start, __Symbol::NtTerm(__nt), __end));
+                14
+            }
+            27 => {
+                // Term = Var => ActionFn(15);
+                let __sym0 = __pop_NtVar(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym0.2.clone();
+                let __nt = super::__action15::<>(input, __sym0);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 1);
+                __symbols.push((__start, __Symbol::NtTerm(__nt), __end));
+                14
+            }
+            28 => {
+                // TopLevel = "?-", Term, "." => ActionFn(1);
+                let __sym2 = __pop_Term_22_2e_22(__symbols);
+                let __sym1 = __pop_NtTerm(__symbols);
+                let __sym0 = __pop_Term_22_3f_2d_22(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym2.2.clone();
+                let __nt = super::__action1::<>(input, __sym0, __sym1, __sym2);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 3);
+                __symbols.push((__start, __Symbol::NtTopLevel(__nt), __end));
+                15
+            }
+            29 => {
+                // TopLevel = Predicate => ActionFn(2);
+                let __sym0 = __pop_NtPredicate(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym0.2.clone();
+                let __nt = super::__action2::<>(input, __sym0);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 1);
+                __symbols.push((__start, __Symbol::NtTopLevel(__nt), __end));
+                15
+            }
+            30 => {
+                // TopLevel = Rule, "." => ActionFn(3);
+                let __sym1 = __pop_Term_22_2e_22(__symbols);
+                let __sym0 = __pop_NtRule(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym1.2.clone();
+                let __nt = super::__action3::<>(input, __sym0, __sym1);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 2);
+                __symbols.push((__start, __Symbol::NtTopLevel(__nt), __end));
+                15
+            }
+            31 => {
+                // TopLevel = Term, "." => ActionFn(4);
+                let __sym1 = __pop_Term_22_2e_22(__symbols);
+                let __sym0 = __pop_NtTerm(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym1.2.clone();
+                let __nt = super::__action4::<>(input, __sym0, __sym1);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 2);
+                __symbols.push((__start, __Symbol::NtTopLevel(__nt), __end));
+                15
+            }
+            32 => {
+                // Var = r#"[A-Z][a-z0-9_]*"# => ActionFn(16);
+                let __sym0 = __pop_Termr_23_22_5bA_2dZ_5d_5ba_2dz0_2d9___5d_2a_22_23(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym0.2.clone();
+                let __nt = super::__action16::<>(input, __sym0);
+                let __states_len = __states.len();
+                __states.truncate(__states_len - 1);
+                __symbols.push((__start, __Symbol::NtVar(__nt), __end));
+                16
+            }
+            33 => {
+                // __TopLevel = TopLevel => ActionFn(0);
+                let __sym0 = __pop_NtTopLevel(__symbols);
+                let __start = __sym0.0.clone();
+                let __end = __sym0.2.clone();
+                let __nt = super::__action0::<>(input, __sym0);
+                return Some(Ok(__nt));
+            }
+            _ => panic!("invalid action code {}", __action)
+        };
+        let __state = *__states.last().unwrap() as usize;
+        let __next_state = __GOTO[__state * 18 + __nonterminal] - 1;
+        __states.push(__next_state);
+        None
+    }
+    fn __pop_Term_22_28_22<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, &'input str, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Term_22_28_22(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_Term_22_29_22<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, &'input str, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Term_22_29_22(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_Term_22_2c_22<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, &'input str, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Term_22_2c_22(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_Term_22_2e_22<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, &'input str, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Term_22_2e_22(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_Term_22_3a_2d_22<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, &'input str, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Term_22_3a_2d_22(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_Term_22_3f_2d_22<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, &'input str, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Term_22_3f_2d_22(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_Termr_23_22_5bA_2dZ_5d_5ba_2dz0_2d9___5d_2a_22_23<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, &'input str, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Termr_23_22_5bA_2dZ_5d_5ba_2dz0_2d9___5d_2a_22_23(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_Termr_23_22_5ba_2dz_5d_5ba_2dz0_2d9___5d_2a_22_23<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, &'input str, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Termr_23_22_5ba_2dz_5d_5ba_2dz0_2d9___5d_2a_22_23(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_Termerror<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, __lalrpop_util::ErrorRecovery<usize, (usize, &'input str), ()>, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Termerror(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_Nt_28_22_2c_22_20_3cTerm_3e_29<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, Term, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Nt_28_22_2c_22_20_3cTerm_3e_29(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_Nt_28_22_2c_22_20_3cTerm_3e_29_2a<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, ::std::vec::Vec<Term>, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Nt_28_22_2c_22_20_3cTerm_3e_29_2a(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_Nt_28_22_2c_22_20_3cTerm_3e_29_2b<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, ::std::vec::Vec<Term>, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Nt_28_22_2c_22_20_3cTerm_3e_29_2b(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_Nt_28_3cBoxedTerm_3e_20_22_2c_22_29<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, Box<Term>, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Nt_28_3cBoxedTerm_3e_20_22_2c_22_29(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_Nt_28_3cBoxedTerm_3e_20_22_2c_22_29_2a<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, ::std::vec::Vec<Box<Term>>, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Nt_28_3cBoxedTerm_3e_20_22_2c_22_29_2a(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_Nt_28_3cBoxedTerm_3e_20_22_2c_22_29_2b<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, ::std::vec::Vec<Box<Term>>, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Nt_28_3cBoxedTerm_3e_20_22_2c_22_29_2b(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_Nt_28_3cPredicateClause_3e_29<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, PredicateClause, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Nt_28_3cPredicateClause_3e_29(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_Nt_28_3cPredicateClause_3e_29_2b<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, ::std::vec::Vec<PredicateClause>, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Nt_28_3cPredicateClause_3e_29_2b(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_NtAtom<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, Atom, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::NtAtom(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_NtBoxedTerm<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, Box<Term>, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::NtBoxedTerm(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_NtClause<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, Term, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::NtClause(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_NtPredicate<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, Vec<PredicateClause>, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::NtPredicate(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_NtPredicateClause<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, PredicateClause, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::NtPredicateClause(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_NtRule<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, Rule, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::NtRule(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_NtTerm<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, Term, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::NtTerm(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_NtTopLevel<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, TopLevel, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::NtTopLevel(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_NtVar<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, Var, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::NtVar(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+    fn __pop_Nt____TopLevel<
+      'input,
+    >(
+        __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
+    ) -> (usize, TopLevel, usize) {
+        match __symbols.pop().unwrap() {
+            (__l, __Symbol::Nt____TopLevel(__v), __r) => (__l, __v, __r),
+            _ => panic!("symbol type mismatch")
+        }
+    }
+}
+pub use self::__parse__TopLevel::parse_TopLevel;
+mod __intern_token {
+    extern crate lalrpop_util as __lalrpop_util;
+    pub struct __Matcher<'input> {
+        text: &'input str,
+        consumed: usize,
+    }
+
+    fn __tokenize(text: &str) -> Option<(usize, usize)> {
+        let mut __chars = text.char_indices();
+        let mut __current_match: Option<(usize, usize)> = None;
+        let mut __current_state: usize = 0;
+        loop {
+            match __current_state {
+                0 => {
+                    let (__index, __ch) = match __chars.next() { Some(p) => p, None => return __current_match };
+                    match __ch as u32 {
+                        40 => /* '(' */ {
+                            __current_match = Some((0, __index + 1));
+                            __current_state = 1;
+                            continue;
+                        }
+                        41 => /* ')' */ {
+                            __current_match = Some((1, __index + 1));
+                            __current_state = 2;
+                            continue;
+                        }
+                        44 => /* ',' */ {
+                            __current_match = Some((2, __index + 1));
+                            __current_state = 3;
+                            continue;
+                        }
+                        46 => /* '.' */ {
+                            __current_match = Some((3, __index + 1));
+                            __current_state = 4;
+                            continue;
+                        }
+                        58 => /* ':' */ {
+                            __current_state = 5;
+                            continue;
+                        }
+                        63 => /* '?' */ {
+                            __current_state = 6;
+                            continue;
+                        }
+                        65 ... 90 => {
+                            __current_match = Some((6, __index + __ch.len_utf8()));
+                            __current_state = 7;
+                            continue;
+                        }
+                        97 ... 122 => {
+                            __current_match = Some((7, __index + __ch.len_utf8()));
+                            __current_state = 8;
+                            continue;
+                        }
+                        _ => {
+                            return __current_match;
+                        }
+                    }
+                }
+                1 => {
+                    let (__index, __ch) = match __chars.next() { Some(p) => p, None => return __current_match };
+                    match __ch as u32 {
+                        _ => {
+                            return __current_match;
+                        }
+                    }
+                }
+                2 => {
+                    let (__index, __ch) = match __chars.next() { Some(p) => p, None => return __current_match };
+                    match __ch as u32 {
+                        _ => {
+                            return __current_match;
+                        }
+                    }
+                }
+                3 => {
+                    let (__index, __ch) = match __chars.next() { Some(p) => p, None => return __current_match };
+                    match __ch as u32 {
+                        _ => {
+                            return __current_match;
+                        }
+                    }
+                }
+                4 => {
+                    let (__index, __ch) = match __chars.next() { Some(p) => p, None => return __current_match };
+                    match __ch as u32 {
+                        _ => {
+                            return __current_match;
+                        }
+                    }
+                }
+                5 => {
+                    let (__index, __ch) = match __chars.next() { Some(p) => p, None => return __current_match };
+                    match __ch as u32 {
+                        45 => /* '-' */ {
+                            __current_match = Some((4, __index + 1));
+                            __current_state = 10;
+                            continue;
+                        }
+                        _ => {
+                            return __current_match;
+                        }
+                    }
+                }
+                6 => {
+                    let (__index, __ch) = match __chars.next() { Some(p) => p, None => return __current_match };
+                    match __ch as u32 {
+                        45 => /* '-' */ {
+                            __current_match = Some((5, __index + 1));
+                            __current_state = 11;
+                            continue;
+                        }
+                        _ => {
+                            return __current_match;
+                        }
+                    }
+                }
+                7 => {
+                    let (__index, __ch) = match __chars.next() { Some(p) => p, None => return __current_match };
+                    match __ch as u32 {
+                        48 ... 57 => {
+                            __current_match = Some((6, __index + __ch.len_utf8()));
+                            __current_state = 12;
+                            continue;
+                        }
+                        95 => /* '_' */ {
+                            __current_match = Some((6, __index + 1));
+                            __current_state = 12;
+                            continue;
+                        }
+                        97 ... 122 => {
+                            __current_match = Some((6, __index + __ch.len_utf8()));
+                            __current_state = 12;
+                            continue;
+                        }
+                        _ => {
+                            return __current_match;
+                        }
+                    }
+                }
+                8 => {
+                    let (__index, __ch) = match __chars.next() { Some(p) => p, None => return __current_match };
+                    match __ch as u32 {
+                        48 ... 57 => {
+                            __current_match = Some((7, __index + __ch.len_utf8()));
+                            __current_state = 13;
+                            continue;
+                        }
+                        95 => /* '_' */ {
+                            __current_match = Some((7, __index + 1));
+                            __current_state = 13;
+                            continue;
+                        }
+                        97 ... 122 => {
+                            __current_match = Some((7, __index + __ch.len_utf8()));
+                            __current_state = 13;
+                            continue;
+                        }
+                        _ => {
+                            return __current_match;
+                        }
+                    }
+                }
+                9 => {
+                    let (__index, __ch) = match __chars.next() { Some(p) => p, None => return __current_match };
+                    match __ch as u32 {
+                        _ => {
+                            return __current_match;
+                        }
+                    }
+                }
+                10 => {
+                    let (__index, __ch) = match __chars.next() { Some(p) => p, None => return __current_match };
+                    match __ch as u32 {
+                        _ => {
+                            return __current_match;
+                        }
+                    }
+                }
+                11 => {
+                    let (__index, __ch) = match __chars.next() { Some(p) => p, None => return __current_match };
+                    match __ch as u32 {
+                        _ => {
+                            return __current_match;
+                        }
+                    }
+                }
+                12 => {
+                    let (__index, __ch) = match __chars.next() { Some(p) => p, None => return __current_match };
+                    match __ch as u32 {
+                        48 ... 57 => {
+                            __current_match = Some((6, __index + __ch.len_utf8()));
+                            __current_state = 12;
+                            continue;
+                        }
+                        95 => /* '_' */ {
+                            __current_match = Some((6, __index + 1));
+                            __current_state = 12;
+                            continue;
+                        }
+                        97 ... 122 => {
+                            __current_match = Some((6, __index + __ch.len_utf8()));
+                            __current_state = 12;
+                            continue;
+                        }
+                        _ => {
+                            return __current_match;
+                        }
+                    }
+                }
+                13 => {
+                    let (__index, __ch) = match __chars.next() { Some(p) => p, None => return __current_match };
+                    match __ch as u32 {
+                        48 ... 57 => {
+                            __current_match = Some((7, __index + __ch.len_utf8()));
+                            __current_state = 13;
+                            continue;
+                        }
+                        95 => /* '_' */ {
+                            __current_match = Some((7, __index + 1));
+                            __current_state = 13;
+                            continue;
+                        }
+                        97 ... 122 => {
+                            __current_match = Some((7, __index + __ch.len_utf8()));
+                            __current_state = 13;
+                            continue;
+                        }
+                        _ => {
+                            return __current_match;
+                        }
+                    }
+                }
+                _ => { panic!("invalid state {}", __current_state); }
+            }
+        }
+    }
+
+    impl<'input> __Matcher<'input> {
+        pub fn new(s: &'input str) -> __Matcher<'input> {
+            __Matcher { text: s, consumed: 0 }
+        }
+    }
+
+    impl<'input> Iterator for __Matcher<'input> {
+        type Item = Result<(usize, (usize, &'input str), usize), __lalrpop_util::ParseError<usize,(usize, &'input str),()>>;
+
+        fn next(&mut self) -> Option<Self::Item> {
+            let __text = self.text.trim_left();
+            let __whitespace = self.text.len() - __text.len();
+            let __start_offset = self.consumed + __whitespace;
+            if __text.is_empty() {
+                self.text = __text;
+                self.consumed = __start_offset;
+                None
+            } else {
+                match __tokenize(__text) {
+                    Some((__index, __length)) => {
+                        let __result = &__text[..__length];
+                        let __remaining = &__text[__length..];
+                        let __end_offset = __start_offset + __length;
+                        self.text = __remaining;
+                        self.consumed = __end_offset;
+                        Some(Ok((__start_offset, (__index, __result), __end_offset)))
+                    }
+                    None => {
+                        Some(Err(__lalrpop_util::ParseError::InvalidToken { location: __start_offset }))
+                    }
+                }
+            }
+        }
+    }
+}
+
+#[allow(unused_variables)]
+pub fn __action0<
+    'input,
+>(
+    input: &'input str,
+    (_, __0, _): (usize, TopLevel, usize),
+) -> TopLevel
+{
+    (__0)
+}
+
+#[allow(unused_variables)]
+pub fn __action1<
+    'input,
+>(
+    input: &'input str,
+    (_, _, _): (usize, &'input str, usize),
+    (_, t, _): (usize, Term, usize),
+    (_, _, _): (usize, &'input str, usize),
+) -> TopLevel
+{
+    TopLevel::Query(t)
+}
+
+#[allow(unused_variables)]
+pub fn __action2<
+    'input,
+>(
+    input: &'input str,
+    (_, __0, _): (usize, Vec<PredicateClause>, usize),
+) -> TopLevel
+{
+    TopLevel::Predicate(__0)
+}
+
+#[allow(unused_variables)]
+pub fn __action3<
+    'input,
+>(
+    input: &'input str,
+    (_, __0, _): (usize, Rule, usize),
+    (_, _, _): (usize, &'input str, usize),
+) -> TopLevel
+{
+    TopLevel::Rule(__0)
+}
+
+#[allow(unused_variables)]
+pub fn __action4<
+    'input,
+>(
+    input: &'input str,
+    (_, __0, _): (usize, Term, usize),
+    (_, _, _): (usize, &'input str, usize),
+) -> TopLevel
+{
+    TopLevel::Fact(__0)
+}
+
+#[allow(unused_variables)]
+pub fn __action5<
+    'input,
+>(
+    input: &'input str,
+    (_, __0, _): (usize, &'input str, usize),
+) -> Atom
+{
+    __0.trim().to_string()
+}
+
+#[allow(unused_variables)]
+pub fn __action6<
+    'input,
+>(
+    input: &'input str,
+    (_, t, _): (usize, Term, usize),
+) -> Box<Term>
+{
+    Box::new(t)
+}
+
+#[allow(unused_variables)]
+pub fn __action7<
+    'input,
+>(
+    input: &'input str,
+    (_, a, _): (usize, Atom, usize),
+    (_, _, _): (usize, &'input str, usize),
+    (_, ts, _): (usize, ::std::vec::Vec<Box<Term>>, usize),
+    (_, t, _): (usize, Box<Term>, usize),
+    (_, _, _): (usize, &'input str, usize),
+) -> Term
+{
+    {
+       let mut ts = ts;
+       ts.push(t);
+       Term::Clause(Cell::new(RegType::Temp(0)), a, ts)
+    }
+}
+
+#[allow(unused_variables)]
+pub fn __action8<
+    'input,
+>(
+    input: &'input str,
+    (_, pcs, _): (usize, ::std::vec::Vec<PredicateClause>, usize),
+    (_, pc, _): (usize, PredicateClause, usize),
+) -> Vec<PredicateClause>
+{
+    {
+        let mut pcs = pcs;
+       pcs.push(pc);
+       pcs
+    }
+}
+
+#[allow(unused_variables)]
+pub fn __action9<
+    'input,
+>(
+    input: &'input str,
+    (_, __0, _): (usize, Rule, usize),
+    (_, _, _): (usize, &'input str, usize),
+) -> PredicateClause
+{
+    PredicateClause::Rule(__0)
+}
+
+#[allow(unused_variables)]
+pub fn __action10<
+    'input,
+>(
+    input: &'input str,
+    (_, __0, _): (usize, Term, usize),
+    (_, _, _): (usize, &'input str, usize),
+) -> PredicateClause
+{
+    PredicateClause::Fact(__0)
+}
+
+#[allow(unused_variables)]
+pub fn __action11<
+    'input,
+>(
+    input: &'input str,
+    (_, c, _): (usize, Term, usize),
+    (_, _, _): (usize, &'input str, usize),
+    (_, h, _): (usize, Term, usize),
+    (_, cs, _): (usize, ::std::vec::Vec<Term>, usize),
+) -> Rule
+{
+    Rule { head: (c, h), clauses: cs }
+}
+
+#[allow(unused_variables)]
+pub fn __action12<
+    'input,
+>(
+    input: &'input str,
+    (_, a, _): (usize, Atom, usize),
+    (_, _, _): (usize, &'input str, usize),
+    (_, h, _): (usize, Term, usize),
+    (_, cs, _): (usize, ::std::vec::Vec<Term>, usize),
+) -> Rule
+{
+    Rule { head: (Term::Atom(Cell::new(RegType::Temp(0)), a), h),
+               clauses: cs }
+}
+
+#[allow(unused_variables)]
+pub fn __action13<
+    'input,
+>(
+    input: &'input str,
+    (_, __0, _): (usize, Term, usize),
+) -> Term
+{
+    __0
+}
+
+#[allow(unused_variables)]
+pub fn __action14<
+    'input,
+>(
+    input: &'input str,
+    (_, __0, _): (usize, Atom, usize),
+) -> Term
+{
+    Term::Atom(Cell::new(RegType::Temp(0)), __0)
+}
+
+#[allow(unused_variables)]
+pub fn __action15<
+    'input,
+>(
+    input: &'input str,
+    (_, __0, _): (usize, Var, usize),
+) -> Term
+{
+    Term::Var(Cell::new(VarReg::Norm(RegType::Temp(0))), __0)
+}
+
+#[allow(unused_variables)]
+pub fn __action16<
+    'input,
+>(
+    input: &'input str,
+    (_, __0, _): (usize, &'input str, usize),
+) -> Var
+{
+    __0.trim().to_string()
+}
+
+#[allow(unused_variables)]
+pub fn __action17<
+    'input,
+>(
+    input: &'input str,
+    __lookbehind: &usize,
+    __lookahead: &usize,
+) -> ::std::vec::Vec<Term>
+{
+    vec![]
+}
+
+#[allow(unused_variables)]
+pub fn __action18<
+    'input,
+>(
+    input: &'input str,
+    (_, v, _): (usize, ::std::vec::Vec<Term>, usize),
+) -> ::std::vec::Vec<Term>
+{
+    v
+}
+
+#[allow(unused_variables)]
+pub fn __action19<
+    'input,
+>(
+    input: &'input str,
+    (_, _, _): (usize, &'input str, usize),
+    (_, __0, _): (usize, Term, usize),
+) -> Term
+{
+    (__0)
+}
+
+#[allow(unused_variables)]
+pub fn __action20<
+    'input,
+>(
+    input: &'input str,
+    (_, __0, _): (usize, PredicateClause, usize),
+) -> ::std::vec::Vec<PredicateClause>
+{
+    vec![__0]
+}
+
+#[allow(unused_variables)]
+pub fn __action21<
+    'input,
+>(
+    input: &'input str,
+    (_, v, _): (usize, ::std::vec::Vec<PredicateClause>, usize),
+    (_, e, _): (usize, PredicateClause, usize),
+) -> ::std::vec::Vec<PredicateClause>
+{
+    { let mut v = v; v.push(e); v }
+}
+
+#[allow(unused_variables)]
+pub fn __action22<
+    'input,
+>(
+    input: &'input str,
+    (_, __0, _): (usize, PredicateClause, usize),
+) -> PredicateClause
+{
+    (__0)
+}
+
+#[allow(unused_variables)]
+pub fn __action23<
+    'input,
+>(
+    input: &'input str,
+    __lookbehind: &usize,
+    __lookahead: &usize,
+) -> ::std::vec::Vec<Box<Term>>
+{
+    vec![]
+}
+
+#[allow(unused_variables)]
+pub fn __action24<
+    'input,
+>(
+    input: &'input str,
+    (_, v, _): (usize, ::std::vec::Vec<Box<Term>>, usize),
+) -> ::std::vec::Vec<Box<Term>>
+{
+    v
+}
+
+#[allow(unused_variables)]
+pub fn __action25<
+    'input,
+>(
+    input: &'input str,
+    (_, __0, _): (usize, Box<Term>, usize),
+    (_, _, _): (usize, &'input str, usize),
+) -> Box<Term>
+{
+    (__0)
+}
+
+#[allow(unused_variables)]
+pub fn __action26<
+    'input,
+>(
+    input: &'input str,
+    (_, __0, _): (usize, Box<Term>, usize),
+) -> ::std::vec::Vec<Box<Term>>
+{
+    vec![__0]
+}
+
+#[allow(unused_variables)]
+pub fn __action27<
+    'input,
+>(
+    input: &'input str,
+    (_, v, _): (usize, ::std::vec::Vec<Box<Term>>, usize),
+    (_, e, _): (usize, Box<Term>, usize),
+) -> ::std::vec::Vec<Box<Term>>
+{
+    { let mut v = v; v.push(e); v }
+}
+
+#[allow(unused_variables)]
+pub fn __action28<
+    'input,
+>(
+    input: &'input str,
+    (_, __0, _): (usize, Term, usize),
+) -> ::std::vec::Vec<Term>
+{
+    vec![__0]
+}
+
+#[allow(unused_variables)]
+pub fn __action29<
+    'input,
+>(
+    input: &'input str,
+    (_, v, _): (usize, ::std::vec::Vec<Term>, usize),
+    (_, e, _): (usize, Term, usize),
+) -> ::std::vec::Vec<Term>
+{
+    { let mut v = v; v.push(e); v }
+}
+
+#[allow(unused_variables)]
+pub fn __action30<
+    'input,
+>(
+    input: &'input str,
+    __0: (usize, &'input str, usize),
+    __1: (usize, Term, usize),
+) -> ::std::vec::Vec<Term>
+{
+    let __start0 = __0.0.clone();
+    let __end0 = __1.2.clone();
+    let __temp0 = __action19(
+        input,
+        __0,
+        __1,
+    );
+    let __temp0 = (__start0, __temp0, __end0);
+    __action28(
+        input,
+        __temp0,
+    )
+}
+
+#[allow(unused_variables)]
+pub fn __action31<
+    'input,
+>(
+    input: &'input str,
+    __0: (usize, ::std::vec::Vec<Term>, usize),
+    __1: (usize, &'input str, usize),
+    __2: (usize, Term, usize),
+) -> ::std::vec::Vec<Term>
+{
+    let __start0 = __1.0.clone();
+    let __end0 = __2.2.clone();
+    let __temp0 = __action19(
+        input,
+        __1,
+        __2,
+    );
+    let __temp0 = (__start0, __temp0, __end0);
+    __action29(
+        input,
+        __0,
+        __temp0,
+    )
+}
+
+#[allow(unused_variables)]
+pub fn __action32<
+    'input,
+>(
+    input: &'input str,
+    __0: (usize, Term, usize),
+    __1: (usize, &'input str, usize),
+    __2: (usize, Term, usize),
+) -> Rule
+{
+    let __start0 = __2.2.clone();
+    let __end0 = __2.2.clone();
+    let __temp0 = __action17(
+        input,
+        &__start0,
+        &__end0,
+    );
+    let __temp0 = (__start0, __temp0, __end0);
+    __action11(
+        input,
+        __0,
+        __1,
+        __2,
+        __temp0,
+    )
+}
+
+#[allow(unused_variables)]
+pub fn __action33<
+    'input,
+>(
+    input: &'input str,
+    __0: (usize, Term, usize),
+    __1: (usize, &'input str, usize),
+    __2: (usize, Term, usize),
+    __3: (usize, ::std::vec::Vec<Term>, usize),
+) -> Rule
+{
+    let __start0 = __3.0.clone();
+    let __end0 = __3.2.clone();
+    let __temp0 = __action18(
+        input,
+        __3,
+    );
+    let __temp0 = (__start0, __temp0, __end0);
+    __action11(
+        input,
+        __0,
+        __1,
+        __2,
+        __temp0,
+    )
+}
+
+#[allow(unused_variables)]
+pub fn __action34<
+    'input,
+>(
+    input: &'input str,
+    __0: (usize, Atom, usize),
+    __1: (usize, &'input str, usize),
+    __2: (usize, Term, usize),
+) -> Rule
+{
+    let __start0 = __2.2.clone();
+    let __end0 = __2.2.clone();
+    let __temp0 = __action17(
+        input,
+        &__start0,
+        &__end0,
+    );
+    let __temp0 = (__start0, __temp0, __end0);
+    __action12(
+        input,
+        __0,
+        __1,
+        __2,
+        __temp0,
+    )
+}
+
+#[allow(unused_variables)]
+pub fn __action35<
+    'input,
+>(
+    input: &'input str,
+    __0: (usize, Atom, usize),
+    __1: (usize, &'input str, usize),
+    __2: (usize, Term, usize),
+    __3: (usize, ::std::vec::Vec<Term>, usize),
+) -> Rule
+{
+    let __start0 = __3.0.clone();
+    let __end0 = __3.2.clone();
+    let __temp0 = __action18(
+        input,
+        __3,
+    );
+    let __temp0 = (__start0, __temp0, __end0);
+    __action12(
+        input,
+        __0,
+        __1,
+        __2,
+        __temp0,
+    )
+}
+
+#[allow(unused_variables)]
+pub fn __action36<
+    'input,
+>(
+    input: &'input str,
+    __0: (usize, Box<Term>, usize),
+    __1: (usize, &'input str, usize),
+) -> ::std::vec::Vec<Box<Term>>
+{
+    let __start0 = __0.0.clone();
+    let __end0 = __1.2.clone();
+    let __temp0 = __action25(
+        input,
+        __0,
+        __1,
+    );
+    let __temp0 = (__start0, __temp0, __end0);
+    __action26(
+        input,
+        __temp0,
+    )
+}
+
+#[allow(unused_variables)]
+pub fn __action37<
+    'input,
+>(
+    input: &'input str,
+    __0: (usize, ::std::vec::Vec<Box<Term>>, usize),
+    __1: (usize, Box<Term>, usize),
+    __2: (usize, &'input str, usize),
+) -> ::std::vec::Vec<Box<Term>>
+{
+    let __start0 = __1.0.clone();
+    let __end0 = __2.2.clone();
+    let __temp0 = __action25(
+        input,
+        __1,
+        __2,
+    );
+    let __temp0 = (__start0, __temp0, __end0);
+    __action27(
+        input,
+        __0,
+        __temp0,
+    )
+}
+
+#[allow(unused_variables)]
+pub fn __action38<
+    'input,
+>(
+    input: &'input str,
+    __0: (usize, Atom, usize),
+    __1: (usize, &'input str, usize),
+    __2: (usize, Box<Term>, usize),
+    __3: (usize, &'input str, usize),
+) -> Term
+{
+    let __start0 = __1.2.clone();
+    let __end0 = __2.0.clone();
+    let __temp0 = __action23(
+        input,
+        &__start0,
+        &__end0,
+    );
+    let __temp0 = (__start0, __temp0, __end0);
+    __action7(
+        input,
+        __0,
+        __1,
+        __temp0,
+        __2,
+        __3,
+    )
+}
+
+#[allow(unused_variables)]
+pub fn __action39<
+    'input,
+>(
+    input: &'input str,
+    __0: (usize, Atom, usize),
+    __1: (usize, &'input str, usize),
+    __2: (usize, ::std::vec::Vec<Box<Term>>, usize),
+    __3: (usize, Box<Term>, usize),
+    __4: (usize, &'input str, usize),
+) -> Term
+{
+    let __start0 = __2.0.clone();
+    let __end0 = __2.2.clone();
+    let __temp0 = __action24(
+        input,
+        __2,
+    );
+    let __temp0 = (__start0, __temp0, __end0);
+    __action7(
+        input,
+        __0,
+        __1,
+        __temp0,
+        __3,
+        __4,
+    )
+}
+
+#[allow(unused_variables)]
+pub fn __action40<
+    'input,
+>(
+    input: &'input str,
+    __0: (usize, PredicateClause, usize),
+) -> ::std::vec::Vec<PredicateClause>
+{
+    let __start0 = __0.0.clone();
+    let __end0 = __0.2.clone();
+    let __temp0 = __action22(
+        input,
+        __0,
+    );
+    let __temp0 = (__start0, __temp0, __end0);
+    __action20(
+        input,
+        __temp0,
+    )
+}
+
+#[allow(unused_variables)]
+pub fn __action41<
+    'input,
+>(
+    input: &'input str,
+    __0: (usize, ::std::vec::Vec<PredicateClause>, usize),
+    __1: (usize, PredicateClause, usize),
+) -> ::std::vec::Vec<PredicateClause>
+{
+    let __start0 = __1.0.clone();
+    let __end0 = __1.2.clone();
+    let __temp0 = __action22(
+        input,
+        __1,
+    );
+    let __temp0 = (__start0, __temp0, __end0);
+    __action21(
+        input,
+        __0,
+        __temp0,
+    )
+}
+
+pub trait __ToTriple<'input, > {
+    type Error;
+    fn to_triple(value: Self) -> Result<(usize,(usize, &'input str),usize),Self::Error>;
+}
+
+impl<'input, > __ToTriple<'input, > for (usize, (usize, &'input str), usize) {
+    type Error = ();
+    fn to_triple(value: Self) -> Result<(usize,(usize, &'input str),usize),()> {
+        Ok(value)
+    }
+}
+impl<'input, > __ToTriple<'input, > for Result<(usize, (usize, &'input str), usize),()> {
+    type Error = ();
+    fn to_triple(value: Self) -> Result<(usize,(usize, &'input str),usize),()> {
+        value
+    }
+}
diff --git a/src/l3/machine.rs b/src/l3/machine.rs
new file mode 100644 (file)
index 0000000..1d6d25c
--- /dev/null
@@ -0,0 +1,677 @@
+use l3::ast::*;
+use l3::codegen::*;
+use l3::heapview::*;
+use l3::and_stack::*;
+use l3::or_stack::*;
+
+use std::collections::HashMap;
+use std::ops::{Index, IndexMut};
+use std::vec::Vec;
+
+#[derive(Clone, Copy)]
+enum MachineMode {
+    Read,
+    Write
+}
+
+struct MachineState {
+    h: usize,
+    s: usize,
+    p: CodePtr,
+    b: usize,
+    e: usize,
+    num_of_args: usize,
+    cp: CodePtr,
+    fail: bool,
+    heap: Heap,
+    mode: MachineMode,
+    and_stack: AndStack,
+    or_stack: OrStack,
+    registers: Registers,
+    trail: Vec<Ref>,
+    tr: usize,
+    hb: usize
+}
+
+type CodeDir = HashMap<(Atom, usize), usize>;
+
+impl Index<RegType> for MachineState {
+    type Output = Addr;
+
+    fn index(&self, reg: RegType) -> &Self::Output {
+        match reg {
+            RegType::Temp(temp) => &self.registers[temp],
+            RegType::Perm(perm) => {
+                let e = self.e;
+                &self.and_stack[e][perm]
+            }
+        }
+    }
+}
+
+impl IndexMut<RegType> for MachineState {
+    fn index_mut(&mut self, reg: RegType) -> &mut Self::Output {
+        match reg {
+            RegType::Temp(temp) => &mut self.registers[temp],
+            RegType::Perm(perm) => {
+                let e = self.e;
+                &mut self.and_stack[e][perm]
+            }
+        }
+    }
+}
+
+pub struct Machine {
+    ms: MachineState,
+    code: Code,
+    code_dir: CodeDir
+}
+
+impl Machine {
+    pub fn new() -> Self {
+        Machine {
+            ms: MachineState::new(),
+            code: Vec::new(),
+            code_dir: HashMap::new()
+        }
+    }
+
+    pub fn failed(&self) -> bool {
+        self.ms.fail
+    }
+
+    pub fn add_fact(&mut self, fact: &Term, mut code: Code) {
+        let p = self.code.len();
+        let name  = fact.name().clone();
+        let arity = fact.arity();
+
+        self.code.append(&mut code);
+        self.code_dir.insert((name, arity), p);
+    }
+
+    pub fn add_rule(&mut self, rule: &Rule, mut code: Code) {
+        let p = self.code.len();
+        let name  = rule.head.0.name().clone();
+        let arity = rule.head.0.arity();
+
+        self.code.append(&mut code);
+        self.code_dir.insert((name, arity), p);
+    }
+
+    pub fn add_predicate(&mut self, pred: &Vec<PredicateClause>, mut code: Code)
+    {
+        let p = self.code.len();
+        let name  = pred.first().unwrap().name().clone();
+        let arity = pred.first().unwrap().arity();
+
+        self.code.append(&mut code);
+        self.code_dir.insert((name, arity), p);
+    }
+
+    fn execute_instr<'a>(&mut self, instr_src: LineOrCodeOffset<'a>) -> bool
+    {
+        let mut instr = match instr_src {
+            LineOrCodeOffset::Instruction(instr) => instr,
+            LineOrCodeOffset::Offset(p) => &self.code[p]
+        };
+
+        loop {
+            match instr {
+                &Line::Choice(ref choice_instr) =>
+                    self.ms.execute_choice_instr(choice_instr),
+                &Line::Fact(ref fact) => {
+                    for fact_instr in fact {
+                        self.ms.execute_fact_instr(&fact_instr);
+                    }
+                    self.ms.p += 1;
+                },
+                &Line::Query(ref query) => {
+                    for query_instr in query {
+                        self.ms.execute_query_instr(&query_instr);
+                    }
+                    self.ms.p += 1;
+                },
+                &Line::Control(ref control_instr) =>
+                    self.ms.execute_ctrl_instr(&self.code_dir, control_instr),
+            }
+
+            if self.failed() {
+                let p = self.ms
+                            .or_stack
+                            .top()
+                            .map(|fr| fr.bp)
+                            .unwrap_or_default();
+
+                if let CodePtr::TopLevel = p {
+                    return false;
+                } else {
+                    self.ms.fail = false;
+                    self.ms.p = p;
+                }
+            }
+
+            match self.ms.p {
+                CodePtr::DirEntry(p) if p < self.code.len() =>
+                    instr = &self.code[p],
+                _ => break
+            }
+        }
+
+        true
+    }
+
+    pub fn heap_view(&self, var_dir: &HeapVarDict) -> String {
+        let mut result = String::new();
+
+        for (var, addr) in var_dir {
+            let mut arities = Vec::new();
+            let viewer = HeapCellViewer::new(&self.ms.heap,
+                                             &self.ms.and_stack,
+                                             *addr);
+
+            if result != "" {
+                result += "\n\r";
+            }
+
+            result += var.as_str();
+            result += " = ";
+
+            for view in viewer {
+                match arities.pop() {
+                    Some(n) => arities.push(n-1),
+                    None => {}
+                }
+
+                if !(arities.is_empty() || result.ends_with("(")) {
+                    result += ", ";
+                }
+
+                match view {
+                    HeapCellView::Str(arity, ref name) => {
+                        result += name.as_str();
+
+                        if arity > 0 {
+                            arities.push(arity);
+                            result += "(";
+                        }
+                    },
+                    HeapCellView::HeapVar(cell_num) => {
+                        result += "_";
+                        result += cell_num.to_string().as_str();
+                    },
+                    HeapCellView::StackVar(fr, sc) => {
+                        result += "_s_";
+                        result += fr.to_string().as_str();
+                        result += "_";
+                        result += sc.to_string().as_str();
+                    }
+                }
+
+                while let Some(&0) = arities.last() {
+                    result += ")";
+                    arities.pop();
+                }
+            }
+        }
+
+        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, vr) in cg.vars() {
+                let addr = self.ms.registers[vr.root_register()];
+                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() {
+            let b = self.ms.b;
+            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
+        }
+    }
+
+    pub fn reset(&mut self) {
+        self.ms.reset();
+    }
+}
+
+impl MachineState {
+    fn new() -> MachineState {
+        MachineState { h: 0,
+                       s: 0,
+                       p: CodePtr::TopLevel,
+                       b: 0,
+                       e: 0,
+                       num_of_args: 0,
+                       cp: CodePtr::TopLevel,
+                       fail: false,
+                       heap: Vec::with_capacity(256),
+                       mode: MachineMode::Write,
+                       and_stack: AndStack::new(),
+                       or_stack: OrStack::new(),
+                       registers: vec![Addr::HeapCell(0); 32],
+                       trail: Vec::new(),
+                       tr: 0,
+                       hb: 0
+        }
+    }
+
+    fn num_frames(&self) -> usize {
+        self.and_stack.len() + self.or_stack.len()
+    }
+
+    fn store(&self, a: Addr) -> Addr {
+        match a {
+            Addr::HeapCell(r)       => self.heap[r].as_addr(r),
+            Addr::StackCell(fr, sc) => self.and_stack[fr][sc],
+            addr                    => addr
+        }
+    }
+
+    fn deref(&self, a: Addr) -> Addr {
+        let mut a = a;
+
+        loop {
+            let value = self.store(a);
+
+            if value.is_ref() && value != a {
+                a = value;
+                continue;
+            }
+
+            return a;
+        };
+    }
+
+    fn bind(&mut self, r1: Ref, a2: Addr) {
+        let t2 = self.store(a2);
+
+        match r1 {
+            Ref::StackCell(fr, sc) =>
+                self.and_stack[fr][sc] = t2,
+            Ref::HeapCell(hc) =>
+                self.heap[hc] = HeapCellValue::from(t2)
+        };
+
+        self.trail(r1);
+    }
+
+    fn unify(&mut self, a1: Addr, a2: Addr) {
+        let mut pdl = vec![a1, a2];
+
+        self.fail = false;
+
+        while !(pdl.is_empty() || self.fail) {
+            let d1 = self.deref(pdl.pop().unwrap());
+            let d2 = self.deref(pdl.pop().unwrap());
+
+            if d1 != d2 {
+                match (self.store(d1), self.store(d2)) {
+                    (Addr::HeapCell(hc), _) =>
+                        self.bind(Ref::HeapCell(hc), d2),
+                    (_, Addr::HeapCell(hc)) =>
+                        self.bind(Ref::HeapCell(hc), d1),
+                    (Addr::StackCell(fr, sc), _) =>
+                        self.bind(Ref::StackCell(fr, sc), d2),
+                    (_, Addr::StackCell(fr, sc)) =>
+                        self.bind(Ref::StackCell(fr, sc), d1),
+                    (Addr::Str(a1), Addr::Str(a2)) => {
+                        let r1 = &self.heap[a1];
+                        let r2 = &self.heap[a2];
+
+                        if let &HeapCellValue::NamedStr(n1, ref f1) = r1 {
+                            if let &HeapCellValue::NamedStr(n2, ref f2) = r2 {
+                                if n1 == n2 && *f1 == *f2 {
+                                    for i in 1 .. n1 + 1 {
+                                        pdl.push(Addr::HeapCell(a1 + i));
+                                        pdl.push(Addr::HeapCell(a2 + i));
+                                    }
+
+                                    continue;
+                                }
+                            }
+                        }
+
+                        self.fail = true;
+                    }
+                };
+            }
+        }
+    }
+
+    fn trail(&mut self, r: Ref) {
+        match r {
+            Ref::HeapCell(hc) => {
+                if hc < self.hb {
+                    self.trail.push(r);
+                    self.tr += 1;
+                }
+            },
+            Ref::StackCell(fr, _) => {
+                let fr_gi = self.and_stack[fr].global_index;
+                let b_gi  = if !self.or_stack.is_empty() {
+                    self.or_stack[self.b].global_index
+                } else {
+                    0
+                };
+
+                if fr_gi < b_gi {
+                    self.trail.push(r);
+                    self.tr += 1;
+                }
+            }
+        }
+    }
+
+    fn unwind_trail(&mut self, a1: usize, a2: usize) {
+        for i in a1 .. a2 {
+            match self.trail[i] {
+                Ref::HeapCell(r) =>
+                    self.heap[r] = HeapCellValue::Ref(self.trail[i]),
+                Ref::StackCell(fr, sc) =>
+                    self.and_stack[fr][sc] = Addr::StackCell(fr, sc)
+            }
+        }
+    }
+
+    fn execute_query_instr(&mut self, instr: &QueryInstruction) {
+        match instr {
+            &QueryInstruction::PutStructure(_, ref name, arity, reg) => {
+                self.heap.push(HeapCellValue::Str(self.h + 1));
+                self.heap.push(HeapCellValue::NamedStr(arity, name.clone()));
+
+                self[reg] = Addr::Str(self.h + 1);
+
+                self.h += 2;
+            },
+            &QueryInstruction::PutValue(norm, arg) =>
+                self.registers[arg] = self[norm],
+            &QueryInstruction::PutVariable(norm, arg) => {
+                self.heap.push(HeapCellValue::Ref(Ref::HeapCell(self.h)));
+
+                self[norm] = Addr::HeapCell(self.h);
+                self.registers[arg] = Addr::HeapCell(self.h);
+
+                self.h += 1;
+            },
+            &QueryInstruction::SetVariable(reg) => {
+                self.heap.push(HeapCellValue::Ref(Ref::HeapCell(self.h)));
+                self[reg] = Addr::HeapCell(self.h);
+
+                self.h += 1;
+            },
+            &QueryInstruction::SetValue(reg) => {
+                let heap_val = self[reg];
+                self.heap.push(HeapCellValue::from(heap_val));
+
+                self.h += 1;
+            },
+        }
+    }
+
+    fn execute_fact_instr(&mut self, instr: &FactInstruction) {
+        match instr {
+            &FactInstruction::GetStructure(_, ref name, arity, reg) => {
+                let addr = self.deref(self[reg]);
+
+                match self.store(addr) {
+                    Addr::Str(a) => {
+                        let result = &self.heap[a];
+
+                        if let &HeapCellValue::NamedStr(narity, ref str) = result {
+                            if narity == arity && *name == *str {
+                                self.s = a + 1;
+                                self.mode = MachineMode::Read;
+                            } else {
+                                self.fail = true;
+                            }
+                        }
+                    },
+                    Addr::HeapCell(_) | Addr::StackCell(_, _) => {
+                        self.heap.push(HeapCellValue::Str(self.h + 1));
+                        self.heap.push(HeapCellValue::NamedStr(arity, name.clone()));
+
+                        let h = self.h;
+
+                        self.bind(addr.as_ref().unwrap(), Addr::HeapCell(h));
+
+                        self.h += 2;
+                        self.mode = MachineMode::Write;
+                    }
+                };
+            },
+            &FactInstruction::GetVariable(norm, arg) =>
+                self[norm] = self.registers[arg],
+            &FactInstruction::GetValue(norm, arg) => {
+                let norm_addr = self[norm];
+                let reg_addr  = self.registers[arg];
+
+                self.unify(norm_addr, reg_addr);
+            },
+            &FactInstruction::UnifyVariable(reg) => {
+                match self.mode {
+                    MachineMode::Read  =>
+                        self[reg] = self.heap[self.s].as_addr(self.s),
+                    MachineMode::Write => {
+                        self.heap.push(HeapCellValue::Ref(Ref::HeapCell(self.h)));
+                        self[reg] = Addr::HeapCell(self.h);
+                        self.h += 1;
+                    }
+                };
+
+                self.s += 1;
+            },
+            &FactInstruction::UnifyValue(reg) => {
+                let s = self.s;
+
+                match self.mode {
+                    MachineMode::Read  => {
+                        let reg_addr = self[reg];
+                        self.unify(reg_addr, Addr::HeapCell(s));
+                    },
+                    MachineMode::Write => {
+                        let heap_val = self.store(self[reg]);
+                        self.heap.push(HeapCellValue::from(heap_val));
+                        self.h += 1;
+                    }
+                };
+
+                self.s += 1;
+            }
+        };
+    }
+
+    fn execute_ctrl_instr(&mut self, code_dir: &CodeDir, instr: &ControlInstruction)
+    {
+        match instr {
+            &ControlInstruction::Allocate(num_cells) => {
+                let num_frames = self.num_frames();
+
+                self.and_stack.push(num_frames + 1, self.e, self.cp, num_cells);
+
+                self.e = self.and_stack.len() - 1;
+                self.p += 1;
+            },
+            &ControlInstruction::Call(ref name, arity) => {
+                let compiled_tl_index = code_dir.get(&(name.clone(), arity))
+                                                .map(|index| *index);
+
+                match compiled_tl_index {
+                    Some(compiled_tl_index) => {
+                        self.cp = self.p + 1;
+                        self.num_of_args = arity;
+                        self.p  = CodePtr::DirEntry(compiled_tl_index);
+                    },
+                    None => self.fail = true
+                };
+            },
+            &ControlInstruction::Deallocate => {
+                let e = self.e;
+
+                let num_frame_e = self.and_stack.top().unwrap().global_index;
+                let num_frame_b = self.or_stack
+                                      .top()
+                                      .map(|fr| fr.global_index)
+                                      .unwrap_or(0);
+
+                self.p = self.and_stack[e].cp;
+                self.e = self.and_stack[e].e;
+
+                if num_frame_e > num_frame_b {
+                    let top_e = self.and_stack.top().unwrap().e;
+                    self.and_stack.drop_frames(top_e - self.e + 1);
+                }
+            },
+            &ControlInstruction::Proceed =>
+                self.p = self.cp,
+        };
+    }
+
+    fn execute_choice_instr(&mut self, instr: &ChoiceInstruction)
+    {
+        match instr {
+            &ChoiceInstruction::TryMeElse(offset) => {
+                let n = self.num_of_args;
+                let num_frames = self.num_frames();
+
+                self.or_stack.push(num_frames + 1,
+                                   self.e,
+                                   self.cp,
+                                   self.b,
+                                   self.p + offset,
+                                   self.tr,
+                                   self.h,
+                                   self.num_of_args);
+
+                self.b = self.or_stack.len() - 1;
+                let b = self.b;
+
+                for i in 1 .. n + 1 {
+                    self.or_stack[b][i] = self.registers[i];
+                }
+
+                self.hb = self.h;
+                self.p += 1;
+            },
+            &ChoiceInstruction::RetryMeElse(offset) => {
+                let b = self.b;
+                let n = self.or_stack[b].num_args();
+
+                for i in 1 .. n + 1 {
+                    self.registers[i] = self.or_stack[b][i];
+                }
+
+                self.e = self.or_stack[b].e;
+                self.cp = self.or_stack[b].cp;
+
+                self.or_stack[b].bp = self.p + offset;
+
+                let old_tr  = self.or_stack[b].tr;
+                let curr_tr = self.tr;
+
+                self.unwind_trail(old_tr, curr_tr);
+                self.tr = self.or_stack[b].tr;
+
+                self.trail.truncate(self.tr);
+                self.heap.truncate(self.or_stack[b].h);
+
+                self.h  = self.or_stack[b].h;
+                self.hb = self.h;
+
+                self.p += 1;
+            },
+            &ChoiceInstruction::TrustMe => {
+                let b = self.b;
+                let n = self.or_stack[b].num_args();
+
+                for i in 1 .. n + 1 {
+                    self.registers[i] = self.or_stack[b][i];
+                }
+
+                self.e  = self.or_stack[b].e;
+                self.cp = self.or_stack[b].cp;
+
+                let old_tr  = self.or_stack[b].tr;
+                let curr_tr = self.tr;
+
+                self.unwind_trail(old_tr, curr_tr);
+
+                self.tr = self.or_stack[b].tr;
+                self.trail.truncate(self.tr);
+
+                self.h = self.or_stack[b].h;
+                self.heap.truncate(self.h);
+
+                self.b = self.or_stack[b].b;
+
+                self.or_stack.pop();
+
+                self.hb = self.h;
+                self.p += 1;
+            }
+        }
+    }
+
+    fn reset(&mut self) {
+        self.h = 0;
+        self.hb = 0;
+        self.e = 0;
+        self.b = 0;
+        self.s = 0;
+        self.tr = 0;
+        self.p = CodePtr::TopLevel;
+        self.cp = CodePtr::TopLevel;
+        self.num_of_args = 0;
+
+        self.fail = false;
+        self.trail.clear();
+        self.heap.clear();
+        self.mode = MachineMode::Write;
+        self.and_stack.clear();
+        self.or_stack.clear();
+        self.registers = vec![Addr::HeapCell(0); 32];
+    }
+}
diff --git a/src/l3/mod.rs b/src/l3/mod.rs
new file mode 100644 (file)
index 0000000..8cdc461
--- /dev/null
@@ -0,0 +1,9 @@
+pub mod and_stack;
+pub mod ast;
+pub mod codegen;
+pub mod heapview;
+pub mod io;
+pub mod iterators;
+pub mod l3_parser;
+pub mod machine;
+pub mod or_stack;
diff --git a/src/l3/or_stack.rs b/src/l3/or_stack.rs
new file mode 100644 (file)
index 0000000..19eb0ad
--- /dev/null
@@ -0,0 +1,112 @@
+use l3::ast::*;
+
+use std::ops::{Index, IndexMut};
+use std::vec::Vec;
+
+pub struct Frame {
+    pub global_index: usize,
+    pub e: usize,
+    pub cp: CodePtr,
+    pub b: usize,
+    pub bp: CodePtr,
+    pub tr: usize,
+    pub h: usize,
+    args: Vec<Addr>
+}
+
+impl Frame {
+    fn new(global_index: usize,
+           e: usize,
+           cp: CodePtr,
+           b: usize,
+           bp: CodePtr,
+           tr: usize,
+           h: usize,
+           n: usize)
+           -> Self
+    {
+        Frame {
+            global_index: global_index,
+            e: e,
+            cp: cp,
+            b: b,
+            bp: bp,
+            tr: tr,
+            h: h,
+            args: vec![Addr::HeapCell(0); n]
+        }
+    }
+
+    pub fn num_args(&self) -> usize {
+        self.args.len()
+    }
+}
+
+pub struct OrStack(Vec<Frame>);
+
+impl OrStack {
+    pub fn new() -> Self {
+        OrStack(Vec::new())
+    }
+
+    pub fn push(&mut self,
+                global_index: usize,
+                e: usize,
+                cp: CodePtr,
+                b: usize,
+                bp: CodePtr,
+                tr: usize,
+                h: usize,
+                n: usize)
+    {
+        self.0.push(Frame::new(global_index, e, cp, b, bp, tr, h, n));
+    }
+
+    pub fn len(&self) -> usize {
+        self.0.len()
+    }
+
+    pub fn clear(&mut self) {
+        self.0.clear()
+    }
+
+    pub fn top(&self) -> Option<&Frame> {
+        self.0.last()
+    }
+
+    pub fn pop(&mut self) {
+        self.0.pop();
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.0.is_empty()
+    }
+}
+
+impl Index<usize> for OrStack {
+    type Output = Frame;
+
+    fn index(&self, index: usize) -> &Self::Output {
+        self.0.index(index)
+    }
+}
+
+impl IndexMut<usize> for OrStack {
+    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+        self.0.index_mut(index)
+    }
+}
+
+impl Index<usize> for Frame {
+    type Output = Addr;
+
+    fn index(&self, index: usize) -> &Self::Output {
+        self.args.index(index - 1)
+    }
+}
+
+impl IndexMut<usize> for Frame {
+    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+        self.args.index_mut(index - 1)
+    }
+}
index f1d55bbd0f60aff1955cf6cce2e09a675b737830..8cbe432f36093a9fbfe0f517ad5e5b98cca352f2 100644 (file)
-mod l2;
-
-use l2::ast::*;
-use l2::codegen::*;
-use l2::machine::*;
-
-use std::io::{self, Write};
-
-fn submit(wam: &mut Machine, buffer: String) -> bool {
-    let result = l2::l2_parser::parse_TopLevel(&*buffer);
-
-    let mut cg = CodeGenerator::new();
-
-    match &result {
-        &Ok(TopLevel::Fact(ref fact)) => {
-            let compiled_fact = cg.compile_fact(&fact);
-            wam.add_fact(fact, compiled_fact);
-        },
-        &Ok(TopLevel::Rule(ref rule)) => {
-            let compiled_rule = cg.compile_rule(&rule);
-            wam.add_rule(rule, compiled_rule);
-        },
-        &Ok(TopLevel::Query(ref query)) => {
-            let compiled_query = cg.compile_query(&query);
-            let output = wam.run_query(compiled_query, &cg);
-
-            match output {
-                Some(result) => {
-                    println!("yes");
-
-                    if result != "" {
-                        println!("{}", result);
-                    }
-                },
-                None => println!("no")
-            }
-        },
-        &Err(_) => println!("Grammatical error of some kind!"),
-    };
-
-    let result = wam.failed();
-    wam.reset();
-    result
-}
+extern crate termion;
+mod l3;
+
+use l3::io::*;
+use l3::machine::*;
 
 #[cfg(test)]
 mod tests {
     use super::*;
-
-    #[inline]
-    fn submit_ss(wam: &mut Machine, buffer: &'static str) -> bool {
-        submit(wam, String::from(buffer))
+    use l3::ast::*;
+    
+    fn submit(wam: &mut Machine, buffer: &str) -> EvalResult {
+        let result = eval(wam, buffer);
+        wam.reset();
+        result
     }
-
+    
     #[test]
     fn test_queries_on_facts() {
         let mut wam = Machine::new();
 
-        submit_ss(&mut wam, "p(Z, Z).");
-        submit_ss(&mut wam, "clouds(are, nice).");
+        submit(&mut wam, "p(Z, Z).");
+        submit(&mut wam, "clouds(are, nice).");
 
-        // submit_ss returns true on failure, false on success.
-        assert_eq!(submit_ss(&mut wam, "?- p(Z, Z)."), false);
-        assert_eq!(submit_ss(&mut wam, "?- p(Z, z)."), false);
-        assert_eq!(submit_ss(&mut wam, "?- p(Z, w)."), false);
-        assert_eq!(submit_ss(&mut wam, "?- p(z, w)."), true);
-        assert_eq!(submit_ss(&mut wam, "?- p(w, w)."), false);
-        assert_eq!(submit_ss(&mut wam, "?- clouds(Z, Z)."), true);
-        assert_eq!(submit_ss(&mut wam, "?- clouds(are, Z)."), false);
-        assert_eq!(submit_ss(&mut wam, "?- clouds(Z, nice)."), false);
+        // 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_ss(&mut wam, "?- p(Z, h(Z, W), f(W))."), true);
+        assert_eq!(submit(&mut wam, "?- p(Z, h(Z, W), f(W)).").failed_query(), true);
 
-        submit_ss(&mut wam, "p(Z, h(Z, W), f(W)).");
+        submit(&mut wam, "p(Z, h(Z, W), f(W)).");
 
-        assert_eq!(submit_ss(&mut wam, "?- p(z, h(z, z), f(w))."), true);
-        assert_eq!(submit_ss(&mut wam, "?- p(z, h(z, w), f(w))."), false);
-        assert_eq!(submit_ss(&mut wam, "?- p(z, h(z, W), f(w))."), false);
-        assert_eq!(submit_ss(&mut wam, "?- p(Z, h(Z, w), f(Z))."), false);
-        assert_eq!(submit_ss(&mut wam, "?- p(z, h(Z, w), f(Z))."), true);
+        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);
 
-        submit_ss(&mut wam, "p(f(X), h(Y, f(a)), Y).");
+        submit(&mut wam, "p(f(X), h(Y, f(a)), Y).");
 
-        assert_eq!(submit_ss(&mut wam, "?- p(Z, h(Z, W), f(W))."), false);
+        assert_eq!(submit(&mut wam, "?- p(Z, h(Z, W), f(W)).").failed_query(), false);
     }
 
     #[test]
     fn test_queries_on_rules() {
         let mut wam = Machine::new();
 
-        submit_ss(&mut wam, "p(X, Y) :- q(X, Z), r(Z, Y).");
-        submit_ss(&mut wam, "q(q, s).");
-        submit_ss(&mut wam, "r(s, t).");
+        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_ss(&mut wam, "?- p(X, Y)."), false);
-        assert_eq!(submit_ss(&mut wam, "?- p(q, t)."), false);
-        assert_eq!(submit_ss(&mut wam, "?- p(t, q)."), true);
-        assert_eq!(submit_ss(&mut wam, "?- p(q, T)."), false);
-        assert_eq!(submit_ss(&mut wam, "?- p(Q, t)."), false);
-        assert_eq!(submit_ss(&mut wam, "?- p(t, t)."), true);
+        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);
 
-        submit_ss(&mut wam, "p(X, Y) :- q(f(f(X)), R), r(S, T).");
-        submit_ss(&mut wam, "q(f(f(X)), r).");
+        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_ss(&mut wam, "?- p(X, Y)."), false);
+        assert_eq!(submit(&mut wam, "?- p(X, Y).").failed_query(), false);
 
-        submit_ss(&mut wam, "q(f(f(x)), r).");
+        submit(&mut wam, "q(f(f(x)), r).");
 
-        assert_eq!(submit_ss(&mut wam, "?- p(X, Y)."), false);
+        assert_eq!(submit(&mut wam, "?- p(X, Y).").failed_query(), false);
 
-        submit_ss(&mut wam, "p(X, Y) :- q(X, Y), r(X, Y).");
-        submit_ss(&mut wam, "q(s, t).");
-        submit_ss(&mut wam, "r(X, Y) :- r(a).");
-        submit_ss(&mut wam, "r(a).");
+        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_ss(&mut wam, "?- p(X, Y)."), false);
-        assert_eq!(submit_ss(&mut wam, "?- p(t, S)."), true);
-        assert_eq!(submit_ss(&mut wam, "?- p(t, s)."), true);
-        assert_eq!(submit_ss(&mut wam, "?- p(s, T)."), false);
-        assert_eq!(submit_ss(&mut wam, "?- p(S, t)."), false);
+        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);
 
-        submit_ss(&mut wam, "p(f(f(a), g(b), X), g(b), h) :- q(X, Y).");
-        submit_ss(&mut wam, "q(X, Y).");
+        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_ss(&mut wam, "?- p(f(X, Y, Z), g(b), h)."), false);
-        assert_eq!(submit_ss(&mut wam, "?- p(f(X, g(Y), Z), g(Z), X)."), true);
-        assert_eq!(submit_ss(&mut wam, "?- p(f(X, g(Y), Z), g(Z), h)."), false);
-        assert_eq!(submit_ss(&mut wam, "?- p(Z, Y, X)."), false);
-        assert_eq!(submit_ss(&mut wam, "?- p(f(X, Y, Z), Y, h)."), false);
+        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);
+    }
+
+    #[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).").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);
+
+        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);
+        
+        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);
+
+        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);
+
+        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);
+
+        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);
+
+        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).").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);
+
+        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).").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);
+
+        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).").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);
     }
 }
 
-fn l2_repl() {
+fn l3_repl() {
     let mut wam = Machine::new();
-
+        
     loop {
-        print!("l2> ");
-
-        let _ = io::stdout().flush();
-        let mut buffer = String::new();
+        print!("l3> ");
 
-        io::stdin().read_line(&mut buffer).unwrap();
+        let buffer = read();
 
-        if &*buffer == "quit\n" {
+        if buffer == "quit\n" {
             break;
-        } else if &*buffer == "clear\n" {
+        } else if buffer == "clear\n" {
             wam = Machine::new();
             continue;
         }
 
-        submit(&mut wam, buffer);
+        let result = eval(&mut wam, buffer.trim());
+        print(&mut wam, result);
+        
+        wam.reset();
     }
 }
 
 fn main() {
-    l2_repl();
+    l3_repl();
 }