From d50d42509903dc3cc1841eb757a703753de84754 Mon Sep 17 00:00:00 2001 From: Skgland Date: Sun, 17 May 2026 19:45:55 +0200 Subject: [PATCH 1/2] ensure pdl is pushed/popped in pairs --- src/machine/machine_state.rs | 2 +- src/machine/unify.rs | 31 +++++++++++++------------------ src/macros.rs | 12 ++++++------ 3 files changed, 20 insertions(+), 25 deletions(-) diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 3744da34..860cfb79 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -115,7 +115,7 @@ impl OccursCheckImpl for StoError { pub struct MachineState { pub atom_tbl: Arc, pub arena: Arena, - pub(super) pdl: Vec, + pub(super) pdl: Vec<(HeapCellValue, HeapCellValue)>, pub(super) s: HeapPtr, pub(super) s_offset: usize, pub(super) p: usize, diff --git a/src/machine/unify.rs b/src/machine/unify.rs index e1f73eae..0957537c 100644 --- a/src/machine/unify.rs +++ b/src/machine/unify.rs @@ -17,11 +17,9 @@ impl MachineState { pub(crate) fn partial_string_to_pdl(&mut self, pstr_loc: usize, l: usize) { let (c, succ_cell) = self.heap.last_str_char_and_tail(pstr_loc); - self.pdl.push(heap_loc_as_cell!(l + 1)); - self.pdl.push(succ_cell); + self.pdl.push((heap_loc_as_cell!(l + 1), succ_cell)); - self.pdl.push(heap_loc_as_cell!(l)); - self.pdl.push(char_as_cell!(c)); + self.pdl.push((heap_loc_as_cell!(l), char_as_cell!(c))); } } @@ -37,8 +35,7 @@ pub(crate) trait Unifier: DerefMut { if n1 == n2 && a1 == a2 { for idx in (0..a1).rev() { - self.pdl.push(heap_loc_as_cell!(s2+1+idx)); - self.pdl.push(heap_loc_as_cell!(s1+1+idx)); + self.pdl.push((heap_loc_as_cell!(s2+1+idx), heap_loc_as_cell!(s1+1+idx))); } } else { self.fail = true; @@ -47,8 +44,7 @@ pub(crate) trait Unifier: DerefMut { (HeapCellValueTag::Lis, l2) => { if a1 == 2 && n1 == atom!(".") { for idx in (0..2).rev() { - self.pdl.push(heap_loc_as_cell!(l2+1+idx)); - self.pdl.push(heap_loc_as_cell!(s1+1+idx)); + self.pdl.push((heap_loc_as_cell!(l2+1+idx), heap_loc_as_cell!(s1+1+idx))); } } else { self.fail = true; @@ -76,8 +72,7 @@ pub(crate) trait Unifier: DerefMut { read_heap_cell!(value, (HeapCellValueTag::Lis, l2) => { for idx in (0..2).rev() { - self.pdl.push(heap_loc_as_cell!(l2 + idx)); - self.pdl.push(heap_loc_as_cell!(l1 + idx)); + self.pdl.push((heap_loc_as_cell!(l2 + idx), heap_loc_as_cell!(l1 + idx))); } } (HeapCellValueTag::Str, s2) => { @@ -86,8 +81,7 @@ pub(crate) trait Unifier: DerefMut { if a2 == 2 && n2 == atom!(".") { for idx in (0..2).rev() { - self.pdl.push(heap_loc_as_cell!(s2+1+idx)); - self.pdl.push(heap_loc_as_cell!(l1+idx)); + self.pdl.push((heap_loc_as_cell!(s2+1+idx), heap_loc_as_cell!(l1+idx))); } } else { self.fail = true; @@ -136,8 +130,7 @@ pub(crate) trait Unifier: DerefMut { (HeapCellValueTag::PStrLoc, other_pstr_loc) => { match machine_st.heap.compare_pstr_segments(pstr_loc, other_pstr_loc) { PStrSegmentCmpResult::Continue(v1, v2) => { - machine_st.pdl.push(v1.offset_by(pstr_loc)); - machine_st.pdl.push(v2.offset_by(other_pstr_loc)); + machine_st.pdl.push((v1.offset_by(pstr_loc), v2.offset_by(other_pstr_loc))); } _ => { machine_st.fail = true; @@ -357,11 +350,13 @@ pub(crate) trait Unifier: DerefMut { fn unify_internal(&mut self) { let mut tabu_list = IndexSet::with_hasher(FxBuildHasher::default()); - while !(self.pdl.is_empty() || self.fail) { - let s1 = self.pdl.pop().unwrap(); - let s1 = (self.deref() as &MachineState).deref(s1); + while let Some((s1, s2)) = self.pdl.pop() { + if self.fail { + // FIXME(msrv) FIXME(edition2024) use let chain to move this to check this in the while condition + break; + } - let s2 = self.pdl.pop().unwrap(); + let s1 = (self.deref() as &MachineState).deref(s1); let s2 = (self.deref() as &MachineState).deref(s2); if s1 != s2 { diff --git a/src/macros.rs b/src/macros.rs index 3d88e437..d99f58f7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -406,22 +406,22 @@ macro_rules! index_store { } macro_rules! unify { - ($machine_st:expr, $($value:expr),*) => {{ - $($machine_st.pdl.push($value);)* + ($machine_st:expr, $($v1:expr, $v2:expr),*) => {{ + $($machine_st.pdl.push(($v1, $v2));)* $machine_st.unify() }}; } macro_rules! unify_fn { - ($machine_st:expr, $($value:expr),*) => {{ - $($machine_st.pdl.push($value);)* + ($machine_st:expr, $($v1:expr, $v2: expr),*) => {{ + $($machine_st.pdl.push(($v1, $v2));)* $machine_st.occurs_check.unify(&mut $machine_st) }}; } macro_rules! unify_with_occurs_check { - ($machine_st:expr, $($value:expr),*) => {{ - $($machine_st.pdl.push($value);)* + ($machine_st:expr, $($v1:expr, $v2:expr),*) => {{ + $($machine_st.pdl.push(($v1, $v2));)* $machine_st.unify_with_occurs_check() }}; } From e4792429d3864eabd840f8cdb1f3723a56d27908 Mon Sep 17 00:00:00 2001 From: Skgland Date: Sun, 17 May 2026 20:50:37 +0200 Subject: [PATCH 2/2] reuse tabu list --- src/machine/machine_state.rs | 3 +++ src/machine/machine_state_impl.rs | 4 ++++ src/machine/unify.rs | 18 +++++++++--------- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 860cfb79..56795ce6 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -16,7 +16,9 @@ use crate::parser::ast::*; use crate::read::TermWriteResult; use crate::types::*; +use fxhash::FxBuildHasher; use indexmap::IndexMap; +use indexmap::IndexSet; use std::convert::TryFrom; use std::fmt; @@ -116,6 +118,7 @@ pub struct MachineState { pub atom_tbl: Arc, pub arena: Arena, pub(super) pdl: Vec<(HeapCellValue, HeapCellValue)>, + pub(super) unify_tabu_list: IndexSet<(HeapCellValue, HeapCellValue), FxBuildHasher>, pub(super) s: HeapPtr, pub(super) s_offset: usize, pub(super) p: usize, diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index 390ad99d..b9b5538f 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -1,3 +1,6 @@ +use fxhash::FxBuildHasher; +use indexmap::IndexSet; + use crate::arena::*; use crate::atom_table::*; use crate::forms::*; @@ -31,6 +34,7 @@ impl MachineState { arena: Arena::new().unwrap(), atom_tbl: AtomTable::new().unwrap(), pdl: Vec::with_capacity(1024), + unify_tabu_list: IndexSet::with_hasher(FxBuildHasher::default()), s: HeapPtr::default(), s_offset: 0, p: 0, diff --git a/src/machine/unify.rs b/src/machine/unify.rs index 0957537c..e7516929 100644 --- a/src/machine/unify.rs +++ b/src/machine/unify.rs @@ -9,8 +9,6 @@ use crate::types::*; use std::ops::{Deref, DerefMut}; use derive_more::*; -use fxhash::FxBuildHasher; -use indexmap::IndexSet; use num_order::NumOrd; impl MachineState { @@ -348,7 +346,7 @@ pub(crate) trait Unifier: DerefMut { } fn unify_internal(&mut self) { - let mut tabu_list = IndexSet::with_hasher(FxBuildHasher::default()); + debug_assert!(self.unify_tabu_list.is_empty()); while let Some((s1, s2)) = self.pdl.pop() { if self.fail { @@ -378,7 +376,7 @@ pub(crate) trait Unifier: DerefMut { Self::unify_atom(self, name, d2); } (HeapCellValueTag::Str, s1) => { - if tabu_list.contains(&(d1, d2)) { + if self.unify_tabu_list.contains(&(d1, d2)) { continue; } @@ -386,11 +384,11 @@ pub(crate) trait Unifier: DerefMut { if !self.fail { let d2 = self.store(d2); - tabu_list.insert((d1, d2)); + self.unify_tabu_list.insert((d1, d2)); } } (HeapCellValueTag::Lis, l1) => { - if d2.is_ref() && tabu_list.contains(&(d1, d2)) { + if d2.is_ref() && self.unify_tabu_list.contains(&(d1, d2)) { continue; } @@ -398,7 +396,7 @@ pub(crate) trait Unifier: DerefMut { if !self.fail { let d2 = self.store(d2); - tabu_list.insert((d1, d2)); + self.unify_tabu_list.insert((d1, d2)); } } (HeapCellValueTag::PStrLoc, l) => { @@ -406,7 +404,7 @@ pub(crate) trait Unifier: DerefMut { (HeapCellValueTag::PStrLoc | HeapCellValueTag::Lis | HeapCellValueTag::Str) => { - if tabu_list.contains(&(d1, d2)) { + if self.unify_tabu_list.contains(&(d1, d2)) { continue; } } @@ -424,7 +422,7 @@ pub(crate) trait Unifier: DerefMut { if !self.fail && !d2.is_constant() { let d2 = self.store(d2); - tabu_list.insert((d1, d2)); + self.unify_tabu_list.insert((d1, d2)); } } (HeapCellValueTag::F64Offset, f1) => { @@ -445,6 +443,8 @@ pub(crate) trait Unifier: DerefMut { ); } } + + self.unify_tabu_list.clear(); } fn bind(&mut self, r: Ref, value: HeapCellValue);