]> Repositorios git - scryer-prolog.git/commitdiff
abstract out iterator for arithmetic terms.
authorMark Thom <[email protected]>
Thu, 18 Jan 2018 05:43:46 +0000 (22:43 -0700)
committerMark Thom <[email protected]>
Thu, 18 Jan 2018 05:43:46 +0000 (22:43 -0700)
src/prolog/arithmetic.rs

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