]> Repositorios git - scryer-prolog.git/commitdiff
fix bugs in call_with_inference_limit
authorMark Thom <[email protected]>
Fri, 23 Feb 2018 07:16:40 +0000 (00:16 -0700)
committerMark Thom <[email protected]>
Fri, 23 Feb 2018 07:16:40 +0000 (00:16 -0700)
src/prolog/ast.rs
src/prolog/builtins.rs
src/prolog/io.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/macros.rs
src/tests.rs

index 019a97142d8849168689cd7b0d8fbebe7aa7d305..e89dc89b61979e58e05c9caeda5869dd98a7458f 100644 (file)
@@ -892,7 +892,7 @@ pub enum BuiltInInstruction {
     GetBall,
     GetCurrentBlock,
     GetCutPoint(RegType),
-    InferenceLevel,
+    InferenceLevel(RegType, RegType),
     InstallCleaner,
     InstallInferenceCounter(RegType, RegType, RegType),
     InstallNewBlock,
index 1bc5593ca5878b7f8b84d76cfa432884523bea04..41606caa56e9828a8d9e701d083bbb3dcd4ad133 100644 (file)
@@ -565,37 +565,37 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
          deallocate!(),
          remove_call_policy_check!(),
          proceed!(),
-         try_me_else!(18), // call_with_inference_limit/5, 404.
+         try_me_else!(19), // 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!(5), 2),
+               get_var_in_fact!(perm_v!(8), 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!(4), perm_v!(6), perm_v!(8)),
+         query![put_var!(perm_v!(7), 3)],
+         install_inference_counter!(perm_v!(4), perm_v!(5), perm_v!(7)),
          query![put_value!(perm_v!(9), 1)],
          call_n!(1),
-         remove_inference_counter!(perm_v!(4), perm_v!(7)),
-         sub!(ArithmeticTerm::Reg(perm_v!(7)),
-              ArithmeticTerm::Reg(perm_v!(8)),
-              1),
+         inference_level!(perm_v!(8), perm_v!(4)),
+         query![put_var!(perm_v!(6), 2)],
+         remove_inference_counter!(perm_v!(4), perm_v!(6)),
          sub!(ArithmeticTerm::Reg(perm_v!(6)),
+              ArithmeticTerm::Reg(perm_v!(7)),
+              1),
+         sub!(ArithmeticTerm::Reg(perm_v!(5)),
               ArithmeticTerm::Interm(1),
               1),
-         query![put_value!(perm_v!(2), 1)],
+         query![put_var!(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!(4), 1),
                 put_value!(perm_v!(3), 2),
                 put_value!(perm_v!(1), 3),
-                put_value!(perm_v!(2), 4)],
+                put_value!(perm_v!(2), 4)],         
          deallocate!(),
-         goto_execute!(442, 4), // goto end_block/4, 442.
-         default_trust_me!(), // 422.
+         goto_execute!(452, 4), // goto end_block/4, 452
+         default_trust_me!(), // 423
          allocate!(3),
          fact![get_var_in_fact!(perm_v!(1), 3),
                get_var_in_fact!(perm_v!(3), 5)],
@@ -603,37 +603,48 @@ fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
          reset_block!(),
          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!(),
+         query![put_value!(perm_v!(3), 1),
+                put_var!(perm_v!(2), 2)],
+         jmp_call!(2, 5),
          erase_ball!(),
          query![put_value!(perm_v!(3), 1),
                 put_unsafe_value!(2, 2),
                 put_value!(perm_v!(1), 3)],
          deallocate!(),
-         goto_execute!(435, 3), // goto handle_ile/3, 435.
-         try_me_else!(4), // handle_ile/3, 435.
+         goto_execute!(444, 3), // goto handle_ile/3, 442.
+         try_me_else!(5), // the inner clause.         
+         query![put_value!(temp_v!(2), 1)],
+         get_ball!(),
+         neck_cut!(),
+         proceed!(),
+         default_trust_me!(),
+         remove_call_policy_check!(),
+         fail!(),
+         try_me_else!(4), // handle_ile/3, 444.
          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!(),
+         remove_call_policy_check!(),
          query![put_value!(temp_v!(2), 1)],
          goto_execute!(59, 1), // goto throw/1, 59.
-         try_me_else!(6), // end_block/4, 442.
+         try_me_else!(6), // end_block/4, 452.
          query![put_value!(temp_v!(3), 1)],
          clean_up_block!(),
          query![put_value!(temp_v!(2), 1)],
          reset_block!(),
          proceed!(),
          default_trust_me!(),
-         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)],
+         query![get_var_in_query!(temp_v!(5), 3),
+                put_value!(temp_v!(4), 2),
+                put_var!(temp_v!(6), 3)],
+         install_inference_counter!(temp_v!(1), temp_v!(4), temp_v!(6)),
+         query![put_value!(temp_v!(5), 1)],
          reset_block!(),
          fail!(),
-         compare_execute!() // compare/3, 454.
+         compare_execute!() // compare/3, 464.
     ]
 }
 
@@ -749,7 +760,7 @@ pub fn build_code_dir(atom_tbl: TabledData<Atom>) -> (Code, CodeDir, OpDir)
     code_dir.insert((tabled_rc!("@<", atom_tbl), 2), (PredicateKeyType::BuiltIn, 390));
     code_dir.insert((tabled_rc!("=@=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 391));
     code_dir.insert((tabled_rc!("\\=@=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 392));
-    code_dir.insert((tabled_rc!("compare", atom_tbl), 3), (PredicateKeyType::BuiltIn, 454));
+    code_dir.insert((tabled_rc!("compare", atom_tbl), 3), (PredicateKeyType::BuiltIn, 464));
     
     (builtin_code, code_dir, op_dir)
 }
index c94532011f78c52a85b364cb5d67aa68e9315514..3a5847eb51fcb6681a551bff59ac84f63f26226f 100644 (file)
@@ -229,8 +229,8 @@ impl fmt::Display for BuiltInInstruction {
                 write!(f, "get_current_block X1"),
             &BuiltInInstruction::GetCutPoint(r) =>
                 write!(f, "get_cp {}", r),
-            &BuiltInInstruction::InferenceLevel =>
-                write!(f, "inference_level"),
+            &BuiltInInstruction::InferenceLevel(r1, r2) =>
+                write!(f, "inference_level {}, {}", r1, r2),
             &BuiltInInstruction::InstallCleaner =>
                 write!(f, "install_cleaner"),
             &BuiltInInstruction::InstallNewBlock =>
index b9663d6c9f2af6bca6c4735ec72b6bc7e5bc9b37..314e4648af04996c5d6e3f011aa3508a1c289716 100644 (file)
@@ -370,7 +370,7 @@ impl CallWithInferenceLimitCallPolicy {
         *policy = Box::new(new_policy);
     }
 
-    fn increment(&mut self) -> CallResult {        
+    fn increment(&mut self) -> CallResult {
         if let Some(&(ref limit, bp)) = self.limits.last() {
             if self.count == **limit {
                 return Err(functor!(self.atom_tbl,
@@ -385,7 +385,6 @@ impl CallWithInferenceLimitCallPolicy {
         Ok(())
     }
 
-    // returns the count.
     pub(crate) fn add_limit(&mut self, limit: Rc<BigInt>, b: usize) -> Rc<BigInt> {
         let limit = Rc::new(&*limit + &self.count);
         
@@ -397,7 +396,6 @@ impl CallWithInferenceLimitCallPolicy {
         Rc::new(self.count.clone())
     }
 
-    // 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 {
index 02cdc8d012d72b3f9bf2863d82c7c3ec66848bd0..ca2c2827bcba359c0969c613b50869a8a07ac17f 100644 (file)
@@ -216,6 +216,7 @@ impl MachineState {
                         let tr = self.tr;
                         let val = self.trail[tr - 1];
                         self.trail[i] = val;
+                        self.tr -= 1; // NEW.
                     },
                 Ref::StackCell(fr, _) => {
                     let b = self.b - 1;
@@ -232,6 +233,7 @@ impl MachineState {
                         let tr = self.tr;
                         let val = self.trail[tr - 1];
                         self.trail[i] = val;
+                        self.tr -= 1; // NEW.
                     }
                 }
             };
@@ -1313,9 +1315,9 @@ impl MachineState {
 
                 self.p += 1;
             },
-            &BuiltInInstruction::InferenceLevel => { // X1 = R, X2 = B.
-                let a1 = self[temp_v!(1)].clone();
-                let a2 = self.store(self.deref(self[temp_v!(2)].clone()));
+            &BuiltInInstruction::InferenceLevel(r1, r2) => { // X1 = R, X2 = B.
+                let a1 = self[r1].clone();
+                let a2 = self.store(self.deref(self[r2].clone()));
 
                 match a2 {
                     Addr::Con(Constant::Usize(bp)) =>
@@ -1366,7 +1368,7 @@ impl MachineState {
                         match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
                             Some(call_policy) => {
                                 let count = call_policy.add_limit(n, bp);
-                                self[r3]  = Addr::Con(Constant::Number(Number::Integer(count)));
+                                self[r3] = Addr::Con(Constant::Number(Number::Integer(count)));
                             },
                             None => panic!("install_inference_counter: should have installed \\
                                             CallWithInferenceLimitCallPolicy.")
@@ -1457,10 +1459,10 @@ impl MachineState {
                                     None
                                 }
                             } else {
-                                panic!("remove_inference_counter: expected Usize in A1.");
+                                panic!("remove_call_policy_check: expected Usize in A1.");
                             }
                         },
-                        None => panic!("remove_inference_counters: requires \\
+                        None => panic!("remove_call_policy_check: requires \\
                                         CallWithInferenceLimitCallPolicy.")
                     };
 
@@ -1470,15 +1472,14 @@ impl MachineState {
 
                 self.p += 1;
             },
-            &BuiltInInstruction::RemoveInferenceCounter(r1, r2) => { // A1 = B, A2 = Count.
+            &BuiltInInstruction::RemoveInferenceCounter(r1, r2) => { // A1 = B
                 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)));
-
+                            self[r2] = Addr::Con(Constant::Number(Number::Integer(count)));
                         } else {
                             panic!("remove_inference_counter: expected Usize in A1.");
                         }
@@ -1844,9 +1845,9 @@ impl MachineState {
                     Ordering::Equal   => atom!("=", self.atom_tbl),
                     Ordering::Less    => atom!("<", self.atom_tbl)
                 });
-                
+
                 self.unify(a1, c);
-            
+
                 self.p += 1;
             },
             &ControlInstruction::CompareExecute => {
@@ -1859,9 +1860,9 @@ impl MachineState {
                     Ordering::Equal   => atom!("=", self.atom_tbl),
                     Ordering::Less    => atom!("<", self.atom_tbl)
                 });
-                
+
                 self.unify(a1, c);
-                
+
                 self.p = self.cp;
             },
             &ControlInstruction::CompareTermCall(qt) => {
index 4fe210425637a7f93e44acb86938d55cdd20862a..20469d64852f94b723e7d10dcce097164316e4ec 100644 (file)
@@ -642,8 +642,8 @@ macro_rules! remove_inference_counter {
 }
 
 macro_rules! inference_level {
-    () => (
-        Line::BuiltIn(BuiltInInstruction::InferenceLevel)
+    ($r1:expr, $r2:expr) => (
+        Line::BuiltIn(BuiltInInstruction::InferenceLevel($r1, $r2))
     )
 }
 
index e7868ae9ae0cb69cf4a61f0fe9f2765cfde65a50..2d325bd3c447dd9a9a88b662d821fa56dc079877 100644 (file)
@@ -1451,9 +1451,7 @@ fn test_queries_on_call_with_inference_limit()
 
     assert_prolog_success!(&mut wam, "?- call_with_inference_limit(throw(error), 0, R).",
                            [["R = inference_limit_exceeded"]]);
-    assert_prolog_success!(&mut wam, "?- catch(call_with_inference_limit(throw(error), 1, R),
-                                               error,
-                                               true).");
+    assert_prolog_success!(&mut wam, "?- catch(call_with_inference_limit(throw(error), 1, R), error, true).");
 
     assert_prolog_failure!(&mut wam, "?- call_with_inference_limit(g(X), 5, R).");
 
@@ -1475,6 +1473,13 @@ fn test_queries_on_call_with_inference_limit()
                            [["R = true", "X = 1"],
                             ["R = true", "X = 2"],
                             ["R = inference_limit_exceeded", "X = _1"]]);
+    assert_prolog_success!(&mut wam, "?- call_with_inference_limit(g(X), 3, R1),
+                                         call_with_inference_limit(g(X), 5, R2).",
+                           [["X = 1", "R1 = true", "R2 = !"],
+                            ["X = 2", "R1 = true", "R2 = !"],
+                            ["X = 3", "R1 = true", "R2 = !"],
+                            ["X = 4", "R1 = true", "R2 = !"],
+                            ["X = 5", "R1 = !", "R2 = !"]]);
 
     submit(&mut wam, "f(X) :- call_with_inference_limit(g(X), 5, _).");