From: Mark Thom Date: Fri, 23 Feb 2018 07:16:40 +0000 (-0700) Subject: fix bugs in call_with_inference_limit X-Git-Tag: v0.8.110~555 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=8d182b3f0217d1727062442fe1c7d5e9ecf5ee66;p=scryer-prolog.git fix bugs in call_with_inference_limit --- diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index 019a9714..e89dc89b 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -892,7 +892,7 @@ pub enum BuiltInInstruction { GetBall, GetCurrentBlock, GetCutPoint(RegType), - InferenceLevel, + InferenceLevel(RegType, RegType), InstallCleaner, InstallInferenceCounter(RegType, RegType, RegType), InstallNewBlock, diff --git a/src/prolog/builtins.rs b/src/prolog/builtins.rs index 1bc5593c..41606caa 100644 --- a/src/prolog/builtins.rs +++ b/src/prolog/builtins.rs @@ -565,37 +565,37 @@ fn get_builtins(atom_tbl: TabledData) -> 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) -> 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) -> (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) } diff --git a/src/prolog/io.rs b/src/prolog/io.rs index c9453201..3a5847eb 100644 --- a/src/prolog/io.rs +++ b/src/prolog/io.rs @@ -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 => diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index b9663d6c..314e4648 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -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, b: usize) -> Rc { 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 { if let Some((_, bp)) = self.limits.last().cloned() { if bp == b { diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 02cdc8d0..ca2c2827 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -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::().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::().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) => { diff --git a/src/prolog/macros.rs b/src/prolog/macros.rs index 4fe21042..20469d64 100644 --- a/src/prolog/macros.rs +++ b/src/prolog/macros.rs @@ -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)) ) } diff --git a/src/tests.rs b/src/tests.rs index e7868ae9..2d325bd3 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -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, _).");