add write variants

This commit is contained in:
Mark Thom
2018-10-23 22:53:50 -06:00
parent 1e3891204e
commit 32fecca45d
9 changed files with 181 additions and 155 deletions

View File

@@ -172,7 +172,10 @@ The following predicates are built-in to rusty-wam.
* `throw/1` * `throw/1`
* `true/0` * `true/0`
* `var/1` * `var/1`
* `write/1`
* `write_canonical/1`
* `writeq/1` * `writeq/1`
* `write_term/2`
## Tutorial ## Tutorial
To enter a multi-clause predicate, the directive "[user]" is used. To enter a multi-clause predicate, the directive "[user]" is used.

View File

@@ -32,29 +32,6 @@ pub enum TokenOrRedirect {
HeadTailSeparator, 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 { pub trait HCValueOutputter {
type Output; type Output;
@@ -110,9 +87,6 @@ impl HCValueOutputter for PrinterOutputter {
} }
} }
// the 'classic' display corresponding to the display predicate.
pub struct WriteqFormatter {}
#[inline] #[inline]
fn is_numbered_var(ct: &ClauseType, arity: usize) -> bool { fn is_numbered_var(ct: &ClauseType, arity: usize) -> bool {
arity == 1 && if let &ClauseType::Named(ref name, _) = ct { 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>>; type ReverseHeapVarDict<'a> = HashMap<Addr, Rc<Var>>;
pub struct HCPrinter<'a, Formatter, Outputter> { pub struct HCPrinter<'a, Outputter> {
formatter: Formatter,
outputter: Outputter, outputter: Outputter,
machine_st: &'a MachineState, machine_st: &'a MachineState,
state_stack: Vec<TokenOrRedirect>, state_stack: Vec<TokenOrRedirect>,
heap_locs: ReverseHeapVarDict<'a>, 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 { 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> impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
HCPrinter<'a, Formatter, 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, HCPrinter { outputter: output,
outputter: output,
machine_st, machine_st,
state_stack: vec![], state_stack: vec![],
heap_locs: ReverseHeapVarDict::new(), 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, pub fn from_heap_locs(machine_st: &'a MachineState, output: Outputter,
output: Outputter, heap_locs: &'a HeapVarDict) heap_locs: &'a HeapVarDict)
-> Self -> 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.heap_locs = reverse_heap_locs(machine_st, heap_locs);
printer 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> { fn offset_as_string(&self, addr: Addr) -> Option<String> {
match addr { match addr {
Addr::HeapCell(h) | Addr::Lis(h) | Addr::Str(h) => Addr::HeapCell(h) | Addr::Lis(h) | Addr::Str(h) =>
@@ -397,7 +374,7 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
match atom.as_str() { match atom.as_str() {
"" => self.outputter.append("''"), "" => self.outputter.append("''"),
";" | "!" => self.outputter.append(atom.as_str()), ";" | "!" => 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()) self.outputter.append(atom.as_str())
} else { } else {
self.outputter.push_char('\''); self.outputter.push_char('\'');
@@ -424,7 +401,7 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
_ => self.outputter.append(&format!("\\x{:x}", c as u32)) _ => self.outputter.append(&format!("\\x{:x}", c as u32))
}; };
} }
fn print_constant(&mut self, c: Constant, op: &Option<DirectedOp>) { fn print_constant(&mut self, c: Constant, op: &Option<DirectedOp>) {
match c { match c {
Constant::Atom(ref atom, Some(fixity)) => { 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)) => Constant::Char(c) if non_quoted_token(once(c)) =>
self.print_char(c), self.print_char(c),
Constant::Char(c) => { Constant::Char(c) =>
self.outputter.push_char('\''); if self.quoted {
self.print_char(c); self.outputter.push_char('\'');
self.outputter.push_char('\''); self.print_char(c);
}, self.outputter.push_char('\'');
} else {
self.print_char(c);
},
Constant::EmptyList => Constant::EmptyList =>
self.outputter.append("[]"), self.outputter.append("[]"),
Constant::Number(Number::Float(fl)) => Constant::Number(Number::Float(fl)) =>
@@ -519,7 +499,7 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
} }
let ct = ClauseType::from(name.clone(), arity, Some(fixity)); 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() { if op.is_some() {
self.state_stack.push(TokenOrRedirect::Open); self.state_stack.push(TokenOrRedirect::Open);
@@ -528,7 +508,7 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
HeapCellValue::NamedStr(arity, name, fixity) => HeapCellValue::NamedStr(arity, name, fixity) =>
push_space_if_amb!(self, name.as_str(), &op, { push_space_if_amb!(self, name.as_str(), &op, {
let ct = ClauseType::from(name, arity, fixity); 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)) => HeapCellValue::Addr(Addr::Con(Constant::EmptyList)) =>
if !self.at_cdr("") { if !self.at_cdr("") {
@@ -581,17 +561,21 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
TokenOrRedirect::Open => TokenOrRedirect::Open =>
self.outputter.append("("), self.outputter.append("("),
TokenOrRedirect::OpenList(delimit) => 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("["); self.outputter.append("[");
} else { } else {
delimit.set(false); delimit.set(false);
}, },
TokenOrRedirect::CloseList(delimit) => TokenOrRedirect::CloseList(delimit) =>
if delimit.get() { if !self.ignore_ops && delimit.get() {
self.outputter.append("]"); self.outputter.append("]");
}, },
TokenOrRedirect::HeadTailSeparator => TokenOrRedirect::HeadTailSeparator =>
self.outputter.append(" | "), if !self.ignore_ops {
self.outputter.append(" | ");
},
TokenOrRedirect::Comma => TokenOrRedirect::Comma =>
self.outputter.append(", ") self.outputter.append(", ")
} }

View File

@@ -242,7 +242,8 @@ pub enum SystemClauseType {
SkipMaxList, SkipMaxList,
Succeed, Succeed,
TermVariables, TermVariables,
UnwindStack UnwindStack,
WriteTerm
} }
impl SystemClauseType { impl SystemClauseType {
@@ -282,6 +283,7 @@ impl SystemClauseType {
&SystemClauseType::Succeed => clause_name!("$succeed"), &SystemClauseType::Succeed => clause_name!("$succeed"),
&SystemClauseType::TermVariables => clause_name!("$term_variables"), &SystemClauseType::TermVariables => clause_name!("$term_variables"),
&SystemClauseType::UnwindStack => clause_name!("$unwind_stack"), &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), ("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
("$term_variables", 2) => Some(SystemClauseType::TermVariables), ("$term_variables", 2) => Some(SystemClauseType::TermVariables),
("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack), ("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack),
("$write_term", 4) => Some(SystemClauseType::WriteTerm),
_ => None _ => None
} }
} }
@@ -329,7 +332,6 @@ pub enum BuiltInClauseType {
Compare, Compare,
CompareTerm(CompareTermQT), CompareTerm(CompareTermQT),
CyclicTerm, CyclicTerm,
Writeq,
CopyTerm, CopyTerm,
Eq, Eq,
Functor, Functor,
@@ -381,7 +383,6 @@ impl BuiltInClauseType {
&BuiltInClauseType::Compare => clause_name!("compare"), &BuiltInClauseType::Compare => clause_name!("compare"),
&BuiltInClauseType::CompareTerm(qt) => clause_name!(qt.name()), &BuiltInClauseType::CompareTerm(qt) => clause_name!(qt.name()),
&BuiltInClauseType::CyclicTerm => clause_name!("cyclic_term"), &BuiltInClauseType::CyclicTerm => clause_name!("cyclic_term"),
&BuiltInClauseType::Writeq => clause_name!("writeq"),
&BuiltInClauseType::CopyTerm => clause_name!("copy_term"), &BuiltInClauseType::CopyTerm => clause_name!("copy_term"),
&BuiltInClauseType::Eq => clause_name!("=="), &BuiltInClauseType::Eq => clause_name!("=="),
&BuiltInClauseType::Functor => clause_name!("functor"), &BuiltInClauseType::Functor => clause_name!("functor"),
@@ -402,7 +403,6 @@ impl BuiltInClauseType {
&BuiltInClauseType::Compare => 2, &BuiltInClauseType::Compare => 2,
&BuiltInClauseType::CompareTerm(_) => 2, &BuiltInClauseType::CompareTerm(_) => 2,
&BuiltInClauseType::CyclicTerm => 1, &BuiltInClauseType::CyclicTerm => 1,
&BuiltInClauseType::Writeq => 1,
&BuiltInClauseType::CopyTerm => 2, &BuiltInClauseType::CopyTerm => 2,
&BuiltInClauseType::Eq => 2, &BuiltInClauseType::Eq => 2,
&BuiltInClauseType::Functor => 3, &BuiltInClauseType::Functor => 3,
@@ -428,7 +428,6 @@ impl BuiltInClauseType {
("@=<", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::LessThanOrEqual)), ("@=<", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::LessThanOrEqual)),
("\\=@=", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::NotEqual)), ("\\=@=", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::NotEqual)),
("=@=", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::Equal)), ("=@=", 2) => Some(BuiltInClauseType::CompareTerm(CompareTermQT::Equal)),
("writeq", 1) => Some(BuiltInClauseType::Writeq),
("copy_term", 2) => Some(BuiltInClauseType::CopyTerm), ("copy_term", 2) => Some(BuiltInClauseType::CopyTerm),
("==", 2) => Some(BuiltInClauseType::Eq), ("==", 2) => Some(BuiltInClauseType::Eq),
("functor", 3) => Some(BuiltInClauseType::Functor), ("functor", 3) => Some(BuiltInClauseType::Functor),

View File

@@ -7,8 +7,8 @@
(==)/2, (\==)/2, (@=<)/2, (@>=)/2, (@<)/2, (@>)/2, (=@=)/2, (==)/2, (\==)/2, (@=<)/2, (@>=)/2, (@<)/2, (@>)/2, (=@=)/2,
(\=@=)/2, (:)/2, call_with_inference_limit/3, catch/3, (\=@=)/2, (:)/2, call_with_inference_limit/3, catch/3,
current_prolog_flag/2, expand_term/2, set_prolog_flag/2, current_prolog_flag/2, expand_term/2, set_prolog_flag/2,
term_variables/2, setup_call_cleanup/3, term_variables/2, throw/1, true/0, false/0,
setup_call_cleanup/3, 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 /* 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 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'(I1 is I0 + 1),
'$call_with_default_policy'(get_args(Args, Func, I1, N)). '$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.
expand_term(Term0, Term) :- '$expand_term'(Term0, Term). expand_term(Term0, Term) :- '$expand_term'(Term0, Term).

View File

@@ -4,7 +4,6 @@ use prolog_parser::string_list::*;
use prolog::instructions::*; use prolog::instructions::*;
use prolog::and_stack::*; use prolog::and_stack::*;
use prolog::copier::*; use prolog::copier::*;
use prolog::heap_print::*;
use prolog::machine::IndexStore; use prolog::machine::IndexStore;
use prolog::machine::machine_errors::*; use prolog::machine::machine_errors::*;
use prolog::num::{BigInt, BigUint, Zero, One}; 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) 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 => { &BuiltInClauseType::CopyTerm => {
machine_st.duplicate_term(); machine_st.duplicate_term();
return_from_clause!(machine_st.last_call, machine_st) return_from_clause!(machine_st.last_call, machine_st)
@@ -671,7 +662,7 @@ pub(crate) trait CallPolicy: Any {
machine_st.execute_inlined(&inlined), machine_st.execute_inlined(&inlined),
ClauseType::Op(..) | ClauseType::Named(..) => { ClauseType::Op(..) | ClauseType::Named(..) => {
let module = name.owning_module(); let module = name.owning_module();
if let Some(idx) = indices.get_code_index((name.clone(), arity), module) { if let Some(idx) = indices.get_code_index((name.clone(), arity), module) {
self.context_call(machine_st, name, arity, idx, indices)?; self.context_call(machine_st, name, arity, idx, indices)?;
} else { } else {

View File

@@ -119,10 +119,10 @@ impl MachineState {
} }
pub(super) pub(super)
fn print_var_eq<Fmt, Outputter>(&self, var: Rc<Var>, addr: Addr, var_dir: &HeapVarDict, fn print_var_eq<Outputter>(&self, var: Rc<Var>, addr: Addr, var_dir: &HeapVarDict,
fmt: Fmt, mut output: Outputter) mut output: Outputter)
-> Outputter -> Outputter
where Fmt: HCValueFormatter, Outputter: HCValueOutputter where Outputter: HCValueOutputter
{ {
let orig_len = output.len(); let orig_len = output.len();
@@ -131,7 +131,9 @@ impl MachineState {
output.append(var.as_str()); output.append(var.as_str());
output.append(" = "); 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 mut output = printer.print(addr);
let bad_ending = format!("= {}", &var); let bad_ending = format!("= {}", &var);
@@ -144,20 +146,11 @@ impl MachineState {
} }
pub(super) pub(super)
fn print_exception<Fmt, Outputter>(&self, addr: Addr, var_dir: &HeapVarDict, fn print_exception<Outputter>(&self, addr: Addr, var_dir: &HeapVarDict, output: Outputter)
fmt: Fmt, output: Outputter) -> Outputter
-> Outputter where Outputter: HCValueOutputter
where Fmt: HCValueFormatter, Outputter: HCValueOutputter
{ {
let printer = HCPrinter::from_heap_locs(&self, fmt, output, var_dir); let printer = HCPrinter::from_heap_locs(&self, 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);
printer.print(addr) printer.print(addr)
} }

View File

@@ -348,7 +348,6 @@ impl Machine {
let error_str = self.machine_st.print_exception(Addr::HeapCell(h), let error_str = self.machine_st.print_exception(Addr::HeapCell(h),
&heap_locs, &heap_locs,
TermFormatter {},
PrinterOutputter::new()) PrinterOutputter::new())
.result(); .result();
@@ -401,9 +400,8 @@ impl Machine {
let mut sorted_vars: Vec<(&Rc<Var>, &Addr)> = var_dir.iter().collect(); let mut sorted_vars: Vec<(&Rc<Var>, &Addr)> = var_dir.iter().collect();
sorted_vars.sort_by_key(|ref v| v.0); sorted_vars.sort_by_key(|ref v| v.0);
for (var, addr) in sorted_vars { for (var, addr) in sorted_vars {
let fmt = TermFormatter {}; output = self.machine_st.print_var_eq(var.clone(), addr.clone(), var_dir, output);
output = self.machine_st.print_var_eq(var.clone(), addr.clone(), var_dir, fmt, output);
} }
output output

View File

@@ -1,6 +1,7 @@
use prolog_parser::ast::*; use prolog_parser::ast::*;
use prolog::heap_iter::*; use prolog::heap_iter::*;
use prolog::heap_print::*;
use prolog::instructions::*; use prolog::instructions::*;
use prolog::machine::IndexStore; use prolog::machine::IndexStore;
use prolog::machine::machine_errors::*; use prolog::machine::machine_errors::*;
@@ -443,31 +444,31 @@ impl MachineState {
&SystemClauseType::TermVariables => { &SystemClauseType::TermVariables => {
let a1 = self[temp_v!(1)].clone(); let a1 = self[temp_v!(1)].clone();
let mut vars = Vec::new(); let mut vars = Vec::new();
{ {
let iter = HCPreOrderIterator::new(self, a1); let iter = HCPreOrderIterator::new(self, a1);
for item in iter { for item in iter {
match item { match item {
HeapCellValue::Addr(Addr::HeapCell(h)) => HeapCellValue::Addr(Addr::HeapCell(h)) =>
vars.push(Ref::HeapCell(h)), vars.push(Ref::HeapCell(h)),
HeapCellValue::Addr(Addr::StackCell(fr, sc)) => 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 mut h = self.heap.h;
let outcome = Addr::HeapCell(h); let outcome = Addr::HeapCell(h);
let mut seen_vars = HashSet::new(); let mut seen_vars = HashSet::new();
for r in vars { for r in vars {
if seen_vars.contains(&r) { if seen_vars.contains(&r) {
continue; continue;
} }
self.heap.push(HeapCellValue::Addr(Addr::Lis(h+1))); self.heap.push(HeapCellValue::Addr(Addr::Lis(h+1)));
self.heap.push(HeapCellValue::Addr(r.as_addr())); self.heap.push(HeapCellValue::Addr(r.as_addr()));
@@ -481,7 +482,31 @@ impl MachineState {
let a2 = self[temp_v!(2)].clone(); let a2 = self[temp_v!(2)].clone();
self.unify(a2, outcome); 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(); self.set_p();

View File

@@ -124,9 +124,11 @@ impl MachineState {
self.reset(); self.reset();
Ok(None) Ok(None)
} else { } else {
let mut output = self.print_term(Addr::HeapCell(h), let mut output = {
WriteqFormatter {}, let mut printer = HCPrinter::new(&self, PrinterOutputter::new());
PrinterOutputter::new()); printer.print(Addr::HeapCell(h))
};
output.push_char('.'); output.push_char('.');
self.reset(); self.reset();