introduce bind_fn, use in applicable Fact/Query instructions (#841)

This commit is contained in:
Mark Thom
2021-02-28 16:19:06 -07:00
parent 08e2b601f1
commit 3f1cfd2995
3 changed files with 48 additions and 20 deletions

View File

@@ -304,6 +304,7 @@ pub(crate) struct MachineState {
pub(crate) global_clock: usize, pub(crate) global_clock: usize,
pub(crate) dynamic_mode: FirstOrNext, pub(crate) dynamic_mode: FirstOrNext,
pub(crate) unify_fn: fn(&mut MachineState, Addr, Addr), pub(crate) unify_fn: fn(&mut MachineState, Addr, Addr),
pub(crate) bind_fn: fn(&mut MachineState, Ref, Addr),
} }
impl fmt::Debug for MachineState { impl fmt::Debug for MachineState {
@@ -343,6 +344,14 @@ impl fmt::Debug for MachineState {
} else { } else {
&"MachineState::unify_with_occurs_check_with_error" &"MachineState::unify_with_occurs_check_with_error"
}) })
.field("bind_fn",
if self.bind_fn as usize == MachineState::bind as usize {
&"MachineState::bind"
} else if self.bind_fn as usize == MachineState::bind_with_occurs_check_wrapper as usize {
&"MachineState::bind_with_occurs_check"
} else {
&"MachineState::bind_with_occurs_check_with_error_wrapper"
})
.finish() .finish()
} }
} }

View File

@@ -57,6 +57,7 @@ impl MachineState {
global_clock: 0, global_clock: 0,
dynamic_mode: FirstOrNext::First, dynamic_mode: FirstOrNext::First,
unify_fn: MachineState::unify, unify_fn: MachineState::unify,
bind_fn: MachineState::bind,
} }
} }
@@ -154,7 +155,25 @@ impl MachineState {
} }
#[inline] #[inline]
fn bind_with_occurs_check(&mut self, r: Ref, addr: Addr) -> bool { pub(super) fn bind_with_occurs_check_with_error_wrapper(&mut self, r: Ref, addr: Addr) {
if self.bind_with_occurs_check(r, addr) {
let err = self.representation_error(
RepFlag::Term,
clause_name!("unify_with_occurs_check"),
2,
);
self.throw_exception(err);
}
}
#[inline]
pub(super) fn bind_with_occurs_check_wrapper(&mut self, r: Ref, addr: Addr) {
self.bind_with_occurs_check(r, addr);
}
#[inline]
pub(super) fn bind_with_occurs_check(&mut self, r: Ref, addr: Addr) -> bool {
if let Ref::StackCell(..) = r { if let Ref::StackCell(..) = r {
// local variable optimization -- r cannot occur in the // local variable optimization -- r cannot occur in the
// data structure bound to addr, so don't bother // data structure bound to addr, so don't bother
@@ -871,7 +890,7 @@ impl MachineState {
} }
Addr::Lis(l) => { Addr::Lis(l) => {
let addr = self.heap.put_constant(c.clone()); let addr = self.heap.put_constant(c.clone());
(self.unify_fn)(self, Addr::Lis(l), addr); self.unify(Addr::Lis(l), addr);
} }
Addr::PStrLocation(h, n) => { Addr::PStrLocation(h, n) => {
if let Constant::String(ref s2) = c { if let Constant::String(ref s2) = c {
@@ -889,7 +908,7 @@ impl MachineState {
if let Some(r) = addr.as_var() { if let Some(r) = addr.as_var() {
self.bind(r, c); self.bind(r, c);
} else { } else {
(self.unify_fn)(self, addr, c); self.unify(addr, c);
} }
} }
}; };
@@ -1222,8 +1241,7 @@ impl MachineState {
let h = self.heap.h(); let h = self.heap.h();
self.heap.push(HeapCellValue::Addr(Addr::Str(h + 1))); self.heap.push(HeapCellValue::Addr(Addr::Str(h + 1)));
self.heap self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec()));
.push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec()));
self.bind(addr.as_var().unwrap(), Addr::HeapCell(h)); self.bind(addr.as_var().unwrap(), Addr::HeapCell(h));
@@ -1283,22 +1301,20 @@ impl MachineState {
self.increment_s_ptr(1); self.increment_s_ptr(1);
} }
MachineMode::Write => { MachineMode::Write => {
let addr = self.deref(self[reg]); let addr = self.store(self.deref(self[reg]));
let h = self.heap.h(); let h = self.heap.h();
if let Addr::HeapCell(hc) = addr { if let Addr::HeapCell(hc) = addr {
if hc < h { let val = self.heap.clone(hc);
let val = self.heap.clone(hc);
self.heap.push(val); self.heap.push(val);
self.increment_s_ptr(1); self.increment_s_ptr(1);
return; return;
}
} }
self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
self.bind(Ref::HeapCell(h), addr); (self.bind_fn)(self, Ref::HeapCell(h), addr);
} }
}; };
} }
@@ -1569,7 +1585,7 @@ impl MachineState {
let h = self.heap.h(); let h = self.heap.h();
self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
self.bind(Ref::HeapCell(h), addr); (self.bind_fn)(self, Ref::HeapCell(h), addr);
self.registers[arg] = self.heap[h].as_addr(h); self.registers[arg] = self.heap[h].as_addr(h);
} }
@@ -1611,7 +1627,7 @@ impl MachineState {
} }
self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
self.bind(Ref::HeapCell(h), addr); (self.bind_fn)(self, Ref::HeapCell(h), addr);
} }
&QueryInstruction::SetVariable(reg) => { &QueryInstruction::SetVariable(reg) => {
let h = self.heap.h(); let h = self.heap.h();
@@ -2466,7 +2482,7 @@ impl MachineState {
self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h + i))); self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h + i)));
} }
self.bind(r, f_a); (self.bind_fn)(self, r, f_a);
} }
pub(super) fn try_functor(&mut self, op_dir: &OpDir) -> CallResult { pub(super) fn try_functor(&mut self, op_dir: &OpDir) -> CallResult {

View File

@@ -253,11 +253,11 @@ impl MachineState {
fn finalize_skip_max_list(&mut self, n: usize, addr: Addr) { fn finalize_skip_max_list(&mut self, n: usize, addr: Addr) {
let target_n = self[temp_v!(1)]; let target_n = self[temp_v!(1)];
(self.unify_fn)(self, Addr::Usize(n), target_n); self.unify(Addr::Usize(n), target_n);
if !self.fail { if !self.fail {
let xs = self[temp_v!(4)]; let xs = self[temp_v!(4)];
(self.unify_fn)(self, addr, xs); self.unify(addr, xs);
} }
} }
@@ -313,7 +313,7 @@ impl MachineState {
let xs0 = self[temp_v!(3)]; let xs0 = self[temp_v!(3)];
let xs = self[temp_v!(4)]; let xs = self[temp_v!(4)];
(self.unify_fn)(self, xs0, xs); self.unify(xs0, xs);
} else { } else {
self.skip_max_list_result(max_steps_n); self.skip_max_list_result(max_steps_n);
} }
@@ -323,7 +323,7 @@ impl MachineState {
let xs0 = self[temp_v!(3)]; let xs0 = self[temp_v!(3)];
let xs = self[temp_v!(4)]; let xs = self[temp_v!(4)];
(self.unify_fn)(self, xs0, xs); self.unify(xs0, xs);
} else { } else {
self.skip_max_list_result(max_steps_n); self.skip_max_list_result(max_steps_n);
} }
@@ -5456,12 +5456,15 @@ impl MachineState {
} }
&SystemClauseType::SetSTOAsUnify => { &SystemClauseType::SetSTOAsUnify => {
self.unify_fn = MachineState::unify_with_occurs_check; self.unify_fn = MachineState::unify_with_occurs_check;
self.bind_fn = MachineState::bind_with_occurs_check_wrapper;
} }
&SystemClauseType::SetNSTOAsUnify => { &SystemClauseType::SetNSTOAsUnify => {
self.unify_fn = MachineState::unify; self.unify_fn = MachineState::unify;
self.bind_fn = MachineState::bind;
} }
&SystemClauseType::SetSTOWithErrorAsUnify => { &SystemClauseType::SetSTOWithErrorAsUnify => {
self.unify_fn = MachineState::unify_with_occurs_check_with_error; self.unify_fn = MachineState::unify_with_occurs_check_with_error;
self.bind_fn = MachineState::bind_with_occurs_check_with_error_wrapper;
} }
&SystemClauseType::HomeDirectory => { &SystemClauseType::HomeDirectory => {
let path = match dirs_next::home_dir() { let path = match dirs_next::home_dir() {