mark unsafe variables and substitute temporary variables in is/2 when appropriate (#1430)
This commit is contained in:
@@ -5,6 +5,7 @@ use crate::fixtures::*;
|
|||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
use crate::iterators::*;
|
use crate::iterators::*;
|
||||||
|
use crate::targets::QueryInstruction;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
@@ -121,15 +122,12 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
|
|||||||
subterms,
|
subterms,
|
||||||
));
|
));
|
||||||
|
|
||||||
self.push_subterm(lvl, &subterms[child_num]);
|
self.push_subterm(lvl.child_level(), &subterms[child_num]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TermIterState::Literal(_, _, c) => return Some(Ok(ArithTermRef::Literal(c))),
|
TermIterState::Literal(_, _, c) => return Some(Ok(ArithTermRef::Literal(c))),
|
||||||
TermIterState::Var(lvl, cell, var) => {
|
TermIterState::Var(lvl, cell, var) => {
|
||||||
// the expression is the second argument of an
|
return Some(Ok(ArithTermRef::Var(lvl, cell, var.clone())));
|
||||||
// is/2 but the iterator can't see that, so the
|
|
||||||
// level needs to be demoted manually.
|
|
||||||
return Some(Ok(ArithTermRef::Var(lvl.child_level(), cell, var.clone())));
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Some(Err(ArithmeticError::NonEvaluableFunctor(
|
return Some(Err(ArithmeticError::NonEvaluableFunctor(
|
||||||
@@ -315,7 +313,7 @@ impl<'a, TermMarker: Allocator> ArithmeticEvaluator<'a, TermMarker> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn eval(
|
pub(crate) fn compile_is(
|
||||||
&mut self,
|
&mut self,
|
||||||
src: &'a Term,
|
src: &'a Term,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
@@ -328,17 +326,7 @@ impl<'a, TermMarker: Allocator> ArithmeticEvaluator<'a, TermMarker> {
|
|||||||
match term_ref? {
|
match term_ref? {
|
||||||
ArithTermRef::Literal(c) => push_literal(&mut self.interm, c)?,
|
ArithTermRef::Literal(c) => push_literal(&mut self.interm, c)?,
|
||||||
ArithTermRef::Var(lvl, cell, name) => {
|
ArithTermRef::Var(lvl, cell, name) => {
|
||||||
let r = if cell.get().norm().reg_num() == 0 {
|
let r = if lvl == Level::Shallow && term_loc.is_last() {
|
||||||
let mut getter = || {
|
|
||||||
use crate::targets::QueryInstruction;
|
|
||||||
|
|
||||||
loop {
|
|
||||||
match self.marker.bindings().get(&name) {
|
|
||||||
Some(&VarData::Temp(_, t, _)) if t != 0 =>
|
|
||||||
return RegType::Temp(t),
|
|
||||||
Some(&VarData::Perm(p)) if p != 0 =>
|
|
||||||
return RegType::Perm(p),
|
|
||||||
_ => {
|
|
||||||
self.marker.mark_var::<QueryInstruction>(
|
self.marker.mark_var::<QueryInstruction>(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
lvl,
|
lvl,
|
||||||
@@ -346,15 +334,27 @@ impl<'a, TermMarker: Allocator> ArithmeticEvaluator<'a, TermMarker> {
|
|||||||
term_loc,
|
term_loc,
|
||||||
&mut code,
|
&mut code,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
getter()
|
self.interm.push(ArithmeticTerm::Reg(temp_v!(2)));
|
||||||
/*
|
continue;
|
||||||
_ => return Err(ArithmeticError::UninstantiatedVar),
|
} else if cell.get().norm().reg_num() == 0 {
|
||||||
*/
|
self.marker.mark_var::<QueryInstruction>(
|
||||||
|
name.clone(),
|
||||||
|
lvl,
|
||||||
|
cell,
|
||||||
|
term_loc,
|
||||||
|
&mut code,
|
||||||
|
);
|
||||||
|
|
||||||
|
match self.marker.bindings().get(&name) {
|
||||||
|
Some(&VarData::Temp(_, t, _)) if t != 0 =>
|
||||||
|
RegType::Temp(t),
|
||||||
|
Some(&VarData::Perm(p)) if p != 0 =>
|
||||||
|
RegType::Perm(p),
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cell.get().norm()
|
cell.get().norm()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -397,6 +397,7 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> {
|
|||||||
perm_v!(1),
|
perm_v!(1),
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -430,7 +431,6 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.update_var_count(chunked_term.post_order_iter());
|
self.update_var_count(chunked_term.post_order_iter());
|
||||||
|
|
||||||
vs.mark_vars_in_chunk(chunked_term.post_order_iter(), lt_arity, term_loc);
|
vs.mark_vars_in_chunk(chunked_term.post_order_iter(), lt_arity, term_loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -663,7 +663,7 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> {
|
|||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
) -> Result<ArithCont, ArithmeticError> {
|
) -> Result<ArithCont, ArithmeticError> {
|
||||||
let mut evaluator = ArithmeticEvaluator::new(&mut self.marker, target_int);
|
let mut evaluator = ArithmeticEvaluator::new(&mut self.marker, target_int);
|
||||||
evaluator.eval(term, term_loc)
|
evaluator.compile_is(term, term_loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_is_call(
|
fn compile_is_call(
|
||||||
@@ -1080,7 +1080,6 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> {
|
|||||||
// the peculiar condition of this block, when false,
|
// the peculiar condition of this block, when false,
|
||||||
// anticipates code.pop_front() being called about a
|
// anticipates code.pop_front() being called about a
|
||||||
// dozen lines below.
|
// dozen lines below.
|
||||||
debug_assert_eq!(code.len(), 1);
|
|
||||||
self.increment_jmp_by_locs_by(code.len());
|
self.increment_jmp_by_locs_by(code.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ impl AppendOrPrepend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Level {
|
pub enum Level {
|
||||||
Deep,
|
Deep,
|
||||||
Root,
|
Root,
|
||||||
|
|||||||
@@ -407,16 +407,7 @@ impl<'a> ChunkedIterator<'a> {
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
pub(crate) fn from_term_sequence(terms: &'a [QueryTerm]) -> Self {
|
|
||||||
ChunkedIterator {
|
|
||||||
chunk_num: 0,
|
|
||||||
iter: Box::new(terms.iter().map(|t| ChunkedTerm::BodyTerm(t))),
|
|
||||||
deep_cut_encountered: false,
|
|
||||||
cut_var_in_head: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
pub(crate) fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec<QueryTerm>) -> Self {
|
pub(crate) fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec<QueryTerm>) -> Self {
|
||||||
let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1)));
|
let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1)));
|
||||||
let iter = inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t)));
|
let iter = inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t)));
|
||||||
|
|||||||
@@ -234,12 +234,22 @@ pub enum GenContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GenContext {
|
impl GenContext {
|
||||||
|
#[inline]
|
||||||
pub fn chunk_num(self) -> usize {
|
pub fn chunk_num(self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
GenContext::Head => 0,
|
GenContext::Head => 0,
|
||||||
GenContext::Mid(cn) | GenContext::Last(cn) => cn,
|
GenContext::Mid(cn) | GenContext::Last(cn) => cn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_last(self) -> bool {
|
||||||
|
if let GenContext::Last(_) = self {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bitfield]
|
#[bitfield]
|
||||||
|
|||||||
Reference in New Issue
Block a user