]> Repositorios git - scryer-prolog.git/commitdiff
eliminate QueryTermRef.
authorMark Thom <[email protected]>
Sun, 12 Nov 2017 01:57:23 +0000 (18:57 -0700)
committerMark Thom <[email protected]>
Sun, 12 Nov 2017 01:57:23 +0000 (18:57 -0700)
src/prolog/ast.rs
src/prolog/codegen.rs
src/prolog/fixtures.rs
src/prolog/iterators.rs
src/prolog/machine.rs
src/prolog/parser

index 9e6b493ef5c2688b8f8a3bdb2e1c7fbf2df192b4..2dd8acbab25a95090afda93716bb1041b7488175 100644 (file)
@@ -39,24 +39,34 @@ pub enum PredicateClause {
 }
 
 impl PredicateClause {
-    pub fn name(&self) -> &Atom {
+    pub fn first_arg(&self) -> Option<&Term> {
         match self {
-            &PredicateClause::Fact(ref t) => t.name().unwrap(),
-            &PredicateClause::Rule(ref rule) => rule.head.0.name().unwrap()
+            &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
+                }
         }
     }
 
-    pub fn first_arg(&self) -> Option<&Term> {
+    pub fn arity(&self) -> usize {
         match self {
-            &PredicateClause::Fact(ref t) => t.first_arg(),
-            &PredicateClause::Rule(ref rule) => rule.head.0.first_arg()
+            &PredicateClause::Fact(ref term) => term.arity(),
+            &PredicateClause::Rule(ref rule) => rule.head.0.arity()
         }
     }
 
-    pub fn arity(&self) -> usize {
+    pub fn name(&self) -> Option<&Atom> {
         match self {
-            &PredicateClause::Fact(ref t) => t.arity(),
-            &PredicateClause::Rule(ref rule) => rule.head.0.arity()
+            &PredicateClause::Fact(ref term) => term.name(),
+            &PredicateClause::Rule(ref rule) =>
+                if let &QueryTerm::Term(ref term) = &rule.head.0 {
+                    term.name()
+                } else {
+                    None
+                }
         }
     }
 }
@@ -217,6 +227,7 @@ pub enum ParserError
     IncompleteReduction,
     InconsistentDeclaration,
     InconsistentPredicate,
+    InvalidRuleHead,
     ParseBigInt,
     ParseFloat(ParseFloatError),
     // TokenTooLong,
@@ -310,30 +321,22 @@ pub enum QueryTerm {
 }
 
 impl QueryTerm {
-    pub fn to_ref(&self) -> QueryTermRef {
+    pub fn arity(&self) -> usize {
         match self {
-            &QueryTerm::CallN(ref terms) =>
-                QueryTermRef::CallN(terms),
-            &QueryTerm::Catch(ref terms) =>
-                QueryTermRef::Catch(terms),
-            &QueryTerm::Cut =>
-                QueryTermRef::Cut,
-            &QueryTerm::Is(ref terms) =>
-                QueryTermRef::Is(terms),
-            &QueryTerm::IsAtomic(ref terms) =>
-                QueryTermRef::IsAtomic(terms.first().unwrap()),
-            &QueryTerm::IsVar(ref terms) =>
-                QueryTermRef::IsVar(terms.first().unwrap()),
-            &QueryTerm::Term(ref term) =>
-                QueryTermRef::Term(term),
-            &QueryTerm::Throw(ref t) =>
-                QueryTermRef::Throw(t)
+            &QueryTerm::Catch(_) => 3,
+            &QueryTerm::Throw(_) => 1,
+            &QueryTerm::Is(_) => 2,
+            &QueryTerm::IsAtomic(_) => 1,
+            &QueryTerm::IsVar(_) => 1,
+            &QueryTerm::CallN(ref terms) => terms.len(),
+            &QueryTerm::Cut => 0,
+            &QueryTerm::Term(ref term) => term.arity(),
         }
     }
 }
 
 pub struct Rule {
-    pub head: (Term, QueryTerm),
+    pub head: (QueryTerm, QueryTerm),
     pub clauses: Vec<QueryTerm>
 }
 
@@ -378,33 +381,6 @@ impl<'a> TermRef<'a> {
     }
 }
 
-#[derive(Clone, Copy)]
-pub enum QueryTermRef<'a> {
-    CallN(&'a Vec<Box<Term>>),
-    Catch(&'a Vec<Box<Term>>),
-    Cut,
-    Is(&'a Vec<Box<Term>>),
-    IsAtomic(&'a Term),
-    IsVar(&'a Term),
-    Term(&'a Term),
-    Throw(&'a Vec<Box<Term>>)
-}
-
-impl<'a> QueryTermRef<'a> {
-    pub fn arity(self) -> usize {
-        match self {
-            QueryTermRef::Catch(_) => 3,
-            QueryTermRef::Throw(_) => 1,
-            QueryTermRef::Is(_) => 2,
-            QueryTermRef::IsAtomic(_) => 1,
-            QueryTermRef::IsVar(_) => 1,
-            QueryTermRef::CallN(terms) => terms.len(),
-            QueryTermRef::Cut => 0,
-            QueryTermRef::Term(term) => term.arity(),
-        }
-    }
-}
-
 pub enum ChoiceInstruction {
     RetryMeElse(usize),
     TrustMe,
@@ -826,14 +802,6 @@ impl Term {
         }
     }
 
-    pub fn is_clause(&self) -> bool {
-        if let &Term::Clause(_, _, _) = self {
-            true
-        } else {
-            false
-        }
-    }
-
     pub fn is_callable(&self) -> bool {
         match self {
             &Term::Clause(_, _, _) | &Term::Constant(_, Constant::Atom(_)) =>
index 6d281c2767cf643d988a39882d2d001c2b76d332..0fb1a53e9867e99065b561ed4e26f8c872a2f827 100644 (file)
@@ -181,8 +181,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
         let mut vs = VariableFixtures::new();
         let at_rule_head = iter.at_rule_head();
 
-        while let Some((chunk_num, last_term_arity, terms)) = iter.next() {
-            for (i, term_or_cut_ref) in terms.iter().enumerate() {
+        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 {
@@ -191,10 +191,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                     GenContext::Last(chunk_num)
                 };
 
-                self.update_var_count(term_or_cut_ref.post_order_iter());
-                vs.mark_vars_in_chunk(term_or_cut_ref.post_order_iter(),
-                                      last_term_arity,
-                                      term_loc);
+                self.update_var_count(query_term.post_order_iter());
+                vs.mark_vars_in_chunk(query_term.post_order_iter(), lt_arity, term_loc);
             }
         }
 
@@ -209,26 +207,26 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
         ConjunctInfo::new(vs, num_of_chunks, has_deep_cut)
     }
 
-    fn add_conditional_call(compiled_query: &mut Code, qt: QueryTermRef, pvs: usize)
+    fn add_conditional_call(compiled_query: &mut Code, qt: &QueryTerm, pvs: usize)
     {
         match qt {
-            QueryTermRef::CallN(terms) => {
+            &QueryTerm::CallN(ref terms) => {
                 let call = ControlInstruction::CallN(terms.len());
                 compiled_query.push(Line::Control(call));
             },
-            QueryTermRef::Catch(_) =>
+            &QueryTerm::Catch(_) =>
                 compiled_query.push(Line::Control(ControlInstruction::CatchCall)),
-            QueryTermRef::IsAtomic(_) | QueryTermRef::IsVar(_) =>
+            &QueryTerm::IsAtomic(_) | &QueryTerm::IsVar(_) =>
                 compiled_query.push(proceed!()),
-            QueryTermRef::Term(&Term::Constant(_, Constant::Atom(ref atom))) => {
+            &QueryTerm::Term(Term::Constant(_, Constant::Atom(ref atom))) => {
                 let call = ControlInstruction::Call(atom.clone(), 0, pvs);
                 compiled_query.push(Line::Control(call));
             },
-            QueryTermRef::Term(&Term::Clause(_, ref atom, ref terms)) => {
+            &QueryTerm::Term(Term::Clause(_, ref atom, ref terms)) => {
                 let call = ControlInstruction::Call(atom.clone(), terms.len(), pvs);
                 compiled_query.push(Line::Control(call));
             },
-            QueryTermRef::Throw(_) =>
+            &QueryTerm::Throw(_) =>
                 compiled_query.push(Line::Control(ControlInstruction::ThrowCall)),
             _ => {}
         }
@@ -276,22 +274,21 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                     GenContext::Last(chunk_num)
                 };
 
-                match term {
-                    &QueryTermRef::Cut if i + 1 < terms.len() => {
-                        code.push(if chunk_num == 0 {
-                            Line::Cut(CutInstruction::NeckCut(Terminal::Non))
+                match *term {
+                    &QueryTerm::Cut => {
+                        let term = if i + 1 < terms.len() {
+                            Terminal::Non
                         } else {
-                            Line::Cut(CutInstruction::Cut(Terminal::Non))
-                        });
-                    },
-                    &QueryTermRef::Cut => {
+                            Terminal::Terminal
+                        };
+
                         code.push(if chunk_num == 0 {
-                            Line::Cut(CutInstruction::NeckCut(Terminal::Terminal))
+                            Line::Cut(CutInstruction::NeckCut(term))
                         } else {
-                            Line::Cut(CutInstruction::Cut(Terminal::Terminal))
+                            Line::Cut(CutInstruction::Cut(term))
                         });
                     },
-                    &QueryTermRef::Is(terms) => {
+                    &QueryTerm::Is(ref terms) => {
                         let mut arith_code = {
                             let mut evaluator = ArithmeticEvaluator::new(self.marker.bindings());
                              evaluator.eval(terms[1].as_ref())?
@@ -335,8 +332,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                             }
                         }
                     },
-                    &QueryTermRef::IsAtomic(inner_term) =>
-                        match inner_term {
+                    &QueryTerm::IsAtomic(ref inner_term) =>
+                        match inner_term[0].as_ref() {
                             &Term::AnonVar | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => {
                                 code.push(fail!());
                             },
@@ -361,8 +358,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                                     }
                                 },
                         },
-                    &QueryTermRef::IsVar(inner_term) =>
-                        match inner_term {
+                    &QueryTerm::IsVar(ref inner_term) =>
+                        match inner_term[0].as_ref() {
                             &Term::Constant(_, _) | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => {
                                 code.push(fail!());
                             },
@@ -392,11 +389,11 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
 
                         let iter = term.post_order_iter();
                         code.push(Line::Query(self.compile_target(iter, term_loc, is_exposed)));
-                        Self::add_conditional_call(code, *term, conjunct_info.perm_vars());
+                        Self::add_conditional_call(code, term, conjunct_info.perm_vars());
                     },
                     _ => {
                         let num_vars = conjunct_info.perm_vs.vars_above_threshold(i + 1);
-                        self.compile_query_line(*term, term_loc, code, num_vars, is_exposed);
+                        self.compile_query_line(term, term_loc, code, num_vars, is_exposed);
                     },
                 };
 
@@ -420,11 +417,11 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
         }
     }
 
-    fn compile_cleanup(code: &mut Code, conjunct_info: &ConjunctInfo, toc: QueryTermRef<'a>)
+    fn compile_cleanup(code: &mut Code, conjunct_info: &ConjunctInfo, toc: &'a QueryTerm)
     {
         //TODO: temporary workaround for inlined builtins.
         match toc {
-            QueryTermRef::IsAtomic(_) | QueryTermRef::IsVar(_) =>
+            &QueryTerm::IsAtomic(_) | &QueryTerm::IsVar(_) =>
                 code.push(proceed!()),
             _ => {}
         }
@@ -447,28 +444,32 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
         self.marker.advance(GenContext::Head, p0.arity());
         self.compile_seq_prelude(&conjunct_info, &mut code);
 
-        if p0.is_clause() {
-            let iter = FactInstruction::iter(p0);
-            code.push(Line::Fact(self.compile_target(iter, GenContext::Head, false)));
-        }
-
-        let iter = ChunkedIterator::from_rule_body(p1, clauses);
-        try!(self.compile_seq(iter, &conjunct_info, &mut code, false));
+        if let &QueryTerm::Term(ref term) = p0 {            
+            if let &Term::Clause(_, _, _) = term {
+                let iter = FactInstruction::iter(term);
+                code.push(Line::Fact(self.compile_target(iter, GenContext::Head, 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(p0, query);
+                if let &mut Line::Query(ref mut query) = &mut code[index] {
+                    conjunct_info.perm_vs.mark_unsafe_vars_in_rule(term, query);
+                }
             }
-        }
 
-        Self::compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1).to_ref());
-        Ok(code)
+            Self::compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1));
+            Ok(code)
+        } else {
+            Err(ParserError::InvalidRuleHead)
+        }        
     }
 
     fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact)
@@ -512,7 +513,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
 
         let mut code = Vec::new();
 
-        if term.is_clause() {
+        if let &Term::Clause(_, _, _) = term {
             let iter = FactInstruction::iter(term);
             let mut compiled_fact = self.compile_target(iter, GenContext::Head, false);
 
@@ -525,7 +526,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
     }
 
     fn compile_query_line(&mut self,
-                          term: QueryTermRef<'a>,
+                          term: &'a QueryTerm,
                           term_loc: GenContext,
                           code: &mut Code,
                           index: usize,
@@ -564,7 +565,10 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
             }
         }
 
-        Self::compile_cleanup(&mut code, &conjunct_info, query.last().unwrap().to_ref());
+        if let Some(query_term) = query.last() {
+            Self::compile_cleanup(&mut code, &conjunct_info, query_term);
+        }
+        
         Ok(code)
     }
 
index 1d40ce29d6d951b693ea239aaae3e76b47e95dd4..240bf57cd337e5e998e68224b49a777ef0ecefb1 100644 (file)
@@ -60,7 +60,7 @@ impl TempVarData {
 
     fn populate_conflict_set(&mut self) {
         if self.last_term_arity > 0 {
-            let arity = self.last_term_arity;            
+            let arity = self.last_term_arity;
             let mut conflict_set : BTreeSet<usize> = (1..arity).collect();
 
             for &(_, reg) in self.use_set.iter() {
@@ -171,10 +171,7 @@ impl<'a> VariableFixtures<'a>
         var_count
     }
 
-    pub fn mark_vars_in_chunk<Iter>(&mut self,
-                                    iter: Iter,
-                                    last_term_arity: usize,                                    
-                                    term_loc: GenContext)
+    pub fn mark_vars_in_chunk<Iter>(&mut self, iter: Iter, lt_arity: usize, term_loc: GenContext)
         where Iter: Iterator<Item=TermRef<'a>>
     {
         let chunk_num = term_loc.chunk_num();
@@ -183,8 +180,7 @@ impl<'a> VariableFixtures<'a>
         for term_ref in iter {
             if let TermRef::Var(lvl, cell, var) = term_ref {
                 let mut status = self.0.remove(var)
-                    .unwrap_or((VarStatus::Temp(chunk_num, TempVarData::new(last_term_arity)),
-                                Vec::new()));
+                    .unwrap_or((VarStatus::Temp(chunk_num, TempVarData::new(lt_arity)), Vec::new()));
 
                 status.1.push(cell);
 
@@ -217,7 +213,7 @@ impl<'a> VariableFixtures<'a>
     pub fn size(&self) -> usize {
         self.0.len()
     }
-    
+
     pub fn set_perm_vals(&self, has_deep_cuts: bool)
     {
         let mut values_vec : Vec<_> = self.values()
@@ -268,7 +264,7 @@ impl<'a> VariableFixtures<'a>
         }
     }
 
-    fn record_unsafe_vars(&self, unsafe_vars: &mut HashMap<RegType, bool>) {        
+    fn record_unsafe_vars(&self, unsafe_vars: &mut HashMap<RegType, bool>) {
         for &(_, ref cb) in self.values() {
             match cb.first() {
                 Some(index) => {
@@ -278,9 +274,9 @@ impl<'a> VariableFixtures<'a>
             };
         }
     }
-    
+
     fn mark_head_vars_as_safe(&self, head: &Term, unsafe_vars: &mut HashMap<RegType, bool>)
-    {                
+    {
         for term_ref in head.breadth_first_iter() {
             match term_ref {
                 TermRef::Var(_, cell, _) => {
@@ -297,12 +293,12 @@ impl<'a> VariableFixtures<'a>
         self.record_unsafe_vars(&mut unsafe_vars);
         self.mark_unsafe_vars(&mut unsafe_vars, query);
     }
-    
+
     pub fn mark_unsafe_vars_in_rule(&self, head: &Term, query: &mut CompiledQuery)
     {
         let mut unsafe_vars = HashMap::new();
 
-        self.record_unsafe_vars(&mut unsafe_vars);        
+        self.record_unsafe_vars(&mut unsafe_vars);
         self.mark_head_vars_as_safe(head, &mut unsafe_vars);
         self.mark_unsafe_vars(&mut unsafe_vars, query);
     }
index 24af15b6adba6664fb128feba4951f532e33f28d..e61a6d5fd4a6849f42020f6ecdf041831265a825 100644 (file)
@@ -41,33 +41,35 @@ impl<'a> QueryIterator<'a> {
         QueryIterator { state_stack: vec![state] }
     }
 
-    fn new(term: QueryTermRef<'a>) -> Self {
+    fn new(term: &'a QueryTerm) -> Self {
         match term {
-            QueryTermRef::CallN(terms) => {
+            &QueryTerm::CallN(ref terms) => {
                 let state = IteratorState::Clause(1, ClauseType::CallN, terms);
                 QueryIterator { state_stack: vec![state] }
             },
-            QueryTermRef::Catch(terms) => {
+            &QueryTerm::Catch(ref terms) => {
                 let state = IteratorState::Clause(0, ClauseType::Catch, terms);
                 QueryIterator { state_stack: vec![state] }
             },
-            QueryTermRef::Is(terms) => {
+            &QueryTerm::Is(ref terms) => {
                 let state = IteratorState::Clause(0, ClauseType::Is, terms);
                 QueryIterator { state_stack: vec![state] }
             },
-            QueryTermRef::IsAtomic(term) | QueryTermRef::IsVar(term) | QueryTermRef::Term(term) =>
+            &QueryTerm::IsAtomic(ref terms) | &QueryTerm::IsVar(ref terms) =>
+                Self::from_term(terms[0].as_ref()),
+            &QueryTerm::Term(ref term) =>
                 Self::from_term(term),
-            QueryTermRef::Throw(term) => {
+            &QueryTerm::Throw(ref term) => {
                 let state = IteratorState::Clause(0, ClauseType::Throw, term);
                 QueryIterator { state_stack: vec![state] }
             },
-            QueryTermRef::Cut => QueryIterator { state_stack: vec![] }
+            &QueryTerm::Cut => QueryIterator { state_stack: vec![] }
         }
     }
 }
 
-impl<'a> QueryTermRef<'a> {
-    pub fn post_order_iter(self) -> QueryIterator<'a> {
+impl QueryTerm {
+    pub fn post_order_iter<'a>(&'a self) -> QueryIterator<'a> {
         QueryIterator::new(self)
     }
 }
@@ -183,7 +185,7 @@ impl<'a> Iterator for FactIterator<'a> {
 
 impl Term {
     pub fn post_order_iter(&self) -> QueryIterator {
-        QueryIterator::new(QueryTermRef::Term(self))
+        QueryIterator::from_term(self)
     }
 
     pub fn breadth_first_iter(&self) -> FactIterator {
@@ -194,7 +196,7 @@ impl Term {
 pub struct ChunkedIterator<'a>
 {
     term_loc: GenContext,
-    iter: Box<Iterator<Item=QueryTermRef<'a>> + 'a>,
+    iter: Box<Iterator<Item=&'a QueryTerm> + 'a>,
     deep_cut_encountered: bool
 }
 
@@ -202,20 +204,18 @@ impl<'a> ChunkedIterator<'a>
 {
     pub fn from_term_sequence(terms: &'a [QueryTerm]) -> Self
     {
-        let iter = terms.iter().map(|c| c.to_ref());
-
         ChunkedIterator {
             term_loc: GenContext::Last(0),
-            iter: Box::new(iter),
+            iter: Box::new(terms.iter()),
             deep_cut_encountered: false
         }
     }
 
     pub fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec<QueryTerm>) -> Self
     {
-        let inner_iter = Box::new(once(p1.to_ref()));
-        let iter = inner_iter.chain(clauses.iter().map(|c| c.to_ref()));
-
+        let inner_iter = Box::new(once(p1));
+        let iter = inner_iter.chain(clauses.iter());
+        
         ChunkedIterator {
             term_loc: GenContext::Last(0),
             iter: Box::new(iter),
@@ -227,15 +227,15 @@ impl<'a> ChunkedIterator<'a>
     {
         let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
 
-        let iter = once(QueryTermRef::Term(p0));
-        let inner_iter = Box::new(once(p1.to_ref()));
-        let iter = iter.chain(inner_iter.chain(clauses.iter().map(|c| c.to_ref())));
+        let iter = once(p0);
+        let inner_iter = Box::new(once(p1));
+        let iter = iter.chain(inner_iter.chain(clauses.iter()));
 
         ChunkedIterator {
             term_loc: GenContext::Head,
             iter: Box::new(iter),
-            deep_cut_encountered: false
-        }
+            deep_cut_encountered: false,
+        }        
     }
 
     pub fn encountered_deep_cut(&self) -> bool {
@@ -250,48 +250,44 @@ impl<'a> ChunkedIterator<'a>
         self.term_loc.chunk_num()
     }
 
-    fn take_chunk(&mut self, term: QueryTermRef<'a>, mut result: Vec<QueryTermRef<'a>>)
-                  -> (usize, usize, Vec<QueryTermRef<'a>>)
+    fn take_chunk(&mut self, term: &'a QueryTerm) -> (usize, usize, Vec<&'a QueryTerm>)
     {
         let mut arity  = 0;
         let mut item   = Some(term);
-
+        let mut result = Vec::new();
+        
         while let Some(term) = item {
             match term {
-                //TODO: This can refer to the term at the head of a
-                // goal, not technically a QueryTerm (ie. a term in a
-                // query).  Think of a better name.
-                QueryTermRef::Term(inner_term) => {
+                &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;
                         }
-                    }
-                },
-                QueryTermRef::CallN(child_terms) => {
+                    },                
+                &QueryTerm::CallN(ref child_terms) => {
                     result.push(term);
                     arity = child_terms.len() + 1;
                     break;
                 },
-                QueryTermRef::Catch(child_terms) | QueryTermRef::Throw(child_terms) => {
+                &QueryTerm::Catch(ref child_terms) | &QueryTerm::Throw(ref child_terms) => {
                     result.push(term);
                     arity = child_terms.len();
                     break;
                 },
-                QueryTermRef::Is(_) => {
+                &QueryTerm::Is(_) => {
                     result.push(term);
                     arity = 2;
                     break;
                 },
-                QueryTermRef::IsAtomic(_) | QueryTermRef::IsVar(_) =>
+                &QueryTerm::IsAtomic(_) | &QueryTerm::IsVar(_) =>
                     result.push(term),
-                QueryTermRef::Cut => {
+                &QueryTerm::Cut => {
                     result.push(term);
 
                     if self.term_loc.chunk_num() > 0 {
@@ -316,9 +312,9 @@ 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<QueryTermRef<'a>>);
+    type Item = (usize, usize, Vec<&'a QueryTerm>);
 
     fn next(&mut self) -> Option<Self::Item> {
-        self.iter.next().map(|term| self.take_chunk(term, Vec::new()))
+        self.iter.next().map(|term| self.take_chunk(term))
     }
 }
index f22f3ba85f5299189f4682792caac0b734e0d8bc..41d58e9d409000c52b0ceff15b87f2c0f03883b2 100644 (file)
@@ -239,44 +239,52 @@ impl Machine {
 
     pub fn add_fact<'a>(&mut self, fact: &Term, mut code: Code) -> EvalSession<'a>
     {
-        if let Some(name) = fact.name() {
-            let p = self.code.len();
+        match fact {
+            &Term::Clause(_, ref name, _) | &Term::Constant(_, Constant::Atom(ref name)) => {
+                let p = self.code.len();
+                let arity = fact.arity();
 
-            let name  = name.clone();
-            let arity = fact.arity();
-
-            self.code.append(&mut code);
-            self.add_user_code(name, arity, p)
-        } else {
-            EvalSession::NamelessEntry
+                self.code.append(&mut code);
+                self.add_user_code(name.clone(), arity, p)
+            },
+            _ => EvalSession::NamelessEntry
         }
     }
 
     pub fn add_rule<'a>(&mut self, rule: &Rule, mut code: Code) -> EvalSession<'a>
     {
-        if let Some(name) = rule.head.0.name() {
-            let p = self.code.len();
+        match &rule.head.0 {
+            &QueryTerm::Term(Term::Clause(_, ref name, _))
+          | &QueryTerm::Term(Term::Constant(_, Constant::Atom(ref name))) => {
+                let p = self.code.len();
 
-            let name  = name.clone();
-            let arity = rule.head.0.arity();
+                let name  = name.clone();
+                let arity = rule.head.0.arity();
 
-            self.code.append(&mut code);
-            self.add_user_code(name, arity, p)
-        } else {
-            EvalSession::NamelessEntry
+                self.code.append(&mut code);
+                self.add_user_code(name, arity, p)
+            },
+            _ => EvalSession::NamelessEntry
         }
     }
 
     pub fn add_predicate<'a>(&mut self, clauses: &Vec<PredicateClause>, mut code: Code)
-        -> EvalSession<'a>
+                             -> EvalSession<'a>
     {
         let p = self.code.len();
 
-        let arity = clauses.first().unwrap().arity();
-        let name  = clauses.first().unwrap().name().clone();
+        if let Some(ref clause) = clauses.first() {
+            if let Some(name) = clause.name() {
+                let arity = clause.arity();
 
-        self.code.append(&mut code);
-        self.add_user_code(name, arity, p)
+                self.code.append(&mut code);
+                self.add_user_code(name.clone(), arity, p)
+            } else {
+                EvalSession::NamelessEntry
+            }
+        } else {
+            EvalSession::ImpermissibleEntry(String::from("predicate must have clauses."))
+        }
     }
 
     fn cached_query_size(&self) -> usize {
@@ -1516,15 +1524,15 @@ impl MachineState {
                     } else {
                         0
                     };
-                                       
+
                     if and_gi <= or_fr.global_index {
                         self.e = or_fr.e;
-                    }                    
+                    }
                 }
 
                 if self.e + 1 < self.and_stack.len() {
                     let index = self.e + 1;
-                    
+
                     self.and_stack[index].e  = self.e;
                     self.and_stack[index].cp = self.cp;
 
index ebecfec050bb67730274fd07be94982cdf33321b..f01fe4feab95bd50a3aefab448f540be5888a296 160000 (submodule)
@@ -1 +1 @@
-Subproject commit ebecfec050bb67730274fd07be94982cdf33321b
+Subproject commit f01fe4feab95bd50a3aefab448f540be5888a296