pass binding info to arithmetic evaluator
This commit is contained in:
@@ -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,8 +124,8 @@ 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() {
|
||||||
1 => {
|
1 => {
|
||||||
@@ -194,12 +196,19 @@ 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)?));
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
Reference in New Issue
Block a user