]> Repositorios git - scryer-prolog.git/commitdiff
add write variants
authorMark Thom <[email protected]>
Wed, 24 Oct 2018 04:53:50 +0000 (22:53 -0600)
committerMark Thom <[email protected]>
Wed, 24 Oct 2018 04:53:50 +0000 (22:53 -0600)
README.md
src/prolog/heap_print.rs
src/prolog/instructions.rs
src/prolog/lib/builtins.pl
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/mod.rs
src/prolog/machine/system_calls.rs
src/prolog/machine/term_expansion.rs

index c62fbf7fffdd724e0fd1b1d0daccdae44c121729..65d0099c225ace09d1ea81611531dd510b74a0e5 100644 (file)
--- a/README.md
+++ b/README.md
@@ -172,7 +172,10 @@ The following predicates are built-in to rusty-wam.
 * `throw/1`
 * `true/0`
 * `var/1`
+* `write/1`
+* `write_canonical/1`
 * `writeq/1`
+* `write_term/2`
 
 ## Tutorial
 To enter a multi-clause predicate, the directive "[user]" is used.
index 0b83b406c8e62a5937fee553a60b1131467fcbef..69ae852be8f294fa2c6d8158cc1b3af08276db28 100644 (file)
@@ -32,29 +32,6 @@ pub enum TokenOrRedirect {
     HeadTailSeparator,
 }
 
-pub trait HCValueFormatter {
-    // this function belongs to the display predicate formatter, which it uses
-    // to format all clauses.
-    fn format_struct(&self, arity: usize, name: ClauseName, 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));
-    }
-
-    // this can be overloaded to handle special cases, falling back on the default of
-    // format_struct when convenient.
-    fn format_clause(&self, &mut HCPreOrderIterator, usize, ClauseType, &mut Vec<TokenOrRedirect>);
-}
-
 pub trait HCValueOutputter {
     type Output;
 
@@ -110,9 +87,6 @@ impl HCValueOutputter for PrinterOutputter {
     }
 }
 
-// the 'classic' display corresponding to the display predicate.
-pub struct WriteqFormatter {}
-
 #[inline]
 fn is_numbered_var(ct: &ClauseType, arity: usize) -> bool {
     arity == 1 && if let &ClauseType::Named(ref name, _) = ct {
@@ -145,68 +119,17 @@ impl MachineState {
     }
 }
 
-fn print_op(ct: ClauseType, fixity: Fixity, state_stack: &mut Vec<TokenOrRedirect>) {
-    match fixity {
-        Fixity::Post => {
-            state_stack.push(TokenOrRedirect::Op(ct.name(), fixity));
-            state_stack.push(TokenOrRedirect::CompositeRedirect(DirectedOp::Right(ct.name())));
-        },
-        Fixity::Pre => {
-            state_stack.push(TokenOrRedirect::CompositeRedirect(DirectedOp::Left(ct.name())));
-            state_stack.push(TokenOrRedirect::Op(ct.name(), fixity));
-        },
-        Fixity::In => {
-            state_stack.push(TokenOrRedirect::CompositeRedirect(DirectedOp::Left(ct.name())));
-            state_stack.push(TokenOrRedirect::Op(ct.name(), fixity));
-            state_stack.push(TokenOrRedirect::CompositeRedirect(DirectedOp::Right(ct.name())));
-        }
-    }
-}
-
-impl HCValueFormatter for WriteqFormatter {
-    fn format_clause(&self, iter: &mut HCPreOrderIterator, arity: usize,
-                     ct: ClauseType, state_stack: &mut Vec<TokenOrRedirect>)
-    {
-        if let Some(fixity) = ct.fixity() {
-            return print_op(ct, fixity, state_stack);
-        } else if is_numbered_var(&ct, arity) {
-            let addr = iter.stack().last().cloned().unwrap();
-
-            // 7.10.4
-            if let Some(var) = iter.machine_st.numbervar(addr) {
-                iter.stack().pop();
-                state_stack.push(TokenOrRedirect::NumberedVar(var));
-                return;
-            }
-        }
-
-        self.format_struct(arity, ct.name(), state_stack);
-    }
-}
-
-pub struct TermFormatter {}
-
-impl HCValueFormatter for TermFormatter {
-    fn format_clause(&self, _: &mut HCPreOrderIterator, arity: usize, ct: ClauseType,
-                     state_stack: &mut Vec<TokenOrRedirect>)
-    {
-        if let Some(fixity) = ct.fixity() {
-            print_op(ct, fixity, state_stack);
-        } else {
-            self.format_struct(arity, ct.name(), state_stack);
-        }
-    }
-}
-
 type ReverseHeapVarDict<'a> = HashMap<Addr, Rc<Var>>;
 
-pub struct HCPrinter<'a, Formatter, Outputter> {
-    formatter:    Formatter,
+pub struct HCPrinter<'a, Outputter> {
     outputter:    Outputter,
     machine_st:   &'a MachineState,
     state_stack:  Vec<TokenOrRedirect>,
     heap_locs:    ReverseHeapVarDict<'a>,
-    printed_vars: HashSet<Addr>
+    printed_vars: HashSet<Addr>,
+    pub(crate) numbervars:   bool,
+    pub(crate) quoted:       bool,
+    pub(crate) ignore_ops:   bool
 }
 
 macro_rules! push_space_if_amb {
@@ -315,29 +238,83 @@ fn ambiguity_check(atom: &str, op: &Option<DirectedOp>) -> Option<DirectedOp>
     }
 }
 
-impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
-    HCPrinter<'a, Formatter, Outputter>
+impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
 {
-    pub fn new(machine_st: &'a MachineState, fmt: Formatter, output: Outputter) -> Self
+    pub fn new(machine_st: &'a MachineState, output: Outputter) -> Self
     {
-        HCPrinter { formatter: fmt,
-                    outputter: output,
+        HCPrinter { outputter: output,
                     machine_st,
                     state_stack: vec![],
                     heap_locs: ReverseHeapVarDict::new(),
-                    printed_vars: HashSet::new() }
+                    printed_vars: HashSet::new(),
+                    numbervars: true,
+                    quoted: true,
+                    ignore_ops: false }
     }
 
-    pub fn from_heap_locs(machine_st: &'a MachineState, fmt: Formatter,
-                          output: Outputter, heap_locs: &'a HeapVarDict)
+    pub fn from_heap_locs(machine_st: &'a MachineState, output: Outputter,
+                          heap_locs: &'a HeapVarDict)
                           -> Self
     {
-        let mut printer = Self::new(machine_st, fmt, output);
+        let mut printer = Self::new(machine_st, output);
 
         printer.heap_locs = reverse_heap_locs(machine_st, heap_locs);
         printer
     }
 
+    fn enqueue_op(&mut self, ct: ClauseType, fixity: Fixity) {
+        match fixity {
+            Fixity::Post => {
+                self.state_stack.push(TokenOrRedirect::Op(ct.name(), fixity));
+                self.state_stack.push(TokenOrRedirect::CompositeRedirect(DirectedOp::Right(ct.name())));
+            },
+            Fixity::Pre => {
+                self.state_stack.push(TokenOrRedirect::CompositeRedirect(DirectedOp::Left(ct.name())));
+                self.state_stack.push(TokenOrRedirect::Op(ct.name(), fixity));
+            },
+            Fixity::In => {
+                self.state_stack.push(TokenOrRedirect::CompositeRedirect(DirectedOp::Left(ct.name())));
+                self.state_stack.push(TokenOrRedirect::Op(ct.name(), fixity));
+                self.state_stack.push(TokenOrRedirect::CompositeRedirect(DirectedOp::Right(ct.name())));
+            }
+        }
+    }
+
+    fn format_struct(&mut self, arity: usize, name: ClauseName)
+    {
+        self.state_stack.push(TokenOrRedirect::Close);
+
+        for _ in 0 .. arity {
+            self.state_stack.push(TokenOrRedirect::Redirect);
+            self.state_stack.push(TokenOrRedirect::Comma);
+        }
+
+        self.state_stack.pop();
+        self.state_stack.push(TokenOrRedirect::Open);
+
+        self.state_stack.push(TokenOrRedirect::Atom(name));
+    }
+
+    fn format_clause(&mut self, iter: &mut HCPreOrderIterator, arity: usize, ct: ClauseType)
+    {
+        if let Some(fixity) = ct.fixity() {
+            if !self.ignore_ops {
+                return self.enqueue_op(ct, fixity);
+            }
+        } else if self.numbervars && is_numbered_var(&ct, arity) {
+            let addr = iter.stack().last().cloned().unwrap();
+
+            // 7.10.4
+            if let Some(var) = iter.machine_st.numbervar(addr) {
+                iter.stack().pop();
+                self.state_stack.push(TokenOrRedirect::NumberedVar(var));
+                return;
+            }
+        }
+
+        self.format_struct(arity, ct.name());
+    }
+
     fn offset_as_string(&self, addr: Addr) -> Option<String> {
         match addr {
             Addr::HeapCell(h) | Addr::Lis(h) | Addr::Str(h) =>
@@ -397,7 +374,7 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
         match atom.as_str() {
             "" => self.outputter.append("''"),
             ";" | "!" => self.outputter.append(atom.as_str()),
-            s => if fixity.is_some() || non_quoted_token(s.chars()) {
+            s => if fixity.is_some() || !self.quoted || non_quoted_token(s.chars()) {
                 self.outputter.append(atom.as_str())
             } else {
                 self.outputter.push_char('\'');
@@ -424,7 +401,7 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
             _ => self.outputter.append(&format!("\\x{:x}", c as u32))
         };
     }
-    
+
     fn print_constant(&mut self, c: Constant, op: &Option<DirectedOp>) {
         match c {
             Constant::Atom(ref atom, Some(fixity)) => {
@@ -444,11 +421,14 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
                 }),
             Constant::Char(c) if non_quoted_token(once(c)) =>
                 self.print_char(c),
-            Constant::Char(c) => {
-                self.outputter.push_char('\'');
-                self.print_char(c);
-                self.outputter.push_char('\'');
-            },
+            Constant::Char(c) =>
+                if self.quoted {
+                    self.outputter.push_char('\'');
+                    self.print_char(c);
+                    self.outputter.push_char('\'');
+                } else {
+                    self.print_char(c);
+                },
             Constant::EmptyList =>
                 self.outputter.append("[]"),
             Constant::Number(Number::Float(fl)) =>
@@ -519,7 +499,7 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
                 }
 
                 let ct = ClauseType::from(name.clone(), arity, Some(fixity));
-                self.formatter.format_clause(iter, arity, ct, &mut self.state_stack);
+                self.format_clause(iter, arity, ct);
 
                 if op.is_some() {
                     self.state_stack.push(TokenOrRedirect::Open);
@@ -528,7 +508,7 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
             HeapCellValue::NamedStr(arity, name, fixity) =>
                 push_space_if_amb!(self, name.as_str(), &op, {
                     let ct = ClauseType::from(name, arity, fixity);
-                    self.formatter.format_clause(iter, arity, ct, &mut self.state_stack)
+                    self.format_clause(iter, arity, ct);
                 }),
             HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) =>
                 if !self.at_cdr("") {
@@ -581,17 +561,21 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
                     TokenOrRedirect::Open =>
                         self.outputter.append("("),
                     TokenOrRedirect::OpenList(delimit) =>
-                        if !self.at_cdr(", ") {
+                        if self.ignore_ops {
+                            self.format_struct(2, clause_name!("."));
+                        } else if !self.at_cdr(", ") {
                             self.outputter.append("[");
                         } else {
                             delimit.set(false);
                         },
                     TokenOrRedirect::CloseList(delimit) =>
-                        if delimit.get() {
+                        if !self.ignore_ops && delimit.get() {
                             self.outputter.append("]");
                         },
                     TokenOrRedirect::HeadTailSeparator =>
-                        self.outputter.append(" | "),
+                        if !self.ignore_ops {
+                            self.outputter.append(" | ");
+                        },
                     TokenOrRedirect::Comma =>
                         self.outputter.append(", ")
                 }
index 0a7723e46b055971f253780db0af1d3a618d0094..50437ccace3afdb4427424d209fd079abe9705ca 100644 (file)
@@ -242,7 +242,8 @@ pub enum SystemClauseType {
     SkipMaxList,
     Succeed,
     TermVariables,
-    UnwindStack
+    UnwindStack,
+    WriteTerm
 }
 
 impl SystemClauseType {
@@ -282,6 +283,7 @@ impl SystemClauseType {
             &SystemClauseType::Succeed => clause_name!("$succeed"),
             &SystemClauseType::TermVariables => clause_name!("$term_variables"),
             &SystemClauseType::UnwindStack => clause_name!("$unwind_stack"),
+            &SystemClauseType::WriteTerm => clause_name!("$write_term"),
         }
     }
 
@@ -317,6 +319,7 @@ impl SystemClauseType {
             ("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
             ("$term_variables", 2) => Some(SystemClauseType::TermVariables),
             ("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack),
+            ("$write_term", 4) => Some(SystemClauseType::WriteTerm),
             _ => None
         }
     }
@@ -329,7 +332,6 @@ pub enum BuiltInClauseType {
     Compare,
     CompareTerm(CompareTermQT),
     CyclicTerm,
-    Writeq,
     CopyTerm,
     Eq,
     Functor,
@@ -381,7 +383,6 @@ impl BuiltInClauseType {
             &BuiltInClauseType::Compare => clause_name!("compare"),
             &BuiltInClauseType::CompareTerm(qt) => clause_name!(qt.name()),
             &BuiltInClauseType::CyclicTerm => clause_name!("cyclic_term"),
-            &BuiltInClauseType::Writeq => clause_name!("writeq"),
             &BuiltInClauseType::CopyTerm => clause_name!("copy_term"),
             &BuiltInClauseType::Eq => clause_name!("=="),
             &BuiltInClauseType::Functor => clause_name!("functor"),
@@ -402,7 +403,6 @@ impl BuiltInClauseType {
             &BuiltInClauseType::Compare => 2,
             &BuiltInClauseType::CompareTerm(_) => 2,
             &BuiltInClauseType::CyclicTerm => 1,
-            &BuiltInClauseType::Writeq => 1,
             &BuiltInClauseType::CopyTerm => 2,
             &BuiltInClauseType::Eq => 2,
             &BuiltInClauseType::Functor => 3,
@@ -428,7 +428,6 @@ impl BuiltInClauseType {
             ("@=<", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::LessThanOrEqual)),
             ("\\=@=", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::NotEqual)),
             ("=@=", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::Equal)),
-            ("writeq", 1) => Some(BuiltInClauseType::Writeq),
             ("copy_term", 2) => Some(BuiltInClauseType::CopyTerm),
             ("==", 2) => Some(BuiltInClauseType::Eq),
             ("functor", 3) => Some(BuiltInClauseType::Functor),
index 9ec86330adffe24a0c9bea3260b25c5e924e2b89..e6cfa3fba89dcc91c578159c64186c9dda474ae7 100644 (file)
@@ -7,8 +7,8 @@
        (==)/2, (\==)/2, (@=<)/2, (@>=)/2, (@<)/2, (@>)/2, (=@=)/2,
        (\=@=)/2, (:)/2, call_with_inference_limit/3, catch/3,
        current_prolog_flag/2, expand_term/2, set_prolog_flag/2,
-       term_variables/2,
-       setup_call_cleanup/3, throw/1, true/0, false/0]).
+       setup_call_cleanup/3, term_variables/2, throw/1, true/0, false/0,
+       write/1, write_canonical/1, writeq/1, write_term/2]).
 
 /* this is an implementation specific declarative operator used to implement call_with_inference_limit/3
    and setup_call_cleanup/3. switches to the default trust_me and retry_me_else. Indexing choice
@@ -206,6 +206,37 @@ get_args([Arg|Args], Func, I0, N) :-
     '$call_with_default_policy'(I1 is I0 + 1),
     '$call_with_default_policy'(get_args(Args, Func, I1, N)).
 
+% write, write_canonical, writeq, write_term.
+is_write_option(Functor) :-
+    Functor =.. [Name, Arg | Args],
+    ( Args == [], Arg == true -> true
+    ; Args == [], Arg == false -> true
+    ; throw(error(domain_error(write_option, Functor), write_term/2)) ), % 8.14.2.3 e)
+    ( Name == ignore_ops -> true
+    ; Name == quoted -> true
+    ; Name == numbervars -> true
+    ; throw(error(domain_error(write_option, Functor), write_term/2)) ). % 8.14.2.3 e)
+
+inst_member_or([X|Xs], Y, _) :-
+    ( nonvar(X), is_write_option(X) -> ( Y = X, ! ; inst_member_or(Xs, Y, _) )
+    ; throw(instantiation_error) ). % 8.14.2.3 b)
+inst_member_or([], Y, Y).
+
+write_term(Term, Options) :-
+    '$skip_max_list'(_, -1, Options, Options0),
+    ( Options0 == [] -> true
+    ; throw(error(type_error(list, Options), write_term/2)) ), % 8.14.2.3 c)
+    inst_member_or(Options, ignore_ops(IgnoreOps), ignore_ops(false)),
+    inst_member_or(Options, numbervars(NumberVars), numbervars(false)),
+    inst_member_or(Options, quoted(Quoted), quoted(false)),
+    '$write_term'(Term, IgnoreOps, NumberVars, Quoted).
+
+write(Term) :- write_term(Term, [numbervars(true)]).
+
+write_canonical(Term) :- write_term(Term, [ignore_ops(true), quoted(true)]).
+
+writeq(Term) :- write_term(Term, [quoted(true), numbervars(true)]).
+
 % expand_term.
 
 expand_term(Term0, Term) :- '$expand_term'(Term0, Term).
index a01fd6d94b94fac32521f98c5c1e67d15ddf890f..5c478c164cf8c6aeab882c4ea987876dda7e1684 100644 (file)
@@ -4,7 +4,6 @@ use prolog_parser::string_list::*;
 use prolog::instructions::*;
 use prolog::and_stack::*;
 use prolog::copier::*;
-use prolog::heap_print::*;
 use prolog::machine::IndexStore;
 use prolog::machine::machine_errors::*;
 use prolog::num::{BigInt, BigUint, Zero, One};
@@ -541,14 +540,6 @@ pub(crate) trait CallPolicy: Any {
 
                 return_from_clause!(machine_st.last_call, machine_st)
             },
-            &BuiltInClauseType::Writeq => {
-                let output = machine_st.print_term(machine_st[temp_v!(1)].clone(),
-                                                   WriteqFormatter {},
-                                                   PrinterOutputter::new());
-
-                println!("{}", output.result());
-                return_from_clause!(machine_st.last_call, machine_st)
-            },
             &BuiltInClauseType::CopyTerm => {
                 machine_st.duplicate_term();
                 return_from_clause!(machine_st.last_call, machine_st)
@@ -671,7 +662,7 @@ pub(crate) trait CallPolicy: Any {
                     machine_st.execute_inlined(&inlined),
                 ClauseType::Op(..) | ClauseType::Named(..) => {
                     let module = name.owning_module();
-                    
+
                     if let Some(idx) = indices.get_code_index((name.clone(), arity), module) {
                         self.context_call(machine_st, name, arity, idx, indices)?;
                     } else {
index 9465b3ab432d1f1f56cc0ab5be44e580b3cfe6d6..9d2beb5e29b16f6f5b5f004b03d8c08955488a19 100644 (file)
@@ -119,10 +119,10 @@ impl MachineState {
     }
 
     pub(super)
-    fn print_var_eq<Fmt, Outputter>(&self, var: Rc<Var>, addr: Addr, var_dir: &HeapVarDict,
-                                    fmt: Fmt, mut output: Outputter)
-                                    -> Outputter
-      where Fmt: HCValueFormatter, Outputter: HCValueOutputter
+    fn print_var_eq<Outputter>(&self, var: Rc<Var>, addr: Addr, var_dir: &HeapVarDict,
+                               mut output: Outputter)
+                               -> Outputter
+      where Outputter: HCValueOutputter
     {
         let orig_len = output.len();
 
@@ -131,7 +131,9 @@ impl MachineState {
         output.append(var.as_str());
         output.append(" = ");
 
-        let printer    = HCPrinter::from_heap_locs(&self, fmt, output, var_dir);
+        let mut printer = HCPrinter::from_heap_locs(&self, output, var_dir);
+        printer.numbervars = false;
+            
         let mut output = printer.print(addr);
 
         let bad_ending = format!("= {}", &var);
@@ -144,20 +146,11 @@ impl MachineState {
     }
 
     pub(super)
-    fn print_exception<Fmt, Outputter>(&self, addr: Addr, var_dir: &HeapVarDict,
-                                       fmt: Fmt, output: Outputter)
-                                       -> Outputter
-      where Fmt: HCValueFormatter, Outputter: HCValueOutputter
+    fn print_exception<Outputter>(&self, addr: Addr, var_dir: &HeapVarDict, output: Outputter)
+                                  -> Outputter
+        where Outputter: HCValueOutputter
     {
-        let printer = HCPrinter::from_heap_locs(&self, fmt, output, var_dir);
-        printer.print(addr)
-    }
-
-    pub(super)
-    fn print_term<Fmt, Outputter>(&self, addr: Addr, fmt: Fmt, output: Outputter) -> Outputter
-      where Fmt: HCValueFormatter, Outputter: HCValueOutputter
-    {
-        let printer = HCPrinter::new(&self, fmt, output);
+        let printer = HCPrinter::from_heap_locs(&self, output, var_dir);
         printer.print(addr)
     }
 
index 0370a58be6aadf75ed140843898df1b4caba5bb9..36df581911b5a2f99592af38194db427d8a34712 100644 (file)
@@ -348,7 +348,6 @@ impl Machine {
 
             let error_str = self.machine_st.print_exception(Addr::HeapCell(h),
                                                             &heap_locs,
-                                                            TermFormatter {},
                                                             PrinterOutputter::new())
                                 .result();
 
@@ -401,9 +400,8 @@ impl Machine {
         let mut sorted_vars: Vec<(&Rc<Var>, &Addr)> = var_dir.iter().collect();
         sorted_vars.sort_by_key(|ref v| v.0);
 
-        for (var, addr) in sorted_vars {
-            let fmt = TermFormatter {};
-            output = self.machine_st.print_var_eq(var.clone(), addr.clone(), var_dir, fmt, output);
+        for (var, addr) in sorted_vars {            
+            output = self.machine_st.print_var_eq(var.clone(), addr.clone(), var_dir, output);
         }
 
         output
index a86835b65bfc88896e80b19ee7d0000c180a09bc..0616d769bf2022a98f6c48e3606883bc0bcf4e20 100644 (file)
@@ -1,6 +1,7 @@
 use prolog_parser::ast::*;
 
 use prolog::heap_iter::*;
+use prolog::heap_print::*;
 use prolog::instructions::*;
 use prolog::machine::IndexStore;
 use prolog::machine::machine_errors::*;
@@ -443,31 +444,31 @@ impl MachineState {
             &SystemClauseType::TermVariables => {
                 let a1 = self[temp_v!(1)].clone();
                 let mut vars = Vec::new();
-                
+
                 {
-                    let iter = HCPreOrderIterator::new(self, a1);                    
-                    
+                    let iter = HCPreOrderIterator::new(self, a1);
+
                     for item in iter {
-                        match item {                        
+                        match item {
                             HeapCellValue::Addr(Addr::HeapCell(h)) =>
-                                vars.push(Ref::HeapCell(h)),                            
+                                vars.push(Ref::HeapCell(h)),
                             HeapCellValue::Addr(Addr::StackCell(fr, sc)) =>
-                                vars.push(Ref::StackCell(fr, sc)),                            
+                                vars.push(Ref::StackCell(fr, sc)),
                             _ => {}
                         }
                     }
                 }
-                
+
                 let mut h = self.heap.h;
                 let outcome = Addr::HeapCell(h);
 
                 let mut seen_vars = HashSet::new();
-                
+
                 for r in vars {
                     if seen_vars.contains(&r) {
                         continue;
                     }
-                    
+
                     self.heap.push(HeapCellValue::Addr(Addr::Lis(h+1)));
                     self.heap.push(HeapCellValue::Addr(r.as_addr()));
 
@@ -481,7 +482,31 @@ impl MachineState {
                 let a2 = self[temp_v!(2)].clone();
                 self.unify(a2, outcome);
             },
-            &SystemClauseType::UnwindStack => self.unwind_stack()
+            &SystemClauseType::UnwindStack => self.unwind_stack(),
+            &SystemClauseType::WriteTerm => {
+                let addr = self[temp_v!(1)].clone();
+
+                let ignore_ops = self[temp_v!(2)].clone();
+                let numbervars = self[temp_v!(3)].clone();
+                let quoted = self[temp_v!(4)].clone();
+
+                let mut printer = HCPrinter::new(&self, PrinterOutputter::new());
+
+                if let &Addr::Con(Constant::Atom(ref name, ..)) = &ignore_ops {
+                    printer.ignore_ops = name.as_str() == "true";
+                }
+
+                if let &Addr::Con(Constant::Atom(ref name, ..)) = &numbervars {
+                    printer.numbervars = name.as_str() == "true";
+                }
+
+                if let &Addr::Con(Constant::Atom(ref name, ..)) = &quoted {
+                    printer.quoted = name.as_str() == "true";
+                }
+
+                let mut output  = printer.print(addr);
+                println!("{}", output.result());
+            }
         };
 
         self.set_p();
index eb1e9be422d60f69f035e662f2751ceaf6f49529..e815711ae08424d307331267a875424b1a821231 100644 (file)
@@ -124,9 +124,11 @@ impl MachineState {
             self.reset();
             Ok(None)
         } else {
-            let mut output = self.print_term(Addr::HeapCell(h),
-                                             WriteqFormatter {},
-                                             PrinterOutputter::new());
+            let mut output  = {
+                let mut printer = HCPrinter::new(&self, PrinterOutputter::new());
+                printer.print(Addr::HeapCell(h))
+            };
+
             output.push_char('.');
 
             self.reset();