From: Mark Thom Date: Sun, 12 Nov 2017 01:57:23 +0000 (-0700) Subject: eliminate QueryTermRef. X-Git-Tag: v0.8.110~672 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=e5a235cf80c5b1431f3d302046712e372e3a9f35;p=scryer-prolog.git eliminate QueryTermRef. --- diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index 9e6b493e..2dd8acba 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -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 } @@ -378,33 +381,6 @@ impl<'a> TermRef<'a> { } } -#[derive(Clone, Copy)] -pub enum QueryTermRef<'a> { - CallN(&'a Vec>), - Catch(&'a Vec>), - Cut, - Is(&'a Vec>), - IsAtomic(&'a Term), - IsVar(&'a Term), - Term(&'a Term), - Throw(&'a Vec>) -} - -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(_)) => diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index 6d281c27..0fb1a53e 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -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) } diff --git a/src/prolog/fixtures.rs b/src/prolog/fixtures.rs index 1d40ce29..240bf57c 100644 --- a/src/prolog/fixtures.rs +++ b/src/prolog/fixtures.rs @@ -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 = (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(&mut self, - iter: Iter, - last_term_arity: usize, - term_loc: GenContext) + pub fn mark_vars_in_chunk(&mut self, iter: Iter, lt_arity: usize, term_loc: GenContext) where Iter: Iterator> { 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) { + fn record_unsafe_vars(&self, unsafe_vars: &mut HashMap) { 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) - { + { 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); } diff --git a/src/prolog/iterators.rs b/src/prolog/iterators.rs index 24af15b6..e61a6d5f 100644 --- a/src/prolog/iterators.rs +++ b/src/prolog/iterators.rs @@ -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> + 'a>, + iter: Box + '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) -> 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>) - -> (usize, usize, Vec>) + 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>); + type Item = (usize, usize, Vec<&'a QueryTerm>); fn next(&mut self) -> Option { - self.iter.next().map(|term| self.take_chunk(term, Vec::new())) + self.iter.next().map(|term| self.take_chunk(term)) } } diff --git a/src/prolog/machine.rs b/src/prolog/machine.rs index f22f3ba8..41d58e9d 100644 --- a/src/prolog/machine.rs +++ b/src/prolog/machine.rs @@ -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, 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; diff --git a/src/prolog/parser b/src/prolog/parser index ebecfec0..f01fe4fe 160000 --- a/src/prolog/parser +++ b/src/prolog/parser @@ -1 +1 @@ -Subproject commit ebecfec050bb67730274fd07be94982cdf33321b +Subproject commit f01fe4feab95bd50a3aefab448f540be5888a296