]> Repositorios git - scryer-prolog.git/commitdiff
fix arithmetic bugs.
authorMark Thom <[email protected]>
Tue, 7 Nov 2017 05:01:54 +0000 (22:01 -0700)
committerMark Thom <[email protected]>
Tue, 7 Nov 2017 05:01:54 +0000 (22:01 -0700)
src/prolog/arithmetic.rs
src/prolog/ast.rs
src/prolog/codegen.rs
src/prolog/io.rs
src/prolog/machine.rs
src/prolog/macros.rs

index 6c8b1d718c4533c0400b725c8fc6bd7a609f03de..8a93ed3fcf34505d6377209d844969a04ba88d25 100644 (file)
@@ -1,5 +1,7 @@
 use prolog::ast::*;
 use prolog::fixtures::*;
+use prolog::num::{BigInt, Zero};
+use prolog::ordered_float::{OrderedFloat};
 
 use std::cell::Cell;
 use std::cmp::{min, max};
@@ -93,7 +95,7 @@ impl<'a> ArithmeticEvaluator<'a> {
         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: usize)
                     -> Result<ArithmeticInstruction, ArithmeticError>
     {
         match name.as_str() {
@@ -102,7 +104,7 @@ impl<'a> ArithmeticEvaluator<'a> {
         }
     }
 
-    fn gen_bin_instr(name: &Atom, a1: ArithmeticTerm, a2: ArithmeticTerm, t: ArithEvalPlace)
+    fn gen_bin_instr(name: &Atom, a1: ArithmeticTerm, a2: ArithmeticTerm, t: usize)
                      -> Result<ArithmeticInstruction, ArithmeticError>
     {
         match name.as_str() {
@@ -124,53 +126,45 @@ impl<'a> ArithmeticEvaluator<'a> {
         temp
     }
 
-    fn instr_from_clause(&mut self, name: &Atom, terms: &Vec<Box<Term>>, deep: bool)
+    fn instr_from_clause(&mut self, name: &Atom, terms: &Vec<Box<Term>>)
                          -> Result<ArithmeticInstruction, ArithmeticError>
     {
         match terms.len() {
             1 => {
                 let a1 = self.interm.pop().unwrap();
 
-                if deep {
-                    let ninterm = if a1.interm_or(0) == 0 {
-                        self.incr_interm()
-                    } else {
-                        self.interm.push(a1.clone());
-                        a1.interm_or(0)
-                    };
-
-                    Self::get_un_instr(name, a1, ArithEvalPlace::Interm(ninterm))
+                let ninterm = if a1.interm_or(0) == 0 {
+                    self.incr_interm()
                 } else {
-                    Self::get_un_instr(name, a1, ArithEvalPlace::Reg(RegType::Temp(2)))
-                }
+                    self.interm.push(a1.clone());
+                    a1.interm_or(0)
+                };
+
+                Self::get_un_instr(name, a1, ninterm)
             },
             2 => {
                 let a2 = self.interm.pop().unwrap();
                 let a1 = self.interm.pop().unwrap();
 
-                if deep {
-                    let min_interm = min(a1.interm_or(0), a2.interm_or(0));
+                let min_interm = min(a1.interm_or(0), a2.interm_or(0));
 
-                    let ninterm = if min_interm == 0 {
-                        let max_interm = max(a1.interm_or(0), a2.interm_or(0));
+                let ninterm = if min_interm == 0 {
+                    let max_interm = max(a1.interm_or(0), a2.interm_or(0));
 
-                        if max_interm == 0 {
-                            self.incr_interm()
-                        } else {
-                            self.interm.push(ArithmeticTerm::Interm(max_interm));
-                            self.interm_c = max_interm + 1;
-                            max_interm
-                        }
+                    if max_interm == 0 {
+                        self.incr_interm()
                     } else {
-                        self.interm.push(ArithmeticTerm::Interm(min_interm));
-                        self.interm_c = min_interm + 1;
-                        min_interm
-                    };
-
-                    Self::gen_bin_instr(name, a1, a2, ArithEvalPlace::Interm(ninterm))
+                        self.interm.push(ArithmeticTerm::Interm(max_interm));
+                        self.interm_c = max_interm + 1;
+                        max_interm
+                    }
                 } else {
-                    Self::gen_bin_instr(name, a1, a2, ArithEvalPlace::Reg(RegType::Temp(2)))
-                }
+                    self.interm.push(ArithmeticTerm::Interm(min_interm));
+                    self.interm_c = min_interm + 1;
+                    min_interm
+                };
+
+                Self::gen_bin_instr(name, a1, a2, ninterm)
             },
             _ => Err(ArithmeticError::InvalidOp)
         }
@@ -200,7 +194,7 @@ impl<'a> ArithmeticEvaluator<'a> {
                     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),
+                            Some(&VarData::Perm(p)) if p != 0 => RegType::Perm(p),
                             _ => return Err(ArithmeticError::UninstantiatedVar)
                         }
                     } else {
@@ -210,11 +204,11 @@ impl<'a> ArithmeticEvaluator<'a> {
                     self.interm.push(ArithmeticTerm::Reg(r));
                 },
                 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)?));
                 },
                 TermRef::Clause(ClauseType::Root, terms) => {
                     let name = term.name().unwrap();
-                    code.push(Line::Arithmetic(self.instr_from_clause(name, terms, false)?));
+                    code.push(Line::Arithmetic(self.instr_from_clause(name, terms)?));
                 },
                 _ =>
                     return Err(ArithmeticError::InvalidTerm)
@@ -223,20 +217,22 @@ impl<'a> ArithmeticEvaluator<'a> {
 
         if let Some(arith_term) = self.interm.pop() {
             match arith_term {
-                ArithmeticTerm::Integer(n) => {
-                    let n = Constant::Integer(n);
-                    code.push(query![put_constant!(Level::Shallow, n, temp_v!(2))]);
+                n @ ArithmeticTerm::Integer(_) => {
+                    let zero = ArithmeticTerm::Integer(BigInt::zero());
+                    code.push(arith![add!(zero, n, 1)]);
+                },
+                n @ ArithmeticTerm::Float(_) => {
+                    let zero = ArithmeticTerm::Float(OrderedFloat(0f64));
+                    code.push(arith![add!(zero, n, 1)]);
                 },
-                ArithmeticTerm::Float(n) => {
-                    let n = Constant::Float(n);
-                    code.push(query![put_constant!(Level::Shallow, n, temp_v!(2))]);
+                r @ ArithmeticTerm::Reg(_) => {
+                    let zero = ArithmeticTerm::Integer(BigInt::zero());
+                    code.push(arith![add!(zero, r, 1)]);
                 },
-                ArithmeticTerm::Reg(r) =>
-                    code.push(query![put_value!(r, 2)]),                
-                _ => return Err(ArithmeticError::InvalidTerm)
+                _ => {}
             };
         }
-
+        
         Ok(code)
     }
 }
index d51756b02eebee07813a41982459c3dd4c22eff4..05fc31b531e535b7fdb9da336f0a65f98510e81a 100644 (file)
@@ -556,17 +556,12 @@ impl ArithmeticTerm {
     }
 }
 
-#[derive(Clone, Copy)]
-pub enum ArithEvalPlace {
-    Interm(usize), Reg(RegType)
-}
-
 pub enum ArithmeticInstruction {
-    Add(ArithmeticTerm, ArithmeticTerm, ArithEvalPlace),
-    Sub(ArithmeticTerm, ArithmeticTerm, ArithEvalPlace),
-    Mul(ArithmeticTerm, ArithmeticTerm, ArithEvalPlace),
-    IDiv(ArithmeticTerm, ArithmeticTerm, ArithEvalPlace),
-    Neg(ArithmeticTerm, ArithEvalPlace)
+    Add(ArithmeticTerm, ArithmeticTerm, usize),
+    Sub(ArithmeticTerm, ArithmeticTerm, usize),
+    Mul(ArithmeticTerm, ArithmeticTerm, usize),
+    IDiv(ArithmeticTerm, ArithmeticTerm, usize),
+    Neg(ArithmeticTerm, usize)
 }
 
 pub enum BuiltInInstruction {
@@ -588,20 +583,20 @@ pub enum BuiltInInstruction {
 }
 
 pub enum ControlInstruction {
-    Allocate(usize),
-    Call(Atom, usize, usize),
-    CallN(usize),
+    Allocate(usize), // num_frames.
+    Call(Atom, usize, usize), // name, arity, perm_vars after threshold.
+    CallN(usize), // arity.
     CatchCall,
     CatchExecute,
     Deallocate,
     Execute(Atom, usize),
     ExecuteN(usize),
     Goto(usize, usize), // p, arity.
+    IsCall(RegType),
+    IsExecute(RegType),
     Proceed,
     ThrowCall,
-    ThrowExecute,
-    UnifyCall,
-    UnifyExecute
+    ThrowExecute,    
 }
 
 impl ControlInstruction {
@@ -617,8 +612,8 @@ impl ControlInstruction {
             &ControlInstruction::ThrowExecute => true,
             &ControlInstruction::Goto(_, _) => true,
             &ControlInstruction::Proceed => true,
-            &ControlInstruction::UnifyCall => true,
-            &ControlInstruction::UnifyExecute => true,            
+            &ControlInstruction::IsCall(_) => true,
+            &ControlInstruction::IsExecute(_) => true,            
             _ => false
         }
     }
index d5164e5fe2c7b655fabfd65232347c6cadde9ecc..b8625a2375289a98a180901ccfc665247c12c3be 100644 (file)
@@ -7,6 +7,7 @@ use prolog::iterators::*;
 use prolog::targets::*;
 
 use std::collections::HashMap;
+use std::mem::swap;
 use std::vec::Vec;
 
 pub struct CodeGenerator<'a, TermMarker> {
@@ -218,9 +219,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
             },
             QueryTermRef::Catch(_) =>
                 compiled_query.push(Line::Control(ControlInstruction::CatchCall)),
-            QueryTermRef::IsAtomic(_) =>
-                compiled_query.push(proceed!()),
-            QueryTermRef::IsVar(_) =>
+            QueryTermRef::IsAtomic(_) | QueryTermRef::IsVar(_) =>
                 compiled_query.push(proceed!()),
             QueryTermRef::Term(&Term::Constant(_, Constant::Atom(ref atom))) => {
                 let call = ControlInstruction::Call(atom.clone(), 0, pvs);
@@ -236,41 +235,29 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
         }
     }
 
-    fn lco(code: &mut Code, toc: QueryTermRef<'a>) -> usize
+    fn lco(code: &mut Code) -> usize
     {
-        let last_arity = toc.arity();
         let mut dealloc_index = code.len() - 1;
 
-        match toc {
-            QueryTermRef::Term(&Term::Clause(_, ref name, _))
-          | QueryTermRef::Term(&Term::Constant(_, Constant::Atom(ref name))) =>
-                if let &mut Line::Control(ref mut ctrl) = code.last_mut().unwrap() {
-                    *ctrl = ControlInstruction::Execute(name.clone(), last_arity);
-                },
-            QueryTermRef::CallN(terms) =>
-                if let &mut Line::Control(ref mut ctrl) = code.last_mut().unwrap() {
-                    *ctrl = ControlInstruction::ExecuteN(terms.len());
-                },
-            QueryTermRef::Catch(_) =>
-                if let &mut Line::Control(ref mut ctrl) = code.last_mut().unwrap() {
-                    *ctrl = ControlInstruction::CatchExecute;
-                },
-            QueryTermRef::Cut => {},
-            QueryTermRef::Throw(_) =>
-                if let &mut Line::Control(ref mut ctrl) = code.last_mut().unwrap() {
-                    *ctrl = ControlInstruction::ThrowExecute;
-                },
-            QueryTermRef::Is(_) =>
-                if let &mut Line::Control(ref mut ctrl) = code.last_mut().unwrap() {
-                    *ctrl = ControlInstruction::UnifyExecute;
-                },
-            QueryTermRef::IsAtomic(_) | QueryTermRef::IsVar(_) => {
-                dealloc_index = code.len();
-                code.push(proceed!());
-            },
-            _ => dealloc_index = code.len()
-        };
-
+        if let Some(&mut Line::Control(ref mut ctrl)) = code.last_mut() {
+            let mut instr = ControlInstruction::Proceed;
+            swap(ctrl, &mut instr);
+            
+            match instr {
+                ControlInstruction::Call(name, arity, _) =>
+                    *ctrl = ControlInstruction::Execute(name, arity),
+                ControlInstruction::CallN(arity) =>
+                    *ctrl = ControlInstruction::ExecuteN(arity),
+                ControlInstruction::IsCall(r) =>
+                    *ctrl = ControlInstruction::IsExecute(r),
+                ControlInstruction::CatchCall =>
+                    *ctrl = ControlInstruction::CatchExecute,
+                ControlInstruction::ThrowCall =>
+                    *ctrl = ControlInstruction::ThrowExecute,
+                _ => dealloc_index += 1 // = code.len()
+            }
+        }
+        
         dealloc_index
     }
 
@@ -310,31 +297,39 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                             let mut evaluator = ArithmeticEvaluator::new(self.marker.bindings());
                              evaluator.eval(terms[1].as_ref())?
                         };
-                        
+
                         code.append(&mut arith_code);
 
                         match terms[0].as_ref() {
-                            &Term::Var(ref vr, ref name) => {
-                                let mut target = Vec::new();
+                            &Term::Var(ref vr, ref name) =>
+                                match self.marker.bindings().get(name) {
+                                    Some(&VarData::Temp(_, t, _)) if t != 0 =>
+                                        code.push(is_call!(temp_v!(t))),
+                                    Some(&VarData::Perm(p)) if p != 0 =>
+                                        code.push(is_call!(perm_v!(p))),
+                                    _ => {
+                                        let mut target = Vec::new();
 
-                                self.marker.advance(term_loc, *term);
-                                self.marker.mark_var(name, Level::Shallow, vr, term_loc, &mut target);
+                                        // reset self.marker.arg_c to 1.
+                                        self.marker.advance(term_loc, *term);
+                                        self.marker.mark_var(name, Level::Shallow, vr, term_loc, &mut target);
 
-                                code.push(Line::Query(target));
-                                code.push(unify_call!());
-                            },
+                                        code.push(Line::Query(target));
+                                        code.push(is_call!(vr.get().norm()));
+                                    }
+                                },
                             &Term::Constant(_, Constant::Float(fl)) => {
                                 code.push(query![put_constant!(Level::Shallow,
                                                                Constant::Float(fl),
                                                                temp_v!(1))]);
-                                code.push(unify_call!());
+                                code.push(is_call!(temp_v!(1)));
                             },
                             &Term::Constant(_, Constant::Integer(ref bi)) => {
                                 let bi = bi.clone();
                                 code.push(query![put_constant!(Level::Shallow,
                                                                Constant::Integer(bi),
                                                                temp_v!(1))]);
-                                code.push(unify_call!());
+                                code.push(is_call!(temp_v!(1)));
                             },
                             _ => {
                                 return Err(ParserError::from(ArithmeticError::InvalidTerm));
@@ -357,9 +352,9 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                                         code.push(is_atomic!(RegType::Perm(p))),
                                     _ => {
                                         let mut target = Vec::new();
-                                        
+
                                         // reset self.marker.arg_c to 1.
-                                        self.marker.advance(term_loc, *term); 
+                                        self.marker.advance(term_loc, *term);
                                         self.marker.mark_var(name, Level::Shallow, vr, term_loc, &mut target);
 
                                         code.push(Line::Query(target));
@@ -383,9 +378,9 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
                                         code.push(is_var!(RegType::Perm(p))),
                                     _ => {
                                         let mut target = Vec::new();
-                                        
+
                                         // reset self.marker.arg_c to 1.
-                                        self.marker.advance(term_loc, *term); 
+                                        self.marker.advance(term_loc, *term);
                                         self.marker.mark_var(name, Level::Shallow, vr, term_loc, &mut target);
 
                                         code.push(Line::Query(target));
@@ -419,19 +414,26 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
             let perm_vars = conjunct_info.perm_vars();
 
             body.push(Line::Control(ControlInstruction::Allocate(perm_vars)));
-            
+
             if conjunct_info.has_deep_cut {
                 body.push(Line::Cut(CutInstruction::GetLevel));
             }
         }
     }
 
-    fn compile_cleanup(body: &mut Code, conjunct_info: &ConjunctInfo, toc: QueryTermRef<'a>)
+    fn compile_cleanup(code: &mut Code, conjunct_info: &ConjunctInfo, toc: QueryTermRef<'a>)
     {
-        let dealloc_index = Self::lco(body, toc);
+        //TODO: temporary workaround for inlined builtins.
+        match toc {
+            QueryTermRef::IsAtomic(_) | QueryTermRef::IsVar(_) =>
+                code.push(proceed!()),
+            _ => {}
+        }
+        
+        let dealloc_index = Self::lco(code);
 
         if conjunct_info.allocates() {
-            body.insert(dealloc_index, Line::Control(ControlInstruction::Deallocate));
+            code.insert(dealloc_index, Line::Control(ControlInstruction::Deallocate));
         }
     }
 
index 0b64587f71a88e9833310b5ef94df1ad88750cc6..38f46bfe79a3c0518e42414fe498d5edad614d1c 100644 (file)
@@ -107,10 +107,10 @@ impl fmt::Display for ControlInstruction {
                 write!(f, "call_throw"),
             &ControlInstruction::ThrowExecute =>
                 write!(f, "execute_throw"),
-            &ControlInstruction::UnifyCall =>
-                write!(f, "unify_call"),
-            &ControlInstruction::UnifyExecute =>
-                write!(f, "unify_execute"),
+            &ControlInstruction::IsCall(r) =>
+                write!(f, "is_call {}", r),
+            &ControlInstruction::IsExecute(r) =>
+                write!(f, "is_execute {}", r),
         }
     }
 }
@@ -203,30 +203,19 @@ impl fmt::Display for ArithmeticTerm {
     }
 }
 
-impl fmt::Display for ArithEvalPlace {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match self {
-            &ArithEvalPlace::Reg(r) =>
-                write!(f, "{}", r),
-            &ArithEvalPlace::Interm(i) =>
-                write!(f, "@{}", i)
-        }
-    }
-}   
-
 impl fmt::Display for ArithmeticInstruction {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
             &ArithmeticInstruction::Add(ref a1, ref a2, ref t) =>
-                write!(f, "add {}, {}, {}", a1, a2, t),
+                write!(f, "add {}, {}, @{}", a1, a2, t),
             &ArithmeticInstruction::Sub(ref a1, ref a2, ref t) =>
-                write!(f, "sub {}, {}, {}", a1, a2, t),
+                write!(f, "sub {}, {}, @{}", a1, a2, t),
             &ArithmeticInstruction::Mul(ref a1, ref a2, ref t) =>
-                write!(f, "mul {}, {}, {}", a1, a2, t),
+                write!(f, "mul {}, {}, @{}", a1, a2, t),
             &ArithmeticInstruction::IDiv(ref a1, ref a2, ref t) =>
-                write!(f, "idiv {}, {}, {}", a1, a2, t),
+                write!(f, "idiv {}, {}, @{}", a1, a2, t),
             &ArithmeticInstruction::Neg(ref a, ref t) =>
-                write!(f, "neg {}, {}", a, t)
+                write!(f, "neg {}, @{}", a, t)
         }
     }
 }
@@ -343,7 +332,7 @@ pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalSession<'
                 Ok(pred) => pred,
                 Err(e)   => return EvalSession::ParserError(e)
             };
-        
+
             wam.add_predicate(clauses, compiled_pred)
         },
         &TopLevel::Fact(ref fact) => {
@@ -359,7 +348,7 @@ pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalSession<'
                 Ok(rule) => rule,
                 Err(e) => return EvalSession::ParserError(e)                
             };
-            
+
             wam.add_rule(rule, compiled_rule)
         },
         &TopLevel::Query(ref query) => {
@@ -369,7 +358,7 @@ pub fn eval<'a, 'b: 'a>(wam: &'a mut Machine, tl: &'b TopLevel) -> EvalSession<'
                 Ok(query) => query,
                 Err(e) => return EvalSession::ParserError(e)
             };
-            
+
             wam.submit_query(compiled_query, cg.take_vars())
         }
     }
index fcca23c2268b00f582fd53a3c0220d66cd8e1370..68374c929e4827749ebc696aca22eb58842972b0 100644 (file)
@@ -765,7 +765,7 @@ impl MachineState {
                 Ref::HeapCell(r) =>
                     self.heap[r] = HeapCellValue::Ref(Ref::HeapCell(r)),
                 Ref::StackCell(fr, sc) =>
-                    self.and_stack[fr][sc] = Addr::StackCell(fr, sc)                   
+                    self.and_stack[fr][sc] = Addr::StackCell(fr, sc)
             }
         }
     }
@@ -848,42 +848,33 @@ impl MachineState {
                         Err("is/2: variable not instantiated to number.")
                 }
             },
-            &ArithmeticTerm::Interm(i)   => Ok(self.interms[i].clone()),
+            &ArithmeticTerm::Interm(i)   => Ok(self.interms[i-1].clone()),
             &ArithmeticTerm::Float(fl)   => Ok(Number::Float(fl)),
             &ArithmeticTerm::Integer(ref bi) => Ok(Number::Integer(bi.clone()))
         }
     }
 
-    fn assign_arith(&mut self, t: ArithEvalPlace, n: Number) {
-        match t {
-            ArithEvalPlace::Reg(r) =>
-                self[r] = Addr::Con(Constant::from(n)),
-            ArithEvalPlace::Interm(i) =>
-                self.interms[i] = n
-        }
-    }
-
     fn execute_arith_instr(&mut self, instr: &ArithmeticInstruction) {
         match instr {
             &ArithmeticInstruction::Add(ref a1, ref a2, t) => {
                 let n1 = try_or_fail!(self, self.get_number(a1));
                 let n2 = try_or_fail!(self, self.get_number(a2));
 
-                self.assign_arith(t, n1 + n2);
+                self.interms[t - 1] = n1 + n2;
                 self.p += 1;
             },
             &ArithmeticInstruction::Sub(ref a1, ref a2, t) => {
                 let n1 = try_or_fail!(self, self.get_number(a1));
                 let n2 = try_or_fail!(self, self.get_number(a2));
 
-                self.assign_arith(t, n1 - n2);
+                self.interms[t - 1] = n1 - n2;
                 self.p += 1;
             },
             &ArithmeticInstruction::Mul(ref a1, ref a2, t) => {
                 let n1 = try_or_fail!(self, self.get_number(a1));
                 let n2 = try_or_fail!(self, self.get_number(a2));
 
-                self.assign_arith(t, n1 * n2);
+                self.interms[t - 1] = n1 * n2;
                 self.p += 1;
             },
             &ArithmeticInstruction::IDiv(ref a1, ref a2, t) => {
@@ -899,7 +890,7 @@ impl MachineState {
                             return;
                         }
 
-                        self.assign_arith(t, Number::Integer(n1 / n2));
+                        self.interms[t - 1] = Number::Integer(n1 / n2);
                         self.p += 1;
                     },
                     _ => {
@@ -913,7 +904,7 @@ impl MachineState {
             &ArithmeticInstruction::Neg(ref a1, t) => {
                 let n1 = try_or_fail!(self, self.get_number(a1));
 
-                self.assign_arith(t, - n1);
+                self.interms[t - 1] = - n1;
                 self.p += 1;
             }
         };
@@ -1492,8 +1483,7 @@ impl MachineState {
                 let d = self.deref(self[r].clone());
 
                 match d {
-                    Addr::HeapCell(_) | Addr::StackCell(_,_) =>
-                        self.p += 1,
+                    Addr::HeapCell(_) | Addr::StackCell(_,_) => self.p += 1,
                     _ => self.fail = true
                 };
             },
@@ -1507,23 +1497,19 @@ impl MachineState {
                 self.p += 1;
             },
             &BuiltInInstruction::Unify => {
-                self.inline_unify();
+                let a1 = self[temp_v!(1)].clone();
+                let a2 = self[temp_v!(2)].clone();
+
+                self.unify(a1, a2);
                 self.p += 1;
             }
         };
     }
 
-    fn inline_unify(&mut self) {
-        let a1 = self[temp_v!(1)].clone();
-        let a2 = self[temp_v!(2)].clone();
-        
-        self.unify(a1, a2);        
-    }
-    
     fn execute_ctrl_instr(&mut self, code_dir: &CodeDir, instr: &ControlInstruction)
     {
         match instr {
-            &ControlInstruction::Allocate(num_cells) => {                
+            &ControlInstruction::Allocate(num_cells) => {
                 let num_frames = self.num_frames();
                 self.and_stack.push(num_frames + 1, self.e, self.cp, num_cells);
 
@@ -1575,14 +1561,20 @@ impl MachineState {
             &ControlInstruction::ThrowExecute => {
                 self.goto_throw();
             },
-            &ControlInstruction::UnifyCall => {
-                self.inline_unify();
+            &ControlInstruction::IsCall(r) => {
+                let a1 = self[r].clone();
+                let a2 = Addr::Con(Constant::from(self.interms[0].clone()));
+
+                self.unify(a1, a2);
                 self.p += 1;
             },
-            &ControlInstruction::UnifyExecute => {
-                self.inline_unify();
+            &ControlInstruction::IsExecute(r) => {
+                let a1 = self[r].clone();
+                let a2 = Addr::Con(Constant::from(self.interms[0].clone()));
+
+                self.unify(a1, a2);
                 self.p = self.cp;
-            }            
+            }
         };
     }
 
index 1fa4b4d0f71d6829aafc5f574b2c8987c21b35fb..75ee4eb690ce6ca7b1022ea71d438b67edbf2abf 100644 (file)
@@ -22,6 +22,12 @@ macro_rules! query {
     )
 }
 
+macro_rules! arith {
+    ($x:expr) => (
+        Line::Arithmetic($x)
+    )
+}
+
 macro_rules! string {
     ($str:expr) => {
         vec![HeapCellValue::Con(Constant::String(String::from($str)))]
@@ -105,6 +111,12 @@ macro_rules! put_unsafe_value {
     )
 }
 
+macro_rules! add {
+    ($r1:expr, $r2:expr, $t:expr) => (
+        ArithmeticInstruction::Add($r1, $r2, $t)
+    )
+}
+
 macro_rules! try_me_else {
     ($o:expr) => (
         Line::Choice(ChoiceInstruction::TryMeElse($o))
@@ -209,9 +221,9 @@ macro_rules! unify {
     )
 }
 
-macro_rules! unify_call {
-    () => (
-        Line::Control(ControlInstruction::UnifyCall)
+macro_rules! is_call {
+    ($r:expr) => (
+        Line::Control(ControlInstruction::IsCall($r))
     )
 }