make system calls exempt from call policy.
This commit is contained in:
@@ -561,9 +561,9 @@ pub enum Term {
|
||||
Var(Cell<VarReg>, Rc<Var>)
|
||||
}
|
||||
|
||||
#[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<Self> {
|
||||
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<usize> 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,14 +232,12 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
|
||||
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<TermMarker>
|
||||
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)
|
||||
-> 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<TermMarker>
|
||||
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<TermMarker>
|
||||
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<TermMarker>
|
||||
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<TermMarker>
|
||||
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<TermMarker>
|
||||
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<TermMarker>
|
||||
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<TermMarker>
|
||||
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<TermMarker>
|
||||
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<TermMarker>
|
||||
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<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)),
|
||||
_ => {
|
||||
let num_perm_vars = if chunk_num == 0 {
|
||||
|
||||
@@ -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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<HeapCellValue>>;
|
||||
|
||||
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 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();
|
||||
|
||||
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();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ impl MachineState {
|
||||
|
||||
fn get_number(&self, at: &ArithmeticTerm) -> Result<Number, MachineError> {
|
||||
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<CallPolicy>,
|
||||
cut_policy: &mut Box<CutPolicy>,
|
||||
instr: &BuiltInInstruction)
|
||||
pub(super)
|
||||
fn execute_built_in_instr<'a>(&mut self, code_dirs: CodeDirs<'a>,
|
||||
call_policy: &mut Box<CallPolicy>,
|
||||
cut_policy: &mut Box<CutPolicy>,
|
||||
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<CallPolicy>,
|
||||
cut_policy: &mut Box<CutPolicy>,
|
||||
@@ -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<CallPolicy>)
|
||||
{
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<CycleSearchResult>
|
||||
{
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user