]> Repositorios git - scryer-prolog.git/commitdiff
complete call_with_inference_limit/3
authorMark Thom <[email protected]>
Thu, 9 Aug 2018 06:31:41 +0000 (00:31 -0600)
committerMark Thom <[email protected]>
Thu, 9 Aug 2018 06:31:41 +0000 (00:31 -0600)
README.md
src/prolog/ast.rs
src/prolog/codegen.rs
src/prolog/compile.rs
src/prolog/io.rs
src/prolog/lib/builtins.pl
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/toplevel.rs
src/tests.rs

index b29e84353a711c775b78d9dcd331b4f1ce8a792b..b085e60966d0bd4497a9700d23b31e5d43db8888 100644 (file)
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@ Extend rusty-wam to include the following, among other features:
 * A revised, not-terrible module system (_done, I think_).
 * Built-in predicates for list processing and top-level declarative
   control (`setup_call_control/3`, `call_with_inference_limit/3`,
-  etc.) (_IN REVISION_)
+  etc.) (_done_)
 * Definite Clause Grammars
 * Attributed variables using the SICStus Prolog interface and
   semantics. Adding coroutines like `dif/2`, `freeze/2`, etc.
@@ -131,6 +131,7 @@ The following predicates are built-in to rusty-wam.
 * `between/3`
 * `call/1..62`
 * `call_cleanup/2`
+* `call_with_inference_limit/3`
 * `catch/3`
 * `compare/3`
 * `compound/1`
index 0de9928fdceae5f650e9ed9b324f66086a4f95c8..996a8f817adf40b2f3633cb7b6c26ab336a11dc9 100644 (file)
@@ -262,6 +262,7 @@ pub trait SubModuleUser {
 }
 
 pub enum Declaration {
+    NonCountedBacktracking(ClauseName, usize), // name, arity
     Module(ModuleDecl),
     Op(OpDecl),
     UseModule(ClauseName),
@@ -538,7 +539,7 @@ pub enum Constant {
 impl Constant {
     pub fn to_atom(self) -> Option<ClauseName> {
         match self {
-            Constant::Atom(a) => Some(a),
+            Constant::Atom(a) => Some(a.defrock_brackets()),
             _ => None
         }
     }
@@ -1042,6 +1043,8 @@ impl<'a> TermRef<'a> {
 
 #[derive(Clone)]
 pub enum ChoiceInstruction {
+    DefaultRetryMeElse(usize),
+    DefaultTrustMe,
     RetryMeElse(usize),
     TrustMe,
     TryMeElse(usize)
index 575f389ef6f17a2baf9bd90f7466010e4a456fcc..392cb49cb51a100653686dd16d954ac195dbcbc5 100644 (file)
@@ -13,7 +13,8 @@ use std::vec::Vec;
 
 pub struct CodeGenerator<TermMarker> {
     marker: TermMarker,
-    var_count: HashMap<Rc<Var>, usize>
+    var_count: HashMap<Rc<Var>, usize>,
+    non_counted_bt: bool
 }
 
 pub struct ConjunctInfo<'a> {
@@ -43,9 +44,10 @@ impl<'a> ConjunctInfo<'a>
 
 impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
 {
-    pub fn new() -> Self {
+    pub fn new(non_counted_bt: bool) -> Self {
         CodeGenerator { marker:  Allocator::new(),
-                        var_count: HashMap::new() }
+                        var_count: HashMap::new(),
+                        non_counted_bt }
     }
 
     pub fn take_vars(self) -> AllocVarDict {
@@ -671,6 +673,22 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
         subseqs
     }
 
+    fn trust_me(&self) -> ChoiceInstruction {
+        if self.non_counted_bt {
+            ChoiceInstruction::DefaultTrustMe
+        } else {
+            ChoiceInstruction::TrustMe
+        }
+    }
+
+    fn retry_me_else(&self, offset: usize) -> ChoiceInstruction {
+        if self.non_counted_bt {
+            ChoiceInstruction::DefaultRetryMeElse(offset)
+        } else {
+            ChoiceInstruction::RetryMeElse(offset)
+        }
+    }
+    
     fn compile_pred_subseq<'b: 'a>(&mut self, clauses: &'b [PredicateClause])
                                    -> Result<Code, ParserError>
     {
@@ -692,8 +710,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
             if num_clauses > 1 {
                 let choice = match i {
                     0 => ChoiceInstruction::TryMeElse(clause_code.len() + 1),
-                    _ if i == num_clauses - 1 => ChoiceInstruction::TrustMe,
-                    _ => ChoiceInstruction::RetryMeElse(clause_code.len() + 1)
+                    _ if i == num_clauses - 1 => self.trust_me(),
+                    _ => self.retry_me_else(clause_code.len() + 1)
                 };
 
                 code_body.push(Line::Choice(choice));
@@ -726,8 +744,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
             if multi_seq {
                 let choice = match l {
                     0 => ChoiceInstruction::TryMeElse(code_segment.len() + 1),
-                    _ if r == clauses.len() => ChoiceInstruction::TrustMe,
-                    _ => ChoiceInstruction::RetryMeElse(code_segment.len() + 1)
+                    _ if r == clauses.len() => self.trust_me(),
+                    _ => self.retry_me_else(code_segment.len() + 1)
                 };
 
                 code.push(Line::Choice(choice));
index a8553a518380830b72e3abe18e5972d040b9af19..ba326864e5d6c8d3be595b3b4046cc5fac2b9731 100644 (file)
@@ -4,7 +4,7 @@ use prolog::codegen::*;
 use prolog::machine::*;
 use prolog::toplevel::*;
 
-use std::collections::{HashMap, VecDeque};
+use std::collections::{HashMap, HashSet, VecDeque};
 use std::mem;
 
 #[allow(dead_code)]
@@ -48,9 +48,9 @@ pub fn parse_code(wam: &mut Machine, buffer: &str) -> Result<TopLevelPacket, Par
 }
 
 // throw errors if declaration or query found.
-fn compile_relation(tl: &TopLevel) -> Result<Code, ParserError>
+fn compile_relation(tl: &TopLevel, non_counted_bt: bool) -> Result<Code, ParserError>
 {
-    let mut cg = CodeGenerator::<DebrayAllocator>::new();
+    let mut cg = CodeGenerator::<DebrayAllocator>::new(non_counted_bt);
 
     match tl {
         &TopLevel::Declaration(_) | &TopLevel::Query(_) =>
@@ -82,11 +82,11 @@ fn set_first_index(code: &mut Code)
     }
 }
 
-fn compile_appendix(code: &mut Code, queue: Vec<TopLevel>) -> Result<(), ParserError>
+fn compile_appendix(code: &mut Code, queue: Vec<TopLevel>, non_counted_bt: bool) -> Result<(), ParserError>
 {
     for tl in queue.iter() {
         set_first_index(code);
-        code.append(&mut compile_relation(tl)?);
+        code.append(&mut compile_relation(tl, non_counted_bt)?);
     }
 
     Ok(())
@@ -94,10 +94,10 @@ fn compile_appendix(code: &mut Code, queue: Vec<TopLevel>) -> Result<(), ParserE
 
 fn compile_query(terms: Vec<QueryTerm>, queue: Vec<TopLevel>) -> Result<(Code, AllocVarDict), ParserError>
 {
-    let mut cg = CodeGenerator::<DebrayAllocator>::new();
+    let mut cg = CodeGenerator::<DebrayAllocator>::new(false); // count backtracking inferences.
     let mut code = try!(cg.compile_query(&terms));
 
-    compile_appendix(&mut code, queue)?;
+    compile_appendix(&mut code, queue, false)?;
     
     Ok((code, cg.take_vars()))
 }
@@ -122,8 +122,8 @@ fn compile_decl(wam: &mut Machine, tl: TopLevel, queue: Vec<TopLevel>) -> EvalSe
                 Err(SessionError::NamelessEntry)
             });
 
-            let mut code = try_eval_session!(compile_relation(&tl));
-            try_eval_session!(compile_appendix(&mut code, queue));
+            let mut code = try_eval_session!(compile_relation(&tl, false));
+            try_eval_session!(compile_appendix(&mut code, queue, false));
 
             if !code.is_empty() {
                 wam.add_user_code(name, tl.arity(), code, tl.as_predicate().ok().unwrap())
@@ -149,12 +149,15 @@ pub fn compile_packet(wam: &mut Machine, tl: TopLevelPacket) -> EvalSession
 
 pub struct ListingCompiler<'a> {
     wam: &'a mut Machine,
+    non_counted_bt_preds: HashSet<PredicateKey>,
     module: Option<Module>
 }
 
 impl<'a> ListingCompiler<'a> {
     pub fn new(wam: &'a mut Machine) -> Self {
-        ListingCompiler { wam, module: None }
+        ListingCompiler { wam,
+                          module: None,
+                          non_counted_bt_preds: HashSet::new() }
     }
 
     fn get_module_name(&self) -> ClauseName {
@@ -174,14 +177,20 @@ impl<'a> ListingCompiler<'a> {
                 cl.name().map(|name| (name, arity))
             }).ok_or(SessionError::NamelessEntry)?;
 
+            let non_counted_bt = self.non_counted_bt_preds.contains(&(name.clone(), arity));
+
             let p = code.len() + self.wam.code_size();
-            let mut decl_code = compile_relation(&TopLevel::Predicate(decl))?;
+            let mut decl_code = compile_relation(&TopLevel::Predicate(decl), non_counted_bt)?;
 
-            compile_appendix(&mut decl_code, Vec::from(queue))?;
+            compile_appendix(&mut decl_code, Vec::from(queue), non_counted_bt)?;
 
+//            println!("\n{}/{}:\n", name.as_str(), arity);
+            
             let idx = code_dir.entry((name, arity)).or_insert(CodeIndex::default());
             set_code_index!(idx, IndexPtr::Index(p), self.get_module_name());
 
+//            print_code(&decl_code);
+
             code.extend(decl_code.into_iter());
         }
 
@@ -202,6 +211,10 @@ impl<'a> ListingCompiler<'a> {
             self.wam.add_batched_ops(op_dir);
         }
     }
+
+    fn add_non_counted_bt_flag(&mut self, name: ClauseName, arity: usize) {
+        self.non_counted_bt_preds.insert((name, arity));
+    }
 }
 
 fn use_module(module: &mut Option<Module>, submodule: &Module, indices: &mut MachineCodeIndices)
@@ -231,6 +244,8 @@ fn compile_listing(wam: &mut Machine, src_str: &str, mut indices: MachineCodeInd
 
     while let Some(decl) = try_eval_session!(worker.consume(&mut indices)) {
         match decl {
+            Declaration::NonCountedBacktracking(name, arity) =>
+                compiler.add_non_counted_bt_flag(name, arity),            
             Declaration::Op(op_decl) =>
                 try_eval_session!(op_decl.submit(compiler.get_module_name(), &mut indices.op_dir)),
             Declaration::UseModule(name) =>
index 6b78785d8a44d113c35bc2e07552df29ab17428e..5276b69854f5f8d2871af99aacb09bed17aba631 100644 (file)
@@ -183,11 +183,15 @@ impl fmt::Display for IndexedChoiceInstruction {
 
 impl fmt::Display for ChoiceInstruction {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match self {
+        match self {            
             &ChoiceInstruction::TryMeElse(offset) =>
                 write!(f, "try_me_else {}", offset),
+            &ChoiceInstruction::DefaultRetryMeElse(offset) =>
+                write!(f, "retry_me_else_by_default {}", offset),
             &ChoiceInstruction::RetryMeElse(offset) =>
                 write!(f, "retry_me_else {}", offset),
+            &ChoiceInstruction::DefaultTrustMe =>
+                write!(f, "trust_me_by_default"),
             &ChoiceInstruction::TrustMe =>
                 write!(f, "trust_me")
         }
index 8a0ff0c294440484cb576e98e43a258de28d0a9c..ace096a0487aa269f46ff1d063fc2a1a3ba59673 100644 (file)
@@ -8,6 +8,11 @@
        (:)/2, call_with_inference_limit/3, catch/3,
        setup_call_cleanup/3, throw/1, true/0, false/0]).
 
+/* this is an implementation specific declarative operator used to implement call_with_inference_limit/3
+   and setup_call_cleanup/3. switches to the default trust_me and retry_me_else. Indexing choice
+   instructions are unchanged. */
+:- op(700, fx, non_counted_backtracking).
+
 % arithmetic operators.
 :- op(700, xfx, is).
 :- op(500, yfx, +).
@@ -67,8 +72,9 @@ false :- '$fail'.
 
 % control operators.
 
-','(G1, G2) :- '$get_cp'(B), ','(G1, G2, B).
+','(G1, G2) :- '$get_b_value'(B), ','(G1, G2, B).
 
+:- non_counted_backtracking (,)/3.
 ','(!, ','(G1, G2), B) :- '$set_cp'(B), ','(G1, G2, B).
 ','(!, !, B) :- '$set_cp'(B).
 ','(!, G, B) :- '$set_cp'(B), G.
@@ -76,16 +82,18 @@ false :- '$fail'.
 ','(G, !, B) :- !, G, '$set_cp'(B).
 ','(G1, G2, _) :- G1, G2.
 
-;(G1, G2) :- '$get_cp'(B), ;(G1, G2, B).
+;(G1, G2) :- '$get_b_value'(B), ;(G1, G2, B).
 
+:- non_counted_backtracking (;)/3.
 ;(G1, G4, B) :- compound(G1), G1 = ->(G2, G3), (G2 -> G3 ; '$set_cp'(B), G4).
 ;(G1, G2, B) :- G1 == !, '$set_cp'(B), call(G2).
 ;(G1, G2, B) :- G2 == !, call(G2), '$set_cp'(B).
 ;(G, _, _) :- G.
 ;(_, G, _) :- G.
 
-G1 -> G2 :- '$get_cp'(B), ->(G1, G2, B).
+G1 -> G2 :- '$get_b_value'(B), ->(G1, G2, B).
 
+:- non_counted_backtracking (->)/3.
 ->(G1, G2, B) :- G2 == !, call(G1), !, '$set_cp'(B).
 ->(G1, G2, B) :- call(G1), '$set_cp'(B), call(G2).
 
@@ -152,29 +160,39 @@ univ_worker(Term, List, _) :-
 
 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) ).
+    ( '$call_with_default_policy'(var(C)) -> throw(error(instantiation_error, setup_call_cleanup/3))
+    ; '$call_with_default_policy'(scc_helper(C, G, Bb)) ).
 
+:- non_counted_backtracking scc_helper/3.
 scc_helper(C, G, Bb) :-
     '$get_cp'(Cp), '$install_scc_cleaner'(C, NBb), call(G),
-    ( '$check_cp'(Cp) -> '$reset_block'(Bb), run_cleaners_without_handling(Cp)
-    ; true
+    ( '$check_cp'(Cp) -> '$reset_block'(Bb),
+                        '$call_with_default_policy'(run_cleaners_without_handling(Cp))
+    ; '$call_with_default_policy'(true)
     ; '$reset_block'(NBb), '$fail').
 scc_helper(_, _, Bb) :-
     '$reset_block'(Bb), '$get_ball'(Ball),
-    run_cleaners_with_handling, throw(Ball).
+    '$call_with_default_policy'(run_cleaners_with_handling),
+    '$erase_ball',
+    '$call_with_default_policy'(throw(Ball)).
 scc_helper(_, _, _) :-
-    '$get_cp'(Cp), run_cleaners_without_handling(Cp), '$fail'.
+    '$get_cp'(Cp),
+    '$call_with_default_policy'(run_cleaners_without_handling(Cp)),
+    '$fail'.
 
+:- non_counted_backtracking run_cleaners_with_handling/0.
 run_cleaners_with_handling :-
-    '$get_scc_cleaner'(C), '$get_level'(B), catch(C, _, true), '$set_cp_by_default'(B),
-    run_cleaners_with_handling.
+    '$get_scc_cleaner'(C), '$get_level'(B),
+    '$call_with_default_policy'(catch(C, _, true)),
+    '$set_cp_by_default'(B),
+    '$call_with_default_policy'(run_cleaners_with_handling).
 run_cleaners_with_handling :-
     '$restore_cut_policy'.
 
+:- non_counted_backtracking run_cleaners_without_handling/1.
 run_cleaners_without_handling(Cp) :-
     '$get_scc_cleaner'(C), '$get_level'(B), C, '$set_cp_by_default'(B),
-    run_cleaners_without_handling(Cp).
+    '$call_with_default_policy'(run_cleaners_without_handling(Cp)).
 run_cleaners_without_handling(Cp) :-
     '$set_cp_by_default'(Cp), '$restore_cut_policy'.
 
@@ -186,6 +204,7 @@ call_with_inference_limit(G, L, R) :-
     '$call_with_default_policy'(call_with_inference_limit(G, L, R, Bb, B)),
     '$remove_call_policy_check'(B).
 
+:- non_counted_backtracking call_with_inference_limit/5.
 call_with_inference_limit(G, L, R, Bb, B) :-
     '$install_new_block'(NBb),
     '$install_inference_counter'(B, L, Count0),
@@ -199,8 +218,10 @@ call_with_inference_limit(_, _, R, Bb, B) :-
     '$remove_inference_counter'(B, _),
     ( '$get_ball'(Ball), '$get_level'(Cp), '$set_cp_by_default'(Cp)
     ; '$remove_call_policy_check'(B), '$fail' ),
+    '$erase_ball',
     '$call_with_default_policy'(handle_ile(B, Ball, R)).
 
+:- non_counted_backtracking end_block/4.
 end_block(_, Bb, NBb, L) :-
     '$clean_up_block'(NBb),
     '$reset_block'(Bb).
@@ -209,19 +230,30 @@ end_block(B, Bb, NBb, L) :-
     '$reset_block'(NBb),
     '$fail'.
 
+:- non_counted_backtracking handle_ile/3.
 handle_ile(B, inference_limit_exceeded(B), inference_limit_exceeded) :- !.
-handle_ile(B, _, _) :- '$remove_call_policy_check'(B), '$unwind_stack'. % throw(E).
+handle_ile(B, E, _) :-
+    '$remove_call_policy_check'(B),
+    '$call_with_default_policy'(throw(E)).
 
 % exceptions.
 
-catch(G,C,R) :- '$get_current_block'(Bb), catch(G,C,R,Bb).
+catch(G,C,R) :- '$get_current_block'(Bb), '$call_with_default_policy'(catch(G,C,R,Bb)).
 
-catch(G,C,R,Bb) :- '$install_new_block'(NBb), call(G), end_block(Bb, NBb).
-catch(G,C,R,Bb) :- '$reset_block'(Bb), '$get_ball'(Ball), handle_ball(Ball, C, R).
+:- non_counted_backtracking catch/4.
+catch(G,C,R,Bb) :-
+    '$install_new_block'(NBb), call(G),
+    '$call_with_default_policy'(end_block(Bb, NBb)).
+catch(G,C,R,Bb) :-
+    '$reset_block'(Bb),
+    '$get_ball'(Ball),
+    '$call_with_default_policy'(handle_ball(Ball, C, R)).
 
+:- non_counted_backtracking end_block/2.
 end_block(Bb, NBb) :- '$clean_up_block'(NBb), '$reset_block'(Bb).
 end_block(Bb, NBb) :- '$reset_block'(NBb), '$fail'.
 
+:- non_counted_backtracking handle_ball/3.
 handle_ball(C, C, R) :- !, '$erase_ball', call(R).
 handle_ball(_, _, _) :- '$unwind_stack'.
 
index 28b04a9ba237b295522b654b7afd5d9e32915eea..32c8d923b31803e2fb6860dbf3e5b065971b151b 100644 (file)
@@ -85,6 +85,7 @@ 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)>;
+    fn op_dir(&self) -> &OpDir;
 }
 
 impl<'a> CodeDirsAdapter<'a> for CodeDirs<'a> {
@@ -95,6 +96,10 @@ impl<'a> CodeDirsAdapter<'a> for CodeDirs<'a> {
     fn get_op(&self, key: OpDirKey) -> Option<(Specifier, usize, ClauseName)> {
         self.op_dir.get(&key).cloned()
     }
+
+    fn op_dir(&self) -> &OpDir {
+        &self.op_dir
+    }
 }
 
 impl<'a> CodeDirsAdapter<'a> for &'a Module {
@@ -107,6 +112,10 @@ impl<'a> CodeDirsAdapter<'a> for &'a Module {
     fn get_op(&self, key: OpDirKey) -> Option<(Specifier, usize, ClauseName)> {
         self.op_dir.get(&key).cloned()
     }
+
+    fn op_dir(&self) -> &OpDir {
+        &self.op_dir
+    }
 }
 
 pub(super) struct DuplicateTerm<'a> {
@@ -506,7 +515,7 @@ pub(crate) trait CallPolicy: Any {
     }
 
     fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType,
-                        code_dirs: CodeDirs<'a>)
+                        code_dirs: Box<CodeDirsAdapter<'a> + 'a>)
                         -> CallResult
     {
         match ct {
@@ -552,7 +561,7 @@ pub(crate) trait CallPolicy: Any {
             &BuiltInClauseType::Read => {
                 let mut reader = Reader::new(machine_st);
 
-                match reader.read_stdin(code_dirs.op_dir) {
+                match reader.read_stdin(code_dirs.op_dir()) {
                     Ok(offset) => {
                         let addr = reader.machine_st[temp_v!(1)].clone();
                         reader.machine_st.unify(addr, Addr::HeapCell(offset));
@@ -658,8 +667,10 @@ pub(crate) trait CallPolicy: Any {
 
                     machine_st.p = CodePtr::CallN(arity, machine_st.p.local());
                 },
-                ClauseType::BuiltIn(built_in) =>
-                    machine_st.setup_built_in_call(built_in),
+                ClauseType::BuiltIn(built_in) => {
+                    machine_st.setup_built_in_call(built_in.clone());
+                    self.call_builtin(machine_st, &built_in, code_dirs)?;
+                },
                 ClauseType::Inlined(inlined) =>
                     machine_st.execute_inlined(&inlined),
                 ClauseType::Op(..) | ClauseType::Named(..) =>
@@ -720,7 +731,7 @@ impl CallPolicy for CWILCallPolicy {
     }
 
     fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType,
-                        code_dirs: CodeDirs<'a>)
+                        code_dirs: Box<CodeDirsAdapter<'a> + 'a>)
                         -> CallResult
     {
         self.prev_policy.call_builtin(machine_st, ct, code_dirs)?;
index a07a8093a494b438b8d431a2b73ffbf7cd88d69f..65f54a5d2478967279049966df927c010e585ef6 100644 (file)
@@ -1825,7 +1825,7 @@ impl MachineState {
             },
             &ControlInstruction::CallClause(ClauseType::BuiltIn(ref ct), _, _, lco) => {
                 self.last_call = lco;
-                try_or_fail!(self, call_policy.call_builtin(self, ct, code_dirs));
+                try_or_fail!(self, call_policy.call_builtin(self, ct, Box::new(code_dirs)));
             },
             &ControlInstruction::CallClause(ClauseType::Inlined(ref ct), ..) =>
                 self.execute_inlined(ct),
@@ -1892,7 +1892,7 @@ impl MachineState {
     pub(super) fn execute_choice_instr(&mut self, instr: &ChoiceInstruction,
                                        call_policy: &mut Box<CallPolicy>)
     {
-        match instr {
+        match instr {            
             &ChoiceInstruction::TryMeElse(offset) => {
                 let n = self.num_of_args;
                 let gi = self.next_global_index();
@@ -1917,6 +1917,14 @@ impl MachineState {
                 self.hb = self.heap.h;
                 self.p += 1;
             },
+            &ChoiceInstruction::DefaultRetryMeElse(offset) => {
+                let mut call_policy = DefaultCallPolicy {};
+                try_or_fail!(self, call_policy.retry_me_else(self, offset))
+            },
+            &ChoiceInstruction::DefaultTrustMe => {
+                let mut call_policy = DefaultCallPolicy {};
+                try_or_fail!(self, call_policy.trust_me(self))
+            },
             &ChoiceInstruction::RetryMeElse(offset) =>
                 try_or_fail!(self, call_policy.retry_me_else(self, offset)),
             &ChoiceInstruction::TrustMe =>
index 3455d865eb1c4b9ac82264f3f021ac39c0966ee7..40619881d70419acdcd875ab342dc9b37e268850 100644 (file)
@@ -139,7 +139,7 @@ fn setup_qualified_import(mut terms: Vec<Box<Term>>) -> Result<UseModuleExport,
 fn setup_declaration(term: Term) -> Result<Declaration, ParserError>
 {
     match term {
-        Term::Clause(_, name, terms, _) =>
+        Term::Clause(_, name, mut terms, _) =>
             if name.as_str() == "op" && terms.len() == 3 {
                 Ok(Declaration::Op(setup_op_decl(terms)?))
             } else if name.as_str() == "module" && terms.len() == 2 {
@@ -149,6 +149,9 @@ fn setup_declaration(term: Term) -> Result<Declaration, ParserError>
             } else if name.as_str() == "use_module" && terms.len() == 2 {
                 let (name, exports) = setup_qualified_import(terms)?;
                 Ok(Declaration::UseQualifiedModule(name, exports))
+            } else if name.as_str() == "non_counted_backtracking" && terms.len() == 1 {
+                let (name, arity) = setup_predicate_export(*terms.pop().unwrap())?;
+                Ok(Declaration::NonCountedBacktracking(name, arity))
             } else {
                 Err(ParserError::InconsistentEntry)
             },
index 15fa8301f4b82e8d3616040ab0e769e1f928d092..e5843f84de679b399a4d9760d3cdf13502c10222 100644 (file)
@@ -1519,7 +1519,7 @@ fn test_queries_on_builtins()
     
     assert_prolog_failure!(&mut wam, "?- Pairs = [a-a|Pairs], keysort(Pairs, _).");
     assert_prolog_success!(&mut wam, "?- Pairs = [a-a|Pairs], catch(keysort(Pairs, _), error(E, _), true).",
-                           [["E = type_error(list, [a-a | _22])", "Pairs = [a-a | Pairs]"]]);
+                           [["E = type_error(list, [a-a | _26])", "Pairs = [a-a | Pairs]"]]);
     
     assert_prolog_success!(&mut wam, "?- keysort([], L).",
                            [["L = []"]]);
@@ -1528,9 +1528,9 @@ fn test_queries_on_builtins()
     assert_prolog_success!(&mut wam, "?- catch(keysort([],[a|a]),error(Pat, _),true).",
                            [["Pat = type_error(list, [a | a])"]]);
     assert_prolog_success!(&mut wam, "?- catch(keysort(_, _), error(E, _), true).",
-                           [["E = type_error(list, _13)"]]);
+                           [["E = type_error(list, _17)"]]);
     assert_prolog_success!(&mut wam, "?- catch(keysort([a-1], [_|b]), error(E, _), true).",
-                           [["E = type_error(list, [_24 | b])"]]);
+                           [["E = type_error(list, [_28 | b])"]]);
     assert_prolog_success!(&mut wam, "?- catch(keysort([a-1], [a-b,c-d,a]), error(E, _), true).",
                            [["E = type_error(pair, a)"]]);
     assert_prolog_success!(&mut wam, "?- catch(keysort([a], [a-b]), error(E, _), true).",
@@ -1543,19 +1543,17 @@ fn test_queries_on_builtins()
     assert_prolog_success!(&mut wam, "?- sort([], L).",
                            [["L = []"]]);
     assert_prolog_success!(&mut wam, "?- catch(sort(_, []), error(E, _), true).",
-                           [["E = type_error(list, _13)"]]);
+                           [["E = type_error(list, _17)"]]);
     assert_prolog_success!(&mut wam, "?- catch(sort([a,b,c], not_a_list), error(E, _), true).",
                            [["E = type_error(list, not_a_list)"]]);
     
     assert_prolog_success!(&mut wam, "?- call(((G = 2 ; fail), B=3, !)).",
                            [["G = 2", "B = 3"]]);
-
-    /*
+    
     assert_prolog_success!(&mut wam, "?- call_with_inference_limit((setup_call_cleanup(S=1,(G=2;fail),writeq(S+G>B)), B=3, !), 100, R).",
                            [["G = 2", "B = 3", "R = !", "S = 1"]]);
     assert_prolog_success!(&mut wam, "?- call_with_inference_limit((setup_call_cleanup(S=1,(G=2;fail),writeq(S+G>B)), B=3, !), 10, R).",
                            [["S = _1", "G = _4", "B = _14", "R = inference_limit_exceeded"]]);
-   */
 }
 
 #[test]