65 lines
1.8 KiB
Rust
65 lines
1.8 KiB
Rust
use l2::ast::*;
|
|
|
|
use std::vec::Vec;
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub enum HeapCellView<'a> {
|
|
Str(usize, &'a Atom),
|
|
Var(usize)
|
|
}
|
|
|
|
pub struct HeapCellViewer<'a> {
|
|
heap: &'a Heap,
|
|
state_stack: Vec<(usize, &'a HeapCellValue)>
|
|
}
|
|
|
|
impl<'a> HeapCellViewer<'a> {
|
|
pub fn new(heap: &'a Heap, focus: usize) -> Self {
|
|
HeapCellViewer {
|
|
heap: heap,
|
|
state_stack: vec![(focus, &heap[focus])]
|
|
}
|
|
}
|
|
|
|
fn follow(&self, value: &'a HeapCellValue) -> &'a HeapCellValue {
|
|
match value {
|
|
&HeapCellValue::NamedStr(_, _) => value,
|
|
&HeapCellValue::Ref(cell_num) | &HeapCellValue::Str(cell_num) =>
|
|
&self.heap[cell_num],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> Iterator for HeapCellViewer<'a> {
|
|
type Item = HeapCellView<'a>;
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
while let Some(hcv) = self.state_stack.pop() {
|
|
match hcv {
|
|
(focus, &HeapCellValue::NamedStr(arity, ref name)) => {
|
|
for i in (1 .. arity + 1).rev() {
|
|
self.state_stack.push((focus + i, &self.heap[focus + i]));
|
|
}
|
|
|
|
return Some(HeapCellView::Str(arity, name));
|
|
},
|
|
(_, &HeapCellValue::Ref(cell_num)) => {
|
|
let new_hcv = self.follow(hcv.1);
|
|
|
|
if hcv.1 == new_hcv {
|
|
return Some(HeapCellView::Var(cell_num));
|
|
} else {
|
|
self.state_stack.push((cell_num, new_hcv));
|
|
}
|
|
},
|
|
(_, &HeapCellValue::Str(cell_num)) => {
|
|
let new_hcv = self.follow(hcv.1);
|
|
self.state_stack.push((cell_num, new_hcv));
|
|
}
|
|
}
|
|
}
|
|
|
|
None
|
|
}
|
|
}
|