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) 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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
Reference in New Issue
Block a user