]> Repositorios git - scryer-prolog.git/commitdiff
prepare for improved (?) ambiguity checks
authorMark Thom <[email protected]>
Wed, 23 Jan 2019 03:50:07 +0000 (20:50 -0700)
committerMark Thom <[email protected]>
Wed, 23 Jan 2019 03:50:07 +0000 (20:50 -0700)
Cargo.lock
Cargo.toml
src/prolog/heap_iter.rs
src/prolog/heap_print.rs
src/prolog/machine/term_expansion.rs
src/tests.rs

index 03097f24cb3cf001e5ccac0b8e29a5940b736a20..3ddf6c257e6656a14e234baa1e112e45c4a3291f 100644 (file)
@@ -86,8 +86,7 @@ dependencies = [
 
 [[package]]
 name = "prolog_parser"
-version = "0.7.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
+version = "0.7.22"
 dependencies = [
  "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -113,7 +112,7 @@ dependencies = [
  "downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "prolog_parser 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "prolog_parser 0.7.22",
  "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -152,7 +151,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070"
 "checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe"
 "checksum ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58d25b6c0e47b20d05226d288ff434940296e7e2f8b877975da32f862152241f"
-"checksum prolog_parser 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "b9b3862488cfa064334bb19f79578384ef0558f9f6462679cfb500291bf8980d"
 "checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0"
 "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
 "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
index 94c6126bda00c59af486390d8fc2a7f4dda311e8..39e7544d6b8a7177f63c2d2a29896e4623a177ec 100644 (file)
@@ -10,7 +10,7 @@ license = "BSD-3-Clause"
 downcast = "0.9.1"
 num = "0.2"
 ordered-float = "0.5.0"
-prolog_parser = "0.7.21"
+prolog_parser = { version = "0.7.22", path = "../prolog_parser" }
 
 [dependencies.termion]
 version = "1.4.0"
\ No newline at end of file
index 411b84c1b8911d1b48b660e3642fbceb3f452d28..4bdb382f3187bf287a17e6f602767d705f687622 100644 (file)
@@ -20,6 +20,10 @@ impl<'a> HCPreOrderIterator<'a> {
         }
     }
 
+    pub fn machine_st(&self) -> &MachineState {
+        &self.machine_st
+    }
+    
     fn follow_heap(&mut self, h: usize) -> Addr
     {
         match &self.machine_st.heap[h] {
@@ -84,56 +88,6 @@ impl<'a> Iterator for HCPreOrderIterator<'a> {
     }
 }
 
-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>;
 }
@@ -191,13 +145,8 @@ impl<HCIter: Iterator<Item=HeapCellValue>> Iterator for HCPostOrderIterator<HCIt
 }
 
 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)
     }
@@ -206,10 +155,6 @@ impl MachineState {
         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))
index d2a30c690006ef991bd3ad707dd0aebade61b56a..486be4735fe18847cb618c8f4e93659713e75cc9 100644 (file)
@@ -11,28 +11,43 @@ use std::collections::{HashMap, HashSet};
 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,
@@ -143,7 +158,6 @@ pub struct HCPrinter<'a, Outputter> {
     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
@@ -152,15 +166,15 @@ pub struct HCPrinter<'a, Outputter> {
 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(' ');
@@ -255,7 +269,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
                     state_stack: vec![],
                     heap_locs: ReverseHeapVarDict::new(),
                     printed_vars: HashSet::new(),
-                    bracketed_addrs: HashSet::new(),
                     numbervars: false,
                     quoted: false,
                     ignore_ops: false }
@@ -283,18 +296,20 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
     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
         }
@@ -302,19 +317,22 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
 
     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));
         }
     }
 
@@ -323,7 +341,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
         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);
         }
 
@@ -333,7 +351,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
         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 {
@@ -363,7 +381,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
         }
     }
 
-    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| {
@@ -528,14 +546,15 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
 
         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,
@@ -543,18 +562,30 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
         };
 
         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);
                     }
                 }
@@ -602,70 +633,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
         }
     }
 
-    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() {
@@ -677,9 +646,9 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
                     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 =>
@@ -702,7 +671,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
                         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;
             }
index e6fe42444a650b577d324cd9ec1d52ec318425fa..850786e0cdb7107921cb1f4569f99f56ec07c03d 100644 (file)
@@ -314,7 +314,6 @@ impl MachineState {
 
                 printer.quoted = true;
                 printer.numbervars = true;
-                printer.ignore_ops = true;
 
                 printer.see_all_locs();
 
index e4e21c17a8668232dae3e2df4101ddf1d62f4f80..e97c4ebd93fce52c3026ad2bd979caa6ba9c64e7 100644 (file)
@@ -1676,7 +1676,9 @@ fn test_queries_on_builtins()
     assert_prolog_success!(&mut wam, "?- X = [.,.(.,.,.)].",
                            [["X = ['.', '.'('.', '.', '.')]"]]);
     assert_prolog_success!(&mut wam, "?- X = a+(b*c).",
-                           [["X = a+(b*c)"]]);
+                           [["X = a+b*c"]]);
+    assert_prolog_success!(&mut wam, "?- X = a*(b+c).",
+                           [["X = a*(b+c)"]]);
     assert_prolog_success!(&mut wam, "?- X = [:-,-].",
                            [["X = [:-, -]"]]);
     assert_prolog_success!(&mut wam, "?- X = a*(b+c).",