add provisional max_depth option to write_term, speed printing of non-cyclic terms
This commit is contained in:
@@ -29,3 +29,6 @@ prolog_parser = { version = "0.8.47", default-features = false }
|
|||||||
ref_thread_local = "0.0.0"
|
ref_thread_local = "0.0.0"
|
||||||
rug = { version = "1.4.0", optional = true }
|
rug = { version = "1.4.0", optional = true }
|
||||||
rustyline = "6.0.0"
|
rustyline = "6.0.0"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
debug = true
|
||||||
@@ -535,7 +535,7 @@ impl SystemClauseType {
|
|||||||
("$use_qualified_module_from_file", 2) =>
|
("$use_qualified_module_from_file", 2) =>
|
||||||
Some(SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile)),
|
Some(SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile)),
|
||||||
("$variant", 2) => Some(SystemClauseType::Variant),
|
("$variant", 2) => Some(SystemClauseType::Variant),
|
||||||
("$write_term", 5) => Some(SystemClauseType::WriteTerm),
|
("$write_term", 6) => Some(SystemClauseType::WriteTerm),
|
||||||
("$wam_instructions", 3) => Some(SystemClauseType::WAMInstructions),
|
("$wam_instructions", 3) => Some(SystemClauseType::WAMInstructions),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,21 +159,21 @@ fn char_to_string(is_quoted: bool, c: char) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum TokenOrRedirect {
|
enum TokenOrRedirect {
|
||||||
Atom(ClauseName),
|
Atom(ClauseName),
|
||||||
BarAsOp,
|
BarAsOp,
|
||||||
Op(ClauseName, SharedOpDesc),
|
Op(ClauseName, SharedOpDesc),
|
||||||
NumberedVar(String),
|
NumberedVar(String),
|
||||||
CompositeRedirect(DirectedOp),
|
CompositeRedirect(usize, DirectedOp),
|
||||||
FunctorRedirect,
|
FunctorRedirect(usize),
|
||||||
Open,
|
Open,
|
||||||
Close,
|
Close,
|
||||||
Comma,
|
Comma,
|
||||||
Space,
|
Space,
|
||||||
LeftCurly,
|
LeftCurly,
|
||||||
RightCurly,
|
RightCurly,
|
||||||
OpenList(Rc<Cell<bool>>),
|
OpenList(Rc<Cell<(bool, usize)>>),
|
||||||
CloseList(Rc<Cell<bool>>),
|
CloseList(Rc<Cell<(bool, usize)>>),
|
||||||
HeadTailSeparator,
|
HeadTailSeparator,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,12 +315,14 @@ pub struct HCPrinter<'a, Outputter> {
|
|||||||
printed_vars: IndexSet<Addr>,
|
printed_vars: IndexSet<Addr>,
|
||||||
last_item_idx: usize,
|
last_item_idx: usize,
|
||||||
cyclic_terms: IndexMap<Addr, usize>,
|
cyclic_terms: IndexMap<Addr, usize>,
|
||||||
|
non_cyclic_terms: IndexSet<usize>,
|
||||||
pub(crate) var_names: IndexMap<Addr, Var>,
|
pub(crate) var_names: IndexMap<Addr, Var>,
|
||||||
pub(crate) numbervars_offset: Integer,
|
pub(crate) numbervars_offset: Integer,
|
||||||
pub(crate) numbervars: bool,
|
pub(crate) numbervars: bool,
|
||||||
pub(crate) quoted: bool,
|
pub(crate) quoted: bool,
|
||||||
pub(crate) ignore_ops: bool,
|
pub(crate) ignore_ops: bool,
|
||||||
pub(crate) print_strings_as_strs: bool,
|
pub(crate) print_strings_as_strs: bool,
|
||||||
|
pub(crate) max_depth: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! push_space_if_amb {
|
macro_rules! push_space_if_amb {
|
||||||
@@ -430,6 +432,18 @@ fn non_quoted_token<Iter: Iterator<Item = char>>(mut iter: Iter) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn functor_location(addr: &Addr) -> Option<usize> {
|
||||||
|
Some(match addr {
|
||||||
|
&Addr::Lis(l) => l,
|
||||||
|
&Addr::Str(s) => s,
|
||||||
|
&Addr::PStrLocation(h, _) | &Addr::PStrTail(h, _) => h,
|
||||||
|
_ => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||||
pub fn new(machine_st: &'a MachineState, op_dir: &'a OpDir, output: Outputter) -> Self {
|
pub fn new(machine_st: &'a MachineState, op_dir: &'a OpDir, output: Outputter) -> Self {
|
||||||
HCPrinter {
|
HCPrinter {
|
||||||
@@ -446,8 +460,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
quoted: false,
|
quoted: false,
|
||||||
ignore_ops: false,
|
ignore_ops: false,
|
||||||
cyclic_terms: IndexMap::new(),
|
cyclic_terms: IndexMap::new(),
|
||||||
|
non_cyclic_terms: IndexSet::new(),
|
||||||
var_names: IndexMap::new(),
|
var_names: IndexMap::new(),
|
||||||
print_strings_as_strs: false,
|
print_strings_as_strs: false,
|
||||||
|
max_depth: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,53 +501,110 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
requires_space(tail, atom)
|
requires_space(tail, atom)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enqueue_op(&mut self, ct: ClauseType, spec: SharedOpDesc) {
|
fn enqueue_op(
|
||||||
|
&mut self,
|
||||||
|
iter: &mut HCPreOrderIterator,
|
||||||
|
mut max_depth: usize,
|
||||||
|
ct: ClauseType,
|
||||||
|
spec: SharedOpDesc,
|
||||||
|
) {
|
||||||
if is_postfix!(spec.assoc()) {
|
if is_postfix!(spec.assoc()) {
|
||||||
|
if self.check_max_depth(&mut max_depth) {
|
||||||
|
iter.stack().pop();
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let right_directed_op = DirectedOp::Right(ct.name(), spec.clone());
|
let right_directed_op = DirectedOp::Right(ct.name(), spec.clone());
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
|
self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
|
||||||
self.state_stack
|
self.state_stack.push(TokenOrRedirect::CompositeRedirect(
|
||||||
.push(TokenOrRedirect::CompositeRedirect(right_directed_op));
|
max_depth,
|
||||||
|
right_directed_op,
|
||||||
|
));
|
||||||
} else if is_prefix!(spec.assoc()) {
|
} else if is_prefix!(spec.assoc()) {
|
||||||
match ct.name().as_str() {
|
match ct.name().as_str() {
|
||||||
"-" | "\\" => {
|
"-" | "\\" => {
|
||||||
self.format_prefix_op_with_space(ct.name(), spec);
|
self.format_prefix_op_with_space(iter, max_depth, ct.name(), spec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if self.check_max_depth(&mut max_depth) {
|
||||||
|
iter.stack().pop();
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
|
||||||
|
self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let left_directed_op = DirectedOp::Left(ct.name(), spec.clone());
|
let left_directed_op = DirectedOp::Left(ct.name(), spec.clone());
|
||||||
|
|
||||||
self.state_stack
|
self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, left_directed_op));
|
||||||
.push(TokenOrRedirect::CompositeRedirect(left_directed_op));
|
|
||||||
self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
|
self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
|
||||||
} else {
|
} else {
|
||||||
// if is_infix!(spec.assoc())
|
// if is_infix!(spec.assoc())
|
||||||
match ct.name().as_str() {
|
match ct.name().as_str() {
|
||||||
"|" => {
|
"|" => {
|
||||||
self.format_bar_separator_op(ct.name(), spec);
|
self.format_bar_separator_op(iter, max_depth, ct.name(), spec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if self.check_max_depth(&mut max_depth) {
|
||||||
|
iter.stack().pop();
|
||||||
|
iter.stack().pop();
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
|
||||||
|
self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let left_directed_op = DirectedOp::Left(ct.name(), spec.clone());
|
let left_directed_op = DirectedOp::Left(ct.name(), spec.clone());
|
||||||
let right_directed_op = DirectedOp::Right(ct.name(), spec.clone());
|
let right_directed_op = DirectedOp::Right(ct.name(), spec.clone());
|
||||||
|
|
||||||
self.state_stack
|
self.state_stack
|
||||||
.push(TokenOrRedirect::CompositeRedirect(left_directed_op));
|
.push(TokenOrRedirect::CompositeRedirect(max_depth, left_directed_op));
|
||||||
self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
|
self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
|
||||||
self.state_stack
|
self.state_stack
|
||||||
.push(TokenOrRedirect::CompositeRedirect(right_directed_op));
|
.push(TokenOrRedirect::CompositeRedirect(max_depth, right_directed_op));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_struct(&mut self, arity: usize, name: ClauseName) {
|
fn format_struct(
|
||||||
|
&mut self,
|
||||||
|
iter: &mut HCPreOrderIterator,
|
||||||
|
mut max_depth: usize,
|
||||||
|
arity: usize,
|
||||||
|
name: ClauseName,
|
||||||
|
) -> bool
|
||||||
|
{
|
||||||
|
if self.check_max_depth(&mut max_depth) {
|
||||||
|
for _ in 0 .. arity {
|
||||||
|
iter.stack().pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::Close);
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
|
||||||
|
self.state_stack.push(TokenOrRedirect::Open);
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(name));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::Close);
|
self.state_stack.push(TokenOrRedirect::Close);
|
||||||
|
|
||||||
for _ in 0..arity {
|
for _ in 0 .. arity {
|
||||||
self.state_stack.push(TokenOrRedirect::FunctorRedirect);
|
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth));
|
||||||
self.state_stack.push(TokenOrRedirect::Comma);
|
self.state_stack.push(TokenOrRedirect::Comma);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -539,29 +612,77 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
self.state_stack.push(TokenOrRedirect::Open);
|
self.state_stack.push(TokenOrRedirect::Open);
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::Atom(name));
|
self.state_stack.push(TokenOrRedirect::Atom(name));
|
||||||
|
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_prefix_op_with_space(&mut self, name: ClauseName, spec: SharedOpDesc) {
|
fn format_prefix_op_with_space(
|
||||||
|
&mut self,
|
||||||
|
iter: &mut HCPreOrderIterator,
|
||||||
|
mut max_depth: usize,
|
||||||
|
name: ClauseName,
|
||||||
|
spec: SharedOpDesc)
|
||||||
|
{
|
||||||
|
if self.check_max_depth(&mut max_depth) {
|
||||||
|
iter.stack().pop();
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
|
||||||
|
self.state_stack.push(TokenOrRedirect::Space);
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(name));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let op = DirectedOp::Left(name.clone(), spec);
|
let op = DirectedOp::Left(name.clone(), spec);
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::CompositeRedirect(op));
|
self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, op));
|
||||||
self.state_stack.push(TokenOrRedirect::Space);
|
self.state_stack.push(TokenOrRedirect::Space);
|
||||||
self.state_stack.push(TokenOrRedirect::Atom(name));
|
self.state_stack.push(TokenOrRedirect::Atom(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_bar_separator_op(&mut self, name: ClauseName, spec: SharedOpDesc) {
|
fn format_bar_separator_op(
|
||||||
|
&mut self,
|
||||||
|
iter: &mut HCPreOrderIterator,
|
||||||
|
mut max_depth: usize,
|
||||||
|
name: ClauseName,
|
||||||
|
spec: SharedOpDesc,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if self.check_max_depth(&mut max_depth) {
|
||||||
|
iter.stack().pop();
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
|
||||||
|
self.state_stack.push(TokenOrRedirect::BarAsOp);
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let left_directed_op = DirectedOp::Left(name.clone(), spec.clone());
|
let left_directed_op = DirectedOp::Left(name.clone(), spec.clone());
|
||||||
let right_directed_op = DirectedOp::Right(name.clone(), spec.clone());
|
let right_directed_op = DirectedOp::Right(name.clone(), spec.clone());
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::CompositeRedirect(left_directed_op));
|
self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, left_directed_op));
|
||||||
self.state_stack.push(TokenOrRedirect::BarAsOp);
|
self.state_stack.push(TokenOrRedirect::BarAsOp);
|
||||||
self.state_stack.push(TokenOrRedirect::CompositeRedirect(right_directed_op));
|
self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, right_directed_op));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_curly_braces(&mut self) {
|
fn format_curly_braces(&mut self, iter: &mut HCPreOrderIterator, mut max_depth: usize) -> bool
|
||||||
|
{
|
||||||
|
if self.check_max_depth(&mut max_depth) {
|
||||||
|
iter.stack().pop();
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::RightCurly);
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
|
||||||
|
self.state_stack.push(TokenOrRedirect::LeftCurly);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::RightCurly);
|
self.state_stack.push(TokenOrRedirect::RightCurly);
|
||||||
self.state_stack.push(TokenOrRedirect::FunctorRedirect);
|
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth));
|
||||||
self.state_stack.push(TokenOrRedirect::LeftCurly);
|
self.state_stack.push(TokenOrRedirect::LeftCurly);
|
||||||
|
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_numbered_vars(&mut self, iter: &mut HCPreOrderIterator) -> bool {
|
fn format_numbered_vars(&mut self, iter: &mut HCPreOrderIterator) -> bool {
|
||||||
@@ -577,29 +698,36 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_clause(&mut self, iter: &mut HCPreOrderIterator, arity: usize, ct: ClauseType) {
|
fn format_clause(
|
||||||
|
&mut self,
|
||||||
|
iter: &mut HCPreOrderIterator,
|
||||||
|
max_depth: usize,
|
||||||
|
arity: usize,
|
||||||
|
ct: ClauseType,
|
||||||
|
) -> bool {
|
||||||
if self.numbervars && is_numbered_var(&ct, arity) {
|
if self.numbervars && is_numbered_var(&ct, arity) {
|
||||||
if self.format_numbered_vars(iter) {
|
if self.format_numbered_vars(iter) {
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(spec) = ct.spec() {
|
if let Some(spec) = ct.spec() {
|
||||||
if "." == ct.name().as_str() && is_infix!(spec.assoc()) {
|
if "." == ct.name().as_str() && is_infix!(spec.assoc()) {
|
||||||
if !self.ignore_ops {
|
if !self.ignore_ops {
|
||||||
self.push_list();
|
self.push_list(iter, max_depth);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.ignore_ops && spec.prec() > 0 {
|
if !self.ignore_ops && spec.prec() > 0 {
|
||||||
return self.enqueue_op(ct, spec);
|
self.enqueue_op(iter, max_depth, ct, spec);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match (ct.name().as_str(), arity) {
|
return match (ct.name().as_str(), arity) {
|
||||||
("{}", 1) if !self.ignore_ops => self.format_curly_braces(),
|
("{}", 1) if !self.ignore_ops => self.format_curly_braces(iter, max_depth),
|
||||||
_ => self.format_struct(arity, ct.name()),
|
_ => self.format_struct(iter, max_depth, arity, ct.name()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,7 +774,60 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_for_seen(&mut self, iter: &mut HCPreOrderIterator) -> Option<HeapCellValue> {
|
fn record_children_as_non_cyclic(&mut self, addr: &Addr) {
|
||||||
|
match addr {
|
||||||
|
&Addr::Lis(l) => {
|
||||||
|
let c1 = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(l)));
|
||||||
|
let c2 = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(l + 1)));
|
||||||
|
|
||||||
|
if let Some(c) = functor_location(&c1) {
|
||||||
|
self.non_cyclic_terms.insert(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(c) = functor_location(&c2) {
|
||||||
|
self.non_cyclic_terms.insert(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&Addr::Str(s) => {
|
||||||
|
let arity =
|
||||||
|
match &self.machine_st.heap[s] {
|
||||||
|
HeapCellValue::NamedStr(arity, ..) => {
|
||||||
|
arity
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for i in 1 .. arity + 1 {
|
||||||
|
let c = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(s + i)));
|
||||||
|
|
||||||
|
if let Some(c) = functor_location(&c) {
|
||||||
|
self.non_cyclic_terms.insert(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&Addr::PStrLocation(h, _) | &Addr::PStrTail(h, _) => {
|
||||||
|
let tail = match &self.machine_st.heap[h] {
|
||||||
|
&HeapCellValue::PartialString(ref pstr) => pstr.tail_addr().clone(),
|
||||||
|
_ => unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
|
let tail = self.machine_st.store(self.machine_st.deref(tail));
|
||||||
|
|
||||||
|
if let Some(c) = functor_location(&tail) {
|
||||||
|
self.non_cyclic_terms.insert(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_for_seen(
|
||||||
|
&mut self,
|
||||||
|
iter: &mut HCPreOrderIterator,
|
||||||
|
) -> Option<HeapCellValue> {
|
||||||
iter.stack().last().cloned().and_then(|addr| {
|
iter.stack().last().cloned().and_then(|addr| {
|
||||||
let addr = self.machine_st.store(self.machine_st.deref(addr));
|
let addr = self.machine_st.store(self.machine_st.deref(addr));
|
||||||
|
|
||||||
@@ -661,6 +842,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
return iter.next();
|
return iter.next();
|
||||||
} else {
|
} else {
|
||||||
iter.stack().pop();
|
iter.stack().pop();
|
||||||
|
|
||||||
push_space_if_amb!(self, &var, {
|
push_space_if_amb!(self, &var, {
|
||||||
self.append_str(&var);
|
self.append_str(&var);
|
||||||
});
|
});
|
||||||
@@ -669,30 +851,38 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if self.machine_st.is_cyclic_term(addr.clone()) {
|
let offset = match functor_location(&addr) {
|
||||||
match self.cyclic_terms.get(&addr).cloned() {
|
Some(offset) => offset,
|
||||||
Some(reps) => {
|
None => {
|
||||||
if reps > 0 {
|
return iter.next();
|
||||||
self.cyclic_terms.insert(addr, reps - 1);
|
}
|
||||||
iter.next()
|
};
|
||||||
} else {
|
|
||||||
push_space_if_amb!(self, "...", {
|
|
||||||
self.append_str("...");
|
|
||||||
});
|
|
||||||
|
|
||||||
iter.stack().pop();
|
if !self.non_cyclic_terms.contains(&offset) {
|
||||||
self.cyclic_terms.swap_remove(&addr);
|
if let Some(reps) = self.cyclic_terms.get(&addr).cloned() {
|
||||||
None
|
if reps > 0 {
|
||||||
}
|
self.cyclic_terms.insert(addr, reps - 1);
|
||||||
}
|
} else {
|
||||||
None => {
|
push_space_if_amb!(self, "...", {
|
||||||
|
self.append_str("...");
|
||||||
|
});
|
||||||
|
|
||||||
|
iter.stack().pop();
|
||||||
self.cyclic_terms.insert(addr, 2);
|
self.cyclic_terms.insert(addr, 2);
|
||||||
iter.next()
|
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
|
} else if self.machine_st.is_cyclic_term(addr.clone()) {
|
||||||
|
self.cyclic_terms.insert(addr, 2);
|
||||||
|
} else {
|
||||||
|
self.record_children_as_non_cyclic(&addr);
|
||||||
|
self.non_cyclic_terms.insert(offset);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
iter.next()
|
self.record_children_as_non_cyclic(&addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iter.next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -807,8 +997,13 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_constant(&mut self, iter: &mut HCPreOrderIterator, c: Constant, op: &Option<DirectedOp>)
|
fn print_constant(
|
||||||
{
|
&mut self,
|
||||||
|
iter: &mut HCPreOrderIterator,
|
||||||
|
max_depth: usize,
|
||||||
|
c: Constant,
|
||||||
|
op: &Option<DirectedOp>,
|
||||||
|
) {
|
||||||
match c {
|
match c {
|
||||||
Constant::Atom(atom, spec) => {
|
Constant::Atom(atom, spec) => {
|
||||||
if let Some(_) = fetch_atom_op_spec(atom.clone(), spec, self.op_dir) {
|
if let Some(_) = fetch_atom_op_spec(atom.clone(), spec, self.op_dir) {
|
||||||
@@ -862,7 +1057,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
self.print_string_as_str(iter, n, s);
|
self.print_string_as_str(iter, n, s);
|
||||||
}
|
}
|
||||||
Constant::String(n, s) => {
|
Constant::String(n, s) => {
|
||||||
self.print_string(iter, n, s);
|
self.print_string(iter, max_depth, n, s);
|
||||||
}
|
}
|
||||||
Constant::Usize(i) => {
|
Constant::Usize(i) => {
|
||||||
self.append_str(&format!("u{}", i));
|
self.append_str(&format!("u{}", i));
|
||||||
@@ -891,39 +1086,77 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
iter.stack().pop();
|
iter.stack().pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_string(&mut self, iter: &mut HCPreOrderIterator, offset: usize, s: Rc<String>) {
|
fn print_string(
|
||||||
|
&mut self,
|
||||||
|
iter: &mut HCPreOrderIterator,
|
||||||
|
mut max_depth: usize,
|
||||||
|
offset: usize,
|
||||||
|
s: Rc<String>)
|
||||||
|
{
|
||||||
if !self.machine_st.machine_flags().double_quotes.is_atom() {
|
if !self.machine_st.machine_flags().double_quotes.is_atom() {
|
||||||
|
if self.check_max_depth(&mut max_depth) {
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if s.len() <= offset && !self.at_cdr("") {
|
if s.len() <= offset && !self.at_cdr("") {
|
||||||
self.append_str("[]");
|
self.append_str("[]");
|
||||||
} else if self.ignore_ops {
|
} else if self.ignore_ops {
|
||||||
let mut paren_count = 0;
|
let mut char_count = 0;
|
||||||
|
let mut byte_len = 0;
|
||||||
|
|
||||||
for c in s[offset ..].chars() {
|
let iter: Box<dyn Iterator<Item=char>> =
|
||||||
|
if self.max_depth == 0 {
|
||||||
|
Box::new(s[offset ..].chars())
|
||||||
|
} else {
|
||||||
|
Box::new(s[offset ..].chars().take(max_depth))
|
||||||
|
};
|
||||||
|
|
||||||
|
for c in iter {
|
||||||
self.print_char('.');
|
self.print_char('.');
|
||||||
self.push_char('(');
|
self.push_char('(');
|
||||||
|
|
||||||
self.print_char(c);
|
self.print_char(c);
|
||||||
self.push_char(',');
|
self.push_char(',');
|
||||||
|
|
||||||
paren_count += 1;
|
char_count += 1;
|
||||||
|
byte_len += c.len_utf8();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.append_str("[]");
|
if self.max_depth > 0 && byte_len < s[offset ..].len() {
|
||||||
|
self.append_str("...");
|
||||||
|
} else {
|
||||||
|
self.append_str("[]");
|
||||||
|
}
|
||||||
|
|
||||||
for _ in 0 .. paren_count {
|
for _ in 0 .. char_count {
|
||||||
self.push_char(')');
|
self.push_char(')');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.push_char('[');
|
self.push_char('[');
|
||||||
|
|
||||||
for c in s[offset ..].chars() {
|
let iter: Box<dyn Iterator<Item=char>> =
|
||||||
|
if self.max_depth == 0 {
|
||||||
|
Box::new(s[offset ..].chars())
|
||||||
|
} else {
|
||||||
|
Box::new(s[offset ..].chars().take(max_depth))
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut byte_len = 0;
|
||||||
|
|
||||||
|
for c in iter {
|
||||||
self.print_char(c);
|
self.print_char(c);
|
||||||
self.push_char(',');
|
self.push_char(',');
|
||||||
|
|
||||||
|
byte_len += c.len_utf8();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.outputter.truncate(self.outputter.len() - ','.len_utf8());
|
if self.max_depth > 0 && byte_len < s[offset ..].len() {
|
||||||
|
self.append_str("...|...]");
|
||||||
self.push_char(']');
|
} else {
|
||||||
|
self.outputter.truncate(self.outputter.len() - ','.len_utf8());
|
||||||
|
self.push_char(']');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iter.stack().pop();
|
iter.stack().pop();
|
||||||
@@ -939,15 +1172,43 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_list(&mut self) {
|
fn check_max_depth(&mut self, max_depth: &mut usize) -> bool {
|
||||||
let cell = Rc::new(Cell::new(true));
|
if self.max_depth > 0 && *max_depth == 0 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
self.state_stack
|
if *max_depth > 0 {
|
||||||
.push(TokenOrRedirect::CloseList(cell.clone()));
|
*max_depth -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::FunctorRedirect);
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_list(&mut self, iter: &mut HCPreOrderIterator, mut max_depth: usize) {
|
||||||
|
if self.check_max_depth(&mut max_depth) {
|
||||||
|
iter.stack().pop();
|
||||||
|
iter.stack().pop();
|
||||||
|
|
||||||
|
let cell = Rc::new(Cell::new((true, 0)));
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::CloseList(cell.clone()));
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
|
||||||
|
self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar
|
||||||
|
self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::OpenList(cell));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cell = Rc::new(Cell::new((true, max_depth)));
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::CloseList(cell.clone()));
|
||||||
|
|
||||||
|
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth));
|
||||||
self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar
|
self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar
|
||||||
self.state_stack.push(TokenOrRedirect::FunctorRedirect);
|
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth));
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::OpenList(cell));
|
self.state_stack.push(TokenOrRedirect::OpenList(cell));
|
||||||
}
|
}
|
||||||
@@ -961,6 +1222,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
is_functor_redirect: bool,
|
is_functor_redirect: bool,
|
||||||
spec: SharedOpDesc,
|
spec: SharedOpDesc,
|
||||||
negated_operand: bool,
|
negated_operand: bool,
|
||||||
|
max_depth: usize,
|
||||||
) {
|
) {
|
||||||
let add_brackets = if !self.ignore_ops {
|
let add_brackets = if !self.ignore_ops {
|
||||||
negated_operand
|
negated_operand
|
||||||
@@ -987,14 +1249,15 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let ct = ClauseType::from(name.clone(), arity, Some(spec));
|
let ct = ClauseType::from(name.clone(), arity, Some(spec));
|
||||||
self.format_clause(iter, arity, ct);
|
|
||||||
|
|
||||||
if add_brackets {
|
if self.format_clause(iter, max_depth, arity, ct) {
|
||||||
self.state_stack.push(TokenOrRedirect::Open);
|
if add_brackets {
|
||||||
|
self.state_stack.push(TokenOrRedirect::Open);
|
||||||
|
|
||||||
if let Some(ref op) = &op {
|
if let Some(ref op) = &op {
|
||||||
if op.is_left() && requires_space(op.as_str(), "(") {
|
if op.is_left() && requires_space(op.as_str(), "(") {
|
||||||
self.state_stack.push(TokenOrRedirect::Space);
|
self.state_stack.push(TokenOrRedirect::Space);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1005,6 +1268,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
iter: &mut HCPreOrderIterator,
|
iter: &mut HCPreOrderIterator,
|
||||||
op: Option<DirectedOp>,
|
op: Option<DirectedOp>,
|
||||||
is_functor_redirect: bool,
|
is_functor_redirect: bool,
|
||||||
|
max_depth: usize,
|
||||||
) {
|
) {
|
||||||
let negated_operand = negated_op_needs_bracketing(iter, &op);
|
let negated_operand = negated_op_needs_bracketing(iter, &op);
|
||||||
|
|
||||||
@@ -1026,11 +1290,12 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
is_functor_redirect,
|
is_functor_redirect,
|
||||||
spec,
|
spec,
|
||||||
negated_operand,
|
negated_operand,
|
||||||
|
max_depth,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
push_space_if_amb!(self, name.as_str(), {
|
push_space_if_amb!(self, name.as_str(), {
|
||||||
let ct = ClauseType::from(name, arity, spec);
|
let ct = ClauseType::from(name, arity, spec);
|
||||||
self.format_clause(iter, arity, ct);
|
self.format_clause(iter, max_depth, arity, ct);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1039,12 +1304,14 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
self.append_str("[]");
|
self.append_str("[]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HeapCellValue::Addr(Addr::Con(c)) => self.print_constant(iter, c, &op),
|
HeapCellValue::Addr(Addr::Con(c)) => {
|
||||||
|
self.print_constant(iter, max_depth, c, &op);
|
||||||
|
}
|
||||||
HeapCellValue::Addr(Addr::Lis(_)) | HeapCellValue::Addr(Addr::PStrLocation(..)) => {
|
HeapCellValue::Addr(Addr::Lis(_)) | HeapCellValue::Addr(Addr::PStrLocation(..)) => {
|
||||||
if self.ignore_ops {
|
if self.ignore_ops {
|
||||||
self.format_struct(2, clause_name!("."));
|
self.format_struct(iter, max_depth, 2, clause_name!("."));
|
||||||
} else {
|
} else {
|
||||||
self.push_list();
|
self.push_list(iter, max_depth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HeapCellValue::Addr(Addr::Stream(stream)) => {
|
HeapCellValue::Addr(Addr::Stream(stream)) => {
|
||||||
@@ -1099,11 +1366,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
TokenOrRedirect::BarAsOp => self.append_str(" | "),
|
TokenOrRedirect::BarAsOp => self.append_str(" | "),
|
||||||
TokenOrRedirect::Op(atom, _) => self.print_op(atom.as_str()),
|
TokenOrRedirect::Op(atom, _) => self.print_op(atom.as_str()),
|
||||||
TokenOrRedirect::NumberedVar(num_var) => self.append_str(num_var.as_str()),
|
TokenOrRedirect::NumberedVar(num_var) => self.append_str(num_var.as_str()),
|
||||||
TokenOrRedirect::CompositeRedirect(op) => {
|
TokenOrRedirect::CompositeRedirect(max_depth, op) => {
|
||||||
self.handle_heap_term(&mut iter, Some(op), false)
|
self.handle_heap_term(&mut iter, Some(op), false, max_depth)
|
||||||
}
|
}
|
||||||
TokenOrRedirect::FunctorRedirect => {
|
TokenOrRedirect::FunctorRedirect(max_depth) => {
|
||||||
self.handle_heap_term(&mut iter, None, true)
|
self.handle_heap_term(&mut iter, None, true, max_depth)
|
||||||
}
|
}
|
||||||
TokenOrRedirect::Close => self.push_char(')'),
|
TokenOrRedirect::Close => self.push_char(')'),
|
||||||
TokenOrRedirect::Open => self.push_char('('),
|
TokenOrRedirect::Open => self.push_char('('),
|
||||||
@@ -1111,11 +1378,12 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
if !self.at_cdr(",") {
|
if !self.at_cdr(",") {
|
||||||
self.push_char('[');
|
self.push_char('[');
|
||||||
} else {
|
} else {
|
||||||
delimit.set(false);
|
let (_, max_depth) = delimit.get();
|
||||||
|
delimit.set((false, max_depth));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TokenOrRedirect::CloseList(delimit) => {
|
TokenOrRedirect::CloseList(delimit) => {
|
||||||
if delimit.get() {
|
if delimit.get().0 {
|
||||||
self.push_char(']');
|
self.push_char(']');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1127,7 +1395,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
} else if !iter.stack().is_empty() {
|
} else if !iter.stack().is_empty() {
|
||||||
let spec = self.toplevel_spec.take();
|
let spec = self.toplevel_spec.take();
|
||||||
self.handle_heap_term(&mut iter, spec, false);
|
self.handle_heap_term(&mut iter, spec, false, self.max_depth);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -289,6 +289,7 @@ is_write_option(Functor) :-
|
|||||||
( Arg == true -> true
|
( Arg == true -> true
|
||||||
; Arg == false -> true
|
; Arg == false -> true
|
||||||
; Name == variable_names -> must_be_var_names_list(Arg)
|
; Name == variable_names -> must_be_var_names_list(Arg)
|
||||||
|
; Name == max_depth -> integer(Arg), Arg >= 0
|
||||||
; var(Arg) -> throw(error(instantiation_error, write_term/2))
|
; var(Arg) -> throw(error(instantiation_error, write_term/2))
|
||||||
; throw(error(domain_error(write_option, Functor), write_term/2))
|
; throw(error(domain_error(write_option, Functor), write_term/2))
|
||||||
), % 8.14.2.3 e)
|
), % 8.14.2.3 e)
|
||||||
@@ -296,6 +297,7 @@ is_write_option(Functor) :-
|
|||||||
; Name == quoted -> true
|
; Name == quoted -> true
|
||||||
; Name == numbervars -> true
|
; Name == numbervars -> true
|
||||||
; Name == variable_names -> true
|
; Name == variable_names -> true
|
||||||
|
; Name == max_depth -> true
|
||||||
; throw(error(domain_error(write_option, Functor), write_term/2))
|
; throw(error(domain_error(write_option, Functor), write_term/2))
|
||||||
). % 8.14.2.3 e)
|
). % 8.14.2.3 e)
|
||||||
|
|
||||||
@@ -338,7 +340,8 @@ write_term(Term, Options) :-
|
|||||||
inst_member_or(Options, numbervars(NumberVars), numbervars(false)),
|
inst_member_or(Options, numbervars(NumberVars), numbervars(false)),
|
||||||
inst_member_or(Options, quoted(Quoted), quoted(false)),
|
inst_member_or(Options, quoted(Quoted), quoted(false)),
|
||||||
inst_member_or(Options, variable_names(VarNames), variable_names([])),
|
inst_member_or(Options, variable_names(VarNames), variable_names([])),
|
||||||
'$write_term'(Term, IgnoreOps, NumberVars, Quoted, VarNames).
|
inst_member_or(Options, max_depth(MaxDepth), max_depth(0)),
|
||||||
|
'$write_term'(Term, IgnoreOps, NumberVars, Quoted, VarNames, MaxDepth).
|
||||||
|
|
||||||
write(Term) :- write_term(Term, [numbervars(true)]).
|
write(Term) :- write_term(Term, [numbervars(true)]).
|
||||||
|
|
||||||
|
|||||||
@@ -2667,6 +2667,7 @@ impl MachineState {
|
|||||||
let ignore_ops = self.store(self.deref(self[temp_v!(2)].clone()));
|
let ignore_ops = self.store(self.deref(self[temp_v!(2)].clone()));
|
||||||
let numbervars = self.store(self.deref(self[temp_v!(3)].clone()));
|
let numbervars = self.store(self.deref(self[temp_v!(3)].clone()));
|
||||||
let quoted = self.store(self.deref(self[temp_v!(4)].clone()));
|
let quoted = self.store(self.deref(self[temp_v!(4)].clone()));
|
||||||
|
let max_depth = self.store(self.deref(self[temp_v!(6)].clone()));
|
||||||
|
|
||||||
let mut printer = HCPrinter::new(&self, &indices.op_dir, PrinterOutputter::new());
|
let mut printer = HCPrinter::new(&self, &indices.op_dir, PrinterOutputter::new());
|
||||||
|
|
||||||
@@ -2682,6 +2683,15 @@ impl MachineState {
|
|||||||
printer.quoted = name.as_str() == "true";
|
printer.quoted = name.as_str() == "true";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let &Addr::Con(Constant::Integer(ref n)) = &max_depth {
|
||||||
|
if let Some(n) = n.to_usize() {
|
||||||
|
printer.max_depth = n;
|
||||||
|
} else {
|
||||||
|
self.fail = true;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let stub = MachineError::functor_stub(clause_name!("write_term"), 2);
|
let stub = MachineError::functor_stub(clause_name!("write_term"), 2);
|
||||||
|
|
||||||
match self.try_from_list(temp_v!(5), stub.clone()) {
|
match self.try_from_list(temp_v!(5), stub.clone()) {
|
||||||
|
|||||||
@@ -114,9 +114,9 @@
|
|||||||
write(' = '),
|
write(' = '),
|
||||||
( '$needs_bracketing'(Value, (=)) ->
|
( '$needs_bracketing'(Value, (=)) ->
|
||||||
write('('),
|
write('('),
|
||||||
write_term(Value, [quoted(true), variable_names(VarList)]),
|
write_term(Value, [quoted(true), variable_names(VarList), max_depth(0)]),
|
||||||
write(')')
|
write(')')
|
||||||
; write_term(Value, [quoted(true), variable_names(VarList)])
|
; write_term(Value, [quoted(true), variable_names(VarList), max_depth(0)])
|
||||||
)
|
)
|
||||||
; G == [] ->
|
; G == [] ->
|
||||||
write('true')
|
write('true')
|
||||||
@@ -129,9 +129,9 @@
|
|||||||
write(' = '),
|
write(' = '),
|
||||||
( '$needs_bracketing'(Value, (=)) ->
|
( '$needs_bracketing'(Value, (=)) ->
|
||||||
write('('),
|
write('('),
|
||||||
write_term(Value, [quoted(true), variable_names(VarList)]),
|
write_term(Value, [quoted(true), variable_names(VarList), max_depth(0)]),
|
||||||
write(')')
|
write(')')
|
||||||
; write_term(Value, [quoted(true), variable_names(VarList)]),
|
; write_term(Value, [quoted(true), variable_names(VarList), max_depth(0)]),
|
||||||
( '$trailing_period_is_ambiguous'(Value) ->
|
( '$trailing_period_is_ambiguous'(Value) ->
|
||||||
write(' ')
|
write(' ')
|
||||||
; true
|
; true
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
)
|
)
|
||||||
; G == [] ->
|
; G == [] ->
|
||||||
write('true')
|
write('true')
|
||||||
; write_term(G, [quoted(true), variable_names(VarList)])
|
; write_term(G, [quoted(true), variable_names(VarList), max_depth(0)])
|
||||||
).
|
).
|
||||||
|
|
||||||
'$write_eq'((G1, G2), VarList) :-
|
'$write_eq'((G1, G2), VarList) :-
|
||||||
@@ -215,7 +215,7 @@
|
|||||||
).
|
).
|
||||||
|
|
||||||
'$print_exception'(E) :-
|
'$print_exception'(E) :-
|
||||||
write_term('caught: ', [quoted(false)]),
|
write_term('caught: ', [quoted(false), max_depth(20)]),
|
||||||
writeq(E),
|
writeq(E),
|
||||||
nl.
|
nl.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user