abstract Outputter of heap_print
This commit is contained in:
@@ -40,6 +40,57 @@ pub trait HeapCellValueFormatter {
|
|||||||
fn format_clause(&self, usize, Rc<Atom>, Option<Fixity>, &mut Vec<TokenOrRedirect>);
|
fn format_clause(&self, usize, Rc<Atom>, Option<Fixity>, &mut Vec<TokenOrRedirect>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait HeapCellValueOutputter {
|
||||||
|
type Output;
|
||||||
|
|
||||||
|
fn new() -> Self;
|
||||||
|
fn append(&mut self, &str);
|
||||||
|
fn begin_new_var(&mut self);
|
||||||
|
fn result(self) -> Self::Output;
|
||||||
|
fn ends_with(&self, &str) -> bool;
|
||||||
|
fn len(&self) -> usize;
|
||||||
|
fn truncate(&mut self, usize);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PrinterOutputter {
|
||||||
|
contents: String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl HeapCellValueOutputter for PrinterOutputter {
|
||||||
|
fn new() -> Self {
|
||||||
|
PrinterOutputter { contents: String::new() }
|
||||||
|
}
|
||||||
|
|
||||||
|
type Output = String;
|
||||||
|
|
||||||
|
fn append(&mut self, contents: &str) {
|
||||||
|
self.contents += contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn begin_new_var(&mut self) {
|
||||||
|
if self.contents.len() != 0 {
|
||||||
|
self.contents += ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn result(self) -> Self::Output {
|
||||||
|
self.contents
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ends_with(&self, s: &str) -> bool {
|
||||||
|
self.contents.ends_with(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn len(&self) -> usize {
|
||||||
|
self.contents.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn truncate(&mut self, len: usize) {
|
||||||
|
self.contents.truncate(len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// the 'classic' display corresponding to the display predicate.
|
// the 'classic' display corresponding to the display predicate.
|
||||||
pub struct DisplayFormatter {}
|
pub struct DisplayFormatter {}
|
||||||
|
|
||||||
@@ -51,7 +102,7 @@ impl HeapCellValueFormatter for DisplayFormatter {
|
|||||||
let mut new_name = String::from("'");
|
let mut new_name = String::from("'");
|
||||||
new_name += name.as_ref();
|
new_name += name.as_ref();
|
||||||
new_name += "'";
|
new_name += "'";
|
||||||
|
|
||||||
let name = Rc::new(new_name);
|
let name = Rc::new(new_name);
|
||||||
self.format_struct(arity, name, state_stack);
|
self.format_struct(arity, name, state_stack);
|
||||||
} else {
|
} else {
|
||||||
@@ -92,28 +143,30 @@ impl HeapCellValueFormatter for TermFormatter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct HeapCellPrinter<'a, Formatter> {
|
pub struct HeapCellPrinter<'a, Formatter, Outputter> {
|
||||||
formatter: Formatter,
|
formatter: Formatter,
|
||||||
|
outputter: Outputter,
|
||||||
iter: HeapCellIterator<'a>,
|
iter: HeapCellIterator<'a>,
|
||||||
state_stack: Vec<TokenOrRedirect>
|
state_stack: Vec<TokenOrRedirect>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Formatter: HeapCellValueFormatter> HeapCellPrinter<'a, Formatter>
|
impl<'a, Formatter: HeapCellValueFormatter, Outputter: HeapCellValueOutputter>
|
||||||
|
HeapCellPrinter<'a, Formatter, Outputter>
|
||||||
{
|
{
|
||||||
pub fn new(iter: HeapCellIterator<'a>, formatter: Formatter) -> Self {
|
pub fn new(iter: HeapCellIterator<'a>, formatter: Formatter, outputter: Outputter) -> Self {
|
||||||
HeapCellPrinter { formatter, iter, state_stack: vec![] }
|
HeapCellPrinter { formatter, outputter, iter, state_stack: vec![] }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_heap_term(&mut self, heap_val: HeapCellValue, result: &mut String) {
|
fn handle_heap_term(&mut self, heap_val: HeapCellValue) {
|
||||||
match heap_val {
|
match heap_val {
|
||||||
HeapCellValue::NamedStr(arity, name, fixity) =>
|
HeapCellValue::NamedStr(arity, name, fixity) =>
|
||||||
self.formatter.format_clause(arity, name, fixity, &mut self.state_stack),
|
self.formatter.format_clause(arity, name, fixity, &mut self.state_stack),
|
||||||
HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) =>
|
HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) =>
|
||||||
if !Self::at_cdr(result, "") {
|
if !self.at_cdr("") {
|
||||||
*result += "[]";
|
self.outputter.append("[]");
|
||||||
},
|
},
|
||||||
HeapCellValue::Addr(Addr::Con(c)) =>
|
HeapCellValue::Addr(Addr::Con(c)) =>
|
||||||
*result += format!("{}", c).as_str(),
|
self.outputter.append(format!("{}", c).as_str()),
|
||||||
HeapCellValue::Addr(Addr::Lis(_)) => {
|
HeapCellValue::Addr(Addr::Lis(_)) => {
|
||||||
let cell = Rc::new(Cell::new(true));
|
let cell = Rc::new(Cell::new(true));
|
||||||
|
|
||||||
@@ -126,65 +179,64 @@ impl<'a, Formatter: HeapCellValueFormatter> HeapCellPrinter<'a, Formatter>
|
|||||||
self.state_stack.push(TokenOrRedirect::OpenList(cell));
|
self.state_stack.push(TokenOrRedirect::OpenList(cell));
|
||||||
},
|
},
|
||||||
HeapCellValue::Addr(Addr::HeapCell(h)) =>
|
HeapCellValue::Addr(Addr::HeapCell(h)) =>
|
||||||
*result += format!("_{}", h).as_str(),
|
self.outputter.append(format!("_{}", h).as_str()),
|
||||||
HeapCellValue::Addr(Addr::StackCell(fr, sc)) =>
|
HeapCellValue::Addr(Addr::StackCell(fr, sc)) =>
|
||||||
*result += format!("s_{}_{}", fr, sc).as_str(),
|
self.outputter.append(format!("s_{}_{}", fr, sc).as_str()),
|
||||||
HeapCellValue::Addr(Addr::Str(_)) => {}
|
HeapCellValue::Addr(Addr::Str(_)) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn at_cdr(result: &mut String, tr: &str) -> bool {
|
fn at_cdr(&mut self, tr: &str) -> bool {
|
||||||
let len = result.len();
|
let len = self.outputter.len();
|
||||||
|
|
||||||
|
if self.outputter.ends_with(" | ") {
|
||||||
|
self.outputter.truncate(len - 3);
|
||||||
|
self.outputter.append(tr);
|
||||||
|
|
||||||
if result.ends_with(" | ") {
|
|
||||||
result.truncate(len - 3);
|
|
||||||
*result += tr;
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print(&mut self) -> String {
|
pub fn print(mut self) -> Outputter {
|
||||||
let mut result = String::new();
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if let Some(loc_data) = self.state_stack.pop() {
|
if let Some(loc_data) = self.state_stack.pop() {
|
||||||
match loc_data {
|
match loc_data {
|
||||||
TokenOrRedirect::Space =>
|
TokenOrRedirect::Space =>
|
||||||
result += " ",
|
self.outputter.append(" "),
|
||||||
TokenOrRedirect::Atom(atom) =>
|
TokenOrRedirect::Atom(atom) =>
|
||||||
result += atom.as_str(),
|
self.outputter.append(atom.as_str()),
|
||||||
TokenOrRedirect::Redirect => {
|
TokenOrRedirect::Redirect => {
|
||||||
let heap_val = self.iter.next().unwrap();
|
let heap_val = self.iter.next().unwrap();
|
||||||
self.handle_heap_term(heap_val, &mut result);
|
self.handle_heap_term(heap_val);
|
||||||
},
|
},
|
||||||
TokenOrRedirect::Close =>
|
TokenOrRedirect::Close =>
|
||||||
result += ")",
|
self.outputter.append(")"),
|
||||||
TokenOrRedirect::Open =>
|
TokenOrRedirect::Open =>
|
||||||
result += "(",
|
self.outputter.append("("),
|
||||||
TokenOrRedirect::OpenList(delimit) =>
|
TokenOrRedirect::OpenList(delimit) =>
|
||||||
if !Self::at_cdr(&mut result, ", ") {
|
if !self.at_cdr(", ") {
|
||||||
result += "[";
|
self.outputter.append("[");
|
||||||
} else {
|
} else {
|
||||||
delimit.set(false);
|
delimit.set(false);
|
||||||
},
|
},
|
||||||
TokenOrRedirect::CloseList(delimit) =>
|
TokenOrRedirect::CloseList(delimit) =>
|
||||||
if delimit.get() == true {
|
if delimit.get() == true {
|
||||||
result += "]";
|
self.outputter.append("]");
|
||||||
},
|
},
|
||||||
TokenOrRedirect::HeadTailSeparator =>
|
TokenOrRedirect::HeadTailSeparator =>
|
||||||
result += " | ",
|
self.outputter.append(" | "),
|
||||||
TokenOrRedirect::Comma =>
|
TokenOrRedirect::Comma =>
|
||||||
result += ", "
|
self.outputter.append(", ")
|
||||||
}
|
}
|
||||||
} else if let Some(heap_val) = self.iter.next() {
|
} else if let Some(heap_val) = self.iter.next() {
|
||||||
self.handle_heap_term(heap_val, &mut result);
|
self.handle_heap_term(heap_val);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
self.outputter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use prolog::ast::*;
|
use prolog::ast::*;
|
||||||
use prolog::codegen::*;
|
use prolog::codegen::*;
|
||||||
use prolog::debray_allocator::*;
|
use prolog::debray_allocator::*;
|
||||||
|
use prolog::heap_print::*;
|
||||||
use prolog::machine::*;
|
use prolog::machine::*;
|
||||||
|
|
||||||
use termion::raw::IntoRawMode;
|
use termion::raw::IntoRawMode;
|
||||||
@@ -440,7 +441,7 @@ pub fn print(wam: &mut Machine, result: EvalSession) {
|
|||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut result = EvalSession::QueryFailure;
|
let mut result = EvalSession::QueryFailure;
|
||||||
let bindings = wam.heap_view(&heap_locs);
|
let bindings = wam.heap_view::<PrinterOutputter>(&heap_locs);
|
||||||
|
|
||||||
let stdin = stdin();
|
let stdin = stdin();
|
||||||
let mut stdout = stdout().into_raw_mode().unwrap();
|
let mut stdout = stdout().into_raw_mode().unwrap();
|
||||||
|
|||||||
@@ -256,25 +256,28 @@ impl MachineState {
|
|||||||
self.trail(r1);
|
self.trail(r1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_var<Fmt>(&self, r: Ref, fmt: Fmt) -> String
|
fn print_var<Fmt, Outputter>(&self, r: Ref, fmt: Fmt, output: Outputter) -> Outputter
|
||||||
where Fmt: HeapCellValueFormatter
|
where Fmt: HeapCellValueFormatter, Outputter: HeapCellValueOutputter
|
||||||
{
|
{
|
||||||
let iter = HeapCellIterator::new(&self, r);
|
let iter = HeapCellIterator::new(&self, r);
|
||||||
let mut printer = HeapCellPrinter::new(iter, fmt);
|
let printer = HeapCellPrinter::new(iter, fmt, output);
|
||||||
|
|
||||||
printer.print()
|
printer.print()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn print_term<Fmt>(&self, addr: &Addr, fmt: Fmt) -> String
|
pub(super) fn print_term<Fmt, Outputter>(&self, addr: &Addr, fmt: Fmt, mut output: Outputter)
|
||||||
where Fmt: HeapCellValueFormatter
|
-> Outputter
|
||||||
|
where Fmt: HeapCellValueFormatter, Outputter: HeapCellValueOutputter
|
||||||
{
|
{
|
||||||
match addr {
|
match addr {
|
||||||
&Addr::Con(ref c) =>
|
&Addr::Con(ref c) => {
|
||||||
format!("{}", c),
|
output.append(format!("{}", c).as_str());
|
||||||
|
output
|
||||||
|
},
|
||||||
&Addr::Lis(h) | &Addr::HeapCell(h) | &Addr::Str(h) =>
|
&Addr::Lis(h) | &Addr::HeapCell(h) | &Addr::Str(h) =>
|
||||||
self.print_var(Ref::HeapCell(h), fmt),
|
self.print_var(Ref::HeapCell(h), fmt, output),
|
||||||
&Addr::StackCell(fr, sc) =>
|
&Addr::StackCell(fr, sc) =>
|
||||||
self.print_var(Ref::StackCell(fr, sc), fmt)
|
self.print_var(Ref::StackCell(fr, sc), fmt, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1520,15 +1523,21 @@ impl MachineState {
|
|||||||
|
|
||||||
self.p += 1;
|
self.p += 1;
|
||||||
},
|
},
|
||||||
&ControlInstruction::DisplayCall => {
|
&ControlInstruction::DisplayCall => {
|
||||||
let result = self.print_term(&self[temp_v!(1)], DisplayFormatter {});
|
let output = self.print_term(&self[temp_v!(1)],
|
||||||
println!("{}", result);
|
DisplayFormatter {},
|
||||||
|
PrinterOutputter::new());
|
||||||
|
|
||||||
|
println!("{}", output.result());
|
||||||
|
|
||||||
self.p += 1;
|
self.p += 1;
|
||||||
},
|
},
|
||||||
&ControlInstruction::DisplayExecute => {
|
&ControlInstruction::DisplayExecute => {
|
||||||
let result = self.print_term(&self[temp_v!(1)], DisplayFormatter {});
|
let output = self.print_term(&self[temp_v!(1)],
|
||||||
println!("{}", result);
|
DisplayFormatter {},
|
||||||
|
PrinterOutputter::new());
|
||||||
|
|
||||||
|
println!("{}", output.result());
|
||||||
|
|
||||||
self.p = self.cp;
|
self.p = self.cp;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -264,7 +264,10 @@ impl Machine {
|
|||||||
let h = self.ms.heap.h;
|
let h = self.ms.heap.h;
|
||||||
self.ms.copy_and_align_ball_to_heap();
|
self.ms.copy_and_align_ball_to_heap();
|
||||||
|
|
||||||
let msg = self.ms.print_term(&Addr::HeapCell(h), TermFormatter {});
|
let msg = self.ms.print_term(&Addr::HeapCell(h),
|
||||||
|
TermFormatter {},
|
||||||
|
PrinterOutputter::new())
|
||||||
|
.result();
|
||||||
|
|
||||||
EvalSession::QueryFailureWithException(msg)
|
EvalSession::QueryFailureWithException(msg)
|
||||||
} else {
|
} else {
|
||||||
@@ -346,21 +349,21 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn heap_view(&self, var_dir: &HeapVarDict) -> String {
|
pub fn heap_view<Outputter>(&self, var_dir: &HeapVarDict) -> Outputter::Output
|
||||||
let mut result = String::new();
|
where Outputter: HeapCellValueOutputter
|
||||||
|
{
|
||||||
|
let mut output = Outputter::new();
|
||||||
|
|
||||||
for (var, addr) in var_dir {
|
for (var, addr) in var_dir {
|
||||||
if result != "" {
|
output.begin_new_var();
|
||||||
result += "\n\r";
|
|
||||||
}
|
|
||||||
|
|
||||||
result += var.as_str();
|
|
||||||
result += " = ";
|
|
||||||
|
|
||||||
result += self.ms.print_term(addr, TermFormatter {}).as_str();
|
output.append(var.as_str());
|
||||||
|
output.append(" = ");
|
||||||
|
|
||||||
|
output = self.ms.print_term(addr, TermFormatter {}, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
output.result()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn or_stack_is_empty(&self) -> bool {
|
pub fn or_stack_is_empty(&self) -> bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user