mark unsafe variables and substitute temporary variables in is/2 when appropriate (#1430)

This commit is contained in:
Mark Thom
2022-04-17 17:33:09 -06:00
parent 35b8f69f92
commit 66075bf45b
5 changed files with 45 additions and 45 deletions

View File

@@ -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()
}; };

View File

@@ -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());
} }

View File

@@ -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,

View File

@@ -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)));

View File

@@ -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]