use crate::types::*;
use std::alloc;
-use std::cmp::Ordering;
use std::convert::TryFrom;
use std::ops::{Bound, Index, IndexMut, Range, RangeBounds};
use std::ptr;
}
}
+#[derive(Debug, Clone, Copy)]
+pub(crate) enum PStrContinuable {
+ PStrOffset(usize),
+ TailIndex(usize),
+}
+
+impl PStrContinuable {
+ #[inline]
+ pub(crate) fn offset_by(&self, pstr_loc: usize) -> HeapCellValue {
+ match self {
+ Self::PStrOffset(pstr_offset) => pstr_loc_as_cell!(pstr_loc + pstr_offset),
+ Self::TailIndex(tail_idx) => heap_loc_as_cell!(tail_idx + cell_index!(pstr_loc)),
+ }
+ }
+}
+
#[derive(Debug, Clone, Copy)]
pub(crate) enum PStrSegmentCmpResult {
Less,
Greater,
- Continue(HeapCellValue, HeapCellValue),
+ Continue(PStrContinuable, PStrContinuable),
+}
+
+pub(crate) fn compare_pstr_slices(slice1: &[u8], slice2: &[u8]) -> PStrSegmentCmpResult {
+ use std::cmp::Ordering;
+
+ debug_assert!(!slice1.is_empty() && !slice2.is_empty());
+ let find_tail = |slice| unsafe { scan_slice_to_str(slice).tail_idx };
+
+ match slice1
+ .iter()
+ .zip(slice2.iter())
+ .position(|(b1, b2)| b1 != b2 || *b1 == 0 || *b2 == 0)
+ {
+ Some(pos) => {
+ if slice1[pos] == 0 {
+ // subtract 1 from pos to offset the increment of scan_slice_to_str if the
+ // string is "\0\".
+ let tail1_idx = find_tail(&slice1[pos..]);
+
+ if slice2[pos] == 0 {
+ let tail2_idx = find_tail(&slice2[pos..]);
+
+ PStrSegmentCmpResult::Continue(
+ PStrContinuable::TailIndex(tail1_idx + cell_index!(pos)),
+ PStrContinuable::TailIndex(tail2_idx + cell_index!(pos)),
+ )
+ } else {
+ PStrSegmentCmpResult::Continue(
+ PStrContinuable::TailIndex(tail1_idx + cell_index!(pos)),
+ PStrContinuable::PStrOffset(pos),
+ )
+ }
+ } else if slice2[pos] == 0 {
+ let tail2_idx = find_tail(&slice2[pos..]);
+
+ PStrSegmentCmpResult::Continue(
+ PStrContinuable::PStrOffset(pos),
+ PStrContinuable::TailIndex(tail2_idx + cell_index!(pos)),
+ )
+ } else {
+ // Compute 7-byte chunks with the mismatching character at pos in the middle of
+ // each. This way, the character of which the byte at pos is a part will be
+ // validated and reached eventually by the utf8_chunks() iterator.
+
+ let slice1_range = pos.saturating_sub(3)..(pos + 4).min(slice1.len());
+ let slice2_range = pos.saturating_sub(3)..(pos + 4).min(slice2.len());
+
+ let chars1_iter = slice1[slice1_range].utf8_chunks();
+ let chars2_iter = slice2[slice2_range].utf8_chunks();
+
+ for (chunk1, chunk2) in chars1_iter.zip(chars2_iter) {
+ let result = chunk1.valid().cmp(chunk2.valid());
+
+ if result == Ordering::Greater {
+ return PStrSegmentCmpResult::Greater;
+ } else if result == Ordering::Less {
+ return PStrSegmentCmpResult::Less;
+ }
+ }
+
+ unreachable!()
+ }
+ }
+ None => {
+ unreachable!()
+ }
+ }
}
#[derive(Debug)]
});
}
+ #[inline]
pub(crate) fn compare_pstr_segments(
&self,
pstr_loc1: usize,
let slice1 = &self.as_slice()[pstr_loc1..];
let slice2 = &self.as_slice()[pstr_loc2..];
- let find_tail = |null_idx: usize| -> usize { self.scan_slice_to_str(null_idx).tail_idx };
-
- match slice1
- .iter()
- .zip(slice2.iter())
- .position(|(b1, b2)| b1 != b2 || *b1 == 0 || *b2 == 0)
- {
- Some(pos) => {
- if slice1[pos] == 0 {
- // subtract 1 from pos to offset the increment of scan_slice_to_str if the
- // string is "\0\".
- let tail1_idx = find_tail(pstr_loc1 + pos);
-
- if slice2[pos] == 0 {
- let tail2_idx = find_tail(pstr_loc2 + pos);
-
- PStrSegmentCmpResult::Continue(
- heap_loc_as_cell!(tail1_idx),
- heap_loc_as_cell!(tail2_idx),
- )
- } else {
- PStrSegmentCmpResult::Continue(
- heap_loc_as_cell!(tail1_idx),
- pstr_loc_as_cell!(pstr_loc2 + pos),
- )
- }
- } else if slice2[pos] == 0 {
- let tail2_idx = find_tail(pstr_loc2 + pos);
-
- PStrSegmentCmpResult::Continue(
- pstr_loc_as_cell!(pstr_loc1 + pos),
- heap_loc_as_cell!(tail2_idx),
- )
- } else {
- // Compute 7-byte chunks with the mismatching character at pos in the middle of
- // each. This way, the character of which the byte at pos is a part will be
- // validated and reached eventually by the utf8_chunks() iterator.
-
- let slice1_range = pos.saturating_sub(3)..(pos + 4).min(slice1.len());
- let slice2_range = pos.saturating_sub(3)..(pos + 4).min(slice2.len());
-
- let chars1_iter = slice1[slice1_range].utf8_chunks();
- let chars2_iter = slice2[slice2_range].utf8_chunks();
-
- for (chunk1, chunk2) in chars1_iter.zip(chars2_iter) {
- let result = chunk1.valid().cmp(chunk2.valid());
-
- if result == Ordering::Greater {
- return PStrSegmentCmpResult::Greater;
- } else if result == Ordering::Less {
- return PStrSegmentCmpResult::Less;
- }
- }
-
- unreachable!()
- }
- }
- None => {
- unreachable!()
- }
- }
+ compare_pstr_slices(slice1, slice2)
}
#[inline]
(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);
- machine_st.pdl.push(v2);
+ machine_st.pdl.push(v1.offset_by(pstr_loc));
+ machine_st.pdl.push(v2.offset_by(other_pstr_loc));
}
_ => {
machine_st.fail = true;
self.fail = !(arity == 0 && name == atom);
}
- /*
- (HeapCellValueTag::CStr, cstr_atom) if atom == atom!("[]") => {
- self.fail = cstr_atom != atom!("");
- }
- (HeapCellValueTag::Char, c1) => {
- if let Some(c2) = atom.as_char() {
- self.fail = c1 != c2;
- } else {
- self.fail = true;
- }
- }
- */
(HeapCellValueTag::AttrVar, h) => {
Self::bind(self, Ref::attr_var(h), atom_as_cell!(atom));
}
self.fail = true;
}
}
- /*
- (HeapCellValueTag::Char, c2) => {
- if c != c2 {
- self.fail = true;
- }
- }
- */
(HeapCellValueTag::AttrVar, h) => {
Self::bind(self, Ref::attr_var(h), char_as_cell!(c));
}
tabu_list.insert((d1, d2));
}
}
- /*
- (HeapCellValueTag::CStr) => {
- read_heap_cell!(d2,
- (HeapCellValueTag::AttrVar, h) => {
- Self::bind(self, Ref::attr_var(h), d1);
- continue;
- }
- (HeapCellValueTag::Var, h) => {
- Self::bind(self, Ref::heap_cell(h), d1);
- continue;
- }
- (HeapCellValueTag::StackVar, s) => {
- Self::bind(self, Ref::stack_cell(s), d1);
- continue;
- }
- (HeapCellValueTag::Str |
- HeapCellValueTag::Lis |
- HeapCellValueTag::PStrLoc) => {
- }
- (HeapCellValueTag::CStr) => {
- self.fail = d1 != d2;
- continue;
- }
- _ => {
- self.fail = true;
- return;
- }
- );
-
- Self::unify_partial_string(self, d2, d1);
- }
- */
(HeapCellValueTag::F64, f1) => {
Self::unify_f64(self, f1, d2);
}