From: Mark Thom Date: Mon, 6 Nov 2017 20:35:48 +0000 (-0700) Subject: pass binding info to arithmetic evaluator X-Git-Tag: v0.8.110~679 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=2225674b58508f1219c870188cfcb1d3a021fa46;p=scryer-prolog.git pass binding info to arithmetic evaluator --- diff --git a/src/prolog/arithmetic.rs b/src/prolog/arithmetic.rs index 91bcf91a..6c8b1d71 100644 --- a/src/prolog/arithmetic.rs +++ b/src/prolog/arithmetic.rs @@ -1,4 +1,5 @@ use prolog::ast::*; +use prolog::fixtures::*; use std::cell::Cell; 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, 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) @@ -122,8 +124,8 @@ impl ArithmeticEvaluator { temp } - fn instr_from_clause<'a>(&mut self, name: &'a Atom, terms: &'a Vec>, deep: bool) - -> Result + fn instr_from_clause(&mut self, name: &Atom, terms: &Vec>, deep: bool) + -> Result { match terms.len() { 1 => { @@ -194,12 +196,19 @@ impl ArithmeticEvaluator { 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)?)); }, diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index ad0f4138..c4bc158f 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -306,23 +306,11 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> }); }, &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() {