]> Repositorios git - scryer-prolog.git/commitdiff
pass binding info to arithmetic evaluator
authorMark Thom <[email protected]>
Mon, 6 Nov 2017 20:35:48 +0000 (13:35 -0700)
committerMark Thom <[email protected]>
Mon, 6 Nov 2017 20:35:48 +0000 (13:35 -0700)
src/prolog/arithmetic.rs
src/prolog/codegen.rs

index 91bcf91ab97aa8cafd1c171194dee676e6cd0d4c..6c8b1d718c4533c0400b725c8fc6bd7a609f03de 100644 (file)
@@ -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<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)
@@ -122,8 +124,8 @@ impl ArithmeticEvaluator {
         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 => {
@@ -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)?));
                 },
index ad0f4138ed0632d035ddae7563ddce85e1054a62..c4bc158f4146ef4b695d816c1af626310589e291 100644 (file)
@@ -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() {