]> Repositorios git - scryer-prolog.git/commitdiff
add call_with_inference_limit/3
authorMark Thom <[email protected]>
Wed, 8 Aug 2018 06:42:57 +0000 (00:42 -0600)
committerMark Thom <[email protected]>
Wed, 8 Aug 2018 06:42:57 +0000 (00:42 -0600)
Cargo.lock
Cargo.toml
src/prolog/ast.rs
src/prolog/iterators.rs
src/prolog/lib/builtins.pl
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/system_calls.rs
src/tests.rs

index 8d7a9487e1bf1239b3e40f62114123bf59744605..3626ee47509a127f75fdd896a156df6809719056 100644 (file)
@@ -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)",
index 2f787b1a6ab4d77d78bf4bace97a68b2ff1441d1..25d4472f5b97ef8ddeae4c85acf9adf2998054e9 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "rusty-wam"
-version = "0.7.8"
+version = "0.7.9"
 authors = ["Mark Thom"]
 
 [dependencies]
index a23f7cc6f71acc7e5d1b0765318b9665156eeae2..0de9928fdceae5f650e9ed9b324f66086a4f95c8 100644 (file)
@@ -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<SystemClauseType> {
         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 {
index dfa1994d6bfdd8653db999e1c74507bf7639280b..852cb535c49e6348d724893bac43e3ee38eed5ff 100644 (file)
@@ -343,6 +343,8 @@ impl<'a> ChunkedIterator<'a>
                     }
                 },
                 ChunkedTerm::BodyTerm(&QueryTerm::GetLevelAndUnify(..)) => {
+                    self.deep_cut_encountered = true;
+                    
                     result.push(term);
                     arity = 1;
                     break;
index 1327ace174ac7072b82b76c57d4008ed6aef9799..8a0ff0c294440484cb576e98e43a258de28d0a9c 100644 (file)
@@ -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'.
index 418c14eab4c67c238f3ba26c465b24cdb9647d0b..1af1610f22a61df874cdc8769099c9a6ba0778b4 100644 (file)
@@ -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<CodeIndex>;
+    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<CodeIndex> {
+        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<CodeIndex> {
+        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<CodeDirsAdapter<'a> + '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<CodeDirsAdapter<'a> + '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<CodeDirsAdapter<'a> + '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<CodeDirsAdapter<'a> + '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<CodeDirsAdapter<'a> + '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<CodeDirsAdapter<'a> + '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<CallPolicy>,
-    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<CallPolicy>)
     {
         let mut prev_policy: Box<CallPolicy> = 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)
     }
 }
index 4d975919b2285c43181be73183f8b3e44bf969b0..a07a8093a494b438b8d431a2b73ffbf7cd88d69f 100644 (file)
@@ -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);
index 1754fe75da5643f8a18351bbfac6ca42ac2da82f..2b1a430622ae18509becc9d0b5c7b331979c0a3f 100644 (file)
@@ -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<CallPolicy>,
-                              cut_policy:  &mut Box<CutPolicy>,)
-                              -> CallResult
+
+    pub(super) fn system_call<'a>(&mut self, ct: &SystemClauseType,
+                                  code_dirs: CodeDirs<'a>,
+                                  call_policy: &mut Box<CallPolicy>,
+                                  cut_policy:  &mut Box<CutPolicy>,)
+                                  -> 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::<CallWithInferenceLimitCallPolicy>().is_err() {
-                    CallWithInferenceLimitCallPolicy::new_in_place(call_policy);
+                if call_policy.downcast_ref::<CWILCallPolicy>().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::<CallWithInferenceLimitCallPolicy>().ok() {
+                        match call_policy.downcast_mut::<CWILCallPolicy>().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::<CallWithInferenceLimitCallPolicy>().ok() {
+                    match call_policy.downcast_mut::<CWILCallPolicy>().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::<CallWithInferenceLimitCallPolicy>().ok() {
+            &SystemClauseType::RemoveInferenceCounter =>
+                match call_policy.downcast_mut::<CWILCallPolicy>().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::<SCCCutPolicy>() {
@@ -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));
             },
index 823aa74b76136e0a3b5bde61332c0b05a5b5b0e1..15fa8301f4b82e8d3616040ab0e769e1f928d092 100644 (file)
@@ -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"]]);
 
 }
-*/