refactor heapview

This commit is contained in:
Mark Thom
2018-01-13 21:50:47 -07:00
parent 20972f18c2
commit 0fb64f412e
7 changed files with 257 additions and 204 deletions

View File

@@ -15,12 +15,12 @@ use std::rc::Rc;
use std::str::Utf8Error; use std::str::Utf8Error;
use std::vec::Vec; use std::vec::Vec;
pub const LEXER_BUF_SIZE: usize = 4096;
pub type Atom = String; pub type Atom = String;
pub type Var = String; pub type Var = String;
pub const LEXER_BUF_SIZE: usize = 4096;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum GenContext { pub enum GenContext {
Head, Mid(usize), Last(usize) // Mid & Last: chunk_num Head, Mid(usize), Last(usize) // Mid & Last: chunk_num

88
src/prolog/heap_iter.rs Normal file
View File

@@ -0,0 +1,88 @@
use prolog::ast::*;
use prolog::machine::machine_state::MachineState;
use std::vec::Vec;
pub struct HeapCellIterator<'a> {
machine_st : &'a MachineState,
state_stack : Vec<Ref>
}
impl<'a> HeapCellIterator<'a> {
pub fn new(machine_st: &'a MachineState, r: Ref) -> Self
{
let mut iter = HeapCellIterator {
machine_st,
state_stack: vec![]
};
iter.state_stack.push(r);
iter
}
// called under the assumption that the location at r is about to
// be visited, and so any follow up states need to be added to
// state_stack. returns the dereferenced Addr from Ref.
fn follow(&mut self, r: Ref) -> Addr
{
match r {
Ref::HeapCell(hc) => self.follow_heap(hc),
Ref::StackCell(fr, sc) => self.follow_addr(Addr::StackCell(fr, sc))
}
}
fn follow_heap(&mut self, h: usize) -> Addr
{
match &self.machine_st.heap[h] {
&HeapCellValue::NamedStr(arity, _) => {
for idx in (1 .. arity + 1).rev() {
self.state_stack.push(Ref::HeapCell(h + idx));
}
Addr::HeapCell(h)
},
&HeapCellValue::Addr(ref a) =>
self.follow_addr(a.clone())
}
}
fn follow_addr(&mut self, addr: Addr) -> Addr
{
let da = self.machine_st.store(self.machine_st.deref(addr));
match &da {
&Addr::Con(_) => da,
&Addr::Lis(a) => {
self.state_stack.push(Ref::HeapCell(a + 1));
self.state_stack.push(Ref::HeapCell(a));
da
},
&Addr::HeapCell(_) | &Addr::StackCell(_, _) =>
da,
&Addr::Str(s) => {
self.follow_heap(s); // record terms of structure.
Addr::HeapCell(s)
}
}
}
}
impl<'a> Iterator for HeapCellIterator<'a> {
type Item = HeapCellValue;
fn next(&mut self) -> Option<Self::Item> {
if let Some(r) = self.state_stack.pop() {
match self.follow(r) {
Addr::HeapCell(h) => Some(self.machine_st.heap[h].clone()),
Addr::StackCell(fr, sc) => {
let heap_val = HeapCellValue::Addr(self.machine_st.and_stack[fr][sc].clone());
Some(heap_val)
},
da => Some(HeapCellValue::Addr(da))
}
} else {
None
}
}
}

135
src/prolog/heap_print.rs Normal file
View File

@@ -0,0 +1,135 @@
use prolog::ast::*;
use prolog::heap_iter::*;
use std::cell::Cell;
use std::rc::Rc;
#[derive(Clone)]
pub enum TokenOrRedirect {
Atom(Rc<Atom>),
Redirect,
Open,
Close,
Comma,
OpenList(Rc<Cell<bool>>),
CloseList(Rc<Cell<bool>>),
HeadTailSeparator
}
pub trait HeapCellValueFormatter {
// this function belongs to the display predicate formatter.
fn format_clause(&self, arity: usize, name: Rc<Atom>, state_stack: &mut Vec<TokenOrRedirect>)
{
state_stack.push(TokenOrRedirect::Close);
for _ in 0 .. arity {
state_stack.push(TokenOrRedirect::Redirect);
state_stack.push(TokenOrRedirect::Comma);
}
state_stack.pop();
state_stack.push(TokenOrRedirect::Open);
state_stack.push(TokenOrRedirect::Atom(name));
}
}
// the 'classic' display corresponding to the display predicate.
pub struct DisplayFormatter {}
impl HeapCellValueFormatter for DisplayFormatter {}
pub struct HeapCellPrinter<'a, Formatter> {
formatter: Formatter,
iter: HeapCellIterator<'a>,
state_stack: Vec<TokenOrRedirect>
}
impl<'a, Formatter: HeapCellValueFormatter> HeapCellPrinter<'a, Formatter>
{
pub fn new(iter: HeapCellIterator<'a>, formatter: Formatter) -> Self {
HeapCellPrinter { formatter, iter, state_stack: vec![] }
}
fn handle_heap_term(&mut self, heap_val: HeapCellValue, result: &mut String) {
match heap_val {
HeapCellValue::NamedStr(arity, name) =>
self.formatter.format_clause(arity, name, &mut self.state_stack),
HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) =>
if !Self::at_cdr(result, "") {
*result += "[]";
},
HeapCellValue::Addr(Addr::Con(c)) =>
*result += format!("{}", c).as_str(),
HeapCellValue::Addr(Addr::Lis(_)) => {
let cell = Rc::new(Cell::new(true));
self.state_stack.push(TokenOrRedirect::CloseList(cell.clone()));
self.state_stack.push(TokenOrRedirect::Redirect);
self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar
self.state_stack.push(TokenOrRedirect::Redirect);
self.state_stack.push(TokenOrRedirect::OpenList(cell));
},
HeapCellValue::Addr(Addr::HeapCell(h)) =>
*result += format!("_{}", h).as_str(),
HeapCellValue::Addr(Addr::StackCell(fr, sc)) =>
*result += format!("s_{}_{}", fr, sc).as_str(),
HeapCellValue::Addr(Addr::Str(_)) => {}
}
}
fn at_cdr(result: &mut String, tr: &str) -> bool {
let len = result.len();
if result.ends_with(" | ") {
result.truncate(len - 3);
*result += tr;
true
} else {
false
}
}
pub fn print(&mut self) -> String {
let mut result = String::new();
loop {
if let Some(loc_data) = self.state_stack.pop() {
match loc_data {
TokenOrRedirect::Atom(atom) =>
result += atom.as_str(),
TokenOrRedirect::Redirect => {
let heap_val = self.iter.next().unwrap();
self.handle_heap_term(heap_val, &mut result);
},
TokenOrRedirect::Close =>
result += ")",
TokenOrRedirect::Open =>
result += "(",
TokenOrRedirect::OpenList(delimit) =>
if !Self::at_cdr(&mut result, ", ") {
result += "[";
} else {
delimit.set(false);
},
TokenOrRedirect::CloseList(delimit) =>
if delimit.get() == true {
result += "]";
},
TokenOrRedirect::HeadTailSeparator =>
result += " | ",
TokenOrRedirect::Comma =>
result += ", "
}
} else if let Some(heap_val) = self.iter.next() {
self.handle_heap_term(heap_val, &mut result);
} else {
break;
}
}
result
}
}

View File

@@ -1,196 +0,0 @@
use prolog::and_stack::*;
use prolog::ast::*;
use std::vec::Vec;
#[derive(Clone, Copy)]
pub enum TToken {
Bar,
Comma,
LRBracket,
LSBracket(usize),
Nothing,
RRBracket,
RSBracket
}
impl TToken {
pub fn as_str(self) -> &'static str {
match self {
TToken::Bar => " | ",
TToken::Comma => ", ",
TToken::LRBracket => "(",
TToken::LSBracket(_) => "[",
TToken::Nothing => "",
TToken::RRBracket => ")",
TToken::RSBracket => "]"
}
}
}
#[derive(Clone, Copy)]
enum CellRef<'a> {
Lis(usize),
View(CellView<'a>),
Redirect(usize),
TToken(TToken)
}
#[derive(Clone, Copy)]
pub enum CellView<'a> {
Con(&'a Constant),
HeapVar(usize),
StackVar(usize, usize),
Str(usize, &'a Atom),
TToken(TToken),
}
pub struct HeapCellViewer<'a> {
and_stack: &'a AndStack,
heap: &'a Heap,
state_stack: Vec<CellRef<'a>>
}
impl<'a> HeapCellViewer<'a>
{
pub fn new(heap: &'a Heap, and_stack: &'a AndStack, addr: &'a Addr) -> Self
{
let mut viewer = HeapCellViewer {
heap: heap,
and_stack: and_stack,
state_stack: vec![]
};
let cell_ref = viewer.deref_cell(addr);
let view = viewer.follow(cell_ref);
viewer.state_stack.push(CellRef::View(view));
viewer
}
fn deref_cell(&self, mut focus: &'a Addr) -> CellRef<'a>
{
loop {
match focus {
&Addr::Con(ref c) =>
return CellRef::View(CellView::Con(c)),
&Addr::Lis(hc) =>
return CellRef::Lis(hc),
&Addr::HeapCell(hc) | &Addr::Str(hc) =>
return CellRef::Redirect(hc),
&Addr::StackCell(fr, sc) => {
match &self.and_stack[fr][sc] {
&Addr::StackCell(fr1, sc1) => {
if fr1 == fr && sc1 == sc {
return CellRef::View(CellView::StackVar(fr, sc));
}
},
_ => focus = &self.and_stack[fr][sc]
}
}
}
}
}
pub fn remove_token(&mut self, loc: usize) {
self.state_stack[loc] = CellRef::TToken(TToken::Nothing);
}
pub fn peek(&mut self) -> Option<CellView<'a>> {
let len = self.state_stack.len();
if len > 0 {
let last_elt = self.state_stack.pop().unwrap();
let cell_view = self.follow(last_elt);
self.state_stack.truncate(len - 1);
self.state_stack.push(last_elt);
Some(cell_view)
} else {
None
}
}
fn handle_list(&mut self, focus: usize) -> CellView<'a> {
self.state_stack.push(CellRef::TToken(TToken::RSBracket));
self.state_stack.push(CellRef::Redirect(focus + 1));
self.state_stack.push(CellRef::TToken(TToken::Bar));
self.state_stack.push(CellRef::Redirect(focus));
let len = self.state_stack.len() - 4;
return CellView::TToken(TToken::LSBracket(len));
}
fn from_heap(&mut self, mut focus: usize) -> CellView<'a> {
loop {
match &self.heap[focus] {
&HeapCellValue::NamedStr(arity, ref name) => {
self.state_stack.push(CellRef::TToken(TToken::RRBracket));
for i in (2 .. arity + 1).rev() {
self.state_stack.push(CellRef::Redirect(focus + i));
self.state_stack.push(CellRef::TToken(TToken::Comma));
}
self.state_stack.push(CellRef::Redirect(focus + 1));
self.state_stack.push(CellRef::TToken(TToken::LRBracket));
return CellView::Str(arity, name);
},
&HeapCellValue::Addr(ref a) =>
match a {
&Addr::Con(ref c) =>
return CellView::Con(c),
&Addr::Lis(a) =>
return self.handle_list(a),
&Addr::HeapCell(hc) =>
if focus == hc {
return CellView::HeapVar(hc);
} else {
focus = hc;
},
&Addr::StackCell(fr, sc) =>
match self.deref_cell(&self.and_stack[fr][sc]) {
CellRef::Lis(hc) => return self.handle_list(hc),
CellRef::View(cell_view) => return cell_view,
CellRef::Redirect(hc) => focus = hc,
CellRef::TToken(token) => return CellView::TToken(token)
},
&Addr::Str(cell_num) =>
focus = cell_num,
},
}
}
}
fn follow(&mut self, cell_ref: CellRef<'a>) -> CellView<'a>
{
match cell_ref {
CellRef::Lis(hc) =>
self.handle_list(hc),
CellRef::Redirect(hc) =>
self.from_heap(hc),
CellRef::View(cell_view) =>
cell_view,
CellRef::TToken(term_token) =>
CellView::TToken(term_token)
}
}
}
impl<'a> Iterator for HeapCellViewer<'a> {
type Item = CellView<'a>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(cell_ref) = self.state_stack.pop() {
Some(self.follow(cell_ref))
} else {
None
}
}
}

View File

@@ -221,7 +221,7 @@ impl MachineState {
if self.b > 0 { self.or_stack[self.b - 1].global_index } else { 0 }) + 1 if self.b > 0 { self.or_stack[self.b - 1].global_index } else { 0 }) + 1
} }
pub(super) fn store(&self, a: Addr) -> Addr { pub(crate) fn store(&self, a: Addr) -> Addr {
match a { match a {
Addr::HeapCell(r) => self.heap[r].as_addr(r), Addr::HeapCell(r) => self.heap[r].as_addr(r),
Addr::StackCell(fr, sc) => self.and_stack[fr][sc].clone(), Addr::StackCell(fr, sc) => self.and_stack[fr][sc].clone(),

View File

@@ -1,7 +1,8 @@
use prolog::ast::*; use prolog::ast::*;
use prolog::builtins::*; use prolog::builtins::*;
use prolog::codegen::*; use prolog::codegen::*;
use prolog::heapview::*; use prolog::heap_iter::*;
use prolog::heap_print::*;
use prolog::fixtures::*; use prolog::fixtures::*;
pub(crate) mod machine_state; pub(crate) mod machine_state;
@@ -321,7 +322,7 @@ impl Machine {
} }
} }
pub fn continue_query<'a>(&mut self, alloc_locs: &AllocVarDict<'a>, heap_locs: &mut HeapVarDict<'a>) pub fn continue_query<'a>(&mut self, alloc_l: &AllocVarDict<'a>, heap_l: &mut HeapVarDict<'a>)
-> EvalSession<'a> -> EvalSession<'a>
{ {
if !self.or_stack_is_empty() { if !self.or_stack_is_empty() {
@@ -332,7 +333,7 @@ impl Machine {
return EvalSession::QueryFailure; return EvalSession::QueryFailure;
} }
self.run_query(alloc_locs, heap_locs); self.run_query(alloc_l, heap_l);
if self.failed() { if self.failed() {
self.fail() self.fail()
@@ -344,6 +345,30 @@ impl Machine {
} }
} }
fn print_var(&self, r: Ref) -> String
{
let disp = DisplayFormatter {};
let iter = HeapCellIterator::new(&self.ms, r);
let mut printer = HeapCellPrinter::new(iter, disp);
printer.print()
}
// NEW ---
fn print_term(&self, addr: &Addr) -> String
{
match addr {
&Addr::Con(ref c) =>
format!("{}", c),
&Addr::Lis(h) | &Addr::HeapCell(h) | &Addr::Str(h) =>
self.print_var(Ref::HeapCell(h)),
&Addr::StackCell(fr, sc) =>
self.print_var(Ref::StackCell(fr, sc))
}
}
/*
fn print_term(&self, addr: &Addr) -> String fn print_term(&self, addr: &Addr) -> String
{ {
let mut viewer = HeapCellViewer::new(&self.ms.heap, let mut viewer = HeapCellViewer::new(&self.ms.heap,
@@ -387,7 +412,7 @@ impl Machine {
result result
} }
*/
pub fn heap_view(&self, var_dir: &HeapVarDict) -> String { pub fn heap_view(&self, var_dir: &HeapVarDict) -> String {
let mut result = String::new(); let mut result = String::new();

View File

@@ -13,7 +13,8 @@ pub mod codegen;
pub mod copier; pub mod copier;
pub mod debray_allocator; pub mod debray_allocator;
pub mod fixtures; pub mod fixtures;
pub mod heapview; pub mod heap_iter;
pub mod heap_print;
pub mod indexing; pub mod indexing;
pub mod io; pub mod io;
pub mod iterators; pub mod iterators;