From 5a631c17c7027accc2f201bfa847b4e6b627bbe8 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 10 May 2018 22:24:15 -0600 Subject: [PATCH] make system calls exempt from call policy. --- src/prolog/ast.rs | 85 +++--- src/prolog/codegen.rs | 28 +- src/prolog/io.rs | 36 --- src/prolog/machine/machine_state.rs | 320 +++++++++-------------- src/prolog/machine/machine_state_impl.rs | 153 ++--------- src/prolog/machine/mod.rs | 2 - src/prolog/machine/system_calls.rs | 110 +++++++- src/prolog/macros.rs | 38 +-- 8 files changed, 320 insertions(+), 452 deletions(-) diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index 09ef2c8a..2e50706a 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -561,9 +561,9 @@ pub enum Term { Var(Cell, Rc) } -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, PartialEq)] pub enum InlinedClauseType { - CompareNumber(CompareNumberQT, RegType, RegType), + CompareNumber(CompareNumberQT, ArithmeticTerm, ArithmeticTerm), IsAtom(RegType), IsAtomic(RegType), IsCompound(RegType), @@ -609,20 +609,23 @@ impl InlinedClauseType { pub fn from(name: &str, arity: usize) -> Option { let r1 = temp_v!(1); let r2 = temp_v!(2); + + let a1 = ArithmeticTerm::Reg(r1); + let a2 = ArithmeticTerm::Reg(r2); match (name, arity) { (">", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThan, r1, r2)), + Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThan, a1, a2)), ("<", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThan, r1, r2)), + Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThan, a1, a2)), (">=", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThanOrEqual,r1, r2)), + Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThanOrEqual,a1, a2)), ("=<", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThanOrEqual, r1, r2)), + Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThanOrEqual, a1, a2)), ("=\\=", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::NotEqual, r1, r2)), + Some(InlinedClauseType::CompareNumber(CompareNumberQT::NotEqual, a1, a2)), ("=:=", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::Equal, r1, r2)), + Some(InlinedClauseType::CompareNumber(CompareNumberQT::Equal, a1, a2)), ("atom", 1) => Some(InlinedClauseType::IsAtom(r1)), ("atomic", 1) => Some(InlinedClauseType::IsAtomic(r1)), ("compound", 1) => Some(InlinedClauseType::IsCompound(r1)), @@ -716,10 +719,12 @@ pub enum SystemClauseType { Fail, GetBall, GetCurrentBlock, + GetCutPoint(RegType), InstallNewBlock, ResetBlock, SetBall, SkipMaxList, + Succeed, UnwindStack } @@ -731,10 +736,12 @@ impl SystemClauseType { &SystemClauseType::Fail => 0, &SystemClauseType::GetBall => 1, &SystemClauseType::GetCurrentBlock => 1, + &SystemClauseType::GetCutPoint(_) => 1, &SystemClauseType::InstallNewBlock => 1, &SystemClauseType::ResetBlock => 1, &SystemClauseType::SetBall => 1, &SystemClauseType::SkipMaxList => 4, + &SystemClauseType::Succeed => 0, &SystemClauseType::UnwindStack => 0 } } @@ -749,11 +756,13 @@ impl SystemClauseType { &SystemClauseType::EraseBall => clause_name!("$erase_ball"), &SystemClauseType::Fail => clause_name!("$fail"), &SystemClauseType::GetBall => clause_name!("$get_ball"), + &SystemClauseType::GetCutPoint(_) => clause_name!("$get_cp"), &SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"), &SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"), &SystemClauseType::ResetBlock => clause_name!("$reset_block"), &SystemClauseType::SetBall => clause_name!("$set_ball"), &SystemClauseType::SkipMaxList => clause_name!("$skip_max_list"), + &SystemClauseType::Succeed => clause_name!("$succeed"), &SystemClauseType::UnwindStack => clause_name!("$unwind_stack"), } } @@ -765,6 +774,7 @@ impl SystemClauseType { ("$fail", 0) => Some(SystemClauseType::Fail), ("$get_ball", 1) => Some(SystemClauseType::GetBall), ("$get_current_block", 1) => Some(SystemClauseType::GetCurrentBlock), + ("$get_cp", 1) => Some(SystemClauseType::GetCutPoint(temp_v!(0))), ("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock), ("$reset_block", 1) => Some(SystemClauseType::ResetBlock), ("$set_ball", 1) => Some(SystemClauseType::SetBall), @@ -790,7 +800,6 @@ pub enum BuiltInClauseType { KeySort, NotEq, Sort, - System(SystemClauseType) } #[derive(Clone)] @@ -799,7 +808,8 @@ pub enum ClauseType { CallN, Inlined(InlinedClauseType), Op(ClauseName, Fixity, CodeIndex), - Named(ClauseName, CodeIndex) + Named(ClauseName, CodeIndex), + System(SystemClauseType) } #[derive(Clone)] @@ -891,8 +901,7 @@ impl BuiltInClauseType { &BuiltInClauseType::Is => clause_name!("is"), &BuiltInClauseType::KeySort => clause_name!("keysort"), &BuiltInClauseType::NotEq => clause_name!("\\=="), - &BuiltInClauseType::Sort => clause_name!("sort"), - &BuiltInClauseType::System(system) => system.name() + &BuiltInClauseType::Sort => clause_name!("sort"), } } @@ -911,7 +920,6 @@ impl BuiltInClauseType { &BuiltInClauseType::KeySort => 2, &BuiltInClauseType::NotEq => 2, &BuiltInClauseType::Sort => 2, - &BuiltInClauseType::System(system) => system.arity() } } @@ -935,7 +943,7 @@ impl BuiltInClauseType { ("keysort", 2) => Some(BuiltInClauseType::KeySort), ("\\==", 2) => Some(BuiltInClauseType::NotEq), ("sort", 2) => Some(BuiltInClauseType::Sort), - _ => SystemClauseType::from(name, arity).map(BuiltInClauseType::System) + _ => None } } } @@ -946,6 +954,7 @@ impl ClauseType { &ClauseType::BuiltIn(ref built_in) => built_in.fixity(), &ClauseType::Inlined(InlinedClauseType::CompareNumber(..)) => Some(Fixity::In), &ClauseType::Op(_, fixity, _) => Some(fixity), + &ClauseType::System(ref system) => system.fixity(), _ => None } } @@ -954,9 +963,10 @@ impl ClauseType { match self { &ClauseType::CallN => clause_name!("call"), &ClauseType::BuiltIn(built_in) => built_in.name(), - &ClauseType::Inlined(inlined) => clause_name!(inlined.name()), + &ClauseType::Inlined(ref inlined) => clause_name!(inlined.name()), &ClauseType::Op(ref name, ..) => name.clone(), &ClauseType::Named(ref name, ..) => name.clone(), + &ClauseType::System(ref system) => system.name(), } } @@ -967,15 +977,19 @@ impl ClauseType { BuiltInClauseType::from(name.as_str(), arity) .map(ClauseType::BuiltIn) .unwrap_or_else(|| { - if let Some(fixity) = fixity { - ClauseType::Op(name, fixity, CodeIndex::default()) - } else if name.as_str() == "call" { - ClauseType::CallN - } else { - ClauseType::Named(name, CodeIndex::default()) - } + SystemClauseType::from(name.as_str(), arity) + .map(ClauseType::System) + .unwrap_or_else(|| { + if let Some(fixity) = fixity { + ClauseType::Op(name, fixity, CodeIndex::default()) + } else if name.as_str() == "call" { + ClauseType::CallN + } else { + ClauseType::Named(name, CodeIndex::default()) + } + }) }) - }) + }) } } @@ -1309,7 +1323,7 @@ impl Neg for Number { } } -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub enum ArithmeticTerm { Reg(RegType), Interm(usize), @@ -1347,30 +1361,14 @@ pub enum ArithmeticInstruction { #[derive(Clone)] pub enum BuiltInInstruction { - CleanUpBlock, - CompareNumber(CompareNumberQT, ArithmeticTerm, ArithmeticTerm), - DefaultRetryMeElse(usize), - DefaultSetCutPoint(RegType), - DefaultTrustMe, - EraseBall, - Fail, GetArg(bool), // last call. - GetBall, - GetCurrentBlock, - GetCutPoint(RegType), InferenceLevel(RegType, RegType), InstallCleaner, InstallInferenceCounter(RegType, RegType, RegType), - InstallNewBlock, RemoveCallPolicyCheck, RemoveInferenceCounter(RegType, RegType), - ResetBlock, RestoreCutPolicy, - SetBall, SetCutPoint(RegType), - Succeed, - Unify, - UnwindStack } #[derive(Clone)] @@ -1379,8 +1377,7 @@ pub enum ControlInstruction { CallClause(ClauseType, usize, usize, bool), // name, arity, perm_vars after threshold, last call. CheckCpExecute, Deallocate, - GetCleanerCall, - Goto(usize, usize, bool), // p, arity, last call. + GetCleanerCall, 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 @@ -1391,7 +1388,6 @@ impl ControlInstruction { match self { &ControlInstruction::CallClause(..) => true, &ControlInstruction::GetCleanerCall => true, - &ControlInstruction::Goto(..) => true, &ControlInstruction::IsClause(..) => true, &ControlInstruction::JmpBy(..) => true, _ => false @@ -1586,7 +1582,6 @@ impl From<(usize, ClauseName)> for CodeIndex { #[derive(Clone, PartialEq)] pub enum CodePtr { BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call. - CallN(usize, LocalCodePtr), // the arity of the call, successor call. Local(LocalCodePtr) } @@ -1594,7 +1589,6 @@ impl CodePtr { pub fn local(&self) -> LocalCodePtr { match self { &CodePtr::BuiltInClause(_, ref local) - | &CodePtr::CallN(_, ref local) | &CodePtr::Local(ref local) => local.clone() } } @@ -1684,7 +1678,6 @@ impl Add for CodePtr { match self { CodePtr::Local(local) => CodePtr::Local(local + rhs), CodePtr::BuiltInClause(_, local) => CodePtr::Local(local + rhs), - CodePtr::CallN(_, local) => CodePtr::Local(local + rhs), } } } diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index 4e6d9ed3..de0f8018 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -232,14 +232,12 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator match ctrl.clone() { 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() + _ => dealloc_index += 1 }, Some(&mut Line::Cut(CutInstruction::Cut(_))) => dealloc_index += 1, @@ -249,12 +247,12 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator dealloc_index } - fn compile_inlined(&mut self, ct: InlinedClauseType, terms: &'a Vec>, + fn compile_inlined(&mut self, ct: &InlinedClauseType, terms: &'a Vec>, term_loc: GenContext, code: &mut Code) -> Result<(), ParserError> { match ct { - InlinedClauseType::CompareNumber(cmp, ..) => { + &InlinedClauseType::CompareNumber(cmp, ..) => { let (mut lcode, at_1) = self.call_arith_eval(terms[0].as_ref(), 1)?; let (mut rcode, at_2) = self.call_arith_eval(terms[1].as_ref(), 2)?; @@ -265,7 +263,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator at_1.unwrap_or(interm!(1)), at_2.unwrap_or(interm!(2)))); }, - InlinedClauseType::IsAtom(..) => + &InlinedClauseType::IsAtom(..) => match terms[0].as_ref() { &Term::Constant(_, Constant::Atom(_)) => { code.push(succeed!()); @@ -278,7 +276,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator code.push(fail!()); } }, - InlinedClauseType::IsAtomic(..) => + &InlinedClauseType::IsAtomic(..) => match terms[0].as_ref() { &Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) => { code.push(fail!()); @@ -291,7 +289,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator code.push(is_atomic!(r)); } }, - InlinedClauseType::IsCompound(..) => + &InlinedClauseType::IsCompound(..) => match terms[0].as_ref() { &Term::Clause(..) | &Term::Cons(..) => { code.push(succeed!()); @@ -304,7 +302,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator code.push(fail!()); } }, - InlinedClauseType::IsRational(..) => + &InlinedClauseType::IsRational(..) => match terms[0].as_ref() { &Term::Constant(_, Constant::Number(Number::Rational(_))) => { code.push(succeed!()); @@ -317,7 +315,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator code.push(fail!()); } }, - InlinedClauseType::IsFloat(..) => + &InlinedClauseType::IsFloat(..) => match terms[0].as_ref() { &Term::Constant(_, Constant::Number(Number::Float(_))) => { code.push(succeed!()); @@ -330,7 +328,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator code.push(fail!()); } }, - InlinedClauseType::IsString(..) => + &InlinedClauseType::IsString(..) => match terms[0].as_ref() { &Term::Constant(_, Constant::String(_)) => { code.push(succeed!()); @@ -343,7 +341,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator code.push(fail!()); } }, - InlinedClauseType::IsNonVar(..) => + &InlinedClauseType::IsNonVar(..) => match terms[0].as_ref() { &Term::AnonVar => { code.push(fail!()); @@ -356,7 +354,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator code.push(succeed!()); } }, - InlinedClauseType::IsInteger(..) => + &InlinedClauseType::IsInteger(..) => match terms[0].as_ref() { &Term::Constant(_, Constant::Number(Number::Integer(_))) => { code.push(succeed!()); @@ -369,7 +367,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator code.push(fail!()); }, }, - InlinedClauseType::IsVar(..) => + &InlinedClauseType::IsVar(..) => match terms[0].as_ref() { &Term::Constant(..) | &Term::Clause(..) | &Term::Cons(..) => { code.push(fail!()); @@ -446,7 +444,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator } } }, - &QueryTerm::Clause(_, ClauseType::Inlined(ct), ref terms) => + &QueryTerm::Clause(_, ClauseType::Inlined(ref ct), ref terms) => try!(self.compile_inlined(ct, terms, term_loc, code)), _ => { let num_perm_vars = if chunk_num == 0 { diff --git a/src/prolog/io.rs b/src/prolog/io.rs index 974876a8..576fa800 100644 --- a/src/prolog/io.rs +++ b/src/prolog/io.rs @@ -139,10 +139,6 @@ impl fmt::Display for ControlInstruction { write!(f, "deallocate"), &ControlInstruction::GetCleanerCall => write!(f, "get_cleaner_call"), - &ControlInstruction::Goto(p, arity, false) => - write!(f, "goto_call {}/{}", p, arity), - &ControlInstruction::Goto(p, arity, true) => - write!(f, "goto_execute {}/{}", p, arity), &ControlInstruction::IsClause(false, r, ref at) => write!(f, "is_call {}, {}", r, at), &ControlInstruction::IsClause(true, r, ref at) => @@ -173,56 +169,24 @@ impl fmt::Display for IndexedChoiceInstruction { impl fmt::Display for BuiltInInstruction { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - &BuiltInInstruction::CleanUpBlock => - write!(f, "clean_up_block"), - &BuiltInInstruction::CompareNumber(cmp, ref at_1, ref at_2) => - write!(f, "number_test {}, {}, {} ", cmp, at_1, at_2), - &BuiltInInstruction::DefaultRetryMeElse(o) => - write!(f, "default_retry_me_else {}", o), - &BuiltInInstruction::DefaultSetCutPoint(r) => - write!(f, "default_set_cp {}", r), - &BuiltInInstruction::DefaultTrustMe => - write!(f, "default_trust_me"), &BuiltInInstruction::InstallInferenceCounter(r1, r2, r3) => write!(f, "install_inference_counter {}, {}, {}", r1, r2, r3), - &BuiltInInstruction::EraseBall => - write!(f, "erase_ball"), - &BuiltInInstruction::Fail => - write!(f, "false"), &BuiltInInstruction::GetArg(false) => write!(f, "get_arg_call X1, X2, X3"), &BuiltInInstruction::GetArg(true) => write!(f, "get_arg_execute X1, X2, X3"), - &BuiltInInstruction::GetBall => - write!(f, "get_ball X1"), - &BuiltInInstruction::GetCurrentBlock => - write!(f, "get_current_block X1"), - &BuiltInInstruction::GetCutPoint(r) => - write!(f, "get_cp {}", r), &BuiltInInstruction::InferenceLevel(r1, r2) => write!(f, "inference_level {}, {}", r1, r2), &BuiltInInstruction::InstallCleaner => write!(f, "install_cleaner"), - &BuiltInInstruction::InstallNewBlock => - write!(f, "install_new_block"), &BuiltInInstruction::RemoveCallPolicyCheck => write!(f, "remove_call_policy_check"), &BuiltInInstruction::RemoveInferenceCounter(r1, r2) => write!(f, "remove_inference_counter {}, {}", r1, r2), - &BuiltInInstruction::ResetBlock => - write!(f, "reset_block"), &BuiltInInstruction::RestoreCutPolicy => write!(f, "restore_cut_point"), - &BuiltInInstruction::SetBall => - write!(f, "set_ball"), &BuiltInInstruction::SetCutPoint(r) => write!(f, "set_cp {}", r), - &BuiltInInstruction::Succeed => - write!(f, "true"), - &BuiltInInstruction::UnwindStack => - write!(f, "unwind_stack"), - &BuiltInInstruction::Unify => - write!(f, "unify"), } } } diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 55d22ed9..74ac779a 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -1,10 +1,10 @@ use prolog::and_stack::*; use prolog::ast::*; use prolog::copier::*; +use prolog::heap_print::*; use prolog::machine::machine_errors::MachineStub; use prolog::num::{BigInt, BigUint, Zero, One}; use prolog::or_stack::*; -use prolog::heap_print::*; use prolog::tabled_rc::*; use downcast::Any; @@ -227,56 +227,6 @@ pub struct MachineState { pub(crate) type CallResult = Result<(), Vec>; pub(crate) trait CallPolicy: Any { - fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName, - arity: usize, idx: CodeIndex, lco: bool) - -> CallResult - { - if lco { - self.try_execute(machine_st, name, arity, idx) - } else { - self.try_call(machine_st, name, arity, idx) - } - } - - fn try_call(&mut self, machine_st: &mut MachineState, name: ClauseName, - arity: usize, idx: CodeIndex) - -> CallResult - { - match idx.0.borrow().0 { - IndexPtr::Undefined => - return Err(machine_st.existence_error(name, arity)), - IndexPtr::Index(compiled_tl_index) => { - let module_name = idx.0.borrow().1.clone(); - - machine_st.cp.assign_if_local(machine_st.p.clone() + 1); - machine_st.num_of_args = arity; - machine_st.b0 = machine_st.b; - machine_st.p = dir_entry!(compiled_tl_index, module_name); - } - } - - Ok(()) - } - - fn try_execute<'a>(&mut self, machine_st: &mut MachineState, name: ClauseName, - arity: usize, idx: CodeIndex) - -> CallResult - { - match idx.0.borrow().0 { - IndexPtr::Undefined => - return Err(machine_st.existence_error(name, arity)), - IndexPtr::Index(compiled_tl_index) => { - let module_name = idx.0.borrow().1.clone(); - - machine_st.num_of_args = arity; - machine_st.b0 = machine_st.b; - machine_st.p = dir_entry!(compiled_tl_index, module_name); - } - } - - Ok(()) - } - fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult { let b = machine_st.b - 1; @@ -400,124 +350,54 @@ pub(crate) trait CallPolicy: Any { Ok(()) } - fn call_n<'a>(&mut self, machine_st: &mut MachineState, mut arity: usize, - code_dirs: CodeDirs<'a>, lco: bool) - -> CallResult + fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName, arity: usize, + idx: CodeIndex, lco: bool) + -> CallResult { - while let Some((name, inner_arity)) = machine_st.setup_call_n(arity) { - let user = clause_name!("user"); + if lco { + self.try_execute(machine_st, name, arity, idx) + } else { + self.try_call(machine_st, name, arity, idx) + } + } - match ClauseType::from(name.clone(), inner_arity, None) { - ClauseType::CallN => { - machine_st.handle_internal_call_n(inner_arity); - - if machine_st.fail { - return Ok(()); - } - - arity = inner_arity; - continue; - }, - ClauseType::BuiltIn(built_in) => - machine_st.setup_built_in_call(built_in, lco), - ClauseType::Inlined(inlined) => - machine_st.execute_inlined(&inlined), - ClauseType::Op(..) | ClauseType::Named(..) => - if let Some(idx) = code_dirs.get(name.clone(), inner_arity, user) { - self.context_call(machine_st, name, inner_arity, idx, lco)?; - } else { - return Err(machine_st.existence_error(name, inner_arity)); - } - }; + fn try_call(&mut self, machine_st: &mut MachineState, name: ClauseName, + arity: usize, idx: CodeIndex) + -> CallResult + { + match idx.0.borrow().0 { + IndexPtr::Undefined => + return Err(machine_st.existence_error(name, arity)), + IndexPtr::Index(compiled_tl_index) => { + let module_name = idx.0.borrow().1.clone(); - break; + machine_st.cp.assign_if_local(machine_st.p.clone() + 1); + machine_st.num_of_args = arity; + machine_st.b0 = machine_st.b; + machine_st.p = dir_entry!(compiled_tl_index, module_name); + } } Ok(()) } - fn system_call(&mut self, machine_st: &mut MachineState, ct: &SystemClauseType) -> CallResult + fn try_execute<'a>(&mut self, machine_st: &mut MachineState, name: ClauseName, + arity: usize, idx: CodeIndex) + -> CallResult { - match ct { - &SystemClauseType::CleanUpBlock => { - let nb = machine_st.store(machine_st.deref(machine_st[temp_v!(1)].clone())); - - match nb { - Addr::Con(Constant::Usize(nb)) => { - let b = machine_st.b - 1; - - if nb > 0 && machine_st.or_stack[b].b == nb { - machine_st.b = machine_st.or_stack[nb - 1].b; - machine_st.or_stack.truncate(machine_st.b); - } - }, - _ => machine_st.fail = true - }; - - Ok(()) - }, - &SystemClauseType::EraseBall => { - machine_st.ball.reset(); - Ok(()) - }, - &SystemClauseType::Fail => { - machine_st.fail = true; - Ok(()) - }, - &SystemClauseType::GetBall => { - let addr = machine_st.store(machine_st.deref(machine_st[temp_v!(1)].clone())); - let h = machine_st.heap.h; - - if machine_st.ball.stub.len() > 0 { - machine_st.copy_and_align_ball_to_heap(); - } else { - machine_st.fail = true; - return Ok(()); - } - - let ball = machine_st.heap[h].as_addr(h); - - match addr.as_var() { - Some(r) => machine_st.bind(r, ball), - _ => machine_st.fail = true - }; - - Ok(()) - }, - &SystemClauseType::GetCurrentBlock => { - let c = Constant::Usize(machine_st.block); - let addr = machine_st[temp_v!(1)].clone(); - - machine_st.write_constant_to_var(addr, c); - Ok(()) - }, - &SystemClauseType::InstallNewBlock => { - machine_st.block = machine_st.b; - - let c = Constant::Usize(machine_st.block); - let addr = machine_st[temp_v!(1)].clone(); + match idx.0.borrow().0 { + IndexPtr::Undefined => + return Err(machine_st.existence_error(name, arity)), + IndexPtr::Index(compiled_tl_index) => { + let module_name = idx.0.borrow().1.clone(); - machine_st.write_constant_to_var(addr, c); - Ok(()) - }, - &SystemClauseType::ResetBlock => { - let addr = machine_st.deref(machine_st[temp_v!(1)].clone()); - machine_st.reset_block(addr); - Ok(()) - }, - &SystemClauseType::SetBall => { - machine_st.set_ball(); - Ok(()) - }, - &SystemClauseType::SkipMaxList => { - machine_st.skip_max_list()?; - Ok(()) - }, - &SystemClauseType::UnwindStack => { - machine_st.unwind_stack(); - Ok(()) + machine_st.num_of_args = arity; + machine_st.b0 = machine_st.b; + machine_st.p = dir_entry!(compiled_tl_index, module_name); } } + + Ok(()) } fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType, lco: bool) @@ -619,7 +499,7 @@ pub(crate) trait CallPolicy: Any { 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); @@ -634,12 +514,95 @@ pub(crate) trait CallPolicy: Any { Ok(()) }, - &BuiltInClauseType::System(ref ct) => { - self.system_call(machine_st, ct)?; - return_from_clause!(lco, machine_st) - } } } + + fn call_n<'a>(&mut self, machine_st: &mut MachineState, mut arity: usize, + code_dirs: CodeDirs<'a>, lco: bool) + -> CallResult + { + while let Some((name, inner_arity)) = machine_st.setup_call_n(arity) { + let user = clause_name!("user"); + + match ClauseType::from(name.clone(), inner_arity, None) { + ClauseType::CallN => { + machine_st.handle_internal_call_n(inner_arity); + + if machine_st.fail { + return Ok(()); + } + + arity = inner_arity; + continue; + }, + ClauseType::BuiltIn(built_in) => + machine_st.setup_built_in_call(built_in), + ClauseType::Inlined(inlined) => + machine_st.execute_inlined(&inlined), + ClauseType::Op(..) | ClauseType::Named(..) => + if let Some(idx) = code_dirs.get(name.clone(), inner_arity, user) { + self.context_call(machine_st, name, inner_arity, idx, lco)?; + } else { + return Err(machine_st.existence_error(name, inner_arity)); + }, + ClauseType::System(ct) => + return machine_st.system_call(&ct) + }; + + break; + } + + Ok(()) + } +} + +impl CallPolicy for CallWithInferenceLimitCallPolicy { + fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName, + arity: usize, idx: CodeIndex, lco: bool) + -> CallResult + { + self.prev_policy.context_call(machine_st, name, arity, idx, lco)?; + self.increment() + } + + fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult + { + self.prev_policy.retry_me_else(machine_st, offset)?; + self.increment() + } + + fn retry(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult + { + self.prev_policy.retry(machine_st, offset)?; + self.increment() + } + + fn trust_me(&mut self, machine_st: &mut MachineState) -> CallResult + { + self.prev_policy.trust_me(machine_st)?; + self.increment() + } + + fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult + { + self.prev_policy.trust(machine_st, offset)?; + self.increment() + } + + fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType, lco: bool) + -> CallResult + { + self.prev_policy.call_builtin(machine_st, ct, lco)?; + self.increment() + } + + fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize, code_dirs: CodeDirs<'a>, + lco: bool) + -> CallResult + { + self.prev_policy.call_n(machine_st, arity, code_dirs, lco)?; + self.increment() + } } downcast!(CallPolicy); @@ -714,39 +677,6 @@ impl CallWithInferenceLimitCallPolicy { } } -impl CallPolicy for CallWithInferenceLimitCallPolicy { - fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult - { - self.prev_policy.retry_me_else(machine_st, offset)?; - self.increment() - } - - fn retry(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult - { - self.prev_policy.retry(machine_st, offset)?; - self.increment() - } - - fn trust_me(&mut self, machine_st: &mut MachineState) -> CallResult - { - self.prev_policy.trust_me(machine_st)?; - self.increment() - } - - fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult - { - self.prev_policy.trust(machine_st, offset)?; - self.increment() - } - - fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType, lco: bool) - -> CallResult - { - self.prev_policy.call_builtin(machine_st, ct, lco)?; - self.increment() - } -} - pub(crate) trait CutPolicy: Any { fn cut(&mut self, &mut MachineState, RegType); } diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 1e368c5f..c8155120 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -296,7 +296,7 @@ impl MachineState { fn get_number(&self, at: &ArithmeticTerm) -> Result { match at { - &ArithmeticTerm::Reg(r) => self.arith_eval_by_metacall(r), + &ArithmeticTerm::Reg(r) => self.arith_eval_by_metacall(r), &ArithmeticTerm::Interm(i) => Ok(self.interms[i-1].clone()), &ArithmeticTerm::Number(ref n) => Ok(n.clone()), } @@ -1319,9 +1319,9 @@ impl MachineState { pub(super) fn execute_inlined(&mut self, inlined: &InlinedClauseType) { match inlined { - &InlinedClauseType::CompareNumber(cmp, r1, r2) => { - let n1 = try_or_fail!(self, self.arith_eval_by_metacall(r1)); - let n2 = try_or_fail!(self, self.arith_eval_by_metacall(r2)); + &InlinedClauseType::CompareNumber(cmp, ref at_1, ref at_2) => { + let n1 = try_or_fail!(self, self.get_number(at_1)); + let n2 = try_or_fail!(self, self.get_number(at_2)); self.compare_numbers(cmp, n1, n2); }, @@ -1400,34 +1400,13 @@ impl MachineState { } } - pub(super) fn execute_built_in_instr<'a>(&mut self, code_dirs: CodeDirs<'a>, - call_policy: &mut Box, - cut_policy: &mut Box, - instr: &BuiltInInstruction) + pub(super) + fn execute_built_in_instr<'a>(&mut self, code_dirs: CodeDirs<'a>, + call_policy: &mut Box, + cut_policy: &mut Box, + instr: &BuiltInInstruction) { - match instr { - &BuiltInInstruction::CompareNumber(cmp, ref at_1, ref at_2) => { - let n1 = try_or_fail!(self, self.get_number(at_1)); - let n2 = try_or_fail!(self, self.get_number(at_2)); - - self.compare_numbers(cmp, n1, n2); - }, - &BuiltInInstruction::DefaultRetryMeElse(o) => { - let mut call_policy = DefaultCallPolicy {}; - try_or_fail!(self, call_policy.retry_me_else(self, o)); - }, - &BuiltInInstruction::DefaultSetCutPoint(r) => { - let mut cut_policy = DefaultCutPolicy {}; - cut_policy.cut(self, r); - }, - &BuiltInInstruction::DefaultTrustMe => { - let mut call_policy = DefaultCallPolicy {}; - try_or_fail!(self, call_policy.trust_me(self)); - }, - &BuiltInInstruction::EraseBall => { - self.ball.reset(); - self.p += 1; - }, + match instr { &BuiltInInstruction::GetArg(lco) => try_or_fail!(self, { let val = self.try_get_arg(); @@ -1440,40 +1419,6 @@ impl MachineState { val }), - &BuiltInInstruction::GetCurrentBlock => { - let c = Constant::Usize(self.block); - let addr = self[temp_v!(1)].clone(); - - self.write_constant_to_var(addr, c); - self.p += 1; - }, - &BuiltInInstruction::GetBall => { - let addr = self.store(self.deref(self[temp_v!(1)].clone())); - let h = self.heap.h; - - if self.ball.stub.len() > 0 { - self.copy_and_align_ball_to_heap(); - } else { - self.fail = true; - return; - } - - let ball = self.heap[h].as_addr(h); - - match addr.as_var() { - Some(r) => { - self.bind(r, ball); - self.p += 1; - }, - _ => self.fail = true - }; - }, - &BuiltInInstruction::GetCutPoint(r) => { - let c = Constant::Usize(self.b); - self[r] = Addr::Con(c); - - self.p += 1; - }, &BuiltInInstruction::InferenceLevel(r1, r2) => { // X1 = R, X2 = B. let a1 = self[r1].clone(); let a2 = self.store(self.deref(self[r2].clone())); @@ -1597,57 +1542,8 @@ impl MachineState { self.p += 1; }, - &BuiltInInstruction::SetBall => { - self.set_ball(); - self.p += 1; - }, &BuiltInInstruction::SetCutPoint(r) => cut_policy.cut(self, r), - &BuiltInInstruction::CleanUpBlock => { - let nb = self.store(self.deref(self[temp_v!(1)].clone())); - - match nb { - Addr::Con(Constant::Usize(nb)) => { - let b = self.b - 1; - - if nb > 0 && self.or_stack[b].b == nb { - self.b = self.or_stack[nb - 1].b; - self.or_stack.truncate(self.b); - } - - self.p += 1; - }, - _ => self.fail = true - }; - }, - &BuiltInInstruction::InstallNewBlock => { - self.block = self.b; - let c = Constant::Usize(self.block); - let addr = self[temp_v!(1)].clone(); - - self.write_constant_to_var(addr, c); - self.p += 1; - }, - &BuiltInInstruction::ResetBlock => { - let addr = self.deref(self[temp_v!(1)].clone()); - self.reset_block(addr); - }, - &BuiltInInstruction::UnwindStack => - self.unwind_stack(), - &BuiltInInstruction::Fail => { - self.fail = true; - self.p += 1; - }, - &BuiltInInstruction::Succeed => { - self.p += 1; - }, - &BuiltInInstruction::Unify => { - let a1 = self[temp_v!(1)].clone(); - let a2 = self[temp_v!(2)].clone(); - - self.unify(a1, a2); - self.p += 1; - }, }; } @@ -1920,7 +1816,7 @@ impl MachineState { false } - pub(super) fn setup_built_in_call(&mut self, ct: BuiltInClauseType, lco: bool) + pub(super) fn setup_built_in_call(&mut self, ct: BuiltInClauseType) { self.num_of_args = ct.arity(); self.b0 = self.b; @@ -1964,8 +1860,8 @@ impl MachineState { self.e = self.and_stack[e].e; self.p += 1; - } - + } + pub(super) fn execute_ctrl_instr<'a>(&mut self, code_dirs: CodeDirs<'a>, call_policy: &mut Box, cut_policy: &mut Box, @@ -1978,12 +1874,21 @@ impl MachineState { try_or_fail!(self, call_policy.call_n(self, arity, code_dirs, lco)), &ControlInstruction::CallClause(ClauseType::BuiltIn(ref ct), _, _, lco) => try_or_fail!(self, call_policy.call_builtin(self, ct, lco)), - &ControlInstruction::CallClause(ClauseType::Inlined(ref ct), _, _, lco) => + &ControlInstruction::CallClause(ClauseType::Inlined(ref ct), ..) => self.execute_inlined(ct), &ControlInstruction::CallClause(ClauseType::Named(ref name, ref idx), arity, _, lco) | &ControlInstruction::CallClause(ClauseType::Op(ref name, _, ref idx), arity, _, lco) => try_or_fail!(self, call_policy.context_call(self, name.clone(), arity, idx.clone(), lco)), + &ControlInstruction::CallClause(ClauseType::System(ref ct), arity, _, lco) => { + try_or_fail!(self, self.system_call(ct)); + + if lco { + self.p = CodePtr::Local(self.cp.clone()); + } else { + self.p += 1; + } + }, &ControlInstruction::CheckCpExecute => { let a = self.store(self.deref(self[temp_v!(2)].clone())); @@ -2025,8 +1930,6 @@ impl MachineState { self.fail = true; }, - &ControlInstruction::Goto(p, arity, lco) => - self.goto_ptr(dir_entry!(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)); @@ -2048,16 +1951,6 @@ impl MachineState { }; } - pub(super) fn goto_ptr(&mut self, p: CodePtr, arity: usize, lco:bool) { - if !lco { - self.cp.assign_if_local(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/machine/mod.rs b/src/prolog/machine/mod.rs index 163c0b16..425ee1e4 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -234,8 +234,6 @@ impl Machine { Some(self.code[p].clone()), CodePtr::BuiltInClause(built_in, _) => Some(call_clause!(ClauseType::BuiltIn(built_in), built_in.arity(), 0)), - CodePtr::CallN(arity, _) => - Some(call_clause!(ClauseType::CallN, arity, 0)) } } diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 1d1c55b1..715969e7 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -19,7 +19,7 @@ impl BrentAlgState { } } -impl MachineState { +impl MachineState { // a step in Brent's algorithm. fn brents_alg_step(&self, brent_st: &mut BrentAlgState) -> Option { @@ -54,8 +54,7 @@ impl MachineState { pub(super) fn detect_cycles_with_max(&self, max_steps: usize, addr: Addr) -> CycleSearchResult { let addr = self.store(self.deref(addr)); - - let mut hare = match addr { + let hare = match addr { Addr::Lis(offset) if max_steps > 0 => offset + 1, Addr::Lis(offset) => return CycleSearchResult::UntouchedList(offset), Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList, @@ -63,7 +62,7 @@ impl MachineState { }; let mut brent_st = BrentAlgState::new(hare); - + loop { if brent_st.steps == max_steps { return CycleSearchResult::PartialList(brent_st.steps, brent_st.hare); @@ -78,22 +77,21 @@ impl MachineState { pub(super) fn detect_cycles(&self, addr: Addr) -> CycleSearchResult { let addr = self.store(self.deref(addr)); - - let mut hare = match addr { + let hare = match addr { Addr::Lis(offset) => offset + 1, Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList, _ => return CycleSearchResult::NotList }; let mut brent_st = BrentAlgState::new(hare); - + loop { if let Some(result) = self.brents_alg_step(&mut brent_st) { return result; } } } - + fn finalize_skip_max_list(&mut self, n: usize, addr: Addr) { let target_n = self[temp_v!(1)].clone(); self.unify(Addr::Con(integer!(n)), target_n); @@ -111,7 +109,7 @@ impl MachineState { Number::Integer(ref max_steps) if max_steps.to_isize().map(|i| i >= -1).unwrap_or(false) => { let n = self.store(self.deref(self[temp_v!(1)].clone())); - + match n { Addr::Con(Constant::Number(Number::Integer(ref n))) if n.is_zero() => { let xs0 = self[temp_v!(3)].clone(); @@ -152,5 +150,97 @@ impl MachineState { }; Ok(()) - } + } + + pub(super) fn system_call(&mut self, ct: &SystemClauseType) -> CallResult + { + match ct { + &SystemClauseType::CleanUpBlock => { + let nb = self.store(self.deref(self[temp_v!(1)].clone())); + + match nb { + Addr::Con(Constant::Usize(nb)) => { + let b = self.b - 1; + + if nb > 0 && self.or_stack[b].b == nb { + self.b = self.or_stack[nb - 1].b; + self.or_stack.truncate(self.b); + } + }, + _ => self.fail = true + }; + + Ok(()) + }, + &SystemClauseType::EraseBall => { + self.ball.reset(); + Ok(()) + }, + &SystemClauseType::Fail => { + self.fail = true; + Ok(()) + }, + &SystemClauseType::GetBall => { + let addr = self.store(self.deref(self[temp_v!(1)].clone())); + let h = self.heap.h; + + if self.ball.stub.len() > 0 { + self.copy_and_align_ball_to_heap(); + } else { + self.fail = true; + return Ok(()); + } + + let ball = self.heap[h].as_addr(h); + + match addr.as_var() { + Some(r) => self.bind(r, ball), + _ => self.fail = true + }; + + Ok(()) + }, + &SystemClauseType::GetCurrentBlock => { + let c = Constant::Usize(self.block); + let addr = self[temp_v!(1)].clone(); + + self.write_constant_to_var(addr, c); + Ok(()) + }, + &SystemClauseType::GetCutPoint(r) => { + let c = Constant::Usize(self.b); + self[r] = Addr::Con(c); + Ok(()) + }, + &SystemClauseType::InstallNewBlock => { + self.block = self.b; + + let c = Constant::Usize(self.block); + let addr = self[temp_v!(1)].clone(); + + self.write_constant_to_var(addr, c); + Ok(()) + }, + &SystemClauseType::ResetBlock => { + let addr = self.deref(self[temp_v!(1)].clone()); + self.reset_block(addr); + Ok(()) + }, + &SystemClauseType::SetBall => { + self.set_ball(); + Ok(()) + }, + &SystemClauseType::SkipMaxList => { + self.skip_max_list()?; + Ok(()) + }, + &SystemClauseType::Succeed => { + Ok(()) + }, + &SystemClauseType::UnwindStack => { + self.unwind_stack(); + Ok(()) + } + } + } } diff --git a/src/prolog/macros.rs b/src/prolog/macros.rs index a665add2..723b02c7 100644 --- a/src/prolog/macros.rs +++ b/src/prolog/macros.rs @@ -19,12 +19,6 @@ macro_rules! atom { ) } -macro_rules! compare_number_instr { - ($cmp: expr, $at_1: expr, $at_2: expr) => ( - Line::BuiltIn(BuiltInInstruction::CompareNumber($cmp, $at_1, $at_2)) - ) -} - macro_rules! interm { ($n: expr) => ( ArithmeticTerm::Interm($n) @@ -156,18 +150,6 @@ macro_rules! is_call { ) } -macro_rules! fail { - () => ( - Line::BuiltIn(BuiltInInstruction::Fail) - ) -} - -macro_rules! succeed { - () => ( - Line::BuiltIn(BuiltInInstruction::Succeed) - ) -} - macro_rules! set_cp { ($r:expr) => ( Line::BuiltIn(BuiltInInstruction::SetCutPoint($r)) @@ -192,6 +174,25 @@ macro_rules! rc_atom { ) } +macro_rules! succeed { + () => ( + call_clause!(ClauseType::System(SystemClauseType::Succeed), 0, 0) + ) +} + +macro_rules! fail { + () => ( + call_clause!(ClauseType::System(SystemClauseType::Fail), 0, 0) + ) +} + +macro_rules! compare_number_instr { + ($cmp: expr, $at_1: expr, $at_2: expr) => {{ + let ct = ClauseType::Inlined(InlinedClauseType::CompareNumber($cmp, $at_1, $at_2)); + call_clause!(ct, 2, 0) + }} +} + macro_rules! jmp_call { ($arity:expr, $offset:expr, $pvs:expr) => ( Line::Control(ControlInstruction::JmpBy($arity, $offset, $pvs, false)) @@ -250,3 +251,4 @@ macro_rules! top_level_code_ptr { CodePtr::Local(LocalCodePtr::TopLevel($p, $q_sz)) ) } + -- 2.54.0