let mut wam = Machine::new();
load_init_str_and_include(&mut wam, BUILTINS, "builtins");
-// load_init_str(&mut wam, LISTS);
+ load_init_str(&mut wam, LISTS);
// load_init_str(&mut wam, CONTROL);
- // load_init_str(&mut wam, QUEUES);
+ // load_init_str(&mut wam, QUEUES);
loop {
print!("prolog> ");
&InlinedClauseType::IsInteger (..) => 1,
&InlinedClauseType::IsRational(..) => 1,
&InlinedClauseType::IsString(..) => 1,
- &InlinedClauseType::IsFloat (..) => 1,
+ &InlinedClauseType::IsFloat (..) => 1,
&InlinedClauseType::IsNonVar(..) => 1,
&InlinedClauseType::IsVar(..) => 1
}
}
-
+
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, a1, a2)),
#[derive(Copy, Clone, PartialEq)]
pub enum SystemClauseType {
+ InstallCleaner,
+ InstallInferenceCounter,
+ RemoveCallPolicyCheck,
+ RemoveInferenceCounter,
+ RestoreCutPolicy,
+ SetCutPoint(RegType),
GetArg,
- InferenceLevel(RegType, RegType),
+ InferenceLevel,
CleanUpBlock,
EraseBall,
Fail,
GetBall,
GetCurrentBlock,
- GetCutPoint(RegType),
+ GetCutPoint,
InstallNewBlock,
ResetBlock,
SetBall,
impl SystemClauseType {
pub fn arity(&self) -> usize {
match self {
+ &SystemClauseType::InstallCleaner => 1,
+ &SystemClauseType::InstallInferenceCounter => 3,
+ &SystemClauseType::RemoveCallPolicyCheck => 1,
+ &SystemClauseType::RemoveInferenceCounter => 2,
+ &SystemClauseType::RestoreCutPolicy => 0,
+ &SystemClauseType::SetCutPoint(_) => 1,
&SystemClauseType::GetArg => 3,
- &SystemClauseType::InferenceLevel(..) => 2,
+ &SystemClauseType::InferenceLevel => 2,
&SystemClauseType::CleanUpBlock => 1,
&SystemClauseType::EraseBall => 0,
&SystemClauseType::Fail => 0,
&SystemClauseType::GetBall => 1,
&SystemClauseType::GetCurrentBlock => 1,
- &SystemClauseType::GetCutPoint(_) => 1,
+ &SystemClauseType::GetCutPoint => 1,
&SystemClauseType::InstallNewBlock => 1,
&SystemClauseType::ResetBlock => 1,
&SystemClauseType::SetBall => 1,
&SystemClauseType::UnwindStack => 0
}
}
-
+
pub fn fixity(&self) -> Option<Fixity> {
None
}
-
+
pub fn name(&self) -> ClauseName {
match self {
+ &SystemClauseType::InstallCleaner => clause_name!("$install_cleaner"),
+ &SystemClauseType::InstallInferenceCounter =>
+ clause_name!("$install_inference_counter"),
+ &SystemClauseType::RemoveCallPolicyCheck =>
+ clause_name!("$remove_call_policy_check"),
+ &SystemClauseType::RemoveInferenceCounter =>
+ clause_name!("$remove_inference_counter"),
+ &SystemClauseType::RestoreCutPolicy => clause_name!("$restore_cut_policy"),
+ &SystemClauseType::SetCutPoint(_) => clause_name!("$set_cp"),
&SystemClauseType::GetArg => clause_name!("$get_arg"),
- &SystemClauseType::InferenceLevel(..) => clause_name!("$inference_level"),
+ &SystemClauseType::InferenceLevel => clause_name!("$inference_level"),
&SystemClauseType::CleanUpBlock => clause_name!("$clean_up_block"),
&SystemClauseType::EraseBall => clause_name!("$erase_ball"),
&SystemClauseType::Fail => clause_name!("$fail"),
&SystemClauseType::GetBall => clause_name!("$get_ball"),
- &SystemClauseType::GetCutPoint(_) => clause_name!("$get_cp"),
+ &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"),
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
match (name, arity) {
+ ("$install_cleaner", 1) =>
+ Some(SystemClauseType::InstallCleaner),
+ ("$install_inference_counter", 3) =>
+ Some(SystemClauseType::InstallInferenceCounter),
+ ("$remove_call_policy_check", 1) =>
+ Some(SystemClauseType::RemoveCallPolicyCheck),
+ ("$remove_inference_counter", 1) =>
+ Some(SystemClauseType::RemoveInferenceCounter),
+ ("$restore_cut_policy", 0) => Some(SystemClauseType::RestoreCutPolicy),
+ ("$set_cp", 1) => Some(SystemClauseType::SetCutPoint(temp_v!(1))),
("$get_arg", 3) => Some(SystemClauseType::GetArg),
- ("$inference_level", 2) => Some(SystemClauseType::InferenceLevel(temp_v!(0), temp_v!(0))),
+ ("$inference_level", 2) => Some(SystemClauseType::InferenceLevel),
("$clean_up_block", 1) => Some(SystemClauseType::CleanUpBlock),
("$erase_ball", 0) => Some(SystemClauseType::EraseBall),
("$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))),
+ ("$get_cp", 1) => Some(SystemClauseType::GetCutPoint),
("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock),
("$reset_block", 1) => Some(SystemClauseType::ResetBlock),
("$set_ball", 1) => Some(SystemClauseType::SetBall),
#[derive(Copy, Clone, PartialEq)]
pub enum BuiltInClauseType {
- AcyclicTerm,
+ AcyclicTerm,
Compare,
CompareTerm(CompareTermQT),
CyclicTerm,
}
#[derive(Clone)]
-pub enum ClauseType {
+pub enum ClauseType {
BuiltIn(BuiltInClauseType),
CallN,
- Inlined(InlinedClauseType),
+ Inlined(InlinedClauseType),
Op(ClauseName, Fixity, CodeIndex),
Named(ClauseName, CodeIndex),
System(SystemClauseType)
pub fn name(&self) -> ClauseName {
match self {
- &BuiltInClauseType::AcyclicTerm => clause_name!("acyclic_term"),
+ &BuiltInClauseType::AcyclicTerm => clause_name!("acyclic_term"),
&BuiltInClauseType::Compare => clause_name!("compare"),
&BuiltInClauseType::CompareTerm(qt) => clause_name!(qt.name()),
&BuiltInClauseType::CyclicTerm => clause_name!("cyclic_term"),
&BuiltInClauseType::Ground => clause_name!("ground"),
&BuiltInClauseType::Is => clause_name!("is"),
&BuiltInClauseType::KeySort => clause_name!("keysort"),
- &BuiltInClauseType::NotEq => clause_name!("\\=="),
- &BuiltInClauseType::Sort => clause_name!("sort"),
+ &BuiltInClauseType::NotEq => clause_name!("\\=="),
+ &BuiltInClauseType::Sort => clause_name!("sort"),
}
- }
+ }
pub fn arity(&self) -> usize {
match self {
- &BuiltInClauseType::AcyclicTerm => 1,
+ &BuiltInClauseType::AcyclicTerm => 1,
&BuiltInClauseType::Compare => 2,
&BuiltInClauseType::CompareTerm(_) => 2,
&BuiltInClauseType::CyclicTerm => 1,
&BuiltInClauseType::Sort => 2,
}
}
-
+
pub fn from(name: &str, arity: usize) -> Option<Self> {
match (name, arity) {
("acyclic_term", 1) => Some(BuiltInClauseType::AcyclicTerm),
pub fn name(&self) -> ClauseName {
match self {
- &ClauseType::CallN => clause_name!("call"),
+ &ClauseType::CallN => clause_name!("call"),
&ClauseType::BuiltIn(built_in) => built_in.name(),
&ClauseType::Inlined(ref inlined) => clause_name!(inlined.name()),
&ClauseType::Op(ref name, ..) => name.clone(),
// call and cut policy exempt instructions.
#[derive(Clone)]
pub enum PEInstruction {
- InstallCleaner,
- InstallInferenceCounter(RegType, RegType, RegType),
- RemoveCallPolicyCheck,
- RemoveInferenceCounter(RegType, RegType),
- RestoreCutPolicy,
- SetCutPoint(RegType),
}
#[derive(Clone)]
CallClause(ClauseType, usize, usize, bool), // name, arity, perm_vars after threshold, last call.
CheckCpExecute,
Deallocate,
- GetCleanerCall,
+ 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
#[derive(Clone)]
pub enum Line {
Arithmetic(ArithmeticInstruction),
- PolicyExempt(PEInstruction),
Choice(ChoiceInstruction),
Control(ControlInstruction),
Cut(CutInstruction),
#[derive(Clone, PartialEq)]
pub enum CodePtr {
BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call.
+ CallN(usize, LocalCodePtr), // arity, local.
Local(LocalCodePtr)
}
pub fn local(&self) -> LocalCodePtr {
match self {
&CodePtr::BuiltInClause(_, ref local)
+ | &CodePtr::CallN(_, ref local)
| &CodePtr::Local(ref local) => local.clone()
}
}
pub fn assign_if_local(&mut self, cp: CodePtr) {
match cp {
- CodePtr::Local(local) => *self = local,
+ CodePtr::Local(local) => *self = local,
_ => {}
}
}
impl PartialOrd<CodePtr> for CodePtr {
fn partial_cmp(&self, other: &CodePtr) -> Option<Ordering> {
match (self, other) {
- (&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => l1.partial_cmp(l2),
+ (&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => l1.partial_cmp(l2),
_ => Some(Ordering::Greater)
}
}
fn add(self, rhs: usize) -> Self::Output {
match self {
- LocalCodePtr::DirEntry(p, name) => LocalCodePtr::DirEntry(p + rhs, name),
+ LocalCodePtr::DirEntry(p, name) => LocalCodePtr::DirEntry(p + rhs, name),
LocalCodePtr::TopLevel(cn, p) => LocalCodePtr::TopLevel(cn, p + rhs)
}
}
fn add(self, rhs: usize) -> Self::Output {
match self {
CodePtr::Local(local) => CodePtr::Local(local + rhs),
- CodePtr::BuiltInClause(_, local) => CodePtr::Local(local + rhs),
+ CodePtr::CallN(_, local) | CodePtr::BuiltInClause(_, local) =>
+ CodePtr::Local(local + rhs),
}
}
}
op_dir.insert((clause_name!(":-"), Fixity::In), (XFX, 1200, module_name.clone()));
op_dir.insert((clause_name!(":-"), Fixity::Pre), (FX, 1200, module_name.clone()));
op_dir.insert((clause_name!("?-"), Fixity::Pre), (FX, 1200, module_name.clone()));
- // op_dir.insert((clause_name!("/"), Fixity::In), (YFX, 400, module_name.clone()));
+ op_dir.insert((clause_name!("/"), Fixity::In), (YFX, 400, module_name.clone()));
/*
// control operators.
}
}
-impl fmt::Display for PEInstruction {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- &PEInstruction::InstallInferenceCounter(r1, r2, r3) =>
- write!(f, "install_inference_counter {}, {}, {}", r1, r2, r3),
- &PEInstruction::InstallCleaner =>
- write!(f, "install_cleaner"),
- &PEInstruction::RemoveCallPolicyCheck =>
- write!(f, "remove_call_policy_check"),
- &PEInstruction::RemoveInferenceCounter(r1, r2) =>
- write!(f, "remove_inference_counter {}, {}", r1, r2),
- &PEInstruction::RestoreCutPolicy =>
- write!(f, "restore_cut_point"),
- &PEInstruction::SetCutPoint(r) =>
- write!(f, "set_cp {}", r),
- }
- }
-}
-
impl fmt::Display for ChoiceInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
for fact_instr in fact {
println!("{}", fact_instr);
},
- &Line::PolicyExempt(ref instr) =>
- println!("{}", instr),
&Line::Cut(ref cut) =>
println!("{}", cut),
&Line::Choice(ref choice) =>
decl_info.label_clauses(wam.code_size(), &mut wam.code_dir, &mut code);
+ print_code(&code);
+
if !code.is_empty() {
wam.add_user_code(name, tl.arity(), code, tl.as_predicate().ok().unwrap())
} else {
:- module(builtins, [(=)/2, (+)/2, (*)/2, (-)/2, (/)/2, (/\)/2,
(\/)/2, (is)/2, (xor)/2, (div)/2, (//)/2, (rdiv)/2, (<<)/2,
- (>>)/2, (mod)/2, (rem)/2, (>)/2, (<)/2, (=\=)/2, (=:=)/2, (-)/1,
- (>=)/2, (=<)/2, (->)/2, (;)/2, catch/3, throw/1, true/0, false/0]).
+ (>>)/2, (mod)/2, (rem)/2, (>)/2, (<)/2, (=\=)/2, (=:=)/2,
+ (-)/1, (>=)/2, (=<)/2, (->)/2, (;)/2, (==)/2, catch/3,
+ throw/1, true/0, false/0]).
% arithmetic operators.
:- op(700, xfx, is).
:- op(700, xfx, >=).
:- op(700, xfx, =<).
+% unify.
+:- op(700, xfx, =).
+
% conditional operators.
:- op(1050, xfy, ->).
:- op(1100, xfy, ;).
-% unify.
-:- op(700, xfx, =).
+% term comparison.
+:- op(700, xfx, ==).
% unify.
X = X.
false :- '$fail'.
-% conditions.
-/*
-','(G1, G2) :- get_cp(B), ','(G1, G2, B).
+% control operators.
+
+','(G1, G2) :- '$get_cp'(B), ','(G1, G2, B).
-','(!, ','(G1, G2), B) :- set_cp(B), ','(G1, G2, B).
-','(!, !, B) :- set_cp(B).
-','(!, G, B) :- set_cp(B), G.
+','(!, ','(G1, G2), B) :- '$set_cp'(B), ','(G1, G2, B).
+','(!, !, B) :- '$set_cp'(B).
+','(!, G, B) :- '$set_cp'(B), G.
','(G, ','(G2, G3), B) :- !, G, ','(G2, G3, B).
-','(G, !, B) :- !, G, set_cp(B).
+','(G, !, B) :- !, G, '$set_cp'(B).
','(G1, G2, _) :- G1, G2.
-;(G1, G2) :- get_cp(B), ;(G1, G2, B).
+;(G1, G2) :- '$get_cp'(B), ;(G1, G2, B).
-;(G1 -> G2, _, B) :- ->(G1, G2, B).
-;(_ -> _ , G, B) :- set_cp(B), G.
-;(!, _, B) :- set_cp(B).
-;(_, !, B) :- set_cp(B).
+;(G1, G4, B) :- compound(G1), G1 = ->(G2, G3), (G2 -> G3 ; '$set_cp'(B), G4).
+;(G1, G2, B) :- G1 == !, '$set_cp'(B), call(G2).
+;(G1, G2, B) :- G2 == !, call(G2), '$set_cp'(B).
;(G, _, _) :- G.
;(_, G, _) :- G.
-G1 -> G2 :- get_cp(B), ->(G1, G2, B).
+G1 -> G2 :- '$get_cp'(B), ->(G1, G2, B).
+
+->(G1, G2, B) :- G2 == !, call(G1), !, '$set_cp'(B).
+->(G1, G2, B) :- call(G1), '$set_cp'(B), call(G2).
-->(G1, !, B) :- call(G1), set_cp(B).
-->(G1, G2, B) :- call(G1), set_cp(B), call(G2).
-*/
+% exception handling.
-% exceptions.
catch(G,C,R) :- '$get_current_block'(Bb), catch(G,C,R,Bb).
catch(G,C,R,Bb) :- '$install_new_block'(NBb), call(G), end_block(Bb, NBb).
let n = machine_st.or_stack[b].num_args();
for i in 1 .. n + 1 {
+ let addr = machine_st.store(machine_st.deref(machine_st.or_stack[b][i].clone()));
machine_st.registers[i] = machine_st.or_stack[b][i].clone();
}
}
}
- fn call_n<'a>(&mut self, machine_st: &mut MachineState, mut arity: usize,
+ fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize,
code_dirs: CodeDirs<'a>, lco: bool)
-> CallResult
{
- while let Some((name, inner_arity)) = machine_st.setup_call_n(arity) {
+ if let Some((name, arity)) = machine_st.setup_call_n(arity) {
let user = clause_name!("user");
- match ClauseType::from(name.clone(), inner_arity, None) {
+ match ClauseType::from(name.clone(), arity, None) {
ClauseType::CallN => {
- machine_st.handle_internal_call_n(inner_arity);
+ machine_st.handle_internal_call_n(arity);
if machine_st.fail {
return Ok(());
}
- arity = inner_arity;
- continue;
+ machine_st.p = CodePtr::CallN(arity, machine_st.p.local());
},
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)?;
+ if let Some(idx) = code_dirs.get(name.clone(), arity, user) {
+ self.context_call(machine_st, name, arity, idx, lco)?;
} else {
- return Err(machine_st.existence_error(name, inner_arity));
+ return Err(machine_st.existence_error(name, arity));
},
ClauseType::System(ct) =>
return Err(machine_st.type_error(ValidType::Callable,
Addr::Con(Constant::Atom(name))))
};
-
- break;
}
Ok(())
machine_st.fail = true;
return;
}
-
- machine_st.p += 1;
}
}
return;
}
- machine_st.p += 1;
-
if !self.out_of_cont_pts() {
machine_st.cp.assign_if_local(machine_st.p.clone());
machine_st.num_of_args = 0;
use prolog::and_stack::*;
use prolog::ast::*;
-use prolog::builtins::*;
use prolog::copier::*;
use prolog::heap_iter::*;
use prolog::heap_print::*;
&ArithmeticInstruction::Xor(ref a1, ref a2, t) => {
let n1 = try_or_fail!(self, self.get_number(a1));
let n2 = try_or_fail!(self, self.get_number(a2));
-
+
self.interms[t - 1] = Number::Integer(try_or_fail!(self, self.xor(n1, n2)));
self.p += 1;
},
self.registers[arg] = self.heap[h].as_addr(h);
}
},
- &QueryInstruction::PutValue(norm, arg) =>
- self.registers[arg] = self[norm].clone(),
+ &QueryInstruction::PutValue(norm, arg) => {
+ let addr = self.store(self.deref(self[norm].clone()));
+ self.registers[arg] = self[norm].clone();
+ },
&QueryInstruction::PutVariable(norm, arg) => {
match norm {
RegType::Perm(n) => {
}
}
- pub(super)
- fn execute_pe_instr<'a>(&mut self, code_dirs: CodeDirs<'a>, call_policy: &mut Box<CallPolicy>,
- cut_policy: &mut Box<CutPolicy>, instr: &PEInstruction)
- {
- match instr {
- &PEInstruction::InstallCleaner => {
- let addr = self[temp_v!(1)].clone();
- let b = self.b;
- let block = self.block;
-
- if cut_policy.downcast_ref::<SetupCallCleanupCutPolicy>().is_err() {
- *cut_policy = Box::new(SetupCallCleanupCutPolicy::new());
- }
-
- match cut_policy.downcast_mut::<SetupCallCleanupCutPolicy>().ok()
- {
- Some(cut_policy) => cut_policy.push_cont_pt(addr, b, block),
- None => panic!("install_cleaner: should have installed \\
- SetupCallCleanupCutPolicy.")
- };
-
- self.p += 1;
- },
- &PEInstruction::InstallInferenceCounter(r1, r2, r3) => { // A1 = B, A2 = L
- let a1 = self.store(self.deref(self[r1].clone()));
- let a2 = self.store(self.deref(self[r2].clone()));
-
- if call_policy.downcast_ref::<CallWithInferenceLimitCallPolicy>().is_err() {
- CallWithInferenceLimitCallPolicy::new_in_place(call_policy);
- }
-
- self.p += 1;
-
- match (a1, a2.clone()) {
- (Addr::Con(Constant::Usize(bp)),
- Addr::Con(Constant::Number(Number::Integer(n)))) =>
- match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
- Some(call_policy) => {
- let count = call_policy.add_limit(n, bp);
- self[r3] = Addr::Con(Constant::Number(Number::Integer(count)));
- },
- None => panic!("install_inference_counter: should have installed \\
- CallWithInferenceLimitCallPolicy.")
- },
- _ => {
- let stub = self.functor_stub(clause_name!("call_with_inference_limit"), 3);
- let type_error = self.error_form(self.type_error(ValidType::Integer, a2),
- stub);
- self.throw_exception(type_error)
- }
- };
- },
- &PEInstruction::RemoveCallPolicyCheck => {
- let restore_default =
- match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
- Some(call_policy) => {
- let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
-
- if let Addr::Con(Constant::Usize(bp)) = a1 {
- if call_policy.is_empty() && bp == self.b {
- Some(call_policy.into_inner())
- } else {
- None
- }
- } else {
- panic!("remove_call_policy_check: expected Usize in A1.");
- }
- },
- None => panic!("remove_call_policy_check: requires \\
- CallWithInferenceLimitCallPolicy.")
- };
-
- if let Some(new_policy) = restore_default {
- *call_policy = new_policy;
- }
-
- self.p += 1;
- },
- &PEInstruction::RemoveInferenceCounter(r1, r2) => { // A1 = B
- match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
- Some(call_policy) => {
- let a1 = self.store(self.deref(self[r1].clone()));
-
- if let Addr::Con(Constant::Usize(bp)) = a1 {
- let count = call_policy.remove_limit(bp);
- self[r2] = Addr::Con(Constant::Number(Number::Integer(count)));
- } else {
- panic!("remove_inference_counter: expected Usize in A1.");
- }
- },
- None => panic!("remove_inference_counters: requires \\
- CallWithInferenceLimitCallPolicy.")
- };
-
- self.p += 1;
- },
- &PEInstruction::RestoreCutPolicy => {
- let restore_default =
- if let Ok(cut_policy) = cut_policy.downcast_ref::<SetupCallCleanupCutPolicy>() {
- cut_policy.out_of_cont_pts()
- } else {
- false
- };
-
- if restore_default {
- *cut_policy = Box::new(DefaultCutPolicy {});
- }
-
- self.p += 1;
- },
- &PEInstruction::SetCutPoint(r) =>
- cut_policy.cut(self, r),
- };
- }
-
pub(super) fn try_functor(&mut self) -> Result<(), MachineError> {
let stub = self.functor_stub(clause_name!("functor"), 3);
let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
}
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.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));
+ try_or_fail!(self, self.system_call(ct, call_policy, cut_policy));
if lco {
self.p = CodePtr::Local(self.cp.clone());
self[r] = Addr::Con(Constant::Usize(b0));
self.p += 1;
},
- &CutInstruction::Cut(r) =>
- cut_policy.cut(self, r),
+ &CutInstruction::Cut(r) => {
+ cut_policy.cut(self, r);
+ self.p += 1;
+ }
}
}
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))
}
}
match instr {
Line::Arithmetic(ref arith_instr) =>
self.ms.execute_arith_instr(arith_instr),
- Line::PolicyExempt(ref built_in_instr) => {
- let code_dirs = CodeDirs::new(&self.code_dir, &self.modules);
- self.ms.execute_pe_instr(code_dirs, &mut self.call_policy,
- &mut self.cut_policy, built_in_instr);
- },
Line::Choice(ref choice_instr) =>
self.ms.execute_choice_instr(choice_instr, &mut self.call_policy),
Line::Cut(ref cut_instr) =>
use prolog::machine::machine_state::*;
use prolog::num::{ToPrimitive, Zero};
use prolog::num::bigint::BigInt;
-use prolog::tabled_rc::*;
use std::rc::Rc;
Ok(())
}
- pub(super) fn system_call(&mut self, ct: &SystemClauseType) -> CallResult
+ pub(super) fn system_call(&mut self, ct: &SystemClauseType, call_policy: &mut Box<CallPolicy>,
+ cut_policy: &mut Box<CutPolicy>,)
+ -> CallResult
{
match ct {
+ &SystemClauseType::InstallCleaner => {
+ let addr = self[temp_v!(1)].clone();
+ let b = self.b;
+ let block = self.block;
+
+ if cut_policy.downcast_ref::<SetupCallCleanupCutPolicy>().is_err() {
+ *cut_policy = Box::new(SetupCallCleanupCutPolicy::new());
+ }
+
+ match cut_policy.downcast_mut::<SetupCallCleanupCutPolicy>().ok()
+ {
+ Some(cut_policy) => cut_policy.push_cont_pt(addr, b, block),
+ None => panic!("install_cleaner: should have installed \\
+ SetupCallCleanupCutPolicy.")
+ };
+ },
+ &SystemClauseType::InstallInferenceCounter => { // A1 = B, A2 = L
+ let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
+ let a2 = self.store(self.deref(self[temp_v!(2)].clone()));
+
+ if call_policy.downcast_ref::<CallWithInferenceLimitCallPolicy>().is_err() {
+ CallWithInferenceLimitCallPolicy::new_in_place(call_policy);
+ }
+
+ match (a1, a2.clone()) {
+ (Addr::Con(Constant::Usize(bp)),
+ Addr::Con(Constant::Number(Number::Integer(n)))) =>
+ match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
+ Some(call_policy) => {
+ let count = call_policy.add_limit(n, bp);
+ self[temp_v!(3)] = Addr::Con(Constant::Number(Number::Integer(count)));
+ },
+ None => panic!("install_inference_counter: should have installed \\
+ CallWithInferenceLimitCallPolicy.")
+ },
+ _ => {
+ let stub = self.functor_stub(clause_name!("call_with_inference_limit"), 3);
+ let type_error = self.error_form(self.type_error(ValidType::Integer, a2),
+ stub);
+ self.throw_exception(type_error)
+ }
+ };
+ },
+ &SystemClauseType::RemoveCallPolicyCheck => {
+ let restore_default =
+ match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
+ Some(call_policy) => {
+ let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
+
+ if let Addr::Con(Constant::Usize(bp)) = a1 {
+ if call_policy.is_empty() && bp == self.b {
+ Some(call_policy.into_inner())
+ } else {
+ None
+ }
+ } else {
+ panic!("remove_call_policy_check: expected Usize in A1.");
+ }
+ },
+ None => panic!("remove_call_policy_check: requires \\
+ CallWithInferenceLimitCallPolicy.")
+ };
+
+ if let Some(new_policy) = restore_default {
+ *call_policy = new_policy;
+ }
+ },
+ &SystemClauseType::RemoveInferenceCounter => {
+ match call_policy.downcast_mut::<CallWithInferenceLimitCallPolicy>().ok() {
+ Some(call_policy) => {
+ let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
+
+ if let Addr::Con(Constant::Usize(bp)) = a1 {
+ let count = call_policy.remove_limit(bp);
+ self[temp_v!(2)] = Addr::Con(Constant::Number(Number::Integer(count)));
+ } else {
+ panic!("remove_inference_counter: expected Usize in A1.");
+ }
+ },
+ None => panic!("remove_inference_counters: requires \\
+ CallWithInferenceLimitCallPolicy.")
+ };
+ },
+ &SystemClauseType::RestoreCutPolicy => {
+ let restore_default =
+ if let Ok(cut_policy) = cut_policy.downcast_ref::<SetupCallCleanupCutPolicy>() {
+ cut_policy.out_of_cont_pts()
+ } else {
+ false
+ };
+
+ if restore_default {
+ *cut_policy = Box::new(DefaultCutPolicy {});
+ }
+ },
+ &SystemClauseType::SetCutPoint(r) =>
+ cut_policy.cut(self, r),
&SystemClauseType::GetArg =>
- self.try_get_arg(),
- &SystemClauseType::InferenceLevel(r1, r2) => {
- let a1 = self[r1].clone();
- let a2 = self.store(self.deref(self[r2].clone()));
+ return self.try_get_arg(),
+ &SystemClauseType::InferenceLevel => {
+ let a1 = self[temp_v!(1)].clone();
+ let a2 = self.store(self.deref(self[temp_v!(2)].clone()));
match a2 {
Addr::Con(Constant::Usize(bp)) =>
},
_ => self.fail = true
};
-
- Ok(())
},
&SystemClauseType::CleanUpBlock => {
let nb = self.store(self.deref(self[temp_v!(1)].clone()));
},
_ => self.fail = true
};
-
- Ok(())
- },
- &SystemClauseType::EraseBall => {
- self.ball.reset();
- Ok(())
- },
- &SystemClauseType::Fail => {
- self.fail = true;
- Ok(())
},
+ &SystemClauseType::EraseBall => self.ball.reset(),
+ &SystemClauseType::Fail => self.fail = true,
&SystemClauseType::GetBall => {
let addr = self.store(self.deref(self[temp_v!(1)].clone()));
let h = self.heap.h;
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::GetCutPoint => {
+ let a1 = self[temp_v!(1)].clone();
+ let a2 = Addr::Con(Constant::Usize(self.b));
+
+ self.unify(a1, a2);
},
&SystemClauseType::InstallNewBlock => {
self.block = self.b;
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(())
- }
- }
+ &SystemClauseType::SetBall => self.set_ball(),
+ &SystemClauseType::SkipMaxList => return self.skip_max_list(),
+ &SystemClauseType::Succeed => {},
+ &SystemClauseType::UnwindStack => self.unwind_stack()
+ };
+
+ Ok(())
}
}
macro_rules! set_cp {
($r:expr) => (
- Line::PolicyExempt(PEInstruction::SetCutPoint($r))
+ call_clause!(ClauseType::System(SystemClauseType::SetCutPoint($r)), 1, 0)
)
}
Term::Var(_, ref v) if v.as_str() == "!" =>
Ok(QueryTerm::UnblockedCut(Cell::default())),
Term::Clause(r, name, mut terms, fixity) =>
- if name.as_str() == ";" {
- if terms.len() == 2 {
- let term = Term::Clause(r, name.clone(), terms, fixity);
- let (stub, clauses) = self.fabricate_disjunct(term);
-
- self.queue.push_back(clauses);
- Ok(QueryTerm::Jump(stub))
- } else {
- Err(ParserError::BuiltInArityMismatch(";"))
- }
+ if name.as_str() == ";" && terms.len() == 2 {
+ let term = Term::Clause(r, name.clone(), terms, fixity);
+ let (stub, clauses) = self.fabricate_disjunct(term);
+
+ self.queue.push_back(clauses);
+ Ok(QueryTerm::Jump(stub))
} else if name.as_str() == "->" && terms.len() == 2 {
- if terms.len() == 2 {
- let conq = *terms.pop().unwrap();
- let prec = *terms.pop().unwrap();
- let (stub, clauses) = self.fabricate_if_then(prec, conq);
-
- self.queue.push_back(clauses);
- Ok(QueryTerm::Jump(stub))
- } else {
- Err(ParserError::BuiltInArityMismatch("->"))
- }
+ let conq = *terms.pop().unwrap();
+ let prec = *terms.pop().unwrap();
+
+ let (stub, clauses) = self.fabricate_if_then(prec, conq);
+
+ self.queue.push_back(clauses);
+ Ok(QueryTerm::Jump(stub))
} else {
Ok(QueryTerm::Clause(Cell::default(),
ClauseType::from(name, terms.len(), fixity),
[["Xs = non_list", "N = 0"]]);
}
-/*
#[test]
fn test_queries_on_conditionals()
{
let mut wam = Machine::new();
-
- submit(&mut wam, "test(A) :- ( A =:= 2 ->
- display(\"A is 2\")
- ; A =:= 3 ->
- display(\"A is 3\")
+ load_init_str_and_include(&mut wam, BUILTINS, "builtins");
+
+ submit(&mut wam, "test(A) :- ( A =:= 2 -> display(\"A is 2\")
+ ; A =:= 3 -> display(\"A is 3\")
; A = \"not 2 or 3\"
).");
[["X = a"], ["X = b"]]);
}
+/*
#[test]
fn test_queries_on_builtins()
{