Merge pull request #3342 from Skgland/pdl-pairs

ensure pdl is pushed/popped in pairs and reuse tabu_list allocation by moving it from a local variable into the machine state
This commit is contained in:
Mark Thom
2026-05-25 15:10:02 -06:00
committed by GitHub
4 changed files with 36 additions and 34 deletions

View File

@@ -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;
@@ -115,7 +117,8 @@ impl OccursCheckImpl for StoError {
pub struct MachineState {
pub atom_tbl: Arc<AtomTable>,
pub arena: Arena,
pub(super) pdl: Vec<HeapCellValue>,
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,

View File

@@ -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,

View File

@@ -9,19 +9,15 @@ use crate::types::*;
use std::ops::{Deref, DerefMut};
use derive_more::*;
use fxhash::FxBuildHasher;
use indexmap::IndexSet;
use num_order::NumOrd;
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 +33,7 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
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 +42,7 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
(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 +70,7 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
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 +79,7 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
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 +128,7 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
(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;
@@ -355,13 +346,15 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
}
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 {
// FIXME(msrv) FIXME(edition2024) use let chain to move this to check this in the while condition
break;
}
while !(self.pdl.is_empty() || self.fail) {
let s1 = self.pdl.pop().unwrap();
let s1 = (self.deref() as &MachineState).deref(s1);
let s2 = self.pdl.pop().unwrap();
let s2 = (self.deref() as &MachineState).deref(s2);
if s1 != s2 {
@@ -383,7 +376,7 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
Self::unify_atom(self, name, d2);
}
(HeapCellValueTag::Str, s1) => {
if tabu_list.contains(&(d1, d2)) {
if self.unify_tabu_list.contains(&(d1, d2)) {
continue;
}
@@ -391,11 +384,11 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
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;
}
@@ -403,7 +396,7 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
if !self.fail {
let d2 = self.store(d2);
tabu_list.insert((d1, d2));
self.unify_tabu_list.insert((d1, d2));
}
}
(HeapCellValueTag::PStrLoc, l) => {
@@ -411,7 +404,7 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
(HeapCellValueTag::PStrLoc |
HeapCellValueTag::Lis |
HeapCellValueTag::Str) => {
if tabu_list.contains(&(d1, d2)) {
if self.unify_tabu_list.contains(&(d1, d2)) {
continue;
}
}
@@ -429,7 +422,7 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
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) => {
@@ -450,6 +443,8 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
);
}
}
self.unify_tabu_list.clear();
}
fn bind(&mut self, r: Ref, value: HeapCellValue);

View File

@@ -401,22 +401,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()
}};
}