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 { 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 } }