From: Mark Thom Date: Tue, 16 Jan 2018 03:18:08 +0000 (-0700) Subject: abstract Outputter of heap_print X-Git-Tag: v0.8.110~625 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=f265546203161882470b6ca1fa40f94b19263c02;p=scryer-prolog.git abstract Outputter of heap_print --- diff --git a/src/prolog/heap_print.rs b/src/prolog/heap_print.rs index c441436c..e7a6551a 100644 --- a/src/prolog/heap_print.rs +++ b/src/prolog/heap_print.rs @@ -40,6 +40,57 @@ pub trait HeapCellValueFormatter { fn format_clause(&self, usize, Rc, Option, &mut Vec); } +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. pub struct DisplayFormatter {} @@ -51,7 +102,7 @@ impl HeapCellValueFormatter for DisplayFormatter { let mut new_name = String::from("'"); new_name += name.as_ref(); new_name += "'"; - + let name = Rc::new(new_name); self.format_struct(arity, name, state_stack); } else { @@ -92,28 +143,30 @@ impl HeapCellValueFormatter for TermFormatter { } } -pub struct HeapCellPrinter<'a, Formatter> { +pub struct HeapCellPrinter<'a, Formatter, Outputter> { formatter: Formatter, + outputter: Outputter, iter: HeapCellIterator<'a>, state_stack: Vec } -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 { - HeapCellPrinter { formatter, iter, state_stack: vec![] } + pub fn new(iter: HeapCellIterator<'a>, formatter: Formatter, outputter: Outputter) -> Self { + 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 { HeapCellValue::NamedStr(arity, name, fixity) => self.formatter.format_clause(arity, name, fixity, &mut self.state_stack), HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) => - if !Self::at_cdr(result, "") { - *result += "[]"; + if !self.at_cdr("") { + self.outputter.append("[]"); }, HeapCellValue::Addr(Addr::Con(c)) => - *result += format!("{}", c).as_str(), + self.outputter.append(format!("{}", c).as_str()), HeapCellValue::Addr(Addr::Lis(_)) => { 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)); }, HeapCellValue::Addr(Addr::HeapCell(h)) => - *result += format!("_{}", h).as_str(), + self.outputter.append(format!("_{}", h).as_str()), 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(_)) => {} } } - fn at_cdr(result: &mut String, tr: &str) -> bool { - let len = result.len(); + fn at_cdr(&mut self, tr: &str) -> bool { + 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 } else { false } } - pub fn print(&mut self) -> String { - let mut result = String::new(); - + pub fn print(mut self) -> Outputter { loop { if let Some(loc_data) = self.state_stack.pop() { match loc_data { TokenOrRedirect::Space => - result += " ", + self.outputter.append(" "), TokenOrRedirect::Atom(atom) => - result += atom.as_str(), + self.outputter.append(atom.as_str()), TokenOrRedirect::Redirect => { let heap_val = self.iter.next().unwrap(); - self.handle_heap_term(heap_val, &mut result); + self.handle_heap_term(heap_val); }, TokenOrRedirect::Close => - result += ")", + self.outputter.append(")"), TokenOrRedirect::Open => - result += "(", + self.outputter.append("("), TokenOrRedirect::OpenList(delimit) => - if !Self::at_cdr(&mut result, ", ") { - result += "["; + if !self.at_cdr(", ") { + self.outputter.append("["); } else { delimit.set(false); }, TokenOrRedirect::CloseList(delimit) => if delimit.get() == true { - result += "]"; + self.outputter.append("]"); }, TokenOrRedirect::HeadTailSeparator => - result += " | ", + self.outputter.append(" | "), TokenOrRedirect::Comma => - result += ", " + self.outputter.append(", ") } } else if let Some(heap_val) = self.iter.next() { - self.handle_heap_term(heap_val, &mut result); + self.handle_heap_term(heap_val); } else { break; } } - result + self.outputter } } diff --git a/src/prolog/io.rs b/src/prolog/io.rs index 5ff9bb27..5a573f68 100644 --- a/src/prolog/io.rs +++ b/src/prolog/io.rs @@ -1,6 +1,7 @@ use prolog::ast::*; use prolog::codegen::*; use prolog::debray_allocator::*; +use prolog::heap_print::*; use prolog::machine::*; use termion::raw::IntoRawMode; @@ -440,7 +441,7 @@ pub fn print(wam: &mut Machine, result: EvalSession) { loop { let mut result = EvalSession::QueryFailure; - let bindings = wam.heap_view(&heap_locs); + let bindings = wam.heap_view::(&heap_locs); let stdin = stdin(); let mut stdout = stdout().into_raw_mode().unwrap(); diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 53d4c4ee..2f0d0189 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -256,25 +256,28 @@ impl MachineState { self.trail(r1); } - fn print_var(&self, r: Ref, fmt: Fmt) -> String - where Fmt: HeapCellValueFormatter - { - let iter = HeapCellIterator::new(&self, r); - let mut printer = HeapCellPrinter::new(iter, fmt); + fn print_var(&self, r: Ref, fmt: Fmt, output: Outputter) -> Outputter + where Fmt: HeapCellValueFormatter, Outputter: HeapCellValueOutputter + { + let iter = HeapCellIterator::new(&self, r); + let printer = HeapCellPrinter::new(iter, fmt, output); printer.print() } - pub(super) fn print_term(&self, addr: &Addr, fmt: Fmt) -> String - where Fmt: HeapCellValueFormatter + pub(super) fn print_term(&self, addr: &Addr, fmt: Fmt, mut output: Outputter) + -> Outputter + where Fmt: HeapCellValueFormatter, Outputter: HeapCellValueOutputter { match addr { - &Addr::Con(ref c) => - format!("{}", c), + &Addr::Con(ref c) => { + output.append(format!("{}", c).as_str()); + output + }, &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) => - 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; }, - &ControlInstruction::DisplayCall => { - let result = self.print_term(&self[temp_v!(1)], DisplayFormatter {}); - println!("{}", result); + &ControlInstruction::DisplayCall => { + let output = self.print_term(&self[temp_v!(1)], + DisplayFormatter {}, + PrinterOutputter::new()); + + println!("{}", output.result()); self.p += 1; }, - &ControlInstruction::DisplayExecute => { - let result = self.print_term(&self[temp_v!(1)], DisplayFormatter {}); - println!("{}", result); + &ControlInstruction::DisplayExecute => { + let output = self.print_term(&self[temp_v!(1)], + DisplayFormatter {}, + PrinterOutputter::new()); + + println!("{}", output.result()); self.p = self.cp; }, diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 0562ef45..9a260a82 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -264,7 +264,10 @@ impl Machine { let h = self.ms.heap.h; 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) } else { @@ -346,21 +349,21 @@ impl Machine { } } - pub fn heap_view(&self, var_dir: &HeapVarDict) -> String { - let mut result = String::new(); - + pub fn heap_view(&self, var_dir: &HeapVarDict) -> Outputter::Output + where Outputter: HeapCellValueOutputter + { + let mut output = Outputter::new(); + for (var, addr) in var_dir { - if result != "" { - result += "\n\r"; - } - - result += var.as_str(); - result += " = "; + output.begin_new_var(); + + output.append(var.as_str()); + output.append(" = "); - result += self.ms.print_term(addr, TermFormatter {}).as_str(); + output = self.ms.print_term(addr, TermFormatter {}, output); } - result + output.result() } pub fn or_stack_is_empty(&self) -> bool {