eliminate need for embedded, handwritten WAM code.
This commit is contained in:
@@ -209,7 +209,7 @@ pub struct MachineState {
|
||||
pub(super) b0: usize,
|
||||
pub(super) e: usize,
|
||||
pub(super) num_of_args: usize,
|
||||
pub(super) cp: CodePtr,
|
||||
pub(super) cp: LocalCodePtr,
|
||||
pub(super) fail: bool,
|
||||
pub(crate) heap: Heap,
|
||||
pub(super) mode: MachineMode,
|
||||
@@ -248,10 +248,10 @@ pub(crate) trait CallPolicy: Any {
|
||||
IndexPtr::Index(compiled_tl_index) => {
|
||||
let module_name = idx.0.borrow().1.clone();
|
||||
|
||||
machine_st.cp = machine_st.p.clone() + 1;
|
||||
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 = CodePtr::DirEntry(compiled_tl_index, module_name);
|
||||
machine_st.p = dir_entry!(compiled_tl_index, module_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,7 +270,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
|
||||
machine_st.num_of_args = arity;
|
||||
machine_st.b0 = machine_st.b;
|
||||
machine_st.p = CodePtr::DirEntry(compiled_tl_index, module_name);
|
||||
machine_st.p = dir_entry!(compiled_tl_index, module_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,55 +400,66 @@ pub(crate) trait CallPolicy: Any {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn try_call_clause<'a>(&mut self, machine_st: &mut MachineState, code_dirs: CodeDirs<'a>,
|
||||
ct: &ClauseType, arity: usize, lco: bool)
|
||||
-> CallResult
|
||||
fn call_n<'a>(&mut self, machine_st: &mut MachineState, arity: usize,
|
||||
code_dirs: CodeDirs<'a>, lco: bool)
|
||||
-> CallResult
|
||||
{
|
||||
loop {
|
||||
if let Some((name, mut arity)) = machine_st.setup_call_n(arity) {
|
||||
let user = clause_name!("user");
|
||||
|
||||
if machine_st.fail {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
match ClauseType::from(name.clone(), arity, None) {
|
||||
ClauseType::CallN => {
|
||||
machine_st.num_of_args = arity;
|
||||
machine_st.handle_internal_call_n();
|
||||
|
||||
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(), arity, user) {
|
||||
self.context_call(machine_st, name, arity, idx, lco)?;
|
||||
} else {
|
||||
return Err(machine_st.existence_error(name, arity));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn system_call(&mut self, machine_st: &mut MachineState, ct: &SystemClauseType) -> CallResult
|
||||
{
|
||||
match ct {
|
||||
&ClauseType::AcyclicTerm => {
|
||||
&SystemClauseType::SkipMaxList => {
|
||||
machine_st.skip_max_list()?;
|
||||
machine_st.p += 1;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType, lco: bool)
|
||||
-> CallResult
|
||||
{
|
||||
match ct {
|
||||
&BuiltInClauseType::AcyclicTerm => {
|
||||
let addr = machine_st[temp_v!(1)].clone();
|
||||
machine_st.fail = machine_st.is_cyclic_term(addr);
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
&ClauseType::Arg => {
|
||||
if !lco {
|
||||
machine_st.cp = machine_st.p.clone() + 1;
|
||||
}
|
||||
|
||||
machine_st.num_of_args = 3;
|
||||
machine_st.b0 = machine_st.b;
|
||||
machine_st.p = CodePtr::DirEntry(166, clause_name!("builtin"));
|
||||
|
||||
Ok(())
|
||||
},
|
||||
&ClauseType::Catch => {
|
||||
if !lco {
|
||||
machine_st.cp = machine_st.p.clone() + 1;
|
||||
}
|
||||
|
||||
machine_st.num_of_args = 3;
|
||||
machine_st.b0 = machine_st.b;
|
||||
machine_st.p = CodePtr::DirEntry(5, clause_name!("builtin"));
|
||||
|
||||
Ok(())
|
||||
},
|
||||
&ClauseType::CallN =>
|
||||
if let Some((name, arity)) = machine_st.setup_call_n(arity) {
|
||||
let user = clause_name!("user");
|
||||
|
||||
match ClauseType::from(name.clone(), arity, None) {
|
||||
ClauseType::Op(..) | ClauseType::Named(..) =>
|
||||
if let Some(idx) = code_dirs.get(name.clone(), arity, user) {
|
||||
self.context_call(machine_st, name, arity, idx, lco)
|
||||
} else {
|
||||
Err(machine_st.existence_error(name, arity))
|
||||
},
|
||||
ct => self.try_call_clause(machine_st, code_dirs, &ct, arity, lco),
|
||||
}
|
||||
} else {
|
||||
Ok(())
|
||||
},
|
||||
&ClauseType::Compare => {
|
||||
&BuiltInClauseType::Compare => {
|
||||
let a1 = machine_st[temp_v!(1)].clone();
|
||||
let a2 = machine_st[temp_v!(2)].clone();
|
||||
let a3 = machine_st[temp_v!(3)].clone();
|
||||
@@ -462,7 +473,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
machine_st.unify(a1, c);
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
&ClauseType::CompareTerm(qt) => {
|
||||
&BuiltInClauseType::CompareTerm(qt) => {
|
||||
match qt {
|
||||
CompareTermQT::Equal =>
|
||||
machine_st.fail = machine_st.structural_eq_test(),
|
||||
@@ -473,12 +484,12 @@ pub(crate) trait CallPolicy: Any {
|
||||
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
&ClauseType::CyclicTerm => {
|
||||
&BuiltInClauseType::CyclicTerm => {
|
||||
let addr = machine_st[temp_v!(1)].clone();
|
||||
machine_st.fail = !machine_st.is_cyclic_term(addr);
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
&ClauseType::Display => {
|
||||
&BuiltInClauseType::Display => {
|
||||
let output = machine_st.print_term(machine_st[temp_v!(1)].clone(),
|
||||
DisplayFormatter {},
|
||||
PrinterOutputter::new());
|
||||
@@ -486,27 +497,27 @@ pub(crate) trait CallPolicy: Any {
|
||||
println!("{}", output.result());
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
&ClauseType::DuplicateTerm => {
|
||||
&BuiltInClauseType::DuplicateTerm => {
|
||||
machine_st.duplicate_term();
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
&ClauseType::Eq => {
|
||||
&BuiltInClauseType::Eq => {
|
||||
machine_st.fail = machine_st.eq_test();
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
&ClauseType::Ground => {
|
||||
&BuiltInClauseType::Ground => {
|
||||
machine_st.fail = machine_st.ground_test();
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
&ClauseType::Functor => {
|
||||
&BuiltInClauseType::Functor => {
|
||||
machine_st.try_functor()?;
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
&ClauseType::NotEq => {
|
||||
&BuiltInClauseType::NotEq => {
|
||||
machine_st.fail = !machine_st.eq_test();
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
&ClauseType::Sort => {
|
||||
&BuiltInClauseType::Sort => {
|
||||
machine_st.check_sort_errors()?;
|
||||
|
||||
let stub = machine_st.functor_stub(clause_name!("sort"), 2);
|
||||
@@ -522,7 +533,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
&ClauseType::KeySort => {
|
||||
&BuiltInClauseType::KeySort => {
|
||||
machine_st.check_keysort_errors()?;
|
||||
|
||||
let stub = machine_st.functor_stub(clause_name!("keysort"), 2);
|
||||
@@ -544,25 +555,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
&ClauseType::Throw => {
|
||||
if !lco {
|
||||
machine_st.cp = machine_st.p.clone() + 1;
|
||||
}
|
||||
|
||||
machine_st.goto_throw();
|
||||
Ok(())
|
||||
},
|
||||
&ClauseType::Named(ref name, ref idx) | &ClauseType::Op(ref name, _, ref idx) =>
|
||||
self.context_call(machine_st, name.clone(), arity, idx.clone(), lco),
|
||||
&ClauseType::CallWithInferenceLimit => {
|
||||
machine_st.goto_ptr(CodePtr::DirEntry(409, clause_name!("builtin")), 3, lco);
|
||||
Ok(())
|
||||
},
|
||||
&ClauseType::SetupCallCleanup => {
|
||||
machine_st.goto_ptr(CodePtr::DirEntry(310, clause_name!("builtin")), 3, lco);
|
||||
Ok(())
|
||||
},
|
||||
&ClauseType::Is => {
|
||||
&BuiltInClauseType::Is => {
|
||||
let a = machine_st[temp_v!(1)].clone();
|
||||
let result = machine_st.arith_eval_by_metacall(temp_v!(2))?;
|
||||
|
||||
@@ -571,14 +564,8 @@ pub(crate) trait CallPolicy: Any {
|
||||
|
||||
Ok(())
|
||||
},
|
||||
&ClauseType::Inlined(ref inlined) => {
|
||||
machine_st.execute_inlined(inlined, &vec![temp_v!(1), temp_v!(2)]);
|
||||
Ok(())
|
||||
},
|
||||
&ClauseType::System(ref system) => {
|
||||
machine_st.execute_system(system)?;
|
||||
return_from_clause!(lco, machine_st)
|
||||
}
|
||||
&BuiltInClauseType::System(ref ct) =>
|
||||
self.system_call(machine_st, ct),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -680,11 +667,10 @@ impl CallPolicy for CallWithInferenceLimitCallPolicy {
|
||||
self.increment()
|
||||
}
|
||||
|
||||
fn try_call_clause<'a>(&mut self, machine_st: &mut MachineState, code_dirs: CodeDirs<'a>,
|
||||
ct: &ClauseType, arity: usize, lco: bool)
|
||||
-> CallResult
|
||||
fn call_builtin<'a>(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType, lco: bool)
|
||||
-> CallResult
|
||||
{
|
||||
self.prev_policy.try_call_clause(machine_st, code_dirs, ct, arity, lco)?;
|
||||
self.prev_policy.call_builtin(machine_st, ct, lco)?;
|
||||
self.increment()
|
||||
}
|
||||
}
|
||||
@@ -757,11 +743,11 @@ impl CutPolicy for SetupCallCleanupCutPolicy {
|
||||
machine_st.p += 1;
|
||||
|
||||
if !self.out_of_cont_pts() {
|
||||
machine_st.cp = machine_st.p.clone();
|
||||
machine_st.cp.assign_if_local(machine_st.p.clone());
|
||||
machine_st.num_of_args = 0;
|
||||
machine_st.b0 = machine_st.b;
|
||||
// goto_call run_cleaners_without_handling/0, 370.
|
||||
machine_st.p = CodePtr::DirEntry(370, clause_name!("builtin"));
|
||||
machine_st.p = dir_entry!(370, clause_name!("builtin"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ impl MachineState {
|
||||
b0: 0,
|
||||
e: 0,
|
||||
num_of_args: 0,
|
||||
cp: CodePtr::default(),
|
||||
cp: LocalCodePtr::default(),
|
||||
fail: false,
|
||||
heap: Heap::with_capacity(256),
|
||||
mode: MachineMode::Write,
|
||||
@@ -670,7 +670,7 @@ impl MachineState {
|
||||
&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;
|
||||
},
|
||||
@@ -1011,8 +1011,7 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_internal_call_n<'a>(&mut self, call_policy: &mut Box<CallPolicy>,
|
||||
code_dirs: CodeDirs<'a>)
|
||||
pub(super) fn handle_internal_call_n(&mut self)
|
||||
{
|
||||
let arity = self.num_of_args + 1;
|
||||
let pred = self.registers[1].clone();
|
||||
@@ -1023,32 +1022,20 @@ impl MachineState {
|
||||
|
||||
if arity > 1 {
|
||||
self.registers[arity - 1] = pred;
|
||||
|
||||
if let Some((name, arity)) = self.setup_call_n(arity - 1) {
|
||||
if let Some(idx) = code_dirs.get(name.clone(), arity, self.p.module_name()) {
|
||||
try_or_fail!(self, call_policy.try_execute(self, name, arity, idx));
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
self.fail = true;
|
||||
}
|
||||
|
||||
pub(super) fn goto_throw(&mut self) {
|
||||
self.num_of_args = 1;
|
||||
self.b0 = self.b;
|
||||
self.p = CodePtr::DirEntry(59, clause_name!("builtin"));
|
||||
}
|
||||
|
||||
pub(super) fn set_ball(&mut self) {
|
||||
let addr = self[temp_v!(1)].clone();
|
||||
self.ball.boundary = self.heap.h;
|
||||
|
||||
|
||||
let mut duplicator = DuplicateBallTerm::new(self);
|
||||
duplicator.duplicate_term(addr);
|
||||
duplicator.duplicate_term(addr);
|
||||
}
|
||||
|
||||
|
||||
pub(super) fn unwind_stack(&mut self) {
|
||||
self.b = self.block;
|
||||
self.or_stack.truncate(self.b);
|
||||
@@ -1071,7 +1058,6 @@ impl MachineState {
|
||||
self.error_form(self.representation_error(RepFlag::MaxArity), stub);
|
||||
|
||||
self.throw_exception(representation_error);
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -1334,20 +1320,15 @@ impl MachineState {
|
||||
};
|
||||
}
|
||||
|
||||
pub(super) fn execute_inlined(&mut self, inlined: &InlinedClauseType, rs: &Vec<RegType>)
|
||||
{
|
||||
let r1 = rs[0].clone();
|
||||
|
||||
pub(super) fn execute_inlined(&mut self, inlined: &InlinedClauseType) {
|
||||
match inlined {
|
||||
&InlinedClauseType::CompareNumber(cmp) => {
|
||||
let r2 = rs[1].clone();
|
||||
|
||||
&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));
|
||||
|
||||
self.compare_numbers(cmp, n1, n2);
|
||||
},
|
||||
&InlinedClauseType::IsAtom => {
|
||||
&InlinedClauseType::IsAtom(r1) => {
|
||||
let d = self.store(self.deref(self[r1].clone()));
|
||||
|
||||
match d {
|
||||
@@ -1355,7 +1336,7 @@ impl MachineState {
|
||||
_ => self.fail = true
|
||||
};
|
||||
},
|
||||
&InlinedClauseType::IsAtomic => {
|
||||
&InlinedClauseType::IsAtomic(r1) => {
|
||||
let d = self.store(self.deref(self[r1].clone()));
|
||||
|
||||
match d {
|
||||
@@ -1363,7 +1344,7 @@ impl MachineState {
|
||||
_ => self.fail = true
|
||||
};
|
||||
},
|
||||
&InlinedClauseType::IsInteger => {
|
||||
&InlinedClauseType::IsInteger(r1) => {
|
||||
let d = self.store(self.deref(self[r1].clone()));
|
||||
|
||||
match d {
|
||||
@@ -1371,7 +1352,7 @@ impl MachineState {
|
||||
_ => self.fail = true
|
||||
};
|
||||
},
|
||||
&InlinedClauseType::IsCompound => {
|
||||
&InlinedClauseType::IsCompound(r1) => {
|
||||
let d = self.store(self.deref(self[r1].clone()));
|
||||
|
||||
match d {
|
||||
@@ -1379,7 +1360,7 @@ impl MachineState {
|
||||
_ => self.fail = true
|
||||
};
|
||||
},
|
||||
&InlinedClauseType::IsFloat => {
|
||||
&InlinedClauseType::IsFloat(r1) => {
|
||||
let d = self.store(self.deref(self[r1].clone()));
|
||||
|
||||
match d {
|
||||
@@ -1387,7 +1368,7 @@ impl MachineState {
|
||||
_ => self.fail = true
|
||||
};
|
||||
},
|
||||
&InlinedClauseType::IsRational => {
|
||||
&InlinedClauseType::IsRational(r1) => {
|
||||
let d = self.store(self.deref(self[r1].clone()));
|
||||
|
||||
match d {
|
||||
@@ -1395,7 +1376,7 @@ impl MachineState {
|
||||
_ => self.fail = true
|
||||
};
|
||||
},
|
||||
&InlinedClauseType::IsString => {
|
||||
&InlinedClauseType::IsString(r1) => {
|
||||
let d = self.store(self.deref(self[r1].clone()));
|
||||
|
||||
match d {
|
||||
@@ -1403,7 +1384,7 @@ impl MachineState {
|
||||
_ => self.fail = true
|
||||
};
|
||||
},
|
||||
&InlinedClauseType::IsNonVar => {
|
||||
&InlinedClauseType::IsNonVar(r1) => {
|
||||
let d = self.store(self.deref(self[r1].clone()));
|
||||
|
||||
match d {
|
||||
@@ -1411,7 +1392,7 @@ impl MachineState {
|
||||
_ => self.p += 1
|
||||
};
|
||||
},
|
||||
&InlinedClauseType::IsVar => {
|
||||
&InlinedClauseType::IsVar(r1) => {
|
||||
let d = self.store(self.deref(self[r1].clone()));
|
||||
|
||||
match d {
|
||||
@@ -1428,8 +1409,6 @@ impl MachineState {
|
||||
instr: &BuiltInInstruction)
|
||||
{
|
||||
match instr {
|
||||
&BuiltInInstruction::CallInlined(ref inlined, ref rs) =>
|
||||
self.execute_inlined(inlined, rs),
|
||||
&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));
|
||||
@@ -1457,7 +1436,7 @@ impl MachineState {
|
||||
let val = self.try_get_arg();
|
||||
|
||||
if lco {
|
||||
self.p = self.cp.clone();
|
||||
self.p = CodePtr::Local(self.cp.clone());
|
||||
} else {
|
||||
self.p += 1;
|
||||
}
|
||||
@@ -1658,8 +1637,6 @@ impl MachineState {
|
||||
},
|
||||
&BuiltInInstruction::UnwindStack =>
|
||||
self.unwind_stack(),
|
||||
&BuiltInInstruction::InternalCallN =>
|
||||
self.handle_internal_call_n(call_policy, code_dirs),
|
||||
&BuiltInInstruction::Fail => {
|
||||
self.fail = true;
|
||||
self.p += 1;
|
||||
@@ -1946,66 +1923,86 @@ impl MachineState {
|
||||
false
|
||||
}
|
||||
|
||||
pub(super) fn setup_built_in_call(&mut self, ct: BuiltInClauseType, lco: bool)
|
||||
{
|
||||
self.num_of_args = ct.arity();
|
||||
self.b0 = self.b;
|
||||
|
||||
self.p = CodePtr::BuiltInClause(ct, self.p.local());
|
||||
}
|
||||
|
||||
pub(super) fn allocate(&mut self, num_cells: usize) {
|
||||
let gi = self.next_global_index();
|
||||
|
||||
self.p += 1;
|
||||
|
||||
if self.e + 1 < self.and_stack.len() {
|
||||
let and_gi = self.and_stack[self.e].global_index;
|
||||
let or_gi = self.or_stack.top()
|
||||
.map(|or_fr| or_fr.global_index)
|
||||
.unwrap_or(0);
|
||||
|
||||
if and_gi > or_gi {
|
||||
let index = self.e + 1;
|
||||
|
||||
self.and_stack[index].e = self.e;
|
||||
self.and_stack[index].cp = self.cp.clone();
|
||||
self.and_stack[index].global_index = gi;
|
||||
|
||||
self.and_stack.resize(index, num_cells);
|
||||
self.e = index;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.and_stack.push(gi, self.e, self.cp.clone(), num_cells);
|
||||
self.e = self.and_stack.len() - 1;
|
||||
}
|
||||
|
||||
fn deallocate(&mut self) {
|
||||
let e = self.e;
|
||||
|
||||
self.cp = self.and_stack[e].cp.clone();
|
||||
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>,
|
||||
instr: &ControlInstruction)
|
||||
{
|
||||
match instr {
|
||||
&ControlInstruction::Allocate(num_cells) => {
|
||||
let gi = self.next_global_index();
|
||||
|
||||
self.p += 1;
|
||||
|
||||
if self.e + 1 < self.and_stack.len() {
|
||||
let and_gi = self.and_stack[self.e].global_index;
|
||||
let or_gi = self.or_stack.top()
|
||||
.map(|or_fr| or_fr.global_index)
|
||||
.unwrap_or(0);
|
||||
|
||||
if and_gi > or_gi {
|
||||
let index = self.e + 1;
|
||||
|
||||
self.and_stack[index].e = self.e;
|
||||
self.and_stack[index].cp = self.cp.clone();
|
||||
self.and_stack[index].global_index = gi;
|
||||
|
||||
self.and_stack.resize(index, num_cells);
|
||||
|
||||
self.e = index;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.and_stack.push(gi, self.e, self.cp.clone(), num_cells);
|
||||
self.e = self.and_stack.len() - 1;
|
||||
},
|
||||
&ControlInstruction::CallClause(ref ct, arity, _, lco) =>
|
||||
try_or_fail!(self, call_policy.try_call_clause(self, code_dirs, ct, arity, lco)),
|
||||
&ControlInstruction::Allocate(num_cells) =>
|
||||
self.allocate(num_cells),
|
||||
&ControlInstruction::CallClause(ClauseType::CallN, arity, _, lco) =>
|
||||
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) =>
|
||||
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::CheckCpExecute => {
|
||||
let a = self.store(self.deref(self[temp_v!(2)].clone()));
|
||||
|
||||
match a {
|
||||
Addr::Con(Constant::Usize(old_b)) if self.b > old_b + 1 => {
|
||||
self.p = self.cp.clone();
|
||||
self.p = CodePtr::Local(self.cp.clone());
|
||||
},
|
||||
_ => {
|
||||
self.num_of_args = 2;
|
||||
self.b0 = self.b;
|
||||
// goto sgc_on_success/2, 382.
|
||||
self.p = CodePtr::DirEntry(382, clause_name!("builtin"));
|
||||
self.p = dir_entry!(382, clause_name!("builtin"));
|
||||
}
|
||||
};
|
||||
},
|
||||
&ControlInstruction::Deallocate => {
|
||||
let e = self.e;
|
||||
|
||||
self.cp = self.and_stack[e].cp.clone();
|
||||
self.e = self.and_stack[e].e;
|
||||
|
||||
self.p += 1;
|
||||
},
|
||||
&ControlInstruction::Deallocate => self.deallocate(),
|
||||
&ControlInstruction::GetCleanerCall => {
|
||||
let dest = self[temp_v!(1)].clone();
|
||||
|
||||
@@ -2032,7 +2029,7 @@ impl MachineState {
|
||||
self.fail = true;
|
||||
},
|
||||
&ControlInstruction::Goto(p, arity, lco) =>
|
||||
self.goto_ptr(CodePtr::DirEntry(p, clause_name!("builtin")), 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));
|
||||
@@ -2042,7 +2039,7 @@ impl MachineState {
|
||||
},
|
||||
&ControlInstruction::JmpBy(arity, offset, _, lco) => {
|
||||
if !lco {
|
||||
self.cp = self.p.clone() + 1;
|
||||
self.cp.assign_if_local(self.p.clone() + 1);
|
||||
}
|
||||
|
||||
self.num_of_args = arity;
|
||||
@@ -2050,13 +2047,13 @@ impl MachineState {
|
||||
self.p += offset;
|
||||
},
|
||||
&ControlInstruction::Proceed =>
|
||||
self.p = self.cp.clone(),
|
||||
self.p = CodePtr::Local(self.cp.clone())
|
||||
};
|
||||
}
|
||||
|
||||
pub(super) fn goto_ptr(&mut self, p: CodePtr, arity: usize, lco:bool) {
|
||||
if !lco {
|
||||
self.cp = self.p.clone() + 1;
|
||||
self.cp.assign_if_local(self.p.clone() + 1);
|
||||
}
|
||||
|
||||
self.num_of_args = arity;
|
||||
@@ -2169,7 +2166,7 @@ impl MachineState {
|
||||
self.s = 0;
|
||||
self.tr = 0;
|
||||
self.p = CodePtr::default();
|
||||
self.cp = CodePtr::default();
|
||||
self.cp = LocalCodePtr::default();
|
||||
self.num_of_args = 0;
|
||||
|
||||
self.fail = false;
|
||||
|
||||
@@ -34,18 +34,18 @@ pub struct Machine {
|
||||
cached_query: Option<Code>
|
||||
}
|
||||
|
||||
impl Index<CodePtr> for Machine {
|
||||
impl Index<LocalCodePtr> for Machine {
|
||||
type Output = Line;
|
||||
|
||||
fn index(&self, ptr: CodePtr) -> &Self::Output {
|
||||
fn index(&self, ptr: LocalCodePtr) -> &Self::Output {
|
||||
match ptr {
|
||||
CodePtr::TopLevel(_, p) => {
|
||||
LocalCodePtr::TopLevel(_, p) => {
|
||||
match &self.cached_query {
|
||||
&Some(ref cq) => &cq[p],
|
||||
&None => panic!("Out-of-bounds top level index.")
|
||||
}
|
||||
},
|
||||
CodePtr::DirEntry(p, _) => &self.code[p]
|
||||
LocalCodePtr::DirEntry(p, _) => &self.code[p]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -223,36 +223,47 @@ impl Machine {
|
||||
}
|
||||
}
|
||||
|
||||
fn lookup_instr(&self, p: CodePtr) -> Option<Line> {
|
||||
match p {
|
||||
CodePtr::Local(LocalCodePtr::TopLevel(_, p)) =>
|
||||
match &self.cached_query {
|
||||
&Some(ref cq) => Some(cq[p].clone()),
|
||||
&None => None
|
||||
},
|
||||
CodePtr::Local(LocalCodePtr::DirEntry(p, _)) =>
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
fn execute_instr(&mut self)
|
||||
{
|
||||
let instr = match self.ms.p {
|
||||
CodePtr::TopLevel(_, p) => {
|
||||
match &self.cached_query {
|
||||
&Some(ref cq) => &cq[p],
|
||||
&None => return
|
||||
}
|
||||
},
|
||||
CodePtr::DirEntry(p, _) => &self.code[p]
|
||||
let instr = match self.lookup_instr(self.ms.p.clone()) {
|
||||
Some(instr) => instr,
|
||||
None => return
|
||||
};
|
||||
|
||||
match instr {
|
||||
&Line::Arithmetic(ref arith_instr) =>
|
||||
Line::Arithmetic(ref arith_instr) =>
|
||||
self.ms.execute_arith_instr(arith_instr),
|
||||
&Line::BuiltIn(ref built_in_instr) => {
|
||||
Line::BuiltIn(ref built_in_instr) => {
|
||||
let code_dirs = CodeDirs::new(&self.code_dir, &self.modules);
|
||||
self.ms.execute_built_in_instr(code_dirs, &mut self.call_policy,
|
||||
&mut self.cut_policy, built_in_instr);
|
||||
},
|
||||
&Line::Choice(ref choice_instr) =>
|
||||
Line::Choice(ref choice_instr) =>
|
||||
self.ms.execute_choice_instr(choice_instr, &mut self.call_policy),
|
||||
&Line::Cut(ref cut_instr) =>
|
||||
Line::Cut(ref cut_instr) =>
|
||||
self.ms.execute_cut_instr(cut_instr, &mut self.cut_policy),
|
||||
&Line::Control(ref control_instr) => {
|
||||
Line::Control(ref control_instr) => {
|
||||
let code_dirs = CodeDirs::new(&self.code_dir, &self.modules);
|
||||
self.ms.execute_ctrl_instr(code_dirs, &mut self.call_policy,
|
||||
&mut self.cut_policy, control_instr)
|
||||
},
|
||||
&Line::Fact(ref fact) => {
|
||||
Line::Fact(ref fact) => {
|
||||
for fact_instr in fact {
|
||||
if self.failed() {
|
||||
break;
|
||||
@@ -263,11 +274,11 @@ impl Machine {
|
||||
|
||||
self.ms.p += 1;
|
||||
},
|
||||
&Line::Indexing(ref indexing_instr) =>
|
||||
Line::Indexing(ref indexing_instr) =>
|
||||
self.ms.execute_indexing_instr(&indexing_instr),
|
||||
&Line::IndexedChoice(ref choice_instr) =>
|
||||
Line::IndexedChoice(ref choice_instr) =>
|
||||
self.ms.execute_indexed_choice_instr(choice_instr, &mut self.call_policy),
|
||||
&Line::Query(ref query) => {
|
||||
Line::Query(ref query) => {
|
||||
for query_instr in query {
|
||||
if self.failed() {
|
||||
break;
|
||||
@@ -289,13 +300,13 @@ impl Machine {
|
||||
self.ms.b0 = self.ms.or_stack[b].b0;
|
||||
self.ms.p = self.ms.or_stack[b].bp.clone();
|
||||
|
||||
if let CodePtr::TopLevel(_, p) = self.ms.p {
|
||||
if let CodePtr::Local(LocalCodePtr::TopLevel(_, p)) = self.ms.p {
|
||||
self.ms.fail = p == 0;
|
||||
} else {
|
||||
self.ms.fail = false;
|
||||
}
|
||||
} else {
|
||||
self.ms.p = CodePtr::TopLevel(0, 0);
|
||||
self.ms.p = CodePtr::Local(LocalCodePtr::TopLevel(0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,8 +320,9 @@ impl Machine {
|
||||
}
|
||||
|
||||
match self.ms.p {
|
||||
CodePtr::DirEntry(p, _) if p < self.code.len() => {},
|
||||
_ => break
|
||||
CodePtr::Local(LocalCodePtr::DirEntry(p, _)) if p < self.code.len() => {},
|
||||
CodePtr::Local(_) => break,
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -342,11 +354,11 @@ impl Machine {
|
||||
|
||||
fn run_query(&mut self, alloc_locs: &AllocVarDict, heap_locs: &mut HeapVarDict)
|
||||
{
|
||||
let end_ptr = CodePtr::TopLevel(0, self.cached_query_size());
|
||||
let end_ptr = top_level_code_ptr!(0, self.cached_query_size());
|
||||
|
||||
while self.ms.p < end_ptr {
|
||||
if let CodePtr::TopLevel(mut cn, p) = self.ms.p {
|
||||
match &self[CodePtr::TopLevel(cn, p)] {
|
||||
if let CodePtr::Local(LocalCodePtr::TopLevel(mut cn, p)) = self.ms.p {
|
||||
match &self[LocalCodePtr::TopLevel(cn, p)] {
|
||||
&Line::Control(ref ctrl_instr) if ctrl_instr.is_jump_instr() => {
|
||||
self.record_var_places(cn, alloc_locs, heap_locs);
|
||||
cn += 1;
|
||||
@@ -354,13 +366,13 @@ impl Machine {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.ms.p = CodePtr::TopLevel(cn, p);
|
||||
self.ms.p = top_level_code_ptr!(cn, p);
|
||||
}
|
||||
|
||||
self.query_stepper();
|
||||
|
||||
match self.ms.p {
|
||||
CodePtr::TopLevel(_, p) if p > 0 => {},
|
||||
CodePtr::Local(LocalCodePtr::TopLevel(_, p)) if p > 0 => {},
|
||||
_ => {
|
||||
if heap_locs.is_empty() {
|
||||
self.record_var_places(0, alloc_locs, heap_locs);
|
||||
@@ -377,7 +389,7 @@ impl Machine {
|
||||
if self.ms.ball.stub.len() > 0 {
|
||||
let h = self.ms.heap.h;
|
||||
self.ms.copy_and_align_ball_to_heap();
|
||||
|
||||
|
||||
let error_str = self.ms.print_exception(Addr::HeapCell(h),
|
||||
&heap_locs,
|
||||
TermFormatter {},
|
||||
@@ -410,7 +422,7 @@ impl Machine {
|
||||
let b = self.ms.b - 1;
|
||||
self.ms.p = self.ms.or_stack[b].bp.clone();
|
||||
|
||||
if let CodePtr::TopLevel(_, 0) = self.ms.p {
|
||||
if let CodePtr::Local(LocalCodePtr::TopLevel(_, 0)) = self.ms.p {
|
||||
return EvalSession::from(SessionError::QueryFailure);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user