]> Repositorios git - scryer-prolog.git/commitdiff
support strings as char lists in term comparisons
authorMark Thom <[email protected]>
Thu, 23 Aug 2018 07:24:26 +0000 (01:24 -0600)
committerMark Thom <[email protected]>
Thu, 23 Aug 2018 07:24:26 +0000 (01:24 -0600)
src/prolog/heap_iter.rs
src/prolog/heap_print.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/string_list.rs

index 4b9544e1f0ac25651ecb38f2b7b96ddcaebe9ac1..e5f045ba0f9813d6c0251a9b6de81d6192029012 100644 (file)
@@ -39,17 +39,28 @@ impl<'a> HCPreOrderIterator<'a> {
     {
         let da = self.machine_st.store(self.machine_st.deref(addr));
 
-        match &da {
-            &Addr::Con(_) => da,
-            &Addr::Lis(a) => {
+        match da {
+            Addr::Con(Constant::String(ref s))
+                if self.machine_st.machine_flags().double_quotes.is_chars() => {
+                    if let Some(c) = s.head() {
+                        let tail = s.tail();
+                    
+                        self.state_stack.push(Addr::Con(Constant::String(tail)));
+                        self.state_stack.push(Addr::Con(Constant::Char(c)));
+                    }
+
+                    Addr::Con(Constant::String(s.clone()))
+                },
+            Addr::Con(_) => da,
+            Addr::Lis(a) => {
                 self.state_stack.push(Addr::HeapCell(a + 1));
                 self.state_stack.push(Addr::HeapCell(a));
 
                 da
             },
-            &Addr::HeapCell(_) | &Addr::StackCell(_, _) =>
+            Addr::HeapCell(_) | Addr::StackCell(_, _) =>
                 da,
-            &Addr::Str(s) =>
+            Addr::Str(s) =>
                 self.follow_heap(s) // record terms of structure.
         }
     }
index 2ae1f57c9932d118fedc1046eaac867f5b7cc7b2..a7ae573befab81bda4ef4a43b7ec76f5ba5b5de7 100644 (file)
@@ -1,9 +1,8 @@
 use prolog::ast::*;
 use prolog::num::*;
 use prolog::heap_iter::*;
-use prolog::machine::machine_state::{DoubleQuotes, MachineState};
+use prolog::machine::machine_state::MachineState;
 use prolog::ordered_float::OrderedFloat;
-use prolog::string_list::*;
 
 use std::cell::Cell;
 use std::collections::{HashMap, HashSet};
@@ -12,7 +11,6 @@ use std::rc::Rc;
 #[derive(Clone)]
 pub enum TokenOrRedirect {
     Atom(ClauseName),
-    Char(char),
     NumberedVar(String),
     Redirect,
     Open,
@@ -292,24 +290,6 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
         }
     }
 
-    fn expand_char_list(&mut self, s: StringList) {
-        let cell = Rc::new(Cell::new(true));        
-        let cursor = s.cursor();
-
-        self.state_stack.push(TokenOrRedirect::CloseList(cell.clone()));
-
-        if !s.is_empty() {
-            for c in s.borrow()[cursor ..].chars().rev() {            
-                self.state_stack.push(TokenOrRedirect::Char(c));
-                self.state_stack.push(TokenOrRedirect::Comma);
-            }
-
-            self.state_stack.pop();
-        }
-        
-        self.state_stack.push(TokenOrRedirect::OpenList(cell));
-    }
-
     fn print_char(&mut self, c: char) {
         if non_quoted_token(c) {
             self.outputter.push_char(c);                    
@@ -351,8 +331,13 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
             Constant::Number(n) =>
                 self.outputter.append(&format!("{}", n)),
             Constant::String(s) =>
-                if let DoubleQuotes::Chars = self.machine_st.machine_flags().double_quotes {
-                    self.expand_char_list(s);
+                if self.machine_st.machine_flags().double_quotes.is_chars() {
+                    if !s.is_empty() {
+                        self.push_list();
+                    } else if !self.at_cdr("") {
+                        self.outputter.append("[]");
+                    }
+                    // self.expand_char_list(s);
                 } else { // for now, == DoubleQuotes::Atom
                     self.outputter.append("\"");
                     self.outputter.append(s.borrow().as_str());
@@ -362,6 +347,18 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
                 self.outputter.append(&format!("u{}", i))
         }
     }
+
+    fn push_list(&mut self) {
+        let cell = Rc::new(Cell::new(true));
+
+        self.state_stack.push(TokenOrRedirect::CloseList(cell.clone()));
+
+        self.state_stack.push(TokenOrRedirect::Redirect);
+        self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar
+        self.state_stack.push(TokenOrRedirect::Redirect);
+
+        self.state_stack.push(TokenOrRedirect::OpenList(cell));        
+    }
     
     fn handle_heap_term(&mut self, iter: &mut HCPreOrderIterator)
     {
@@ -381,17 +378,8 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
                 },
             HeapCellValue::Addr(Addr::Con(c)) =>
                 self.print_constant(c),
-            HeapCellValue::Addr(Addr::Lis(_)) => {
-                let cell = Rc::new(Cell::new(true));
-
-                self.state_stack.push(TokenOrRedirect::CloseList(cell.clone()));
-
-                self.state_stack.push(TokenOrRedirect::Redirect);
-                self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar
-                self.state_stack.push(TokenOrRedirect::Redirect);
-
-                self.state_stack.push(TokenOrRedirect::OpenList(cell));
-            },
+            HeapCellValue::Addr(Addr::Lis(_)) =>
+                self.push_list(),
             HeapCellValue::Addr(addr) => self.print_offset(addr)
         }
     }
@@ -417,8 +405,6 @@ impl<'a, Formatter: HCValueFormatter, Outputter: HCValueOutputter>
                 match loc_data {
                     TokenOrRedirect::Atom(atom) =>
                         self.outputter.append(atom.as_str()),
-                    TokenOrRedirect::Char(c) =>
-                        self.print_char(c),
                     TokenOrRedirect::NumberedVar(num_var) =>
                         self.outputter.append(num_var.as_str()),
                     TokenOrRedirect::Redirect =>
index 950ae36b743079224f22e0b4a7c1780ad0e4cd9b..6ff632cd5c43b91f19facdfd4742f9ca56abbb21 100644 (file)
@@ -622,7 +622,15 @@ pub(crate) trait CallPolicy: Any {
                 return_from_clause!(machine_st.last_call, machine_st)
             },
             &BuiltInClauseType::Eq => {
-                machine_st.fail = machine_st.eq_test();
+                let a1 = machine_st[temp_v!(1)].clone();
+                let a2 = machine_st[temp_v!(2)].clone();
+
+                machine_st.fail = if let Ordering::Equal = machine_st.compare_term_test(&a1, &a2) {
+                    false
+                } else {
+                    true
+                };
+
                 return_from_clause!(machine_st.last_call, machine_st)
             },
             &BuiltInClauseType::Ground => {
@@ -634,7 +642,15 @@ pub(crate) trait CallPolicy: Any {
                 return_from_clause!(machine_st.last_call, machine_st)
             },
             &BuiltInClauseType::NotEq => {
-                machine_st.fail = !machine_st.eq_test();
+                let a1 = machine_st[temp_v!(1)].clone();
+                let a2 = machine_st[temp_v!(2)].clone();
+
+                machine_st.fail = if let Ordering::Equal = machine_st.compare_term_test(&a1, &a2) {
+                    true
+                } else {
+                    false
+                };
+                
                 return_from_clause!(machine_st.last_call, machine_st)
             },
             &BuiltInClauseType::Sort => {
index f61008932ef84ab889c77d67ff32fb997cfd2e4d..12db9d2a5b9f1f24a4cc6e1e1d547231802f1612 100644 (file)
@@ -1324,6 +1324,37 @@ impl MachineState {
 
         for (v1, v2) in iter {
             match (v1, v2) {
+                (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Con(Constant::String(_))))
+              | (HeapCellValue::Addr(Addr::Con(Constant::String(_))), HeapCellValue::Addr(Addr::Lis(_)))
+                    if self.flags.double_quotes.is_chars() => {},
+                (HeapCellValue::Addr(Addr::Con(Constant::EmptyList)),
+                 HeapCellValue::Addr(Addr::Con(Constant::String(ref s))))
+                    if self.flags.double_quotes.is_chars() => if s.is_empty() {
+                        return Ordering::Equal;
+                    } else {
+                        return Ordering::Greater;
+                    },
+                (HeapCellValue::Addr(Addr::Con(Constant::Atom(atom))),
+                 HeapCellValue::Addr(Addr::Con(Constant::Char(c)))) =>
+                    return if atom.as_str().chars().count() == 1 {
+                        atom.as_str().chars().next().cmp(&Some(c))
+                    } else {
+                        Ordering::Greater
+                    },
+                (HeapCellValue::Addr(Addr::Con(Constant::Char(c))),
+                 HeapCellValue::Addr(Addr::Con(Constant::Atom(atom)))) =>
+                    return if atom.as_str().chars().count() == 1 {
+                        Some(c).cmp(&atom.as_str().chars().next())
+                    } else {
+                        Ordering::Less
+                    },
+                (HeapCellValue::Addr(Addr::Con(Constant::String(ref s))),
+                 HeapCellValue::Addr(Addr::Con(Constant::EmptyList))) 
+                    if self.flags.double_quotes.is_chars() => if s.is_empty() {
+                        return Ordering::Equal;
+                    } else {
+                        return Ordering::Less;
+                    },
                 (HeapCellValue::Addr(Addr::HeapCell(hc1)),
                  HeapCellValue::Addr(Addr::HeapCell(hc2))) =>
                     if hc1 != hc2 {
@@ -1413,7 +1444,7 @@ impl MachineState {
                         return Ordering::Less;
                     } else {
                         return n.as_str().cmp(".");
-                    },
+                    },                
                 (HeapCellValue::NamedStr(..), _) =>
                     return Ordering::Greater,
                 (HeapCellValue::Addr(Addr::Lis(_)), _) =>
@@ -1724,44 +1755,41 @@ impl MachineState {
     }
 
     // returns true on failure.
-    pub(super) fn eq_test(&self) -> bool
+    pub(super) fn structural_eq_test(&self) -> bool
     {
         let a1 = self[temp_v!(1)].clone();
         let a2 = self[temp_v!(2)].clone();
 
+        let mut var_pairs = HashMap::new();
+
         let iter = self.zipped_acyclic_pre_order_iter(a1, a2);
 
         for (v1, v2) in iter {
             match (v1, v2) {
-                (HeapCellValue::NamedStr(ar1, n1, _), HeapCellValue::NamedStr(ar2, n2, _)) =>
-                    if ar1 != ar2 || n1 != n2 {
+                (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Con(Constant::String(ref s))))
+              | (HeapCellValue::Addr(Addr::Con(Constant::String(ref s))), HeapCellValue::Addr(Addr::Lis(_)))
+                    if self.flags.double_quotes.is_chars() => if s.is_empty() {
                         return true;
                     },
-                (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) =>
-                    continue,
-                (HeapCellValue::Addr(a1), HeapCellValue::Addr(a2)) =>
-                    if a1 != a2 {
+                (HeapCellValue::Addr(Addr::Con(Constant::String(ref s))),
+                 HeapCellValue::Addr(Addr::Con(Constant::EmptyList)))
+              | (HeapCellValue::Addr(Addr::Con(Constant::EmptyList)),
+                 HeapCellValue::Addr(Addr::Con(Constant::String(ref s))))
+                    if self.flags.double_quotes.is_chars() => if !s.is_empty() {
                         return true;
                     },
-                _ => return true
-            }
-        }
-
-        false
-    }
-
-    // returns true on failure.
-    pub(super) fn structural_eq_test(&self) -> bool
-    {
-        let a1 = self[temp_v!(1)].clone();
-        let a2 = self[temp_v!(2)].clone();
-
-        let mut var_pairs = HashMap::new();
-
-        let iter = self.zipped_acyclic_pre_order_iter(a1, a2);
-
-        for (v1, v2) in iter {
-            match (v1, v2) {
+                (HeapCellValue::Addr(Addr::Con(Constant::Atom(atom))),
+                 HeapCellValue::Addr(Addr::Con(Constant::Char(c))))
+              | (HeapCellValue::Addr(Addr::Con(Constant::Char(c))),
+                 HeapCellValue::Addr(Addr::Con(Constant::Atom(atom)))) => {
+                  if atom.as_str().chars().count() == 1 {
+                      if Some(c) == atom.as_str().chars().next() {
+                          continue;
+                      }
+                  }
+                  
+                  return true;
+                },
                 (HeapCellValue::NamedStr(ar1, n1, _), HeapCellValue::NamedStr(ar2, n2, _)) =>
                     if ar1 != ar2 || n1 != n2 {
                         return true;
index d2acb5c7697a4eaecbc7cb48397797d713c4d882..d4f8e35ebd2f7deb4c71eb89bb29d366db4f7338 100644 (file)
@@ -24,7 +24,8 @@ pub struct StringList {
 
 impl Hash for StringList {
     fn hash<H: Hasher>(&self, state: &mut H) {
-        self.borrow().hash(state)
+        let h = self.borrow().hash(state);
+        (h, self.cursor, self.expandable).hash(state);
     }
 }
 
@@ -63,11 +64,6 @@ impl StringList {
         }
     }
 
-    #[inline]
-    pub fn cursor(&self) -> usize {
-        self.cursor
-    }
-
     #[inline]
     pub fn head(&self) -> Option<char> {
         self.borrow()[self.cursor ..].chars().next()