]> Repositorios git - scryer-prolog.git/commitdiff
track the parent operator of the current operator in heap_print to emit space if...
authorMark <[email protected]>
Tue, 25 Jul 2023 02:05:28 +0000 (20:05 -0600)
committerMark <[email protected]>
Tue, 25 Jul 2023 02:05:28 +0000 (20:05 -0600)
src/heap_print.rs
tests-pl/iso-conformity-tests.pl

index d1d87587bb55bf15d2942dbf79d1178fe22bf9cf..1f01b0def5833f851cfb8d2be8d01afc8b3e8e72 100644 (file)
@@ -26,7 +26,6 @@ use std::cell::Cell;
 use std::convert::TryFrom;
 use std::iter::once;
 use std::net::{IpAddr, TcpListener};
-use std::ops::{Range, RangeFrom};
 use std::rc::Rc;
 
 /* contains the location, name, precision and Specifier of the parent op. */
@@ -64,11 +63,7 @@ impl DirectedOp {
 
     #[inline]
     fn is_left(&self) -> bool {
-        if let &DirectedOp::Left(..) = self {
-            true
-        } else {
-            false
-        }
+        matches!(self, DirectedOp::Left(..))
     }
 }
 
@@ -330,8 +325,7 @@ pub trait HCValueOutputter {
     fn ends_with(&self, s: &str) -> bool;
     fn len(&self) -> usize;
     fn truncate(&mut self, len: usize);
-    fn range(&self, range: Range<usize>) -> &str;
-    fn range_from(&self, range: RangeFrom<usize>) -> &str;
+    fn as_str(&self) -> &str;
 }
 
 #[derive(Debug)]
@@ -386,12 +380,8 @@ impl HCValueOutputter for PrinterOutputter {
         self.contents.truncate(len);
     }
 
-    fn range(&self, index: Range<usize>) -> &str {
-        &self.contents.as_str()[index]
-    }
-
-    fn range_from(&self, index: RangeFrom<usize>) -> &str {
-        &self.contents.as_str().get(index).unwrap_or("")
+    fn as_str(&self) -> &str {
+        &self.contents
     }
 }
 
@@ -492,6 +482,8 @@ pub struct HCPrinter<'a, Outputter> {
     state_stack: Vec<TokenOrRedirect>,
     toplevel_spec: Option<DirectedOp>,
     last_item_idx: usize,
+    num_ops_on_stack: usize,
+    parent_of_first_op: Option<(DirectedOp, usize)>,
     pub var_names: IndexMap<HeapCellValue, VarPtr>,
     pub numbervars_offset: Integer,
     pub numbervars: bool,
@@ -567,6 +559,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
             state_stack: vec![],
             toplevel_spec: None,
             last_item_idx: 0,
+            num_ops_on_stack: 0,
+            parent_of_first_op: None,
             numbervars: false,
             numbervars_offset: Integer::from(0),
             quoted: false,
@@ -580,7 +574,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
 
     #[inline]
     fn ambiguity_check(&self, atom: &str) -> bool {
-        let tail = self.outputter.range_from(self.last_item_idx..);
+        let tail = &self.outputter.as_str()[self.last_item_idx..];
 
         if !self.quoted || non_quoted_token(atom.chars()) {
             requires_space(tail, atom)
@@ -589,7 +583,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
         }
     }
 
-    fn enqueue_op(&mut self, mut max_depth: usize, name: Atom, spec: OpDesc) {
+    fn set_parent_of_first_op(&mut self, parent_op: Option<DirectedOp>) {
+        self.parent_of_first_op = parent_op.map(|op| (op, self.last_item_idx));
+    }
+
+    fn enqueue_op(&mut self, mut max_depth: usize, name: Atom, spec: OpDesc, parent_op: Option<DirectedOp>) {
         if is_postfix!(spec.get_spec()) {
             if self.max_depth_exhausted(max_depth) {
                 self.iter.pop_stack();
@@ -600,17 +598,15 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
 
                 self.state_stack.push(TokenOrRedirect::Op(name, spec));
                 self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
+            } else {
+                let right_directed_op = DirectedOp::Right(name, spec);
 
-                return;
+                self.state_stack.push(TokenOrRedirect::Op(name, spec));
+                self.state_stack.push(TokenOrRedirect::CompositeRedirect(
+                    max_depth,
+                    right_directed_op,
+                ));
             }
-
-            let right_directed_op = DirectedOp::Right(name, spec);
-
-            self.state_stack.push(TokenOrRedirect::Op(name, spec));
-            self.state_stack.push(TokenOrRedirect::CompositeRedirect(
-                max_depth,
-                right_directed_op,
-            ));
         } else if is_prefix!(spec.get_spec()) {
             if self.max_depth_exhausted(max_depth) {
                 self.iter.pop_stack();
@@ -620,15 +616,13 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                 self.iter.pop_stack();
 
                 self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
-                self.state_stack.push(TokenOrRedirect::Atom(name));
+                self.state_stack.push(TokenOrRedirect::Op(name, spec));
+            } else {
+                let op = DirectedOp::Left(name, spec);
 
-                return;
+                self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, op));
+                self.state_stack.push(TokenOrRedirect::Op(name, spec));
             }
-
-            let op = DirectedOp::Left(name, spec);
-
-            self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, op));
-            self.state_stack.push(TokenOrRedirect::Atom(name));
         } else {
             match name.as_str() {
                 "|" => {
@@ -638,15 +632,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                 _ => {}
             };
 
-            let left_directed_op = DirectedOp::Left(name, spec);
-            let right_directed_op = DirectedOp::Right(name, spec);
-
             if self.max_depth_exhausted(max_depth) {
                 self.iter.pop_stack();
                 self.iter.pop_stack();
 
                 self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
-
                 return;
             } else if self.check_max_depth(&mut max_depth) {
                 self.iter.pop_stack();
@@ -655,14 +645,21 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                 self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
                 self.state_stack.push(TokenOrRedirect::Op(name, spec));
                 self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
+            } else {
+                let left_directed_op = DirectedOp::Left(name, spec);
+                let right_directed_op = DirectedOp::Right(name, spec);
 
-                return;
+                self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, left_directed_op));
+                self.state_stack.push(TokenOrRedirect::Op(name, spec));
+                self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, right_directed_op));
             }
+        }
 
-            self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, left_directed_op));
-            self.state_stack.push(TokenOrRedirect::Op(name, spec));
-            self.state_stack.push(TokenOrRedirect::CompositeRedirect(max_depth, right_directed_op));
+        if self.num_ops_on_stack == 0 {
+            self.set_parent_of_first_op(parent_op);
         }
+
+        self.num_ops_on_stack += 1;
     }
 
     fn format_struct(&mut self, mut max_depth: usize, arity: usize, name: Atom) -> bool {
@@ -776,6 +773,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
         arity: usize,
         name: Atom,
         op_desc: Option<OpDesc>,
+        parent_op: Option<DirectedOp>,
     ) -> bool {
         if self.numbervars && is_numbered_var(name, arity) {
             if self.format_numbered_vars() {
@@ -794,7 +792,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
             }
 
             if !self.ignore_ops && spec.get_prec() > 0 {
-                self.enqueue_op(max_depth, name, spec);
+                self.enqueue_op(max_depth, name, spec, parent_op);
                 return true;
             }
         }
@@ -976,7 +974,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                     });
                 }
                 Number::Rational(r) => {
-                    self.print_rational(max_depth, r);
+                    self.print_rational(max_depth, r, *op);
                 }
                 n => {
                     let output_str = format!("{}", n);
@@ -1007,7 +1005,12 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
         }
     }
 
-    fn print_rational(&mut self, mut max_depth: usize, r: TypedArenaPtr<Rational>) {
+    fn print_rational(
+        &mut self,
+        mut max_depth: usize,
+        r: TypedArenaPtr<Rational>,
+        parent_op: Option<DirectedOp>,
+    ) {
         if self.check_max_depth(&mut max_depth) {
             self.state_stack.push(TokenOrRedirect::Close);
             self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
@@ -1050,15 +1053,15 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                         NumberFocus::Denominator(r),
                         left_directed_op,
                     ));
-
-                    self.state_stack
-                        .push(TokenOrRedirect::Op(rdiv_ct, *op_desc));
-
+                    self.state_stack.push(TokenOrRedirect::Op(rdiv_ct, *op_desc));
                     self.state_stack.push(TokenOrRedirect::NumberFocus(
                         max_depth,
                         NumberFocus::Numerator(r),
                         right_directed_op,
                     ));
+
+                    self.num_ops_on_stack += 1;
+                    self.set_parent_of_first_op(parent_op);
                 } else {
                     self.state_stack.push(TokenOrRedirect::Close);
 
@@ -1347,7 +1350,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
         &mut self,
         name: Atom,
         arity: usize,
-        op: &Option<DirectedOp>,
+        op: Option<DirectedOp>,
         is_functor_redirect: bool,
         op_desc: OpDesc,
         negated_operand: bool,
@@ -1378,20 +1381,33 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
 
         if add_brackets {
             self.state_stack.push(TokenOrRedirect::Close);
-        }
-
-        if self.format_clause(max_depth, arity, name, Some(op_desc)) && add_brackets {
+            self.format_clause(max_depth, arity, name, Some(op_desc), op);
             self.state_stack.push(TokenOrRedirect::Open);
 
-            if let Some(ref op) = &op {
-                if !self.outputter.ends_with(" ") {
-                    if op.is_left() {
-                        if op.is_prefix() || requires_space(op.as_atom().as_str(), "(") {
+            let parent_op = self.parent_of_first_op
+                .and_then(|(parent_op, last_item_idx)| {
+                    // if parent_op isn't printed to the output string
+                    // already, then it doesn't border the present op
+                    // and we should return None.
+                    if self.last_item_idx == last_item_idx {
+                        Some(parent_op)
+                    } else {
+                        None
+                    }
+                });
+
+            for op in &[op, parent_op] {
+                if let Some(ref op) = &op {
+                    if !self.outputter.ends_with(" ") {
+                        if op.is_left() && (op.is_prefix() || requires_space(op.as_atom().as_str(), "(")) {
                             self.state_stack.push(TokenOrRedirect::Space);
+                            break;
                         }
                     }
                 }
             }
+        } else {
+            self.format_clause(max_depth, arity, name, Some(op_desc), op);
         }
     }
 
@@ -1500,7 +1516,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                     printer.handle_op_as_struct(
                         name,
                         arity,
-                        &op,
+                        op,
                         is_functor_redirect,
                         spec,
                         negated_operand,
@@ -1508,7 +1524,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                     );
                 } else {
                     push_space_if_amb!(printer, name.as_str(), {
-                        printer.format_clause(max_depth, arity, name, None);
+                        printer.format_clause(max_depth, arity, name, None, op);
                     });
                 }
             } else if fetch_op_spec(name, arity, printer.op_dir).is_some() {
@@ -1566,7 +1582,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                     self.handle_op_as_struct(
                         name,
                         arity,
-                        &op,
+                        op,
                         is_functor_redirect,
                         spec,
                         negated_operand,
@@ -1574,7 +1590,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                     );
                 } else {
                     push_space_if_amb!(self, name.as_str(), {
-                        self.format_clause(max_depth, arity, name, None);
+                        self.format_clause(max_depth, arity, name, None, op);
                     });
                 }
             }
@@ -1655,7 +1671,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                 TokenOrRedirect::Atom(atom) => self.print_impromptu_atom(atom),
                 TokenOrRedirect::BarAsOp => append_str!(self, " | "),
                 TokenOrRedirect::Char(c) => print_char!(self, self.quoted, c),
-                TokenOrRedirect::Op(atom, _) => self.print_op(atom.as_str()),
+                TokenOrRedirect::Op(atom, ..) => {
+                    self.num_ops_on_stack -= 1;
+                    self.parent_of_first_op = None;
+                    self.print_op(atom.as_str());
+                }
                 TokenOrRedirect::NumberedVar(num_var) => append_str!(self, &num_var),
                 TokenOrRedirect::CompositeRedirect(max_depth, op) => {
                     self.handle_heap_term(Some(op), false, max_depth)
index c86620dabc1ce1b7c7cad8a26c879cb5f15ead78..94185a072bea74e75e3ad7272d87e8f47c297cc6 100644 (file)
@@ -998,6 +998,9 @@ test_310 :- test_syntax_error("writeq({\\+ (}).", syntax_error(incomplete_reduct
 
 test_311 :- test_syntax_error("Finis ().", syntax_error(incomplete_reduction)).
 
+test_318 :- writeq_term_to_chars(+((1*2)^3), C),
+            C == "+ (1*2)^3".
+
 run_tests([Test|Tests]) -->
     (  { call(Test) } ->
        []