From: Mark Thom Date: Wed, 23 Jan 2019 03:50:07 +0000 (-0700) Subject: prepare for improved (?) ambiguity checks X-Git-Tag: v0.8.110~291 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=e92996126bf50a9da4f0a451bd85f6f1409adbfe;p=scryer-prolog.git prepare for improved (?) ambiguity checks --- diff --git a/Cargo.lock b/Cargo.lock index 03097f24..3ddf6c25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/Cargo.toml b/Cargo.toml index 94c6126b..39e7544d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 diff --git a/src/prolog/heap_iter.rs b/src/prolog/heap_iter.rs index 411b84c1..4bdb382f 100644 --- a/src/prolog/heap_iter.rs +++ b/src/prolog/heap_iter.rs @@ -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 { - self.pre_iter.stack() - } -} - -impl<'a> Iterator for HCTrackingPreOrderIter<'a> { - type Item = HeapCellValue; - - fn next(&mut self) -> Option { - 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 { fn stack(&mut self) -> &mut Vec; } @@ -191,13 +145,8 @@ impl> Iterator for HCPostOrderIterator = HCPostOrderIterator>; -pub type HCAcyclicPostOrderIterator<'a> = HCPostOrderIterator>>; -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> { HCAcyclicIterator::new(HCPreOrderIterator::new(self, a)) diff --git a/src/prolog/heap_print.rs b/src/prolog/heap_print.rs index d2a30c69..486be473 100644 --- a/src/prolog/heap_print.rs +++ b/src/prolog/heap_print.rs @@ -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, heap_locs: ReverseHeapVarDict, printed_vars: HashSet, - bracketed_addrs: HashSet, 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) -> Option { 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) + fn check_for_seen(&mut self, iter: &mut HCPreOrderIterator, op: &Option) -> Option { 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) + fn handle_heap_term(&mut self, iter: &mut HCPreOrderIterator, op: Option, + 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; } diff --git a/src/prolog/machine/term_expansion.rs b/src/prolog/machine/term_expansion.rs index e6fe4244..850786e0 100644 --- a/src/prolog/machine/term_expansion.rs +++ b/src/prolog/machine/term_expansion.rs @@ -314,7 +314,6 @@ impl MachineState { printer.quoted = true; printer.numbervars = true; - printer.ignore_ops = true; printer.see_all_locs(); diff --git a/src/tests.rs b/src/tests.rs index e4e21c17..e97c4ebd 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -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).",