From 7016d378d6748dba5035f4bf06f1cb02e1e221c1 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 8 Aug 2018 00:42:57 -0600 Subject: [PATCH] add call_with_inference_limit/3 --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/prolog/ast.rs | 15 ++- src/prolog/iterators.rs | 2 + src/prolog/lib/builtins.pl | 45 ++++++- src/prolog/machine/machine_state.rs | 144 +++++++++++++++-------- src/prolog/machine/machine_state_impl.rs | 7 +- src/prolog/machine/system_calls.rs | 75 +++++++----- src/tests.rs | 2 - 9 files changed, 201 insertions(+), 93 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8d7a9487..3626ee47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -99,7 +99,7 @@ dependencies = [ [[package]] name = "rusty-wam" -version = "0.7.8" +version = "0.7.9" dependencies = [ "downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 2f787b1a..25d4472f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rusty-wam" -version = "0.7.8" +version = "0.7.9" authors = ["Mark Thom"] [dependencies] diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index a23f7cc6..0de9928f 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -700,7 +700,9 @@ pub struct Rule { #[derive(Copy, Clone, PartialEq)] pub enum SystemClauseType { - CheckCutPoint, + CallWithDefaultPolicy, + CheckCutPoint, + GetBValue, GetSCCCleaner, InstallSCCCleaner, InstallInferenceCounter, @@ -731,7 +733,9 @@ impl SystemClauseType { pub fn name(&self) -> ClauseName { match self { + &SystemClauseType::CallWithDefaultPolicy => clause_name!("$call_with_default_policy"), &SystemClauseType::CheckCutPoint => clause_name!("$check_cp"), + &SystemClauseType::GetBValue => clause_name!("$get_b_value"), &SystemClauseType::GetSCCCleaner => clause_name!("$get_scc_cleaner"), &SystemClauseType::InstallSCCCleaner => clause_name!("$install_scc_cleaner"), &SystemClauseType::InstallInferenceCounter => @@ -740,7 +744,7 @@ impl SystemClauseType { clause_name!("$remove_call_policy_check"), &SystemClauseType::RemoveInferenceCounter => clause_name!("$remove_inference_counter"), - &SystemClauseType::RestoreCutPolicy => clause_name!("$restore_cut_policy"), + &SystemClauseType::RestoreCutPolicy => clause_name!("$restore_cut_policy"), &SystemClauseType::SetCutPoint(_) => clause_name!("$set_cp"), &SystemClauseType::InferenceLevel => clause_name!("$inference_level"), &SystemClauseType::CleanUpBlock => clause_name!("$clean_up_block"), @@ -761,7 +765,9 @@ impl SystemClauseType { pub fn from(name: &str, arity: usize) -> Option { match (name, arity) { + ("$call_with_default_policy", 1) => Some(SystemClauseType::CallWithDefaultPolicy), ("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint), + ("$get_b_value", 1) => Some(SystemClauseType::GetBValue), ("$get_scc_cleaner", 1) => Some(SystemClauseType::GetSCCCleaner), ("$install_scc_cleaner", 2) => Some(SystemClauseType::InstallSCCCleaner), @@ -769,7 +775,7 @@ impl SystemClauseType { Some(SystemClauseType::InstallInferenceCounter), ("$remove_call_policy_check", 1) => Some(SystemClauseType::RemoveCallPolicyCheck), - ("$remove_inference_counter", 1) => + ("$remove_inference_counter", 2) => Some(SystemClauseType::RemoveInferenceCounter), ("$restore_cut_policy", 0) => Some(SystemClauseType::RestoreCutPolicy), ("$set_cp", 1) => Some(SystemClauseType::SetCutPoint(temp_v!(1))), @@ -1613,9 +1619,6 @@ impl CodePtr { pub enum LocalCodePtr { DirEntry(usize, ClauseName), // offset, resident module name. TopLevel(usize, usize), // chunk_num, offset. - // DynamicModuleCall(ClauseName, ClauseName, usize) - // module name, predicate name and arity. - // used for internal, dynamic module calls. } impl LocalCodePtr { diff --git a/src/prolog/iterators.rs b/src/prolog/iterators.rs index dfa1994d..852cb535 100644 --- a/src/prolog/iterators.rs +++ b/src/prolog/iterators.rs @@ -343,6 +343,8 @@ impl<'a> ChunkedIterator<'a> } }, ChunkedTerm::BodyTerm(&QueryTerm::GetLevelAndUnify(..)) => { + self.deep_cut_encountered = true; + result.push(term); arity = 1; break; diff --git a/src/prolog/lib/builtins.pl b/src/prolog/lib/builtins.pl index 1327ace1..8a0ff0c2 100644 --- a/src/prolog/lib/builtins.pl +++ b/src/prolog/lib/builtins.pl @@ -5,7 +5,8 @@ (>>)/2, (mod)/2, (rem)/2, (>)/2, (<)/2, (=\=)/2, (=:=)/2, (-)/1, (>=)/2, (=<)/2, (,)/2, (->)/2, (;)/2, (=..)/2, (==)/2, (\==)/2, (@=<)/2, (@>=)/2, (@<)/2, (@>)/2, (=@=)/2, (\=@=)/2, - (:)/2, catch/3, setup_call_cleanup/3, throw/1, true/0, false/0]). + (:)/2, call_with_inference_limit/3, catch/3, + setup_call_cleanup/3, throw/1, true/0, false/0]). % arithmetic operators. :- op(700, xfx, is). @@ -149,13 +150,13 @@ univ_worker(Term, List, _) :- % setup_call_cleanup. -setup_call_cleanup(S, G, C) :- '$get_cp'(B), +setup_call_cleanup(S, G, C) :- '$get_b_value'(B), S, '$set_cp_by_default'(B), '$get_current_block'(Bb), ( var(C) -> throw(error(instantiation_error, setup_call_cleanup/3)) ; scc_helper(C, G, Bb) ). scc_helper(C, G, Bb) :- - '$get_level'(Cp), '$install_scc_cleaner'(C, NBb), call(G), + '$get_cp'(Cp), '$install_scc_cleaner'(C, NBb), call(G), ( '$check_cp'(Cp) -> '$reset_block'(Bb), run_cleaners_without_handling(Cp) ; true ; '$reset_block'(NBb), '$fail'). @@ -163,7 +164,7 @@ scc_helper(_, _, Bb) :- '$reset_block'(Bb), '$get_ball'(Ball), run_cleaners_with_handling, throw(Ball). scc_helper(_, _, _) :- - run_cleaners_without_handling(Cp), false. + '$get_cp'(Cp), run_cleaners_without_handling(Cp), '$fail'. run_cleaners_with_handling :- '$get_scc_cleaner'(C), '$get_level'(B), catch(C, _, true), '$set_cp_by_default'(B), @@ -177,6 +178,40 @@ run_cleaners_without_handling(Cp) :- run_cleaners_without_handling(Cp) :- '$set_cp_by_default'(Cp), '$restore_cut_policy'. +% call_with_inference_limit + +call_with_inference_limit(G, L, R) :- + '$get_current_block'(Bb), + '$get_b_value'(B), + '$call_with_default_policy'(call_with_inference_limit(G, L, R, Bb, B)), + '$remove_call_policy_check'(B). + +call_with_inference_limit(G, L, R, Bb, B) :- + '$install_new_block'(NBb), + '$install_inference_counter'(B, L, Count0), + call(G), + '$inference_level'(R, B), + '$remove_inference_counter'(B, Count1), + '$call_with_default_policy'(is(Diff, L - (Count1 - Count0))), + '$call_with_default_policy'(end_block(B, Bb, NBb, Diff)). +call_with_inference_limit(_, _, R, Bb, B) :- + '$reset_block'(Bb), + '$remove_inference_counter'(B, _), + ( '$get_ball'(Ball), '$get_level'(Cp), '$set_cp_by_default'(Cp) + ; '$remove_call_policy_check'(B), '$fail' ), + '$call_with_default_policy'(handle_ile(B, Ball, R)). + +end_block(_, Bb, NBb, L) :- + '$clean_up_block'(NBb), + '$reset_block'(Bb). +end_block(B, Bb, NBb, L) :- + '$install_inference_counter'(B, L, _), + '$reset_block'(NBb), + '$fail'. + +handle_ile(B, inference_limit_exceeded(B), inference_limit_exceeded) :- !. +handle_ile(B, _, _) :- '$remove_call_policy_check'(B), '$unwind_stack'. % throw(E). + % exceptions. catch(G,C,R) :- '$get_current_block'(Bb), catch(G,C,R,Bb). @@ -187,7 +222,7 @@ catch(G,C,R,Bb) :- '$reset_block'(Bb), '$get_ball'(Ball), handle_ball(Ball, C, R end_block(Bb, NBb) :- '$clean_up_block'(NBb), '$reset_block'(Bb). end_block(Bb, NBb) :- '$reset_block'(NBb), '$fail'. -handle_ball(Ball, C, R) :- Ball = C, '$get_level'(B), '$set_cp_by_default'(B), '$erase_ball', call(R). +handle_ball(C, C, R) :- !, '$erase_ball', call(R). handle_ball(_, _, _) :- '$unwind_stack'. throw(Ball) :- '$set_ball'(Ball), '$unwind_stack'. diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 418c14ea..1af1610f 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -10,6 +10,7 @@ use prolog::tabled_rc::*; use downcast::Any; +use std::cell::RefCell; use std::cmp::Ordering; use std::mem::swap; use std::ops::{Index, IndexMut}; @@ -31,6 +32,7 @@ impl Ball { } } +#[derive(Clone, Copy)] pub(crate) struct CodeDirs<'a> { pub code_dir: &'a CodeDir, pub op_dir: &'a OpDir, @@ -60,7 +62,7 @@ impl<'a> CodeDirs<'a> { .and_then(|ref module| module.code_dir.get(&(name, arity))) .cloned() } - + pub(super) fn get_cleaner_sites(&self) -> (usize, usize) { let r_w_h = clause_name!("run_cleaners_with_handling"); let r_wo_h = clause_name!("run_cleaners_without_handling"); @@ -80,6 +82,33 @@ impl<'a> CodeDirs<'a> { } } +pub trait CodeDirsAdapter<'a> { + fn get_code_index(&self, PredicateKey, ClauseName) -> Option; + fn get_op(&self, OpDirKey) -> Option<(Specifier, usize, ClauseName)>; +} + +impl<'a> CodeDirsAdapter<'a> for CodeDirs<'a> { + fn get_code_index(&self, key: PredicateKey, module: ClauseName) -> Option { + self.get(key.0, key.1, module) + } + + fn get_op(&self, key: OpDirKey) -> Option<(Specifier, usize, ClauseName)> { + self.op_dir.get(&key).cloned() + } +} + +impl<'a> CodeDirsAdapter<'a> for &'a Module { + fn get_code_index(&self, key: PredicateKey, _: ClauseName) -> Option { + self.code_dir.get(&key) + .cloned() + .map(|ModuleCodeIndex(ptr, module)| CodeIndex(Rc::new(RefCell::new((ptr, module))))) + } + + fn get_op(&self, key: OpDirKey) -> Option<(Specifier, usize, ClauseName)> { + self.op_dir.get(&key).cloned() + } +} + pub(super) struct DuplicateTerm<'a> { state: &'a mut MachineState } @@ -391,9 +420,9 @@ pub(crate) trait CallPolicy: Any { Ok(()) } - fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName, arity: usize, - idx: CodeIndex, code_dirs: CodeDirs) - -> CallResult + fn context_call<'a>(&mut self, machine_st: &mut MachineState, name: ClauseName, arity: usize, + idx: CodeIndex, code_dirs: Box + 'a>) + -> CallResult { if machine_st.last_call { self.try_execute(machine_st, name, arity, idx, code_dirs) @@ -402,9 +431,9 @@ pub(crate) trait CallPolicy: Any { } } - fn try_call(&mut self, machine_st: &mut MachineState, name: ClauseName, arity: usize, - idx: CodeIndex, code_dirs: CodeDirs) - -> CallResult + fn try_call<'a>(&mut self, machine_st: &mut MachineState, name: ClauseName, arity: usize, + idx: CodeIndex, code_dirs: Box + 'a>) + -> CallResult { match idx.0.borrow().0 { IndexPtr::Module => { @@ -412,7 +441,8 @@ pub(crate) trait CallPolicy: Any { let module_name = idx.0.borrow().1.clone(); let h = machine_st.heap.h; - if let Some(ref idx) = code_dirs.get(name.clone(), arity, module_name.clone()) { + if let Some(ref idx) = code_dirs.get_code_index((name.clone(), arity), module_name.clone()) + { if let IndexPtr::Index(compiled_tl_index) = idx.0.borrow().0 { call_at_index(machine_st, module_name, arity, compiled_tl_index); return Ok(()); @@ -439,7 +469,7 @@ pub(crate) trait CallPolicy: Any { } fn try_execute<'a>(&mut self, machine_st: &mut MachineState, name: ClauseName, - arity: usize, idx: CodeIndex, code_dirs: CodeDirs) + arity: usize, idx: CodeIndex, code_dirs: Box + 'a>) -> CallResult { match idx.0.borrow().0 { @@ -448,7 +478,8 @@ pub(crate) trait CallPolicy: Any { let module_name = idx.0.borrow().1.clone(); let h = machine_st.heap.h; - if let Some(ref idx) = code_dirs.get(name.clone(), arity, module_name.clone()) { + if let Some(ref idx) = code_dirs.get_code_index((name.clone(), arity), module_name.clone()) + { if let IndexPtr::Index(compiled_tl_index) = idx.0.borrow().0 { execute_at_index(machine_st, module_name, arity, compiled_tl_index); return Ok(()); @@ -610,7 +641,8 @@ pub(crate) trait CallPolicy: Any { } } - fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize, code_dirs: CodeDirs<'a>) + fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize, + code_dirs: Box + 'a>) -> CallResult { if let Some((name, arity)) = machine_st.setup_call_n(arity) { @@ -631,7 +663,7 @@ pub(crate) trait CallPolicy: Any { ClauseType::Inlined(inlined) => machine_st.execute_inlined(&inlined), ClauseType::Op(..) | ClauseType::Named(..) => - if let Some(idx) = code_dirs.get(name.clone(), arity, user) { + if let Some(idx) = code_dirs.get_code_index((name.clone(), arity), user) { self.context_call(machine_st, name, arity, idx, code_dirs)?; } else { let h = machine_st.heap.h; @@ -654,37 +686,37 @@ pub(crate) trait CallPolicy: Any { } } -impl CallPolicy for CallWithInferenceLimitCallPolicy { - fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName, - arity: usize, idx: CodeIndex, code_dirs: CodeDirs) - -> CallResult +impl CallPolicy for CWILCallPolicy { + fn context_call<'a>(&mut self, machine_st: &mut MachineState, name: ClauseName, + arity: usize, idx: CodeIndex, code_dirs: Box + 'a>) + -> CallResult { self.prev_policy.context_call(machine_st, name, arity, idx, code_dirs)?; - self.increment() + self.increment(machine_st) } fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { self.prev_policy.retry_me_else(machine_st, offset)?; - self.increment() + self.increment(machine_st) } fn retry(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { self.prev_policy.retry(machine_st, offset)?; - self.increment() + self.increment(machine_st) } fn trust_me(&mut self, machine_st: &mut MachineState) -> CallResult { self.prev_policy.trust_me(machine_st)?; - self.increment() + self.increment(machine_st) } fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { self.prev_policy.trust(machine_st, offset)?; - self.increment() + self.increment(machine_st) } fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType, @@ -692,14 +724,15 @@ impl CallPolicy for CallWithInferenceLimitCallPolicy { -> CallResult { self.prev_policy.call_builtin(machine_st, ct, code_dirs)?; - self.increment() + self.increment(machine_st) } - fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize, code_dirs: CodeDirs<'a>) + fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize, + code_dirs: Box + 'a>) -> CallResult { self.prev_policy.call_n(machine_st, arity, code_dirs)?; - self.increment() + self.increment(machine_st) } } @@ -709,27 +742,34 @@ pub(crate) struct DefaultCallPolicy {} impl CallPolicy for DefaultCallPolicy {} -pub(crate) struct CallWithInferenceLimitCallPolicy { +pub(crate) struct CWILCallPolicy { pub(crate) prev_policy: Box, - count: BigUint, - limits: Vec<(BigUint, usize)> + pub(crate) count: BigUint, + limits: Vec<(BigUint, usize)>, + inference_limit_exceeded: bool } -impl CallWithInferenceLimitCallPolicy { +impl CWILCallPolicy { pub(crate) fn new_in_place(policy: &mut Box) { let mut prev_policy: Box = Box::new(DefaultCallPolicy {}); swap(&mut prev_policy, policy); - let new_policy = CallWithInferenceLimitCallPolicy { prev_policy, - count: BigUint::zero(), - limits: vec![] }; + let new_policy = CWILCallPolicy { prev_policy, + count: BigUint::zero(), + limits: vec![], + inference_limit_exceeded: false }; *policy = Box::new(new_policy); } - fn increment(&mut self) -> CallResult { + fn increment(&mut self, machine_st: &MachineState) -> CallResult { + if self.inference_limit_exceeded || machine_st.ball.stub.len() > 0 { + return Ok(()); + } + if let Some(&(ref limit, bp)) = self.limits.last() { if self.count == *limit { + self.inference_limit_exceeded = true; return Err(functor!("inference_limit_exceeded", 1, [HeapCellValue::Addr(Addr::Con(Constant::Usize(bp)))])); } else { @@ -782,24 +822,34 @@ pub(crate) trait CutPolicy: Any { downcast!(CutPolicy); +fn cut_body(machine_st: &mut MachineState, addr: Addr) -> bool { + let b = machine_st.b; + + if let Addr::Con(Constant::Usize(b0)) = addr { + if b > b0 { + machine_st.b = b0; + machine_st.tidy_trail(); + machine_st.or_stack.truncate(machine_st.b); + } + } else { + machine_st.fail = true; + return true; + } + + false +} + pub(crate) struct DefaultCutPolicy {} +pub(super) fn deref_cut(machine_st: &mut MachineState, r: RegType) { + let addr = machine_st.store(machine_st.deref(machine_st[r].clone())); + cut_body(machine_st, addr); +} + impl CutPolicy for DefaultCutPolicy { fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool { - let b = machine_st.b; - - if let Addr::Con(Constant::Usize(b0)) = machine_st[r].clone() { - if b > b0 { - machine_st.b = b0; - machine_st.tidy_trail(); - machine_st.or_stack.truncate(machine_st.b); - } - } else { - machine_st.fail = true; - return true; - } - - false + let addr = machine_st[r].clone(); + cut_body(machine_st, addr) } } @@ -867,6 +917,6 @@ impl CutPolicy for SCCCutPolicy { return true; } - self.run_cleaners(machine_st) + self.run_cleaners(machine_st) } } diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 4d975919..a07a8093 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -1821,7 +1821,7 @@ impl MachineState { self.allocate(num_cells), &ControlInstruction::CallClause(ClauseType::CallN, arity, _, lco) => { self.last_call = lco; - try_or_fail!(self, call_policy.call_n(self, arity, code_dirs)); + try_or_fail!(self, call_policy.call_n(self, arity, Box::new(code_dirs))); }, &ControlInstruction::CallClause(ClauseType::BuiltIn(ref ct), _, _, lco) => { self.last_call = lco; @@ -1833,7 +1833,7 @@ impl MachineState { | &ControlInstruction::CallClause(ClauseType::Op(ref name, _, ref idx), arity, _, lco) => { self.last_call = lco; try_or_fail!(self, call_policy.context_call(self, name.clone(), arity, idx.clone(), - code_dirs)); + Box::new(code_dirs))); }, &ControlInstruction::CallClause(ClauseType::System(ref ct), _, _, lco) => { self.last_call = lco; @@ -1947,7 +1947,8 @@ impl MachineState { self.p += 1; }, &CutInstruction::GetLevelAndUnify(r) => { - let b0 = Addr::Con(Constant::Usize(self.b0)); + // let b0 = Addr::Con(Constant::Usize(self.b0)); + let b0 = self[perm_v!(1)].clone(); let a = self[r].clone(); self.unify(a, b0); diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 1754fe75..2b1a4306 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -2,7 +2,7 @@ use prolog::ast::*; use prolog::machine::machine_errors::*; use prolog::machine::machine_state::*; use prolog::num::{ToPrimitive, Zero}; -use prolog::num::bigint::BigInt; +use prolog::num::bigint::{BigInt}; use std::rc::Rc; @@ -177,16 +177,24 @@ impl MachineState { self.p = CodePtr::Local(self.cp.clone()); } else { self.p += 1; - } + } } - - pub(super) fn system_call(&mut self, ct: &SystemClauseType, - code_dirs: CodeDirs, - call_policy: &mut Box, - cut_policy: &mut Box,) - -> CallResult + + pub(super) fn system_call<'a>(&mut self, ct: &SystemClauseType, + code_dirs: CodeDirs<'a>, + call_policy: &mut Box, + cut_policy: &mut Box,) + -> CallResult { match ct { + // this system call is only to be used within the builtins module. + // TODO: in the future I'd like to use serde to serialize/deserialize builtins + // and thereby avoid this kludge, but for now it's ok. + &SystemClauseType::CallWithDefaultPolicy => + if let Some(builtins) = code_dirs.modules.get(&clause_name!("builtins")) { + let mut call_policy = DefaultCallPolicy {}; + return call_policy.call_n(self, 1, Box::new(builtins)); + }, &SystemClauseType::CheckCutPoint => { let addr = self.store(self.deref(self[temp_v!(1)].clone())); @@ -207,7 +215,7 @@ impl MachineState { if let Some(r) = dest.as_var() { self.bind(r, addr.clone()); self.set_p(); - + return Ok(()); } } else { @@ -243,20 +251,24 @@ impl MachineState { let a1 = self.store(self.deref(self[temp_v!(1)].clone())); let a2 = self.store(self.deref(self[temp_v!(2)].clone())); - if call_policy.downcast_ref::().is_err() { - CallWithInferenceLimitCallPolicy::new_in_place(call_policy); + if call_policy.downcast_ref::().is_err() { + CWILCallPolicy::new_in_place(call_policy); } match (a1, a2.clone()) { (Addr::Con(Constant::Usize(bp)), Addr::Con(Constant::Number(Number::Integer(n)))) => - match call_policy.downcast_mut::().ok() { + match call_policy.downcast_mut::().ok() { Some(call_policy) => { let count = call_policy.add_limit(n, bp); - self[temp_v!(3)] = Addr::Con(Constant::Number(Number::Integer(count))); + let count = Addr::Con(Constant::Number(Number::Integer(count))); + + let a3 = self[temp_v!(3)].clone(); + + self.unify(a3, count); }, None => panic!("install_inference_counter: should have installed \\ - CallWithInferenceLimitCallPolicy.") + CWILCallPolicy.") }, _ => { let stub = MachineError::functor_stub(clause_name!("call_with_inference_limit"), 3); @@ -268,7 +280,7 @@ impl MachineState { }, &SystemClauseType::RemoveCallPolicyCheck => { let restore_default = - match call_policy.downcast_mut::().ok() { + match call_policy.downcast_mut::().ok() { Some(call_policy) => { let a1 = self.store(self.deref(self[temp_v!(1)].clone())); @@ -283,29 +295,32 @@ impl MachineState { } }, None => panic!("remove_call_policy_check: requires \\ - CallWithInferenceLimitCallPolicy.") + CWILCallPolicy.") }; if let Some(new_policy) = restore_default { *call_policy = new_policy; } }, - &SystemClauseType::RemoveInferenceCounter => { - match call_policy.downcast_mut::().ok() { + &SystemClauseType::RemoveInferenceCounter => + match call_policy.downcast_mut::().ok() { Some(call_policy) => { let a1 = self.store(self.deref(self[temp_v!(1)].clone())); if let Addr::Con(Constant::Usize(bp)) = a1 { let count = call_policy.remove_limit(bp); - self[temp_v!(2)] = Addr::Con(Constant::Number(Number::Integer(count))); + let count = Addr::Con(Constant::Number(Number::Integer(count))); + + let a2 = self[temp_v!(2)].clone(); + + self.unify(a2, count); } else { panic!("remove_inference_counter: expected Usize in A1."); } }, - None => panic!("remove_inference_counters: requires \\ - CallWithInferenceLimitCallPolicy.") - }; - }, + None => panic!("remove_inference_counter: requires \\ + CWILCallPolicy.") + }, &SystemClauseType::RestoreCutPolicy => { let restore_default = if let Ok(cut_policy) = cut_policy.downcast_ref::() { @@ -321,10 +336,8 @@ impl MachineState { &SystemClauseType::SetCutPoint(r) => if cut_policy.cut(self, r) { return Ok(()); }, - &SystemClauseType::SetCutPointByDefault(r) => { - let mut cut_policy = DefaultCutPolicy {}; - cut_policy.cut(self, r); - }, + &SystemClauseType::SetCutPointByDefault(r) => + deref_cut(self, r), &SystemClauseType::InferenceLevel => { let a1 = self[temp_v!(1)].clone(); let a2 = self.store(self.deref(self[temp_v!(2)].clone())); @@ -382,12 +395,18 @@ impl MachineState { self.write_constant_to_var(addr, c); }, - &SystemClauseType::GetCutPoint => { + &SystemClauseType::GetBValue => { let a1 = self[temp_v!(1)].clone(); let a2 = Addr::Con(Constant::Usize(self.b)); self.unify(a1, a2); }, + &SystemClauseType::GetCutPoint => { + let a1 = self[temp_v!(1)].clone(); + let a2 = Addr::Con(Constant::Usize(self.b0)); + + self.unify(a1, a2); + }, &SystemClauseType::InstallNewBlock => { self.install_new_block(temp_v!(1)); }, diff --git a/src/tests.rs b/src/tests.rs index 823aa74b..15fa8301 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1618,7 +1618,6 @@ fn test_queries_on_setup_call_cleanup() [["Y = 1", "X = 1"]]); } -/* #[test] fn test_queries_on_call_with_inference_limit() { @@ -1739,4 +1738,3 @@ fn test_queries_on_call_with_inference_limit() [["R = inference_limit_exceeded", "X = _1"]]); } -*/ -- 2.54.0