introduce bind_fn, use in applicable Fact/Query instructions (#841)
This commit is contained in:
@@ -304,6 +304,7 @@ pub(crate) struct MachineState {
|
||||
pub(crate) global_clock: usize,
|
||||
pub(crate) dynamic_mode: FirstOrNext,
|
||||
pub(crate) unify_fn: fn(&mut MachineState, Addr, Addr),
|
||||
pub(crate) bind_fn: fn(&mut MachineState, Ref, Addr),
|
||||
}
|
||||
|
||||
impl fmt::Debug for MachineState {
|
||||
@@ -343,6 +344,14 @@ impl fmt::Debug for MachineState {
|
||||
} else {
|
||||
&"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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ impl MachineState {
|
||||
global_clock: 0,
|
||||
dynamic_mode: FirstOrNext::First,
|
||||
unify_fn: MachineState::unify,
|
||||
bind_fn: MachineState::bind,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +155,25 @@ impl MachineState {
|
||||
}
|
||||
|
||||
#[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 {
|
||||
// local variable optimization -- r cannot occur in the
|
||||
// data structure bound to addr, so don't bother
|
||||
@@ -871,7 +890,7 @@ impl MachineState {
|
||||
}
|
||||
Addr::Lis(l) => {
|
||||
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) => {
|
||||
if let Constant::String(ref s2) = c {
|
||||
@@ -889,7 +908,7 @@ impl MachineState {
|
||||
if let Some(r) = addr.as_var() {
|
||||
self.bind(r, c);
|
||||
} else {
|
||||
(self.unify_fn)(self, addr, c);
|
||||
self.unify(addr, c);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1222,8 +1241,7 @@ impl MachineState {
|
||||
let h = self.heap.h();
|
||||
|
||||
self.heap.push(HeapCellValue::Addr(Addr::Str(h + 1)));
|
||||
self.heap
|
||||
.push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec()));
|
||||
self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec()));
|
||||
|
||||
self.bind(addr.as_var().unwrap(), Addr::HeapCell(h));
|
||||
|
||||
@@ -1283,22 +1301,20 @@ impl MachineState {
|
||||
self.increment_s_ptr(1);
|
||||
}
|
||||
MachineMode::Write => {
|
||||
let addr = self.deref(self[reg]);
|
||||
let addr = self.store(self.deref(self[reg]));
|
||||
let h = self.heap.h();
|
||||
|
||||
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.increment_s_ptr(1);
|
||||
self.heap.push(val);
|
||||
self.increment_s_ptr(1);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -1611,7 +1627,7 @@ impl MachineState {
|
||||
}
|
||||
|
||||
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) => {
|
||||
let h = self.heap.h();
|
||||
@@ -2466,7 +2482,7 @@ impl MachineState {
|
||||
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 {
|
||||
|
||||
@@ -253,11 +253,11 @@ impl MachineState {
|
||||
|
||||
fn finalize_skip_max_list(&mut self, n: usize, addr: Addr) {
|
||||
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 {
|
||||
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 xs = self[temp_v!(4)];
|
||||
|
||||
(self.unify_fn)(self, xs0, xs);
|
||||
self.unify(xs0, xs);
|
||||
} else {
|
||||
self.skip_max_list_result(max_steps_n);
|
||||
}
|
||||
@@ -323,7 +323,7 @@ impl MachineState {
|
||||
let xs0 = self[temp_v!(3)];
|
||||
let xs = self[temp_v!(4)];
|
||||
|
||||
(self.unify_fn)(self, xs0, xs);
|
||||
self.unify(xs0, xs);
|
||||
} else {
|
||||
self.skip_max_list_result(max_steps_n);
|
||||
}
|
||||
@@ -5456,12 +5456,15 @@ impl MachineState {
|
||||
}
|
||||
&SystemClauseType::SetSTOAsUnify => {
|
||||
self.unify_fn = MachineState::unify_with_occurs_check;
|
||||
self.bind_fn = MachineState::bind_with_occurs_check_wrapper;
|
||||
}
|
||||
&SystemClauseType::SetNSTOAsUnify => {
|
||||
self.unify_fn = MachineState::unify;
|
||||
self.bind_fn = MachineState::bind;
|
||||
}
|
||||
&SystemClauseType::SetSTOWithErrorAsUnify => {
|
||||
self.unify_fn = MachineState::unify_with_occurs_check_with_error;
|
||||
self.bind_fn = MachineState::bind_with_occurs_check_with_error_wrapper;
|
||||
}
|
||||
&SystemClauseType::HomeDirectory => {
|
||||
let path = match dirs_next::home_dir() {
|
||||
|
||||
Reference in New Issue
Block a user