separate handling of inlined query terms.
This commit is contained in:
@@ -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(),
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Submodule src/prolog/parser updated: f01fe4feab...41d2d7d26f
Reference in New Issue
Block a user