pass binding info to arithmetic evaluator

This commit is contained in:
Mark Thom
2017-11-06 13:35:48 -07:00
parent 4cc3409809
commit 2225674b58
2 changed files with 24 additions and 27 deletions

View File

@@ -1,4 +1,5 @@
use prolog::ast::*; use prolog::ast::*;
use prolog::fixtures::*;
use std::cell::Cell; use std::cell::Cell;
use std::cmp::{min, max}; use std::cmp::{min, max};
@@ -81,14 +82,15 @@ impl<'a> Iterator for ArithExprIterator<'a> {
} }
} }
pub struct ArithmeticEvaluator { pub struct ArithmeticEvaluator<'a> {
bindings: &'a AllocVarDict<'a>,
interm: Vec<ArithmeticTerm>, interm: Vec<ArithmeticTerm>,
interm_c: usize interm_c: usize
} }
impl ArithmeticEvaluator { impl<'a> ArithmeticEvaluator<'a> {
pub fn new() -> Self { pub fn new(bindings: &'a AllocVarDict<'a>) -> Self {
ArithmeticEvaluator { interm: Vec::new(), interm_c: 1 } ArithmeticEvaluator { bindings, interm: Vec::new(), interm_c: 1 }
} }
fn get_un_instr(name: &Atom, a1: ArithmeticTerm, t: ArithEvalPlace) fn get_un_instr(name: &Atom, a1: ArithmeticTerm, t: ArithEvalPlace)
@@ -122,7 +124,7 @@ impl ArithmeticEvaluator {
temp temp
} }
fn instr_from_clause<'a>(&mut self, name: &'a Atom, terms: &'a Vec<Box<Term>>, deep: bool) fn instr_from_clause(&mut self, name: &Atom, terms: &Vec<Box<Term>>, deep: bool)
-> Result<ArithmeticInstruction, ArithmeticError> -> Result<ArithmeticInstruction, ArithmeticError>
{ {
match terms.len() { match terms.len() {
@@ -194,11 +196,18 @@ impl ArithmeticEvaluator {
match term_ref { match term_ref {
TermRef::Constant(_, _, c) => TermRef::Constant(_, _, c) =>
try!(self.push_constant(c)), try!(self.push_constant(c)),
TermRef::Var(_, var_reg, _) => TermRef::Var(_, vr, name) => {
if var_reg.get().norm().reg_num() == 0 { let r = if vr.get().norm().reg_num() == 0 {
return Err(ArithmeticError::UninstantiatedVar); match self.bindings.get(name) {
Some(&VarData::Temp(_, t, _)) if t != 0 => RegType::Temp(t),
Some(&VarData::Perm(p)) => RegType::Perm(p),
_ => return Err(ArithmeticError::UninstantiatedVar)
}
} else { } else {
self.interm.push(ArithmeticTerm::Reg(var_reg.get().norm())); vr.get().norm()
};
self.interm.push(ArithmeticTerm::Reg(r));
}, },
TermRef::Clause(ClauseType::Deep(_, _, name), terms) => { TermRef::Clause(ClauseType::Deep(_, _, name), terms) => {
code.push(Line::Arithmetic(self.instr_from_clause(name, terms, true)?)); code.push(Line::Arithmetic(self.instr_from_clause(name, terms, true)?));

View File

@@ -306,23 +306,11 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
}); });
}, },
&QueryTermRef::Is(terms) => { &QueryTermRef::Is(terms) => {
let mut target = Vec::new(); let mut arith_code = {
self.marker.advance(term_loc, *term); let mut evaluator = ArithmeticEvaluator::new(self.marker.bindings());
evaluator.eval(terms[1].as_ref())?
};
// instantiate any vars introduced in the expr.
for term_ref in terms[1].post_order_iter() {
if let TermRef::Var(lvl, vr, name) = term_ref {
self.marker.mark_var(name, lvl, vr, term_loc, &mut target);
}
}
if !target.is_empty() {
code.push(Line::Query(target));
}
let mut evaluator = ArithmeticEvaluator::new();
let mut arith_code = evaluator.eval(terms[1].as_ref())?;
code.append(&mut arith_code); code.append(&mut arith_code);
match terms[0].as_ref() { match terms[0].as_ref() {