From 5de03444eb51c1c5ba6d2aa14c05bef7592493a4 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 21 Feb 2018 19:46:15 -0700 Subject: [PATCH] fix bugs in call_with_inference_limit --- src/main.rs | 5 +- src/prolog/ast.rs | 5 +- src/prolog/builtins.rs | 109 +++++++++++++---------- src/prolog/io.rs | 10 ++- src/prolog/lib/control.pl | 13 +++ src/prolog/lib/control.rs | 13 --- src/prolog/lib/lists.pl | 57 ++++++++++++ src/prolog/lib/lists.rs | 57 ------------ src/prolog/lib/mod.rs | 3 - src/prolog/machine/machine_state.rs | 82 ++++++++--------- src/prolog/machine/machine_state_impl.rs | 74 +++++++++------ src/prolog/macros.rs | 20 ++++- src/prolog/mod.rs | 1 - 13 files changed, 248 insertions(+), 201 deletions(-) create mode 100644 src/prolog/lib/control.pl delete mode 100644 src/prolog/lib/control.rs create mode 100644 src/prolog/lib/lists.pl delete mode 100644 src/prolog/lib/lists.rs delete mode 100644 src/prolog/lib/mod.rs diff --git a/src/main.rs b/src/main.rs index 3b4a4900..c7ae8b1d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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) { diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index 6eff00d3..86ea088d 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -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, diff --git a/src/prolog/builtins.rs b/src/prolog/builtins.rs index 97462fbb..32d28dcd 100644 --- a/src/prolog/builtins.rs +++ b/src/prolog/builtins.rs @@ -548,74 +548,89 @@ fn get_builtins(atom_tbl: TabledData) -> 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!() ] diff --git a/src/prolog/io.rs b/src/prolog/io.rs index bb7ccbcc..3a0a083f 100644 --- a/src/prolog/io.rs +++ b/src/prolog/io.rs @@ -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 index 00000000..df794db4 --- /dev/null +++ b/src/prolog/lib/control.pl @@ -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 index 41ce18bf..00000000 --- a/src/prolog/lib/control.rs +++ /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 index 00000000..3816c546 --- /dev/null +++ b/src/prolog/lib/lists.pl @@ -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 index 0f503e74..00000000 --- a/src/prolog/lib/lists.rs +++ /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 index 21c58b2b..00000000 --- a/src/prolog/lib/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod control; -pub mod lists; - diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index eff3a5c4..94daa4ac 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -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 { - Some(self.cmp(other)) - } -} - pub(crate) struct CallWithInferenceLimitCallPolicy { atom_tbl: TabledData, pub(crate) prev_policy: Box, - count: BigUint, - limits: BinaryHeap + count: BigInt, + limits: Vec<(Rc, usize)> } impl CallWithInferenceLimitCallPolicy { pub(crate) fn new_in_place(atom_tbl: TabledData, policy: &mut Box) { let mut prev_policy: Box = 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) { - 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, b: usize) -> Rc { + 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 { - self.limits.pop().map(|i| i.0 - &self.count) + // returns the count. + pub(crate) fn remove_limit(&mut self, b: usize) -> Rc { + 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 { let mut new_inner: Box = 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)?; diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 3288f361..56416a9c 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -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::().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::().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::().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::().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::() { diff --git a/src/prolog/macros.rs b/src/prolog/macros.rs index c1c495ec..4886b13f 100644 --- a/src/prolog/macros.rs +++ b/src/prolog/macros.rs @@ -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) + ) +} diff --git a/src/prolog/mod.rs b/src/prolog/mod.rs index 3f30c84c..0eaa1d9c 100644 --- a/src/prolog/mod.rs +++ b/src/prolog/mod.rs @@ -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; -- 2.54.0