abstract out iterator for arithmetic terms.

This commit is contained in:
Mark Thom
2018-01-17 22:43:46 -07:00
parent f95901a6d0
commit 1fefcc2d28

View File

@@ -1,17 +1,18 @@
use prolog::ast::*; use prolog::ast::*;
use prolog::fixtures::*; use prolog::fixtures::*;
use prolog::tabled_rc::*;
use std::cell::Cell; use std::cell::Cell;
use std::cmp::{min, max}; use std::cmp::{min, max};
use std::vec::Vec; use std::vec::Vec;
pub struct ArithExprIterator<'a> { pub struct ArithInstructionIterator<'a> {
state_stack: Vec<TermIterState<'a>> state_stack: Vec<TermIterState<'a>>
} }
pub type ArithCont = (Code, Option<ArithmeticTerm>); pub type ArithCont = (Code, Option<ArithmeticTerm>);
impl<'a> ArithExprIterator<'a> { impl<'a> ArithInstructionIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) { fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
self.state_stack.push(TermIterState::to_state(lvl, term)); self.state_stack.push(TermIterState::to_state(lvl, term));
} }
@@ -30,13 +31,7 @@ impl<'a> ArithExprIterator<'a> {
TermIterState::Var(Level::Shallow, cell, var) TermIterState::Var(Level::Shallow, cell, var)
}; };
Ok(ArithExprIterator { state_stack: vec![state] }) Ok(ArithInstructionIterator { state_stack: vec![state] })
}
}
impl Term {
pub fn arith_expr_iter<'a>(&'a self) -> Result<ArithExprIterator<'a>, ArithmeticError> {
ArithExprIterator::new(self)
} }
} }
@@ -46,7 +41,7 @@ pub enum ArithTermRef<'a> {
Var(&'a Cell<VarReg>, &'a Var) Var(&'a Cell<VarReg>, &'a Var)
} }
impl<'a> Iterator for ArithExprIterator<'a> { impl<'a> Iterator for ArithInstructionIterator<'a> {
type Item = Result<ArithTermRef<'a>, ArithmeticError>; type Item = Result<ArithTermRef<'a>, ArithmeticError>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
@@ -78,14 +73,37 @@ impl<'a> Iterator for ArithExprIterator<'a> {
pub struct ArithmeticEvaluator<'a> { pub struct ArithmeticEvaluator<'a> {
bindings: &'a AllocVarDict<'a>, bindings: &'a AllocVarDict<'a>,
interm: Vec<ArithmeticTerm>, interm: Vec<ArithmeticTerm>,
interm_c: usize interm_c: usize
} }
impl<'a> ArithmeticEvaluator<'a> { pub trait ArithmeticTermIter<'a> {
type Iter : Iterator<Item=Result<ArithTermRef<'a>, ArithmeticError>>;
fn iter(&self) -> Result<Self::Iter, ArithmeticError>;
fn root_name(&self) -> Result<TabledRc<Atom>, ArithmeticError>;
}
impl<'a> ArithmeticTermIter<'a> for &'a Term {
type Iter = ArithInstructionIterator<'a>;
fn iter(&self) -> Result<Self::Iter, ArithmeticError> {
ArithInstructionIterator::new(self)
}
fn root_name(&self) -> Result<TabledRc<Atom>, ArithmeticError> {
match self {
&&Term::Clause(_, ref name, _, _) => Ok(name.clone()),
_ => Err(ArithmeticError::InvalidTerm)
}
}
}
impl<'a> ArithmeticEvaluator<'a>
{
pub fn new(bindings: &'a AllocVarDict<'a>, target_int: usize) -> Self { pub fn new(bindings: &'a AllocVarDict<'a>, target_int: usize) -> Self {
ArithmeticEvaluator { bindings, interm: Vec::new(), interm_c: target_int } ArithmeticEvaluator { bindings, interm: Vec::new(), interm_c: target_int }
} }
fn get_unary_instr(name: &Atom, a1: ArithmeticTerm, t: usize) fn get_unary_instr(name: &Atom, a1: ArithmeticTerm, t: usize)
-> Result<ArithmeticInstruction, ArithmeticError> -> Result<ArithmeticInstruction, ArithmeticError>
{ {
@@ -95,7 +113,7 @@ impl<'a> ArithmeticEvaluator<'a> {
} }
} }
fn gen_binary_instr(name: &Atom, a1: ArithmeticTerm, a2: ArithmeticTerm, t: usize) fn get_binary_instr(name: &Atom, a1: ArithmeticTerm, a2: ArithmeticTerm, t: usize)
-> Result<ArithmeticInstruction, ArithmeticError> -> Result<ArithmeticInstruction, ArithmeticError>
{ {
match name.as_str() { match name.as_str() {
@@ -116,7 +134,7 @@ impl<'a> ArithmeticEvaluator<'a> {
_ => Err(ArithmeticError::InvalidOp) _ => Err(ArithmeticError::InvalidOp)
} }
} }
fn incr_interm(&mut self) -> usize { fn incr_interm(&mut self) -> usize {
let temp = self.interm_c; let temp = self.interm_c;
@@ -164,7 +182,7 @@ impl<'a> ArithmeticEvaluator<'a> {
min_interm min_interm
}; };
Self::gen_binary_instr(name, a1, a2, ninterm) Self::get_binary_instr(name, a1, a2, ninterm)
}, },
_ => Err(ArithmeticError::InvalidOp) _ => Err(ArithmeticError::InvalidOp)
} }
@@ -181,10 +199,13 @@ impl<'a> ArithmeticEvaluator<'a> {
Ok(()) Ok(())
} }
pub fn eval(&mut self, term: &Term) -> Result<ArithCont, ArithmeticError> { pub fn eval<Iter>(&mut self, src: Iter) -> Result<ArithCont, ArithmeticError>
let mut code = Vec::new(); where Iter: ArithmeticTermIter<'a>
{
for term_ref in term.arith_expr_iter()? { let mut code = vec![];
for term_ref in src.iter()?
{
match term_ref? { match term_ref? {
ArithTermRef::Constant(c) => self.push_constant(c)?, ArithTermRef::Constant(c) => self.push_constant(c)?,
ArithTermRef::Var(cell, name) => { ArithTermRef::Var(cell, name) => {
@@ -204,7 +225,7 @@ impl<'a> ArithmeticEvaluator<'a> {
code.push(Line::Arithmetic(self.instr_from_clause(&*name, terms)?)); code.push(Line::Arithmetic(self.instr_from_clause(&*name, terms)?));
}, },
ArithTermRef::Op(ClauseType::Root, terms) => { ArithTermRef::Op(ClauseType::Root, terms) => {
let name = term.name().unwrap(); let name = src.root_name()?;
code.push(Line::Arithmetic(self.instr_from_clause(&*name, terms)?)); code.push(Line::Arithmetic(self.instr_from_clause(&*name, terms)?));
}, },
_ => _ =>