add write variants
This commit is contained in:
@@ -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.
|
||||||
|
|||||||
@@ -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('\'');
|
||||||
@@ -444,10 +421,13 @@ 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) =>
|
||||||
|
if self.quoted {
|
||||||
self.outputter.push_char('\'');
|
self.outputter.push_char('\'');
|
||||||
self.print_char(c);
|
self.print_char(c);
|
||||||
self.outputter.push_char('\'');
|
self.outputter.push_char('\'');
|
||||||
|
} else {
|
||||||
|
self.print_char(c);
|
||||||
},
|
},
|
||||||
Constant::EmptyList =>
|
Constant::EmptyList =>
|
||||||
self.outputter.append("[]"),
|
self.outputter.append("[]"),
|
||||||
@@ -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(", ")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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).
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 Fmt: HCValueFormatter, Outputter: HCValueOutputter
|
where 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
@@ -402,8 +401,7 @@ impl Machine {
|
|||||||
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
|
||||||
|
|||||||
@@ -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::*;
|
||||||
@@ -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, ..)) = "ed {
|
||||||
|
printer.quoted = name.as_str() == "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut output = printer.print(addr);
|
||||||
|
println!("{}", output.result());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.set_p();
|
self.set_p();
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user