diff --git a/src/heap_print.rs b/src/heap_print.rs index 3ca68c4fc..8be390768 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -484,7 +484,6 @@ pub struct HCPrinter<'a, Outputter> { state_stack: Vec, toplevel_spec: Option, last_item_idx: usize, - num_ops_on_stack: usize, parent_of_first_op: Option<(DirectedOp, usize)>, pub var_names: IndexMap, pub numbervars_offset: Integer, @@ -563,7 +562,6 @@ 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), @@ -588,15 +586,18 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } fn set_parent_of_first_op(&mut self, parent_op: Option) { - self.parent_of_first_op = parent_op.map(|op| (op, self.last_item_idx)); + if let Some(op) = parent_op { + if op.is_left() && op.is_prefix() { + self.parent_of_first_op = Some((op, self.last_item_idx)); + } + } } - fn enqueue_op(&mut self, mut max_depth: usize, name: Atom, spec: OpDesc, parent_op: Option) { + fn enqueue_op(&mut self, mut max_depth: usize, name: Atom, spec: OpDesc) { if is_postfix!(spec.get_spec()) { if self.max_depth_exhausted(max_depth) { 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(); @@ -641,7 +642,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { 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(); self.iter.pop_stack(); @@ -658,12 +658,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { 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 { @@ -777,7 +771,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { arity: usize, name: Atom, op_desc: Option, - parent_op: Option, ) -> bool { if self.numbervars && is_numbered_var(name, arity) { if self.format_numbered_vars() { @@ -796,7 +789,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } if !self.ignore_ops && spec.get_prec() > 0 { - self.enqueue_op(max_depth, name, spec, parent_op); + self.enqueue_op(max_depth, name, spec); return true; } } @@ -1064,7 +1057,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { right_directed_op, )); - self.num_ops_on_stack += 1; self.set_parent_of_first_op(parent_op); } else { self.state_stack.push(TokenOrRedirect::Close); @@ -1385,33 +1377,33 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { if add_brackets { self.state_stack.push(TokenOrRedirect::Close); - self.format_clause(max_depth, arity, name, Some(op_desc), op); + self.format_clause(max_depth, arity, name, Some(op_desc)); self.state_stack.push(TokenOrRedirect::Open); - 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 - } - }); + if !self.outputter.ends_with(" ") { + 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(" ") { + for op in &[op, parent_op] { + if let Some(ref op) = &op { if op.is_left() && (op.is_prefix() || requires_space(op.as_atom().as_str(), "(")) { self.state_stack.push(TokenOrRedirect::Space); - break; + return; } } } } } else { - self.format_clause(max_depth, arity, name, Some(op_desc), op); + self.format_clause(max_depth, arity, name, Some(op_desc)); } } @@ -1528,7 +1520,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, op); + printer.format_clause(max_depth, arity, name, None); }); } } else if fetch_op_spec(name, arity, printer.op_dir).is_some() { @@ -1594,7 +1586,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, op); + self.format_clause(max_depth, arity, name, None); }); } } @@ -1675,10 +1667,12 @@ 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.num_ops_on_stack -= 1; - self.parent_of_first_op = None; + TokenOrRedirect::Op(atom, op) => { self.print_op(atom.as_str()); + + if is_prefix!(op.get_spec()) { + self.set_parent_of_first_op(Some(DirectedOp::Left(atom, op))); + } } TokenOrRedirect::NumberedVar(num_var) => append_str!(self, &num_var), TokenOrRedirect::CompositeRedirect(max_depth, op) => { @@ -2020,5 +2014,21 @@ mod tests { all_cells_unmarked(&wam.machine_st.heap); assert_eq!(&wam.parse_and_print_term("[a|[b|c]*d].").unwrap(), "[a|[b|c]*d]"); + + all_cells_unmarked(&wam.machine_st.heap); + + wam.op_dir.insert( + (atom!("fy"), Fixity::Pre), + OpDesc::build_with(9, FY as u8), + ); + + wam.op_dir.insert( + (atom!("yf"), Fixity::Post), + OpDesc::build_with(9, YF as u8), + ); + + assert_eq!(&wam.parse_and_print_term("(fy (fy 1)yf)yf.").unwrap(), "(fy (fy 1)yf)yf"); + + assert_eq!(&wam.parse_and_print_term("fy(fy(yf(fy(1)))).").unwrap(), "fy fy (fy 1)yf"); } }