]> Repositorios git - scryer-prolog.git/commitdiff
major refactor.
authorMark Thom <[email protected]>
Sun, 25 Feb 2018 19:13:07 +0000 (12:13 -0700)
committerMark Thom <[email protected]>
Sun, 25 Feb 2018 19:13:07 +0000 (12:13 -0700)
20 files changed:
Cargo.lock
Cargo.toml
src/prolog/arithmetic.rs
src/prolog/ast.rs
src/prolog/builtins.rs
src/prolog/codegen.rs
src/prolog/debray_allocator.rs
src/prolog/fixtures.rs
src/prolog/heap_print.rs
src/prolog/indexing.rs
src/prolog/io.rs
src/prolog/iterators.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/mod.rs
src/prolog/macros.rs
src/prolog/parser
src/prolog/tabled_rc.rs
src/prolog/targets.rs
src/tests.rs

index 27072053033c2eea1a58270959fd665bee49078e..2083ddcf371246c1e83f55c7e4cc9764fa222f58 100644 (file)
@@ -176,7 +176,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "rusty-wam"
-version = "0.7.5"
+version = "0.7.6"
 dependencies = [
  "downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
index b29cd2302f3ca10b0568d1c3212aa95fb39159ca..bf3be3bc579161c60144925d0a4d04f08cf47e8a 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "rusty-wam"
-version = "0.7.5"
+version = "0.7.6"
 authors = ["Mark Thom"]
 
 [dependencies]
index e7445828943fc724e78eb3f851c5e52368d2bb7a..ce3ce89e6ef60896f87d1fc459826c8dceb668bf 100644 (file)
@@ -13,15 +13,19 @@ pub type ArithCont = (Code, Option<ArithmeticTerm>);
 
 impl<'a> ArithInstructionIterator<'a> {
     fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
-        self.state_stack.push(TermIterState::to_state(lvl, term));
+        self.state_stack.push(TermIterState::subterm_to_state(lvl, term));
     }
 
     fn new(term: &'a Term) -> Result<Self, ArithmeticError> {
         let state = match term {
             &Term::AnonVar =>
                 return Err(ArithmeticError::InvalidTerm),
-            &Term::Clause(_, ref name, ref terms, _) =>
-                TermIterState::Clause(0, ClauseType::Root(name), terms),
+            &Term::Clause(ref cell, ref name, ref terms, fixity) =>
+                match ClauseType::from(name.clone(), terms.len(), fixity) {
+                    ct @ ClauseType::Named(..) | ct @ ClauseType::Op(..) =>
+                        Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms)),
+                    _ => Err(ArithmeticError::InvalidOp)
+                }?,
             &Term::Constant(ref cell, ref cons) =>
                 TermIterState::Constant(Level::Shallow, cell, cons),
             &Term::Cons(_, _, _) =>
@@ -36,7 +40,7 @@ impl<'a> ArithInstructionIterator<'a> {
 
 pub enum ArithTermRef<'a> {
     Constant(&'a Constant),
-    Op(&'a str, usize), // name, arity.
+    Op(ClauseName, usize), // name, arity.
     Var(&'a Cell<VarReg>, &'a Var)
 }
 
@@ -48,14 +52,14 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
             match iter_state {
                 TermIterState::AnonVar(_) =>
                     return Some(Err(ArithmeticError::UninstantiatedVar)),
-                TermIterState::Clause(child_num, ct, child_terms) => {
-                    let arity = child_terms.len();
+                TermIterState::Clause(lvl, child_num, cell, ct, subterms) => {
+                    let arity = subterms.len();                    
 
                     if child_num == arity {
                         return Some(Ok(ArithTermRef::Op(ct.name(), arity)));
                     } else {
-                        self.state_stack.push(TermIterState::Clause(child_num + 1, ct, child_terms));
-                        self.push_subterm(ct.level_of_subterms(), child_terms[child_num].as_ref());
+                        self.state_stack.push(TermIterState::Clause(lvl, child_num + 1, cell, ct, subterms));
+                        self.push_subterm(lvl, subterms[child_num].as_ref());
                     }
                 },
                 TermIterState::Constant(_, _, c) =>
@@ -97,19 +101,19 @@ impl<'a> ArithmeticEvaluator<'a>
         ArithmeticEvaluator { bindings, interm: Vec::new(), interm_c: target_int }
     }
 
-    fn get_unary_instr(name: &str, a1: ArithmeticTerm, t: usize)
+    fn get_unary_instr(name: ClauseName, a1: ArithmeticTerm, t: usize)
                        -> Result<ArithmeticInstruction, ArithmeticError>
     {
-        match name {
+        match name.as_str() {
             "-" => Ok(ArithmeticInstruction::Neg(a1, t)),
              _  => Err(ArithmeticError::InvalidOp)
         }
     }
 
-    fn get_binary_instr(name: &str, a1: ArithmeticTerm, a2: ArithmeticTerm, t: usize)
+    fn get_binary_instr(name: ClauseName, a1: ArithmeticTerm, a2: ArithmeticTerm, t: usize)
                         -> Result<ArithmeticInstruction, ArithmeticError>
     {
-        match name {
+        match name.as_str() {
             "+"    => Ok(ArithmeticInstruction::Add(a1, a2, t)),
             "-"    => Ok(ArithmeticInstruction::Sub(a1, a2, t)),
             "/"    => Ok(ArithmeticInstruction::Div(a1, a2, t)),
@@ -137,7 +141,7 @@ impl<'a> ArithmeticEvaluator<'a>
         temp
     }
 
-    fn instr_from_clause(&mut self, name: &str, arity: usize)
+    fn instr_from_clause(&mut self, name: ClauseName, arity: usize)
                          -> Result<ArithmeticInstruction, ArithmeticError>
     {
         match arity {
@@ -215,7 +219,7 @@ impl<'a> ArithmeticEvaluator<'a>
                     self.interm.push(ArithmeticTerm::Reg(r));
                 },
                 ArithTermRef::Op(name, arity) => {
-                    code.push(Line::Arithmetic(self.instr_from_clause(&*name, arity)?));
+                    code.push(Line::Arithmetic(self.instr_from_clause(name, arity)?));
                 }
             }
         }
index e89dc89b61979e58e05c9caeda5869dd98a7458f..ac52c74b2b166d7bcc949bf6bb7e31d538e28aa6 100644 (file)
@@ -8,6 +8,7 @@ use std::cell::Cell;
 use std::cmp::Ordering;
 use std::collections::{HashMap, VecDeque};
 use std::fmt;
+use std::hash::{Hash, Hasher};
 use std::io::Error as IOError;
 use std::num::{ParseFloatError};
 use std::ops::{Add, AddAssign, Div, Index, IndexMut, Sub, Mul, Neg};
@@ -46,37 +47,27 @@ impl PredicateClause {
     pub fn first_arg(&self) -> Option<&Term> {
         match self {
             &PredicateClause::Fact(ref term) => term.first_arg(),
-            &PredicateClause::Rule(ref rule) =>
-                if let &QueryTerm::Term(ref term) = &rule.head.0 {
-                    term.first_arg()
-                } else {
-                    None
-                }
+            &PredicateClause::Rule(ref rule) => rule.head.1.first().map(|bt| bt.as_ref()),
         }
     }
 
     pub fn arity(&self) -> usize {
         match self {
             &PredicateClause::Fact(ref term) => term.arity(),
-            &PredicateClause::Rule(ref rule) => rule.head.0.arity()
+            &PredicateClause::Rule(ref rule) => rule.head.1.len()
         }
     }
 
-    pub fn name(&self) -> Option<TabledRc<Atom>> {
+    pub fn name(&self) -> Option<ClauseName> {
         match self {
             &PredicateClause::Fact(ref term) => term.name(),
-            &PredicateClause::Rule(ref rule) =>
-                if let &QueryTerm::Term(ref term) = &rule.head.0 {
-                    term.name()
-                } else {
-                    None
-                }
+            &PredicateClause::Rule(ref rule) => Some(rule.head.0.clone()),
         }
     }
 }
 
 pub enum Declaration {
-    Op(usize, Specifier, TabledRc<Atom>)
+    Op(usize, Specifier, ClauseName)
 }
 
 pub enum TopLevel {
@@ -88,7 +79,7 @@ pub enum TopLevel {
 }
 
 impl TopLevel {
-    pub fn name(&self) -> Option<TabledRc<Atom>> {
+    pub fn name(&self) -> Option<ClauseName> {
         match self {
             &TopLevel::Declaration(_) => None,
             &TopLevel::Fact(ref term) => term.name(),
@@ -99,15 +90,8 @@ impl TopLevel {
                     None
                 },
             &TopLevel::Query(_) => None,
-            &TopLevel::Rule(Rule { head: (QueryTerm::Term(ref term), _), .. }) =>
-                match term {
-                    &Term::Clause(_, ref name, ..)
-                  | &Term::Constant(_, Constant::Atom(ref name)) =>
-                        Some(name.clone()),
-                    _ =>
-                        None
-                },
-            _ => None
+            &TopLevel::Rule(Rule { ref head, .. }) =>
+                Some(head.0.clone())
         }
     }
 
@@ -118,14 +102,23 @@ impl TopLevel {
             &TopLevel::Predicate(ref clauses) =>
                 clauses.first().map(|t| t.arity()).unwrap_or(0),
             &TopLevel::Query(_) => 0,
-            &TopLevel::Rule(Rule { head: (ref qt, _), ..}) => qt.arity(),
+            &TopLevel::Rule(Rule { ref head, .. }) => head.1.len()
         }
     }
 }
 
 #[derive(Clone, Copy)]
 pub enum Level {
-    Deep, Shallow
+    Deep, Root, Shallow
+}
+
+impl Level {
+    pub fn child_level(self) -> Level {
+        match self {
+            Level::Root => Level::Shallow,
+            _ => Level::Deep
+        }
+    }
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
@@ -305,7 +298,7 @@ pub enum Fixity {
 
 #[derive(Clone, Eq, Hash, PartialEq)]
 pub enum Constant {
-    Atom(TabledRc<Atom>),
+    Atom(ClauseName),
     Number(Number),
     String(Rc<String>),
     Usize(usize),
@@ -332,36 +325,57 @@ impl fmt::Display for Constant {
 #[derive(PartialEq, Eq, Clone)]
 pub enum Term {
     AnonVar,
-    Clause(Cell<RegType>, TabledRc<Atom>, Vec<Box<Term>>, Option<Fixity>),
+    Clause(Cell<RegType>, ClauseName, Vec<Box<Term>>, Option<Fixity>),
     Cons(Cell<RegType>, Box<Term>, Box<Term>),
     Constant(Cell<RegType>, Constant),
     Var(Cell<VarReg>, Rc<Var>)
 }
 
-pub enum InlinedQueryTerm {
-    CompareNumber(CompareNumberQT, Vec<Box<Term>>),
-    IsAtomic(Vec<Box<Term>>),
-    IsCompound(Vec<Box<Term>>),
-    IsInteger(Vec<Box<Term>>),
-    IsRational(Vec<Box<Term>>),
-    IsString(Vec<Box<Term>>),
-    IsFloat(Vec<Box<Term>>),
-    IsNonVar(Vec<Box<Term>>),
-    IsVar(Vec<Box<Term>>),
-}
-
-impl InlinedQueryTerm {
-    pub fn arity(&self) -> usize {
+#[derive(Clone, Copy)]
+pub enum InlinedClauseType {
+    CompareNumber(CompareNumberQT),
+    IsAtomic,
+    IsCompound,
+    IsInteger,
+    IsRational,
+    IsString,
+    IsFloat,
+    IsNonVar,
+    IsVar,
+}
+
+impl InlinedClauseType {
+    pub fn name(&self) -> &'static str {
         match self {
-            &InlinedQueryTerm::CompareNumber(_, _) => 2,
-            &InlinedQueryTerm::IsAtomic(_) => 1,
-            &InlinedQueryTerm::IsCompound(_) => 1,
-            &InlinedQueryTerm::IsFloat(_) => 1,
-            &InlinedQueryTerm::IsRational(_) => 1,
-            &InlinedQueryTerm::IsString(_) => 1,
-            &InlinedQueryTerm::IsNonVar(_) => 1,
-            &InlinedQueryTerm::IsInteger(_) => 1,
-            &InlinedQueryTerm::IsVar(_) => 1,
+            &InlinedClauseType::CompareNumber(qt) => qt.name(),
+            &InlinedClauseType::IsAtomic => "atomic",
+            &InlinedClauseType::IsCompound => "compound",
+            &InlinedClauseType::IsInteger  => "integer",
+            &InlinedClauseType::IsRational => "rational",
+            &InlinedClauseType::IsString => "string",
+            &InlinedClauseType::IsFloat  => "float",
+            &InlinedClauseType::IsNonVar => "nonvar",
+            &InlinedClauseType::IsVar => "var"
+        }
+    }
+
+    pub fn from(name: &str, arity: usize) -> Option<Self> {
+        match (name, arity) {
+            (">", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThan)),
+            ("<", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThan)),
+            (">=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThanOrEqual)),
+            ("<=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThanOrEqual)),
+            ("=\\=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::NotEqual)),
+            ("=:=", 2) => Some(InlinedClauseType::CompareNumber(CompareNumberQT::Equal)),
+            ("atomic", 1) => Some(InlinedClauseType::IsAtomic),
+            ("compound", 1) => Some(InlinedClauseType::IsCompound),
+            ("integer", 1) => Some(InlinedClauseType::IsInteger),
+            ("rational", 1) => Some(InlinedClauseType::IsRational),
+            ("string", 1) => Some(InlinedClauseType::IsString),
+            ("float", 1) => Some(InlinedClauseType::IsFloat),
+            ("nonvar", 1) => Some(InlinedClauseType::IsNonVar),
+            ("var", 1) => Some(InlinedClauseType::IsVar),
+            _ => None
         }
     }
 }
@@ -377,7 +391,7 @@ pub enum CompareNumberQT {
 }
 
 impl CompareNumberQT {
-    fn name<'a>(self) -> &'a str {
+    fn name(self) -> &'static str {
         match self {
             CompareNumberQT::GreaterThan => ">",
             CompareNumberQT::LessThan => "<",
@@ -390,13 +404,13 @@ impl CompareNumberQT {
 }
 
 #[derive(Clone, Copy)]
-pub enum CompareTermQT {    
+pub enum CompareTermQT {
     LessThan,
     LessThanOrEqual,
     Equal,
     GreaterThanOrEqual,
-    GreaterThan,        
-    NotEqual,    
+    GreaterThan,
+    NotEqual,
 }
 
 impl CompareTermQT {
@@ -417,118 +431,174 @@ impl CompareTermQT {
 pub type JumpStub = Vec<Term>;
 
 pub enum QueryTerm {
-    Arg(Vec<Box<Term>>),
-    CallN(Vec<Box<Term>>),
-    CallWithInferenceLimit(Vec<Box<Term>>),
-    Catch(Vec<Box<Term>>),
-    Compare(Vec<Box<Term>>),
-    CompareTerm(CompareTermQT, Vec<Box<Term>>),
+    Clause(Cell<RegType>, ClauseType, Vec<Box<Term>>),
     Cut,
-    Display(Vec<Box<Term>>),
-    DuplicateTerm(Vec<Box<Term>>),
-    Eq(Vec<Box<Term>>),
-    Functor(Vec<Box<Term>>),
-    Ground(Vec<Box<Term>>),
-    Inlined(InlinedQueryTerm),
-    Is(Vec<Box<Term>>),
-    Jump(JumpStub),
-    NotEq(Vec<Box<Term>>),
-    SetupCallCleanup(Vec<Box<Term>>),
-    Term(Term),
-    Throw(Vec<Box<Term>>)
+    Jump(JumpStub)
 }
 
 impl QueryTerm {
     pub fn arity(&self) -> usize {
         match self {
-            &QueryTerm::Arg(_) => 3,
-            &QueryTerm::Catch(_) => 3,
-            &QueryTerm::Compare(_) => 3,
-            &QueryTerm::CompareTerm(..) => 2,
-            &QueryTerm::Display(_) => 1,
-            &QueryTerm::Throw(_) => 1,
-            &QueryTerm::DuplicateTerm(_) => 2,
-            &QueryTerm::Eq(_) => 2,
-            &QueryTerm::Functor(_) => 3,
-            &QueryTerm::Ground(_) => 1,
-            &QueryTerm::Inlined(ref term) => term.arity(),
-            &QueryTerm::Is(_) => 2,
-            &QueryTerm::Jump(ref vars) => vars.len(),
-            &QueryTerm::NotEq(_) => 2,
-            &QueryTerm::CallN(ref terms) => terms.len(),
-            &QueryTerm::CallWithInferenceLimit(_) => 3,
+            &QueryTerm::Clause(_, _, ref subterms) => subterms.len(),
             &QueryTerm::Cut => 0,
-            &QueryTerm::SetupCallCleanup(_) => 3,
-            &QueryTerm::Term(ref term) => term.arity(),
+            &QueryTerm::Jump(ref vars) => vars.len()
         }
     }
 }
 
 pub struct Rule {
-    pub head: (QueryTerm, QueryTerm),
+    pub head: (ClauseName, Vec<Box<Term>>, QueryTerm),
     pub clauses: Vec<QueryTerm>
 }
 
-#[derive(Clone, Copy)]
-pub enum ClauseType<'a> {
+#[derive(Clone)]
+pub enum ClauseType {
     Arg,
     CallN,
     CallWithInferenceLimit,
     Catch,
     Compare,
-    CompareNumber(CompareNumberQT),
     CompareTerm(CompareTermQT),
-    Deep(Level, &'a Cell<RegType>, &'a TabledRc<Atom>, Option<Fixity>),
     Display,
     DuplicateTerm,
     Eq,
     Functor,
     Ground,
+    Inlined(InlinedClauseType),
     Is,
     NotEq,
-    Root(&'a TabledRc<Atom>),
+    Op(ClauseName, Fixity),
+    Named(ClauseName),
     SetupCallCleanup,
     Throw,
 }
 
-impl<'a> ClauseType<'a> {
-    pub fn name(&self) -> &'a str {
+impl ClauseType {
+    pub fn fixity(&self) -> Option<Fixity> {
+        match self {
+            &ClauseType::Compare | &ClauseType::CompareTerm(_)
+          | &ClauseType::Inlined(InlinedClauseType::CompareNumber(_))
+          | &ClauseType::NotEq | &ClauseType::Is | &ClauseType::Eq => Some(Fixity::In),
+            &ClauseType::Op(_, fixity) => Some(fixity),
+            _ => None
+        }
+    }
+}
+
+#[derive(Clone)]
+pub enum ClauseName {
+    BuiltIn(&'static str),
+    User(TabledRc<Atom>)
+}
+
+impl Hash for ClauseName {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        (*self.as_str()).hash(state)
+    }        
+}
+
+impl PartialEq for ClauseName {
+    fn eq(&self, other: &ClauseName) -> bool {
+        *self.as_str() == *other.as_str()
+    }
+}
+
+impl Eq for ClauseName {}
+
+impl Ord for ClauseName {
+    fn cmp(&self, other: &ClauseName) -> Ordering {
+        (*self.as_str()).cmp(other.as_str())
+    }
+}
+
+impl PartialOrd for ClauseName {
+    fn partial_cmp(&self, other: &ClauseName) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl<'a> From<&'a TabledRc<Atom>> for ClauseName {
+    fn from(name: &'a TabledRc<Atom>) -> ClauseName {
+        ClauseName::User(name.clone())
+    }
+}
+
+impl ClauseName {
+    pub fn as_str(&self) -> &str {
         match self {
-            &ClauseType::Arg => "arg",
-            &ClauseType::CallN => "call",
-            &ClauseType::CallWithInferenceLimit => "call_with_inference_limit",
-            &ClauseType::Catch => "catch",
-            &ClauseType::Compare => "compare",
-            &ClauseType::CompareNumber(qt) => qt.name(),
-            &ClauseType::CompareTerm(qt) => qt.name(),
-            &ClauseType::Display => "display",
-            &ClauseType::Deep(_, _, name, _) => name.as_str(),
-            &ClauseType::DuplicateTerm => "duplicate_term",
-            &ClauseType::Eq => "==",
-            &ClauseType::Functor => "functor",
-            &ClauseType::Ground  => "ground",
-            &ClauseType::Is => "is",
-            &ClauseType::NotEq => "\\==",
-            &ClauseType::Root(name) => name.as_str(),
-            &ClauseType::SetupCallCleanup => "setup_call_cleanup",
-            &ClauseType::Throw => "throw"
+            &ClauseName::BuiltIn(s) => s,
+            &ClauseName::User(ref name) => name.as_ref()
         }
     }
+}
 
-    pub fn level_of_subterms(self) -> Level {
+impl ClauseType {
+    pub fn name(&self) -> ClauseName {
         match self {
-            ClauseType::Deep(..) => Level::Deep,
-            _ => Level::Shallow
+            &ClauseType::Arg => ClauseName::BuiltIn("arg"),
+            &ClauseType::CallN => ClauseName::BuiltIn("call"),
+            &ClauseType::CallWithInferenceLimit => ClauseName::BuiltIn("call_with_inference_limit"),
+            &ClauseType::Catch => ClauseName::BuiltIn("catch"),
+            &ClauseType::Compare => ClauseName::BuiltIn("compare"),
+            &ClauseType::CompareTerm(qt) => ClauseName::BuiltIn(qt.name()),
+            &ClauseType::Display => ClauseName::BuiltIn("display"),
+            &ClauseType::DuplicateTerm => ClauseName::BuiltIn("duplicate_term"),
+            &ClauseType::Eq => ClauseName::BuiltIn("=="),
+            &ClauseType::Functor => ClauseName::BuiltIn("functor"),
+            &ClauseType::Ground  => ClauseName::BuiltIn("ground"),
+            &ClauseType::Inlined(inlined) => ClauseName::BuiltIn(inlined.name()),
+            &ClauseType::Is => ClauseName::BuiltIn("is"),
+            &ClauseType::NotEq => ClauseName::BuiltIn("\\=="),
+            &ClauseType::Op(ref name, _) => name.clone(),
+            &ClauseType::Named(ref name) => name.clone(),
+            &ClauseType::SetupCallCleanup => ClauseName::BuiltIn("setup_call_cleanup"),
+            &ClauseType::Throw => ClauseName::BuiltIn("throw")
+        }
+    }
+
+    pub fn from(name: ClauseName, arity: usize, fixity: Option<Fixity>) -> Self {
+        match (name.as_str(), arity) {
+            ("arg", 3)   => ClauseType::Arg,
+            ("call", _)  => ClauseType::CallN,
+            ("call_with_inference_limit", 3) => ClauseType::CallWithInferenceLimit,
+            ("catch", 3) => ClauseType::Catch,
+            ("compare", 3) => ClauseType::Compare,
+            ("@>", 2) => ClauseType::CompareTerm(CompareTermQT::GreaterThan),
+            ("@<", 2) => ClauseType::CompareTerm(CompareTermQT::LessThan),
+            ("@>=", 2) => ClauseType::CompareTerm(CompareTermQT::GreaterThanOrEqual),
+            ("@<=", 2) => ClauseType::CompareTerm(CompareTermQT::LessThanOrEqual),
+            ("\\=@=", 2) => ClauseType::CompareTerm(CompareTermQT::NotEqual),
+            ("=@=", 2) => ClauseType::CompareTerm(CompareTermQT::Equal),
+            ("display", 1) => ClauseType::Display,
+            ("duplicate_term", 2) => ClauseType::DuplicateTerm,
+            ("==", 2) => ClauseType::Eq,
+            ("functor", 3) => ClauseType::Functor,
+            ("ground", 1) => ClauseType::Ground,
+            ("is", 2) => ClauseType::Is,
+            ("\\==", 2) => ClauseType::NotEq,
+            ("setup_call_cleanup", 3) => ClauseType::SetupCallCleanup,
+            ("throw", 1) => ClauseType::Throw,
+            _ => if let Some(fixity) = fixity {
+                ClauseType::Op(name, fixity)
+            } else {
+                ClauseType::Named(name)
+            }
         }
     }
 }
 
-#[derive(Clone, Copy)]
+impl From<InlinedClauseType> for ClauseType {
+    fn from(inlined_ct: InlinedClauseType) -> Self {
+        ClauseType::Inlined(inlined_ct)
+    }
+}
+
+#[derive(Clone)]
 pub enum TermRef<'a> {
     AnonVar(Level),
     Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
     Constant(Level, &'a Cell<RegType>, &'a Constant),
-    Clause(ClauseType<'a>, &'a Vec<Box<Term>>),
+    Clause(Level, &'a Cell<RegType>, ClauseType, &'a Vec<Box<Term>>),
     Var(Level, &'a Cell<VarReg>, &'a Var)
 }
 
@@ -538,9 +608,8 @@ impl<'a> TermRef<'a> {
             TermRef::AnonVar(lvl)
           | TermRef::Cons(lvl, ..)
           | TermRef::Constant(lvl, ..)
-          | TermRef::Var(lvl, ..) => lvl,
-            TermRef::Clause(ClauseType::Deep(lvl, ..), ..) => lvl,
-            _ => Level::Shallow
+          | TermRef::Var(lvl, ..)
+          | TermRef::Clause(lvl, ..) => lvl
         }
     }
 }
@@ -921,7 +990,7 @@ pub enum ControlInstruction {
     Allocate(usize), // num_frames.
     ArgCall,
     ArgExecute,
-    Call(TabledRc<Atom>, usize, usize), // name, arity, perm_vars after threshold.
+    Call(ClauseName, usize, usize), // name, arity, perm_vars after threshold.
     CallN(usize), // arity.
     CatchCall,
     CatchExecute,
@@ -934,11 +1003,11 @@ pub enum ControlInstruction {
     DisplayExecute,
     Deallocate,
     DuplicateTermCall,
-    DuplicateTermExecute,    
+    DuplicateTermExecute,
     DynamicIs,
     EqCall,
     EqExecute,
-    Execute(TabledRc<Atom>, usize),
+    Execute(ClauseName, usize),
     ExecuteN(usize),
     FunctorCall,
     FunctorExecute,
@@ -949,11 +1018,11 @@ pub enum ControlInstruction {
     GroundExecute,
     JmpByCall(usize, usize),    // arity, global_offset.
     JmpByExecute(usize, usize),
-    IsCall(RegType, ArithmeticTerm),    
+    IsCall(RegType, ArithmeticTerm),
     IsExecute(RegType, ArithmeticTerm),
     NotEqCall,
     NotEqExecute,
-    Proceed,    
+    Proceed,
     ThrowCall,
     ThrowExecute,
 }
@@ -965,7 +1034,7 @@ impl ControlInstruction {
             &ControlInstruction::ArgExecute => true,
             &ControlInstruction::Call(_, _, _)  => true,
             &ControlInstruction::CatchCall => true,
-            &ControlInstruction::CatchExecute => true,            
+            &ControlInstruction::CatchExecute => true,
             &ControlInstruction::CompareTermCall(..) => true,
             &ControlInstruction::CompareTermExecute(..) => true,
             &ControlInstruction::DisplayCall => true,
@@ -1003,7 +1072,7 @@ impl ControlInstruction {
 pub enum IndexingInstruction {
     SwitchOnTerm(usize, usize, usize, usize),
     SwitchOnConstant(usize, HashMap<Constant, usize>),
-    SwitchOnStructure(usize, HashMap<(TabledRc<Atom>, usize), usize>)
+    SwitchOnStructure(usize, HashMap<(ClauseName, usize), usize>)
 }
 
 impl From<IndexingInstruction> for Line {
@@ -1015,7 +1084,7 @@ impl From<IndexingInstruction> for Line {
 pub enum FactInstruction {
     GetConstant(Level, Constant, RegType),
     GetList(Level, RegType),
-    GetStructure(Level, TabledRc<Atom>, usize, RegType, Option<Fixity>),
+    GetStructure(ClauseType, usize, RegType),
     GetValue(RegType, usize),
     GetVariable(RegType, usize),
     UnifyConstant(Constant),
@@ -1029,7 +1098,7 @@ pub enum QueryInstruction {
     GetVariable(RegType, usize),
     PutConstant(Level, Constant, RegType),
     PutList(Level, RegType),
-    PutStructure(Level, TabledRc<Atom>, usize, RegType, Option<Fixity>),
+    PutStructure(ClauseType, usize, RegType),
     PutUnsafeValue(usize, usize),
     PutValue(RegType, usize),
     PutVariable(RegType, usize),
@@ -1113,7 +1182,7 @@ pub enum Ref {
 #[derive(Clone, PartialEq)]
 pub enum HeapCellValue {
     Addr(Addr),
-    NamedStr(usize, TabledRc<Atom>, Option<Fixity>), // arity, name, fixity if it has one.
+    NamedStr(usize, ClauseName, Option<Fixity>), // arity, name, fixity if it has one.
 }
 
 impl HeapCellValue {
@@ -1233,15 +1302,7 @@ impl Term {
         }
     }
 
-    pub fn is_callable(&self) -> bool {
-        match self {
-            &Term::Clause(..) | &Term::Constant(_, Constant::Atom(_)) =>
-                true,
-            _ => false
-        }
-    }
-
-    pub fn name(&self) -> Option<TabledRc<Atom>> {
+    pub fn name(&self) -> Option<ClauseName> {
         match self {
             &Term::Constant(_, Constant::Atom(ref atom))
           | &Term::Clause(_, ref atom, ..) => Some(atom.clone()),
@@ -1259,20 +1320,27 @@ impl Term {
 
 pub enum TermIterState<'a> {
     AnonVar(Level),
-    Clause(usize, ClauseType<'a>, &'a Vec<Box<Term>>),
     Constant(Level, &'a Cell<RegType>, &'a Constant),
+    Clause(Level, usize, &'a Cell<RegType>, ClauseType, &'a Vec<Box<Term>>),
     InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
     FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
     Var(Level, &'a Cell<VarReg>, &'a Var)
 }
 
 impl<'a> TermIterState<'a> {
-    pub fn to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> {
+    pub fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> {
         match term {
             &Term::AnonVar =>
                 TermIterState::AnonVar(lvl),
-            &Term::Clause(ref cell, ref atom, ref child_terms, fixity) =>
-                TermIterState::Clause(0, ClauseType::Deep(lvl, cell, atom, fixity), child_terms),
+            &Term::Clause(ref cell, ref name, ref subterms, fixity) => {                
+                let ct = if let Some(fixity) = fixity {
+                    ClauseType::Op(name.clone(), fixity)
+                } else {
+                    ClauseType::Named(name.clone())
+                };
+                
+                TermIterState::Clause(lvl, 0, cell, ct, subterms)
+            },
             &Term::Cons(ref cell, ref head, ref tail) =>
                 TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref()),
             &Term::Constant(ref cell, ref constant) =>
index 41606caa56e9828a8d9e701d083bbb3dcd4ad133..649fc3aedf497508d5b55f1bb818dddf9a76b967 100644 (file)
@@ -1,11 +1,10 @@
 use prolog::ast::*;
 use prolog::num::bigint::{BigInt};
-use prolog::tabled_rc::*;
 
 use std::collections::HashMap;
 use std::rc::Rc;
 
-pub type PredicateKey = (TabledRc<Atom>, usize); // name, arity, type.
+pub type PredicateKey = (ClauseName, usize); // name, arity, type.
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub enum PredicateKeyType {
@@ -13,13 +12,13 @@ pub enum PredicateKeyType {
     User
 }
 
-pub type OpDirKey = (TabledRc<Atom>, Fixity);
+pub type OpDirKey = (ClauseName, Fixity);
 // name and fixity -> operator type and precedence.
 pub type OpDir = HashMap<OpDirKey, (Specifier, usize)>;
 
 pub type CodeDir = HashMap<PredicateKey, (PredicateKeyType, usize)>;
 
-fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
+fn get_builtins() -> Code {
     vec![internal_call_n!(), // callN/N, 0.
          is_atomic!(temp_v!(1)), // atomic/1, 1.
          proceed!(),
@@ -115,25 +114,25 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
          retry!(7),
          trust!(10),
          try_me_else!(4),
-         fact![get_constant!(atom!("!", atom_tbl), temp_v!(1)),
-               get_structure!(atom_tbl, ",", 2, temp_v!(2), Some(infix!())),
+         fact![get_constant!(atom!("!"), temp_v!(1)),
+               get_structure!(",", 2, temp_v!(2), Some(infix!())),
                unify_variable!(temp_v!(1)),
                unify_variable!(temp_v!(2))],
          set_cp!(temp_v!(3)),
          goto_execute!(83, 3),
          retry_me_else!(4),
-         fact![get_constant!(atom!("!", atom_tbl), temp_v!(1)),
-               get_constant!(atom!("!", atom_tbl), temp_v!(2))],
+         fact![get_constant!(atom!("!"), temp_v!(1)),
+               get_constant!(atom!("!"), temp_v!(2))],
          set_cp!(temp_v!(3)),
          proceed!(),
          trust_me!(),
-         fact![get_constant!(atom!("!", atom_tbl), temp_v!(1))],
+         fact![get_constant!(atom!("!"), temp_v!(1))],
          set_cp!(temp_v!(3)),
          query![put_value!(temp_v!(2), 1)],
          execute_n!(1),
          retry_me_else!(8),
          allocate!(3),
-         fact![get_structure!(atom_tbl, ",", 2, temp_v!(2), Some(infix!())),
+         fact![get_structure!(",", 2, temp_v!(2), Some(infix!())),
                unify_variable!(perm_v!(2)),
                unify_variable!(perm_v!(1)),
                get_var_in_fact!(perm_v!(3), 3)],
@@ -147,7 +146,7 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
          retry_me_else!(10),
          allocate!(2),
          get_level!(perm_v!(2)),
-         fact![get_constant!(atom!("!", atom_tbl), temp_v!(2)),
+         fact![get_constant!(atom!("!"), temp_v!(2)),
                get_var_in_fact!(perm_v!(1), 3)],
          neck_cut!(),
          call_n!(1),
@@ -168,12 +167,12 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
          indexed_try!(3),
          trust!(5),
          try_me_else!(3),
-         fact![get_structure!(atom_tbl, "->", 2, temp_v!(1), Some(infix!())),
+         fact![get_structure!("->", 2, temp_v!(1), Some(infix!())),
                unify_variable!(temp_v!(1)),
                unify_variable!(temp_v!(2))],
          goto_execute!(139, 3),
          trust_me!(),
-         fact![get_structure!(atom_tbl, "->", 2, temp_v!(1), Some(infix!())),
+         fact![get_structure!("->", 2, temp_v!(1), Some(infix!())),
                unify_void!(2)],
          query![put_value!(temp_v!(2), 1)],
          neck_cut!(),
@@ -232,13 +231,8 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
          goto_execute!(149, 3), // goto get_arg/3.
          trust_me!(),
          query![get_var_in_query!(temp_v!(4), 1),
-                put_structure!(atom_tbl,
-                               Level::Shallow,
-                               String::from("type_error"),
-                               1,
-                               temp_v!(1),
-                               None),
-                set_constant!(atom!("integer_expected", atom_tbl))],
+                put_structure!("type_error", 1, temp_v!(1), None),
+                set_constant!(atom!("integer_expected"))],
          goto_execute!(59, 1), // goto throw/1.
          try_me_else!(5), // arg_/5, 173.
          fact![get_value!(temp_v!(1), 2),
@@ -405,13 +399,8 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
          trust_me!(),
          fact![get_var_in_fact!(temp_v!(3), 1),
                get_var_in_fact!(temp_v!(4), 2)],
-         query![put_structure!(atom_tbl,
-                               Level::Shallow,
-                               String::from("type_error"),
-                               2,
-                               temp_v!(1),
-                               None),
-                set_constant!(atom!("integer_expected", atom_tbl)),
+         query![put_structure!("type_error", 2, temp_v!(1), None),
+                set_constant!(atom!("integer_expected")),
                 set_value!(temp_v!(4))],
          goto_execute!(59, 1), // goto throw/1, 59.
          switch_on_term!(1,2,5,0), // length/3, 281.
@@ -453,7 +442,8 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
          try_me_else!(5), // 304.
          is_var!(temp_v!(1)),
          neck_cut!(),
-         query![put_constant!(Level::Shallow, atom!("instantiation_error", atom_tbl),
+         query![put_constant!(Level::Shallow,
+                              atom!("instantiation_error"),
                               temp_v!(1))],
          goto_execute!(59, 1),
          trust_me!(),
@@ -502,7 +492,7 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
          get_cleaner_call!(),
          query![put_value!(perm_v!(2), 1),
                 put_var!(temp_v!(4), 2),
-                put_constant!(Level::Shallow, atom!("true", atom_tbl), temp_v!(3))],
+                put_constant!(Level::Shallow, atom!("true"), temp_v!(3))],
          goto_call!(5, 3), // goto catch/3, 5.
          set_cp!(perm_v!(1)),
          deallocate!(),
@@ -621,9 +611,9 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
          remove_call_policy_check!(),
          fail!(),
          try_me_else!(4), // handle_ile/3, 444.
-         fact![get_structure!(atom_tbl, "inference_limit_exceeded", 1, temp_v!(2), None),
+         fact![get_structure!("inference_limit_exceeded", 1, temp_v!(2), None),
                unify_value!(temp_v!(1)),
-               get_constant!(atom!("inference_limit_exceeded", atom_tbl), temp_v!(3))],
+               get_constant!(atom!("inference_limit_exceeded"), temp_v!(3))],
          neck_cut!(),
          proceed!(),
          default_trust_me!(),
@@ -648,119 +638,119 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
     ]
 }
 
-pub fn build_code_dir(atom_tbl: TabledData<Atom>) -> (Code, CodeDir, OpDir)
+pub fn build_code_dir() -> (Code, CodeDir, OpDir)
 {
     let mut code_dir = HashMap::new();
     let mut op_dir   = HashMap::new();
 
-    let builtin_code = get_builtins(atom_tbl.clone());
+    let builtin_code = get_builtins();
 
-    op_dir.insert((tabled_rc!(":-", atom_tbl), Fixity::In),   (XFX, 1200));
-    op_dir.insert((tabled_rc!(":-", atom_tbl), Fixity::Pre),  (FX, 1200));
-    op_dir.insert((tabled_rc!("?-", atom_tbl), Fixity::Pre),  (FX, 1200));
+    op_dir.insert((clause_name!(":-"), Fixity::In),   (XFX, 1200));
+    op_dir.insert((clause_name!(":-"), Fixity::Pre),  (FX, 1200));
+    op_dir.insert((clause_name!("?-"), Fixity::Pre),  (FX, 1200));
 
     // control operators.
-    op_dir.insert((tabled_rc!("\\+", atom_tbl), Fixity::Pre), (FY, 900));
-    op_dir.insert((tabled_rc!("=", atom_tbl), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!("\\+"), Fixity::Pre), (FY, 900));
+    op_dir.insert((clause_name!("="), Fixity::In), (XFX, 700));
 
     // arithmetic operators.
-    op_dir.insert((tabled_rc!("is", atom_tbl), Fixity::In), (XFX, 700));
-    op_dir.insert((tabled_rc!("+", atom_tbl), Fixity::In), (YFX, 500));
-    op_dir.insert((tabled_rc!("-", atom_tbl), Fixity::In), (YFX, 500));
-    op_dir.insert((tabled_rc!("/\\", atom_tbl), Fixity::In), (YFX, 500));
-    op_dir.insert((tabled_rc!("\\/", atom_tbl), Fixity::In), (YFX, 500));
-    op_dir.insert((tabled_rc!("xor", atom_tbl), Fixity::In), (YFX, 500));
-    op_dir.insert((tabled_rc!("//", atom_tbl), Fixity::In), (YFX, 400));
-    op_dir.insert((tabled_rc!("/", atom_tbl), Fixity::In), (YFX, 400));
-    op_dir.insert((tabled_rc!("div", atom_tbl), Fixity::In), (YFX, 400));
-    op_dir.insert((tabled_rc!("*", atom_tbl), Fixity::In), (YFX, 400));
-    op_dir.insert((tabled_rc!("-", atom_tbl), Fixity::Pre), (FY, 200));
-    op_dir.insert((tabled_rc!("rdiv", atom_tbl), Fixity::In), (YFX, 400));
-    op_dir.insert((tabled_rc!("<<", atom_tbl), Fixity::In), (YFX, 400));
-    op_dir.insert((tabled_rc!(">>", atom_tbl), Fixity::In), (YFX, 400));
-    op_dir.insert((tabled_rc!("mod", atom_tbl), Fixity::In), (YFX, 400));
-    op_dir.insert((tabled_rc!("rem", atom_tbl), Fixity::In), (YFX, 400));
+    op_dir.insert((clause_name!("is"), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!("+"), Fixity::In), (YFX, 500));
+    op_dir.insert((clause_name!("-"), Fixity::In), (YFX, 500));
+    op_dir.insert((clause_name!("/\\"), Fixity::In), (YFX, 500));
+    op_dir.insert((clause_name!("\\/"), Fixity::In), (YFX, 500));
+    op_dir.insert((clause_name!("xor"), Fixity::In), (YFX, 500));
+    op_dir.insert((clause_name!("//"), Fixity::In), (YFX, 400));
+    op_dir.insert((clause_name!("/"), Fixity::In), (YFX, 400));
+    op_dir.insert((clause_name!("div"), Fixity::In), (YFX, 400));
+    op_dir.insert((clause_name!("*"), Fixity::In), (YFX, 400));
+    op_dir.insert((clause_name!("-"), Fixity::Pre), (FY, 200));
+    op_dir.insert((clause_name!("rdiv"), Fixity::In), (YFX, 400));
+    op_dir.insert((clause_name!("<<"), Fixity::In), (YFX, 400));
+    op_dir.insert((clause_name!(">>"), Fixity::In), (YFX, 400));
+    op_dir.insert((clause_name!("mod"), Fixity::In), (YFX, 400));
+    op_dir.insert((clause_name!("rem"), Fixity::In), (YFX, 400));
 
     // arithmetic comparison operators.
-    op_dir.insert((tabled_rc!(">", atom_tbl), Fixity::In), (XFX, 700));
-    op_dir.insert((tabled_rc!("<", atom_tbl), Fixity::In), (XFX, 700));
-    op_dir.insert((tabled_rc!("=\\=", atom_tbl), Fixity::In), (XFX, 700));
-    op_dir.insert((tabled_rc!("=:=", atom_tbl), Fixity::In), (XFX, 700));
-    op_dir.insert((tabled_rc!(">=", atom_tbl), Fixity::In), (XFX, 700));
-    op_dir.insert((tabled_rc!("=<", atom_tbl), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!(">"), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!("<"), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!("=\\="), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!("=:="), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!(">="), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!("=<"), Fixity::In), (XFX, 700));
 
     // control operators.
-    op_dir.insert((tabled_rc!(";", atom_tbl), Fixity::In), (XFY, 1100));
-    op_dir.insert((tabled_rc!("->", atom_tbl), Fixity::In), (XFY, 1050));
+    op_dir.insert((clause_name!(";"), Fixity::In), (XFY, 1100));
+    op_dir.insert((clause_name!("->"), Fixity::In), (XFY, 1050));
 
-    op_dir.insert((tabled_rc!("=..", atom_tbl), Fixity::In), (XFX, 700));
-    op_dir.insert((tabled_rc!("==", atom_tbl), Fixity::In), (XFX, 700));
-    op_dir.insert((tabled_rc!("\\==", atom_tbl), Fixity::In), (XFX, 700));
-    op_dir.insert((tabled_rc!("@=<", atom_tbl), Fixity::In), (XFX, 700));
-    op_dir.insert((tabled_rc!("@>=", atom_tbl), Fixity::In), (XFX, 700));
-    op_dir.insert((tabled_rc!("@<", atom_tbl), Fixity::In), (XFX, 700));
-    op_dir.insert((tabled_rc!("@>", atom_tbl), Fixity::In), (XFX, 700));
-    op_dir.insert((tabled_rc!("=@=", atom_tbl), Fixity::In), (XFX, 700));
-    op_dir.insert((tabled_rc!("\\=@=", atom_tbl), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!("=.."), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!("=="), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!("\\=="), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!("@=<"), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!("@>="), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!("@<"), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!("@>"), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!("=@="), Fixity::In), (XFX, 700));
+    op_dir.insert((clause_name!("\\=@="), Fixity::In), (XFX, 700));
 
     // there are 63 registers in the VM, so call/N is defined for all 0 <= N <= 62
     // (an extra register is needed for the predicate name)
     for arity in 0 .. 63 {
-        code_dir.insert((tabled_rc!("call", atom_tbl), arity), (PredicateKeyType::BuiltIn, 0));
+        code_dir.insert((clause_name!("call"), arity), (PredicateKeyType::BuiltIn, 0));
     }
 
-    code_dir.insert((tabled_rc!("atomic", atom_tbl), 1), (PredicateKeyType::BuiltIn, 1));
-    code_dir.insert((tabled_rc!("var", atom_tbl), 1), (PredicateKeyType::BuiltIn, 3));
-    code_dir.insert((tabled_rc!("false", atom_tbl), 0), (PredicateKeyType::BuiltIn, 61));
-    code_dir.insert((tabled_rc!("\\+", atom_tbl), 1), (PredicateKeyType::BuiltIn, 62));
-    code_dir.insert((tabled_rc!("duplicate_term", atom_tbl), 2), (PredicateKeyType::BuiltIn, 71));
-    code_dir.insert((tabled_rc!("catch", atom_tbl), 3), (PredicateKeyType::BuiltIn, 5));
-    code_dir.insert((tabled_rc!("throw", atom_tbl), 1), (PredicateKeyType::BuiltIn, 59));
-    code_dir.insert((tabled_rc!("=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 73));
-    code_dir.insert((tabled_rc!("true", atom_tbl), 0), (PredicateKeyType::BuiltIn, 75));
+    code_dir.insert((clause_name!("atomic"), 1), (PredicateKeyType::BuiltIn, 1));
+    code_dir.insert((clause_name!("var"), 1), (PredicateKeyType::BuiltIn, 3));
+    code_dir.insert((clause_name!("false"), 0), (PredicateKeyType::BuiltIn, 61));
+    code_dir.insert((clause_name!("\\+"), 1), (PredicateKeyType::BuiltIn, 62));
+    code_dir.insert((clause_name!("duplicate_term"), 2), (PredicateKeyType::BuiltIn, 71));
+    code_dir.insert((clause_name!("catch"), 3), (PredicateKeyType::BuiltIn, 5));
+    code_dir.insert((clause_name!("throw"), 1), (PredicateKeyType::BuiltIn, 59));
+    code_dir.insert((clause_name!("="), 2), (PredicateKeyType::BuiltIn, 73));
+    code_dir.insert((clause_name!("true"), 0), (PredicateKeyType::BuiltIn, 75));
 
-    code_dir.insert((tabled_rc!(",", atom_tbl), 2), (PredicateKeyType::BuiltIn, 76));
-    code_dir.insert((tabled_rc!(";", atom_tbl), 2), (PredicateKeyType::BuiltIn, 120));
-    code_dir.insert((tabled_rc!("->", atom_tbl), 2), (PredicateKeyType::BuiltIn, 138));
+    code_dir.insert((clause_name!(","), 2), (PredicateKeyType::BuiltIn, 76));
+    code_dir.insert((clause_name!(";"), 2), (PredicateKeyType::BuiltIn, 120));
+    code_dir.insert((clause_name!("->"), 2), (PredicateKeyType::BuiltIn, 138));
 
-    code_dir.insert((tabled_rc!("functor", atom_tbl), 3), (PredicateKeyType::BuiltIn, 146));
-    code_dir.insert((tabled_rc!("arg", atom_tbl), 3), (PredicateKeyType::BuiltIn, 150));
-    code_dir.insert((tabled_rc!("integer", atom_tbl), 1), (PredicateKeyType::BuiltIn, 147));
-    code_dir.insert((tabled_rc!("display", atom_tbl), 1), (PredicateKeyType::BuiltIn, 192));
+    code_dir.insert((clause_name!("functor"), 3), (PredicateKeyType::BuiltIn, 146));
+    code_dir.insert((clause_name!("arg"), 3), (PredicateKeyType::BuiltIn, 150));
+    code_dir.insert((clause_name!("integer"), 1), (PredicateKeyType::BuiltIn, 147));
+    code_dir.insert((clause_name!("display"), 1), (PredicateKeyType::BuiltIn, 192));
 
-    code_dir.insert((tabled_rc!("is", atom_tbl), 2), (PredicateKeyType::BuiltIn, 194));
-    code_dir.insert((tabled_rc!(">", atom_tbl), 2), (PredicateKeyType::BuiltIn, 196));
-    code_dir.insert((tabled_rc!("<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 198));
-    code_dir.insert((tabled_rc!(">=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 200));
-    code_dir.insert((tabled_rc!("<=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 202));
-    code_dir.insert((tabled_rc!("=\\=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 204));
-    code_dir.insert((tabled_rc!("=:=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 206));
-    code_dir.insert((tabled_rc!("=..", atom_tbl), 2), (PredicateKeyType::BuiltIn, 208));
+    code_dir.insert((clause_name!("is"), 2), (PredicateKeyType::BuiltIn, 194));
+    code_dir.insert((clause_name!(">"), 2), (PredicateKeyType::BuiltIn, 196));
+    code_dir.insert((clause_name!("<"), 2), (PredicateKeyType::BuiltIn, 198));
+    code_dir.insert((clause_name!(">="), 2), (PredicateKeyType::BuiltIn, 200));
+    code_dir.insert((clause_name!("<="), 2), (PredicateKeyType::BuiltIn, 202));
+    code_dir.insert((clause_name!("=\\="), 2), (PredicateKeyType::BuiltIn, 204));
+    code_dir.insert((clause_name!("=:="), 2), (PredicateKeyType::BuiltIn, 206));
+    code_dir.insert((clause_name!("=.."), 2), (PredicateKeyType::BuiltIn, 208));
 
-    code_dir.insert((tabled_rc!("length", atom_tbl), 2), (PredicateKeyType::BuiltIn, 261));
-    code_dir.insert((tabled_rc!("setup_call_cleanup", atom_tbl), 3),
+    code_dir.insert((clause_name!("length"), 2), (PredicateKeyType::BuiltIn, 261));
+    code_dir.insert((clause_name!("setup_call_cleanup"), 3),
                     (PredicateKeyType::BuiltIn, 294));
-    code_dir.insert((tabled_rc!("call_with_inference_limit", atom_tbl), 3),
+    code_dir.insert((clause_name!("call_with_inference_limit"), 3),
                     (PredicateKeyType::BuiltIn, 393));
-    code_dir.insert((tabled_rc!("_handle_inference_limit_exceeded", atom_tbl), 2),
+    code_dir.insert((clause_name!("_handle_inference_limit_exceeded"), 2),
                     (PredicateKeyType::BuiltIn, 421));
 
-    code_dir.insert((tabled_rc!("compound", atom_tbl), 1), (PredicateKeyType::BuiltIn, 372));
-    code_dir.insert((tabled_rc!("rational", atom_tbl), 1), (PredicateKeyType::BuiltIn, 374));
-    code_dir.insert((tabled_rc!("string", atom_tbl), 1), (PredicateKeyType::BuiltIn, 376));
-    code_dir.insert((tabled_rc!("float", atom_tbl), 1), (PredicateKeyType::BuiltIn, 378));
-    code_dir.insert((tabled_rc!("nonvar", atom_tbl), 1), (PredicateKeyType::BuiltIn, 380));
+    code_dir.insert((clause_name!("compound"), 1), (PredicateKeyType::BuiltIn, 372));
+    code_dir.insert((clause_name!("rational"), 1), (PredicateKeyType::BuiltIn, 374));
+    code_dir.insert((clause_name!("string"), 1), (PredicateKeyType::BuiltIn, 376));
+    code_dir.insert((clause_name!("float"), 1), (PredicateKeyType::BuiltIn, 378));
+    code_dir.insert((clause_name!("nonvar"), 1), (PredicateKeyType::BuiltIn, 380));
 
-    code_dir.insert((tabled_rc!("ground", atom_tbl), 1), (PredicateKeyType::BuiltIn, 384));
-    code_dir.insert((tabled_rc!("==", atom_tbl), 2), (PredicateKeyType::BuiltIn, 385));
-    code_dir.insert((tabled_rc!("\\==", atom_tbl), 2), (PredicateKeyType::BuiltIn, 386));
-    code_dir.insert((tabled_rc!("@>=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 387));
-    code_dir.insert((tabled_rc!("@=<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 388));
-    code_dir.insert((tabled_rc!("@>", atom_tbl), 2), (PredicateKeyType::BuiltIn, 389));
-    code_dir.insert((tabled_rc!("@<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 390));
-    code_dir.insert((tabled_rc!("=@=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 391));
-    code_dir.insert((tabled_rc!("\\=@=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 392));
-    code_dir.insert((tabled_rc!("compare", atom_tbl), 3), (PredicateKeyType::BuiltIn, 464));
+    code_dir.insert((clause_name!("ground"), 1), (PredicateKeyType::BuiltIn, 384));
+    code_dir.insert((clause_name!("=="), 2), (PredicateKeyType::BuiltIn, 385));
+    code_dir.insert((clause_name!("\\=="), 2), (PredicateKeyType::BuiltIn, 386));
+    code_dir.insert((clause_name!("@>="), 2), (PredicateKeyType::BuiltIn, 387));
+    code_dir.insert((clause_name!("@=<"), 2), (PredicateKeyType::BuiltIn, 388));
+    code_dir.insert((clause_name!("@>"), 2), (PredicateKeyType::BuiltIn, 389));
+    code_dir.insert((clause_name!("@<"), 2), (PredicateKeyType::BuiltIn, 390));
+    code_dir.insert((clause_name!("=@="), 2), (PredicateKeyType::BuiltIn, 391));
+    code_dir.insert((clause_name!("\\=@="), 2), (PredicateKeyType::BuiltIn, 392));
+    code_dir.insert((clause_name!("compare"), 3), (PredicateKeyType::BuiltIn, 464));
     
     (builtin_code, code_dir, op_dir)
 }
index 9d3b61c0524d747452c9a1ac2ef039520a1eaeed..0c12c03a30d993495fe9b5cefa47b63d5cb11d26 100644 (file)
@@ -156,25 +156,6 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
         };
     }
 
-    fn compile_clause<Target>(&mut self, ct: ClauseType<'a>, term_loc: GenContext,
-                              is_exposed: bool, terms: &'a Vec<Box<Term>>,
-                              target: &mut Vec<Target>)
-        where Target: CompilationTarget<'a>
-    {
-        match ct {
-            ClauseType::Deep(lvl, cell, atom, fixity) => {
-                self.marker.mark_non_var(lvl, term_loc, cell, target);
-                target.push(Target::to_structure(lvl, atom.clone(), terms.len(),
-                                                 cell.get(), fixity));
-
-                for subterm in terms {
-                    self.subterm_to_instr(subterm.as_ref(), term_loc, is_exposed, target);
-                }
-            },
-            _ => {}
-        }
-    }
-
     fn compile_target<Target, Iter>(&mut self, iter: Iter, term_loc: GenContext, is_exposed: bool)
                                     -> Vec<Target>
         where Target: CompilationTarget<'a>, Iter: Iterator<Item=TermRef<'a>>
@@ -183,8 +164,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
 
         for term in iter {
             match term {
-                TermRef::Clause(ct, terms) =>
-                    self.compile_clause(ct, term_loc, is_exposed, terms, &mut target),
+                TermRef::Clause(lvl, cell, ct, terms) => {
+                    self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
+                    target.push(Target::to_structure(ct, terms.len(), cell.get()));
+
+                    for subterm in terms {
+                        self.subterm_to_instr(subterm.as_ref(), term_loc, is_exposed, &mut target);
+                    }
+                },
                 TermRef::Cons(lvl, cell, head, tail) => {
                     self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
                     target.push(Target::to_list(lvl, cell.get()));
@@ -214,24 +201,24 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
     fn collect_var_data(&mut self, mut iter: ChunkedIterator<'a>) -> ConjunctInfo<'a>
     {
         let mut vs = VariableFixtures::new();
-        let at_rule_head = iter.at_rule_head();
 
-        while let Some((chunk_num, lt_arity, terms)) = iter.next() {
-            for (i, query_term) in terms.iter().enumerate() {
-                let term_loc = if chunk_num == 0 && i == 0 && at_rule_head {
-                    GenContext::Head
-                } else if i < terms.len() - 1 {
-                    GenContext::Mid(chunk_num)
-                } else {
-                    GenContext::Last(chunk_num)
-                };
+        while let Some((chunk_num, lt_arity, chunked_terms)) = iter.next() {
+            for (i, chunked_term) in chunked_terms.iter().enumerate() {
+                let term_loc = match chunked_term {
+                    &ChunkedTerm::HeadClause(..) => GenContext::Head,
+                    &ChunkedTerm::BodyTerm(_) => if i < chunked_terms.len() - 1 {
+                        GenContext::Mid(chunk_num)
+                    } else {
+                        GenContext::Last(chunk_num)
+                    }
+                };                
 
-                self.update_var_count(query_term.post_order_iter());
-                vs.mark_vars_in_chunk(query_term.post_order_iter(), lt_arity, term_loc);
+                self.update_var_count(chunked_term.post_order_iter());
+                vs.mark_vars_in_chunk(chunked_term.post_order_iter(), lt_arity, term_loc);
             }
         }
 
-        let num_of_chunks = iter.chunk_num();
+        let num_of_chunks = iter.chunk_num;
         let has_deep_cut  = iter.encountered_deep_cut();
 
         vs.populate_restricting_sets();
@@ -245,51 +232,51 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
     fn add_conditional_call(code: &mut Code, qt: &QueryTerm, pvs: usize)
     {
         match qt {
-            &QueryTerm::CallWithInferenceLimit(_) =>
-                code.push(goto_call!(393, 3)),
-            &QueryTerm::SetupCallCleanup(_) =>
-                code.push(goto_call!(294, 3)),
-            &QueryTerm::Arg(_) => {
-                let call = ControlInstruction::ArgCall;
-                code.push(Line::Control(call));
-            },
-            &QueryTerm::CallN(ref terms) => {
-                let call = ControlInstruction::CallN(terms.len());
-                code.push(Line::Control(call));
-            },
-            &QueryTerm::Catch(_) =>
-                code.push(Line::Control(ControlInstruction::CatchCall)),
-            &QueryTerm::Compare(_) =>
-                code.push(Line::Control(ControlInstruction::CompareCall)),
-            &QueryTerm::CompareTerm(qt, _) =>
-                code.push(Line::Control(ControlInstruction::CompareTermCall(qt))),
-            &QueryTerm::Display(_) =>
-                code.push(Line::Control(ControlInstruction::DisplayCall)),
-            &QueryTerm::DuplicateTerm(_) =>
-                code.push(Line::Control(ControlInstruction::DuplicateTermCall)),
-            &QueryTerm::Eq(_) =>
-                code.push(Line::Control(ControlInstruction::EqCall)),
-            &QueryTerm::Ground(_) =>
-                code.push(Line::Control(ControlInstruction::GroundCall)),
-            &QueryTerm::Functor(_) =>
-                code.push(Line::Control(ControlInstruction::FunctorCall)),
-            &QueryTerm::Inlined(_) =>
-                code.push(proceed!()),
             &QueryTerm::Jump(ref vars) => {
                 code.push(jmp_call!(vars.len(), 0));
             },
-            &QueryTerm::NotEq(_) =>
-                code.push(Line::Control(ControlInstruction::NotEqCall)),
-            &QueryTerm::Term(Term::Constant(_, Constant::Atom(ref atom))) => {
-                let call = ControlInstruction::Call(atom.clone(), 0, pvs);
-                code.push(Line::Control(call));
-            },
-            &QueryTerm::Term(Term::Clause(_, ref atom, ref terms, _)) => {
-                let call = ControlInstruction::Call(atom.clone(), terms.len(), pvs);
-                code.push(Line::Control(call));
-            },
-            &QueryTerm::Throw(_) =>
-                code.push(Line::Control(ControlInstruction::ThrowCall)),
+            &QueryTerm::Clause(_, ref ct, ref terms) =>
+                match ct {
+                    &ClauseType::CallWithInferenceLimit =>
+                        code.push(goto_call!(393, 3)),
+                    &ClauseType::SetupCallCleanup =>
+                        code.push(goto_call!(294, 3)),
+                    &ClauseType::Arg => {
+                        let call = ControlInstruction::ArgCall;
+                        code.push(Line::Control(call));
+                    },
+                    &ClauseType::CallN => {
+                        let call = ControlInstruction::CallN(terms.len());
+                        code.push(Line::Control(call));
+                    },
+                    &ClauseType::Catch =>
+                        code.push(Line::Control(ControlInstruction::CatchCall)),
+                    &ClauseType::Compare =>
+                        code.push(Line::Control(ControlInstruction::CompareCall)),
+                    &ClauseType::CompareTerm(qt) =>
+                        code.push(Line::Control(ControlInstruction::CompareTermCall(qt))),
+                    &ClauseType::Display =>
+                        code.push(Line::Control(ControlInstruction::DisplayCall)),
+                    &ClauseType::DuplicateTerm =>
+                        code.push(Line::Control(ControlInstruction::DuplicateTermCall)),
+                    &ClauseType::Eq =>
+                        code.push(Line::Control(ControlInstruction::EqCall)),
+                    &ClauseType::Ground =>
+                        code.push(Line::Control(ControlInstruction::GroundCall)),
+                    &ClauseType::Functor =>
+                        code.push(Line::Control(ControlInstruction::FunctorCall)),
+                    &ClauseType::Inlined(_) =>
+                        code.push(proceed!()),
+                    &ClauseType::NotEq =>
+                        code.push(Line::Control(ControlInstruction::NotEqCall)),
+                    &ClauseType::Named(ref name) | &ClauseType::Op(ref name, _) => {
+                        let call = ControlInstruction::Call(name.clone(), terms.len(), pvs);
+                        code.push(Line::Control(call));
+                    },
+                    &ClauseType::Throw =>
+                        code.push(Line::Control(ControlInstruction::ThrowCall)),
+                    _ => {}
+                },
             _ => {}
         }
     }
@@ -344,11 +331,12 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
         dealloc_index
     }
 
-    fn compile_inlined(&mut self, term: &'a InlinedQueryTerm, term_loc: GenContext, code: &mut Code)
+    fn compile_inlined(&mut self, ct: InlinedClauseType, terms: &'a Vec<Box<Term>>,
+                       term_loc: GenContext, code: &mut Code)
                        -> Result<(), ParserError>
     {
-        match term {
-            &InlinedQueryTerm::CompareNumber(cmp, ref terms) => {
+        match ct {
+            InlinedClauseType::CompareNumber(cmp) => {
                 let (mut lcode, at_1) = self.call_arith_eval(terms[0].as_ref(), 1)?;
                 let (mut rcode, at_2) = self.call_arith_eval(terms[1].as_ref(), 2)?;
 
@@ -359,8 +347,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                                                 at_1.unwrap_or(interm!(1)),
                                                 at_2.unwrap_or(interm!(2))));
             },
-            &InlinedQueryTerm::IsAtomic(ref inner_term) =>
-                match inner_term[0].as_ref() {
+            InlinedClauseType::IsAtomic =>
+                match terms[0].as_ref() {
                     &Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) => {
                         code.push(fail!());
                     },
@@ -372,8 +360,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                         code.push(is_atomic!(r));
                     }
                 },
-            &InlinedQueryTerm::IsCompound(ref inner_term) =>
-                match inner_term[0].as_ref() {
+            InlinedClauseType::IsCompound =>
+                match terms[0].as_ref() {
                     &Term::Clause(..) | &Term::Cons(..) => {
                         code.push(succeed!());
                     },
@@ -385,8 +373,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                         code.push(fail!());
                     }
                 },
-            &InlinedQueryTerm::IsRational(ref inner_term) =>
-                match inner_term[0].as_ref() {
+            InlinedClauseType::IsRational =>
+                match terms[0].as_ref() {
                     &Term::Constant(_, Constant::Number(Number::Rational(_))) => {
                         code.push(succeed!());
                     },
@@ -398,8 +386,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                         code.push(fail!());
                     }
                 },
-            &InlinedQueryTerm::IsFloat(ref inner_term) =>
-                match inner_term[0].as_ref() {
+            InlinedClauseType::IsFloat =>
+                match terms[0].as_ref() {
                     &Term::Constant(_, Constant::Number(Number::Float(_))) => {
                         code.push(succeed!());
                     },
@@ -411,8 +399,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                         code.push(fail!());
                     }
                 },
-            &InlinedQueryTerm::IsString(ref inner_term) =>
-                match inner_term[0].as_ref() {
+            InlinedClauseType::IsString =>
+                match terms[0].as_ref() {
                     &Term::Constant(_, Constant::String(_)) => {
                         code.push(succeed!());
                     },
@@ -424,8 +412,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                         code.push(fail!());
                     }
                 },
-            &InlinedQueryTerm::IsNonVar(ref inner_term) =>
-                match inner_term[0].as_ref() {
+            InlinedClauseType::IsNonVar =>
+                match terms[0].as_ref() {
                     &Term::AnonVar => {
                         code.push(fail!());
                     },
@@ -437,8 +425,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                         code.push(succeed!());
                     }
                 },
-            &InlinedQueryTerm::IsInteger(ref inner_term) =>
-                match inner_term[0].as_ref() {
+            InlinedClauseType::IsInteger =>
+                match terms[0].as_ref() {
                     &Term::Constant(_, Constant::Number(Number::Integer(_))) => {
                         code.push(succeed!());
                     },
@@ -450,8 +438,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                         code.push(fail!());
                     },
                 },
-            &InlinedQueryTerm::IsVar(ref inner_term) =>
-                match inner_term[0].as_ref() {
+            InlinedClauseType::IsVar =>
+                match terms[0].as_ref() {
                     &Term::Constant(..) | &Term::Clause(..) | &Term::Cons(..) => {
                         code.push(fail!());
                     },
@@ -488,14 +476,20 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                     GenContext::Last(chunk_num)
                 };
 
+                let term = if let &ChunkedTerm::BodyTerm(ref term) = term {
+                    Ok(term)
+                } else {
+                    Err(ParserError::InadmissibleQueryTerm)
+                }?;
+
                 match *term {
                     &QueryTerm::Cut =>
                         code.push(if chunk_num == 0 {
                             Line::Cut(CutInstruction::NeckCut)
                         } else {
                             Line::Cut(CutInstruction::Cut(perm_v!(1)))
-                        }),                    
-                    &QueryTerm::Is(ref terms) => {
+                        }),
+                    &QueryTerm::Clause(_, ClauseType::Is, ref terms) => {
                         let (mut acode, at) = self.call_arith_eval(terms[1].as_ref(), 1)?;
                         code.append(&mut acode);
 
@@ -510,7 +504,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                                 if !target.is_empty() {
                                     code.push(Line::Query(target));
                                 }
-                                
+
                                 code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1))));
                             },
                             &Term::Constant(_, ref c @ Constant::Number(_)) => {
@@ -524,8 +518,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                             }
                         }
                     },
-                    &QueryTerm::Inlined(ref term) =>
-                        try!(self.compile_inlined(term, term_loc, code)),
+                    &QueryTerm::Clause(_, ClauseType::Inlined(ct), ref terms) =>
+                        try!(self.compile_inlined(ct, terms, term_loc, code)),
                     _ => {
                         let num_perm_vars = if chunk_num == 0 {
                             conjunct_info.perm_vars()
@@ -535,7 +529,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
 
                         self.compile_query_line(term, term_loc, code, num_perm_vars, is_exposed);
                     },
-                };                
+                };
             }
 
             self.marker.reset_contents();
@@ -559,10 +553,9 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
 
     fn compile_cleanup(code: &mut Code, conjunct_info: &ConjunctInfo, toc: &'a QueryTerm)
     {
-        // add a proceed to bookend any trailing inlines or cuts.
+        // add a proceed to bookend any trailing cuts.
         match toc {
-            &QueryTerm::Inlined(_) | &QueryTerm::Cut =>
-                code.push(proceed!()),
+            &QueryTerm::Cut => code.push(proceed!()),
             _ => {}
         };
 
@@ -579,42 +572,37 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
         let iter = ChunkedIterator::from_rule(rule);
         let conjunct_info = self.collect_var_data(iter);
 
-        let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
+        let &Rule { head: (_, ref args, ref p1), ref clauses } = rule;
         let mut code = Vec::new();
 
-        if let &QueryTerm::Term(ref term) = p0 {
-            self.marker.reset_arg(term.arity());
-            self.compile_seq_prelude(&conjunct_info, &mut code);
+        self.marker.reset_arg(args.len());
+        self.compile_seq_prelude(&conjunct_info, &mut code);
 
-            if let &Term::Clause(..) = term {
-                let iter = FactInstruction::iter(term);
-                let fact = self.compile_target(iter, GenContext::Head, false);
+        let iter = FactIterator::from_rule_head_clause(args);
+        let fact = self.compile_target(iter, GenContext::Head, false);
 
-                if !fact.is_empty() {
-                    code.push(Line::Fact(fact));
-                }
-            }
+        if !fact.is_empty() {
+            code.push(Line::Fact(fact));
+        }
 
-            let iter = ChunkedIterator::from_rule_body(p1, clauses);
-            try!(self.compile_seq(iter, &conjunct_info, &mut code, false));
+        let iter = ChunkedIterator::from_rule_body(p1, clauses);
+        try!(self.compile_seq(iter, &conjunct_info, &mut code, false));
 
-            if conjunct_info.allocates() {
-                let index = if let &Line::Control(_) = code.last().unwrap() {
-                    code.len() - 2
-                } else {
-                    code.len() - 1
-                };
+        if conjunct_info.allocates() {
+            let index = if let &Line::Control(_) = code.last().unwrap() {
+                code.len() - 2
+            } else {
+                code.len() - 1
+            };
 
-                if let &mut Line::Query(ref mut query) = &mut code[index] {
-                    conjunct_info.perm_vs.mark_unsafe_vars_in_rule(term, query);
-                }
+            if let &mut Line::Query(ref mut query) = &mut code[index] {
+                let head_iter = FactIterator::from_rule_head_clause(args);
+                conjunct_info.perm_vs.mark_unsafe_vars_in_rule(head_iter, query);
             }
-
-            Self::compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1));
-            Ok(code)
-        } else {
-            Err(ParserError::InvalidRuleHead)
         }
+
+        Self::compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1));
+        Ok(code)
     }
 
     fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact)
index 0e86efe9bc66edb56bd18f4bb4527b8873e5b269..4fda7415f9ccdf22eb886a7a0593243116a81c2c 100644 (file)
@@ -210,7 +210,7 @@ impl<'a> Allocator<'a> for DebrayAllocator<'a>
 
         match lvl {
             Level::Deep => target.push(Target::subterm_to_variable(r)),
-            Level::Shallow => {
+            Level::Root | Level::Shallow => {
                 let k = self.arg_c;
                 self.arg_c += 1;
 
@@ -218,12 +218,9 @@ impl<'a> Allocator<'a> for DebrayAllocator<'a>
             }
         };
     }
-
-    fn mark_non_var<Target>(&mut self,
-                            lvl: Level,
-                            term_loc: GenContext,
-                            cell: &Cell<RegType>,
-                            target: &mut Vec<Target>)
+    
+    fn mark_non_var<Target>(&mut self, lvl: Level, term_loc: GenContext,
+                            cell: &Cell<RegType>, target: &mut Vec<Target>)
         where Target: CompilationTarget<'a>
     {
         let r = cell.get();
@@ -270,7 +267,7 @@ impl<'a> Allocator<'a> for DebrayAllocator<'a>
         };
 
         match lvl {
-            Level::Shallow => {
+            Level::Root | Level::Shallow => {
                 let k = self.arg_c;
 
                 if self.is_curr_arg_distinct_from(var) {
index 7d09b5bd7f9e3a2cdaca9bee43b8574be6ee1278..3b9abcf63e77eb069e3f56a86d4304ef2664b680 100644 (file)
@@ -1,4 +1,5 @@
 use prolog::ast::*;
+use prolog::iterators::*;
 
 use std::cell::Cell;
 use std::collections::{BTreeMap, BTreeSet, HashMap};
@@ -275,9 +276,9 @@ impl<'a> VariableFixtures<'a>
         }
     }
 
-    fn mark_head_vars_as_safe(&self, head: &Term, unsafe_vars: &mut HashMap<RegType, bool>)
+    fn mark_head_vars_as_safe(&self, head_iter: FactIterator<'a>, unsafe_vars: &mut HashMap<RegType, bool>)
     {
-        for term_ref in head.breadth_first_iter() {
+        for term_ref in head_iter {
             match term_ref {
                 TermRef::Var(Level::Shallow, cell, _) => {
                     unsafe_vars.remove(&cell.get().norm());
@@ -294,12 +295,12 @@ impl<'a> VariableFixtures<'a>
         self.mark_unsafe_vars(&mut unsafe_vars, query);
     }
 
-    pub fn mark_unsafe_vars_in_rule(&self, head: &Term, query: &mut CompiledQuery)
+    pub fn mark_unsafe_vars_in_rule(&self, head_iter: FactIterator<'a>, query: &mut CompiledQuery)
     {
         let mut unsafe_vars = HashMap::new();
 
         self.record_unsafe_vars(&mut unsafe_vars);
-        self.mark_head_vars_as_safe(head, &mut unsafe_vars);
+        self.mark_head_vars_as_safe(head_iter, &mut unsafe_vars);
         self.mark_unsafe_vars(&mut unsafe_vars, query);
     }
 }
index 07ddbd2ee1421b6a39064cd07b077c3d9460ee21..21e568ce33a36895848b1465104acc38a51c555c 100644 (file)
@@ -1,13 +1,12 @@
 use prolog::ast::*;
 use prolog::heap_iter::*;
-use prolog::tabled_rc::*;
 
 use std::cell::Cell;
 use std::rc::Rc;
 
 #[derive(Clone)]
 pub enum TokenOrRedirect {
-    Atom(TabledRc<Atom>),
+    Atom(ClauseName),
     Redirect,
     Open,
     Close,
@@ -21,7 +20,7 @@ pub enum TokenOrRedirect {
 pub trait HeapCellValueFormatter {
     // this function belongs to the display predicate formatter, which it uses
     // to format all clauses.
-    fn format_struct(&self, arity: usize, name: TabledRc<Atom>, state_stack: &mut Vec<TokenOrRedirect>)
+    fn format_struct(&self, arity: usize, name: ClauseName, state_stack: &mut Vec<TokenOrRedirect>)
     {
         state_stack.push(TokenOrRedirect::Close);
 
@@ -38,7 +37,7 @@ pub trait HeapCellValueFormatter {
 
     // this can be overloaded to handle special cases, falling back on the default of
     // format_struct when convenient.
-    fn format_clause(&self, usize, TabledRc<Atom>, Option<Fixity>, &mut Vec<TokenOrRedirect>);
+    fn format_clause(&self, usize, ClauseType, &mut Vec<TokenOrRedirect>);
 }
 
 pub trait HeapCellValueOutputter {
@@ -95,18 +94,16 @@ impl HeapCellValueOutputter for PrinterOutputter {
 pub struct DisplayFormatter {}
 
 impl HeapCellValueFormatter for DisplayFormatter {
-    fn format_clause(&self, arity: usize, name: TabledRc<Atom>, fixity: Option<Fixity>,
-                     state_stack: &mut Vec<TokenOrRedirect>)
+    fn format_clause(&self, arity: usize, ct: ClauseType, state_stack: &mut Vec<TokenOrRedirect>)
     {
-        if fixity.is_some() {
+        if ct.fixity().is_some() {
             let mut new_name = String::from("'");
-            new_name += name.as_ref();
+            new_name += ct.name().as_str();
             new_name += "'";
-
-            let name = TabledRc::new(new_name, name.table());
-            self.format_struct(arity, name, state_stack);
+            
+            self.format_struct(arity, ct.name(), state_stack);
         } else {
-            self.format_struct(arity, name, state_stack);
+            self.format_struct(arity, ct.name(), state_stack);
         }
     }
 }
@@ -114,31 +111,30 @@ impl HeapCellValueFormatter for DisplayFormatter {
 pub struct TermFormatter {}
 
 impl HeapCellValueFormatter for TermFormatter {
-    fn format_clause(&self, arity: usize, name: TabledRc<Atom>, fixity: Option<Fixity>,
-                     state_stack: &mut Vec<TokenOrRedirect>)
+    fn format_clause(&self, arity: usize, ct: ClauseType, state_stack: &mut Vec<TokenOrRedirect>)
     {
-        if let Some(fixity) = fixity {
+        if let Some(fixity) = ct.fixity() {
             match fixity {
                 Fixity::Post => {
-                    state_stack.push(TokenOrRedirect::Atom(name));
+                    state_stack.push(TokenOrRedirect::Atom(ct.name()));
                     state_stack.push(TokenOrRedirect::Space);
                     state_stack.push(TokenOrRedirect::Redirect);
                 },
                 Fixity::Pre => {
                     state_stack.push(TokenOrRedirect::Redirect);
                     state_stack.push(TokenOrRedirect::Space);
-                    state_stack.push(TokenOrRedirect::Atom(name));
+                    state_stack.push(TokenOrRedirect::Atom(ct.name()));
                 },
                 Fixity::In => {
                     state_stack.push(TokenOrRedirect::Redirect);
                     state_stack.push(TokenOrRedirect::Space);
-                    state_stack.push(TokenOrRedirect::Atom(name));
+                    state_stack.push(TokenOrRedirect::Atom(ct.name()));
                     state_stack.push(TokenOrRedirect::Space);
                     state_stack.push(TokenOrRedirect::Redirect);
                 }
             }
         } else {
-            self.format_struct(arity, name, state_stack);
+            self.format_struct(arity, ct.name(), state_stack);
         }
     }
 }
@@ -161,8 +157,10 @@ impl<'a, Formatter: HeapCellValueFormatter, Outputter: HeapCellValueOutputter>
 
     fn handle_heap_term(&mut self, heap_val: HeapCellValue) {
         match heap_val {
-            HeapCellValue::NamedStr(arity, name, fixity) =>
-                self.formatter.format_clause(arity, name, fixity, &mut self.state_stack),
+            HeapCellValue::NamedStr(arity, name, fixity) => {
+                let ct = ClauseType::from(name, arity, fixity);
+                self.formatter.format_clause(arity, ct, &mut self.state_stack)
+            },
             HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) =>
                 if !self.at_cdr("") {
                     self.outputter.append("[]");
index 48a26d98ae99b18495f4561a2f1b22ce27aa7968..384a343fa380f5859b7b1d6823bf6a889db99601 100644 (file)
@@ -1,5 +1,4 @@
 use prolog::ast::*;
-use prolog::tabled_rc::*;
 
 use std::collections::{HashMap, VecDeque};
 use std::hash::Hash;
@@ -12,7 +11,7 @@ enum IntIndex {
 pub struct CodeOffsets {
     pub constants:  HashMap<Constant, ThirdLevelIndex>,
     pub lists: ThirdLevelIndex,
-    pub structures: HashMap<(TabledRc<Atom>, usize), ThirdLevelIndex>
+    pub structures: HashMap<(ClauseName, usize), ThirdLevelIndex>
 }
 
 impl CodeOffsets {
@@ -145,7 +144,7 @@ impl CodeOffsets {
         }
     }
 
-    fn switch_on_structure(str_ind: HashMap<(TabledRc<Atom>, usize), ThirdLevelIndex>,
+    fn switch_on_structure(str_ind: HashMap<(ClauseName, usize), ThirdLevelIndex>,
                            prelude: &mut CodeDeque)
                            -> IntIndex
     {
index 3a5847eb51fcb6681a551bff59ac84f63f26226f..8418d88ec1908bd2e2cff39e6ffc7e1156263560 100644 (file)
@@ -13,21 +13,21 @@ use termion::event::Key;
 use std::io::{Write, stdin, stdout};
 use std::fmt;
 
+impl fmt::Display for ClauseName {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.as_str())
+    }
+}
+
 impl fmt::Display for FactInstruction {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            &FactInstruction::GetConstant(Level::Shallow, ref constant, ref r) =>
-                write!(f, "get_constant {}, A{}", constant, r.reg_num()),
-            &FactInstruction::GetConstant(Level::Deep, ref constant, ref r) =>
-                write!(f, "get_constant {}, {}", constant, r),
-            &FactInstruction::GetList(Level::Shallow, ref r) =>
-                write!(f, "get_list A{}", r.reg_num()),
-            &FactInstruction::GetList(Level::Deep, ref r) =>
-                write!(f, "get_list {}", r),
-            &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::GetConstant(lvl, ref constant, ref r) =>
+                write!(f, "get_constant {}, {}{}", constant, lvl, r.reg_num()),
+            &FactInstruction::GetList(lvl, ref r) =>
+                write!(f, "get_list {}{}", lvl, r.reg_num()),
+            &FactInstruction::GetStructure(ref ct, ref arity, ref r) =>
+                write!(f, "get_structure {}/{}, {}", ct.name(), arity, r),
             &FactInstruction::GetValue(ref x, ref a) =>
                 write!(f, "get_value {}, A{}", x, a),
             &FactInstruction::GetVariable(ref x, ref a) =>
@@ -51,18 +51,12 @@ impl fmt::Display for QueryInstruction {
         match self {
             &QueryInstruction::GetVariable(ref x, ref a) =>
                 write!(f, "query:get_variable {}, A{}", x, a),
-            &QueryInstruction::PutConstant(Level::Shallow, ref constant, ref r) =>
-                write!(f, "put_constant {}, A{}", constant, r.reg_num()),
-            &QueryInstruction::PutConstant(Level::Deep, ref constant, ref r) =>
-                write!(f, "put_constant {}, {}", constant, r),
-            &QueryInstruction::PutList(Level::Shallow, ref r) =>
-                write!(f, "put_list A{}", r.reg_num()),
-            &QueryInstruction::PutList(Level::Deep, ref r) =>
-                write!(f, "put_list {}", r),
-            &QueryInstruction::PutStructure(Level::Deep, ref name, ref arity, ref r, _) =>
-                write!(f, "put_structure {}/{}, {}", name, arity, r),
-            &QueryInstruction::PutStructure(Level::Shallow, ref name, ref arity, ref r, _) =>
-                write!(f, "put_structure {}/{}, A{}", name, arity, r.reg_num()),
+            &QueryInstruction::PutConstant(lvl, ref constant, ref r) =>
+                write!(f, "put_constant {}, {}{}", constant, lvl, r.reg_num()),
+            &QueryInstruction::PutList(lvl, ref r) =>
+                write!(f, "put_list {}{}", lvl, r.reg_num()),
+            &QueryInstruction::PutStructure(ref ct, ref arity, ref r) =>
+                write!(f, "put_structure {}/{}, {}", ct.name(), arity, r),
             &QueryInstruction::PutUnsafeValue(y, a) =>
                 write!(f, "put_unsafe_value Y{}, A{}", y, a),
             &QueryInstruction::PutValue(ref x, ref a) =>
@@ -382,7 +376,7 @@ impl fmt::Display for CutInstruction {
 impl fmt::Display for Level {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            &Level::Shallow => write!(f, "A"),
+            &Level::Root | &Level::Shallow => write!(f, "A"),
             &Level::Deep => write!(f, "X")
         }
     }
@@ -531,7 +525,7 @@ fn compile_query<'a>(terms: &'a Vec<QueryTerm>, queue: &'a Vec<TopLevel>)
     let mut code = try!(cg.compile_query(terms));
 
     compile_appendix(&mut code, queue)?;
-
+    
     Ok((code, cg.take_vars()))
 }
 
index 600ed11646d7ed3ec55c4b34055d1cfd302d6fce..c29fec66638b45d618c53f9f12d8e9f262672219 100644 (file)
@@ -10,21 +10,31 @@ pub struct QueryIterator<'a> {
 
 impl<'a> QueryIterator<'a> {
     fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
-        self.state_stack.push(TermIterState::to_state(lvl, term));
+        self.state_stack.push(TermIterState::subterm_to_state(lvl, term));
+    }
+
+    fn from_rule_head_clause(terms: &'a Vec<Box<Term>>) -> Self {
+        let state_stack = terms.iter().rev()
+            .map(|bt| TermIterState::subterm_to_state(Level::Shallow, bt.as_ref()))
+            .collect();
+
+        QueryIterator { state_stack }
     }
 
     fn from_term(term: &'a Term) -> Self {
         let state = match term {
             &Term::AnonVar =>
                 return QueryIterator { state_stack: vec![] },
-            &Term::Clause(_, ref name, ref terms, _) =>
-                TermIterState::Clause(0, ClauseType::Root(name), terms),
+            &Term::Clause(ref r, ref name, ref terms, fixity) =>
+                TermIterState::Clause(Level::Root, 0, r,
+                                      ClauseType::from(name.clone(), terms.len(), fixity),
+                                      terms),
             &Term::Cons(..) =>
                 return QueryIterator { state_stack: vec![] },
             &Term::Constant(_, _) =>
                 return QueryIterator { state_stack: vec![] },
             &Term::Var(ref cell, ref var) =>
-                TermIterState::Var(Level::Shallow, cell, var)
+                TermIterState::Var(Level::Root, cell, var)
         };
 
         QueryIterator { state_stack: vec![state] }
@@ -32,87 +42,18 @@ impl<'a> QueryIterator<'a> {
 
     fn new(term: &'a QueryTerm) -> Self {
         match term {
-            &QueryTerm::CallN(ref terms) => {
-                let state = TermIterState::Clause(1, ClauseType::CallN, terms);
-                QueryIterator { state_stack: vec![state] }
-            },
-            &QueryTerm::CallWithInferenceLimit(ref terms) => {
-                let ct    = ClauseType::CallWithInferenceLimit;
-                let state = TermIterState::Clause(0, ct, terms);
-
-                QueryIterator { state_stack: vec![state] }
-            },
-            &QueryTerm::Catch(ref terms) => {
-                let state = TermIterState::Clause(0, ClauseType::Catch, terms);
-                QueryIterator { state_stack: vec![state] }
-            },
-            &QueryTerm::DuplicateTerm(ref terms) => {
-                let state = TermIterState::Clause(0, ClauseType::DuplicateTerm, terms);
-                QueryIterator { state_stack: vec![state] }
-            },
-            &QueryTerm::Arg(ref terms) => {
-                let state = TermIterState::Clause(0, ClauseType::Arg, terms);
-                QueryIterator { state_stack: vec![state] }
-            },
-            &QueryTerm::SetupCallCleanup(ref terms) => {
-                let state = TermIterState::Clause(0, ClauseType::SetupCallCleanup, terms);
-                QueryIterator { state_stack: vec![state] }
-            },
-            &QueryTerm::Eq(ref terms) => {
-                let state = TermIterState::Clause(0, ClauseType::Eq, terms);
-                QueryIterator { state_stack: vec![state] }
-            },
-            &QueryTerm::Functor(ref terms) => {
-                let state = TermIterState::Clause(0, ClauseType::Functor, terms);
-                QueryIterator { state_stack: vec![state] }
-            },
-            &QueryTerm::Display(ref terms) => {
-                let state = TermIterState::Clause(0, ClauseType::Display, terms);
-                QueryIterator { state_stack: vec![state] }
-            },
-            &QueryTerm::Ground(ref terms) => {
-                let state = TermIterState::Clause(0, ClauseType::Ground, terms);
+            &QueryTerm::Clause(ref cell, ClauseType::CallN, ref terms) => {
+                let state = TermIterState::Clause(Level::Root, 1, cell, ClauseType::CallN, terms);
                 QueryIterator { state_stack: vec![state] }
             },
-            &QueryTerm::Inlined(InlinedQueryTerm::CompareNumber(qt, ref terms)) => {
-                let state = TermIterState::Clause(0, ClauseType::CompareNumber(qt), terms);
-                QueryIterator { state_stack: vec![state] }
-            },
-            &QueryTerm::Compare(ref terms) => {
-                let state = TermIterState::Clause(0, ClauseType::Compare, terms);
-                QueryIterator { state_stack: vec![state] }
-            },
-            &QueryTerm::CompareTerm(qt, ref terms) => {
-                let state = TermIterState::Clause(0, ClauseType::CompareTerm(qt), terms);
-                QueryIterator { state_stack: vec![state] }
-            },
-            &QueryTerm::Is(ref terms) => {
-                let state = TermIterState::Clause(0, ClauseType::Is, terms);
-                QueryIterator { state_stack: vec![state] }
-            },
-            &QueryTerm::Inlined(InlinedQueryTerm::IsAtomic(ref terms))
-          | &QueryTerm::Inlined(InlinedQueryTerm::IsInteger(ref terms))
-          | &QueryTerm::Inlined(InlinedQueryTerm::IsVar(ref terms))
-          | &QueryTerm::Inlined(InlinedQueryTerm::IsNonVar(ref terms))
-          | &QueryTerm::Inlined(InlinedQueryTerm::IsFloat(ref terms))
-          | &QueryTerm::Inlined(InlinedQueryTerm::IsRational(ref terms))
-          | &QueryTerm::Inlined(InlinedQueryTerm::IsCompound(ref terms))
-          | &QueryTerm::Inlined(InlinedQueryTerm::IsString(ref terms)) =>
-                Self::from_term(terms[0].as_ref()),
-            &QueryTerm::NotEq(ref terms) => {
-                let state = TermIterState::Clause(0, ClauseType::NotEq, terms);
-                QueryIterator { state_stack: vec![state] }
-            },
-            &QueryTerm::Term(ref term) =>
-                Self::from_term(term),
-            &QueryTerm::Throw(ref term) => {
-                let state = TermIterState::Clause(0, ClauseType::Throw, term);
+            &QueryTerm::Clause(ref cell, ref ct, ref terms) => {
+                let state = TermIterState::Clause(Level::Root, 0, cell, ct.clone(), terms);
                 QueryIterator { state_stack: vec![state] }
             },
             &QueryTerm::Cut => QueryIterator { state_stack: vec![] },
             &QueryTerm::Jump(ref vars) => {
                 let state_stack = vars.iter().rev().map(|t| {
-                    TermIterState::to_state(Level::Shallow, t)
+                    TermIterState::subterm_to_state(Level::Shallow, t)
                 }).collect();
 
                 QueryIterator { state_stack }
@@ -121,12 +62,6 @@ impl<'a> QueryIterator<'a> {
     }
 }
 
-impl QueryTerm {
-    pub fn post_order_iter<'a>(&'a self) -> QueryIterator<'a> {
-        QueryIterator::new(self)
-    }
-}
-
 impl<'a> Iterator for QueryIterator<'a> {
     type Item = TermRef<'a>;
 
@@ -135,25 +70,30 @@ impl<'a> Iterator for QueryIterator<'a> {
             match iter_state {
                 TermIterState::AnonVar(lvl) =>
                     return Some(TermRef::AnonVar(lvl)),
-                TermIterState::Clause(child_num, ct, child_terms) => {
+                TermIterState::Clause(lvl, child_num, cell, ct, child_terms) => {
                     if child_num == child_terms.len() {
                         match ct {
                             ClauseType::CallN =>
                                 self.push_subterm(Level::Shallow, child_terms[0].as_ref()),
-                            ClauseType::Deep(..) =>
-                                return Some(TermRef::Clause(ct, child_terms)),
+                            ClauseType::Named(..) | ClauseType::Op(..) =>
+                                return match lvl {
+                                    Level::Root => None,
+                                    lvl => Some(TermRef::Clause(lvl, cell, ct, child_terms))
+                                },
                             _ =>
                                 return None
                         };
                     } else {
-                        self.state_stack.push(TermIterState::Clause(child_num + 1, ct, child_terms));
-                        self.push_subterm(ct.level_of_subterms(), child_terms[child_num].as_ref());
+                        self.state_stack.push(TermIterState::Clause(lvl, child_num + 1,
+                                                                    cell, ct, child_terms));
+                        self.push_subterm(lvl.child_level(), child_terms[child_num].as_ref());
                     }
                 },
                 TermIterState::InitialCons(lvl, cell, head, tail) => {
                     self.state_stack.push(TermIterState::FinalCons(lvl, cell, head, tail));
-                    self.push_subterm(Level::Deep, tail);
-                    self.push_subterm(Level::Deep, head);
+
+                    self.push_subterm(lvl.child_level(), tail);
+                    self.push_subterm(lvl.child_level(), head);
                 },
                 TermIterState::FinalCons(lvl, cell, head, tail) =>
                     return Some(TermRef::Cons(lvl, cell, head, tail)),
@@ -174,24 +114,31 @@ pub struct FactIterator<'a> {
 
 impl<'a> FactIterator<'a> {
     fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
-        self.state_queue.push_back(TermIterState::to_state(lvl, term));
+        self.state_queue.push_back(TermIterState::subterm_to_state(lvl, term));
+    }
+
+    pub fn from_rule_head_clause(terms: &'a Vec<Box<Term>>) -> Self {
+        let state_queue = terms.iter()
+            .map(|bt| TermIterState::subterm_to_state(Level::Shallow, bt.as_ref()))
+            .collect();
+
+        FactIterator { state_queue }
     }
 
-    fn new(term: &'a Term) -> FactIterator<'a> {
+    fn new(term: &'a Term) -> Self {
         let states = match term {
             &Term::AnonVar =>
-                vec![TermIterState::AnonVar(Level::Shallow)],
-            &Term::Clause(.., ref name, ref terms, _) =>
-                vec![TermIterState::Clause(0, ClauseType::Root(name), terms)],
+                vec![TermIterState::AnonVar(Level::Root)],
+            &Term::Clause(ref cell, ref name, ref terms, fixity) => {
+                let ct = ClauseType::from(name.clone(), terms.len(), fixity);
+                vec![TermIterState::Clause(Level::Root, 0, cell, ct, terms)]
+            },
             &Term::Cons(ref cell, ref head, ref tail) =>
-                vec![TermIterState::InitialCons(Level::Shallow,
-                                                cell,
-                                                head.as_ref(),
-                                                tail.as_ref())],
+                vec![TermIterState::InitialCons(Level::Root, cell, head.as_ref(), tail.as_ref())],
             &Term::Constant(ref cell, ref constant) =>
-                vec![TermIterState::Constant(Level::Shallow, cell, constant)],
+                vec![TermIterState::Constant(Level::Root, cell, constant)],
             &Term::Var(ref cell, ref var) =>
-                vec![TermIterState::Var(Level::Shallow, cell, var)]
+                vec![TermIterState::Var(Level::Root, cell, var)]
         };
 
         FactIterator { state_queue: VecDeque::from(states) }
@@ -206,16 +153,14 @@ impl<'a> Iterator for FactIterator<'a> {
             match state {
                 TermIterState::AnonVar(lvl) =>
                     return Some(TermRef::AnonVar(lvl)),
-                TermIterState::Clause(_, ct, child_terms) => {
+                TermIterState::Clause(lvl, _, cell, ct, child_terms) => {
                     for child_term in child_terms {
-                        self.push_subterm(ct.level_of_subterms(), child_term);
+                        self.push_subterm(lvl.child_level(), child_term);
                     }
 
-                    match ct {
-                        ClauseType::Deep(..) =>
-                            return Some(TermRef::Clause(ct, child_terms)),
-                        _ =>
-                            continue
+                    match lvl {
+                        Level::Root => continue,
+                        _ => return Some(TermRef::Clause(lvl, cell, ct, child_terms))
                     };
                 },
                 TermIterState::InitialCons(lvl, cell, head, tail) => {
@@ -246,10 +191,32 @@ impl Term {
     }
 }
 
+pub enum ChunkedTerm<'a> {
+    HeadClause(ClauseName, &'a Vec<Box<Term>>),
+    BodyTerm(&'a QueryTerm)
+}
+
+impl QueryTerm {
+    pub fn post_order_iter<'a>(&'a self) -> QueryIterator<'a> {
+        QueryIterator::new(self)
+    }
+}
+
+impl<'a> ChunkedTerm<'a> {
+    pub fn post_order_iter(&self) -> QueryIterator<'a> {
+        match self {
+            &ChunkedTerm::BodyTerm(ref qt) =>
+                QueryIterator::new(qt),
+            &ChunkedTerm::HeadClause(_, terms) =>
+                QueryIterator::from_rule_head_clause(terms)
+        }
+    }
+}
+
 pub struct ChunkedIterator<'a>
 {
-    term_loc: GenContext,
-    iter: Box<Iterator<Item=&'a QueryTerm> + 'a>,
+    pub chunk_num: usize,
+    iter: Box<Iterator<Item=ChunkedTerm<'a>> + 'a>,
     deep_cut_encountered: bool
 }
 
@@ -258,19 +225,19 @@ impl<'a> ChunkedIterator<'a>
     pub fn from_term_sequence(terms: &'a [QueryTerm]) -> Self
     {
         ChunkedIterator {
-            term_loc: GenContext::Last(0),
-            iter: Box::new(terms.iter()),
+            chunk_num: 0,
+            iter: Box::new(terms.iter().map(|t| ChunkedTerm::BodyTerm(t))),
             deep_cut_encountered: false
         }
     }
 
     pub fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec<QueryTerm>) -> Self
     {
-        let inner_iter = Box::new(once(p1));
-        let iter = inner_iter.chain(clauses.iter());
+        let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1)));
+        let iter = inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t)));
 
         ChunkedIterator {
-            term_loc: GenContext::Last(0),
+            chunk_num: 0,
             iter: Box::new(iter),
             deep_cut_encountered: false
         }
@@ -278,14 +245,14 @@ impl<'a> ChunkedIterator<'a>
 
     pub fn from_rule(rule: &'a Rule) -> Self
     {
-        let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
+        let &Rule { head: (ref name, ref args, ref p1), ref clauses } = rule;
 
-        let iter = once(p0);
-        let inner_iter = Box::new(once(p1));
-        let iter = iter.chain(inner_iter.chain(clauses.iter()));
+        let iter = once(ChunkedTerm::HeadClause(name.clone(), args));
+        let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1)));
+        let iter = iter.chain(inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t))));
 
         ChunkedIterator {
-            term_loc: GenContext::Head,
+            chunk_num: 0,
             iter: Box::new(iter),
             deep_cut_encountered: false,
         }
@@ -295,15 +262,7 @@ impl<'a> ChunkedIterator<'a>
         self.deep_cut_encountered
     }
 
-    pub fn at_rule_head(&self) -> bool {
-        self.term_loc == GenContext::Head
-    }
-
-    pub fn chunk_num(&self) -> usize {
-        self.term_loc.chunk_num()
-    }
-
-    fn take_chunk(&mut self, term: &'a QueryTerm) -> (usize, usize, Vec<&'a QueryTerm>)
+    fn take_chunk(&mut self, term: ChunkedTerm<'a>) -> (usize, usize, Vec<ChunkedTerm<'a>>)
     {
         let mut arity  = 0;
         let mut item   = Some(term);
@@ -311,81 +270,39 @@ impl<'a> ChunkedIterator<'a>
 
         while let Some(term) = item {
             match term {
-                &QueryTerm::Jump(ref vars) => {
+                ChunkedTerm::HeadClause(..) =>
+                    result.push(term),
+                ChunkedTerm::BodyTerm(&QueryTerm::Jump(ref vars)) => {
                     result.push(term);
                     arity = vars.len();
                     break;
                 },
-                &QueryTerm::CompareTerm(..) => {
-                    result.push(term);
-                    arity = 2;
-                    break;
-                },
-                &QueryTerm::Term(ref inner_term) =>
-                    if let GenContext::Head = self.term_loc {
-                        result.push(term);
-                        self.term_loc = GenContext::Last(0);
-                    } else {
-                        result.push(term);
-
-                        if inner_term.is_callable() {
-                            arity = inner_term.arity();
-                            break;
-                        }
-                    },
-                &QueryTerm::SetupCallCleanup(_) | &QueryTerm::Compare(_) => {
-                    result.push(term);
-                    arity = 3;
-                    break;
-                },
-                &QueryTerm::CallN(ref child_terms) => {
-                    result.push(term);
-                    arity = child_terms.len() + 1;
-                    break;
-                },
-                &QueryTerm::Catch(ref child_terms)
-              | &QueryTerm::Throw(ref child_terms) => {
+                ChunkedTerm::BodyTerm(&QueryTerm::Cut) => {
                     result.push(term);
-                    arity = child_terms.len();
-                    break;
-                },
-                &QueryTerm::Ground(_) | &QueryTerm::Display(_) => {
-                    result.push(term);
-                    arity = 1;
-                    break;
+
+                    if self.chunk_num > 0 {
+                        self.deep_cut_encountered = true;
+                    }
                 },
-                &QueryTerm::Arg(_)
-              | &QueryTerm::Functor(_)
-              | &QueryTerm::CallWithInferenceLimit(_) => {
+                ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::Inlined(_), _)) =>
+                    result.push(term),                
+                ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::CallN, ref subterms)) => {
                     result.push(term);
-                    arity = 3;
+                    arity = subterms.len() + 1;
                     break;
                 },
-                &QueryTerm::Eq(_) | &QueryTerm::NotEq(_)
-              | &QueryTerm::Is(_) | &QueryTerm::DuplicateTerm(_) => {
+                ChunkedTerm::BodyTerm(qt) => {
                     result.push(term);
-                    arity = 2;
+                    arity = qt.arity();
                     break;
-                },
-                &QueryTerm::Inlined(_) =>
-                    result.push(term),
-                &QueryTerm::Cut => {
-                    result.push(term);
-
-                    if self.term_loc.chunk_num() > 0 {
-                        self.deep_cut_encountered = true;
-                    }
-                },
+                }
             };
 
             item = self.iter.next();
         }
 
-        let chunk_num = self.term_loc.chunk_num();
-
-        if let &mut GenContext::Last(ref mut chunk_num) = &mut self.term_loc {
-            *chunk_num += 1;
-        }
+        let chunk_num = self.chunk_num;
+        self.chunk_num += 1;
 
         (chunk_num, arity, result)
     }
@@ -394,7 +311,7 @@ impl<'a> ChunkedIterator<'a>
 impl<'a> Iterator for ChunkedIterator<'a>
 {
     // the chunk number, last term arity, and vector of references.
-    type Item = (usize, usize, Vec<&'a QueryTerm>);
+    type Item = (usize, usize, Vec<ChunkedTerm<'a>>);
 
     fn next(&mut self) -> Option<Self::Item> {
         self.iter.next().map(|term| self.take_chunk(term))
index 8368984db526f04f34882aebf8318e4cfef7a824..55e5fcc88921a742b03fa07af44edbe8b3c34a82 100644 (file)
@@ -185,7 +185,7 @@ pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
 
 pub(crate) trait CallPolicy: Any {
     fn try_call(&mut self, machine_st: &mut MachineState, code_dir: &CodeDir,
-                name: TabledRc<Atom>, arity: usize)
+                name: ClauseName, arity: usize)
                 -> CallResult
     {
         let compiled_tl_index = code_dir.get(&(name, arity)).map(|index| index.1);
@@ -204,7 +204,7 @@ pub(crate) trait CallPolicy: Any {
     }
 
     fn try_execute(&mut self, machine_st: &mut MachineState, code_dir: &CodeDir,
-                   name: TabledRc<Atom>, arity: usize)
+                   name: ClauseName, arity: usize)
                    -> CallResult
     {
         let compiled_tl_index = code_dir.get(&(name, arity)).map(|index| index.1);
@@ -351,20 +351,19 @@ pub(crate) struct DefaultCallPolicy {}
 
 impl CallPolicy for DefaultCallPolicy {}
 
-pub(crate) struct CallWithInferenceLimitCallPolicy {
-    atom_tbl: TabledData<Atom>,
+pub(crate) struct CallWithInferenceLimitCallPolicy {    
     pub(crate) prev_policy: Box<CallPolicy>,
     count:  BigUint,
     limits: Vec<(BigUint, usize)>
 }
 
 impl CallWithInferenceLimitCallPolicy {
-    pub(crate) fn new_in_place(atom_tbl: TabledData<Atom>, policy: &mut Box<CallPolicy>)
+    pub(crate) fn new_in_place(policy: &mut Box<CallPolicy>)
     {
         let mut prev_policy: Box<CallPolicy> = Box::new(DefaultCallPolicy {});
         swap(&mut prev_policy, policy);
 
-        let new_policy = CallWithInferenceLimitCallPolicy { atom_tbl, prev_policy,
+        let new_policy = CallWithInferenceLimitCallPolicy { prev_policy,
                                                             count:  BigUint::zero(),
                                                             limits: vec![] };
         *policy = Box::new(new_policy);
@@ -373,15 +372,13 @@ impl CallWithInferenceLimitCallPolicy {
     fn increment(&mut self) -> CallResult {
         if let Some(&(ref limit, bp)) = self.limits.last() {
             if self.count == *limit {
-                return Err(functor!(self.atom_tbl,
-                                    "inference_limit_exceeded",
-                                    1,
+                return Err(functor!("inference_limit_exceeded", 1,
                                     [HeapCellValue::Addr(Addr::Con(Constant::Usize(bp)))]));
             } else {
                 self.count += BigUint::one();
             }
         }
-
+        
         Ok(())
     }
 
@@ -422,7 +419,7 @@ impl CallWithInferenceLimitCallPolicy {
 
 impl CallPolicy for CallWithInferenceLimitCallPolicy {
     fn try_call(&mut self, machine_st: &mut MachineState, code_dir: &CodeDir,
-                name: TabledRc<Atom>, arity: usize)
+                name: ClauseName, arity: usize)
                 -> CallResult
     {
         self.prev_policy.try_call(machine_st, code_dir, name, arity)?;
@@ -430,7 +427,7 @@ impl CallPolicy for CallWithInferenceLimitCallPolicy {
     }
 
     fn try_execute(&mut self, machine_st: &mut MachineState, code_dir: &CodeDir,
-                   name: TabledRc<Atom>, arity: usize)
+                   name: ClauseName, arity: usize)
                    -> CallResult
     {
         self.prev_policy.try_execute(machine_st, code_dir, name, arity)?;
index ca2c2827bcba359c0969c613b50869a8a07ac17f..5d5059bf64641678472149850036a7d5df27c95f 100644 (file)
@@ -269,13 +269,7 @@ impl MachineState {
 
                 match item {
                     Addr::Con(Constant::Number(n)) => Ok(n),
-                    _ => {
-                        let atom_tbl = self.atom_tbl.clone();
-                        Err(functor!(self.atom_tbl,
-                                     "instantiation_error",
-                                     1,
-                                     [heap_atom!("(is)/2", atom_tbl)]))
-                    }
+                    _ => Err(functor!("instantiation_error", 1, [heap_atom!("(is)/2")]))
                 }
             },
             &ArithmeticTerm::Interm(i)     => Ok(self.interms[i-1].clone()),
@@ -292,10 +286,7 @@ impl MachineState {
                 if let Some(r) = Ratio::from_float(fl.into_inner()) {
                     Ok(Rc::new(r))
                 } else {
-                    Err(functor!(self.atom_tbl,
-                                 "instantiation_error",
-                                 1,
-                                 [heap_atom!("(is)/2", self.atom_tbl)]))
+                    Err(functor!("instantiation_error", 1, [heap_atom!("(is)/2")]))
                 },
             Number::Integer(bi) =>
                 Ok(Rc::new(Ratio::from_integer((*bi).clone())))
@@ -316,9 +307,7 @@ impl MachineState {
 
     fn arith_eval_by_metacall(&self, r: RegType) -> Result<Number, Vec<HeapCellValue>>
     {
-        let instantiation_err = functor!(self.atom_tbl.clone(), "instantiation_error", 1,
-                                         [heap_atom!("(is)/2", self.atom_tbl.clone())]);
-
+        let instantiation_err = functor!("instantiation_error", 1, [heap_atom!("(is)/2")]);
         let a = self[r].clone();
 
         if let &Addr::Con(Constant::Number(ref n)) = &a {
@@ -378,8 +367,7 @@ impl MachineState {
             -> Result<Rc<Ratio<BigInt>>, Vec<HeapCellValue>>
     {
         if *r2 == Ratio::zero() {
-            Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
-                         [heap_atom!("zero_divisor", self.atom_tbl.clone())]))
+            Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
         } else {
             Ok(Rc::new(&*r1 / &*r2))
         }
@@ -390,13 +378,11 @@ impl MachineState {
         match (n1, n2) {
             (Number::Integer(n1), Number::Integer(n2)) =>
                 if *n2 == BigInt::zero() {
-                    Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
-                                 [heap_atom!("zero_divisor", self.atom_tbl.clone())]))
+                    Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
                 } else {
                     Ok(Rc::new(n1.div_floor(&n2)))
                 },
-            _ => Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
-                              [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+            _ => Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
         }
     }
 
@@ -405,22 +391,19 @@ impl MachineState {
         match (n1, n2) {
             (Number::Integer(n1), Number::Integer(n2)) =>
                 if *n2 == BigInt::zero() {
-                    Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
-                                 [heap_atom!("zero_divisor", self.atom_tbl.clone())]))
+                    Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
                 } else {
                     Ok(Rc::new(&*n1 / &*n2))
                 },
             _ =>
-                Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
-                             [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+                Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
         }
     }
 
     fn div(&self, n1: Number, n2: Number) -> Result<Number, Vec<HeapCellValue>>
     {
         if n2.is_zero() {
-            Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
-                         [heap_atom!("zero_divisor", self.atom_tbl.clone())]))
+            Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
         } else {
             Ok(n1 / n2)
         }
@@ -435,8 +418,7 @@ impl MachineState {
                     _        => Ok(Rc::new(&*n1 >> usize::max_value()))
                 },
             _ =>
-                Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
-                             [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+                Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
         }
     }
 
@@ -449,8 +431,7 @@ impl MachineState {
                     _        => Ok(Rc::new(&*n1 << usize::max_value()))
                 },
             _ =>
-                Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
-                             [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+                Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
         }
     }
 
@@ -460,8 +441,7 @@ impl MachineState {
             (Number::Integer(n1), Number::Integer(n2)) =>
                 Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 ^ u_n2)),
             _ =>
-                Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
-                             [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+                Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
         }
     }
 
@@ -471,8 +451,7 @@ impl MachineState {
             (Number::Integer(n1), Number::Integer(n2)) =>
                 Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 & u_n2)),
             _ =>
-                Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
-                             [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+                Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
         }
     }
 
@@ -481,14 +460,12 @@ impl MachineState {
         match (n1, n2) {
             (Number::Integer(n1), Number::Integer(n2)) =>
                 if *n2 == BigInt::zero() {
-                    Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
-                                 [heap_atom!("zero_divisor", self.atom_tbl.clone())]))
+                    Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
                 } else {
                     Ok(Rc::new(n1.mod_floor(&n2)))
                 },
             _ =>
-                Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
-                             [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+                Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
         }
     }
 
@@ -497,14 +474,12 @@ impl MachineState {
         match (n1, n2) {
             (Number::Integer(n1), Number::Integer(n2)) =>
                 if *n2 == BigInt::zero() {
-                    Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
-                                 [heap_atom!("zero_divisor", self.atom_tbl.clone())]))
+                    Err(functor!("evaluation_error", 1, [heap_atom!("zero_divisor")]))
                 } else {
                     Ok(Rc::new(&*n1 % &*n2))
                 },
             _ =>
-                Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
-                             [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+                Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
         }
     }
 
@@ -514,8 +489,7 @@ impl MachineState {
             (Number::Integer(n1), Number::Integer(n2)) =>
                 Ok(self.signed_bitwise_op(&*n1, &*n2, |u_n1, u_n2| u_n1 & u_n2)),
             _ =>
-                Err(functor!(self.atom_tbl.clone(), "evaluation_error", 1,
-                             [heap_atom!("expected_integer_args", self.atom_tbl.clone())]))
+                Err(functor!("evaluation_error", 1, [heap_atom!("expected_integer_args")]))
         }
     }
 
@@ -661,15 +635,15 @@ impl MachineState {
                     _ => self.fail = true
                 };
             },
-            &FactInstruction::GetStructure(_, ref name, arity, reg, fixity) => {
+            &FactInstruction::GetStructure(ref ct, arity, reg) => {
                 let addr = self.deref(self[reg].clone());
 
                 match self.store(addr.clone()) {
                     Addr::Str(a) => {
                         let result = &self.heap[a];
 
-                        if let &HeapCellValue::NamedStr(narity, ref str, _) = result {
-                            if narity == arity && *name == *str {
+                        if let &HeapCellValue::NamedStr(narity, ref s, _) = result {
+                            if narity == arity && ct.name() == *s {
                                 self.s = a + 1;
                                 self.mode = MachineMode::Read;
                             } else {
@@ -681,7 +655,7 @@ impl MachineState {
                         let h = self.heap.h;
 
                         self.heap.push(HeapCellValue::Addr(Addr::Str(h + 1)));
-                        self.heap.push(HeapCellValue::NamedStr(arity, name.clone(), fixity));
+                        self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.fixity()));
 
                         self.bind(addr.as_var().unwrap(), Addr::HeapCell(h));
 
@@ -858,10 +832,10 @@ impl MachineState {
                 self[reg] = Addr::Con(constant.clone()),
             &QueryInstruction::PutList(_, reg) =>
                 self[reg] = Addr::Lis(self.heap.h),
-            &QueryInstruction::PutStructure(_, ref name, arity, reg, fixity) => {
+            &QueryInstruction::PutStructure(ref ct, arity, reg) => {
                 let h = self.heap.h;
 
-                self.heap.push(HeapCellValue::NamedStr(arity, name.clone(), fixity));
+                self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.fixity()));
                 self[reg] = Addr::Str(h);
             },
             &QueryInstruction::PutUnsafeValue(n, arg) => {
@@ -979,11 +953,8 @@ impl MachineState {
 
                 if let HeapCellValue::NamedStr(narity, name, _) = result {
                     if narity + arity > 63 {
-                        let atom_tbl = self.atom_tbl.clone();
-                        self.throw_exception(functor!(atom_tbl,
-                                                      "representation_error",
-                                                      1,
-                                                      [heap_atom!("exceeds_max_arity", atom_tbl)]));
+                        self.throw_exception(functor!("representation_error", 1,
+                                                      [heap_atom!("exceeds_max_arity")]));
                         return None;
                     }
 
@@ -1003,16 +974,12 @@ impl MachineState {
             },
             Addr::Con(Constant::Atom(name)) => (name, 0),
             Addr::HeapCell(_) | Addr::StackCell(_, _) => {
-                let atom_tbl = self.atom_tbl.clone();
-                self.throw_exception(functor!(atom_tbl, "instantiation_error", 0, []));
+                self.throw_exception(functor!("instantiation_error"));
                 return None;
             },
             _ => {
-                let atom_tbl = self.atom_tbl.clone();
-                self.throw_exception(functor!(atom_tbl,
-                                              "type_error",
-                                              2,
-                                              [heap_atom!("callable", atom_tbl),
+                self.throw_exception(functor!("type_error", 2,
+                                              [heap_atom!("callable"),
                                                HeapCellValue::Addr(addr)]));
                 return None;
             }
@@ -1065,10 +1032,7 @@ impl MachineState {
                     _ => self.fail = true
                 };
             } else {
-                return Err(functor!(self.atom_tbl,
-                                    "type_error",
-                                    1,
-                                    [heap_atom!("compound_expected", self.atom_tbl)]));
+                return Err(functor!("type_error", 1, [heap_atom!("compound_expected")]))
             }
         }
 
@@ -1201,7 +1165,7 @@ impl MachineState {
                         return Ordering::Less;
                     } else if ar1 > ar2 {
                         return Ordering::Greater;
-                    } else if *n1 != *n2 {
+                    } else if n1 != n2 {
                         return n1.cmp(&n2);
                     } else {
                         continue;
@@ -1210,14 +1174,14 @@ impl MachineState {
                     continue,
                 (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::NamedStr(ar, n, _))
               | (HeapCellValue::NamedStr(ar, n, _), HeapCellValue::Addr(Addr::Lis(_))) =>
-                    if ar == 2 && *n == "." {
+                    if ar == 2 && n.as_str() == "." {
                         continue;
                     } else if ar < 2 {
                         return Ordering::Greater;
                     } else if ar > 2 {
                         return Ordering::Less;
                     } else {
-                        return n.cmp(&String::from("."));
+                        return n.as_str().cmp(".");
                     },
                 (HeapCellValue::NamedStr(..), _) =>
                     return Ordering::Greater,
@@ -1356,8 +1320,7 @@ impl MachineState {
                 let a2 = self.store(self.deref(self[r2].clone()));
 
                 if call_policy.downcast_ref::<CallWithInferenceLimitCallPolicy>().is_err() {
-                    CallWithInferenceLimitCallPolicy::new_in_place(self.atom_tbl.clone(),
-                                                                   call_policy);
+                    CallWithInferenceLimitCallPolicy::new_in_place(call_policy);
                 }
 
                 self.p += 1;
@@ -1373,13 +1336,7 @@ impl MachineState {
                             None => panic!("install_inference_counter: should have installed \\
                                             CallWithInferenceLimitCallPolicy.")
                         },
-                    _ => {
-                        let atom_tbl = self.atom_tbl.clone();
-                        self.throw_exception(functor!(atom_tbl,
-                                                      "type_error",
-                                                      1,
-                                                      [heap_atom!("integer_expected", atom_tbl)]))
-                    }
+                    _ => self.throw_exception(functor!("type_error", 1, [heap_atom!("integer_expected")]))
                 };
             },
             &BuiltInInstruction::IsAtomic(r) => {
@@ -1634,10 +1591,10 @@ impl MachineState {
 
                         self.unify(a1, f_a);
                     } else {
-                        return Err(functor!(self.atom_tbl, "instantiation_error", 0, []));
+                        return Err(functor!("instantiation_error"));
                     }
                 } else {
-                    return Err(functor!(self.atom_tbl, "instantiation_error", 0, []));
+                    return Err(functor!("instantiation_error"));
                 }
             },
             _ => {
@@ -1681,7 +1638,7 @@ impl MachineState {
         for (v1, v2) in iter {
             match (v1, v2) {
                 (HeapCellValue::NamedStr(ar1, n1, _), HeapCellValue::NamedStr(ar2, n2, _)) =>
-                    if ar1 != ar2 || *n1 != *n2 {
+                    if ar1 != ar2 || n1 != n2 {
                         return true;
                     },
                 (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) =>
@@ -1710,7 +1667,7 @@ impl MachineState {
         for (v1, v2) in iter {
             match (v1, v2) {
                 (HeapCellValue::NamedStr(ar1, n1, _), HeapCellValue::NamedStr(ar2, n2, _)) =>
-                    if ar1 != ar2 || *n1 != *n2 {
+                    if ar1 != ar2 || n1 != n2 {
                         return true;
                     },
                 (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) =>
index e6b9da4670e4deff30a59082d9b94f39873ece11..0d012eb75c23c77c89fc4f477a33b97a58394dd1 100644 (file)
@@ -46,7 +46,7 @@ impl Index<CodePtr> for Machine {
 impl Machine {
     pub fn new() -> Self {
         let atom_tbl = Rc::new(RefCell::new(HashSet::new()));
-        let (code, code_dir, op_dir) = build_code_dir(atom_tbl.clone());
+        let (code, code_dir, op_dir) = build_code_dir();
 
         Machine {
             ms: MachineState::new(atom_tbl),
@@ -67,7 +67,7 @@ impl Machine {
         self.ms.atom_tbl.clone()
     }
 
-    pub fn add_user_code<'a>(&mut self, name: TabledRc<Atom>, arity: usize, mut code: Code)
+    pub fn add_user_code<'a>(&mut self, name: ClauseName, arity: usize, mut code: Code)
                              -> EvalSession<'a>
     {
         match self.code_dir.get(&(name.clone(), arity)) {
@@ -165,8 +165,7 @@ impl Machine {
 
     fn query_stepper<'a>(&mut self)
     {
-        loop
-        {
+        loop {
             self.execute_instr();
 
             if self.failed() {
@@ -180,10 +179,8 @@ impl Machine {
         }
     }
 
-    fn record_var_places<'a>(&self,
-                             chunk_num: usize,
-                             alloc_locs: &AllocVarDict<'a>,
-                             heap_locs: &mut HeapVarDict<'a>)
+    fn record_var_places<'a>(&self, chunk_num: usize,
+                             alloc_locs: &AllocVarDict<'a>, heap_locs: &mut HeapVarDict<'a>)
     {
         for (var, var_data) in alloc_locs {
             match var_data {
index 20469d64852f94b723e7d10dcce097164316e4ec..4dc1e785477e16155c097ea860b766ff1628adca 100644 (file)
@@ -1,3 +1,9 @@
+macro_rules! clause_name {
+    ($name: expr) => (
+        ClauseName::BuiltIn($name)
+    )
+}
+
 macro_rules! tabled_rc {
     ($e:expr, $tbl:expr) => (
         TabledRc::new(String::from($e), $tbl.clone())
@@ -6,7 +12,10 @@ macro_rules! tabled_rc {
 
 macro_rules! atom {
     ($e:expr, $tbl:expr) => (
-        Constant::Atom(tabled_rc!($e, $tbl))
+        Constant::Atom(ClauseName::User(tabled_rc!($e, $tbl)))
+    );
+    ($e:expr) => (
+        Constant::Atom(clause_name!($e))
     )
 }
 
@@ -47,22 +56,21 @@ macro_rules! query {
 }
 
 macro_rules! heap_atom {
+    ($name:expr) => (
+        HeapCellValue::Addr(Addr::Con(atom!($name)))
+    );
     ($name:expr, $tbl:expr) => (
         HeapCellValue::Addr(Addr::Con(atom!($name, $tbl)))
     )
 }
 
 macro_rules! functor {
-    ($tbl:expr, $name:expr, $len:expr, [$($args:expr),*]) => {{
-        if $len > 0 {
-            vec![ HeapCellValue::NamedStr($len,
-                                          tabled_rc!($name, $tbl),
-                                          None),
-                  $($args),* ]
-        } else {
-            vec![ heap_atom!($name, $tbl) ]
-        }
-    }}
+    ($name:expr) => (
+        vec![ heap_atom!($name) ]
+    );
+    ($name:expr, $len:expr, [$($args:expr),*]) => (
+        vec![ HeapCellValue::NamedStr($len, clause_name!($name), None), $($args),* ]
+    )
 }
 
 macro_rules! fact {
@@ -115,8 +123,11 @@ macro_rules! put_var {
 }
 
 macro_rules! put_structure {
-    ($tbl:expr, $lvl:expr, $name:expr, $arity:expr, $r:expr, $fix:expr) => (
-        QueryInstruction::PutStructure($lvl, tabled_rc!($name, $tbl), $arity, $r, $fix)
+    ($atom:expr, $arity:expr, $r:expr, Some($fix:expr)) => (
+        QueryInstruction::PutStructure(ClauseType::Op(clause_name!($atom), $fix), $arity, $r)
+    );
+    ($atom:expr, $arity:expr, $r:expr, None) => (
+        QueryInstruction::PutStructure(ClauseType::Named(clause_name!($atom)), $arity, $r)
     )
 }
 
@@ -368,12 +379,11 @@ macro_rules! get_constant {
 }
 
 macro_rules! get_structure {
-    ($tbl:expr, $atom:expr, $arity:expr, $r:expr, $fix:expr) => (
-        FactInstruction::GetStructure(Level::Shallow,
-                                      tabled_rc!($atom, $tbl),
-                                      $arity,
-                                      $r,
-                                      $fix)
+    ($atom:expr, $arity:expr, $r:expr, Some($fix:expr)) => (
+        FactInstruction::GetStructure(ClauseType::Op(clause_name!($atom), $fix), $arity, $r)
+    );
+    ($atom:expr, $arity:expr, $r:expr, None) => (
+        FactInstruction::GetStructure(ClauseType::Named(clause_name!($atom)), $arity, $r)
     )
 }
 
index cd115d7a6781a59003f0d52451319ae68988e785..5b74536d6edfc55c943f77c72a99ad00dcbd96c4 160000 (submodule)
@@ -1 +1 @@
-Subproject commit cd115d7a6781a59003f0d52451319ae68988e785
+Subproject commit 5b74536d6edfc55c943f77c72a99ad00dcbd96c4
index dc8f719463e5a8dbebb625ec16deb1f41bd56642..09d253a4fd9ebfe3e823d0180ec5081bf839f05f 100644 (file)
@@ -1,4 +1,5 @@
 use std::cell::RefCell;
+use std::cmp::Ordering;
 use std::collections::HashSet;
 use std::fmt;
 use std::hash::{Hash, Hasher};
@@ -6,13 +7,27 @@ use std::ops::Deref;
 use std::rc::Rc;
 
 pub type TabledData<T> = Rc<RefCell<HashSet<Rc<T>>>>;
-    
+
 #[derive(Clone)]
 pub struct TabledRc<T: Hash + Eq> {
     atom: Rc<T>,
     table: TabledData<T>
 }
 
+impl<T: Ord + Hash + Eq> PartialOrd for TabledRc<T> {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering>
+    {
+        Some(self.atom.cmp(&other.atom))
+    }
+}
+
+impl<T: Ord + Hash + Eq> Ord for TabledRc<T> {
+    fn cmp(&self, other: &Self) -> Ordering
+    {
+        self.atom.cmp(&other.atom)
+    }
+}
+
 impl<T: Hash + Eq> PartialEq for TabledRc<T> {
     fn eq(&self, other: &TabledRc<T>) -> bool
     {
@@ -23,9 +38,8 @@ impl<T: Hash + Eq> PartialEq for TabledRc<T> {
 impl<T: Hash + Eq> Eq for TabledRc<T> {}
 
 impl<T: Hash + Eq> Hash for TabledRc<T> {
-    fn hash<H: Hasher>(&self, state: &mut H)
-    {
-        self.atom.hash(state)        
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.atom.hash(state)
     }
 }
 
@@ -40,10 +54,6 @@ impl<T: Hash + Eq> TabledRc<T> {
 
         TabledRc { atom, table }
     }
-
-    pub fn table(&self) -> TabledData<T> {
-        self.table.clone()
-    }
 }
 
 impl<T: Hash + Eq> Drop for TabledRc<T> {
index 783c502ecd926517e029d93a3ccb8c2c2aa3795b..9999c42905d730a1c2a3f0b40dc985c2e36f257a 100644 (file)
@@ -1,6 +1,5 @@
 use prolog::ast::*;
 use prolog::iterators::*;
-use prolog::tabled_rc::*;
 
 pub trait CompilationTarget<'a> {
     type Iterator : Iterator<Item=TermRef<'a>>;
@@ -9,7 +8,7 @@ pub trait CompilationTarget<'a> {
 
     fn to_constant(Level, Constant, RegType) -> Self;
     fn to_list(Level, RegType) -> Self;
-    fn to_structure(Level, TabledRc<Atom>, usize, RegType, Option<Fixity>) -> Self;
+    fn to_structure(ClauseType, usize, RegType) -> Self;
 
     fn to_void(usize) -> Self;
     fn is_void_instr(&self) -> bool;
@@ -40,11 +39,9 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
         FactInstruction::GetConstant(lvl, constant, reg)
     }
 
-    fn to_structure(lvl: Level, atom: TabledRc<Atom>, arity: usize,
-                    reg: RegType, fixity: Option<Fixity>)
-                    -> Self
+    fn to_structure(ct: ClauseType, arity: usize, reg: RegType) -> Self
     {
-        FactInstruction::GetStructure(lvl, atom, arity, reg, fixity)
+        FactInstruction::GetStructure(ct, arity, reg)
     }
 
     fn to_list(lvl: Level, reg: RegType) -> Self {
@@ -105,11 +102,9 @@ impl<'a> CompilationTarget<'a> for QueryInstruction {
         term.post_order_iter()
     }
 
-    fn to_structure(lvl: Level, atom: TabledRc<Atom>, arity: usize,
-                    reg: RegType, fixity: Option<Fixity>)
-                    -> Self
+    fn to_structure(ct: ClauseType, arity: usize, r: RegType) -> Self
     {
-        QueryInstruction::PutStructure(lvl, atom, arity, reg, fixity)
+        QueryInstruction::PutStructure(ct, arity, r)
     }
 
     fn to_constant(lvl: Level, constant: Constant, reg: RegType) -> Self {
index b443515bb19ddbd42252d1ff04eb2a951eff812f..b6b227df9ecaf290b97363b1d21f3c71e48702b4 100644 (file)
@@ -672,8 +672,8 @@ fn test_queries_on_call_n()
 {
     let mut wam = Machine::new();
 
-    submit(&mut wam, "maplist(Pred, []).
-                      maplist(Pred, [X|Xs]) :- call(Pred, X), maplist(Pred, Xs).");
+    submit(&mut wam, "maplist(_, []).
+                      maplist(P, [X|Xs]) :- call(P, X), maplist(P, Xs).");
     submit(&mut wam, "f(a). f(b). f(c).");
 
     assert_prolog_success!(&mut wam, "?- maplist(f, [X,Y,Z]).",