]> Repositorios git - scryer-prolog.git/commitdiff
abstract Outputter of heap_print
authorMark Thom <[email protected]>
Tue, 16 Jan 2018 03:18:08 +0000 (20:18 -0700)
committerMark Thom <[email protected]>
Tue, 16 Jan 2018 03:18:08 +0000 (20:18 -0700)
src/prolog/heap_print.rs
src/prolog/io.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/mod.rs

index c441436cc769d1a44c3e2fbbe55aaa55f73a8222..e7a6551a184917a91ba4348159866e66743f4e93 100644 (file)
@@ -40,6 +40,57 @@ pub trait HeapCellValueFormatter {
     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.
 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<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 {
-        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
     }
 }
index 5ff9bb27f86933a554864ea42fbe262c1cee23fb..5a573f68d0c161c848f28c1403038164ddaded56 100644 (file)
@@ -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::<PrinterOutputter>(&heap_locs);
 
                 let stdin  = stdin();
                 let mut stdout = stdout().into_raw_mode().unwrap();
index 53d4c4eefd5612e704bd6150031422bcb63d22ef..2f0d0189b838102656de8dccca21746838d93b41 100644 (file)
@@ -256,25 +256,28 @@ impl MachineState {
         self.trail(r1);
     }
     
-    fn print_var<Fmt>(&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<Fmt, Outputter>(&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<Fmt>(&self, addr: &Addr, fmt: Fmt) -> String
-        where Fmt: HeapCellValueFormatter
+    pub(super) fn print_term<Fmt, Outputter>(&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;
             },
index 0562ef45b4049ed10f67da8851878d39ba348b4b..9a260a8269fe72b268dbc486d14ca4dd21cfa5d6 100644 (file)
@@ -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<Outputter>(&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 {