]> Repositorios git - scryer-prolog.git/commitdiff
update writer
authorMark Thom <[email protected]>
Sat, 30 Mar 2019 04:49:33 +0000 (22:49 -0600)
committerMark Thom <[email protected]>
Sat, 30 Mar 2019 04:49:33 +0000 (22:49 -0600)
Cargo.toml
src/prolog/heap_iter.rs
src/prolog/heap_print.rs
src/prolog/lib/builtins.pl
src/prolog/read.rs

index ed38a9a3507a30750713ab887f2e356e454cc61d..e104be8693c25bc14b024bb250ed9e11d3627320 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "scryer-prolog"
-version = "0.8.22"
+version = "0.8.23"
 authors = ["Mark Thom <[email protected]>"]
 repository = "https://github.com/mthom/scryer-prolog"
 description = "A modern Prolog implementation written mostly in Rust."
@@ -14,7 +14,7 @@ cfg-if = "0.1.7"
 downcast = "0.9.1"
 num = "0.2"
 ordered-float = "0.5.0"
-prolog_parser = "0.8.3"
+prolog_parser = "0.8.4"
 readline_rs_compat = { version = "0.1.7", optional = true }
 ref_thread_local = "0.0.0"
 
index a5bf3d256e6da4f3ffdcd6bd64afbf4733e99c2a..3353c3239d40bc91e05c91f97ac43239307e3a9a 100644 (file)
@@ -9,8 +9,8 @@ use std::ops::Deref;
 use std::vec::Vec;
 
 pub struct HCPreOrderIterator<'a> {
-    machine_st: &'a MachineState,
-    state_stack: Vec<Addr>
+    pub machine_st: &'a MachineState,
+    pub state_stack: Vec<Addr>
 }
 
 impl<'a> HCPreOrderIterator<'a> {
@@ -24,7 +24,7 @@ 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] {
index 54fdd6b5c4dab91a711cc76d7cd7c9678c043e22..d13aa8e98c20b9afec5f1571e77625b86855aaf9 100644 (file)
@@ -28,9 +28,18 @@ impl DirectedOp {
                 name.as_str()
         }
     }
+
+    #[inline]
+    fn is_negative_sign(&self) -> bool {
+        match self {
+            &DirectedOp::Left(ref name, (_, spec)) | &DirectedOp::Right(ref name, (_, spec)) =>
+                name.as_str() == "-" && is_prefix!(spec)
+        }
+    }
 }
 
-fn needs_bracketing(child_spec: (usize, Specifier), op: &DirectedOp) -> bool {
+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);
@@ -43,6 +52,45 @@ fn needs_bracketing(child_spec: (usize, Specifier), op: &DirectedOp) -> bool {
     }
 }
 
+impl<'a> HCPreOrderIterator<'a> {
+    /*
+     * descend into the subtree where the iterator is currently parked
+     * and check that the leftmost leaf is a number, with every node
+     * encountered on the way an infix or postfix operator, and not blocked
+     * by brackets.
+     */
+    fn leftmost_leaf_is_positive_number(&self) -> bool {
+        let mut addr = match self.state_stack.last().cloned() {
+            Some(addr) => addr,
+            None => return false
+        };
+
+        let mut parent_spec = DirectedOp::Left(clause_name!("-"), (200, FY));
+
+        loop {
+            match self.machine_st.store(self.machine_st.deref(addr)) {
+                Addr::Str(s) =>
+                    match &self.machine_st.heap[s] {
+                        &HeapCellValue::NamedStr(_, ref name, Some(spec))
+                            if is_postfix!(spec.1) || is_infix!(spec.1) =>
+                                if needs_bracketing(spec, &parent_spec) {
+                                    return false;
+                                } else {
+                                    addr = Addr::HeapCell(s+1);
+                                    parent_spec = DirectedOp::Right(name.clone(), spec);
+                                },
+                        _ =>
+                            return false
+                    },
+                Addr::Con(Constant::Number(n)) =>
+                    return n.is_positive(),
+                _ =>
+                    return false
+            }
+        }
+    }
+}
+
 #[derive(Clone)]
 pub enum TokenOrRedirect {
     Atom(ClauseName),
@@ -53,6 +101,9 @@ pub enum TokenOrRedirect {
     Open,
     Close,
     Comma,
+    Space,
+    LeftCurly,
+    RightCurly,
     OpenList(Rc<Cell<bool>>),
     CloseList(Rc<Cell<bool>>),
     HeadTailSeparator,
@@ -137,6 +188,16 @@ fn is_numbered_var(ct: &ClauseType, arity: usize) -> bool {
     }
 }
 
+#[inline]
+fn negated_op_needs_bracketing(iter: &HCPreOrderIterator, op: &Option<DirectedOp>) -> bool
+{
+    if let &Some(ref op) = op {
+        op.is_negative_sign() && iter.leftmost_leaf_is_positive_number()
+    } else {
+        false
+    }
+}
+
 impl MachineState {
     pub fn numbervar(&self, offset: &BigInt, addr: Addr) -> Option<Var> {
         static CHAR_CODES: [char; 26] = ['A','B','C','D','E','F','G','H','I','J',
@@ -181,8 +242,10 @@ pub struct HCPrinter<'a, Outputter> {
 macro_rules! push_space_if_amb {
     ($self:expr, $atom:expr, $action:block) => (
         if $self.ambiguity_check($atom) {
-            if !$self.outputter.range(0 .. $self.last_item_idx).ends_with(" ") {
-                $self.outputter.insert($self.last_item_idx, ' ');
+            if $self.last_item_idx > 1 {
+                if !$self.outputter.range(0 .. $self.last_item_idx).ends_with(" ") {
+                    $self.outputter.insert($self.last_item_idx, ' ');
+                }
             }
 
             $self.outputter.push_char(' ');
@@ -314,6 +377,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
         continues_with_append(tail, atom)
     }
 
+    // TODO: create a DirectedOp factory method. Use it here, and above.
     fn enqueue_op(&mut self, ct: ClauseType, spec: (usize, Specifier)) {
         if is_postfix!(spec.1) {
             let right_directed_op = DirectedOp::Right(ct.name(), spec);
@@ -321,6 +385,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
             self.state_stack.push(TokenOrRedirect::Op(ct.name(), spec));
             self.state_stack.push(TokenOrRedirect::CompositeRedirect(right_directed_op));
         } else if is_prefix!(spec.1) {
+            if ct.name().as_str() == "-" {
+                self.format_negated_operand();
+                return;
+            }
+
             let left_directed_op = DirectedOp::Left(ct.name(), spec);
 
             self.state_stack.push(TokenOrRedirect::CompositeRedirect(left_directed_op));
@@ -350,6 +419,22 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
         self.state_stack.push(TokenOrRedirect::Atom(name));
     }
 
+    fn format_negated_operand(&mut self)
+    {
+        let op = DirectedOp::Left(clause_name!("-"), (200, FY));
+
+        self.state_stack.push(TokenOrRedirect::CompositeRedirect(op));
+        self.state_stack.push(TokenOrRedirect::Space);
+        self.state_stack.push(TokenOrRedirect::Atom(clause_name!("-")));
+    }
+
+    fn format_curly_braces(&mut self)
+    {
+        self.state_stack.push(TokenOrRedirect::RightCurly);
+        self.state_stack.push(TokenOrRedirect::FunctorRedirect);
+        self.state_stack.push(TokenOrRedirect::LeftCurly);
+    }
+
     fn format_clause(&mut self, iter: &mut HCPreOrderIterator, arity: usize, ct: ClauseType)
     {
         if let Some(spec) = ct.spec() {
@@ -367,7 +452,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
             }
         }
 
-        self.format_struct(arity, ct.name());
+        match (ct.name().as_str(), arity) {
+            ("-", 1) => self.format_negated_operand(),
+            ("{}", 1) => self.format_curly_braces(),
+            _ =>  self.format_struct(arity, ct.name())
+        };
     }
 
     #[inline]
@@ -476,6 +565,45 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
         };
     }
 
+    fn print_number(&mut self, n: Number, op: &Option<DirectedOp>) {
+        let add_brackets = if let Some(op) = op {
+            op.is_negative_sign() && n.is_positive()
+        } else {
+            false
+        };
+
+        if add_brackets {
+            self.push_char('(');
+        }
+
+        match n {
+            Number::Float(fl) =>
+                if &fl == &OrderedFloat(0f64) {
+                    push_space_if_amb!(self, "0", {
+                        self.append_str("0");
+                    });
+                } else {
+                    let OrderedFloat(fl) = fl;
+                    let output_str = format!("{0:<20?}", fl);
+
+                    push_space_if_amb!(self, &output_str, {
+                        self.append_str(&output_str.trim());
+                    });
+                },
+            n => {
+                let output_str = format!("{}", n);
+
+                push_space_if_amb!(self, &output_str, {
+                    self.append_str(&output_str);
+                });
+            }
+        }
+
+        if add_brackets {
+            self.push_char(')');
+        }
+    }
+
     fn print_constant(&mut self, c: Constant, op: &Option<DirectedOp>) {
         match c {
             Constant::Atom(ref atom, Some(spec)) => {
@@ -509,26 +637,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
                 },
             Constant::EmptyList =>
                 self.append_str("[]"),
-            Constant::Number(Number::Float(fl)) =>
-                if &fl == &OrderedFloat(0f64) {
-                    push_space_if_amb!(self, "0", {
-                        self.append_str("0");
-                    });
-                } else {
-                    let OrderedFloat(fl) = fl;
-                    let output_str = format!("{0:<20?}", fl);
-
-                    push_space_if_amb!(self, &output_str, {
-                        self.append_str(&output_str.trim());
-                    });
-                },
-            Constant::Number(n) => {                
-                let output_str = format!("{}", n);
-
-                push_space_if_amb!(self, &output_str, {
-                    self.append_str(&output_str);
-                });
-            },
+            Constant::Number(n) =>
+                self.print_number(n, op),
             Constant::String(s) =>
                 if self.machine_st.machine_flags().double_quotes.is_chars() {
                     if !s.is_empty() {
@@ -571,6 +681,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
     fn handle_heap_term(&mut self, iter: &mut HCPreOrderIterator, op: Option<DirectedOp>,
                         is_functor_redirect: bool)
     {
+        let add_brackets = negated_op_needs_bracketing(iter, &op);
+
         let heap_val = match self.check_for_seen(iter) {
             Some(heap_val) => heap_val,
             None => return
@@ -579,7 +691,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
         match heap_val {
             HeapCellValue::NamedStr(arity, ref name, Some(spec)) => {
                 let add_brackets = if !self.ignore_ops {
-                    if let Some(ref op) = &op {
+                    add_brackets || if let Some(ref op) = &op {
                         needs_bracketing(spec, op)
                     } else {
                         is_functor_redirect && spec.0 >= 1000
@@ -604,7 +716,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
                     let ct = ClauseType::from(name, 0, fixity);
                     self.format_clause(iter, 0, ct);
                 }),
-            HeapCellValue::NamedStr(arity, name, fixity) => {                    
+            HeapCellValue::NamedStr(arity, name, fixity) => {
                 let ct = ClauseType::from(name, arity, fixity);
                 self.format_clause(iter, arity, ct);
             },
@@ -675,7 +787,13 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
                     TokenOrRedirect::HeadTailSeparator =>
                         self.append_str(" | "),
                     TokenOrRedirect::Comma =>
-                        self.append_str(", ")
+                        self.append_str(", "),
+                    TokenOrRedirect::Space =>
+                        self.push_char(' '),
+                    TokenOrRedirect::LeftCurly =>
+                        self.push_char('{'),
+                    TokenOrRedirect::RightCurly =>
+                        self.push_char('}'),
                 }
             } else if !iter.stack().is_empty() {
                 let spec = self.toplevel_spec.take();
index c429d65daf047d33219f970f5d3506d2a091774c..e612dd8efd6eeff1a0a4c97b1af094580aa4de1c 100644 (file)
@@ -388,7 +388,7 @@ findall(Template, Goal, Solutions) :-
                                      Error,
                                      ( truncate_lh_to(LhLength), throw(Error) ))).
 
-:- non_counted_backtracking '$iterate_find_all_diff'/4.
+:- non_counted_backtracking '$iterate_find_all_diff'/5.
 '$iterate_find_all_diff'(Template, Goal, _, _, LhOffset) :-
     call(Goal),
     '$copy_to_lh'(LhOffset, Template),
index 7285946d49f6336b31a0d05e6320c88fa09de95d..17d030e0dffbe6139a4b231712c2244b4e821ebe 100644 (file)
@@ -117,7 +117,7 @@ pub mod readline
         if let LineMode::Single = LINE_MODE {
             insert_text_rl("?- ");
         }
-
+        
         0
     }