}
}
+ pub fn machine_st(&self) -> &MachineState {
+ &self.machine_st
+ }
+
fn follow_heap(&mut self, h: usize) -> Addr
{
match &self.machine_st.heap[h] {
}
}
-pub struct HCTrackingPreOrderIter<'a> {
- pre_iter: HCPreOrderIterator<'a>,
- this_addr: Addr
-}
-
-impl<'a> HCTrackingPreOrderIter<'a> {
- fn new(machine_st: &'a MachineState, a: Addr) -> Self {
- HCTrackingPreOrderIter {
- pre_iter: HCPreOrderIterator::new(machine_st, a.clone()),
- this_addr: a
- }
- }
-
- #[inline]
- pub fn this_addr(&self) -> Addr {
- self.this_addr.clone()
- }
-
- #[inline]
- pub fn machine_st(&self) -> &MachineState {
- self.pre_iter.machine_st
- }
-}
-
-impl<'a> MutStackHCIterator for HCTrackingPreOrderIter<'a> {
- fn stack(&mut self) -> &mut Vec<Addr> {
- self.pre_iter.stack()
- }
-}
-
-impl<'a> Iterator for HCTrackingPreOrderIter<'a> {
- type Item = HeapCellValue;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.pre_iter.state_stack.pop().map(|a| {
- let addr = self.pre_iter.follow(a);
- self.this_addr = addr.clone();
-
- match addr {
- Addr::HeapCell(h) =>
- self.pre_iter.machine_st.heap[h].clone(),
- Addr::StackCell(fr, sc) =>
- HeapCellValue::Addr(self.pre_iter.machine_st.and_stack[fr][sc].clone()),
- da =>
- HeapCellValue::Addr(da)
- }
- })
- }
-}
-
pub trait MutStackHCIterator where Self: Iterator<Item=HeapCellValue> {
fn stack(&mut self) -> &mut Vec<Addr>;
}
}
pub type HCProperPostOrderIterator<'a> = HCPostOrderIterator<HCPreOrderIterator<'a>>;
-pub type HCAcyclicPostOrderIterator<'a> = HCPostOrderIterator<HCAcyclicIterator<HCTrackingPreOrderIter<'a>>>;
-impl MachineState {
- pub fn tracking_pre_order_iter<'a>(&'a self, a: Addr) -> HCTrackingPreOrderIter<'a> {
- HCTrackingPreOrderIter::new(self, a)
- }
-
+impl MachineState {
pub fn pre_order_iter<'a>(&'a self, a: Addr) -> HCPreOrderIterator<'a> {
HCPreOrderIterator::new(self, a)
}
HCPostOrderIterator::new(HCPreOrderIterator::new(self, a))
}
- pub fn acyclic_tracking_post_order_iter<'a>(&'a self, a: Addr) -> HCAcyclicPostOrderIterator<'a> {
- HCPostOrderIterator::new(HCAcyclicIterator::new(HCTrackingPreOrderIter::new(self, a)))
- }
-
pub fn acyclic_pre_order_iter<'a>(&'a self, a: Addr) -> HCAcyclicIterator<HCPreOrderIterator<'a>>
{
HCAcyclicIterator::new(HCPreOrderIterator::new(self, a))
use std::iter::once;
use std::rc::Rc;
+/* contains the location, name, precision and Specifier of the parent op. */
#[derive(Clone)]
pub enum DirectedOp {
- Left(ClauseName, bool), // bool is true if infix.
- Right(ClauseName),
+ Left(ClauseName, (usize, Specifier)),
+ Right(ClauseName, (usize, Specifier)),
}
impl DirectedOp {
+ #[inline]
fn as_str(&self) -> &str {
match self {
- &DirectedOp::Left(ref name, _) | &DirectedOp::Right(ref name) =>
+ &DirectedOp::Left(ref name, _) | &DirectedOp::Right(ref name, _) =>
name.as_str()
}
}
}
+fn needs_bracketing(child_spec: (usize, Specifier), op: &DirectedOp) -> bool {
+ match op {
+ &DirectedOp::Left(_, (priority, spec)) => {
+ let is_strict_right = is_yfx!(spec) || is_xfx!(spec) || is_fx!(spec);
+ child_spec.0 > priority || (child_spec.0 == priority && is_strict_right)
+ },
+ &DirectedOp::Right(_, (priority, spec)) => {
+ let is_strict_left = is_xfx!(spec) || is_xfy!(spec) || is_xf!(spec);
+ child_spec.0 > priority || (child_spec.0 == priority && is_strict_left)
+ }
+ }
+}
+
#[derive(Clone)]
pub enum TokenOrRedirect {
Atom(ClauseName),
Op(ClauseName, (usize, Specifier)),
NumberedVar(String),
CompositeRedirect(DirectedOp),
- Redirect,
+ FunctorRedirect,
Open,
Close,
Comma,
state_stack: Vec<TokenOrRedirect>,
heap_locs: ReverseHeapVarDict,
printed_vars: HashSet<Addr>,
- bracketed_addrs: HashSet<Addr>,
pub(crate) numbervars: bool,
pub(crate) quoted: bool,
pub(crate) ignore_ops: bool
macro_rules! push_space_if_amb {
($self:expr, $atom:expr, $op:expr, $action:block) => (
match $self.ambiguity_check($atom, $op) {
- Some(DirectedOp::Left(_, false)) => {
- $self.outputter.push_char(' ');
- $action;
- },
- Some(DirectedOp::Left(lop, true)) => {
- $self.outputter.insert_from_end(lop.as_str().len(), ' ');
- $self.outputter.push_char(' ');
- $action;
- },
+ Some(DirectedOp::Left(lop, (_, spec))) =>
+ if is_infix!(spec) {
+ $self.outputter.insert_from_end(lop.as_str().len(), ' ');
+ $self.outputter.push_char(' ');
+ $action;
+ } else {
+ $self.outputter.push_char(' ');
+ $action;
+ },
Some(DirectedOp::Right(..)) => {
$action;
$self.outputter.push_char(' ');
state_stack: vec![],
heap_locs: ReverseHeapVarDict::new(),
printed_vars: HashSet::new(),
- bracketed_addrs: HashSet::new(),
numbervars: false,
quoted: false,
ignore_ops: false }
fn ambiguity_check(&self, atom: &str, op: &Option<DirectedOp>) -> Option<DirectedOp>
{
match op {
- &Some(DirectedOp::Left(ref lop, false)) if continues_with_append(lop.as_str(), atom) =>
- Some(DirectedOp::Left(lop.clone(), false)),
- &Some(DirectedOp::Left(ref lop, true)) =>
+ &Some(DirectedOp::Left(ref lop, (priority, spec))) if is_infix!(spec) =>
if self.outputter.ends_with(&format!(" {}", lop.as_str())) {
- Some(DirectedOp::Left(lop.clone(), false))
+ Some(DirectedOp::Left(lop.clone(), (priority, spec)))
} else if continues_with_append(lop.as_str(), atom) {
- Some(DirectedOp::Left(lop.clone(), true))
+ Some(DirectedOp::Left(lop.clone(), (priority, spec)))
} else {
None
},
- &Some(DirectedOp::Right(ref rop)) if continues_with_append(atom, rop.as_str()) =>
- Some(DirectedOp::Right(rop.clone())),
+ &Some(DirectedOp::Left(ref lop, spec))
+ if continues_with_append(lop.as_str(), atom) =>
+ Some(DirectedOp::Left(lop.clone(), spec)),
+ &Some(DirectedOp::Right(ref rop, spec))
+ if continues_with_append(atom, rop.as_str()) =>
+ Some(DirectedOp::Right(rop.clone(), spec)),
_ =>
None
}
fn enqueue_op(&mut self, ct: ClauseType, spec: (usize, Specifier)) {
if is_postfix!(spec.1) {
+ let right_directed_op = DirectedOp::Right(ct.name(), spec);
+
self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
- self.state_stack.push(TokenOrRedirect::CompositeRedirect(DirectedOp::Right(ct.name())));
+ self.state_stack.push(TokenOrRedirect::CompositeRedirect(right_directed_op));
} else if is_prefix!(spec.1) {
- let left_directed_op = DirectedOp::Left(ct.name(), false);
+ let left_directed_op = DirectedOp::Left(ct.name(), spec);
self.state_stack.push(TokenOrRedirect::CompositeRedirect(left_directed_op));
self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
} else { // if is_infix!(spec.1)
- let left_directed_op = DirectedOp::Left(ct.name(), true);
+ let left_directed_op = DirectedOp::Left(ct.name(), spec);
+ let right_directed_op = DirectedOp::Right(ct.name(), spec);
self.state_stack.push(TokenOrRedirect::CompositeRedirect(left_directed_op));
self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
- self.state_stack.push(TokenOrRedirect::CompositeRedirect(DirectedOp::Right(ct.name())));
+ self.state_stack.push(TokenOrRedirect::CompositeRedirect(right_directed_op));
}
}
self.state_stack.push(TokenOrRedirect::Close);
for _ in 0 .. arity {
- self.state_stack.push(TokenOrRedirect::Redirect);
+ self.state_stack.push(TokenOrRedirect::FunctorRedirect);
self.state_stack.push(TokenOrRedirect::Comma);
}
self.state_stack.push(TokenOrRedirect::Atom(name));
}
- fn format_clause(&mut self, iter: &mut HCTrackingPreOrderIter, arity: usize, ct: ClauseType)
+ fn format_clause(&mut self, iter: &mut HCPreOrderIterator, arity: usize, ct: ClauseType)
{
if let Some(spec) = ct.spec() {
if !self.ignore_ops {
}
}
- fn check_for_seen(&mut self, iter: &mut HCTrackingPreOrderIter, op: &Option<DirectedOp>)
+ fn check_for_seen(&mut self, iter: &mut HCPreOrderIterator, op: &Option<DirectedOp>)
-> Option<HeapCellValue>
{
iter.stack().last().cloned().and_then(|addr| {
self.state_stack.push(TokenOrRedirect::CloseList(cell.clone()));
- self.state_stack.push(TokenOrRedirect::Redirect);
+ self.state_stack.push(TokenOrRedirect::FunctorRedirect);
self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar
- self.state_stack.push(TokenOrRedirect::Redirect);
+ self.state_stack.push(TokenOrRedirect::FunctorRedirect);
self.state_stack.push(TokenOrRedirect::OpenList(cell));
}
- fn handle_heap_term(&mut self, iter: &mut HCTrackingPreOrderIter, op: Option<DirectedOp>)
+ fn handle_heap_term(&mut self, iter: &mut HCPreOrderIterator, op: Option<DirectedOp>,
+ is_functor_redirect: bool)
{
let heap_val = match self.check_for_seen(iter, &op) {
Some(heap_val) => heap_val,
};
match heap_val {
- HeapCellValue::NamedStr(arity, ref name, Some(spec)) if name.as_str() != "," => {
- if op.is_some() {
+ HeapCellValue::NamedStr(arity, ref name, Some(spec)) => {
+ let add_brackets = if !self.ignore_ops {
+ if let Some(ref op) = &op {
+ needs_bracketing(spec, op)
+ } else {
+ is_functor_redirect && spec.0 >= 1000
+ }
+ } else {
+ false
+ };
+
+ if add_brackets {
self.state_stack.push(TokenOrRedirect::Close);
}
let ct = ClauseType::from(name.clone(), arity, Some(spec));
self.format_clause(iter, arity, ct);
- if let Some(ref op) = op {
+ if add_brackets {
self.state_stack.push(TokenOrRedirect::Open);
+ }
- if self.outputter.ends_with(&format!(" {}", op.as_str())) {
+ if let Some(op) = op {
+ if !add_brackets && self.outputter.ends_with(&format!(" {}", op.as_str())) {
self.state_stack.push(TokenOrRedirect::Space);
}
}
}
}
- fn mark_terms_for_brackets(&mut self, addr: Addr) {
- let mut iter = self.machine_st.acyclic_tracking_post_order_iter(addr);
- let mut stack: Vec<(Addr, usize)> = vec![];
-
- while let Some(heap_val) = iter.next() {
- let addr = iter.this_addr();
-
- match heap_val {
- HeapCellValue::NamedStr(2, _, Some((prec, spec))) => {
- let (addr_2, prec_2) = stack.pop().unwrap();
- let (addr_1, prec_1) = stack.pop().unwrap();
-
- if prec_1 > prec || (prec_1 == prec && (is_xfy!(spec) || is_xfx!(spec))) {
- self.bracketed_addrs.insert(addr_1);
- }
-
- if prec_2 > prec || (prec_2 == prec && (is_yfx!(spec) || is_xfx!(spec))) {
- self.bracketed_addrs.insert(addr_2);
- }
-
- stack.push((addr, prec));
- continue;
- },
- HeapCellValue::NamedStr(1, _, Some((prec, spec))) => {
- let (addr_1, prec_1) = stack.pop().unwrap();
-
- if prec_1 > prec || (prec_1 == prec && (is_fx!(spec) || is_xf!(spec))) {
- self.bracketed_addrs.insert(addr_1);
- }
-
- stack.push((addr, prec));
- continue;
- },
- HeapCellValue::NamedStr(arity, _, None) => {
- let stack_len = stack.len();
-
- for (addr_1, prec_1) in stack.drain(stack_len - arity ..) {
- if prec_1 >= 1000 { // 1000 is the precedence of the (,) operator.
- self.bracketed_addrs.insert(addr_1);
- }
- }
- },
- HeapCellValue::Addr(addr_1 @ Addr::Con(Constant::Atom(_, Some(_)))) => {
- self.bracketed_addrs.insert(addr_1);
- },
- HeapCellValue::Addr(Addr::Lis(_)) => {
- let stack_len = stack.len();
-
- for (addr_1, prec_1) in stack.drain(stack_len - 2 ..) {
- if prec_1 >= 1000 { // 1000 is the precedence of the (,) operator.
- self.bracketed_addrs.insert(addr_1);
- }
- }
- },
- _ => {}
- };
-
- stack.push((addr, 0));
- }
- }
-
pub fn print(mut self, addr: Addr) -> Outputter {
- self.mark_terms_for_brackets(addr.clone());
- let mut iter = self.machine_st.tracking_pre_order_iter(addr);
+ let mut iter = self.machine_st.pre_order_iter(addr);
loop {
if let Some(loc_data) = self.state_stack.pop() {
TokenOrRedirect::NumberedVar(num_var) =>
self.outputter.append(num_var.as_str()),
TokenOrRedirect::CompositeRedirect(op) =>
- self.handle_heap_term(&mut iter, Some(op)),
- TokenOrRedirect::Redirect =>
- self.handle_heap_term(&mut iter, None),
+ self.handle_heap_term(&mut iter, Some(op), false),
+ TokenOrRedirect::FunctorRedirect =>
+ self.handle_heap_term(&mut iter, None, true),
TokenOrRedirect::Space =>
self.outputter.push_char(' '),
TokenOrRedirect::Close =>
self.outputter.append(", ")
}
} else if !iter.stack().is_empty() {
- self.handle_heap_term(&mut iter, None);
+ self.handle_heap_term(&mut iter, None, false);
} else {
break;
}