From: Mark Thom Date: Sat, 17 Mar 2018 07:26:50 +0000 (-0600) Subject: refactor ControlInstruction X-Git-Tag: v0.8.110~523 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=d8bcf474627d801f972a1f15b6ca8413d664f59e;p=scryer-prolog.git refactor ControlInstruction --- diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index e090828e..80456e2b 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -165,7 +165,7 @@ impl SubModuleUser for Module { fn code_dir(&mut self) -> &mut CodeDir { &mut self.code_dir - } + } } pub trait SubModuleUser { @@ -175,7 +175,7 @@ pub trait SubModuleUser { // returns true on successful import. fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool { let name = name.defrock_brackets(); - + if arity == 1 { if let Some(op_data) = submodule.op_dir.get(&(name.clone(), Fixity::Pre)) { self.op_dir().insert((name.clone(), Fixity::Pre), op_data.clone()); @@ -201,14 +201,14 @@ pub trait SubModuleUser { false } } - + fn use_qualified_module(&mut self, submodule: &Module, exports: Vec) -> EvalSession { for (name, arity) in exports { if !submodule.module_decl.exports.contains(&(name.clone(), arity)) { continue; } - + if !self.import_decl(name, arity, submodule) { return EvalSession::from(EvalError::ModuleDoesNotContainExport); } @@ -216,14 +216,14 @@ pub trait SubModuleUser { EvalSession::EntrySuccess } - + fn use_module(&mut self, submodule: &Module) -> EvalSession { for (name, arity) in submodule.module_decl.exports.iter().cloned() { if !self.import_decl(name, arity, submodule) { return EvalSession::from(EvalError::ModuleDoesNotContainExport); } } - + EvalSession::EntrySuccess } } @@ -695,18 +695,6 @@ pub enum ClauseType { Throw, } -impl ClauseType { - pub fn fixity(&self) -> Option { - match self { - &ClauseType::Compare | &ClauseType::CompareTerm(_) - | &ClauseType::Inlined(InlinedClauseType::CompareNumber(_)) - | &ClauseType::NotEq | &ClauseType::Is | &ClauseType::Eq => Some(Fixity::In), - &ClauseType::Op(_, fixity) => Some(fixity), - _ => None - } - } -} - #[derive(Clone)] pub enum ClauseName { BuiltIn(&'static str), @@ -761,7 +749,7 @@ impl ClauseName { s } } - + match self { ClauseName::BuiltIn(s) => ClauseName::BuiltIn(defrock_brackets(s)), @@ -773,6 +761,16 @@ impl ClauseName { } impl ClauseType { + pub fn fixity(&self) -> Option { + match self { + &ClauseType::Compare | &ClauseType::CompareTerm(_) + | &ClauseType::Inlined(InlinedClauseType::CompareNumber(_)) + | &ClauseType::NotEq | &ClauseType::Is | &ClauseType::Eq => Some(Fixity::In), + &ClauseType::Op(_, fixity) => Some(fixity), + _ => None + } + } + pub fn name(&self) -> ClauseName { match self { &ClauseType::Arg => clause_name!("arg"), @@ -1235,90 +1233,26 @@ pub enum BuiltInInstruction { #[derive(Clone)] pub enum ControlInstruction { Allocate(usize), // num_frames. - ArgCall, - ArgExecute, - Call(ClauseName, usize, usize), // name, arity, perm_vars after threshold. - CallN(usize), // arity. - CatchCall, - CatchExecute, + CallClause(ClauseType, usize, usize, bool), // name, arity, perm_vars after threshold, last call. CheckCpExecute, - CompareCall, - CompareExecute, - CompareTermCall(CompareTermQT), - CompareTermExecute(CompareTermQT), - DisplayCall, - DisplayExecute, Deallocate, - DuplicateTermCall, - DuplicateTermExecute, - DynamicIs, - EqCall, - EqExecute, - Execute(ClauseName, usize), - ExecuteN(usize), - FunctorCall, - FunctorExecute, + DynamicIs, GetCleanerCall, - GotoCall(usize, usize), // p, arity. - GotoExecute(usize, usize), // p, arity. - GroundCall, - GroundExecute, - IsCall(RegType, ArithmeticTerm), - IsExecute(RegType, ArithmeticTerm), - JmpByCall(usize, usize), // arity, global_offset. - JmpByExecute(usize, usize), - KeySortCall, - KeySortExecute, - NotEqCall, - NotEqExecute, - Proceed, - SortCall, - SortExecute, - ThrowCall, - ThrowExecute, + Goto(usize, usize, bool), // p, arity, last call. + IsClause(bool, RegType, ArithmeticTerm), // last call, register of var, term. + JmpBy(usize, usize, usize, bool), // arity, global_offset, perm_vars after threshold, last call. + Proceed } impl ControlInstruction { pub fn is_jump_instr(&self) -> bool { match self { - &ControlInstruction::ArgCall => true, - &ControlInstruction::ArgExecute => true, - &ControlInstruction::Call(_, _, _) => true, - &ControlInstruction::CatchCall => true, - &ControlInstruction::CatchExecute => true, - &ControlInstruction::CompareTermCall(..) => true, - &ControlInstruction::CompareTermExecute(..) => true, - &ControlInstruction::DisplayCall => true, - &ControlInstruction::DisplayExecute => true, - &ControlInstruction::DuplicateTermCall => true, - &ControlInstruction::DuplicateTermExecute => true, + &ControlInstruction::CallClause(..) => true, &ControlInstruction::DynamicIs => true, - &ControlInstruction::EqCall => true, - &ControlInstruction::EqExecute => true, - &ControlInstruction::Execute(_, _) => true, - &ControlInstruction::CallN(_) => true, - &ControlInstruction::ExecuteN(_) => true, - &ControlInstruction::FunctorCall => true, - &ControlInstruction::FunctorExecute => true, - &ControlInstruction::NotEqCall => true, - &ControlInstruction::NotEqExecute => true, - &ControlInstruction::ThrowCall => true, - &ControlInstruction::ThrowExecute => true, &ControlInstruction::GetCleanerCall => true, - &ControlInstruction::GotoCall(..) => true, - &ControlInstruction::GotoExecute(..) => true, - &ControlInstruction::GroundCall => true, - &ControlInstruction::GroundExecute => true, - &ControlInstruction::IsCall(..) => true, - &ControlInstruction::IsExecute(..) => true, - &ControlInstruction::JmpByCall(..) => true, - &ControlInstruction::JmpByExecute(..) => true, - &ControlInstruction::CompareCall => true, - &ControlInstruction::CompareExecute => true, - &ControlInstruction::SortCall => true, - &ControlInstruction::SortExecute => true, - &ControlInstruction::KeySortCall => true, - &ControlInstruction::KeySortExecute => true, + &ControlInstruction::Goto(..) => true, + &ControlInstruction::IsClause(..) => true, + &ControlInstruction::JmpBy(..) => true, _ => false } } @@ -1455,7 +1389,7 @@ pub enum CodePtr { TopLevel(usize, usize) // chunk_num, offset. } -impl CodePtr { +impl CodePtr { pub fn module_name(&self) -> ClauseName { match self { &CodePtr::DirEntry(_, ref name) => name.clone(), diff --git a/src/prolog/builtins.rs b/src/prolog/builtins.rs index 535db093..9484a786 100644 --- a/src/prolog/builtins.rs +++ b/src/prolog/builtins.rs @@ -424,7 +424,7 @@ fn get_builtins() -> Code { put_unsafe_value!(4, 2), put_value!(perm_v!(2), 3)], deallocate!(), - jmp_execute!(3, 1), + jmp_execute!(3, 1, 0), try_me_else!(5), // 304. is_var!(temp_v!(1)), neck_cut!(), @@ -581,7 +581,7 @@ fn get_builtins() -> Code { remove_inference_counter!(perm_v!(3), temp_v!(2)), query![put_value!(perm_v!(3), 1), put_var!(perm_v!(2), 2)], - jmp_call!(2, 5), + jmp_call!(2, 5, 0), erase_ball!(), query![put_value!(perm_v!(3), 1), put_unsafe_value!(2, 2), diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index 3ca845d8..84a9ac6a 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -24,8 +24,7 @@ pub struct ConjunctInfo<'a> { impl<'a> ConjunctInfo<'a> { - fn new(perm_vs: VariableFixtures<'a>, num_of_chunks: usize, has_deep_cut: bool) -> Self - { + fn new(perm_vs: VariableFixtures<'a>, num_of_chunks: usize, has_deep_cut: bool) -> Self { ConjunctInfo { perm_vs, num_of_chunks, has_deep_cut } } @@ -205,55 +204,10 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator fn add_conditional_call(code: &mut Code, qt: &QueryTerm, pvs: usize) { match qt { - &QueryTerm::Jump(ref vars) => { - code.push(jmp_call!(vars.len(), 0)); - }, + &QueryTerm::Jump(ref vars) => + code.push(jmp_call!(vars.len(), 0, pvs)), &QueryTerm::Clause(_, ref ct, ref terms) => - match ct { - &ClauseType::CallWithInferenceLimit => - code.push(goto_call!(393, 3)), - &ClauseType::SetupCallCleanup => - code.push(goto_call!(294, 3)), - &ClauseType::Arg => { - let call = ControlInstruction::ArgCall; - code.push(Line::Control(call)); - }, - &ClauseType::CallN => { - let call = ControlInstruction::CallN(terms.len()); - code.push(Line::Control(call)); - }, - &ClauseType::Catch => - code.push(Line::Control(ControlInstruction::CatchCall)), - &ClauseType::Compare => - code.push(Line::Control(ControlInstruction::CompareCall)), - &ClauseType::CompareTerm(qt) => - code.push(Line::Control(ControlInstruction::CompareTermCall(qt))), - &ClauseType::Display => - code.push(Line::Control(ControlInstruction::DisplayCall)), - &ClauseType::DuplicateTerm => - code.push(Line::Control(ControlInstruction::DuplicateTermCall)), - &ClauseType::Eq => - code.push(Line::Control(ControlInstruction::EqCall)), - &ClauseType::Ground => - code.push(Line::Control(ControlInstruction::GroundCall)), - &ClauseType::Functor => - code.push(Line::Control(ControlInstruction::FunctorCall)), - &ClauseType::Inlined(_) => - code.push(proceed!()), - &ClauseType::KeySort => - code.push(keysort_call!()), - &ClauseType::NotEq => - code.push(Line::Control(ControlInstruction::NotEqCall)), - &ClauseType::Named(ref name) | &ClauseType::Op(ref name, _) => { - let call = ControlInstruction::Call(name.clone(), terms.len(), pvs); - code.push(Line::Control(call)); - }, - &ClauseType::Sort => - code.push(sort_call!()), - &ClauseType::Throw => - code.push(Line::Control(ControlInstruction::ThrowCall)), - _ => {} - }, + code.push(call_clause!(ct.clone(), terms.len(), pvs)), _ => {} } } @@ -265,42 +219,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator match code.last_mut() { Some(&mut Line::Control(ref mut ctrl)) => match ctrl.clone() { - ControlInstruction::GotoCall(p, arity) => - *ctrl = ControlInstruction::GotoExecute(p, arity), - ControlInstruction::ArgCall => - *ctrl = ControlInstruction::ArgExecute, - ControlInstruction::Call(name, arity, _) => - *ctrl = ControlInstruction::Execute(name, arity), - ControlInstruction::CallN(arity) => - *ctrl = ControlInstruction::ExecuteN(arity), - ControlInstruction::CompareCall => - *ctrl = ControlInstruction::CompareExecute, - ControlInstruction::CompareTermCall(qt) => - *ctrl = ControlInstruction::CompareTermExecute(qt), - ControlInstruction::DisplayCall => - *ctrl = ControlInstruction::DisplayExecute, - ControlInstruction::DuplicateTermCall => - *ctrl = ControlInstruction::DuplicateTermExecute, - ControlInstruction::EqCall => - *ctrl = ControlInstruction::EqExecute, - ControlInstruction::GroundCall => - *ctrl = ControlInstruction::GroundExecute, - ControlInstruction::FunctorCall => - *ctrl = ControlInstruction::FunctorExecute, - ControlInstruction::JmpByCall(arity, offset) => - *ctrl = ControlInstruction::JmpByExecute(arity, offset), - ControlInstruction::NotEqCall => - *ctrl = ControlInstruction::NotEqExecute, - ControlInstruction::CatchCall => - *ctrl = ControlInstruction::CatchExecute, - ControlInstruction::KeySortCall => - *ctrl = ControlInstruction::KeySortExecute, - ControlInstruction::SortCall => - *ctrl = ControlInstruction::SortExecute, - ControlInstruction::ThrowCall => - *ctrl = ControlInstruction::ThrowExecute, - ControlInstruction::IsCall(r, at) => - *ctrl = ControlInstruction::IsExecute(r, at), + ControlInstruction::CallClause(ct, arity, pvs, false) => + *ctrl = ControlInstruction::CallClause(ct, arity, pvs, true), + ControlInstruction::Goto(p, arity, false) => + *ctrl = ControlInstruction::Goto(p, arity, true), + ControlInstruction::JmpBy(arity, offset, pvs, false) => + *ctrl = ControlInstruction::JmpBy(arity, offset, pvs, true), + ControlInstruction::IsClause(false, r, at) => + *ctrl = ControlInstruction::IsClause(true, r, at), ControlInstruction::Proceed => {}, _ => dealloc_index += 1 // = code.len() }, diff --git a/src/prolog/debray_allocator.rs b/src/prolog/debray_allocator.rs index b53a5878..00aa1ed2 100644 --- a/src/prolog/debray_allocator.rs +++ b/src/prolog/debray_allocator.rs @@ -34,7 +34,7 @@ impl DebrayAllocator { fn is_in_use(&self, r: usize) -> bool { let in_use_range = r <= self.arity && r >= self.arg_c; - self.in_use.contains(&r) || in_use_range + in_use_range || self.in_use.contains(&r) } fn alloc_with_cr(&self, var: &Var) -> usize diff --git a/src/prolog/io.rs b/src/prolog/io.rs index f9db8fc7..3b4824c4 100644 --- a/src/prolog/io.rs +++ b/src/prolog/io.rs @@ -109,88 +109,32 @@ impl fmt::Display for ControlInstruction { match self { &ControlInstruction::Allocate(num_cells) => write!(f, "allocate {}", num_cells), - &ControlInstruction::ArgCall => - write!(f, "arg_call"), - &ControlInstruction::ArgExecute => - write!(f, "arg_execute"), - &ControlInstruction::Call(ref name, arity, pvs) => - write!(f, "call {}/{}, {}", name, arity, pvs), - &ControlInstruction::CallN(arity) => - write!(f, "call_N {}", arity), - &ControlInstruction::CatchCall => - write!(f, "catch_call"), - &ControlInstruction::CatchExecute => - write!(f, "catch_execute"), + &ControlInstruction::CallClause(ref ct, arity, pvs, true) => + write!(f, "execute {}/{}, {}", ct.name(), arity, pvs), + &ControlInstruction::CallClause(ref ct, arity, pvs, false) => + write!(f, "call {}/{}, {}", ct.name(), arity, pvs), &ControlInstruction::CheckCpExecute => write!(f, "check_cp_execute"), - &ControlInstruction::CompareCall => - write!(f, "compare_call"), - &ControlInstruction::CompareExecute => - write!(f, "compare_execute"), - &ControlInstruction::CompareTermCall(qt) => - write!(f, "compare_term_call {}", qt), - &ControlInstruction::CompareTermExecute(qt) => - write!(f, "compare_term_execute {}", qt), - &ControlInstruction::DisplayCall => - write!(f, "display_call"), - &ControlInstruction::DisplayExecute => - write!(f, "display_execute"), - &ControlInstruction::DuplicateTermCall => - write!(f, "call_duplicate_term"), - &ControlInstruction::DuplicateTermExecute => - write!(f, "execute_duplicate_term"), - &ControlInstruction::EqCall => - write!(f, "eq_call"), - &ControlInstruction::EqExecute => - write!(f, "eq_execute"), - &ControlInstruction::ExecuteN(arity) => - write!(f, "execute_N {}", arity), - &ControlInstruction::FunctorCall => - write!(f, "functor_call"), - &ControlInstruction::FunctorExecute => - write!(f, "functor_execute"), &ControlInstruction::Deallocate => write!(f, "deallocate"), - &ControlInstruction::GroundCall => - write!(f, "ground_call"), - &ControlInstruction::GroundExecute => - write!(f, "ground_execute"), - &ControlInstruction::Execute(ref name, arity) => - write!(f, "execute {}/{}", name, arity), &ControlInstruction::GetCleanerCall => write!(f, "get_cleaner_call"), - &ControlInstruction::GotoCall(p, arity) => + &ControlInstruction::Goto(p, arity, false) => write!(f, "goto_call {}/{}", p, arity), - &ControlInstruction::GotoExecute(p, arity) => + &ControlInstruction::Goto(p, arity, true) => write!(f, "goto_execute {}/{}", p, arity), - &ControlInstruction::IsCall(r, ref at) => + &ControlInstruction::IsClause(false, r, ref at) => write!(f, "is_call {}, {}", r, at), - &ControlInstruction::IsExecute(r, ref at) => + &ControlInstruction::IsClause(true, r, ref at) => write!(f, "is_execute {}, {}", r, at), &ControlInstruction::DynamicIs => write!(f, "call_is"), - &ControlInstruction::JmpByCall(arity, offset) => - write!(f, "jmp_by_call {}/{}", offset, arity), - &ControlInstruction::JmpByExecute(arity, offset) => - write!(f, "jmp_by_execute {}/{}", offset, arity), - &ControlInstruction::KeySortCall => - write!(f, "keysort_call"), - &ControlInstruction::KeySortExecute => - write!(f, "keysort_execute"), - &ControlInstruction::NotEqCall => - write!(f, "neq_call"), - &ControlInstruction::NotEqExecute => - write!(f, "neq_execute"), + &ControlInstruction::JmpBy(arity, offset, pvs, false) => + write!(f, "jmp_by_call {}/{}, {}", offset, arity, pvs), + &ControlInstruction::JmpBy(arity, offset, pvs, true) => + write!(f, "jmp_by_execute {}/{}, {}", offset, arity, pvs), &ControlInstruction::Proceed => write!(f, "proceed"), - &ControlInstruction::SortCall => - write!(f, "call_sort"), - &ControlInstruction::SortExecute => - write!(f, "execute_sort"), - &ControlInstruction::ThrowCall => - write!(f, "call_throw"), - &ControlInstruction::ThrowExecute => - write!(f, "execute_throw"), } } } @@ -521,10 +465,9 @@ fn set_first_index(code: &mut Code) for (idx, line) in code.iter_mut().enumerate() { match line { - &mut Line::Control(ControlInstruction::JmpByExecute(_, ref mut offset)) - | &mut Line::Control(ControlInstruction::JmpByCall(_, ref mut offset)) if *offset == 0 => { - *offset = code_len - idx; - break; + &mut Line::Control(ControlInstruction::JmpBy(_, ref mut offset, ..)) if *offset == 0 => { + *offset = code_len - idx; + break; }, _ => {} }; diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index b52565ac..dbc34905 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -3,10 +3,12 @@ use prolog::ast::*; use prolog::copier::*; use prolog::num::{BigInt, BigUint, Zero, One}; use prolog::or_stack::*; +use prolog::heap_print::*; use prolog::tabled_rc::*; use downcast::Any; +use std::cmp::Ordering; use std::collections::HashMap; use std::mem::swap; use std::ops::{Index, IndexMut}; @@ -36,7 +38,7 @@ impl<'a> CodeDirs<'a> { pub(crate) fn get(&self, name: ClauseName, arity: usize, p: &CodePtr) -> Option<(usize, ClauseName)> { - let code_dir = self.get_current_code_dir(p); + let code_dir = self.get_current_code_dir(p); code_dir.get(&(name, arity)).cloned() } } @@ -230,7 +232,7 @@ pub(crate) trait CallPolicy: Any { }, None => machine_st.fail = true }; - + Ok(()) } @@ -376,6 +378,154 @@ pub(crate) trait CallPolicy: Any { Ok(()) } + + fn try_call_clause<'a>(&mut self, machine_st: &mut MachineState, code_dirs: CodeDirs<'a>, + ct: &ClauseType, arity: usize, lco: bool) + -> CallResult + { + match ct { + &ClauseType::Arg => { + if !lco { + machine_st.cp = machine_st.p.clone() + 1; + } + + machine_st.num_of_args = 3; + machine_st.b0 = machine_st.b; + machine_st.p = CodePtr::DirEntry(150, clause_name!("builtin")); + + Ok(()) + }, + &ClauseType::Catch => { + if !lco { + machine_st.cp = machine_st.p.clone() + 1; + } + + machine_st.num_of_args = 3; + machine_st.b0 = machine_st.b; + machine_st.p = CodePtr::DirEntry(5, clause_name!("builtin")); + + Ok(()) + }, + &ClauseType::CallN => + if let Some((name, arity)) = machine_st.setup_call_n(arity) { + if lco { + self.try_execute(machine_st, code_dirs, name, arity) + } else { + self.try_call(machine_st, code_dirs, name, arity) + } + } else { + Ok(()) + }, + &ClauseType::Compare => { + let a1 = machine_st[temp_v!(1)].clone(); + let a2 = machine_st[temp_v!(2)].clone(); + let a3 = machine_st[temp_v!(3)].clone(); + + let c = Addr::Con(match machine_st.compare_term_test(&a2, &a3) { + Ordering::Greater => atom!(">", machine_st.atom_tbl), + Ordering::Equal => atom!("=", machine_st.atom_tbl), + Ordering::Less => atom!("<", machine_st.atom_tbl) + }); + + machine_st.unify(a1, c); + return_from_clause!(lco, machine_st) + }, + &ClauseType::CompareTerm(qt) => { + match qt { + CompareTermQT::Equal => + machine_st.fail = machine_st.structural_eq_test(), + CompareTermQT::NotEqual => + machine_st.fail = !machine_st.structural_eq_test(), + _ => machine_st.compare_term(qt) + }; + + return_from_clause!(lco, machine_st) + }, + &ClauseType::Display => { + let output = machine_st.print_term(machine_st[temp_v!(1)].clone(), + DisplayFormatter {}, + PrinterOutputter::new()); + + println!("{}", output.result()); + return_from_clause!(lco, machine_st) + }, + &ClauseType::DuplicateTerm => { + machine_st.duplicate_term(); + return_from_clause!(lco, machine_st) + }, + &ClauseType::Eq => { + machine_st.fail = machine_st.eq_test(); + return_from_clause!(lco, machine_st) + }, + &ClauseType::Ground => { + machine_st.fail = machine_st.ground_test(); + return_from_clause!(lco, machine_st) + }, + &ClauseType::Functor => { + machine_st.try_functor()?; + return_from_clause!(lco, machine_st) + }, + &ClauseType::NotEq => { + machine_st.fail = !machine_st.eq_test(); + return_from_clause!(lco, machine_st) + }, + &ClauseType::Sort => { + let mut list = machine_st.try_from_list(temp_v!(1))?; + + list.sort_unstable_by(|a1, a2| machine_st.compare_term_test(a1, a2)); + machine_st.term_dedup(&mut list); + + let heap_addr = Addr::HeapCell(machine_st.to_list(list.into_iter())); + + let r2 = machine_st[temp_v!(2)].clone(); + machine_st.unify(r2, heap_addr); + + return_from_clause!(lco, machine_st) + }, + &ClauseType::KeySort => { + let mut list = machine_st.try_from_list(temp_v!(1))?; + let mut key_pairs = Vec::new(); + + for val in list { + let key = machine_st.project_onto_key(val.clone())?; + key_pairs.push((key, val.clone())); + } + + key_pairs.sort_by(|a1, a2| machine_st.compare_term_test(&a1.0, &a2.0)); + + let key_pairs = key_pairs.into_iter().map(|kp| kp.1); + let heap_addr = Addr::HeapCell(machine_st.to_list(key_pairs)); + + let r2 = machine_st[temp_v!(2)].clone(); + machine_st.unify(r2, heap_addr); + + return_from_clause!(lco, machine_st) + }, + &ClauseType::Throw => { + if !lco { + machine_st.cp = machine_st.p.clone() + 1; + } + + machine_st.goto_throw(); + Ok(()) + }, + &ClauseType::Named(ref name) | &ClauseType::Op(ref name, _) => + if lco { + self.try_execute(machine_st, code_dirs, name.clone(), arity) + } else { + self.try_call(machine_st, code_dirs, name.clone(), arity) + }, + &ClauseType::CallWithInferenceLimit => { + machine_st.goto_ptr(CodePtr::DirEntry(393, clause_name!("builtin")), 3, lco); + Ok(()) + }, + &ClauseType::SetupCallCleanup => { + machine_st.goto_ptr(CodePtr::DirEntry(294, clause_name!("builtin")), 3, lco); + Ok(()) + }, + _ => panic!("(is)/2 or an inlined command: should have been superseded by previous clause.") + } + } } downcast!(CallPolicy); @@ -490,6 +640,14 @@ impl CallPolicy for CallWithInferenceLimitCallPolicy { self.prev_policy.trust(machine_st, offset)?; self.increment() } + + fn try_call_clause<'a>(&mut self, machine_st: &mut MachineState, code_dirs: CodeDirs<'a>, + ct: &ClauseType, arity: usize, lco: bool) + -> CallResult + { + self.prev_policy.try_call_clause(machine_st, code_dirs, ct, arity, lco)?; + self.increment() + } } pub(crate) trait CutPolicy: Any { diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 97adb11d..1d72446e 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -91,8 +91,7 @@ impl MachineState { self.trail(r1); } - pub(super) fn print_term(&self, a: Addr, fmt: Fmt, output: Outputter) - -> Outputter + pub(super) fn print_term(&self, a: Addr, fmt: Fmt, output: Outputter) -> Outputter where Fmt: HeapCellValueFormatter, Outputter: HeapCellValueOutputter { let iter = HeapCellPreOrderIterator::new(&self, a); @@ -101,7 +100,7 @@ impl MachineState { printer.print() } - fn unify(&mut self, a1: Addr, a2: Addr) { + pub(super) fn unify(&mut self, a1: Addr, a2: Addr) { let mut pdl = vec![a1, a2]; self.fail = false; @@ -929,7 +928,7 @@ impl MachineState { } } - fn goto_throw(&mut self) { + pub(super) fn goto_throw(&mut self) { self.num_of_args = 1; self.b0 = self.b; self.p = CodePtr::DirEntry(59, clause_name!("builtin")); @@ -947,7 +946,7 @@ impl MachineState { self.goto_throw(); } - fn setup_call_n(&mut self, arity: usize) -> Option + pub(super) fn setup_call_n(&mut self, arity: usize) -> Option { let addr = self.store(self.deref(self.registers[arity].clone())); @@ -1057,7 +1056,7 @@ impl MachineState { self.p += 1; } - fn compare_term(&mut self, qt: CompareTermQT) { + pub(super) fn compare_term(&mut self, qt: CompareTermQT) { let a1 = self[temp_v!(1)].clone(); let a2 = self[temp_v!(2)].clone(); @@ -1080,7 +1079,7 @@ impl MachineState { }; } - fn compare_term_test(&self, a1: &Addr, a2: &Addr) -> Ordering { + pub(super) fn compare_term_test(&self, a1: &Addr, a2: &Addr) -> Ordering { let iter = self.zipped_acyclic_pre_order_iter(a1.clone(), a2.clone()); for (v1, v2) in iter { @@ -1564,7 +1563,7 @@ impl MachineState { }; } - fn try_functor(&mut self) -> Result<(), Vec> { + pub(super) fn try_functor(&mut self) -> Result<(), Vec> { let a1 = self.store(self.deref(self[temp_v!(1)].clone())); match a1.clone() { @@ -1633,7 +1632,7 @@ impl MachineState { Ok(()) } - fn term_dedup(&self, list: &mut Vec) { + pub(super) fn term_dedup(&self, list: &mut Vec) { let mut result = vec![]; for a2 in list.iter().cloned() { @@ -1645,11 +1644,11 @@ impl MachineState { result.push(a2); } - + *list = result; } - - fn to_list>(&mut self, values: Iter) -> usize { + + pub(super) fn to_list>(&mut self, values: Iter) -> usize { let head_addr = self.heap.h; for value in values { @@ -1663,7 +1662,7 @@ impl MachineState { head_addr } - fn try_from_list(&self, r: RegType) -> Result, Vec> + pub(super) fn try_from_list(&self, r: RegType) -> Result, Vec> { let a1 = self.store(self.deref(self[r].clone())); @@ -1673,7 +1672,7 @@ impl MachineState { result.push(self.heap[l].as_addr(l)); l += 1; - + loop { match self.heap[l].clone() { HeapCellValue::Addr(Addr::Lis(hcp)) => { @@ -1696,7 +1695,7 @@ impl MachineState { } } - fn project_onto_key(&self, a: Addr) -> Result> { + pub(super) fn project_onto_key(&self, a: Addr) -> Result> { match self.store(self.deref(a)) { Addr::Str(s) => match self.heap[s].clone() { @@ -1709,8 +1708,8 @@ impl MachineState { a => Err(functor!("type_error", 2, [heap_atom!("callable"), HeapCellValue::Addr(a)])) } } - - fn duplicate_term(&mut self) { + + pub(super) fn duplicate_term(&mut self) { let old_h = self.heap.h; let a1 = self[temp_v!(1)].clone(); @@ -1727,7 +1726,7 @@ impl MachineState { } // returns true on failure. - fn eq_test(&self) -> bool + pub(super) fn eq_test(&self) -> bool { let a1 = self[temp_v!(1)].clone(); let a2 = self[temp_v!(2)].clone(); @@ -1754,7 +1753,7 @@ impl MachineState { } // returns true on failure. - fn structural_eq_test(&self) -> bool + pub(super) fn structural_eq_test(&self) -> bool { let a1 = self[temp_v!(1)].clone(); let a2 = self[temp_v!(2)].clone(); @@ -1797,7 +1796,7 @@ impl MachineState { } // returns true on failure. - fn ground_test(&self) -> bool + pub(super) fn ground_test(&self) -> bool { let a = self.store(self.deref(self[temp_v!(1)].clone())); @@ -1849,34 +1848,8 @@ impl MachineState { self.and_stack.push(gi, self.e, self.cp.clone(), num_cells); self.e = self.and_stack.len() - 1; }, - &ControlInstruction::ArgCall => { - self.cp = self.p.clone() + 1; - self.num_of_args = 3; - self.b0 = self.b; - self.p = CodePtr::DirEntry(150, clause_name!("builtin")); - }, - &ControlInstruction::ArgExecute => { - self.num_of_args = 3; - self.b0 = self.b; - self.p = CodePtr::DirEntry(150, clause_name!("builtin")); - }, - &ControlInstruction::Call(ref name, arity, _) => - try_or_fail!(self, call_policy.try_call(self, code_dirs, name.clone(), arity)), - &ControlInstruction::CatchCall => { - self.cp = self.p.clone() + 1; - self.num_of_args = 3; - self.b0 = self.b; - self.p = CodePtr::DirEntry(5, clause_name!("builtin")); - }, - &ControlInstruction::CatchExecute => { - self.num_of_args = 3; - self.b0 = self.b; - self.p = CodePtr::DirEntry(5, clause_name!("builtin")); - }, - &ControlInstruction::CallN(arity) => - if let Some((name, arity)) = self.setup_call_n(arity) { - try_or_fail!(self, call_policy.try_call(self, code_dirs, name, arity)) - }, + &ControlInstruction::CallClause(ref ct, arity, _, lco) => + try_or_fail!(self, call_policy.try_call_clause(self, code_dirs, ct, arity, lco)), &ControlInstruction::CheckCpExecute => { let a = self.store(self.deref(self[temp_v!(2)].clone())); @@ -1892,58 +1865,6 @@ impl MachineState { } }; }, - &ControlInstruction::CompareCall => { - let a1 = self[temp_v!(1)].clone(); - let a2 = self[temp_v!(2)].clone(); - let a3 = self[temp_v!(3)].clone(); - - let c = Addr::Con(match self.compare_term_test(&a2, &a3) { - Ordering::Greater => atom!(">", self.atom_tbl), - Ordering::Equal => atom!("=", self.atom_tbl), - Ordering::Less => atom!("<", self.atom_tbl) - }); - - self.unify(a1, c); - - self.p += 1; - }, - &ControlInstruction::CompareExecute => { - let a1 = self[temp_v!(1)].clone(); - let a2 = self[temp_v!(2)].clone(); - let a3 = self[temp_v!(3)].clone(); - - let c = Addr::Con(match self.compare_term_test(&a2, &a3) { - Ordering::Greater => atom!(">", self.atom_tbl), - Ordering::Equal => atom!("=", self.atom_tbl), - Ordering::Less => atom!("<", self.atom_tbl) - }); - - self.unify(a1, c); - - self.p = self.cp.clone(); - }, - &ControlInstruction::CompareTermCall(qt) => { - match qt { - CompareTermQT::Equal => - self.fail = self.structural_eq_test(), - CompareTermQT::NotEqual => - self.fail = !self.structural_eq_test(), - _ => self.compare_term(qt) - }; - - self.p += 1; - }, - &ControlInstruction::CompareTermExecute(qt) => { - match qt { - CompareTermQT::Equal => - self.fail = self.structural_eq_test(), - CompareTermQT::NotEqual => - self.fail = !self.structural_eq_test(), - _ => self.compare_term(qt) - }; - - self.p = self.cp.clone(); - }, &ControlInstruction::Deallocate => { let e = self.e; @@ -1952,32 +1873,6 @@ impl MachineState { self.p += 1; }, - &ControlInstruction::DisplayCall => { - let output = self.print_term(self[temp_v!(1)].clone(), - DisplayFormatter {}, - PrinterOutputter::new()); - - println!("{}", output.result()); - - self.p += 1; - }, - &ControlInstruction::DisplayExecute => { - let output = self.print_term(self[temp_v!(1)].clone(), - DisplayFormatter {}, - PrinterOutputter::new()); - - println!("{}", output.result()); - - self.p = self.cp.clone(); - }, - &ControlInstruction::DuplicateTermCall => { - self.duplicate_term(); - self.p += 1; - }, - &ControlInstruction::DuplicateTermExecute => { - self.duplicate_term(); - self.p = self.cp.clone(); - }, &ControlInstruction::DynamicIs => { let a = self[temp_v!(1)].clone(); let result = try_or_fail!(self, self.arith_eval_by_metacall(temp_v!(2))); @@ -1985,40 +1880,6 @@ impl MachineState { self.unify(a, Addr::Con(Constant::Number(result))); self.p += 1; }, - &ControlInstruction::EqCall => { - self.fail = self.eq_test(); - self.p += 1; - }, - &ControlInstruction::EqExecute => { - self.fail = self.eq_test(); - self.p = self.cp.clone(); - }, - &ControlInstruction::GroundCall => { - self.fail = self.ground_test(); - self.p += 1; - }, - &ControlInstruction::GroundExecute => { - self.fail = self.ground_test(); - self.p = self.cp.clone(); - }, - &ControlInstruction::Execute(ref name, arity) => - try_or_fail!(self, call_policy.try_execute(self, code_dirs, name.clone(), arity)), - &ControlInstruction::ExecuteN(arity) => - if let Some((name, arity)) = self.setup_call_n(arity) { - try_or_fail!(self, call_policy.try_execute(self, code_dirs, name, arity)) - }, - &ControlInstruction::FunctorCall => - try_or_fail!(self, { - let val = self.try_functor(); - self.p += 1; - val - }), - &ControlInstruction::FunctorExecute => - try_or_fail!(self, { - let val = self.try_functor(); - self.p = self.cp.clone(); - val - }), &ControlInstruction::GetCleanerCall => { let dest = self[temp_v!(1)].clone(); @@ -2044,136 +1905,39 @@ impl MachineState { self.fail = true; }, - &ControlInstruction::GotoCall(p, arity) => { - self.cp = self.p.clone() + 1; - self.num_of_args = arity; - self.b0 = self.b; - self.p = CodePtr::DirEntry(p, clause_name!("builtin")); - }, - &ControlInstruction::GotoExecute(p, arity) => { - self.num_of_args = arity; - self.b0 = self.b; - self.p = CodePtr::DirEntry(p, clause_name!("builtin")); - }, - &ControlInstruction::IsCall(r, ref at) => { + &ControlInstruction::Goto(p, arity, lco) => + self.goto_ptr(CodePtr::DirEntry(p, clause_name!("builtin")), arity, lco), + &ControlInstruction::IsClause(lco, r, ref at) => { let a1 = self[r].clone(); let a2 = try_or_fail!(self, self.get_number(at)); self.unify(a1, Addr::Con(Constant::Number(a2))); - self.p += 1; + try_or_fail!(self, return_from_clause!(lco, self)); }, - &ControlInstruction::IsExecute(r, ref at) => { - let a1 = self[r].clone(); - let a2 = try_or_fail!(self, self.get_number(at)); + &ControlInstruction::JmpBy(arity, offset, _, lco) => { + if !lco { + self.cp = self.p.clone() + 1; + } - self.unify(a1, Addr::Con(Constant::Number(a2))); - self.p = self.cp.clone(); - }, - &ControlInstruction::JmpByCall(arity, offset) => { - self.cp = self.p.clone() + 1; self.num_of_args = arity; self.b0 = self.b; self.p += offset; }, - &ControlInstruction::JmpByExecute(arity, offset) => { - self.num_of_args = arity; - self.b0 = self.b; - self.p += offset; - }, - &ControlInstruction::NotEqCall => { - self.fail = !self.eq_test(); - self.p += 1; - }, - &ControlInstruction::NotEqExecute => { - self.fail = !self.eq_test(); - self.p = self.cp.clone(); - }, &ControlInstruction::Proceed => self.p = self.cp.clone(), - &ControlInstruction::SortCall => { - let mut list = try_or_fail!(self, { - let val = self.try_from_list(temp_v!(1)); - self.p += 1; - val - }); - - list.sort_unstable_by(|a1, a2| self.compare_term_test(a1, a2)); - self.term_dedup(&mut list); - - let heap_addr = Addr::HeapCell(self.to_list(list.into_iter())); - - let r2 = self[temp_v!(2)].clone(); - self.unify(r2, heap_addr); - }, - &ControlInstruction::SortExecute => { - let mut list = try_or_fail!(self, { - let val = self.try_from_list(temp_v!(1)); - self.p = self.cp.clone(); - val - }); - - list.sort_unstable_by(|a1, a2| self.compare_term_test(a1, a2)); - self.term_dedup(&mut list); - - let heap_addr = Addr::HeapCell(self.to_list(list.into_iter())); - - let r2 = self[temp_v!(2)].clone(); - self.unify(r2, heap_addr); - }, - &ControlInstruction::KeySortCall => { - let mut list = try_or_fail!(self, { - let val = self.try_from_list(temp_v!(1)); - self.p += 1; - val - }); - - let mut key_pairs = Vec::new(); - - for val in list { - let key = try_or_fail!(self, self.project_onto_key(val.clone())); - key_pairs.push((key, val.clone())); - } - - key_pairs.sort_by(|a1, a2| self.compare_term_test(&a1.0, &a2.0)); - - let key_pairs = key_pairs.into_iter().map(|kp| kp.1); - let heap_addr = Addr::HeapCell(self.to_list(key_pairs)); - - let r2 = self[temp_v!(2)].clone(); - self.unify(r2, heap_addr); - }, - &ControlInstruction::KeySortExecute => { - let mut list = try_or_fail!(self, { - let val = self.try_from_list(temp_v!(1)); - self.p = self.cp.clone(); - val - }); - - let mut key_pairs = Vec::new(); - - for val in list { - let key = try_or_fail!(self, self.project_onto_key(val.clone())); - key_pairs.push((key, val.clone())); - } - - key_pairs.sort_by(|a1, a2| self.compare_term_test(&a1.0, &a2.0)); - - let key_pairs = key_pairs.into_iter().map(|kp| kp.1); - let heap_addr = Addr::HeapCell(self.to_list(key_pairs)); - - let r2 = self[temp_v!(2)].clone(); - self.unify(r2, heap_addr); - }, - &ControlInstruction::ThrowCall => { - self.cp = self.p.clone() + 1; - self.goto_throw(); - }, - &ControlInstruction::ThrowExecute => { - self.goto_throw(); - }, }; } + pub(super) fn goto_ptr(&mut self, p: CodePtr, arity: usize, lco:bool) { + if !lco { + self.cp = self.p.clone() + 1; + } + + self.num_of_args = arity; + self.b0 = self.b; + self.p = p; + } + pub(super) fn execute_indexed_choice_instr(&mut self, instr: &IndexedChoiceInstruction, call_policy: &mut Box) { diff --git a/src/prolog/macros.rs b/src/prolog/macros.rs index c6fed893..4c3a5816 100644 --- a/src/prolog/macros.rs +++ b/src/prolog/macros.rs @@ -228,15 +228,21 @@ macro_rules! trust_me { ) } +macro_rules! call_clause { + ($ct:expr, $arity:expr, $pvs:expr) => ( + Line::Control(ControlInstruction::CallClause($ct, $arity, $pvs, false)) + ) +} + macro_rules! call_n { ($arity:expr) => ( - Line::Control(ControlInstruction::CallN($arity)) + Line::Control(ControlInstruction::CallClause(ClauseType::CallN, $arity, 0, false)) ) } macro_rules! execute_n { ($arity:expr) => ( - Line::Control(ControlInstruction::ExecuteN($arity)) + Line::Control(ControlInstruction::CallClause(ClauseType::CallN, $arity, 0, true)) ) } @@ -272,13 +278,13 @@ macro_rules! install_new_block { macro_rules! goto_call { ($line:expr, $arity:expr) => ( - Line::Control(ControlInstruction::GotoCall($line, $arity)) + Line::Control(ControlInstruction::Goto($line, $arity, false)) ) } macro_rules! goto_execute { ($line:expr, $arity:expr) => ( - Line::Control(ControlInstruction::GotoExecute($line, $arity)) + Line::Control(ControlInstruction::Goto($line, $arity, true)) ) } @@ -308,7 +314,8 @@ macro_rules! unify { macro_rules! is_call { ($r:expr, $at:expr) => ( - Line::Control(ControlInstruction::IsCall($r, $at)) + Line::Control(ControlInstruction::IsClause(false, $r, $at)) + ) } @@ -344,7 +351,7 @@ macro_rules! succeed { macro_rules! duplicate_term { () => ( - Line::Control(ControlInstruction::DuplicateTermCall) + Line::Control(ControlInstruction::CallClause(ClauseType::DuplicateTerm, 2, 0, false)) ) } @@ -395,13 +402,13 @@ macro_rules! get_structure { macro_rules! functor_call { () => ( - Line::Control(ControlInstruction::FunctorCall) + Line::Control(ControlInstruction::CallClause(ClauseType::Functor, 3, 0, false)) ) } macro_rules! functor_execute { () => ( - Line::Control(ControlInstruction::FunctorExecute) + Line::Control(ControlInstruction::CallClause(ClauseType::Functor, 3, 0, true)) ) } @@ -485,7 +492,7 @@ macro_rules! infix { macro_rules! display { () => ( - Line::Control(ControlInstruction::DisplayCall) + Line::Control(ControlInstruction::CallClause(ClauseType::Display, 1, 0, false)) ) } @@ -538,14 +545,14 @@ macro_rules! cmp_eq { } macro_rules! jmp_call { - ($arity:expr, $offset:expr) => ( - Line::Control(ControlInstruction::JmpByCall($arity, $offset)) + ($arity:expr, $offset:expr, $pvs:expr) => ( + Line::Control(ControlInstruction::JmpBy($arity, $offset, $pvs, false)) ) } macro_rules! jmp_execute { - ($arity:expr, $offset:expr) => ( - Line::Control(ControlInstruction::JmpByExecute($arity, $offset)) + ($arity:expr, $offset:expr, $pvs:expr) => ( + Line::Control(ControlInstruction::JmpBy($arity, $offset, $pvs, true)) ) } @@ -587,25 +594,25 @@ macro_rules! restore_cut_policy { macro_rules! ground_execute { () => ( - Line::Control(ControlInstruction::GroundExecute) + Line::Control(ControlInstruction::CallClause(ClauseType::Ground, 1, 0, true)) ) } macro_rules! eq_execute { () => ( - Line::Control(ControlInstruction::EqExecute) + Line::Control(ControlInstruction::CallClause(ClauseType::Eq, 2, 0, true)) ) } macro_rules! not_eq_execute { () => ( - Line::Control(ControlInstruction::NotEqExecute) + Line::Control(ControlInstruction::CallClause(ClauseType::NotEq, 2, 0, true)) ) } macro_rules! compare_term_execute { ($qt:expr) => ( - Line::Control(ControlInstruction::CompareTermExecute($qt)) + Line::Control(ControlInstruction::CallClause(ClauseType::CompareTerm($qt), 2, 0, true)) ) } @@ -689,7 +696,7 @@ macro_rules! remove_call_policy_check { macro_rules! compare_execute { () => ( - Line::Control(ControlInstruction::CompareExecute) + Line::Control(ControlInstruction::CallClause(ClauseType::Compare, 2, 0, true)) ) } @@ -708,26 +715,26 @@ macro_rules! try_eval_session { ) } -macro_rules! sort_call { +macro_rules! sort_execute { () => ( - Line::Control(ControlInstruction::SortCall) + Line::Control(ControlInstruction::CallClause(ClauseType::Sort, 2, 0, true)) ) } -macro_rules! keysort_call { +macro_rules! keysort_execute { () => ( - Line::Control(ControlInstruction::KeySortCall) + Line::Control(ControlInstruction::CallClause(ClauseType::KeySort, 2, 0, true)) ) } -macro_rules! sort_execute { - () => ( - Line::Control(ControlInstruction::SortExecute) - ) -} +macro_rules! return_from_clause { + ($lco:expr, $machine_st:expr) => {{ + if $lco { + $machine_st.p = $machine_st.cp.clone(); + } else { + $machine_st.p += 1; + } -macro_rules! keysort_execute { - () => ( - Line::Control(ControlInstruction::KeySortExecute) - ) + Ok(()) + }} } diff --git a/src/tests.rs b/src/tests.rs index 6640fd1b..b144c748 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1694,59 +1694,59 @@ fn test_queries_on_call_with_inference_limit() submit(&mut wam, "f(X) :- call_with_inference_limit(g(X), 5, _)."); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 6, R).", + assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 7, R).", [["R = true", "X = 1"], ["R = true", "X = 2"], ["R = true", "X = 3"], ["R = true", "X = 4"], ["R = !", "X = 5"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 5, R).", + assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 6, R).", [["R = true", "X = 1"], ["R = true", "X = 2"], ["R = true", "X = 3"], ["R = true", "X = 4"], ["R = inference_limit_exceeded", "X = _1"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 3, R).", + assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 4, R).", [["R = true", "X = 1"], ["R = true", "X = 2"], ["R = inference_limit_exceeded", "X = _1"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 2, R).", + assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 3, R).", [["R = true", "X = 1"], ["R = inference_limit_exceeded", "X = _1"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 1, R).", + assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X), 2, R).", [["R = inference_limit_exceeded", "X = _1"]]); submit(&mut wam, "e(X) :- call_with_inference_limit(f(X), 10, _)."); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 7, R).", + assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 10, R).", [["R = true", "X = 1"], ["R = true", "X = 2"], ["R = true", "X = 3"], ["R = true", "X = 4"], ["R = !", "X = 5"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 6, R).", + assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 8, R).", [["R = true", "X = 1"], ["R = true", "X = 2"], ["R = true", "X = 3"], ["R = true", "X = 4"], ["R = inference_limit_exceeded", "X = _1"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 4, R).", + assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 6, R).", [["R = true", "X = 1"], ["R = true", "X = 2"], ["R = inference_limit_exceeded", "X = _1"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 3, R).", + assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 5, R).", [["R = true", "X = 1"], ["R = inference_limit_exceeded", "X = _1"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 2, R).", + assert_prolog_success!(&mut wam, "?- call_with_inference_limit(e(X), 4, R).", [["R = inference_limit_exceeded", "X = _1"]]); submit(&mut wam, "f(X, R) :- call_with_inference_limit(g(X), 5, R)."); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X, R), 3, S).", + assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X, R), 4, S).", [["S = true", "X = 1", "R = true"], ["S = true", "X = 2", "R = true"], ["S = inference_limit_exceeded", "X = _1", "R = _2"]]); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X, R), 7, R).", + assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X, R), 8, R).", [["R = true", "X = 1"], ["R = true", "X = 2"], ["R = true", "X = 3"], @@ -1755,7 +1755,7 @@ fn test_queries_on_call_with_inference_limit() submit(&mut wam, "g(1). g(2). g(3). g(4). g(5). g(6)."); - assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X, R), 7, S).", + assert_prolog_success!(&mut wam, "?- call_with_inference_limit(f(X, R), 8, S).", [["R = true", "X = 1", "S = true"], ["R = true", "X = 2", "S = true"], ["R = true", "X = 3", "S = true"],