]> Repositorios git - scryer-prolog.git/commitdiff
expand goals in queries and queues
authorMark Thom <[email protected]>
Sat, 2 Feb 2019 06:36:51 +0000 (23:36 -0700)
committerMark Thom <[email protected]>
Sat, 2 Feb 2019 06:36:51 +0000 (23:36 -0700)
src/main.rs
src/prolog/compile.rs
src/prolog/lib/atts.pl
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/term_expansion.rs
src/prolog/read.rs
src/prolog/toplevel.rs
src/prolog/write.rs
src/tests.rs

index 3f0076e99001df9037c39b856c26a20f30198012..48dc33d49d23dcb1ad210d84064d0c11112e0771 100644 (file)
@@ -9,6 +9,7 @@ mod prolog;
 use prolog::compile::*;
 use prolog::machine::*;
 use prolog::read::*;
+use prolog::toplevel::string_to_toplevel;
 use prolog::write::*;
 
 use std::io::{Write, stdin, stdout};
@@ -23,9 +24,14 @@ fn prolog_repl() {
         print!("prolog> ");
         stdout().flush().unwrap();
         
-        match read_toplevel(&mut wam) {
-            Ok(Input::Term(term)) => {
-                let result = compile_term(&mut wam, term);
+        match toplevel_read_line() {
+            Ok(Input::TermString(buffer)) => {
+                let stdin  = stdin();
+                let result = match string_to_toplevel(stdin.lock(), buffer, &mut wam) {
+                    Ok(packet) => compile_term(&mut wam, packet),
+                    Err(e) => EvalSession::from(e)
+                };
+
                 print(&mut wam, result)
             },
             Ok(Input::Batch) => {
index 2f746e79d83dd4c6fd1cb171cab97b9ce08e2030..49c1f491deee0ce42ba347bf1a59af26048055a2 100644 (file)
@@ -138,10 +138,8 @@ fn compile_decl(wam: &mut Machine, compiler: &mut ListingCompiler, decl: Declara
     Ok(indices)
 }
 
-pub fn compile_term(wam: &mut Machine, term: Term) -> EvalSession
+pub fn compile_term(wam: &mut Machine, packet: TopLevelPacket) -> EvalSession
 {
-    let packet = try_eval_session!(consume_term(term, &mut wam.indices));
-
     match packet {
         TopLevelPacket::Query(terms, queue) =>
             match compile_query(terms, queue, wam.machine_flags()) {
@@ -260,7 +258,7 @@ impl ListingCompiler {
                                                  wam.machine_flags())?;
 
             compile_appendix(&mut decl_code, &queue, non_counted_bt, wam.machine_flags())?;
-            
+
             let idx = code_dir.entry((name, arity)).or_insert(CodeIndex::default());
             set_code_index!(idx, IndexPtr::Index(p), self.get_module_name());
 
@@ -384,7 +382,6 @@ impl ListingCompiler {
                              -> Result<GatherResult, SessionError>
     {
         let flags = wam.machine_flags();
-        let machine_st  = &mut wam.machine_st;
         let wam_indices = &mut wam.indices;
 
         let atom_tbl   = wam_indices.atom_tbl.clone();
@@ -395,7 +392,7 @@ impl ListingCompiler {
         let mut toplevel_results = vec![];
         let mut toplevel_indices = default_index_store!(atom_tbl.clone());
 
-        while let Some(decl) = worker.consume(machine_st, indices)? {
+        while let Some(decl) = worker.consume(indices)? {
             if decl.is_module_decl() {
                 toplevel_indices.copy_and_swap(indices);
                 mem::swap(&mut worker.results, &mut toplevel_results);
index a202e2de62a52ecfb166fc20d6e58b6cd91ed2f7..76c600c9004728140d14e0209fd256eaf8b13709 100644 (file)
@@ -111,9 +111,9 @@ get_attr(Name, Arity) -->
      (get_atts(V,  Attr) :- !, functor(Attr, _, _), get_attr(V, Attr)),
      (get_atts(V, -Attr) :- !, functor(Attr, _, _), absent_attr(V, Attr))].
 
-user:goal_expansion(Term, [M:put_atts(Var, Attr)]) :-
+user:goal_expansion(Term, M:put_atts(Var, Attr)) :-
     nonvar(Term),
     Term = put_atts(Var, M, Attr).
-user:goal_expansion(Term, [M:get_atts(Var, Attr)]) :-
+user:goal_expansion(Term, M:get_atts(Var, Attr)) :-
     nonvar(Term),
     Term = get_atts(Var, M, Attr).
index efe72501a3bc50b48ac69480be7d6744327215eb..11a41941eb8e5c10e1b0feface5a1b8304af9eb5 100644 (file)
@@ -31,7 +31,7 @@ macro_rules! try_or_fail {
 }
 
 impl MachineState {
-    pub(super) fn new() -> Self {
+    pub(crate) fn new() -> Self {
         MachineState {
             s: 0,
             p: CodePtr::default(),
index 2106895ad3749ddc3f320a1e6d84eb4ebca14fad..2b336973e3093caf5550953d7148e8da586cec69 100644 (file)
@@ -193,17 +193,17 @@ impl<'a, R: Read> TermStream<'a, R> {
         }
     }
 
-    fn parse_expansion_output(&mut self, term_string: &str, op_dir: &OpDir)
-                              -> Result<Term, ParserError>
+    fn parse_expansion_output(&self, term_string: &str, op_dir: &OpDir) -> Result<Term, ParserError>
     {
         let mut parser = Parser::new(term_string.trim().as_bytes(), self.parser.get_atom_tbl(),
                                      self.flags);
         parser.read_term(composite_op!(self.in_module, &self.indices.op_dir, op_dir))
     }
 
-    pub fn read_term(&mut self, machine_st: &mut MachineState, op_dir: &OpDir)
-                     -> Result<Term, ParserError>
+    pub fn read_term(&mut self, op_dir: &OpDir) -> Result<Term, ParserError>
     {
+        let mut machine_st = MachineState::new();
+
         loop {
             while let Some(term) = self.stack.pop() {
                 match machine_st.try_expand_term(self.indices, self.policies, self.code_repo,
@@ -214,7 +214,7 @@ impl<'a, R: Read> TermStream<'a, R> {
                         self.enqueue_term(term)?
                     },
                     None => {
-                        let term = self.run_goal_expanders(machine_st, op_dir, term)?;
+                        let term = self.run_goal_expanders(&mut machine_st, op_dir, term)?;
                         return Ok(term);
                     }
                 };
@@ -227,6 +227,7 @@ impl<'a, R: Read> TermStream<'a, R> {
         }
     }
 
+    pub(crate)
     fn run_goal_expanders(&mut self, machine_st: &mut MachineState, op_dir: &OpDir, term: Term)
                           -> Result<Term, ParserError>
     {
@@ -257,8 +258,7 @@ impl<'a, R: Read> TermStream<'a, R> {
         }
     }
 
-    fn expand_goals(&mut self, machine_st: &mut MachineState, op_dir: &OpDir,
-                    mut terms: VecDeque<Term>)
+    fn expand_goals(&mut self, machine_st: &mut MachineState, op_dir: &OpDir, mut terms: VecDeque<Term>)
                     -> Result<Vec<Term>, ParserError>
     {
         let mut results = vec![];
@@ -275,8 +275,7 @@ impl<'a, R: Read> TermStream<'a, R> {
                             for term in extract_from_list(head, tail)? {
                                 terms.push_front(term);
                             },
-                        term =>
-                            terms.push_front(term)
+                        term => terms.push_front(term)
                     };
                 },
                 None => results.push(term)
index 891280ad3b794bb522a1149bec03f76358eed793..6dc39e3e85c119f9aa91781cfabf20f44ba1434f 100644 (file)
@@ -4,9 +4,7 @@ use prolog_parser::tabled_rc::TabledData;
 
 use prolog::instructions::*;
 use prolog::iterators::*;
-use prolog::machine::*;
 use prolog::machine::machine_state::MachineState;
-use prolog::machine::term_expansion::*;
 
 use std::collections::VecDeque;
 use std::io::{Read, stdin};
@@ -28,10 +26,10 @@ pub enum Input {
     Quit,
     Clear,
     Batch,
-    Term(Term)
+    TermString(String)
 }
 
-pub fn read_toplevel(wam: &mut Machine) -> Result<Input, ParserError> {
+pub fn toplevel_read_line() -> Result<Input, ParserError> {
     let mut buffer = String::new();
 
     let stdin = stdin();
@@ -44,14 +42,7 @@ pub fn read_toplevel(wam: &mut Machine) -> Result<Input, ParserError> {
             println!("(type Enter + Ctrl-D to terminate the stream when finished)");
             Ok(Input::Batch)
         },
-        _ => {
-            let mut term_stream = TermStream::new(stdin.lock(), wam.indices.atom_tbl.clone(),
-                                                  wam.machine_flags(), &mut wam.indices,
-                                                  &mut wam.policies, &mut wam.code_repo);
-
-            term_stream.add_to_top(buffer.as_str());
-            Ok(Input::Term(term_stream.read_term(&mut wam.machine_st, &OpDir::new())?))
-        }
+        _ => Ok(Input::TermString(buffer))
     }
 }
 
index cc8be68e67858b18c1967e2a2cff53e85c38fa76..edafbe2d237882f82d18ed8c660f11a4bde5c48b 100644 (file)
@@ -700,7 +700,6 @@ impl RelationWorker {
         while let Some(terms) = self.queue.pop_front() {
             let clauses = merge_clauses(&mut self.try_terms_to_tls(indices, terms, false)?)?;
             queue.push_back(clauses);
-
         }
 
         Ok(queue)
@@ -709,29 +708,59 @@ impl RelationWorker {
     fn absorb(&mut self, other: RelationWorker) {
         self.queue.extend(other.queue.into_iter());
     }
+
+    fn expand_queue_contents<'a, R>(&mut self, term_stream: &mut TermStream<'a, R>, op_dir: &OpDir)
+                                    -> Result<(), SessionError>
+        where R: Read
+    {
+        let mut machine_st = MachineState::new();
+        let mut new_queue  = VecDeque::new();
+
+        while let Some(terms) = self.queue.pop_front() {
+            let mut new_terms = VecDeque::new();
+
+            for term in terms {
+                new_terms.push_back(term_stream.run_goal_expanders(&mut machine_st, &op_dir, term)?);
+            }
+
+            new_queue.push_back(new_terms);
+        }
+
+        Ok(self.queue = new_queue)
+    }
 }
 
-// used to parse queries in test.
-#[cfg(test)]
-pub fn parse_term<R: Read>(wam: &Machine, buf: R) -> Result<Term, ParserError>
+fn term_to_toplevel<'a, R>(term_stream: &mut TermStream<'a, R>, code_dir: &mut CodeDir, term: Term)
+                           -> Result<(TopLevel, RelationWorker), ParserError>
+    where R: Read
 {
-    use prolog_parser::parser::*;
+    let mut rel_worker = RelationWorker::new();
+    let mut indices = composite_indices!(false, term_stream.indices, code_dir);
 
-    let mut parser = Parser::new(buf, wam.indices.atom_tbl.clone(), wam.machine_flags());
-    parser.read_term(composite_op!(&wam.indices.op_dir))
+    Ok((rel_worker.try_term_to_tl(&mut indices, term, true)?, rel_worker))
 }
 
 pub
-fn consume_term(term: Term, indices: &mut IndexStore) -> Result<TopLevelPacket, ParserError>
+fn string_to_toplevel<R: Read>(src: R, buffer: String, wam: &mut Machine)
+                               -> Result<TopLevelPacket, SessionError>
 {
-    let mut rel_worker = RelationWorker::new();
+    let mut term_stream = TermStream::new(src, wam.indices.atom_tbl.clone(),
+                                          wam.machine_flags(), &mut wam.indices,
+                                          &mut wam.policies, &mut wam.code_repo);
+
+    term_stream.add_to_top(buffer.as_str());
+
+    let term = term_stream.read_term(&OpDir::new())?;
     let mut code_dir = CodeDir::new();
-    let mut indices = composite_indices!(false, indices, &mut code_dir);
 
-    let tl = rel_worker.try_term_to_tl(&mut indices, term, true)?;
-    let results = rel_worker.parse_queue(&mut indices)?;
+    let (tl, mut rel_worker) = term_to_toplevel(&mut term_stream, &mut code_dir, term)?;
+
+    rel_worker.expand_queue_contents(&mut term_stream, &OpDir::new())?;
+
+    let mut indices = composite_indices!(false, term_stream.indices, &mut code_dir);
+    let queue = rel_worker.parse_queue(&mut indices)?;
 
-    Ok(deque_to_packet(tl, results))
+    Ok(deque_to_packet(tl, queue))
 }
 
 pub struct TopLevelBatchWorker<'a, R: Read> {
@@ -756,31 +785,47 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
                               in_module: false }
     }
 
+    fn try_term_to_tl(&self, indices: &mut IndexStore, term: Term)
+                      -> Result<(TopLevel, RelationWorker), SessionError>
+    {
+        let mut new_rel_worker = RelationWorker::new();
+        let mut indices = composite_indices!(self.in_module, indices,
+                                             &self.term_stream.indices.code_dir);
+
+        Ok((new_rel_worker.try_term_to_tl(&mut indices, term, true)?, new_rel_worker))
+    }
+
+    fn process_result(&mut self, indices: &mut IndexStore, preds: &mut Vec<PredicateClause>)
+                      -> Result<(Predicate, VecDeque<TopLevel>), SessionError>
+    {
+        self.rel_worker.expand_queue_contents(&mut self.term_stream, &indices.op_dir)?;
+
+        let mut indices = composite_indices!(self.in_module, indices,
+                                             &mut self.term_stream.indices.code_dir);
+
+        let queue  = self.rel_worker.parse_queue(&mut indices)?;
+        let result = (append_preds(preds), queue);
+
+        let in_situ_code_dir = &mut self.term_stream.indices.in_situ_code_dir;
+
+        self.term_stream.code_repo.add_in_situ_result(&result, in_situ_code_dir,
+                                                      self.term_stream.flags)?;
+
+        Ok(result)
+    }
+
     pub
-    fn consume(&mut self, machine_st: &mut MachineState, indices: &mut IndexStore)
-               -> Result<Option<Declaration>, SessionError>
+    fn consume(&mut self, indices: &mut IndexStore) -> Result<Option<Declaration>, SessionError>
     {
         let mut preds = vec![];
 
         while !self.term_stream.eof()? {
-            let mut new_rel_worker = RelationWorker::new();
-            let term = self.term_stream.read_term(machine_st, &indices.op_dir)?;
+            let term = self.term_stream.read_term(&indices.op_dir)?;
+            let (tl, new_rel_worker) = self.try_term_to_tl(indices, term)?;
 
-            let mut indices =
-                composite_indices!(self.in_module, indices,
-                                   &mut self.term_stream.indices.code_dir);
-
-            let tl = new_rel_worker.try_term_to_tl(&mut indices, term, true)?;
-
-            // if is_consistent returns false, preds is non-empty.
+            // if is_consistent is false, preds is non-empty.
             if !is_consistent(&tl, &preds) {
-                let result_queue = self.rel_worker.parse_queue(&mut indices)?;
-                let result = (append_preds(&mut preds), result_queue);
-                let in_situ_code_dir = &mut self.term_stream.indices.in_situ_code_dir;
-
-                self.term_stream.code_repo.add_in_situ_result(&result,
-                                                              in_situ_code_dir,
-                                                              self.term_stream.flags)?;
+                let result = self.process_result(indices, &mut preds)?;
                 self.results.push(result);
             }
 
@@ -796,12 +841,8 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> {
         }
 
         if !preds.is_empty() {
-            let mut indices =
-                composite_indices!(self.in_module, indices,
-                                   &mut self.term_stream.indices.code_dir);
-
-            let result_queue = self.rel_worker.parse_queue(&mut indices)?;
-            self.results.push((append_preds(&mut preds), result_queue));
+            let result = self.process_result(indices, &mut preds)?;
+            self.results.push(result);
         }
 
         Ok(None)
index 1b6bf0c1fb90c8c785164852361fc4d86169606f..e54d8527ed7b7074a3e098b311f1a91b61f7b762 100644 (file)
@@ -320,7 +320,7 @@ impl fmt::Display for Level {
 pub fn print(wam: &mut Machine, result: EvalSession) {
     match result {
         EvalSession::InitialQuerySuccess(alloc_locs, mut heap_locs) => {
-            if heap_locs.is_empty() {
+            if wam.or_stack_is_empty() && heap_locs.is_empty() {
                 println!("true.");
                 return;
             }
index 4e5ab35e125f4960b3768242d130e840aa3535a1..df2904a3f8079e8337bf94c6eb2f3329d2fb6c17 100644 (file)
@@ -5,6 +5,7 @@ use prolog::machine::*;
 use prolog::toplevel::*;
 
 use std::collections::HashSet;
+use std::io::empty;
 use std::mem::swap;
 use std::ops::{Range, RangeFrom};
 
@@ -146,7 +147,7 @@ pub fn submit_query(wam: &mut Machine, buffer: &str, result: Vec<HashSet<String>
 {
     wam.reset();
 
-    match parse_term(&wam, buffer.as_bytes()) {
+    match string_to_toplevel(empty(), String::from(buffer), wam) {
         Ok(term) =>
             match compile_term(wam, term) {
                 EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
@@ -154,22 +155,23 @@ pub fn submit_query(wam: &mut Machine, buffer: &str, result: Vec<HashSet<String>
                 EvalSession::EntrySuccess => true,
                 _ => false
             },
-        Err(e) => panic!("syntax_error({})", e.as_str())
+        Err(_) => panic!("syntax error")
     }
 }
 
 #[allow(dead_code)]
-pub fn submit_query_without_results(wam: &mut Machine, buffer: &str) -> bool {
+pub fn submit_query_without_results(wam: &mut Machine, buffer: &str) -> bool
+{
     wam.reset();
 
-    match parse_term(&wam, buffer.as_bytes()) {
+    match string_to_toplevel(empty(), String::from(buffer), wam) {
         Ok(term) =>
             match compile_term(wam, term) {
                 EvalSession::InitialQuerySuccess(..)
               | EvalSession::EntrySuccess => true,
                 _ => false
             },
-        Err(e) => panic!("syntax_error({})", e.as_str())
+        Err(_) => panic!("syntax error")
     }
 }
 
@@ -180,7 +182,7 @@ pub fn submit_query_with_limit(wam: &mut Machine, buffer: &str,
 {
     wam.reset();
 
-    match parse_term(&wam, buffer.as_bytes()) {
+    match string_to_toplevel(empty(), String::from(buffer), wam) {
         Ok(term) =>
             match compile_term(wam, term) {
                 EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
@@ -189,7 +191,7 @@ pub fn submit_query_with_limit(wam: &mut Machine, buffer: &str,
                 EvalSession::EntrySuccess => true,
                 _ => false
             },
-        Err(e) => panic!("syntax_error({})", e.as_str())
+        Err(_) => panic!("syntax_error")
     }
 }