fix function_casts_as_integer warning
Comparing addresses of function pointers is brittle. Functions may be duplicated resulting in function pointers to the same function to compare !=. Functions may be merged/de-duplicated resulting in function pointers to different function to compare ==. The later shouldn't be relevant here as the function differ in behavior, but mentioning it for completeness.
This commit is contained in:
@@ -1104,7 +1104,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
push_cell!(self, heap_loc_as_cell!(h), return);
|
push_cell!(self, heap_loc_as_cell!(h), return);
|
||||||
(self.bind_fn)(self, Ref::heap_cell(h), value);
|
self.occurs_check.bind(self, Ref::heap_cell(h), value);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1152,7 +1152,7 @@ impl MachineState {
|
|||||||
push_cell!(self, heap_loc_as_cell!(h), return);
|
push_cell!(self, heap_loc_as_cell!(h), return);
|
||||||
|
|
||||||
let addr = self.store(self[r]);
|
let addr = self.store(self[r]);
|
||||||
(self.bind_fn)(self, Ref::heap_cell(h), addr);
|
self.occurs_check.bind(self, Ref::heap_cell(h), addr);
|
||||||
|
|
||||||
// the former code of this match arm was:
|
// the former code of this match arm was:
|
||||||
|
|
||||||
@@ -1235,7 +1235,7 @@ impl MachineState {
|
|||||||
let h = self.heap.cell_len();
|
let h = self.heap.cell_len();
|
||||||
push_cell!(self, heap_loc_as_cell!(h), return);
|
push_cell!(self, heap_loc_as_cell!(h), return);
|
||||||
|
|
||||||
(self.bind_fn)(self, Ref::heap_cell(h), addr);
|
self.occurs_check.bind(self, Ref::heap_cell(h), addr);
|
||||||
self.registers[arg] = heap_loc_as_cell!(h);
|
self.registers[arg] = heap_loc_as_cell!(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1281,7 +1281,7 @@ impl MachineState {
|
|||||||
if stored_v.is_stack_var() {
|
if stored_v.is_stack_var() {
|
||||||
let h = self.heap.cell_len();
|
let h = self.heap.cell_len();
|
||||||
push_cell!(self, heap_loc_as_cell!(h), return);
|
push_cell!(self, heap_loc_as_cell!(h), return);
|
||||||
(self.bind_fn)(self, Ref::heap_cell(h), stored_v);
|
self.occurs_check.bind(self, Ref::heap_cell(h), stored_v);
|
||||||
} else {
|
} else {
|
||||||
push_cell!(self, stored_v, return);
|
push_cell!(self, stored_v, return);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,62 @@ pub enum OnEOF {
|
|||||||
Return,
|
Return,
|
||||||
Continue,
|
Continue,
|
||||||
}
|
}
|
||||||
|
pub(crate) trait OccursCheckImpl {
|
||||||
|
fn flag_value(&self) -> Atom;
|
||||||
|
fn unify(&self, state: &mut MachineState);
|
||||||
|
fn bind(&self, state: &mut MachineState, r: Ref, h: HeapCellValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Not subject to occurs-check
|
||||||
|
pub(crate) struct Nsto;
|
||||||
|
|
||||||
|
impl OccursCheckImpl for Nsto {
|
||||||
|
fn flag_value(&self) -> Atom {
|
||||||
|
atom!("false")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unify(&self, state: &mut MachineState) {
|
||||||
|
state.unify();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bind(&self, state: &mut MachineState, r: Ref, h: HeapCellValue) {
|
||||||
|
state.bind(r, h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Subject to occurs-check
|
||||||
|
pub(crate) struct Sto;
|
||||||
|
|
||||||
|
impl OccursCheckImpl for Sto {
|
||||||
|
fn flag_value(&self) -> Atom {
|
||||||
|
atom!("true")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unify(&self, state: &mut MachineState) {
|
||||||
|
state.unify_with_occurs_check();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bind(&self, state: &mut MachineState, r: Ref, h: HeapCellValue) {
|
||||||
|
state.bind_with_occurs_check_wrapper(r, h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Subject to occurs-check -> error
|
||||||
|
pub(crate) struct StoError;
|
||||||
|
|
||||||
|
impl OccursCheckImpl for StoError {
|
||||||
|
fn flag_value(&self) -> Atom {
|
||||||
|
atom!("error")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unify(&self, state: &mut MachineState) {
|
||||||
|
state.unify_with_occurs_check_with_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bind(&self, state: &mut MachineState, r: Ref, h: HeapCellValue) {
|
||||||
|
state.bind_with_occurs_check_with_error_wrapper(r, h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct MachineState {
|
pub struct MachineState {
|
||||||
pub atom_tbl: Arc<AtomTable>,
|
pub atom_tbl: Arc<AtomTable>,
|
||||||
@@ -93,8 +149,7 @@ pub struct MachineState {
|
|||||||
pub(crate) cc: usize,
|
pub(crate) cc: usize,
|
||||||
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),
|
pub(crate) occurs_check: &'static dyn OccursCheckImpl,
|
||||||
pub(crate) bind_fn: fn(&mut MachineState, Ref, HeapCellValue),
|
|
||||||
pub(crate) run_cleaners_fn: fn(&mut Machine) -> bool,
|
pub(crate) run_cleaners_fn: fn(&mut Machine) -> bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,28 +183,8 @@ impl fmt::Debug for MachineState {
|
|||||||
.field("cc", &self.cc)
|
.field("cc", &self.cc)
|
||||||
.field("global_clock", &self.global_clock)
|
.field("global_clock", &self.global_clock)
|
||||||
.field("dynamic_mode", &self.dynamic_mode)
|
.field("dynamic_mode", &self.dynamic_mode)
|
||||||
.field(
|
.field("unify_fn", &&*self.occurs_check.flag_value().as_str())
|
||||||
"unify_fn",
|
.field("bind_fn", &&*self.occurs_check.flag_value().as_str())
|
||||||
if self.unify_fn as usize == MachineState::unify as usize {
|
|
||||||
&"MachineState::unify"
|
|
||||||
} else if self.unify_fn as usize == MachineState::unify_with_occurs_check as usize {
|
|
||||||
&"MachineState::unify_with_occurs_check"
|
|
||||||
} 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()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,8 +64,7 @@ impl MachineState {
|
|||||||
cc: 0,
|
cc: 0,
|
||||||
global_clock: 0,
|
global_clock: 0,
|
||||||
dynamic_mode: FirstOrNext::First,
|
dynamic_mode: FirstOrNext::First,
|
||||||
unify_fn: MachineState::unify,
|
occurs_check: &Nsto,
|
||||||
bind_fn: MachineState::bind,
|
|
||||||
run_cleaners_fn: |_| false,
|
run_cleaners_fn: |_| false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -951,7 +950,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
(self.bind_fn)(self, r, f_a);
|
self.occurs_check.bind(self, r, f_a);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,13 +5,42 @@ use crate::machine::machine_errors::CycleSearchResult;
|
|||||||
use crate::machine::system_calls::BrentAlgState;
|
use crate::machine::system_calls::BrentAlgState;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
|
trait StepperImpl {
|
||||||
|
fn step<'a>(&self, iter: &mut HeapPStrIter<'a>) -> Option<PStrIteratee>;
|
||||||
|
fn is_cyclic(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PreCycleDiscoverStepper;
|
||||||
|
|
||||||
|
impl StepperImpl for PreCycleDiscoverStepper {
|
||||||
|
fn step<'a>(&self, iter: &mut HeapPStrIter<'a>) -> Option<PStrIteratee> {
|
||||||
|
iter.pre_cycle_discovery_stepper()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_cyclic(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PostCycleDiscoverStepper;
|
||||||
|
|
||||||
|
impl StepperImpl for PostCycleDiscoverStepper {
|
||||||
|
fn step<'a>(&self, iter: &mut HeapPStrIter<'a>) -> Option<PStrIteratee> {
|
||||||
|
iter.post_cycle_discovery_stepper()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_cyclic(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct HeapPStrIter<'a> {
|
pub struct HeapPStrIter<'a> {
|
||||||
pub heap: &'a Heap,
|
pub heap: &'a Heap,
|
||||||
// pub focus: HeapCellValue,
|
// pub focus: HeapCellValue,
|
||||||
orig_focus: usize,
|
orig_focus: usize,
|
||||||
brent_st: BrentAlgState,
|
brent_st: BrentAlgState,
|
||||||
stepper: fn(&mut HeapPStrIter<'a>) -> Option<PStrIteratee>,
|
stepper: &'static dyn StepperImpl,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PStrIterStep {
|
struct PStrIterStep {
|
||||||
@@ -33,7 +62,7 @@ impl<'a> HeapPStrIter<'a> {
|
|||||||
heap,
|
heap,
|
||||||
orig_focus,
|
orig_focus,
|
||||||
brent_st: BrentAlgState::new(orig_focus),
|
brent_st: BrentAlgState::new(orig_focus),
|
||||||
stepper: HeapPStrIter::pre_cycle_discovery_stepper,
|
stepper: &PreCycleDiscoverStepper,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +190,7 @@ impl<'a> HeapPStrIter<'a> {
|
|||||||
debug_assert!(matches!(cycle_result, CycleSearchResult::Cyclic { .. }));
|
debug_assert!(matches!(cycle_result, CycleSearchResult::Cyclic { .. }));
|
||||||
|
|
||||||
self.walk_hare_to_cycle_end();
|
self.walk_hare_to_cycle_end();
|
||||||
self.stepper = HeapPStrIter::post_cycle_discovery_stepper;
|
self.stepper = &PostCycleDiscoverStepper;
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// self.focus = self.heap[next_hare];
|
// self.focus = self.heap[next_hare];
|
||||||
@@ -194,7 +223,7 @@ impl<'a> HeapPStrIter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_cyclic(&self) -> bool {
|
pub(crate) fn is_cyclic(&self) -> bool {
|
||||||
self.stepper as usize == Self::post_cycle_discovery_stepper as usize
|
self.stepper.is_cyclic()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +232,7 @@ impl<'a> Iterator for HeapPStrIter<'a> {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
(self.stepper)(self)
|
self.stepper.step(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9213,36 +9213,25 @@ impl Machine {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn is_sto_enabled(&mut self) {
|
pub(crate) fn is_sto_enabled(&mut self) {
|
||||||
if self.machine_st.unify_fn as usize == MachineState::unify_with_occurs_check as usize {
|
self.machine_st.unify_atom(
|
||||||
self.machine_st
|
self.machine_st.occurs_check.flag_value(),
|
||||||
.unify_atom(atom!("true"), self.machine_st.registers[1]);
|
self.machine_st.registers[1],
|
||||||
} else if self.machine_st.unify_fn as usize
|
);
|
||||||
== MachineState::unify_with_occurs_check_with_error as usize
|
|
||||||
{
|
|
||||||
self.machine_st
|
|
||||||
.unify_atom(atom!("error"), self.machine_st.registers[1]);
|
|
||||||
} else {
|
|
||||||
self.machine_st
|
|
||||||
.unify_atom(atom!("false"), self.machine_st.registers[1]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn set_sto_as_unify(&mut self) {
|
pub(crate) fn set_sto_as_unify(&mut self) {
|
||||||
self.machine_st.unify_fn = MachineState::unify_with_occurs_check;
|
self.machine_st.occurs_check = &Sto;
|
||||||
self.machine_st.bind_fn = MachineState::bind_with_occurs_check_wrapper;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn set_nsto_as_unify(&mut self) {
|
pub(crate) fn set_nsto_as_unify(&mut self) {
|
||||||
self.machine_st.unify_fn = MachineState::unify;
|
self.machine_st.occurs_check = &Nsto;
|
||||||
self.machine_st.bind_fn = MachineState::bind;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn set_sto_with_error_as_unify(&mut self) {
|
pub(crate) fn set_sto_with_error_as_unify(&mut self) {
|
||||||
self.machine_st.unify_fn = MachineState::unify_with_occurs_check_with_error;
|
self.machine_st.occurs_check = &StoError;
|
||||||
self.machine_st.bind_fn = MachineState::bind_with_occurs_check_with_error_wrapper;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|||||||
@@ -415,7 +415,7 @@ macro_rules! unify {
|
|||||||
macro_rules! unify_fn {
|
macro_rules! unify_fn {
|
||||||
($machine_st:expr, $($value:expr),*) => {{
|
($machine_st:expr, $($value:expr),*) => {{
|
||||||
$($machine_st.pdl.push($value);)*
|
$($machine_st.pdl.push($value);)*
|
||||||
($machine_st.unify_fn)(&mut $machine_st)
|
$machine_st.occurs_check.unify(&mut $machine_st)
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user