]> Repositorios git - scryer-prolog.git/commitdiff
add the initialization directive
authorMark Thom <[email protected]>
Tue, 1 Oct 2019 22:51:22 +0000 (16:51 -0600)
committerMark Thom <[email protected]>
Tue, 1 Oct 2019 22:51:22 +0000 (16:51 -0600)
Cargo.toml
src/prolog/forms.rs
src/prolog/machine/compile.rs
src/prolog/machine/machine_errors.rs
src/prolog/machine/mod.rs
src/prolog/machine/modules.rs
src/prolog/machine/term_expansion.rs
src/prolog/machine/toplevel.rs

index b9d6df859778f1fa7940310d1a93b44d6907ab2c..86ed4cc5b4dc7cf1a25d57f603151dd710770d60 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "scryer-prolog"
-version = "0.8.96"
+version = "0.8.97"
 authors = ["Mark Thom <[email protected]>"]
 build = "build.rs"
 repository = "https://github.com/mthom/scryer-prolog"
index 1fe2700250cbbdc52b7ab6ff1d1f55547f05ae08..0f05587c9f242e740ab47c34ba6cd2cdd57f98ea 100644 (file)
@@ -174,6 +174,7 @@ pub enum Declaration {
     Dynamic(ClauseName, usize), // name, arity
     EndOfFile,
     Hook(CompileTimeHook, PredicateClause, VecDeque<TopLevel>),
+    ModuleInitialization(Vec<QueryTerm>, VecDeque<TopLevel>), // goal
     Module(ModuleDecl),
     NonCountedBacktracking(ClauseName, usize), // name, arity
     Op(OpDecl),
@@ -328,7 +329,7 @@ pub struct Module {
     pub user_term_expansions: (Predicate, VecDeque<TopLevel>), // term expansions inherited from the user scope.
     pub user_goal_expansions: (Predicate, VecDeque<TopLevel>), // same for goal_expansions.
     pub inserted_expansions: bool, // has the module been successfully inserted into toplevel??
-}
+ }
 
 #[derive(Clone, PartialEq, Eq)]
 pub enum Number {
index 6d391f9a580f6f4c880697882f403db2174877e7..2df48229c617367de66dba3766da0e40d6f837e2 100644 (file)
@@ -420,6 +420,7 @@ pub struct ListingCompiler {
     user_term_dir: TermDir,
     orig_term_expansion_lens: (usize, usize),
     orig_goal_expansion_lens: (usize, usize),
+    initialization_goals: (Vec<QueryTerm>, VecDeque<TopLevel>)
 }
 
 fn add_toplevel_code(wam: &mut Machine, code: Code, mut indices: IndexStore) {
@@ -485,6 +486,7 @@ impl ListingCompiler {
                 .term_dir_entry_len((clause_name!("term_expansion"), 2)),
             orig_goal_expansion_lens: code_repo
                 .term_dir_entry_len((clause_name!("goal_expansion"), 2)),
+           initialization_goals: (vec![], VecDeque::from(vec![]))
         }
     }
 
@@ -531,7 +533,7 @@ impl ListingCompiler {
                 wam_indices.insert_module(submodule)
             );
 
-            if let &mut Some(ref mut module) = &mut self.module {
+            if let Some(ref mut module) = &mut self.module {
                 module.remove_module(module_name, &submodule);
                 unwind_protect!(
                     module.use_module(code_repo, flags, &submodule),
@@ -590,6 +592,18 @@ impl ListingCompiler {
             .unwrap_or(ClauseName::BuiltIn("user"))
     }
 
+    fn generate_init_goal_code(
+       &mut self,
+       flags: MachineFlags
+    ) -> Result<Code, SessionError> {
+       let query_terms = mem::replace(&mut self.initialization_goals.0, vec![]);
+       let queue = mem::replace(&mut self.initialization_goals.1, VecDeque::new());
+
+       compile_query(query_terms, queue, flags)
+           .map(|(code, _)| code)
+           .map_err(SessionError::from)
+    }
+
     pub(crate) fn generate_code(
         &mut self,
         decls: Vec<PredicateCompileQueue>,
@@ -766,6 +780,12 @@ impl ListingCompiler {
                     indices,
                 )
             }
+           Declaration::ModuleInitialization(query_terms, queue) => {
+               self.initialization_goals.0.extend(query_terms.into_iter());
+               self.initialization_goals.1.extend(queue.into_iter());
+               
+               Ok(())
+           }   
             Declaration::Dynamic(..) => Ok(()),
         }
     }
@@ -866,7 +886,7 @@ fn compile_work_impl(
     wam: &mut Machine,
     mut indices: IndexStore,
     mut results: GatherResult,
-) -> EvalSession {
+) -> EvalSession {   
     let module_code = try_eval_session!(compiler.generate_code(
         results.worker_results,
         wam,
@@ -916,6 +936,14 @@ fn compile_work_impl(
         ));
     }
 
+    let init_goal_code = try_eval_session!(compiler.generate_init_goal_code(
+       wam.machine_flags()
+    ));
+    
+    if init_goal_code.len() > 0 {
+       wam.run_init_code(init_goal_code);
+    }
+    
     EvalSession::EntrySuccess
 }
 
index e8eb479b3000ea0240eac9808cbcbe258bb2529b..ad0ff42761f448331196167474d1fe4c3f2cca0f 100644 (file)
@@ -127,7 +127,7 @@ impl MachineError {
         match err {
             SessionError::ParserError(err) => Self::syntax_error(h, err),
             SessionError::CannotOverwriteBuiltIn(pred_str)
-            | SessionError::CannotOverwriteImport(pred_str) => {
+          | SessionError::CannotOverwriteImport(pred_str) => {
                 Self::permission_error(PermissionError::Modify, "private_procedure", pred_str)
             }
             SessionError::InvalidFileName(filename) => {
index 0e6f3536cfa54ef865c17c74fb8e6ff30f56a9dc..a5770c62ebe3336d0f754e5bc553a602dfecedac 100644 (file)
@@ -221,6 +221,16 @@ impl Machine {
         self.machine_st.reset();
     }
 
+    pub fn run_init_code(&mut self, code: Code) {
+       let old_machine_st = self.machine_st.sink_to_snapshot();
+       self.machine_st.reset();
+       
+       self.code_repo.cached_query = code;
+       self.run_query(&AllocVarDict::new());
+
+       self.machine_st.absorb_snapshot(old_machine_st);
+    }
+
     pub fn run_top_level(&mut self) {
        use std::env;
 
@@ -433,10 +443,10 @@ impl Machine {
            // remove previous exports.
            self.indices.remove_module(clause_name!("user"), &module);
            self.indices.use_module(&mut self.code_repo, self.machine_st.flags, &module)?;
-
+           
            Ok(self.indices.insert_module(module))
-       });
-
+       });     
+       
        self.code_repo.cached_query = cached_query;
 
        if let Err(e) = result {
index 94f218baef97593ee25f94d2bf272117be9924f9..c4e26449c21598736344de44eb9d5189a37698d0 100644 (file)
@@ -281,7 +281,7 @@ impl SubModuleUser for Module {
         self.user_goal_expansions
             .1
             .extend(submodule.goal_expansions.1.iter().cloned());
-
+       
         Ok(())
     }
 }
index eaa4d23e5571c31d345880a21ee1725586208a10..3880ac416d75ceb5618c5faa52ec2274e7da63a5 100644 (file)
@@ -369,8 +369,8 @@ impl MachineState {
         self[temp_v!(2)] = Addr::HeapCell(h);
 
         let code = vec![call_clause!(ClauseType::Hook(hook), 2, 0, true)];
-
         wam.code_repo.cached_query = code;
+       
         self.query_stepper(
             &mut wam.indices,
             &mut wam.policies,
index 6eca3e084e1394f42bae4f3d40397673f207ea55..3a7c4322fba8e2fcd2a20e279b6856a05e3f5a2b 100644 (file)
@@ -265,34 +265,6 @@ fn setup_qualified_import(mut terms: Vec<Box<Term>>) -> Result<UseModuleExport,
     }
 }
 
-fn setup_declaration(mut terms: Vec<Box<Term>>) -> Result<Declaration, ParserError> {
-    let term = *terms.pop().unwrap();
-
-    match term {
-        Term::Clause(_, name, mut terms, _) => {
-            if name.as_str() == "op" && terms.len() == 3 {
-                Ok(Declaration::Op(setup_op_decl(terms)?))
-            } else if name.as_str() == "module" && terms.len() == 2 {
-                Ok(Declaration::Module(setup_module_decl(terms)?))
-            } else if name.as_str() == "use_module" && terms.len() == 1 {
-                Ok(Declaration::UseModule(setup_use_module_decl(terms)?))
-            } else if name.as_str() == "use_module" && terms.len() == 2 {
-                let (name, exports) = setup_qualified_import(terms)?;
-                Ok(Declaration::UseQualifiedModule(name, exports))
-            } else if name.as_str() == "non_counted_backtracking" && terms.len() == 1 {
-                let (name, arity) = setup_predicate_indicator(*terms.pop().unwrap())?;
-                Ok(Declaration::NonCountedBacktracking(name, arity))
-            } else if name.as_str() == "dynamic" && terms.len() == 1 {
-                let (name, arity) = setup_predicate_indicator(*terms.pop().unwrap())?;
-                Ok(Declaration::Dynamic(name, arity))
-            } else {
-                Err(ParserError::InconsistentEntry)
-            }
-        }
-        _ => return Err(ParserError::InconsistentEntry),
-    }
-}
-
 fn is_consistent(tl: &TopLevel, clauses: &Vec<PredicateClause>) -> bool {
     match clauses.first() {
         Some(ref cl) => tl.name() == cl.name() && tl.arity() == cl.arity(),
@@ -412,6 +384,48 @@ fn flatten_hook(mut term: Term) -> Term {
     term
 }
 
+fn setup_declaration(
+    indices: &mut CompositeIndices,
+    flags: MachineFlags,
+    mut terms: Vec<Box<Term>>
+) -> Result<Declaration, ParserError> {
+    let term = *terms.pop().unwrap();
+
+    match term {
+        Term::Clause(_, name, mut terms, _) =>
+           match (name.as_str(), terms.len()) {
+               ("op", 3) =>
+                   Ok(Declaration::Op(setup_op_decl(terms)?)),
+               ("module", 2) =>
+                   Ok(Declaration::Module(setup_module_decl(terms)?)),
+               ("use_module", 1) =>
+                   Ok(Declaration::UseModule(setup_use_module_decl(terms)?)),
+               ("use_module", 2) => {
+                   let (name, exports) = setup_qualified_import(terms)?;
+                   Ok(Declaration::UseQualifiedModule(name, exports))
+               }
+               ("non_counted_backtracking", 1) => {
+                   let (name, arity) = setup_predicate_indicator(*terms.pop().unwrap())?;
+                   Ok(Declaration::NonCountedBacktracking(name, arity))
+               }
+               ("dynamic", 1) => {
+                   let (name, arity) = setup_predicate_indicator(*terms.pop().unwrap())?;
+                   Ok(Declaration::Dynamic(name, arity))
+               }
+               ("initialization", 1) => {
+                   let mut rel_worker = RelationWorker::new(flags);
+                   let query_terms = rel_worker.setup_query(indices, terms, false)?;
+                   let queue = rel_worker.parse_queue(indices)?;
+                   
+                   Ok(Declaration::ModuleInitialization(query_terms, queue))
+               }
+               _ =>
+                   Err(ParserError::InconsistentEntry)
+           },
+        _ => return Err(ParserError::InconsistentEntry),
+    }
+}
+
 pub enum TopLevelPacket {
     Query(Vec<QueryTerm>, VecDeque<TopLevel>),
     Decl(TopLevel, VecDeque<TopLevel>),
@@ -743,13 +757,6 @@ impl RelationWorker {
         terms: Vec<Box<Term>>,
         blocks_cuts: bool,
     ) -> Result<TopLevel, ParserError> {
-       /*
-        match setup_declaration(terms.iter().cloned().collect()) {
-            Ok(Declaration::Op(..)) => {} // this is now a predicate call in the query context.
-            Ok(decl) => return Ok(TopLevel::Declaration(decl)),
-            _ => {}
-        };
-       */
         Ok(TopLevel::Query(self.setup_query(
             indices,
             terms,
@@ -782,7 +789,7 @@ impl RelationWorker {
                         true,
                     )?))
                 } else if name.as_str() == ":-" && terms.len() == 1 {
-                    Ok(TopLevel::Declaration(setup_declaration(terms)?))
+                    Ok(TopLevel::Declaration(setup_declaration(indices, self.flags, terms)?))
                 } else {
                     let term = Term::Clause(r, name, terms, fixity);
                     Ok(TopLevel::Fact(try!(self.setup_fact(term, true))))