677 lines
21 KiB
Rust
677 lines
21 KiB
Rust
use crate::atom_table::*;
|
|
|
|
use crate::machine::heap::*;
|
|
use crate::machine::machine_errors::CycleSearchResult;
|
|
use crate::machine::system_calls::BrentAlgState;
|
|
use crate::types::*;
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub struct HeapPStrIter<'a> {
|
|
pub heap: &'a Heap,
|
|
// pub focus: HeapCellValue,
|
|
orig_focus: usize,
|
|
brent_st: BrentAlgState,
|
|
stepper: fn(&mut HeapPStrIter<'a>) -> Option<PStrIteratee>,
|
|
}
|
|
|
|
struct PStrIterStep {
|
|
iteratee: PStrIteratee,
|
|
next_hare: usize,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum PStrIteratee {
|
|
Char { heap_loc: usize, value: char },
|
|
PStrSlice { slice_loc: usize, slice_len: usize },
|
|
}
|
|
|
|
impl<'a> HeapPStrIter<'a> {
|
|
pub fn new(heap: &'a Heap, orig_focus: usize) -> Self {
|
|
debug_assert!(heap[orig_focus].is_ref());
|
|
|
|
Self {
|
|
heap,
|
|
orig_focus,
|
|
brent_st: BrentAlgState::new(orig_focus),
|
|
stepper: HeapPStrIter::pre_cycle_discovery_stepper,
|
|
}
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn focus(&self) -> usize {
|
|
self.brent_st.hare
|
|
}
|
|
|
|
fn walk_hare_to_cycle_end(&mut self) {
|
|
// walk_hare_to_cycle_end assumes a cycle has been found,
|
|
// so it is always safe to unwrap self.step()
|
|
|
|
let orig_hare = self.brent_st.hare;
|
|
|
|
self.brent_st.hare = self.orig_focus;
|
|
self.brent_st.tortoise = self.orig_focus;
|
|
|
|
for _ in 0..self.brent_st.lam {
|
|
self.brent_st.hare = self.step(self.brent_st.hare).unwrap().next_hare;
|
|
}
|
|
|
|
while self.brent_st.hare != self.brent_st.tortoise {
|
|
self.brent_st.tortoise = self.step(self.brent_st.tortoise).unwrap().next_hare;
|
|
self.brent_st.hare = self.step(self.brent_st.hare).unwrap().next_hare;
|
|
}
|
|
|
|
// self.focus = self.heap[orig_hare];
|
|
self.brent_st.hare = orig_hare;
|
|
}
|
|
|
|
pub fn to_string_mut(&mut self) -> String {
|
|
let mut buf = String::with_capacity(32);
|
|
|
|
while let Some(iteratee) = self.next() {
|
|
match iteratee {
|
|
PStrIteratee::Char { value: c, .. } => {
|
|
buf.push(c);
|
|
}
|
|
PStrIteratee::PStrSlice {
|
|
slice_loc,
|
|
slice_len,
|
|
} => {
|
|
buf += self.heap.slice_to_str(slice_loc, slice_len);
|
|
}
|
|
}
|
|
}
|
|
|
|
buf
|
|
}
|
|
|
|
// return the next step in the iteration or the updated curr_hare
|
|
// for the sake of pointing to the pstr tail
|
|
fn step(&self, mut curr_hare: usize) -> Result<PStrIterStep, usize> {
|
|
loop {
|
|
read_heap_cell!(self.heap[curr_hare],
|
|
(HeapCellValueTag::PStrLoc, h) => {
|
|
let HeapStringScan { string, tail_idx } = self.heap.scan_slice_to_str(h);
|
|
|
|
return Ok(PStrIterStep {
|
|
iteratee: PStrIteratee::PStrSlice { slice_loc: h, slice_len: string.len() },
|
|
next_hare: tail_idx,
|
|
});
|
|
}
|
|
(HeapCellValueTag::Lis, h) => {
|
|
let value = heap_bound_store(
|
|
self.heap,
|
|
heap_bound_deref(self.heap, self.heap[h]),
|
|
);
|
|
|
|
return value.as_char().map(|c| PStrIterStep {
|
|
iteratee: PStrIteratee::Char { heap_loc: curr_hare, value: c },
|
|
next_hare: h+1,
|
|
}).ok_or(curr_hare)
|
|
}
|
|
(HeapCellValueTag::Str, s) => {
|
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
|
.get_name_and_arity();
|
|
|
|
return if name == atom!(".") && arity == 2 {
|
|
let value = heap_bound_store(
|
|
self.heap,
|
|
heap_bound_deref(self.heap, self.heap[s+1]),
|
|
);
|
|
|
|
value.as_char().map(|c| PStrIterStep {
|
|
iteratee: PStrIteratee::Char { heap_loc: curr_hare, value: c },
|
|
next_hare: s+2,
|
|
}).ok_or(curr_hare)
|
|
} else {
|
|
Err(curr_hare)
|
|
};
|
|
}
|
|
(HeapCellValueTag::Atom, (_name, arity)) => {
|
|
debug_assert!(arity == 0);
|
|
return Err(curr_hare);
|
|
}
|
|
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
|
if h == curr_hare {
|
|
return Err(curr_hare);
|
|
}
|
|
|
|
curr_hare = h;
|
|
}
|
|
_ => {
|
|
return Err(curr_hare);
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
fn pre_cycle_discovery_stepper(&mut self) -> Option<PStrIteratee> {
|
|
let PStrIterStep {
|
|
iteratee,
|
|
next_hare,
|
|
} = match self.step(self.brent_st.hare) {
|
|
Ok(results) => results,
|
|
Err(next_hare) => {
|
|
self.brent_st.hare = next_hare;
|
|
return None;
|
|
}
|
|
};
|
|
|
|
match self.brent_st.step(next_hare) {
|
|
Some(cycle_result) => {
|
|
debug_assert!(matches!(cycle_result, CycleSearchResult::Cyclic { .. }));
|
|
|
|
self.walk_hare_to_cycle_end();
|
|
self.stepper = HeapPStrIter::post_cycle_discovery_stepper;
|
|
}
|
|
None => {
|
|
// self.focus = self.heap[next_hare];
|
|
}
|
|
}
|
|
|
|
Some(iteratee)
|
|
}
|
|
|
|
fn post_cycle_discovery_stepper(&mut self) -> Option<PStrIteratee> {
|
|
if self.brent_st.hare == self.brent_st.tortoise {
|
|
return None;
|
|
}
|
|
|
|
let PStrIterStep {
|
|
iteratee,
|
|
next_hare,
|
|
} = match self.step(self.brent_st.hare) {
|
|
Ok(results) => results,
|
|
Err(next_hare) => {
|
|
self.brent_st.hare = next_hare;
|
|
return None;
|
|
}
|
|
};
|
|
|
|
// self.focus = self.heap[next_hare];
|
|
self.brent_st.hare = next_hare;
|
|
|
|
Some(iteratee)
|
|
}
|
|
|
|
pub(crate) fn is_cyclic(&self) -> bool {
|
|
self.stepper as usize == Self::post_cycle_discovery_stepper as usize
|
|
}
|
|
}
|
|
|
|
impl<'a> Iterator for HeapPStrIter<'a> {
|
|
type Item = PStrIteratee;
|
|
|
|
#[inline(always)]
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
(self.stepper)(self)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
use crate::machine::mock_wam::*;
|
|
|
|
#[test]
|
|
#[cfg_attr(miri, ignore = "it takes too long to run")]
|
|
fn pstr_iter_tests() {
|
|
let mut wam = MockWAM::new();
|
|
|
|
let pstr_cell = wam.machine_st.heap.allocate_pstr("abc ").unwrap();
|
|
wam.machine_st
|
|
.heap
|
|
.push_cell(empty_list_as_cell!())
|
|
.unwrap();
|
|
|
|
// not overwriting anything! 0 is an interstitial cell
|
|
// reserved for use by the runtime
|
|
wam.machine_st.heap[0] = pstr_cell;
|
|
|
|
{
|
|
let mut iter = HeapPStrIter::new(&wam.machine_st.heap, 0);
|
|
|
|
assert_eq!(
|
|
iter.next(),
|
|
Some(PStrIteratee::PStrSlice {
|
|
slice_loc: heap_index!(1),
|
|
slice_len: "abc ".len()
|
|
}),
|
|
);
|
|
assert_eq!(iter.next(), None);
|
|
assert!(!iter.is_cyclic());
|
|
}
|
|
|
|
assert_eq!(wam.machine_st.heap[2], empty_list_as_cell!());
|
|
|
|
wam.machine_st.heap[2] = pstr_loc_as_cell!(heap_index!(3));
|
|
|
|
wam.machine_st.heap.allocate_pstr("def").unwrap();
|
|
let h = wam.machine_st.heap.cell_len();
|
|
|
|
wam.machine_st.heap.push_cell(heap_loc_as_cell!(h)).unwrap();
|
|
|
|
{
|
|
let mut iter = HeapPStrIter::new(&wam.machine_st.heap, 0);
|
|
|
|
assert_eq!(
|
|
iter.next(),
|
|
Some(PStrIteratee::PStrSlice {
|
|
slice_loc: heap_index!(1),
|
|
slice_len: "abc ".len()
|
|
})
|
|
);
|
|
assert_eq!(
|
|
iter.next(),
|
|
Some(PStrIteratee::PStrSlice {
|
|
slice_loc: heap_index!(3),
|
|
slice_len: "def".len(),
|
|
})
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
assert!(!iter.is_cyclic());
|
|
}
|
|
|
|
assert_eq!(wam.machine_st.heap[h], heap_loc_as_cell!(h));
|
|
|
|
wam.machine_st.heap[h] = empty_list_as_cell!();
|
|
|
|
{
|
|
let mut iter = HeapPStrIter::new(&wam.machine_st.heap, 0);
|
|
|
|
assert_eq!(
|
|
iter.next(),
|
|
Some(PStrIteratee::PStrSlice {
|
|
slice_loc: heap_index!(1),
|
|
slice_len: "abc ".len()
|
|
})
|
|
);
|
|
assert_eq!(
|
|
iter.next(),
|
|
Some(PStrIteratee::PStrSlice {
|
|
slice_loc: heap_index!(3),
|
|
slice_len: "def".len(),
|
|
})
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
assert!(!iter.is_cyclic());
|
|
}
|
|
|
|
wam.machine_st.heap[h] = pstr_loc_as_cell!(heap_index!(3));
|
|
|
|
{
|
|
let mut iter = HeapPStrIter::new(&wam.machine_st.heap, 0);
|
|
for _ in iter.by_ref() {}
|
|
assert!(iter.is_cyclic());
|
|
}
|
|
|
|
// test "abc" = [X,Y,Z].
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
let pstr_cell = wam.machine_st.heap.allocate_cstr("abc").unwrap();
|
|
let start = wam.machine_st.heap.cell_len();
|
|
|
|
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
|
|
|
|
writer.write_with(|section| {
|
|
section.push_cell(list_loc_as_cell!(1 + start));
|
|
section.push_cell(heap_loc_as_cell!(1 + start));
|
|
|
|
section.push_cell(list_loc_as_cell!(3 + start));
|
|
section.push_cell(heap_loc_as_cell!(3 + start));
|
|
|
|
section.push_cell(list_loc_as_cell!(5 + start));
|
|
section.push_cell(heap_loc_as_cell!(5 + start));
|
|
|
|
section.push_cell(empty_list_as_cell!());
|
|
});
|
|
|
|
unify!(wam.machine_st, pstr_cell, heap_loc_as_cell!(2));
|
|
|
|
assert_eq!(wam.machine_st.heap[1 + start], char_as_cell!('a'));
|
|
assert_eq!(wam.machine_st.heap[3 + start], char_as_cell!('b'));
|
|
assert_eq!(wam.machine_st.heap[5 + start], char_as_cell!('c'));
|
|
|
|
// test "abc" = [X,Y,Z|D].
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
let pstr_cell = wam.machine_st.heap.allocate_cstr("abc").unwrap();
|
|
let start = wam.machine_st.heap.cell_len();
|
|
|
|
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
|
|
|
|
writer.write_with(|section| {
|
|
section.push_cell(list_loc_as_cell!(1 + start));
|
|
section.push_cell(heap_loc_as_cell!(1 + start)); // X
|
|
|
|
section.push_cell(list_loc_as_cell!(3 + start));
|
|
section.push_cell(heap_loc_as_cell!(3 + start)); // Y
|
|
|
|
section.push_cell(list_loc_as_cell!(5 + start));
|
|
section.push_cell(heap_loc_as_cell!(5 + start)); // Z
|
|
|
|
section.push_cell(heap_loc_as_cell!(6 + start)); // D
|
|
});
|
|
|
|
unify!(wam.machine_st, pstr_cell, heap_loc_as_cell!(2));
|
|
|
|
assert!(!wam.machine_st.fail);
|
|
|
|
assert_eq!(wam.machine_st.heap[3], char_as_cell!('a'),);
|
|
assert_eq!(wam.machine_st.heap[5], char_as_cell!('b'),);
|
|
assert_eq!(wam.machine_st.heap[7], char_as_cell!('c'),);
|
|
assert_eq!(wam.machine_st.heap[8], empty_list_as_cell!(),);
|
|
|
|
// test "d" = [d].
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
let pstr_cell = wam.machine_st.heap.allocate_cstr("d").unwrap();
|
|
let start = wam.machine_st.heap.cell_len();
|
|
|
|
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
|
|
|
|
writer.write_with(|section| {
|
|
section.push_cell(list_loc_as_cell!(1 + start));
|
|
section.push_cell(char_as_cell!('d'));
|
|
section.push_cell(empty_list_as_cell!());
|
|
});
|
|
|
|
unify!(wam.machine_st, pstr_cell, heap_loc_as_cell!(start));
|
|
|
|
assert!(!wam.machine_st.fail);
|
|
|
|
// test "abc" = [X,b,Z].
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
let pstr_cell = wam.machine_st.heap.allocate_cstr("abc").unwrap();
|
|
let start = wam.machine_st.heap.cell_len();
|
|
|
|
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
|
|
|
|
writer.write_with(|section| {
|
|
section.push_cell(list_loc_as_cell!(1 + start));
|
|
section.push_cell(heap_loc_as_cell!(1 + start));
|
|
|
|
section.push_cell(list_loc_as_cell!(3 + start));
|
|
section.push_cell(char_as_cell!('b'));
|
|
|
|
section.push_cell(list_loc_as_cell!(5 + start));
|
|
section.push_cell(heap_loc_as_cell!(5 + start));
|
|
|
|
section.push_cell(empty_list_as_cell!());
|
|
});
|
|
|
|
unify!(wam.machine_st, pstr_cell, heap_loc_as_cell!(start));
|
|
|
|
assert!(!wam.machine_st.fail);
|
|
|
|
assert_eq!(wam.machine_st.heap[1 + start], char_as_cell!('a'));
|
|
assert_eq!(wam.machine_st.heap[3 + start], char_as_cell!('b'));
|
|
assert_eq!(wam.machine_st.heap[5 + start], char_as_cell!('c'));
|
|
|
|
// test "abcdef" = [a,b,c|X].
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
let pstr_cell = wam.machine_st.heap.allocate_cstr("abcdef").unwrap();
|
|
let start = wam.machine_st.heap.cell_len();
|
|
|
|
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
|
|
|
|
writer.write_with(|section| {
|
|
section.push_pstr("abc");
|
|
let h = section.cell_len(); // h == 3
|
|
section.push_cell(heap_loc_as_cell!(h));
|
|
});
|
|
|
|
unify!(
|
|
wam.machine_st,
|
|
pstr_cell,
|
|
pstr_loc_as_cell!(heap_index!(start))
|
|
);
|
|
|
|
assert!(!wam.machine_st.fail);
|
|
|
|
assert_eq!(
|
|
wam.machine_st.heap.slice_to_str(0, "abcdef".len()),
|
|
"abcdef"
|
|
);
|
|
assert_eq!(
|
|
wam.machine_st
|
|
.heap
|
|
.slice_to_str(heap_index!(start), "abc".len()),
|
|
"abc"
|
|
);
|
|
assert_eq!(
|
|
wam.machine_st.heap[3],
|
|
pstr_loc_as_cell!(heap_index!(0) + 3)
|
|
);
|
|
|
|
// test iteration on X = [b,c,b,c,b,c,b,c|...] as an offset.
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
wam.machine_st.heap.allocate_cstr("abc").unwrap();
|
|
let start = wam.machine_st.heap.cell_len();
|
|
|
|
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
|
|
|
|
writer.write_with(|section| {
|
|
section.push_cell(pstr_loc_as_cell!('a'.len_utf8()));
|
|
});
|
|
|
|
{
|
|
let mut iter = HeapPStrIter::new(&wam.machine_st.heap, start);
|
|
|
|
assert_eq!(
|
|
iter.next(),
|
|
Some(PStrIteratee::PStrSlice {
|
|
slice_loc: 'a'.len_utf8(),
|
|
slice_len: "bc".len()
|
|
})
|
|
);
|
|
|
|
for _ in iter {}
|
|
}
|
|
|
|
// #2293, test1.
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
wam.machine_st.heap.allocate_cstr("a ").unwrap();
|
|
let start = wam.machine_st.heap.cell_len();
|
|
|
|
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
|
|
|
|
writer.write_with(|section| {
|
|
section.push_cell(heap_loc_as_cell!(start));
|
|
section.push_cell(list_loc_as_cell!(2 + start));
|
|
section.push_cell(char_as_cell!(' '));
|
|
section.push_cell(empty_list_as_cell!());
|
|
});
|
|
|
|
unify!(
|
|
wam.machine_st,
|
|
list_loc_as_cell!(start),
|
|
pstr_loc_as_cell!(0)
|
|
);
|
|
|
|
assert!(!wam.machine_st.fail);
|
|
|
|
// #2293, test2.
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
wam.machine_st.heap.allocate_cstr(" a").unwrap();
|
|
let start = wam.machine_st.heap.cell_len();
|
|
|
|
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
|
|
|
|
writer.write_with(|section| {
|
|
section.push_cell(char_as_cell!(' '));
|
|
section.push_cell(list_loc_as_cell!(2 + start));
|
|
section.push_cell(heap_loc_as_cell!(2 + start));
|
|
section.push_cell(empty_list_as_cell!());
|
|
});
|
|
|
|
unify!(
|
|
wam.machine_st,
|
|
list_loc_as_cell!(start),
|
|
pstr_loc_as_cell!(0)
|
|
);
|
|
|
|
assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a'));
|
|
assert!(!wam.machine_st.fail);
|
|
|
|
// #2293, test3.
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
wam.machine_st.heap.allocate_cstr("a b").unwrap();
|
|
let start = wam.machine_st.heap.cell_len();
|
|
|
|
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
|
|
|
|
writer.write_with(|section| {
|
|
section.push_cell(heap_loc_as_cell!(start));
|
|
section.push_cell(list_loc_as_cell!(2 + start));
|
|
section.push_cell(char_as_cell!(' '));
|
|
section.push_cell(list_loc_as_cell!(4 + start));
|
|
section.push_cell(heap_loc_as_cell!(4 + start));
|
|
section.push_cell(empty_list_as_cell!());
|
|
});
|
|
|
|
unify!(
|
|
wam.machine_st,
|
|
list_loc_as_cell!(start),
|
|
pstr_loc_as_cell!(0)
|
|
);
|
|
|
|
assert_eq!(wam.machine_st.heap[start], char_as_cell!('a'));
|
|
assert_eq!(wam.machine_st.heap[4 + start], char_as_cell!('b'));
|
|
assert!(!wam.machine_st.fail);
|
|
|
|
// #2293, test4.
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
wam.machine_st.heap.allocate_cstr(" a ").unwrap();
|
|
let start = wam.machine_st.heap.cell_len();
|
|
|
|
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
|
|
|
|
writer.write_with(|section| {
|
|
section.push_cell(char_as_cell!(' '));
|
|
section.push_cell(list_loc_as_cell!(2 + start));
|
|
section.push_cell(heap_loc_as_cell!(2 + start));
|
|
section.push_cell(list_loc_as_cell!(4 + start));
|
|
section.push_cell(char_as_cell!(' '));
|
|
section.push_cell(empty_list_as_cell!());
|
|
});
|
|
|
|
unify!(
|
|
wam.machine_st,
|
|
list_loc_as_cell!(start),
|
|
pstr_loc_as_cell!(0)
|
|
);
|
|
|
|
assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a'));
|
|
assert!(!wam.machine_st.fail);
|
|
|
|
// #2293, test5.
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
wam.machine_st.heap.allocate_cstr(" a bc").unwrap();
|
|
let start = wam.machine_st.heap.cell_len();
|
|
|
|
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
|
|
|
|
writer.write_with(|section| {
|
|
section.push_cell(char_as_cell!(' '));
|
|
section.push_cell(list_loc_as_cell!(2 + start));
|
|
section.push_cell(heap_loc_as_cell!(2 + start));
|
|
section.push_cell(list_loc_as_cell!(4 + start));
|
|
section.push_cell(char_as_cell!(' '));
|
|
section.push_cell(heap_loc_as_cell!(5 + start));
|
|
});
|
|
|
|
unify!(
|
|
wam.machine_st,
|
|
list_loc_as_cell!(start),
|
|
pstr_loc_as_cell!(0)
|
|
);
|
|
|
|
assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a'));
|
|
assert_eq!(
|
|
wam.machine_st.heap[5 + start],
|
|
pstr_loc_as_cell!(heap_index!(0) + 3)
|
|
);
|
|
assert!(!wam.machine_st.fail);
|
|
|
|
// #2293, test6.
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
wam.machine_st.heap.allocate_cstr("abc").unwrap();
|
|
let start = wam.machine_st.heap.cell_len();
|
|
|
|
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
|
|
|
|
writer.write_with(|section| {
|
|
section.push_cell(heap_loc_as_cell!(start));
|
|
section.push_cell(list_loc_as_cell!(2 + start));
|
|
section.push_cell(char_as_cell!('b'));
|
|
section.push_cell(list_loc_as_cell!(4 + start));
|
|
section.push_cell(heap_loc_as_cell!(4 + start));
|
|
section.push_cell(empty_list_as_cell!());
|
|
});
|
|
|
|
unify!(
|
|
wam.machine_st,
|
|
list_loc_as_cell!(start),
|
|
pstr_loc_as_cell!(0)
|
|
);
|
|
|
|
assert_eq!(wam.machine_st.heap[start], char_as_cell!('a'));
|
|
assert_eq!(wam.machine_st.heap[4 + start], char_as_cell!('c'));
|
|
assert!(!wam.machine_st.fail);
|
|
|
|
// #2293, test7.
|
|
|
|
wam.machine_st.heap.clear();
|
|
wam.machine_st.heap.allocate_cstr("abcde").unwrap();
|
|
|
|
let start = wam.machine_st.heap.cell_len();
|
|
let mut writer = wam.machine_st.heap.reserve(16).unwrap();
|
|
|
|
writer.write_with(|section| {
|
|
section.push_cell(char_as_cell!('a'));
|
|
section.push_cell(list_loc_as_cell!(2 + start));
|
|
section.push_cell(heap_loc_as_cell!(2 + start));
|
|
section.push_cell(list_loc_as_cell!(4 + start));
|
|
section.push_cell(char_as_cell!('c'));
|
|
section.push_cell(list_loc_as_cell!(6 + start));
|
|
section.push_cell(heap_loc_as_cell!(6 + start));
|
|
section.push_cell(list_loc_as_cell!(8 + start));
|
|
section.push_cell(char_as_cell!('e'));
|
|
section.push_cell(empty_list_as_cell!());
|
|
});
|
|
|
|
unify!(
|
|
wam.machine_st,
|
|
list_loc_as_cell!(start),
|
|
pstr_loc_as_cell!(0)
|
|
);
|
|
|
|
assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('b'));
|
|
assert_eq!(wam.machine_st.heap[6 + start], char_as_cell!('d'));
|
|
assert!(!wam.machine_st.fail);
|
|
}
|
|
}
|