]> Repositorios git - scryer-prolog.git/commitdiff
compact lists of characters to partial strings in read_term_from_heap (#1452, #1453)
authorMark Thom <[email protected]>
Mon, 2 May 2022 05:13:48 +0000 (23:13 -0600)
committerMark Thom <[email protected]>
Wed, 4 May 2022 01:12:16 +0000 (19:12 -0600)
src/arithmetic.rs
src/codegen.rs
src/iterators.rs
src/lib/dcgs.pl
src/machine/loader.rs
src/parser/ast.rs
src/parser/parser.rs
src/read.rs

index 432926c872d341788f7af437374e8e10cac4db9e..77274fbdc63f8a0e9d8992938322b14f5fbc3393 100644 (file)
@@ -79,7 +79,7 @@ impl<'a> ArithInstructionIterator<'a> {
                 )),
             }?,
             Term::Literal(cell, cons) => TermIterState::Literal(Level::Shallow, cell, cons),
-            Term::Cons(..) | Term::PartialString(..) => {
+            Term::Cons(..) | Term::PartialString(..) | Term::CompleteString(..) => {
                 return Err(ArithmeticError::NonEvaluableFunctor(
                     Literal::Atom(atom!(".")),
                     2,
index 0224d2980c97bf0f5f80499a3caba10b3582e89d..5d67e5f8d8e6f51c80b545acd0d95338be6da49c 100644 (file)
@@ -324,7 +324,8 @@ impl<'b> CodeGenerator<'b> {
             }
             &Term::Cons(ref cell, ..) |
             &Term::Clause(ref cell, ..) |
-            Term::PartialString(ref cell, ..) => {
+            Term::PartialString(ref cell, ..) |
+            Term::CompleteString(ref cell, ..) => {
                 self.marker.mark_non_var::<Target>(Level::Deep, term_loc, cell, target);
                 target.push(Target::clause_arg_to_instr(cell.get()));
             }
@@ -383,13 +384,14 @@ impl<'b> CodeGenerator<'b> {
                 }
                 TermRef::PartialString(lvl, cell, string, tail) => {
                     self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
+                    let atom = self.atom_tbl.build_with(&string);
 
-                    if let Some(tail) = tail {
-                        target.push(Target::to_pstr(lvl, string, cell.get(), true));
-                        self.subterm_to_instr::<Target>(tail, term_loc, is_exposed, &mut target);
-                    } else {
-                        target.push(Target::to_pstr(lvl, string, cell.get(), false));
-                    }
+                    target.push(Target::to_pstr(lvl, atom, cell.get(), true));
+                    self.subterm_to_instr::<Target>(tail, term_loc, is_exposed, &mut target);
+                }
+                TermRef::CompleteString(lvl, cell, atom) => {
+                    self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
+                    target.push(Target::to_pstr(lvl, atom, cell.get(), false));
                 }
                 TermRef::Var(lvl @ Level::Shallow, cell, ref var) if var.as_str() == "!" => {
                     if self.marker.is_unbound(var.clone()) {
@@ -550,7 +552,8 @@ impl<'b> CodeGenerator<'b> {
                 &Term::AnonVar |
                 &Term::Clause(..) |
                 &Term::Cons(..) |
-                &Term::PartialString(..) => {
+                &Term::PartialString(..) |
+                &Term::CompleteString(..) => {
                     code.push(instr!("$fail", 0));
                 }
                 &Term::Literal(_, Literal::String(_)) => {
@@ -577,6 +580,7 @@ impl<'b> CodeGenerator<'b> {
                 &Term::Clause(..) |
                 &Term::Cons(..) |
                 &Term::PartialString(..) |
+                &Term::CompleteString(..) |
                 &Term::Literal(_, Literal::String(..)) => {
                     code.push(instr!("$succeed", 0));
                 }
@@ -702,7 +706,8 @@ impl<'b> CodeGenerator<'b> {
                 &Term::Literal(..) |
                 &Term::Clause(..) |
                 &Term::Cons(..) |
-                &Term::PartialString(..) => {
+                &Term::PartialString(..) |
+                &Term::CompleteString(..) => {
                     code.push(instr!("$fail", 0));
                 }
                 &Term::AnonVar => {
index 422ad667af345ff987f293b689e7f5869493d96b..f6ee98f2ed02febf508c6451d9d98b5d2f723bfd 100644 (file)
@@ -17,7 +17,8 @@ pub(crate) enum TermRef<'a> {
     Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
     Literal(Level, &'a Cell<RegType>, &'a Literal),
     Clause(Level, &'a Cell<RegType>, ClauseType, &'a Vec<Term>),
-    PartialString(Level, &'a Cell<RegType>, Atom, &'a Option<Box<Term>>),
+    PartialString(Level, &'a Cell<RegType>, &'a String, &'a Box<Term>),
+    CompleteString(Level, &'a Cell<RegType>, Atom),
     Var(Level, &'a Cell<VarReg>, Rc<String>),
 }
 
@@ -28,8 +29,9 @@ impl<'a> TermRef<'a> {
             | TermRef::Cons(lvl, ..)
             | TermRef::Literal(lvl, ..)
             | TermRef::Var(lvl, ..)
-            | TermRef::Clause(lvl, ..) => lvl,
-            TermRef::PartialString(lvl, ..) => lvl,
+            | TermRef::Clause(lvl, ..)
+            | TermRef::CompleteString(lvl, ..)
+            | TermRef::PartialString(lvl, ..) => lvl,
         }
     }
 }
@@ -41,8 +43,9 @@ pub(crate) enum TermIterState<'a> {
     Clause(Level, usize, &'a Cell<RegType>, ClauseType, &'a Vec<Term>),
     InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
     FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
-    InitialPartialString(Level, &'a Cell<RegType>, Atom, &'a Option<Box<Term>>),
-    FinalPartialString(Level, &'a Cell<RegType>, Atom, &'a Option<Box<Term>>),
+    InitialPartialString(Level, &'a Cell<RegType>, &'a String, &'a Box<Term>),
+    FinalPartialString(Level, &'a Cell<RegType>, &'a String, &'a Box<Term>),
+    CompleteString(Level, &'a Cell<RegType>, Atom),
     Var(Level, &'a Cell<VarReg>, Rc<String>),
 }
 
@@ -59,7 +62,10 @@ impl<'a> TermIterState<'a> {
             }
             Term::Literal(cell, constant) => TermIterState::Literal(lvl, cell, constant),
             Term::PartialString(cell, string_buf, tail) => {
-                TermIterState::InitialPartialString(lvl, cell, *string_buf, tail)
+                TermIterState::InitialPartialString(lvl, cell, string_buf, tail)
+            }
+            Term::CompleteString(cell, atom) => {
+                TermIterState::CompleteString(lvl, cell, *atom)
             }
             Term::Var(cell, var) => TermIterState::Var(lvl, cell, var.clone()),
         }
@@ -89,7 +95,8 @@ impl<'a> QueryIterator<'a> {
 
     fn from_term(term: &'a Term) -> Self {
         let state = match term {
-            Term::AnonVar | Term::Cons(..) | Term::Literal(..) | Term::PartialString(..) => {
+            Term::AnonVar | Term::Cons(..) | Term::Literal(..) |
+            Term::PartialString(..) | Term::CompleteString(..) => {
                 return QueryIterator {
                     state_stack: vec![],
                 }
@@ -196,13 +203,13 @@ impl<'a> Iterator for QueryIterator<'a> {
                 }
                 TermIterState::InitialPartialString(lvl, cell, string, tail) => {
                     self.state_stack.push(TermIterState::FinalPartialString(lvl, cell, string, tail));
-
-                    if let Some(tail) = tail {
-                        self.push_subterm(lvl.child_level(), tail);
-                    }
+                    self.push_subterm(lvl.child_level(), tail);
                 }
-                TermIterState::FinalPartialString(lvl, cell, string, tail) => {
-                    return Some(TermRef::PartialString(lvl, cell, string, tail));
+                TermIterState::FinalPartialString(lvl, cell, atom, tail) => {
+                    return Some(TermRef::PartialString(lvl, cell, atom, tail));
+                }
+                TermIterState::CompleteString(lvl, cell, atom) => {
+                    return Some(TermRef::CompleteString(lvl, cell, atom));
                 }
                 TermIterState::FinalCons(lvl, cell, head, tail) => {
                     return Some(TermRef::Cons(lvl, cell, head, tail));
@@ -259,12 +266,19 @@ impl<'a> FactIterator<'a> {
                 head.as_ref(),
                 tail.as_ref(),
             )],
-            Term::PartialString(cell, string_buf, tail_opt) => {
+            Term::PartialString(cell, string_buf, tail) => {
                 vec![TermIterState::InitialPartialString(
                     Level::Root,
                     cell,
-                    *string_buf,
-                    tail_opt,
+                    string_buf,
+                    tail,
+                )]
+            }
+            Term::CompleteString(cell, atom) => {
+                vec![TermIterState::CompleteString(
+                    Level::Root,
+                    cell,
+                    *atom,
                 )]
             }
             Term::Literal(cell, constant) => {
@@ -307,12 +321,12 @@ impl<'a> Iterator for FactIterator<'a> {
 
                     return Some(TermRef::Cons(lvl, cell, head, tail));
                 }
-                TermIterState::InitialPartialString(lvl, cell, string_buf, tail_opt) => {
-                    if let Some(tail) = tail_opt {
-                        self.push_subterm(Level::Deep, tail);
-                    }
-
-                    return Some(TermRef::PartialString(lvl, cell, string_buf, tail_opt));
+                TermIterState::InitialPartialString(lvl, cell, string_buf, tail) => {
+                    self.push_subterm(Level::Deep, tail);
+                    return Some(TermRef::PartialString(lvl, cell, string_buf, tail));
+                }
+                TermIterState::CompleteString(lvl, cell, atom) => {
+                    return Some(TermRef::CompleteString(lvl, cell, atom));
                 }
                 TermIterState::Literal(lvl, cell, constant) => {
                     return Some(TermRef::Literal(lvl, cell, constant))
index 488c7a92e68cd6665298ee0e0bc55ed900eded5a..4fe172f75f3e53d81119ecb2c82208f77c06b1f9 100644 (file)
@@ -8,6 +8,7 @@
           ]).
 
 :- use_module(library(error)).
+:- use_module(library(iso_ext)).
 :- use_module(library(lists), [append/3, member/2]).
 :- use_module(library(loader), [strip_module/3]).
 
index bf7456be1f64c0c049fffddc9669498b62437099..e8f0688db41fbed0fea86b4ff8caf63cf1c3fec5 100644 (file)
@@ -485,10 +485,21 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
 
             read_heap_cell!(addr,
                 (HeapCellValueTag::Lis) => {
+                    use crate::parser::parser::as_partial_string;
+
                     let tail = term_stack.pop().unwrap();
                     let head = term_stack.pop().unwrap();
 
-                    term_stack.push(Term::Cons(Cell::default(), Box::new(head), Box::new(tail)));
+                    match as_partial_string(head, tail) {
+                        Ok((string, Some(tail))) => {
+                            term_stack.push(Term::PartialString(Cell::default(), string, tail));
+                        }
+                        Ok((string, None)) => {
+                            let atom = machine_st.atom_tbl.build_with(&string);
+                            term_stack.push(Term::CompleteString(Cell::default(), atom));
+                        }
+                        Err(cons_term) => term_stack.push(cons_term),
+                    }
                 }
                 (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar, h) => {
                     let offset_string = format!("_{}", h);
@@ -509,31 +520,27 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
                         term_stack.push(Term::Clause(Cell::default(), name, subterms));
                     }
                 }
-                (HeapCellValueTag::PStr, string) => {
+                (HeapCellValueTag::PStr, atom) => {
                     let tail = term_stack.pop().unwrap();
 
                     if let Term::Literal(_, Literal::Atom(atom!("[]"))) = &tail {
-                        term_stack.push(Term::PartialString(
-                            Cell::default(),
-                            string,
-                            None,
-                        ));
+                        term_stack.push(Term::CompleteString(Cell::default(), atom));
                     } else {
                         term_stack.push(Term::PartialString(
                             Cell::default(),
-                            string,
-                            Some(Box::new(tail)),
+                            atom.as_str().to_owned(),
+                            Box::new(tail),
                         ));
                     }
                 }
                 (HeapCellValueTag::PStrLoc, h) => {
-                    let string = cell_as_atom_cell!(iter.heap[h]).get_name();
+                    let atom = cell_as_atom_cell!(iter.heap[h]).get_name();
                     let tail = term_stack.pop().unwrap();
 
                     term_stack.push(Term::PartialString(
                         Cell::default(),
-                        string,
-                        Some(Box::new(tail)),
+                        atom.as_str().to_owned(),
+                        Box::new(tail),
                     ));
                 }
                 _ => {
index 9f7288675043a5c7ab5e9bb301338497cf6190ad..3cc1ccbbe40d676afd73c15957f0586ab67426ff 100644 (file)
@@ -541,11 +541,7 @@ impl fmt::Display for Literal {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
             Literal::Atom(ref atom) => {
-                //                if atom.as_str().chars().any(|c| "`.$'\" ".contains(c)) {
-                //                    write!(f, "'{}'", atom)
-                //                } else {
                 write!(f, "{}", atom.flat_index())
-                //                }
             }
             Literal::Char(c) => write!(f, "'{}'", *c as u32),
             Literal::Fixnum(n) => write!(f, "{}", n.get_num()),
@@ -553,7 +549,6 @@ impl fmt::Display for Literal {
             Literal::Rational(ref n) => write!(f, "{}", n),
             Literal::Float(ref n) => write!(f, "{}", *n),
             Literal::String(ref s) => write!(f, "\"{}\"", s.as_str()),
-            //          Literal::Usize(integer) => write!(f, "u{}", integer),
         }
     }
 }
@@ -573,7 +568,10 @@ pub enum Term {
     Clause(Cell<RegType>, Atom, Vec<Term>),
     Cons(Cell<RegType>, Box<Term>, Box<Term>),
     Literal(Cell<RegType>, Literal),
-    PartialString(Cell<RegType>, Atom, Option<Box<Term>>),
+    // PartialString wraps a String in anticipation of it absorbing
+    // other PartialString variants in as_partial_string.
+    PartialString(Cell<RegType>, String, Box<Term>),
+    CompleteString(Cell<RegType>, Atom),
     Var(Cell<VarReg>, Rc<String>),
 }
 
index 431f3799cd3c4ca8e347db7f5d60bb4f2a401f16..ecdc2ab00eceb88adddbdd502d32bb285c4f3bfc 100644 (file)
@@ -49,11 +49,10 @@ struct TokenDesc {
     spec: u32,
 }
 
-fn is_partial_string(
+pub(crate) fn as_partial_string(
     head: Term,
     mut tail: Term,
-    atom_tbl: &mut AtomTable,
-) -> Result<(Atom, Option<Box<Term>>), Term> {
+) -> Result<(String, Option<Box<Term>>), Term> {
     let mut string = match &head {
         Term::Literal(_, Literal::Atom(atom)) => {
             if let Some(c) = atom.as_char() {
@@ -92,6 +91,15 @@ fn is_partial_string(
 
                 tail_ref = succ;
             }
+            Term::PartialString(_, pstr, tail) => {
+                string += &pstr;
+                tail_ref = tail;
+            }
+            Term::CompleteString(_, cstr) => {
+                string += cstr.as_str();
+                tail = Term::Literal(Cell::default(), Literal::Atom(atom!("[]")));
+                break;
+            }
             tail_ref => {
                 tail = mem::replace(tail_ref, Term::AnonVar);
                 break;
@@ -101,21 +109,17 @@ fn is_partial_string(
 
     match &tail {
         Term::AnonVar | Term::Var(..) => {
-            let pstr_atom = atom_tbl.build_with(&string);
-            Ok((pstr_atom, Some(Box::new(tail))))
+            Ok((string, Some(Box::new(tail))))
         }
         Term::Literal(_, Literal::Atom(atom!("[]"))) => {
-            let pstr_atom = atom_tbl.build_with(&string);
-            Ok((pstr_atom, None))
+            Ok((string, None))
         }
         Term::Literal(_, Literal::String(tail)) => {
             string += tail.as_str();
-            let pstr_atom = atom_tbl.build_with(&string);
-            Ok((pstr_atom, None))
+            Ok((string, None))
         }
         _ => {
-            let pstr_atom = atom_tbl.build_with(&string);
-            Ok((pstr_atom, Some(Box::new(tail))))
+            Ok((string, Some(Box::new(tail))))
         }
     }
 }
@@ -412,7 +416,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
                 TokenType::Term
             }
             Token::Literal(Literal::String(s)) if self.lexer.machine_st.flags.double_quotes.is_chars() => {
-                self.terms.push(Term::PartialString(Cell::default(), s, None));
+                self.terms.push(Term::CompleteString(Cell::default(), s));
                 TokenType::Term
             }
             Token::Literal(c) => {
@@ -564,24 +568,19 @@ impl<'a, R: CharRead> Parser<'a, R> {
                         let head = subterms.pop().unwrap();
 
                         self.terms.push(
-                            match is_partial_string(head, tail, &mut self.lexer.machine_st.atom_tbl) {
-                                Ok((string_buf, tail_opt)) => {
-                                    Term::PartialString(Cell::default(), string_buf, tail_opt)
+                            match as_partial_string(head, tail) {
+                                Ok((string_buf, Some(tail))) => {
+                                    Term::PartialString(Cell::default(), string_buf, tail)
+                                }
+                                Ok((string_buf, None)) => {
+                                    let atom = self.lexer.machine_st.atom_tbl.build_with(&string_buf);
+                                    Term::CompleteString(Cell::default(), atom)
                                 }
                                 Err(term) => term,
                             },
                         );
-
-                        /*
-                        self.terms.push(Term::Cons(
-                            Cell::default(),
-                            Box::new(head),
-                            Box::new(tail),
-                        ));
-                        */
                     } else {
-                        self.terms
-                            .push(Term::Clause(Cell::default(), name, subterms));
+                        self.terms.push(Term::Clause(Cell::default(), name, subterms));
                     }
 
                     if let Some(&mut TokenDesc {
@@ -741,9 +740,13 @@ impl<'a, R: CharRead> Parser<'a, R> {
 
         self.terms.push(match list {
             Term::Cons(_, head, tail) => {
-                match is_partial_string(*head, *tail, &mut self.lexer.machine_st.atom_tbl) {
-                    Ok((string_buf, tail_opt)) => {
-                        Term::PartialString(Cell::default(), string_buf, tail_opt)
+                match as_partial_string(*head, *tail) {
+                    Ok((string_buf, Some(tail))) => {
+                        Term::PartialString(Cell::default(), string_buf, tail)
+                    }
+                    Ok((string_buf, None)) => {
+                        let atom = self.lexer.machine_st.atom_tbl.build_with(&string_buf);
+                        Term::CompleteString(Cell::default(), atom)
                     }
                     Err(term) => term,
                 }
index 20af4836aa6dcbad11a8a2b2ea8c20cf12483ad9..c58e99f4f17fae9d0aea51a2a2cd04700e672ffe 100644 (file)
@@ -286,7 +286,7 @@ impl<'a, 'b> TermWriter<'a, 'b> {
         match term {
             &TermRef::Cons(..) => list_loc_as_cell!(h),
             &TermRef::AnonVar(_) | &TermRef::Var(..) => heap_loc_as_cell!(h),
-            &TermRef::PartialString(_, _, ref src, None) =>
+            &TermRef::CompleteString(_, _, ref src) =>
                 if src.as_str().is_empty() {
                     empty_list_as_cell!()
                 } else if self.heap[h].get_tag() == HeapCellValueTag::CStr {
@@ -369,20 +369,17 @@ impl<'a, 'b> TermWriter<'a, 'b> {
 
                     continue;
                 }
-                &TermRef::PartialString(lvl, _, ref src, tail) => {
-                    if tail.is_some() {
-                        allocate_pstr(self.heap, src.as_str(), self.atom_tbl);
-                    } else {
-                        put_complete_string(self.heap, src.as_str(), self.atom_tbl);
-                    }
+                &TermRef::CompleteString(_, _, ref src) => {
+                    put_complete_string(self.heap, src.as_str(), self.atom_tbl);
+                }
+                &TermRef::PartialString(lvl, _, ref src, _) => {
+                    allocate_pstr(self.heap, src.as_str(), self.atom_tbl);
 
-                    if tail.is_some() {
-                        let h = self.heap.len();
-                        self.queue.push_back((1, h - 1));
+                    let h = self.heap.len();
+                    self.queue.push_back((1, h - 1));
 
-                        if let Level::Root = lvl {
-                            continue;
-                        }
+                    if let Level::Root = lvl {
+                        continue;
                     }
                 }
                 &TermRef::Var(_, _, ref var) => {