use prolog::ast::*;
+use prolog::fixtures::*;
use std::cell::Cell;
use std::cmp::{min, max};
}
}
-pub struct ArithmeticEvaluator {
+pub struct ArithmeticEvaluator<'a> {
+ bindings: &'a AllocVarDict<'a>,
interm: Vec<ArithmeticTerm>,
interm_c: usize
}
-impl ArithmeticEvaluator {
- pub fn new() -> Self {
- ArithmeticEvaluator { interm: Vec::new(), interm_c: 1 }
+impl<'a> ArithmeticEvaluator<'a> {
+ pub fn new(bindings: &'a AllocVarDict<'a>) -> Self {
+ ArithmeticEvaluator { bindings, interm: Vec::new(), interm_c: 1 }
}
fn get_un_instr(name: &Atom, a1: ArithmeticTerm, t: ArithEvalPlace)
temp
}
- fn instr_from_clause<'a>(&mut self, name: &'a Atom, terms: &'a Vec<Box<Term>>, deep: bool)
- -> Result<ArithmeticInstruction, ArithmeticError>
+ fn instr_from_clause(&mut self, name: &Atom, terms: &Vec<Box<Term>>, deep: bool)
+ -> Result<ArithmeticInstruction, ArithmeticError>
{
match terms.len() {
1 => {
match term_ref {
TermRef::Constant(_, _, c) =>
try!(self.push_constant(c)),
- TermRef::Var(_, var_reg, _) =>
- if var_reg.get().norm().reg_num() == 0 {
- return Err(ArithmeticError::UninstantiatedVar);
+ TermRef::Var(_, vr, name) => {
+ let r = if vr.get().norm().reg_num() == 0 {
+ 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 {
- self.interm.push(ArithmeticTerm::Reg(var_reg.get().norm()));
- },
+ vr.get().norm()
+ };
+
+ self.interm.push(ArithmeticTerm::Reg(r));
+ },
TermRef::Clause(ClauseType::Deep(_, _, name), terms) => {
code.push(Line::Arithmetic(self.instr_from_clause(name, terms, true)?));
},
});
},
&QueryTermRef::Is(terms) => {
- let mut target = Vec::new();
- self.marker.advance(term_loc, *term);
-
- // 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 arith_code = {
+ let mut evaluator = ArithmeticEvaluator::new(self.marker.bindings());
+ evaluator.eval(terms[1].as_ref())?
+ };
- let mut evaluator = ArithmeticEvaluator::new();
-
- let mut arith_code = evaluator.eval(terms[1].as_ref())?;
code.append(&mut arith_code);
match terms[0].as_ref() {