]> Repositorios git - scryer-prolog.git/commitdiff
fix bugs in call_with_inference_limit
authorMark Thom <[email protected]>
Thu, 22 Feb 2018 02:46:15 +0000 (19:46 -0700)
committerMark Thom <[email protected]>
Thu, 22 Feb 2018 02:46:15 +0000 (19:46 -0700)
13 files changed:
src/main.rs
src/prolog/ast.rs
src/prolog/builtins.rs
src/prolog/io.rs
src/prolog/lib/control.pl [new file with mode: 0644]
src/prolog/lib/control.rs [deleted file]
src/prolog/lib/lists.pl [new file with mode: 0644]
src/prolog/lib/lists.rs [deleted file]
src/prolog/lib/mod.rs [deleted file]
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/macros.rs
src/prolog/mod.rs

index 3b4a49003a39c84727baa181a2ed6f4b9f74d146..c7ae8b1d3bb571780aeef84c974f9b8248620d1c 100644 (file)
@@ -6,13 +6,14 @@ mod prolog;
 #[macro_use] mod test_utils;
 
 use prolog::io::*;
-use prolog::lib::control::*;
-use prolog::lib::lists::*;
 use prolog::machine::*;
 
 #[cfg(test)]
 mod tests;
 
+pub static LISTS: &str   = include_str!("./prolog/lib/lists.pl");
+pub static CONTROL: &str = include_str!("./prolog/lib/control.pl");
+
 fn process_buffer(wam: &mut Machine, buffer: &str)
 {
     match parse_code(wam, buffer) {
index 6eff00d331e96a54445206abf6921fd61cb98e83..86ea088de33901da444d47043ed2e45cde496533 100644 (file)
@@ -890,7 +890,7 @@ pub enum BuiltInInstruction {
     GetCutPoint(RegType),
     InferenceLevel,
     InstallCleaner,
-    InstallInferenceCounter(RegType),
+    InstallInferenceCounter(RegType, RegType, RegType),
     InstallNewBlock,
     InternalCallN,
     IsAtomic(RegType),
@@ -901,7 +901,8 @@ pub enum BuiltInInstruction {
     IsRational(RegType),
     IsString(RegType),
     IsVar(RegType),
-    RemoveInferenceCounter(RegType),
+    RemoveCallPolicyCheck,
+    RemoveInferenceCounter(RegType, RegType),
     ResetBlock,
     RestoreCutPolicy,
     SetBall,
index 97462fbb31ea5a3c51e504703c9a56d92cc42853..32d28dcddf84926b8d0bbbfbd916940c5e48d3f3 100644 (file)
@@ -548,74 +548,89 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
          compare_term_execute!(term_cmp_lt!()), // (@<)/2, 390.
          compare_term_execute!(term_cmp_eq!()), // (=@=)/2, 391.
          compare_term_execute!(term_cmp_ne!()), // (\=@=)/2, 392.
-         allocate!(4), // call_with_inference_limit/3, 393.
-         fact![get_var_in_fact!(perm_v!(3), 1),
-               get_var_in_fact!(perm_v!(2), 2),
-               get_var_in_fact!(perm_v!(1), 3)],
-         query![put_var!(perm_v!(4), 1)],
+         allocate!(5), // call_with_inference_limit/3, 393.
+         fact![get_var_in_fact!(perm_v!(4), 1),
+               get_var_in_fact!(perm_v!(3), 2),
+               get_var_in_fact!(perm_v!(2), 3)],
+         query![put_var!(perm_v!(5), 1)],
          get_current_block!(),
-         query![put_value!(perm_v!(3), 1),
-                put_value!(perm_v!(2), 2),
-                put_value!(perm_v!(1), 3),
-                put_value!(perm_v!(4), 4)],
+         get_cp!(perm_v!(1)),
+         query![put_value!(perm_v!(4), 1),
+                put_value!(perm_v!(3), 2),
+                put_value!(perm_v!(2), 3),
+                put_value!(perm_v!(5), 4),
+                put_value!(perm_v!(1), 5)],
+         goto_call!(404, 5), // goto call_with_inference_limit/4, 404.
+         query![put_value!(perm_v!(1), 1)],
          deallocate!(),
-         goto_execute!(400, 4), // goto call_with_inference_limit/4, 400.
-         try_me_else!(16), // call_with_inference_limit/4, 400.
-         allocate!(7),
-         fact![get_var_in_fact!(perm_v!(6), 1),
-               get_var_in_fact!(perm_v!(7), 2),
-               get_var_in_fact!(perm_v!(4), 3),
-               get_var_in_fact!(perm_v!(3), 4)],
+         remove_call_policy_check!(),
+         proceed!(),
+         try_me_else!(18), // call_with_inference_limit/5, 404.
+         allocate!(9),
+         fact![get_var_in_fact!(perm_v!(9), 1),
+               get_var_in_fact!(perm_v!(6), 2),
+               get_var_in_fact!(perm_v!(5), 3),
+               get_var_in_fact!(perm_v!(3), 4),
+               get_var_in_fact!(perm_v!(4), 5)],
          query![put_var!(perm_v!(1), 1)],
          install_new_block!(),
-         install_inference_counter!(perm_v!(7)),
-         get_cp!(perm_v!(5)),
-         query![put_value!(perm_v!(6), 1)],
+         install_inference_counter!(perm_v!(4), perm_v!(6), perm_v!(8)),
+         query![put_value!(perm_v!(9), 1)],
          call_n!(1),
-         query![put_var!(perm_v!(2), 3)],
-         remove_inference_counter!(perm_v!(2)),
-         query![put_value!(perm_v!(4), 1),
-                put_value!(perm_v!(5), 2)],
+         remove_inference_counter!(perm_v!(4), perm_v!(7)),
+         sub!(ArithmeticTerm::Reg(perm_v!(7)),
+              ArithmeticTerm::Reg(perm_v!(8)),
+              1),
+         sub!(ArithmeticTerm::Reg(perm_v!(6)),
+              ArithmeticTerm::Interm(1),
+              1),
+         query![put_value!(perm_v!(2), 1)],
+         is_call!(temp_v!(1), ArithmeticTerm::Interm(1)),
+         query![put_value!(perm_v!(5), 1),
+                put_value!(perm_v!(4), 2)],
          inference_level!(),
-         query![put_value!(perm_v!(3), 1),
-                put_value!(perm_v!(1), 2),
-                put_value!(perm_v!(2), 3)],
+         query![put_value!(perm_v!(4), 1),
+                put_value!(perm_v!(3), 2),
+                put_value!(perm_v!(1), 3),
+                put_value!(perm_v!(2), 4)],
          deallocate!(),
-         goto_execute!(436, 3), // goto end_block/3, 436.
-         default_trust_me!(), // 416.
-         allocate!(2),
-         fact![get_var_in_fact!(perm_v!(1), 3)],
+         goto_execute!(442, 4), // goto end_block/4, 442.
+         default_trust_me!(), // 422.
+         allocate!(3),
+         fact![get_var_in_fact!(perm_v!(1), 3),
+               get_var_in_fact!(perm_v!(3), 5)],
          query![put_value!(temp_v!(4), 1)],
          reset_block!(),
-         query![put_var!(temp_v!(2), 1)],
-         remove_inference_counter!(temp_v!(1)),
+         query![put_var!(temp_v!(3), 2)],
+         remove_inference_counter!(perm_v!(3), temp_v!(2)),
          query![put_var!(perm_v!(2), 1)],
          get_ball!(),
          erase_ball!(),
-         query![put_unsafe_value!(2, 1),
-                put_value!(perm_v!(1), 2)],
+         query![put_value!(perm_v!(3), 1),
+                put_unsafe_value!(2, 2),
+                put_value!(perm_v!(1), 3)],
          deallocate!(),
-         goto_execute!(429, 2), // goto handle_ile/2, 429.
-         try_me_else!(5), // handle_ile/2, 429.
-         switch_on_term!(1, 1, 0, 0),
-         fact![get_constant!(atom!("inference_limit_exceeded", atom_tbl), temp_v!(1)),
-               get_constant!(atom!("inference_limit_exceeded", atom_tbl), temp_v!(2))],
+         goto_execute!(435, 3), // goto handle_ile/3, 435.
+         try_me_else!(4), // handle_ile/3, 435.
+         fact![get_structure!(atom_tbl, "inference_limit_exceeded", 1, temp_v!(2), None),
+               unify_value!(temp_v!(1)),
+               get_constant!(atom!("inference_limit_exceeded", atom_tbl), temp_v!(3))],
          neck_cut!(),
          proceed!(),
          default_trust_me!(),
-         goto_execute!(59, 1), // goto throw/1, 59.
-         try_me_else!(9), // end_block/3, 436.
-         allocate!(1),
-         fact![get_var_in_fact!(perm_v!(1), 1)],
          query![put_value!(temp_v!(2), 1)],
+         goto_execute!(59, 1), // goto throw/1, 59.
+         try_me_else!(6), // end_block/4, 442.
+         query![put_value!(temp_v!(3), 1)],
          clean_up_block!(),
-         query![put_value!(perm_v!(1), 1)],
-         deallocate!(),
+         query![put_value!(temp_v!(2), 1)],
          reset_block!(),
          proceed!(),
          default_trust_me!(),
-         install_inference_counter!(temp_v!(3)),
-         query![put_value!(temp_v!(2), 1)],
+         query![put_value!(temp_v!(4), 2),
+                put_var!(temp_v!(4), 4)],
+         install_inference_counter!(temp_v!(1), temp_v!(2), temp_v!(4)),
+         query![put_value!(temp_v!(3), 1)],
          reset_block!(),
          fail!()
     ]
index bb7ccbcc007a5d70c5ce0ba6d9518d53526c52e0..3a0a083f9c80ad34b45570f3dc3c2808fb1a4e75 100644 (file)
@@ -209,8 +209,8 @@ impl fmt::Display for BuiltInInstruction {
                 write!(f, "clean_up_block"),
             &BuiltInInstruction::DefaultTrustMe =>
                 write!(f, "default_trust_me"),
-            &BuiltInInstruction::InstallInferenceCounter(r) =>
-                write!(f, "install_inference_counter {}", r),
+            &BuiltInInstruction::InstallInferenceCounter(r1, r2, r3) =>
+                write!(f, "install_inference_counter {}, {}, {}", r1, r2, r3),
             &BuiltInInstruction::EraseBall =>
                 write!(f, "erase_ball"),
             &BuiltInInstruction::Fail =>
@@ -267,8 +267,10 @@ impl fmt::Display for BuiltInInstruction {
                 write!(f, "number_test {}, {}, {} ", cmp, at_1, at_2),
             &BuiltInInstruction::DynamicCompareNumber(cmp) =>
                 write!(f, "dynamic_number_test {}", cmp),
-            &BuiltInInstruction::RemoveInferenceCounter(r) =>
-                write!(f, "remove_inference_counter {}", r)
+            &BuiltInInstruction::RemoveCallPolicyCheck =>
+                write!(f, "remove_call_policy_check"),
+            &BuiltInInstruction::RemoveInferenceCounter(r1, r2) =>
+                write!(f, "remove_inference_counter {}, {}", r1, r2)
         }
     }
 }
diff --git a/src/prolog/lib/control.pl b/src/prolog/lib/control.pl
new file mode 100644 (file)
index 0000000..df794db
--- /dev/null
@@ -0,0 +1,13 @@
+:- op(700, xfx, \=).
+
+once(G) :- G, !.
+
+\=(X, X) :- !, false.
+\=(_, _).
+
+between(Lower, Upper, Lower) :-
+    Lower =< Upper.
+between(Lower1, Upper, X) :-
+    Lower1 < Upper,
+    Lower2 is Lower1 + 1,
+    between(Lower2, Upper, X).
diff --git a/src/prolog/lib/control.rs b/src/prolog/lib/control.rs
deleted file mode 100644 (file)
index 41ce18b..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-pub static CONTROL: &str = ":- op(700, xfx, \\=).
-
-                            once(G) :- G, !.
-
-                            \\=(X, X) :- !, false.
-                            \\=(_, _).
-
-                            between(Lower, Upper, Lower) :-
-                               Lower =< Upper.
-                            between(Lower1, Upper, X) :-
-                               Lower1 < Upper,
-                               Lower2 is Lower1 + 1,
-                               between(Lower2, Upper, X).";
diff --git a/src/prolog/lib/lists.pl b/src/prolog/lib/lists.pl
new file mode 100644 (file)
index 0000000..3816c54
--- /dev/null
@@ -0,0 +1,57 @@
+member(X, [X|_]).
+member(X, [_|Xs]) :- member(X, Xs).
+
+select(X, [X|Xs], Xs).
+select(X, [Y|Xs], [Y|Ys]) :- select(X, Xs, Ys).
+
+append([], R, R).
+append([X|L], R, [X|S]) :- append(L, R, S).
+
+memberchk(X, Xs) :- member(X, Xs), !.
+
+reverse(Xs, Ys) :- var(Ys), !, reverse(Xs, [], Ys).
+reverse(Ys, Xs) :- reverse(Xs, [], Ys).
+
+reverse([], Ys, Ys).
+reverse([H|T], Ps, Rs) :-
+    reverse(T, [H|Ps], Rs).
+
+maplist(_, []).
+maplist(Cont1, [E1|E1s]) :-
+    call(Cont1, E1),
+    maplist(Cont1, E1s).
+
+maplist(_, [], []).
+maplist(Cont2, [E1|E1s], [E2|E2s]) :-
+    call(Cont2, E1, E2),
+    maplist(Cont2, E1s, E2s).
+
+maplist(_, [], [], []).
+maplist(Cont3, [E1|E1s], [E2|E2s], [E3|E3s]) :-
+    call(Cont3, E1, E2, E3),
+    maplist(Cont3, E1s, E2s, E3s).
+
+maplist(_, [], [], [], []).
+maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s]) :-
+    call(Cont, E1, E2, E3, E4),
+    maplist(Cont, E1s, E2s, E3s, E4s).
+
+maplist(_, [], [], [], [], []).
+maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s]) :-
+    call(Cont, E1, E2, E3, E4, E5),
+    maplist(Cont, E1s, E2s, E3s, E4s, E5s).
+
+maplist(_, [], [], [], [], [], []).
+maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s]) :-
+    call(Cont, E1, E2, E3, E4, E5, E6),
+    maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s).
+
+maplist(_, [], [], [], [], [], [], []).
+maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7s]) :-
+    call(Cont, E1, E2, E3, E4, E5, E6, E7),
+    maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s, E7s).
+
+maplist(_, [], [], [], [], [], [], [], []).
+maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7s], [E8|E8s]) :-
+    call(Cont, E1, E2, E3, E4, E5, E6, E7),
+    maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s, E7s, E8s).
diff --git a/src/prolog/lib/lists.rs b/src/prolog/lib/lists.rs
deleted file mode 100644 (file)
index 0f503e7..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-pub static LISTS: &str = "member(X, [X|_]).
-                          member(X, [_|Xs]) :- member(X, Xs).
-
-                          select(X, [X|Xs], Xs).
-                          select(X, [Y|Xs], [Y|Ys]) :- select(X, Xs, Ys).
-
-                          append([], R, R).
-                          append([X|L], R, [X|S]) :- append(L, R, S).
-
-                          memberchk(X, Xs) :- member(X, Xs), !.
-
-                          reverse(Xs, Ys) :- var(Ys), !, reverse(Xs, [], Ys).
-                          reverse(Ys, Xs) :- reverse(Xs, [], Ys).
-
-                          reverse([], Ys, Ys).
-                          reverse([H|T], Ps, Rs) :-
-                              reverse(T, [H|Ps], Rs).
-
-                          maplist(_, []).
-                          maplist(Cont1, [E1|E1s]) :-
-                             call(Cont1, E1),
-                             maplist(Cont1, E1s).
-
-                          maplist(_, [], []).
-                          maplist(Cont2, [E1|E1s], [E2|E2s]) :-
-                             call(Cont2, E1, E2),
-                             maplist(Cont2, E1s, E2s).
-
-                          maplist(_, [], [], []).
-                          maplist(Cont3, [E1|E1s], [E2|E2s], [E3|E3s]) :-
-                             call(Cont3, E1, E2, E3),
-                             maplist(Cont3, E1s, E2s, E3s).
-
-                          maplist(_, [], [], [], []).
-                          maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s]) :-
-                             call(Cont, E1, E2, E3, E4),
-                             maplist(Cont, E1s, E2s, E3s, E4s).
-
-                          maplist(_, [], [], [], [], []).
-                          maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s]) :-
-                             call(Cont, E1, E2, E3, E4, E5),
-                             maplist(Cont, E1s, E2s, E3s, E4s, E5s).
-
-                          maplist(_, [], [], [], [], [], []).
-                          maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s]) :-
-                             call(Cont, E1, E2, E3, E4, E5, E6),
-                             maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s).
-
-                          maplist(_, [], [], [], [], [], [], []).
-                          maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7s]) :-
-                             call(Cont, E1, E2, E3, E4, E5, E6, E7),
-                             maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s, E7s).
-
-                          maplist(_, [], [], [], [], [], [], [], []).
-                          maplist(Cont, [E1|E1s], [E2|E2s], [E3|E3s], [E4|E4s], [E5|E5s], [E6|E6s], [E7|E7s], [E8|E8s]) :-
-                             call(Cont, E1, E2, E3, E4, E5, E6, E7),
-                             maplist(Cont, E1s, E2s, E3s, E4s, E5s, E6s, E7s, E8s).";
diff --git a/src/prolog/lib/mod.rs b/src/prolog/lib/mod.rs
deleted file mode 100644 (file)
index 21c58b2..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-pub mod control;
-pub mod lists;
-
index eff3a5c4e389b0308c150ba6d2cbf25b471ddf01..94daa4ac59c32bfa1edfb9c134f724ccd03bb258 100644 (file)
@@ -2,14 +2,12 @@ use prolog::and_stack::*;
 use prolog::builtins::CodeDir;
 use prolog::ast::*;
 use prolog::copier::*;
-use prolog::num::{BigInt, BigUint, Zero, One};
+use prolog::num::{BigInt, Zero, One};
 use prolog::or_stack::*;
 use prolog::tabled_rc::*;
 
 use downcast::Any;
 
-use std::cmp::Ordering;
-use std::collections::binary_heap::BinaryHeap;
 use std::mem::swap;
 use std::ops::{Index, IndexMut};
 use std::rc::Rc;
@@ -249,7 +247,7 @@ pub(crate) trait CallPolicy: Any {
         machine_st.hb = machine_st.heap.h;
 
         machine_st.p += 1;
-        
+
         Ok(())
     }
 
@@ -284,7 +282,7 @@ pub(crate) trait CallPolicy: Any {
     }
 
     fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult
-    {        
+    {
         let b = machine_st.b - 1;
         let n = machine_st.or_stack[b].num_args();
 
@@ -353,69 +351,67 @@ pub(crate) struct DefaultCallPolicy {}
 
 impl CallPolicy for DefaultCallPolicy {}
 
-#[derive(Clone, Eq, PartialEq)]
-struct InferenceLimit(BigUint);
-
-// ensure the heap behaves as a min-heap.
-impl Ord for InferenceLimit {
-    fn cmp(&self, other: &InferenceLimit) -> Ordering {
-        other.0.cmp(&self.0)
-    }
-}
-
-impl PartialOrd for InferenceLimit {
-    fn partial_cmp(&self, other: &InferenceLimit) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-}
-
 pub(crate) struct CallWithInferenceLimitCallPolicy {
     atom_tbl: TabledData<Atom>,
     pub(crate) prev_policy: Box<CallPolicy>,
-    count:  BigUint,
-    limits: BinaryHeap<InferenceLimit>
+    count:  BigInt,
+    limits: Vec<(Rc<BigInt>, usize)>
 }
 
 impl CallWithInferenceLimitCallPolicy {
     pub(crate) fn new_in_place(atom_tbl: TabledData<Atom>, policy: &mut Box<CallPolicy>)
     {
         let mut prev_policy: Box<CallPolicy> = Box::new(DefaultCallPolicy {});
-        swap(&mut prev_policy, policy);        
-        
-        let new_policy = CallWithInferenceLimitCallPolicy { atom_tbl, prev_policy,
-                                                            count:  BigUint::zero(),
-                                                            limits: BinaryHeap::new() };
+        swap(&mut prev_policy, policy);
 
+        let new_policy = CallWithInferenceLimitCallPolicy { atom_tbl, prev_policy,
+                                                            count:  BigInt::zero(),
+                                                            limits: vec![] };
         *policy = Box::new(new_policy);
     }
 
-    fn increment(&mut self) -> CallResult {        
-        if let Some(ref limit) = self.limits.peek() {
-            if self.count == limit.0 {
-                return Err(vec![heap_atom!("inference_limit_exceeded", self.atom_tbl)])
+    fn increment(&mut self) -> CallResult {
+        if let Some(&(ref limit, bp)) = self.limits.last() {
+            if self.count == **limit {
+                return Err(functor!(self.atom_tbl,
+                                    "inference_limit_exceeded",
+                                    1,
+                                    [HeapCellValue::Addr(Addr::Con(Constant::Usize(bp)))]));
             } else {
-                self.count = BigUint::one() + &self.count;
+                self.count = BigInt::one() + &self.count;
             }
         }
 
         Ok(())
     }
 
-    pub(crate) fn add_limit(&mut self, limit: Rc<BigInt>) {
-        match limit.to_biguint() {
-            Some(limit) => self.limits.push(InferenceLimit(limit + &self.count)),
-            _ => panic!("add_limit: expected unsigned integer.")
+    // returns the count.
+    pub(crate) fn add_limit(&mut self, limit: Rc<BigInt>, b: usize) -> Rc<BigInt> {
+        let limit = Rc::new(&*limit + &self.count);
+        
+        match self.limits.last().cloned() {
+            Some((ref inner_limit, _)) if *inner_limit <= limit => {},
+            _ => self.limits.push((limit, b))
         };
+
+        Rc::new(self.count.clone())
     }
 
-    pub(crate) fn remove_limit(&mut self) -> Option<BigUint> {
-        self.limits.pop().map(|i| i.0 - &self.count)
+    // returns the count.
+    pub(crate) fn remove_limit(&mut self, b: usize) -> Rc<BigInt> {
+        if let Some((_, bp)) = self.limits.last().cloned() {
+            if bp == b {
+                self.limits.pop();
+            }
+        }
+
+        Rc::new(self.count.clone())
     }
 
     pub(crate) fn is_empty(&self) -> bool {
         self.limits.is_empty()
     }
-    
+
     pub(crate) fn into_inner(&mut self) -> Box<CallPolicy> {
         let mut new_inner: Box<CallPolicy> = Box::new(DefaultCallPolicy {});
         swap(&mut self.prev_policy, &mut new_inner);
@@ -445,19 +441,19 @@ impl CallPolicy for CallWithInferenceLimitCallPolicy {
         self.prev_policy.retry_me_else(machine_st, offset)?;
         self.increment()
     }
-    
+
     fn retry(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult
     {
         self.prev_policy.retry(machine_st, offset)?;
         self.increment()
     }
-    
+
     fn trust_me(&mut self, machine_st: &mut MachineState) -> CallResult
     {
         self.prev_policy.trust_me(machine_st)?;
         self.increment()
     }
-    
+
     fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult
     {
         self.prev_policy.trust(machine_st, offset)?;
index 3288f361b676b017da43c25c5890cf03129ffc5d..56416a9c61c7d89aa1f081633ee1ea4b60654551 100644 (file)
@@ -1311,11 +1311,11 @@ impl MachineState {
             },
             &BuiltInInstruction::InferenceLevel => { // X1 = R, X2 = B.
                 let a1 = self[temp_v!(1)].clone();
-                let a2 = self.store(self.deref(self[temp_v!(2)].clone()));                
+                let a2 = self.store(self.deref(self[temp_v!(2)].clone()));
 
                 match a2 {
                     Addr::Con(Constant::Usize(bp)) =>
-                        if self.b <= bp {
+                        if self.b <= bp + 1 {
                             let a2 = Addr::Con(atom!("!", self.atom_tbl));
                             self.unify(a1, a2);
                         } else {
@@ -1324,7 +1324,7 @@ impl MachineState {
                         },
                     _ => self.fail = true
                 };
-                
+
                 self.p += 1;
             },
             &BuiltInInstruction::InstallCleaner => {
@@ -1340,35 +1340,41 @@ impl MachineState {
                 {
                     Some(cut_policy) => cut_policy.push_cont_pt(addr, b, block),
                     None => panic!("install_cleaner: should have installed \\
-SetupCallCleanupCutPolicy.")
+                                    SetupCallCleanupCutPolicy.")
                 };
 
                 self.p += 1;
             },
-            &BuiltInInstruction::InstallInferenceCounter(r) => {
-                let addr = self.store(self.deref(self[r].clone()));
-                
+            &BuiltInInstruction::InstallInferenceCounter(r1, r2, r3) => { // A1 = B, A2 = L
+                let a1 = self.store(self.deref(self[r1].clone()));
+                let a2 = self.store(self.deref(self[r2].clone()));
+
                 if call_policy.downcast_ref::<CallWithInferenceLimitCallPolicy>().is_err() {
-                    CallWithInferenceLimitCallPolicy::new_in_place(self.atom_tbl.clone(), call_policy);
+                    CallWithInferenceLimitCallPolicy::new_in_place(self.atom_tbl.clone(),
+                                                                   call_policy);
                 }
 
                 self.p += 1;
-                
-                match addr {
-                    Addr::Con(Constant::Number(Number::Integer(n))) =>
+
+                match (a1, a2) {
+                    (Addr::Con(Constant::Usize(bp)),
+                     Addr::Con(Constant::Number(Number::Integer(n)))) =>
                         match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
-                            Some(call_policy) => call_policy.add_limit(n),
+                            Some(call_policy) => {
+                                let count = call_policy.add_limit(n, bp);
+                                self[r3]  = Addr::Con(Constant::Number(Number::Integer(count)));
+                            },
                             None => panic!("install_inference_counter: should have installed \\
                                             CallWithInferenceLimitCallPolicy.")
                         },
                     _ => {
-                        let atom_tbl = self.atom_tbl.clone();                        
+                        let atom_tbl = self.atom_tbl.clone();
                         self.throw_exception(functor!(atom_tbl,
                                                       "type_error",
                                                       1,
                                                       [heap_atom!("integer_expected", atom_tbl)]))
                     }
-                };                
+                };
             },
             &BuiltInInstruction::IsAtomic(r) => {
                 let d = self.store(self.deref(self[r].clone()));
@@ -1434,21 +1440,20 @@ SetupCallCleanupCutPolicy.")
                     _ => self.fail = true
                 };
             },
-            &BuiltInInstruction::RemoveInferenceCounter(r) => {
+            &BuiltInInstruction::RemoveCallPolicyCheck => {
                 let restore_default =
                     match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
                         Some(call_policy) => {
-                            if let Some(diff) = call_policy.remove_limit() {
-                                let addr = self[r].clone();
-                                self.unify(addr, Addr::Con(integer!(diff)));
-                            } else {
-                                panic!("remove_inference_counters: no limit found.");
-                            }
-                            
-                            if call_policy.is_empty() {
-                                Some(call_policy.into_inner())
+                            let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
+
+                            if let Addr::Con(Constant::Usize(bp)) = a1 {
+                                if call_policy.is_empty() && bp == self.b {
+                                    Some(call_policy.into_inner())
+                                } else {
+                                    None
+                                }
                             } else {
-                                None
+                                panic!("remove_inference_counter: expected Usize in A1.");
                             }
                         },
                         None => panic!("remove_inference_counters: requires \\
@@ -1461,6 +1466,25 @@ SetupCallCleanupCutPolicy.")
 
                 self.p += 1;
             },
+            &BuiltInInstruction::RemoveInferenceCounter(r1, r2) => { // A1 = B, A2 = Count.
+                match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
+                    Some(call_policy) => {
+                        let a1 = self.store(self.deref(self[r1].clone()));
+
+                        if let Addr::Con(Constant::Usize(bp)) = a1 {
+                            let count = call_policy.remove_limit(bp);
+                            self[r2]  = Addr::Con(Constant::Number(Number::Integer(count)));
+
+                        } else {
+                            panic!("remove_inference_counter: expected Usize in A1.");
+                        }
+                    },
+                    None => panic!("remove_inference_counters: requires \\
+                                    CallWithInferenceLimitCallPolicy.")
+                };
+
+                self.p += 1;
+            },
             &BuiltInInstruction::RestoreCutPolicy => {
                 let restore_default =
                     if let Ok(cut_policy) = cut_policy.downcast_ref::<SetupCallCleanupCutPolicy>() {
index c1c495ec973f5eda012cd32c455aad25bfec6c8b..4886b13f616d16c3659cf57832cf0cdb75647273 100644 (file)
@@ -431,6 +431,12 @@ macro_rules! add {
     )
 }
 
+macro_rules! sub {
+    ($at_1:expr, $at_2:expr, $o:expr) => (
+        Line::Arithmetic(ArithmeticInstruction::Sub($at_1, $at_2, $o))
+    )
+}
+
 macro_rules! get_arg_call {
     () => (
         Line::BuiltIn(BuiltInInstruction::GetArgCall)
@@ -624,14 +630,14 @@ macro_rules! term_cmp_eq {
 }
 
 macro_rules! install_inference_counter {
-    ($r:expr) => (
-        Line::BuiltIn(BuiltInInstruction::InstallInferenceCounter($r))
+    ($r1:expr, $r2:expr, $r3:expr) => (
+        Line::BuiltIn(BuiltInInstruction::InstallInferenceCounter($r1, $r2, $r3))
     )
 }
 
 macro_rules! remove_inference_counter {
-    ($r:expr) => (
-        Line::BuiltIn(BuiltInInstruction::RemoveInferenceCounter($r))
+    ($r1:expr, $r2:expr) => (
+        Line::BuiltIn(BuiltInInstruction::RemoveInferenceCounter($r1, $r2))
     )
 }
 
@@ -646,3 +652,9 @@ macro_rules! default_trust_me {
         Line::BuiltIn(BuiltInInstruction::DefaultTrustMe)
     )
 }
+
+macro_rules! remove_call_policy_check {
+    () => (
+        Line::BuiltIn(BuiltInInstruction::RemoveCallPolicyCheck)
+    )
+}
index 3f30c84c01aae68fe382d40670cda613ae94300e..0eaa1d9c05ce06ad9ea87cc986d3f647e66f8766 100644 (file)
@@ -18,7 +18,6 @@ pub mod heap_print;
 pub mod indexing;
 pub mod io;
 pub mod iterators;
-pub mod lib;
 pub mod machine;
 pub mod or_stack;
 pub mod parser;