separate handling of inlined query terms.

This commit is contained in:
Mark Thom
2017-11-13 13:18:05 -07:00
parent b1ae09d7aa
commit ded701436a
4 changed files with 138 additions and 106 deletions

View File

@@ -309,13 +309,26 @@ pub enum Term {
Var(Cell<VarReg>, Var) Var(Cell<VarReg>, Var)
} }
pub enum InlinedQueryTerm {
Is(Vec<Box<Term>>),
IsAtomic(Vec<Box<Term>>),
IsVar(Vec<Box<Term>>)
}
impl InlinedQueryTerm {
pub fn arity(&self) -> usize {
match self {
&InlinedQueryTerm::Is(_) => 2,
_ => 1
}
}
}
pub enum QueryTerm { pub enum QueryTerm {
CallN(Vec<Box<Term>>), CallN(Vec<Box<Term>>),
Catch(Vec<Box<Term>>), Catch(Vec<Box<Term>>),
Cut, Cut,
Is(Vec<Box<Term>>), Inlined(InlinedQueryTerm),
IsAtomic(Vec<Box<Term>>),
IsVar(Vec<Box<Term>>),
Term(Term), Term(Term),
Throw(Vec<Box<Term>>) Throw(Vec<Box<Term>>)
} }
@@ -325,9 +338,7 @@ impl QueryTerm {
match self { match self {
&QueryTerm::Catch(_) => 3, &QueryTerm::Catch(_) => 3,
&QueryTerm::Throw(_) => 1, &QueryTerm::Throw(_) => 1,
&QueryTerm::Is(_) => 2, &QueryTerm::Inlined(ref term) => term.arity(),
&QueryTerm::IsAtomic(_) => 1,
&QueryTerm::IsVar(_) => 1,
&QueryTerm::CallN(ref terms) => terms.len(), &QueryTerm::CallN(ref terms) => terms.len(),
&QueryTerm::Cut => 0, &QueryTerm::Cut => 0,
&QueryTerm::Term(ref term) => term.arity(), &QueryTerm::Term(ref term) => term.arity(),

View File

@@ -231,27 +231,36 @@ 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: &QueryTerm, pvs: usize) fn add_conditional_call_inlined(term: &InlinedQueryTerm, code: &mut Code)
{
match term {
&InlinedQueryTerm::IsAtomic(_) | &InlinedQueryTerm::IsVar(_) =>
code.push(proceed!()),
_ => {}
};
}
fn add_conditional_call(code: &mut Code, qt: &QueryTerm, pvs: usize)
{ {
match qt { match qt {
&QueryTerm::CallN(ref terms) => { &QueryTerm::CallN(ref terms) => {
let call = ControlInstruction::CallN(terms.len()); let call = ControlInstruction::CallN(terms.len());
compiled_query.push(Line::Control(call)); code.push(Line::Control(call));
}, },
&QueryTerm::Catch(_) => &QueryTerm::Catch(_) =>
compiled_query.push(Line::Control(ControlInstruction::CatchCall)), code.push(Line::Control(ControlInstruction::CatchCall)),
&QueryTerm::IsAtomic(_) | &QueryTerm::IsVar(_) => &QueryTerm::Inlined(ref term) =>
compiled_query.push(proceed!()), Self::add_conditional_call_inlined(term, code),
&QueryTerm::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)); code.push(Line::Control(call));
}, },
&QueryTerm::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)); code.push(Line::Control(call));
}, },
&QueryTerm::Throw(_) => &QueryTerm::Throw(_) =>
compiled_query.push(Line::Control(ControlInstruction::ThrowCall)), code.push(Line::Control(ControlInstruction::ThrowCall)),
_ => {} _ => {}
} }
} }
@@ -282,37 +291,11 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
dealloc_index dealloc_index
} }
fn compile_seq(&mut self, fn compile_inlined(&mut self, term: &'a InlinedQueryTerm, term_loc: GenContext, code: &mut Code)
iter: ChunkedIterator<'a>,
conjunct_info: &ConjunctInfo<'a>,
code: &mut Code,
is_exposed: bool)
-> Result<(), ParserError> -> Result<(), ParserError>
{ {
for (chunk_num, _, terms) in iter { match term {
for (i, term) in terms.iter().enumerate() &InlinedQueryTerm::Is(ref terms) => {
{
let term_loc = if i + 1 < terms.len() {
GenContext::Mid(chunk_num)
} else {
GenContext::Last(chunk_num)
};
match *term {
&QueryTerm::Cut => {
let term = if i + 1 < terms.len() {
Terminal::Non
} else {
Terminal::Terminal
};
code.push(if chunk_num == 0 {
Line::Cut(CutInstruction::NeckCut(term))
} else {
Line::Cut(CutInstruction::Cut(term))
});
},
&QueryTerm::Is(ref 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())?
@@ -323,7 +306,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
match terms[0].as_ref() { match terms[0].as_ref() {
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
let r = self.mark_non_callable(name, let r = self.mark_non_callable(name,
term.arity(), 2,
term_loc, term_loc,
vr, vr,
code); code);
@@ -348,7 +331,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
} }
} }
}, },
&QueryTerm::IsAtomic(ref inner_term) => &InlinedQueryTerm::IsAtomic(ref inner_term) =>
match inner_term[0].as_ref() { match inner_term[0].as_ref() {
&Term::AnonVar | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => { &Term::AnonVar | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => {
code.push(fail!()); code.push(fail!());
@@ -358,7 +341,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
}, },
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
let r = self.mark_non_callable(name, let r = self.mark_non_callable(name,
term.arity(), 1,
term_loc, term_loc,
vr, vr,
code); code);
@@ -366,7 +349,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
code.push(is_atomic!(r)); code.push(is_atomic!(r));
} }
}, },
&QueryTerm::IsVar(ref inner_term) => &InlinedQueryTerm::IsVar(ref inner_term) =>
match inner_term[0].as_ref() { match inner_term[0].as_ref() {
&Term::Constant(_, _) | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => { &Term::Constant(_, _) | &Term::Clause(_, _, _) | &Term::Cons(_, _, _) => {
code.push(fail!()); code.push(fail!());
@@ -376,14 +359,51 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
}, },
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
let r = self.mark_non_callable(name, let r = self.mark_non_callable(name,
term.arity(), 1,
term_loc, term_loc,
vr, vr,
code); code);
code.push(is_var!(r)); code.push(is_var!(r));
} }
}
}
Ok(())
}
fn compile_seq(&mut self,
iter: ChunkedIterator<'a>,
conjunct_info: &ConjunctInfo<'a>,
code: &mut Code,
is_exposed: bool)
-> Result<(), ParserError>
{
for (chunk_num, _, terms) in iter {
for (i, term) in terms.iter().enumerate()
{
let term_loc = if i + 1 < terms.len() {
GenContext::Mid(chunk_num)
} else {
GenContext::Last(chunk_num)
};
match *term {
&QueryTerm::Cut => {
let is_terminal = if i + 1 < terms.len() {
Terminal::Non
} else {
Terminal::Terminal
};
code.push(if chunk_num == 0 {
Line::Cut(CutInstruction::NeckCut(is_terminal))
} else {
Line::Cut(CutInstruction::Cut(is_terminal))
});
}, },
&QueryTerm::Inlined(ref term) =>
try!(self.compile_inlined(term, term_loc, code)),
_ if chunk_num == 0 => { _ if chunk_num == 0 => {
self.marker.reset_arg(term.arity()); self.marker.reset_arg(term.arity());
@@ -419,12 +439,11 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
fn compile_cleanup(code: &mut Code, conjunct_info: &ConjunctInfo, toc: &'a QueryTerm) fn compile_cleanup(code: &mut Code, conjunct_info: &ConjunctInfo, toc: &'a QueryTerm)
{ {
//TODO: temporary workaround for inlined builtins.
match toc { match toc {
&QueryTerm::IsAtomic(_) | &QueryTerm::IsVar(_) => &QueryTerm::Inlined(ref term) =>
code.push(proceed!()), Self::add_conditional_call_inlined(term, code),
_ => {} _ => {}
} };
let dealloc_index = Self::lco(code); let dealloc_index = Self::lco(code);

View File

@@ -40,11 +40,12 @@ impl<'a> QueryIterator<'a> {
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] }
}, },
&QueryTerm::Is(ref terms) => { &QueryTerm::Inlined(InlinedQueryTerm::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] }
}, },
&QueryTerm::IsAtomic(ref terms) | &QueryTerm::IsVar(ref terms) => &QueryTerm::Inlined(InlinedQueryTerm::IsAtomic(ref terms))
| &QueryTerm::Inlined(InlinedQueryTerm::IsVar(ref terms)) =>
Self::from_term(terms[0].as_ref()), Self::from_term(terms[0].as_ref()),
&QueryTerm::Term(ref term) => &QueryTerm::Term(ref term) =>
Self::from_term(term), Self::from_term(term),
@@ -269,12 +270,13 @@ impl<'a> ChunkedIterator<'a>
arity = child_terms.len(); arity = child_terms.len();
break; break;
}, },
&QueryTerm::Is(_) => { &QueryTerm::Inlined(InlinedQueryTerm::Is(_)) => {
result.push(term); result.push(term);
arity = 2; arity = 2;
break; break;
}, },
&QueryTerm::IsAtomic(_) | &QueryTerm::IsVar(_) => &QueryTerm::Inlined(InlinedQueryTerm::IsAtomic(_))
| &QueryTerm::Inlined(InlinedQueryTerm::IsVar(_)) =>
result.push(term), result.push(term),
&QueryTerm::Cut => { &QueryTerm::Cut => {
result.push(term); result.push(term);