make system calls exempt from call policy.

This commit is contained in:
Mark Thom
2018-05-10 22:24:15 -06:00
parent 0f980e204d
commit 5a631c17c7
8 changed files with 320 additions and 452 deletions

View File

@@ -561,9 +561,9 @@ pub enum Term {
Var(Cell<VarReg>, Rc<Var>) Var(Cell<VarReg>, Rc<Var>)
} }
#[derive(Clone, Copy, PartialEq)] #[derive(Clone, PartialEq)]
pub enum InlinedClauseType { pub enum InlinedClauseType {
CompareNumber(CompareNumberQT, RegType, RegType), CompareNumber(CompareNumberQT, ArithmeticTerm, ArithmeticTerm),
IsAtom(RegType), IsAtom(RegType),
IsAtomic(RegType), IsAtomic(RegType),
IsCompound(RegType), IsCompound(RegType),
@@ -610,19 +610,22 @@ impl InlinedClauseType {
let r1 = temp_v!(1); let r1 = temp_v!(1);
let r2 = temp_v!(2); let r2 = temp_v!(2);
let a1 = ArithmeticTerm::Reg(r1);
let a2 = ArithmeticTerm::Reg(r2);
match (name, arity) { match (name, arity) {
(">", 2) => (">", 2) =>
Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThan, r1, r2)), Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThan, a1, a2)),
("<", 2) => ("<", 2) =>
Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThan, r1, r2)), Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThan, a1, a2)),
(">=", 2) => (">=", 2) =>
Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThanOrEqual,r1, r2)), Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThanOrEqual,a1, a2)),
("=<", 2) => ("=<", 2) =>
Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThanOrEqual, r1, r2)), Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThanOrEqual, a1, a2)),
("=\\=", 2) => ("=\\=", 2) =>
Some(InlinedClauseType::CompareNumber(CompareNumberQT::NotEqual, r1, r2)), Some(InlinedClauseType::CompareNumber(CompareNumberQT::NotEqual, a1, a2)),
("=:=", 2) => ("=:=", 2) =>
Some(InlinedClauseType::CompareNumber(CompareNumberQT::Equal, r1, r2)), Some(InlinedClauseType::CompareNumber(CompareNumberQT::Equal, a1, a2)),
("atom", 1) => Some(InlinedClauseType::IsAtom(r1)), ("atom", 1) => Some(InlinedClauseType::IsAtom(r1)),
("atomic", 1) => Some(InlinedClauseType::IsAtomic(r1)), ("atomic", 1) => Some(InlinedClauseType::IsAtomic(r1)),
("compound", 1) => Some(InlinedClauseType::IsCompound(r1)), ("compound", 1) => Some(InlinedClauseType::IsCompound(r1)),
@@ -716,10 +719,12 @@ pub enum SystemClauseType {
Fail, Fail,
GetBall, GetBall,
GetCurrentBlock, GetCurrentBlock,
GetCutPoint(RegType),
InstallNewBlock, InstallNewBlock,
ResetBlock, ResetBlock,
SetBall, SetBall,
SkipMaxList, SkipMaxList,
Succeed,
UnwindStack UnwindStack
} }
@@ -731,10 +736,12 @@ impl SystemClauseType {
&SystemClauseType::Fail => 0, &SystemClauseType::Fail => 0,
&SystemClauseType::GetBall => 1, &SystemClauseType::GetBall => 1,
&SystemClauseType::GetCurrentBlock => 1, &SystemClauseType::GetCurrentBlock => 1,
&SystemClauseType::GetCutPoint(_) => 1,
&SystemClauseType::InstallNewBlock => 1, &SystemClauseType::InstallNewBlock => 1,
&SystemClauseType::ResetBlock => 1, &SystemClauseType::ResetBlock => 1,
&SystemClauseType::SetBall => 1, &SystemClauseType::SetBall => 1,
&SystemClauseType::SkipMaxList => 4, &SystemClauseType::SkipMaxList => 4,
&SystemClauseType::Succeed => 0,
&SystemClauseType::UnwindStack => 0 &SystemClauseType::UnwindStack => 0
} }
} }
@@ -749,11 +756,13 @@ impl SystemClauseType {
&SystemClauseType::EraseBall => clause_name!("$erase_ball"), &SystemClauseType::EraseBall => clause_name!("$erase_ball"),
&SystemClauseType::Fail => clause_name!("$fail"), &SystemClauseType::Fail => clause_name!("$fail"),
&SystemClauseType::GetBall => clause_name!("$get_ball"), &SystemClauseType::GetBall => clause_name!("$get_ball"),
&SystemClauseType::GetCutPoint(_) => clause_name!("$get_cp"),
&SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"), &SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"),
&SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"), &SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"),
&SystemClauseType::ResetBlock => clause_name!("$reset_block"), &SystemClauseType::ResetBlock => clause_name!("$reset_block"),
&SystemClauseType::SetBall => clause_name!("$set_ball"), &SystemClauseType::SetBall => clause_name!("$set_ball"),
&SystemClauseType::SkipMaxList => clause_name!("$skip_max_list"), &SystemClauseType::SkipMaxList => clause_name!("$skip_max_list"),
&SystemClauseType::Succeed => clause_name!("$succeed"),
&SystemClauseType::UnwindStack => clause_name!("$unwind_stack"), &SystemClauseType::UnwindStack => clause_name!("$unwind_stack"),
} }
} }
@@ -765,6 +774,7 @@ impl SystemClauseType {
("$fail", 0) => Some(SystemClauseType::Fail), ("$fail", 0) => Some(SystemClauseType::Fail),
("$get_ball", 1) => Some(SystemClauseType::GetBall), ("$get_ball", 1) => Some(SystemClauseType::GetBall),
("$get_current_block", 1) => Some(SystemClauseType::GetCurrentBlock), ("$get_current_block", 1) => Some(SystemClauseType::GetCurrentBlock),
("$get_cp", 1) => Some(SystemClauseType::GetCutPoint(temp_v!(0))),
("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock), ("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock),
("$reset_block", 1) => Some(SystemClauseType::ResetBlock), ("$reset_block", 1) => Some(SystemClauseType::ResetBlock),
("$set_ball", 1) => Some(SystemClauseType::SetBall), ("$set_ball", 1) => Some(SystemClauseType::SetBall),
@@ -790,7 +800,6 @@ pub enum BuiltInClauseType {
KeySort, KeySort,
NotEq, NotEq,
Sort, Sort,
System(SystemClauseType)
} }
#[derive(Clone)] #[derive(Clone)]
@@ -799,7 +808,8 @@ pub enum ClauseType {
CallN, CallN,
Inlined(InlinedClauseType), Inlined(InlinedClauseType),
Op(ClauseName, Fixity, CodeIndex), Op(ClauseName, Fixity, CodeIndex),
Named(ClauseName, CodeIndex) Named(ClauseName, CodeIndex),
System(SystemClauseType)
} }
#[derive(Clone)] #[derive(Clone)]
@@ -892,7 +902,6 @@ impl BuiltInClauseType {
&BuiltInClauseType::KeySort => clause_name!("keysort"), &BuiltInClauseType::KeySort => clause_name!("keysort"),
&BuiltInClauseType::NotEq => clause_name!("\\=="), &BuiltInClauseType::NotEq => clause_name!("\\=="),
&BuiltInClauseType::Sort => clause_name!("sort"), &BuiltInClauseType::Sort => clause_name!("sort"),
&BuiltInClauseType::System(system) => system.name()
} }
} }
@@ -911,7 +920,6 @@ impl BuiltInClauseType {
&BuiltInClauseType::KeySort => 2, &BuiltInClauseType::KeySort => 2,
&BuiltInClauseType::NotEq => 2, &BuiltInClauseType::NotEq => 2,
&BuiltInClauseType::Sort => 2, &BuiltInClauseType::Sort => 2,
&BuiltInClauseType::System(system) => system.arity()
} }
} }
@@ -935,7 +943,7 @@ impl BuiltInClauseType {
("keysort", 2) => Some(BuiltInClauseType::KeySort), ("keysort", 2) => Some(BuiltInClauseType::KeySort),
("\\==", 2) => Some(BuiltInClauseType::NotEq), ("\\==", 2) => Some(BuiltInClauseType::NotEq),
("sort", 2) => Some(BuiltInClauseType::Sort), ("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::BuiltIn(ref built_in) => built_in.fixity(),
&ClauseType::Inlined(InlinedClauseType::CompareNumber(..)) => Some(Fixity::In), &ClauseType::Inlined(InlinedClauseType::CompareNumber(..)) => Some(Fixity::In),
&ClauseType::Op(_, fixity, _) => Some(fixity), &ClauseType::Op(_, fixity, _) => Some(fixity),
&ClauseType::System(ref system) => system.fixity(),
_ => None _ => None
} }
} }
@@ -954,9 +963,10 @@ impl ClauseType {
match self { match self {
&ClauseType::CallN => clause_name!("call"), &ClauseType::CallN => clause_name!("call"),
&ClauseType::BuiltIn(built_in) => built_in.name(), &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::Op(ref name, ..) => name.clone(),
&ClauseType::Named(ref name, ..) => name.clone(), &ClauseType::Named(ref name, ..) => name.clone(),
&ClauseType::System(ref system) => system.name(),
} }
} }
@@ -966,6 +976,9 @@ impl ClauseType {
.unwrap_or_else(|| { .unwrap_or_else(|| {
BuiltInClauseType::from(name.as_str(), arity) BuiltInClauseType::from(name.as_str(), arity)
.map(ClauseType::BuiltIn) .map(ClauseType::BuiltIn)
.unwrap_or_else(|| {
SystemClauseType::from(name.as_str(), arity)
.map(ClauseType::System)
.unwrap_or_else(|| { .unwrap_or_else(|| {
if let Some(fixity) = fixity { if let Some(fixity) = fixity {
ClauseType::Op(name, fixity, CodeIndex::default()) ClauseType::Op(name, fixity, CodeIndex::default())
@@ -976,6 +989,7 @@ impl ClauseType {
} }
}) })
}) })
})
} }
} }
@@ -1309,7 +1323,7 @@ impl Neg for Number {
} }
} }
#[derive(Clone)] #[derive(Clone, PartialEq)]
pub enum ArithmeticTerm { pub enum ArithmeticTerm {
Reg(RegType), Reg(RegType),
Interm(usize), Interm(usize),
@@ -1347,30 +1361,14 @@ pub enum ArithmeticInstruction {
#[derive(Clone)] #[derive(Clone)]
pub enum BuiltInInstruction { pub enum BuiltInInstruction {
CleanUpBlock,
CompareNumber(CompareNumberQT, ArithmeticTerm, ArithmeticTerm),
DefaultRetryMeElse(usize),
DefaultSetCutPoint(RegType),
DefaultTrustMe,
EraseBall,
Fail,
GetArg(bool), // last call. GetArg(bool), // last call.
GetBall,
GetCurrentBlock,
GetCutPoint(RegType),
InferenceLevel(RegType, RegType), InferenceLevel(RegType, RegType),
InstallCleaner, InstallCleaner,
InstallInferenceCounter(RegType, RegType, RegType), InstallInferenceCounter(RegType, RegType, RegType),
InstallNewBlock,
RemoveCallPolicyCheck, RemoveCallPolicyCheck,
RemoveInferenceCounter(RegType, RegType), RemoveInferenceCounter(RegType, RegType),
ResetBlock,
RestoreCutPolicy, RestoreCutPolicy,
SetBall,
SetCutPoint(RegType), SetCutPoint(RegType),
Succeed,
Unify,
UnwindStack
} }
#[derive(Clone)] #[derive(Clone)]
@@ -1380,7 +1378,6 @@ pub enum ControlInstruction {
CheckCpExecute, CheckCpExecute,
Deallocate, Deallocate,
GetCleanerCall, GetCleanerCall,
Goto(usize, usize, bool), // p, arity, last call.
IsClause(bool, RegType, ArithmeticTerm), // last call, register of var, term. IsClause(bool, RegType, ArithmeticTerm), // last call, register of var, term.
JmpBy(usize, usize, usize, bool), // arity, global_offset, perm_vars after threshold, last call. JmpBy(usize, usize, usize, bool), // arity, global_offset, perm_vars after threshold, last call.
Proceed Proceed
@@ -1391,7 +1388,6 @@ impl ControlInstruction {
match self { match self {
&ControlInstruction::CallClause(..) => true, &ControlInstruction::CallClause(..) => true,
&ControlInstruction::GetCleanerCall => true, &ControlInstruction::GetCleanerCall => true,
&ControlInstruction::Goto(..) => true,
&ControlInstruction::IsClause(..) => true, &ControlInstruction::IsClause(..) => true,
&ControlInstruction::JmpBy(..) => true, &ControlInstruction::JmpBy(..) => true,
_ => false _ => false
@@ -1586,7 +1582,6 @@ impl From<(usize, ClauseName)> for CodeIndex {
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub enum CodePtr { pub enum CodePtr {
BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call. BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call.
CallN(usize, LocalCodePtr), // the arity of the call, successor call.
Local(LocalCodePtr) Local(LocalCodePtr)
} }
@@ -1594,7 +1589,6 @@ impl CodePtr {
pub fn local(&self) -> LocalCodePtr { pub fn local(&self) -> LocalCodePtr {
match self { match self {
&CodePtr::BuiltInClause(_, ref local) &CodePtr::BuiltInClause(_, ref local)
| &CodePtr::CallN(_, ref local)
| &CodePtr::Local(ref local) => local.clone() | &CodePtr::Local(ref local) => local.clone()
} }
} }
@@ -1684,7 +1678,6 @@ impl Add<usize> for CodePtr {
match self { match self {
CodePtr::Local(local) => CodePtr::Local(local + rhs), CodePtr::Local(local) => CodePtr::Local(local + rhs),
CodePtr::BuiltInClause(_, local) => CodePtr::Local(local + rhs), CodePtr::BuiltInClause(_, local) => CodePtr::Local(local + rhs),
CodePtr::CallN(_, local) => CodePtr::Local(local + rhs),
} }
} }
} }

View File

@@ -232,14 +232,12 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
match ctrl.clone() { match ctrl.clone() {
ControlInstruction::CallClause(ct, arity, pvs, false) => ControlInstruction::CallClause(ct, arity, pvs, false) =>
*ctrl = ControlInstruction::CallClause(ct, arity, pvs, true), *ctrl = ControlInstruction::CallClause(ct, arity, pvs, true),
ControlInstruction::Goto(p, arity, false) =>
*ctrl = ControlInstruction::Goto(p, arity, true),
ControlInstruction::JmpBy(arity, offset, pvs, false) => ControlInstruction::JmpBy(arity, offset, pvs, false) =>
*ctrl = ControlInstruction::JmpBy(arity, offset, pvs, true), *ctrl = ControlInstruction::JmpBy(arity, offset, pvs, true),
ControlInstruction::IsClause(false, r, at) => ControlInstruction::IsClause(false, r, at) =>
*ctrl = ControlInstruction::IsClause(true, r, at), *ctrl = ControlInstruction::IsClause(true, r, at),
ControlInstruction::Proceed => {}, ControlInstruction::Proceed => {},
_ => dealloc_index += 1 // = code.len() _ => dealloc_index += 1
}, },
Some(&mut Line::Cut(CutInstruction::Cut(_))) => Some(&mut Line::Cut(CutInstruction::Cut(_))) =>
dealloc_index += 1, dealloc_index += 1,
@@ -249,12 +247,12 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
dealloc_index dealloc_index
} }
fn compile_inlined(&mut self, ct: InlinedClauseType, terms: &'a Vec<Box<Term>>, fn compile_inlined(&mut self, ct: &InlinedClauseType, terms: &'a Vec<Box<Term>>,
term_loc: GenContext, code: &mut Code) term_loc: GenContext, code: &mut Code)
-> Result<(), ParserError> -> Result<(), ParserError>
{ {
match ct { match ct {
InlinedClauseType::CompareNumber(cmp, ..) => { &InlinedClauseType::CompareNumber(cmp, ..) => {
let (mut lcode, at_1) = self.call_arith_eval(terms[0].as_ref(), 1)?; 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)?; let (mut rcode, at_2) = self.call_arith_eval(terms[1].as_ref(), 2)?;
@@ -265,7 +263,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
at_1.unwrap_or(interm!(1)), at_1.unwrap_or(interm!(1)),
at_2.unwrap_or(interm!(2)))); at_2.unwrap_or(interm!(2))));
}, },
InlinedClauseType::IsAtom(..) => &InlinedClauseType::IsAtom(..) =>
match terms[0].as_ref() { match terms[0].as_ref() {
&Term::Constant(_, Constant::Atom(_)) => { &Term::Constant(_, Constant::Atom(_)) => {
code.push(succeed!()); code.push(succeed!());
@@ -278,7 +276,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
code.push(fail!()); code.push(fail!());
} }
}, },
InlinedClauseType::IsAtomic(..) => &InlinedClauseType::IsAtomic(..) =>
match terms[0].as_ref() { match terms[0].as_ref() {
&Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) => { &Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) => {
code.push(fail!()); code.push(fail!());
@@ -291,7 +289,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
code.push(is_atomic!(r)); code.push(is_atomic!(r));
} }
}, },
InlinedClauseType::IsCompound(..) => &InlinedClauseType::IsCompound(..) =>
match terms[0].as_ref() { match terms[0].as_ref() {
&Term::Clause(..) | &Term::Cons(..) => { &Term::Clause(..) | &Term::Cons(..) => {
code.push(succeed!()); code.push(succeed!());
@@ -304,7 +302,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
code.push(fail!()); code.push(fail!());
} }
}, },
InlinedClauseType::IsRational(..) => &InlinedClauseType::IsRational(..) =>
match terms[0].as_ref() { match terms[0].as_ref() {
&Term::Constant(_, Constant::Number(Number::Rational(_))) => { &Term::Constant(_, Constant::Number(Number::Rational(_))) => {
code.push(succeed!()); code.push(succeed!());
@@ -317,7 +315,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
code.push(fail!()); code.push(fail!());
} }
}, },
InlinedClauseType::IsFloat(..) => &InlinedClauseType::IsFloat(..) =>
match terms[0].as_ref() { match terms[0].as_ref() {
&Term::Constant(_, Constant::Number(Number::Float(_))) => { &Term::Constant(_, Constant::Number(Number::Float(_))) => {
code.push(succeed!()); code.push(succeed!());
@@ -330,7 +328,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
code.push(fail!()); code.push(fail!());
} }
}, },
InlinedClauseType::IsString(..) => &InlinedClauseType::IsString(..) =>
match terms[0].as_ref() { match terms[0].as_ref() {
&Term::Constant(_, Constant::String(_)) => { &Term::Constant(_, Constant::String(_)) => {
code.push(succeed!()); code.push(succeed!());
@@ -343,7 +341,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
code.push(fail!()); code.push(fail!());
} }
}, },
InlinedClauseType::IsNonVar(..) => &InlinedClauseType::IsNonVar(..) =>
match terms[0].as_ref() { match terms[0].as_ref() {
&Term::AnonVar => { &Term::AnonVar => {
code.push(fail!()); code.push(fail!());
@@ -356,7 +354,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
code.push(succeed!()); code.push(succeed!());
} }
}, },
InlinedClauseType::IsInteger(..) => &InlinedClauseType::IsInteger(..) =>
match terms[0].as_ref() { match terms[0].as_ref() {
&Term::Constant(_, Constant::Number(Number::Integer(_))) => { &Term::Constant(_, Constant::Number(Number::Integer(_))) => {
code.push(succeed!()); code.push(succeed!());
@@ -369,7 +367,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
code.push(fail!()); code.push(fail!());
}, },
}, },
InlinedClauseType::IsVar(..) => &InlinedClauseType::IsVar(..) =>
match terms[0].as_ref() { match terms[0].as_ref() {
&Term::Constant(..) | &Term::Clause(..) | &Term::Cons(..) => { &Term::Constant(..) | &Term::Clause(..) | &Term::Cons(..) => {
code.push(fail!()); code.push(fail!());
@@ -446,7 +444,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
} }
} }
}, },
&QueryTerm::Clause(_, ClauseType::Inlined(ct), ref terms) => &QueryTerm::Clause(_, ClauseType::Inlined(ref ct), ref terms) =>
try!(self.compile_inlined(ct, terms, term_loc, code)), try!(self.compile_inlined(ct, terms, term_loc, code)),
_ => { _ => {
let num_perm_vars = if chunk_num == 0 { let num_perm_vars = if chunk_num == 0 {

View File

@@ -139,10 +139,6 @@ impl fmt::Display for ControlInstruction {
write!(f, "deallocate"), write!(f, "deallocate"),
&ControlInstruction::GetCleanerCall => &ControlInstruction::GetCleanerCall =>
write!(f, "get_cleaner_call"), 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) => &ControlInstruction::IsClause(false, r, ref at) =>
write!(f, "is_call {}, {}", r, at), write!(f, "is_call {}, {}", r, at),
&ControlInstruction::IsClause(true, r, ref at) => &ControlInstruction::IsClause(true, r, ref at) =>
@@ -173,56 +169,24 @@ impl fmt::Display for IndexedChoiceInstruction {
impl fmt::Display for BuiltInInstruction { impl fmt::Display for BuiltInInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { 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) => &BuiltInInstruction::InstallInferenceCounter(r1, r2, r3) =>
write!(f, "install_inference_counter {}, {}, {}", 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) => &BuiltInInstruction::GetArg(false) =>
write!(f, "get_arg_call X1, X2, X3"), write!(f, "get_arg_call X1, X2, X3"),
&BuiltInInstruction::GetArg(true) => &BuiltInInstruction::GetArg(true) =>
write!(f, "get_arg_execute X1, X2, X3"), 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) => &BuiltInInstruction::InferenceLevel(r1, r2) =>
write!(f, "inference_level {}, {}", r1, r2), write!(f, "inference_level {}, {}", r1, r2),
&BuiltInInstruction::InstallCleaner => &BuiltInInstruction::InstallCleaner =>
write!(f, "install_cleaner"), write!(f, "install_cleaner"),
&BuiltInInstruction::InstallNewBlock =>
write!(f, "install_new_block"),
&BuiltInInstruction::RemoveCallPolicyCheck => &BuiltInInstruction::RemoveCallPolicyCheck =>
write!(f, "remove_call_policy_check"), write!(f, "remove_call_policy_check"),
&BuiltInInstruction::RemoveInferenceCounter(r1, r2) => &BuiltInInstruction::RemoveInferenceCounter(r1, r2) =>
write!(f, "remove_inference_counter {}, {}", r1, r2), write!(f, "remove_inference_counter {}, {}", r1, r2),
&BuiltInInstruction::ResetBlock =>
write!(f, "reset_block"),
&BuiltInInstruction::RestoreCutPolicy => &BuiltInInstruction::RestoreCutPolicy =>
write!(f, "restore_cut_point"), write!(f, "restore_cut_point"),
&BuiltInInstruction::SetBall =>
write!(f, "set_ball"),
&BuiltInInstruction::SetCutPoint(r) => &BuiltInInstruction::SetCutPoint(r) =>
write!(f, "set_cp {}", r), write!(f, "set_cp {}", r),
&BuiltInInstruction::Succeed =>
write!(f, "true"),
&BuiltInInstruction::UnwindStack =>
write!(f, "unwind_stack"),
&BuiltInInstruction::Unify =>
write!(f, "unify"),
} }
} }
} }

View File

@@ -1,10 +1,10 @@
use prolog::and_stack::*; use prolog::and_stack::*;
use prolog::ast::*; use prolog::ast::*;
use prolog::copier::*; use prolog::copier::*;
use prolog::heap_print::*;
use prolog::machine::machine_errors::MachineStub; use prolog::machine::machine_errors::MachineStub;
use prolog::num::{BigInt, BigUint, Zero, One}; use prolog::num::{BigInt, BigUint, Zero, One};
use prolog::or_stack::*; use prolog::or_stack::*;
use prolog::heap_print::*;
use prolog::tabled_rc::*; use prolog::tabled_rc::*;
use downcast::Any; use downcast::Any;
@@ -227,56 +227,6 @@ pub struct MachineState {
pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>; pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
pub(crate) trait CallPolicy: Any { 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 fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult
{ {
let b = machine_st.b - 1; let b = machine_st.b - 1;
@@ -400,124 +350,54 @@ pub(crate) trait CallPolicy: Any {
Ok(()) Ok(())
} }
fn call_n<'a>(&mut self, machine_st: &mut MachineState, mut arity: usize, fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName, arity: usize,
code_dirs: CodeDirs<'a>, lco: bool) idx: CodeIndex, lco: bool)
-> CallResult -> CallResult
{ {
while let Some((name, inner_arity)) = machine_st.setup_call_n(arity) { if lco {
let user = clause_name!("user"); self.try_execute(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 { } else {
return Err(machine_st.existence_error(name, inner_arity)); self.try_call(machine_st, name, arity, idx)
} }
};
break;
} }
Ok(()) fn try_call(&mut self, machine_st: &mut MachineState, name: ClauseName,
} arity: usize, idx: CodeIndex)
-> CallResult
fn system_call(&mut self, machine_st: &mut MachineState, ct: &SystemClauseType) -> CallResult
{ {
match ct { match idx.0.borrow().0 {
&SystemClauseType::CleanUpBlock => { IndexPtr::Undefined =>
let nb = machine_st.store(machine_st.deref(machine_st[temp_v!(1)].clone())); return Err(machine_st.existence_error(name, arity)),
IndexPtr::Index(compiled_tl_index) => {
let module_name = idx.0.borrow().1.clone();
match nb { machine_st.cp.assign_if_local(machine_st.p.clone() + 1);
Addr::Con(Constant::Usize(nb)) => { machine_st.num_of_args = arity;
let b = machine_st.b - 1; machine_st.b0 = machine_st.b;
machine_st.p = dir_entry!(compiled_tl_index, module_name);
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();
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(())
} }
} }
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 call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType, lco: bool) fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType, lco: bool)
@@ -634,11 +514,94 @@ pub(crate) trait CallPolicy: Any {
Ok(()) 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()
} }
} }
@@ -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 { pub(crate) trait CutPolicy: Any {
fn cut(&mut self, &mut MachineState, RegType); fn cut(&mut self, &mut MachineState, RegType);
} }

View File

@@ -1319,9 +1319,9 @@ impl MachineState {
pub(super) fn execute_inlined(&mut self, inlined: &InlinedClauseType) { pub(super) fn execute_inlined(&mut self, inlined: &InlinedClauseType) {
match inlined { match inlined {
&InlinedClauseType::CompareNumber(cmp, r1, r2) => { &InlinedClauseType::CompareNumber(cmp, ref at_1, ref at_2) => {
let n1 = try_or_fail!(self, self.arith_eval_by_metacall(r1)); let n1 = try_or_fail!(self, self.get_number(at_1));
let n2 = try_or_fail!(self, self.arith_eval_by_metacall(r2)); let n2 = try_or_fail!(self, self.get_number(at_2));
self.compare_numbers(cmp, n1, n2); 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>, pub(super)
fn execute_built_in_instr<'a>(&mut self, code_dirs: CodeDirs<'a>,
call_policy: &mut Box<CallPolicy>, call_policy: &mut Box<CallPolicy>,
cut_policy: &mut Box<CutPolicy>, cut_policy: &mut Box<CutPolicy>,
instr: &BuiltInInstruction) instr: &BuiltInInstruction)
{ {
match instr { 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;
},
&BuiltInInstruction::GetArg(lco) => &BuiltInInstruction::GetArg(lco) =>
try_or_fail!(self, { try_or_fail!(self, {
let val = self.try_get_arg(); let val = self.try_get_arg();
@@ -1440,40 +1419,6 @@ impl MachineState {
val 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. &BuiltInInstruction::InferenceLevel(r1, r2) => { // X1 = R, X2 = B.
let a1 = self[r1].clone(); let a1 = self[r1].clone();
let a2 = self.store(self.deref(self[r2].clone())); let a2 = self.store(self.deref(self[r2].clone()));
@@ -1597,57 +1542,8 @@ impl MachineState {
self.p += 1; self.p += 1;
}, },
&BuiltInInstruction::SetBall => {
self.set_ball();
self.p += 1;
},
&BuiltInInstruction::SetCutPoint(r) => &BuiltInInstruction::SetCutPoint(r) =>
cut_policy.cut(self, 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 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.num_of_args = ct.arity();
self.b0 = self.b; self.b0 = self.b;
@@ -1978,12 +1874,21 @@ impl MachineState {
try_or_fail!(self, call_policy.call_n(self, arity, code_dirs, lco)), try_or_fail!(self, call_policy.call_n(self, arity, code_dirs, lco)),
&ControlInstruction::CallClause(ClauseType::BuiltIn(ref ct), _, _, lco) => &ControlInstruction::CallClause(ClauseType::BuiltIn(ref ct), _, _, lco) =>
try_or_fail!(self, call_policy.call_builtin(self, 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), self.execute_inlined(ct),
&ControlInstruction::CallClause(ClauseType::Named(ref name, ref idx), arity, _, lco) &ControlInstruction::CallClause(ClauseType::Named(ref name, ref idx), arity, _, lco)
| &ControlInstruction::CallClause(ClauseType::Op(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(), try_or_fail!(self, call_policy.context_call(self, name.clone(), arity, idx.clone(),
lco)), 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 => { &ControlInstruction::CheckCpExecute => {
let a = self.store(self.deref(self[temp_v!(2)].clone())); let a = self.store(self.deref(self[temp_v!(2)].clone()));
@@ -2025,8 +1930,6 @@ impl MachineState {
self.fail = true; 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) => { &ControlInstruction::IsClause(lco, r, ref at) => {
let a1 = self[r].clone(); let a1 = self[r].clone();
let a2 = try_or_fail!(self, self.get_number(at)); 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, pub(super) fn execute_indexed_choice_instr(&mut self, instr: &IndexedChoiceInstruction,
call_policy: &mut Box<CallPolicy>) call_policy: &mut Box<CallPolicy>)
{ {

View File

@@ -234,8 +234,6 @@ impl Machine {
Some(self.code[p].clone()), Some(self.code[p].clone()),
CodePtr::BuiltInClause(built_in, _) => CodePtr::BuiltInClause(built_in, _) =>
Some(call_clause!(ClauseType::BuiltIn(built_in), built_in.arity(), 0)), Some(call_clause!(ClauseType::BuiltIn(built_in), built_in.arity(), 0)),
CodePtr::CallN(arity, _) =>
Some(call_clause!(ClauseType::CallN, arity, 0))
} }
} }

View File

@@ -54,8 +54,7 @@ impl MachineState {
pub(super) fn detect_cycles_with_max(&self, max_steps: usize, addr: Addr) -> CycleSearchResult pub(super) fn detect_cycles_with_max(&self, max_steps: usize, addr: Addr) -> CycleSearchResult
{ {
let addr = self.store(self.deref(addr)); let addr = self.store(self.deref(addr));
let hare = match addr {
let mut hare = match addr {
Addr::Lis(offset) if max_steps > 0 => offset + 1, Addr::Lis(offset) if max_steps > 0 => offset + 1,
Addr::Lis(offset) => return CycleSearchResult::UntouchedList(offset), Addr::Lis(offset) => return CycleSearchResult::UntouchedList(offset),
Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList, Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList,
@@ -78,8 +77,7 @@ impl MachineState {
pub(super) fn detect_cycles(&self, addr: Addr) -> CycleSearchResult pub(super) fn detect_cycles(&self, addr: Addr) -> CycleSearchResult
{ {
let addr = self.store(self.deref(addr)); let addr = self.store(self.deref(addr));
let hare = match addr {
let mut hare = match addr {
Addr::Lis(offset) => offset + 1, Addr::Lis(offset) => offset + 1,
Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList, Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList,
_ => return CycleSearchResult::NotList _ => return CycleSearchResult::NotList
@@ -153,4 +151,96 @@ impl MachineState {
Ok(()) 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(())
}
}
}
} }

View File

@@ -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 { macro_rules! interm {
($n: expr) => ( ($n: expr) => (
ArithmeticTerm::Interm($n) 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 { macro_rules! set_cp {
($r:expr) => ( ($r:expr) => (
Line::BuiltIn(BuiltInInstruction::SetCutPoint($r)) 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 { macro_rules! jmp_call {
($arity:expr, $offset:expr, $pvs:expr) => ( ($arity:expr, $offset:expr, $pvs:expr) => (
Line::Control(ControlInstruction::JmpBy($arity, $offset, $pvs, false)) 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)) CodePtr::Local(LocalCodePtr::TopLevel($p, $q_sz))
) )
} }