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),
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)),
Fail,
GetBall,
GetCurrentBlock,
+ GetCutPoint(RegType),
InstallNewBlock,
ResetBlock,
SetBall,
SkipMaxList,
+ Succeed,
UnwindStack
}
&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
}
}
&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"),
}
}
("$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),
KeySort,
NotEq,
Sort,
- System(SystemClauseType)
}
#[derive(Clone)]
CallN,
Inlined(InlinedClauseType),
Op(ClauseName, Fixity, CodeIndex),
- Named(ClauseName, CodeIndex)
+ Named(ClauseName, CodeIndex),
+ System(SystemClauseType)
}
#[derive(Clone)]
&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"),
}
}
&BuiltInClauseType::KeySort => 2,
&BuiltInClauseType::NotEq => 2,
&BuiltInClauseType::Sort => 2,
- &BuiltInClauseType::System(system) => system.arity()
}
}
("keysort", 2) => Some(BuiltInClauseType::KeySort),
("\\==", 2) => Some(BuiltInClauseType::NotEq),
("sort", 2) => Some(BuiltInClauseType::Sort),
- _ => SystemClauseType::from(name, arity).map(BuiltInClauseType::System)
+ _ => None
}
}
}
&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
}
}
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(),
}
}
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())
+ }
+ })
})
- })
+ })
}
}
}
}
-#[derive(Clone)]
+#[derive(Clone, PartialEq)]
pub enum ArithmeticTerm {
Reg(RegType),
Interm(usize),
#[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)]
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
match self {
&ControlInstruction::CallClause(..) => true,
&ControlInstruction::GetCleanerCall => true,
- &ControlInstruction::Goto(..) => true,
&ControlInstruction::IsClause(..) => true,
&ControlInstruction::JmpBy(..) => true,
_ => false
#[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)
}
pub fn local(&self) -> LocalCodePtr {
match self {
&CodePtr::BuiltInClause(_, ref local)
- | &CodePtr::CallN(_, ref local)
| &CodePtr::Local(ref local) => local.clone()
}
}
match self {
CodePtr::Local(local) => CodePtr::Local(local + rhs),
CodePtr::BuiltInClause(_, local) => CodePtr::Local(local + rhs),
- CodePtr::CallN(_, local) => CodePtr::Local(local + rhs),
}
}
}
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,
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)?;
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!());
code.push(fail!());
}
},
- InlinedClauseType::IsAtomic(..) =>
+ &InlinedClauseType::IsAtomic(..) =>
match terms[0].as_ref() {
&Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) => {
code.push(fail!());
code.push(is_atomic!(r));
}
},
- InlinedClauseType::IsCompound(..) =>
+ &InlinedClauseType::IsCompound(..) =>
match terms[0].as_ref() {
&Term::Clause(..) | &Term::Cons(..) => {
code.push(succeed!());
code.push(fail!());
}
},
- InlinedClauseType::IsRational(..) =>
+ &InlinedClauseType::IsRational(..) =>
match terms[0].as_ref() {
&Term::Constant(_, Constant::Number(Number::Rational(_))) => {
code.push(succeed!());
code.push(fail!());
}
},
- InlinedClauseType::IsFloat(..) =>
+ &InlinedClauseType::IsFloat(..) =>
match terms[0].as_ref() {
&Term::Constant(_, Constant::Number(Number::Float(_))) => {
code.push(succeed!());
code.push(fail!());
}
},
- InlinedClauseType::IsString(..) =>
+ &InlinedClauseType::IsString(..) =>
match terms[0].as_ref() {
&Term::Constant(_, Constant::String(_)) => {
code.push(succeed!());
code.push(fail!());
}
},
- InlinedClauseType::IsNonVar(..) =>
+ &InlinedClauseType::IsNonVar(..) =>
match terms[0].as_ref() {
&Term::AnonVar => {
code.push(fail!());
code.push(succeed!());
}
},
- InlinedClauseType::IsInteger(..) =>
+ &InlinedClauseType::IsInteger(..) =>
match terms[0].as_ref() {
&Term::Constant(_, Constant::Number(Number::Integer(_))) => {
code.push(succeed!());
code.push(fail!());
},
},
- InlinedClauseType::IsVar(..) =>
+ &InlinedClauseType::IsVar(..) =>
match terms[0].as_ref() {
&Term::Constant(..) | &Term::Clause(..) | &Term::Cons(..) => {
code.push(fail!());
}
}
},
- &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 {
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) =>
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"),
}
}
}
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;
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;
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)
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);
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);
}
}
-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);
}
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()),
}
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);
},
}
}
- 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();
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()));
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;
- },
};
}
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;
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>,
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()));
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));
};
}
- 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>)
{
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))
}
}
}
}
-impl MachineState {
+impl MachineState {
// a step in Brent's algorithm.
fn brents_alg_step(&self, brent_st: &mut BrentAlgState) -> Option<CycleSearchResult>
{
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,
};
let mut brent_st = BrentAlgState::new(hare);
-
+
loop {
if brent_st.steps == max_steps {
return CycleSearchResult::PartialList(brent_st.steps, brent_st.hare);
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);
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();
};
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(())
+ }
+ }
+ }
}
)
}
-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)
)
}
-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))
)
}
+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))
CodePtr::Local(LocalCodePtr::TopLevel($p, $q_sz))
)
}
+