]> Repositorios git - scryer-prolog.git/commitdiff
re: issue #120
authorMark Thom <[email protected]>
Sat, 27 Apr 2019 06:40:00 +0000 (00:40 -0600)
committerMark Thom <[email protected]>
Sat, 27 Apr 2019 06:40:00 +0000 (00:40 -0600)
Cargo.toml
src/prolog/heap_print.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/system_calls.rs
src/prolog/machine/toplevel.rs
src/tests.rs

index 8374e5be0340d0b291fe501b17127696a0d5e02d..4bdfe967b04dee47cd8f1e06514bb608cce9aeb7 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "scryer-prolog"
-version = "0.8.67"
+version = "0.8.68"
 authors = ["Mark Thom <[email protected]>"]
 repository = "https://github.com/mthom/scryer-prolog"
 description = "A modern Prolog implementation written mostly in Rust."
index 431f698ba00be6518bffed7803e212e8f602c1a1..bb1dba0dc250dac80bd0d53a727f2d216d48a770 100644 (file)
@@ -137,6 +137,7 @@ impl<'a> HCPreOrderIterator<'a> {
 
 fn char_to_string(c: char) -> String {
     match c {
+        '\'' => "\\'".to_string(),
         '\n' => "\\n".to_string(),
         '\r' => "\\r".to_string(),
         '\t' => "\\t".to_string(),
index 4e064c61b61832981aa708be1b6051333f475045..fd6b8c92f539c660eecacdf469a81d8cf2b09216 100644 (file)
@@ -320,6 +320,26 @@ fn try_in_situ(machine_st: &mut MachineState, name: ClauseName, arity: usize,
     }
 }
 
+pub(super) fn try_char_list(addrs: Vec<Addr>) -> Result<String, MachineError>
+{        
+    let mut chars = String::new();
+
+    for addr in addrs.iter() {
+        match addr {
+            &Addr::Con(Constant::Char(c)) =>
+                chars.push(c),
+            &Addr::Con(Constant::Atom(ref name, _))
+                if name.as_str().len() == 1 => {
+                    chars += name.as_str();
+                },
+            _ =>
+                return Err(MachineError::type_error(ValidType::Character, addr.clone()))
+        }
+    }
+
+    Ok(chars)        
+}
+
 pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
 
 pub(crate) trait CallPolicy: Any {
@@ -635,15 +655,11 @@ pub(crate) trait CallPolicy: Any {
                 return_from_clause!(machine_st.last_call, machine_st)
             },
             &BuiltInClauseType::PartialString => {
-                let a1 = machine_st[temp_v!(1)].clone();
+                let mut s = machine_st.try_string_list(temp_v!(1))?;
                 let a2 = machine_st[temp_v!(2)].clone();
 
-                if let Addr::Con(Constant::String(s)) = a1 {
-                    s.set_expandable(true);
-                    machine_st.write_constant_to_var(a2, Constant::String(s));
-                } else {
-                    machine_st.fail = true;
-                }
+                s.set_expandable(true);
+                machine_st.write_constant_to_var(a2, Constant::String(s));
 
                 return_from_clause!(machine_st.last_call, machine_st)
             },
index 33d862a006b60e32d6653537b3388338e22aeb3c..70427a6509792508bf15a10e081fca03fe51a0c5 100644 (file)
@@ -2165,6 +2165,29 @@ impl MachineState {
         *list = result;
     }
 
+    pub(super)
+    fn try_string_list(&self, r: RegType) -> Result<StringList, MachineStub> {
+        let a1 = self[r].clone();
+        let a1 = self.store(self.deref(a1));
+
+        if let Addr::Con(Constant::String(s)) = a1 {
+            return Ok(s);
+        } else {
+            let stub = MachineError::functor_stub(clause_name!("partial_string"), 2);
+            
+            match self.try_from_list(r, stub.clone()) {
+                Ok(addrs) =>
+                    Ok(StringList::new(match try_char_list(addrs) {
+                        Ok(string) => string,
+                        Err(err) => {                            
+                            return Err(self.error_form(err, stub));
+                        }
+                    }, false)),
+                Err(err) => return Err(err)
+            }
+        }
+    }
+
     pub(super)
     fn try_from_list(&self, r: RegType, caller: MachineStub) -> Result<Vec<Addr>, MachineStub>
     {
index a0f8b042c2b37401a50797273abb2d68cdb5b797..508b946ee83812236757cbe8aadc7ced5e75e160 100644 (file)
@@ -9,7 +9,7 @@ use prolog::machine::copier::*;
 use prolog::machine::machine_errors::*;
 use prolog::machine::machine_indices::*;
 use prolog::machine::machine_state::*;
-use prolog::machine::toplevel::to_op_decl;
+use prolog::machine::toplevel::{to_op_decl};
 use prolog::num::{FromPrimitive, ToPrimitive, Zero};
 use prolog::num::bigint::{BigInt};
 use prolog::read::{PrologStream, readline};
@@ -35,7 +35,7 @@ impl BrentAlgState {
     }
 }
 
-impl MachineState {
+impl MachineState {    
     // a step in Brent's algorithm.
     fn brents_alg_step(&self, brent_st: &mut BrentAlgState) -> Option<CycleSearchResult>
     {
@@ -393,28 +393,15 @@ impl MachineState {
 
                         match self.try_from_list(temp_v!(2), stub.clone()) {
                             Err(e) => return Err(e),
-                            Ok(addrs) => {
-                                let mut chars = String::new();
-
-                                for addr in addrs.iter() {
-                                    match addr {
-                                        &Addr::Con(Constant::Char(c)) =>
-                                            chars.push(c),
-                                        &Addr::Con(Constant::Atom(ref name, _))
-                                            if name.as_str().len() == 1 => {
-                                                chars += name.as_str();
-                                            },
-                                        _ => {
-                                            let err = MachineError::type_error(ValidType::Character,
-                                                                               addr.clone());
-                                            return Err(self.error_form(err, stub));
-                                        }
-                                    }
-                                }
-
-                                let chars = clause_name!(chars, indices.atom_tbl);
-                                self.unify(addr.clone(), Addr::Con(Constant::Atom(chars, None)));
-                            }
+                            Ok(addrs) =>
+                                match try_char_list(addrs) {
+                                    Ok(string) => {
+                                        let chars = clause_name!(string, indices.atom_tbl);
+                                        self.unify(addr.clone(), Addr::Con(Constant::Atom(chars, None)));
+                                    },
+                                    Err(err) => 
+                                        return Err(self.error_form(err, stub))
+                                }                        
                         }
                     },
                     _ => unreachable!()
index 65ed9c9a798252851c61dc7c1a600d031eae8a64..2949b8ebfa51ed53779aa8428f217a0791f825f0 100644 (file)
@@ -390,13 +390,15 @@ pub enum TopLevelPacket {
 }
 
 struct RelationWorker {
+    flags: MachineFlags,
     dynamic_clauses: Vec<(Term, Term)>, // Head, Body.
     queue: VecDeque<VecDeque<Term>>,
 }
 
 impl RelationWorker {
-    fn new() -> Self {
+    fn new(flags: MachineFlags) -> Self {
         RelationWorker { dynamic_clauses: vec![],
+                         flags,
                          queue: VecDeque::new() }
     }
 
@@ -538,14 +540,8 @@ impl RelationWorker {
                             Err(ParserError::InadmissibleQueryTerm)
                         },
                     ("partial_string", 2) => {
-                        if let Term::Constant(_, Constant::String(_)) = *terms[0].clone() {
-                            if let Term::Var(..) = *terms[1].clone() {
-                                let ct = ClauseType::BuiltIn(BuiltInClauseType::PartialString);
-                                return Ok(QueryTerm::Clause(Cell::default(), ct, terms, false));
-                            }
-                        }
-
-                        Err(ParserError::InadmissibleQueryTerm)
+                        let ct = ClauseType::BuiltIn(BuiltInClauseType::PartialString);
+                        return Ok(QueryTerm::Clause(Cell::default(), ct, terms, false));
                     },
                     _ => {
                         let ct = indices.get_clause_type(name, terms.len(), fixity);
@@ -768,11 +764,11 @@ impl RelationWorker {
     }
 }
 
-fn term_to_toplevel<R>(term_stream: &mut TermStream<R>, code_dir: &mut CodeDir, term: Term)
+fn term_to_toplevel<R>(term_stream: &mut TermStream<R>, code_dir: &mut CodeDir, term: Term, flags: MachineFlags)
                        -> Result<(TopLevel, RelationWorker), ParserError>
     where R: Read
 {
-    let mut rel_worker = RelationWorker::new();
+    let mut rel_worker = RelationWorker::new(flags);
     let mut indices = composite_indices!(false, term_stream.indices, code_dir);
 
     let tl = rel_worker.try_term_to_tl(&mut indices, term, true)?;
@@ -784,6 +780,7 @@ pub
 fn stream_to_toplevel<R: Read>(mut buffer: ParsingStream<R>, wam: &mut Machine)
                                -> Result<TopLevelPacket, SessionError>
 {
+    let flags = wam.machine_flags();
     let mut term_stream = TermStream::new(&mut buffer, wam.indices.atom_tbl(),
                                           wam.machine_flags(), &mut wam.indices,
                                           &mut wam.policies, &mut wam.code_repo);
@@ -791,9 +788,9 @@ fn stream_to_toplevel<R: Read>(mut buffer: ParsingStream<R>, wam: &mut Machine)
     term_stream.add_to_top("?- ");
 
     let term = term_stream.read_term(&OpDir::new())?;
-    let mut code_dir = CodeDir::new();
+    let mut code_dir = CodeDir::new();    
 
-    let (tl, mut rel_worker) = term_to_toplevel(&mut term_stream, &mut code_dir, term)?;
+    let (tl, mut rel_worker) = term_to_toplevel(&mut term_stream, &mut code_dir, term, flags)?;
     rel_worker.expand_queue_contents(&mut term_stream, &OpDir::new())?;
 
     let mut indices = composite_indices!(false, term_stream.indices, &mut code_dir);
@@ -823,7 +820,7 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
                                           indices, policies, code_repo);
 
         TopLevelBatchWorker { term_stream,
-                              rel_worker: RelationWorker::new(),
+                              rel_worker: RelationWorker::new(flags),
                               results: vec![],
                               dynamic_clause_map: HashMap::new(),
                               in_module: false }
@@ -832,7 +829,7 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
     fn try_term_to_tl(&self, indices: &mut IndexStore, term: Term)
                       -> Result<(TopLevel, RelationWorker), SessionError>
     {
-        let mut new_rel_worker = RelationWorker::new();
+        let mut new_rel_worker = RelationWorker::new(self.rel_worker.flags);
         let mut indices = composite_indices!(self.in_module, indices,
                                              &self.term_stream.indices.code_dir);
 
@@ -877,7 +874,8 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
         }
     }
 
-    pub fn consume(&mut self, indices: &mut IndexStore) -> Result<Option<Declaration>, SessionError>
+    pub fn consume(&mut self, indices: &mut IndexStore)
+                   -> Result<Option<Declaration>, SessionError>
     {
         let mut preds = vec![];
 
index 5f9e8270374efdfacadba6d0884fbaf28749aa94..4ea95c81d5ec05de7042519cd351d21d46497f55 100644 (file)
@@ -2391,7 +2391,7 @@ fn test_queries_on_string_lists()
     assert_prolog_success!(&mut wam, "partial_string(\"appendy\", X), f(X).",
                            [["X = [a, p, p, e, n, d, y, ' ', j, o, n, e, s]"],
                             ["X = [a, p, p, e, n, d, y, ' ', s, m, i, t, h, e, r, s, ' ', j, o, n, e, s]"],
-                            ["X = [a, p, p, e, n, d, y, ' ', o, ''', t, o, o, l, e]"]]);
+                            ["X = [a, p, p, e, n, d, y, ' ', o, '\\'', t, o, o, l, e]"]]);
 
     assert_prolog_success!(&mut wam, "partial_string(\"abc\", X), partial_string(\"abcdef\", X).",
                            [["X = [a, b, c, d, e, f | _]"]]);