eliminate QueryTermRef.

This commit is contained in:
Mark Thom
2017-11-11 18:57:23 -07:00
parent 1f19d5de95
commit e5a235cf80
6 changed files with 170 additions and 198 deletions

View File

@@ -39,26 +39,36 @@ pub enum PredicateClause {
} }
impl PredicateClause { impl PredicateClause {
pub fn name(&self) -> &Atom {
match self {
&PredicateClause::Fact(ref t) => t.name().unwrap(),
&PredicateClause::Rule(ref rule) => rule.head.0.name().unwrap()
}
}
pub fn first_arg(&self) -> Option<&Term> { pub fn first_arg(&self) -> Option<&Term> {
match self { match self {
&PredicateClause::Fact(ref t) => t.first_arg(), &PredicateClause::Fact(ref term) => term.first_arg(),
&PredicateClause::Rule(ref rule) => rule.head.0.first_arg() &PredicateClause::Rule(ref rule) =>
if let &QueryTerm::Term(ref term) = &rule.head.0 {
term.first_arg()
} else {
None
}
} }
} }
pub fn arity(&self) -> usize { pub fn arity(&self) -> usize {
match self { match self {
&PredicateClause::Fact(ref t) => t.arity(), &PredicateClause::Fact(ref term) => term.arity(),
&PredicateClause::Rule(ref rule) => rule.head.0.arity() &PredicateClause::Rule(ref rule) => rule.head.0.arity()
} }
} }
pub fn name(&self) -> Option<&Atom> {
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
}
}
}
} }
pub enum Declaration { pub enum Declaration {
@@ -217,6 +227,7 @@ pub enum ParserError
IncompleteReduction, IncompleteReduction,
InconsistentDeclaration, InconsistentDeclaration,
InconsistentPredicate, InconsistentPredicate,
InvalidRuleHead,
ParseBigInt, ParseBigInt,
ParseFloat(ParseFloatError), ParseFloat(ParseFloatError),
// TokenTooLong, // TokenTooLong,
@@ -310,30 +321,22 @@ pub enum QueryTerm {
} }
impl QueryTerm { impl QueryTerm {
pub fn to_ref(&self) -> QueryTermRef { pub fn arity(&self) -> usize {
match self { match self {
&QueryTerm::CallN(ref terms) => &QueryTerm::Catch(_) => 3,
QueryTermRef::CallN(terms), &QueryTerm::Throw(_) => 1,
&QueryTerm::Catch(ref terms) => &QueryTerm::Is(_) => 2,
QueryTermRef::Catch(terms), &QueryTerm::IsAtomic(_) => 1,
&QueryTerm::Cut => &QueryTerm::IsVar(_) => 1,
QueryTermRef::Cut, &QueryTerm::CallN(ref terms) => terms.len(),
&QueryTerm::Is(ref terms) => &QueryTerm::Cut => 0,
QueryTermRef::Is(terms), &QueryTerm::Term(ref term) => term.arity(),
&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)
} }
} }
} }
pub struct Rule { pub struct Rule {
pub head: (Term, QueryTerm), pub head: (QueryTerm, QueryTerm),
pub clauses: Vec<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 { pub enum ChoiceInstruction {
RetryMeElse(usize), RetryMeElse(usize),
TrustMe, 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 { pub fn is_callable(&self) -> bool {
match self { match self {
&Term::Clause(_, _, _) | &Term::Constant(_, Constant::Atom(_)) => &Term::Clause(_, _, _) | &Term::Constant(_, Constant::Atom(_)) =>

View File

@@ -181,8 +181,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
let mut vs = VariableFixtures::new(); let mut vs = VariableFixtures::new();
let at_rule_head = iter.at_rule_head(); let at_rule_head = iter.at_rule_head();
while let Some((chunk_num, last_term_arity, terms)) = iter.next() { while let Some((chunk_num, lt_arity, terms)) = iter.next() {
for (i, term_or_cut_ref) in terms.iter().enumerate() { for (i, query_term) in terms.iter().enumerate() {
let term_loc = if chunk_num == 0 && i == 0 && at_rule_head { let term_loc = if chunk_num == 0 && i == 0 && at_rule_head {
GenContext::Head GenContext::Head
} else if i < terms.len() - 1 { } else if i < terms.len() - 1 {
@@ -191,10 +191,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
GenContext::Last(chunk_num) GenContext::Last(chunk_num)
}; };
self.update_var_count(term_or_cut_ref.post_order_iter()); self.update_var_count(query_term.post_order_iter());
vs.mark_vars_in_chunk(term_or_cut_ref.post_order_iter(), vs.mark_vars_in_chunk(query_term.post_order_iter(), lt_arity, term_loc);
last_term_arity,
term_loc);
} }
} }
@@ -209,26 +207,26 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
ConjunctInfo::new(vs, num_of_chunks, has_deep_cut) 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 { match qt {
QueryTermRef::CallN(terms) => { &QueryTerm::CallN(ref terms) => {
let call = ControlInstruction::CallN(terms.len()); let call = ControlInstruction::CallN(terms.len());
compiled_query.push(Line::Control(call)); compiled_query.push(Line::Control(call));
}, },
QueryTermRef::Catch(_) => &QueryTerm::Catch(_) =>
compiled_query.push(Line::Control(ControlInstruction::CatchCall)), compiled_query.push(Line::Control(ControlInstruction::CatchCall)),
QueryTermRef::IsAtomic(_) | QueryTermRef::IsVar(_) => &QueryTerm::IsAtomic(_) | &QueryTerm::IsVar(_) =>
compiled_query.push(proceed!()), 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); let call = ControlInstruction::Call(atom.clone(), 0, pvs);
compiled_query.push(Line::Control(call)); 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); let call = ControlInstruction::Call(atom.clone(), terms.len(), pvs);
compiled_query.push(Line::Control(call)); compiled_query.push(Line::Control(call));
}, },
QueryTermRef::Throw(_) => &QueryTerm::Throw(_) =>
compiled_query.push(Line::Control(ControlInstruction::ThrowCall)), compiled_query.push(Line::Control(ControlInstruction::ThrowCall)),
_ => {} _ => {}
} }
@@ -276,22 +274,21 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
GenContext::Last(chunk_num) GenContext::Last(chunk_num)
}; };
match term { match *term {
&QueryTermRef::Cut if i + 1 < terms.len() => { &QueryTerm::Cut => {
code.push(if chunk_num == 0 { let term = if i + 1 < terms.len() {
Line::Cut(CutInstruction::NeckCut(Terminal::Non)) Terminal::Non
} else { } else {
Line::Cut(CutInstruction::Cut(Terminal::Non)) Terminal::Terminal
};
code.push(if chunk_num == 0 {
Line::Cut(CutInstruction::NeckCut(term))
} else {
Line::Cut(CutInstruction::Cut(term))
}); });
}, },
&QueryTermRef::Cut => { &QueryTerm::Is(ref terms) => {
code.push(if chunk_num == 0 {
Line::Cut(CutInstruction::NeckCut(Terminal::Terminal))
} else {
Line::Cut(CutInstruction::Cut(Terminal::Terminal))
});
},
&QueryTermRef::Is(terms) => {
let mut arith_code = { let mut arith_code = {
let mut evaluator = ArithmeticEvaluator::new(self.marker.bindings()); let mut evaluator = ArithmeticEvaluator::new(self.marker.bindings());
evaluator.eval(terms[1].as_ref())? evaluator.eval(terms[1].as_ref())?
@@ -335,8 +332,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
} }
} }
}, },
&QueryTermRef::IsAtomic(inner_term) => &QueryTerm::IsAtomic(ref inner_term) =>
match inner_term { match inner_term[0].as_ref() {
&Term::AnonVar | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => { &Term::AnonVar | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => {
code.push(fail!()); code.push(fail!());
}, },
@@ -361,8 +358,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
} }
}, },
}, },
&QueryTermRef::IsVar(inner_term) => &QueryTerm::IsVar(ref inner_term) =>
match inner_term { match inner_term[0].as_ref() {
&Term::Constant(_, _) | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => { &Term::Constant(_, _) | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => {
code.push(fail!()); code.push(fail!());
}, },
@@ -392,11 +389,11 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
let iter = term.post_order_iter(); let iter = term.post_order_iter();
code.push(Line::Query(self.compile_target(iter, term_loc, is_exposed))); 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); 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. //TODO: temporary workaround for inlined builtins.
match toc { match toc {
QueryTermRef::IsAtomic(_) | QueryTermRef::IsVar(_) => &QueryTerm::IsAtomic(_) | &QueryTerm::IsVar(_) =>
code.push(proceed!()), code.push(proceed!()),
_ => {} _ => {}
} }
@@ -447,28 +444,32 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
self.marker.advance(GenContext::Head, p0.arity()); self.marker.advance(GenContext::Head, p0.arity());
self.compile_seq_prelude(&conjunct_info, &mut code); self.compile_seq_prelude(&conjunct_info, &mut code);
if p0.is_clause() { if let &QueryTerm::Term(ref term) = p0 {
let iter = FactInstruction::iter(p0); if let &Term::Clause(_, _, _) = term {
code.push(Line::Fact(self.compile_target(iter, GenContext::Head, false))); 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 let &mut Line::Query(ref mut query) = &mut code[index] {
conjunct_info.perm_vs.mark_unsafe_vars_in_rule(p0, query);
} }
}
let iter = ChunkedIterator::from_rule_body(p1, clauses);
try!(self.compile_seq(iter, &conjunct_info, &mut code, false));
Self::compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1).to_ref()); if conjunct_info.allocates() {
Ok(code) 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);
}
}
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) 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(); let mut code = Vec::new();
if term.is_clause() { if let &Term::Clause(_, _, _) = term {
let iter = FactInstruction::iter(term); let iter = FactInstruction::iter(term);
let mut compiled_fact = self.compile_target(iter, GenContext::Head, false); 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, fn compile_query_line(&mut self,
term: QueryTermRef<'a>, term: &'a QueryTerm,
term_loc: GenContext, term_loc: GenContext,
code: &mut Code, code: &mut Code,
index: usize, 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) Ok(code)
} }

View File

@@ -60,7 +60,7 @@ impl TempVarData {
fn populate_conflict_set(&mut self) { fn populate_conflict_set(&mut self) {
if self.last_term_arity > 0 { 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(); let mut conflict_set : BTreeSet<usize> = (1..arity).collect();
for &(_, reg) in self.use_set.iter() { for &(_, reg) in self.use_set.iter() {
@@ -171,10 +171,7 @@ impl<'a> VariableFixtures<'a>
var_count var_count
} }
pub fn mark_vars_in_chunk<Iter>(&mut self, pub fn mark_vars_in_chunk<Iter>(&mut self, iter: Iter, lt_arity: usize, term_loc: GenContext)
iter: Iter,
last_term_arity: usize,
term_loc: GenContext)
where Iter: Iterator<Item=TermRef<'a>> where Iter: Iterator<Item=TermRef<'a>>
{ {
let chunk_num = term_loc.chunk_num(); let chunk_num = term_loc.chunk_num();
@@ -183,8 +180,7 @@ impl<'a> VariableFixtures<'a>
for term_ref in iter { for term_ref in iter {
if let TermRef::Var(lvl, cell, var) = term_ref { if let TermRef::Var(lvl, cell, var) = term_ref {
let mut status = self.0.remove(var) let mut status = self.0.remove(var)
.unwrap_or((VarStatus::Temp(chunk_num, TempVarData::new(last_term_arity)), .unwrap_or((VarStatus::Temp(chunk_num, TempVarData::new(lt_arity)), Vec::new()));
Vec::new()));
status.1.push(cell); status.1.push(cell);
@@ -217,7 +213,7 @@ impl<'a> VariableFixtures<'a>
pub fn size(&self) -> usize { pub fn size(&self) -> usize {
self.0.len() self.0.len()
} }
pub fn set_perm_vals(&self, has_deep_cuts: bool) pub fn set_perm_vals(&self, has_deep_cuts: bool)
{ {
let mut values_vec : Vec<_> = self.values() 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() { for &(_, ref cb) in self.values() {
match cb.first() { match cb.first() {
Some(index) => { 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>) fn mark_head_vars_as_safe(&self, head: &Term, unsafe_vars: &mut HashMap<RegType, bool>)
{ {
for term_ref in head.breadth_first_iter() { for term_ref in head.breadth_first_iter() {
match term_ref { match term_ref {
TermRef::Var(_, cell, _) => { TermRef::Var(_, cell, _) => {
@@ -297,12 +293,12 @@ impl<'a> VariableFixtures<'a>
self.record_unsafe_vars(&mut unsafe_vars); self.record_unsafe_vars(&mut unsafe_vars);
self.mark_unsafe_vars(&mut unsafe_vars, query); 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: &Term, query: &mut CompiledQuery)
{ {
let mut unsafe_vars = HashMap::new(); 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_head_vars_as_safe(head, &mut unsafe_vars);
self.mark_unsafe_vars(&mut unsafe_vars, query); self.mark_unsafe_vars(&mut unsafe_vars, query);
} }

View File

@@ -41,33 +41,35 @@ impl<'a> QueryIterator<'a> {
QueryIterator { state_stack: vec![state] } QueryIterator { state_stack: vec![state] }
} }
fn new(term: QueryTermRef<'a>) -> Self { fn new(term: &'a QueryTerm) -> Self {
match term { match term {
QueryTermRef::CallN(terms) => { &QueryTerm::CallN(ref terms) => {
let state = IteratorState::Clause(1, ClauseType::CallN, terms); let state = IteratorState::Clause(1, ClauseType::CallN, terms);
QueryIterator { state_stack: vec![state] } QueryIterator { state_stack: vec![state] }
}, },
QueryTermRef::Catch(terms) => { &QueryTerm::Catch(ref terms) => {
let state = IteratorState::Clause(0, ClauseType::Catch, terms); let state = IteratorState::Clause(0, ClauseType::Catch, terms);
QueryIterator { state_stack: vec![state] } QueryIterator { state_stack: vec![state] }
}, },
QueryTermRef::Is(terms) => { &QueryTerm::Is(ref terms) => {
let state = IteratorState::Clause(0, ClauseType::Is, terms); let state = IteratorState::Clause(0, ClauseType::Is, terms);
QueryIterator { state_stack: vec![state] } 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), Self::from_term(term),
QueryTermRef::Throw(term) => { &QueryTerm::Throw(ref term) => {
let state = IteratorState::Clause(0, ClauseType::Throw, term); let state = IteratorState::Clause(0, ClauseType::Throw, term);
QueryIterator { state_stack: vec![state] } QueryIterator { state_stack: vec![state] }
}, },
QueryTermRef::Cut => QueryIterator { state_stack: vec![] } &QueryTerm::Cut => QueryIterator { state_stack: vec![] }
} }
} }
} }
impl<'a> QueryTermRef<'a> { impl QueryTerm {
pub fn post_order_iter(self) -> QueryIterator<'a> { pub fn post_order_iter<'a>(&'a self) -> QueryIterator<'a> {
QueryIterator::new(self) QueryIterator::new(self)
} }
} }
@@ -183,7 +185,7 @@ impl<'a> Iterator for FactIterator<'a> {
impl Term { impl Term {
pub fn post_order_iter(&self) -> QueryIterator { pub fn post_order_iter(&self) -> QueryIterator {
QueryIterator::new(QueryTermRef::Term(self)) QueryIterator::from_term(self)
} }
pub fn breadth_first_iter(&self) -> FactIterator { pub fn breadth_first_iter(&self) -> FactIterator {
@@ -194,7 +196,7 @@ impl Term {
pub struct ChunkedIterator<'a> pub struct ChunkedIterator<'a>
{ {
term_loc: GenContext, term_loc: GenContext,
iter: Box<Iterator<Item=QueryTermRef<'a>> + 'a>, iter: Box<Iterator<Item=&'a QueryTerm> + 'a>,
deep_cut_encountered: bool deep_cut_encountered: bool
} }
@@ -202,20 +204,18 @@ impl<'a> ChunkedIterator<'a>
{ {
pub fn from_term_sequence(terms: &'a [QueryTerm]) -> Self pub fn from_term_sequence(terms: &'a [QueryTerm]) -> Self
{ {
let iter = terms.iter().map(|c| c.to_ref());
ChunkedIterator { ChunkedIterator {
term_loc: GenContext::Last(0), term_loc: GenContext::Last(0),
iter: Box::new(iter), iter: Box::new(terms.iter()),
deep_cut_encountered: false deep_cut_encountered: false
} }
} }
pub fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec<QueryTerm>) -> Self pub fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec<QueryTerm>) -> Self
{ {
let inner_iter = Box::new(once(p1.to_ref())); let inner_iter = Box::new(once(p1));
let iter = inner_iter.chain(clauses.iter().map(|c| c.to_ref())); let iter = inner_iter.chain(clauses.iter());
ChunkedIterator { ChunkedIterator {
term_loc: GenContext::Last(0), term_loc: GenContext::Last(0),
iter: Box::new(iter), iter: Box::new(iter),
@@ -227,15 +227,15 @@ impl<'a> ChunkedIterator<'a>
{ {
let &Rule { head: (ref p0, ref p1), ref clauses } = rule; let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
let iter = once(QueryTermRef::Term(p0)); let iter = once(p0);
let inner_iter = Box::new(once(p1.to_ref())); let inner_iter = Box::new(once(p1));
let iter = iter.chain(inner_iter.chain(clauses.iter().map(|c| c.to_ref()))); let iter = iter.chain(inner_iter.chain(clauses.iter()));
ChunkedIterator { ChunkedIterator {
term_loc: GenContext::Head, term_loc: GenContext::Head,
iter: Box::new(iter), iter: Box::new(iter),
deep_cut_encountered: false deep_cut_encountered: false,
} }
} }
pub fn encountered_deep_cut(&self) -> bool { pub fn encountered_deep_cut(&self) -> bool {
@@ -250,48 +250,44 @@ impl<'a> ChunkedIterator<'a>
self.term_loc.chunk_num() self.term_loc.chunk_num()
} }
fn take_chunk(&mut self, term: QueryTermRef<'a>, mut result: Vec<QueryTermRef<'a>>) fn take_chunk(&mut self, term: &'a QueryTerm) -> (usize, usize, Vec<&'a QueryTerm>)
-> (usize, usize, Vec<QueryTermRef<'a>>)
{ {
let mut arity = 0; let mut arity = 0;
let mut item = Some(term); let mut item = Some(term);
let mut result = Vec::new();
while let Some(term) = item { while let Some(term) = item {
match term { match term {
//TODO: This can refer to the term at the head of a &QueryTerm::Term(ref inner_term) =>
// goal, not technically a QueryTerm (ie. a term in a
// query). Think of a better name.
QueryTermRef::Term(inner_term) => {
if let GenContext::Head = self.term_loc { if let GenContext::Head = self.term_loc {
result.push(term); result.push(term);
self.term_loc = GenContext::Last(0); self.term_loc = GenContext::Last(0);
} else { } else {
result.push(term); result.push(term);
if inner_term.is_callable() { if inner_term.is_callable() {
arity = inner_term.arity(); arity = inner_term.arity();
break; break;
} }
} },
}, &QueryTerm::CallN(ref child_terms) => {
QueryTermRef::CallN(child_terms) => {
result.push(term); result.push(term);
arity = child_terms.len() + 1; arity = child_terms.len() + 1;
break; break;
}, },
QueryTermRef::Catch(child_terms) | QueryTermRef::Throw(child_terms) => { &QueryTerm::Catch(ref child_terms) | &QueryTerm::Throw(ref child_terms) => {
result.push(term); result.push(term);
arity = child_terms.len(); arity = child_terms.len();
break; break;
}, },
QueryTermRef::Is(_) => { &QueryTerm::Is(_) => {
result.push(term); result.push(term);
arity = 2; arity = 2;
break; break;
}, },
QueryTermRef::IsAtomic(_) | QueryTermRef::IsVar(_) => &QueryTerm::IsAtomic(_) | &QueryTerm::IsVar(_) =>
result.push(term), result.push(term),
QueryTermRef::Cut => { &QueryTerm::Cut => {
result.push(term); result.push(term);
if self.term_loc.chunk_num() > 0 { if self.term_loc.chunk_num() > 0 {
@@ -316,9 +312,9 @@ impl<'a> ChunkedIterator<'a>
impl<'a> Iterator for ChunkedIterator<'a> impl<'a> Iterator for ChunkedIterator<'a>
{ {
// the chunk number, last term arity, and vector of references. // 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> { 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))
} }
} }

View File

@@ -239,44 +239,52 @@ impl Machine {
pub fn add_fact<'a>(&mut self, fact: &Term, mut code: Code) -> EvalSession<'a> pub fn add_fact<'a>(&mut self, fact: &Term, mut code: Code) -> EvalSession<'a>
{ {
if let Some(name) = fact.name() { match fact {
let p = self.code.len(); &Term::Clause(_, ref name, _) | &Term::Constant(_, Constant::Atom(ref name)) => {
let p = self.code.len();
let arity = fact.arity();
let name = name.clone(); self.code.append(&mut code);
let arity = fact.arity(); self.add_user_code(name.clone(), arity, p)
},
self.code.append(&mut code); _ => EvalSession::NamelessEntry
self.add_user_code(name, arity, p)
} else {
EvalSession::NamelessEntry
} }
} }
pub fn add_rule<'a>(&mut self, rule: &Rule, mut code: Code) -> EvalSession<'a> pub fn add_rule<'a>(&mut self, rule: &Rule, mut code: Code) -> EvalSession<'a>
{ {
if let Some(name) = rule.head.0.name() { match &rule.head.0 {
let p = self.code.len(); &QueryTerm::Term(Term::Clause(_, ref name, _))
| &QueryTerm::Term(Term::Constant(_, Constant::Atom(ref name))) => {
let p = self.code.len();
let name = name.clone(); let name = name.clone();
let arity = rule.head.0.arity(); let arity = rule.head.0.arity();
self.code.append(&mut code); self.code.append(&mut code);
self.add_user_code(name, arity, p) self.add_user_code(name, arity, p)
} else { },
EvalSession::NamelessEntry _ => EvalSession::NamelessEntry
} }
} }
pub fn add_predicate<'a>(&mut self, clauses: &Vec<PredicateClause>, mut code: Code) pub fn add_predicate<'a>(&mut self, clauses: &Vec<PredicateClause>, mut code: Code)
-> EvalSession<'a> -> EvalSession<'a>
{ {
let p = self.code.len(); let p = self.code.len();
let arity = clauses.first().unwrap().arity(); if let Some(ref clause) = clauses.first() {
let name = clauses.first().unwrap().name().clone(); if let Some(name) = clause.name() {
let arity = clause.arity();
self.code.append(&mut code); self.code.append(&mut code);
self.add_user_code(name, arity, p) 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 { fn cached_query_size(&self) -> usize {
@@ -1516,15 +1524,15 @@ impl MachineState {
} else { } else {
0 0
}; };
if and_gi <= or_fr.global_index { if and_gi <= or_fr.global_index {
self.e = or_fr.e; self.e = or_fr.e;
} }
} }
if self.e + 1 < self.and_stack.len() { if self.e + 1 < self.and_stack.len() {
let index = self.e + 1; let index = self.e + 1;
self.and_stack[index].e = self.e; self.and_stack[index].e = self.e;
self.and_stack[index].cp = self.cp; self.and_stack[index].cp = self.cp;