From abc7498a427c41ef44a729da2ea37a1d1aaa90e7 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 1 Oct 2019 16:51:22 -0600 Subject: [PATCH] add the initialization directive --- Cargo.toml | 2 +- src/prolog/forms.rs | 3 +- src/prolog/machine/compile.rs | 32 ++++++++++- src/prolog/machine/machine_errors.rs | 2 +- src/prolog/machine/mod.rs | 16 ++++-- src/prolog/machine/modules.rs | 2 +- src/prolog/machine/term_expansion.rs | 2 +- src/prolog/machine/toplevel.rs | 79 +++++++++++++++------------- 8 files changed, 92 insertions(+), 46 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b9d6df85..86ed4cc5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "scryer-prolog" -version = "0.8.96" +version = "0.8.97" authors = ["Mark Thom "] build = "build.rs" repository = "https://github.com/mthom/scryer-prolog" diff --git a/src/prolog/forms.rs b/src/prolog/forms.rs index 1fe27002..0f05587c 100644 --- a/src/prolog/forms.rs +++ b/src/prolog/forms.rs @@ -174,6 +174,7 @@ pub enum Declaration { Dynamic(ClauseName, usize), // name, arity EndOfFile, Hook(CompileTimeHook, PredicateClause, VecDeque), + ModuleInitialization(Vec, VecDeque), // goal Module(ModuleDecl), NonCountedBacktracking(ClauseName, usize), // name, arity Op(OpDecl), @@ -328,7 +329,7 @@ pub struct Module { pub user_term_expansions: (Predicate, VecDeque), // term expansions inherited from the user scope. pub user_goal_expansions: (Predicate, VecDeque), // same for goal_expansions. pub inserted_expansions: bool, // has the module been successfully inserted into toplevel?? -} + } #[derive(Clone, PartialEq, Eq)] pub enum Number { diff --git a/src/prolog/machine/compile.rs b/src/prolog/machine/compile.rs index 6d391f9a..2df48229 100644 --- a/src/prolog/machine/compile.rs +++ b/src/prolog/machine/compile.rs @@ -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, VecDeque) } 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 { + 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, @@ -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 } diff --git a/src/prolog/machine/machine_errors.rs b/src/prolog/machine/machine_errors.rs index e8eb479b..ad0ff427 100644 --- a/src/prolog/machine/machine_errors.rs +++ b/src/prolog/machine/machine_errors.rs @@ -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) => { diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 0e6f3536..a5770c62 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -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 { diff --git a/src/prolog/machine/modules.rs b/src/prolog/machine/modules.rs index 94f218ba..c4e26449 100644 --- a/src/prolog/machine/modules.rs +++ b/src/prolog/machine/modules.rs @@ -281,7 +281,7 @@ impl SubModuleUser for Module { self.user_goal_expansions .1 .extend(submodule.goal_expansions.1.iter().cloned()); - + Ok(()) } } diff --git a/src/prolog/machine/term_expansion.rs b/src/prolog/machine/term_expansion.rs index eaa4d23e..3880ac41 100644 --- a/src/prolog/machine/term_expansion.rs +++ b/src/prolog/machine/term_expansion.rs @@ -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, diff --git a/src/prolog/machine/toplevel.rs b/src/prolog/machine/toplevel.rs index 6eca3e08..3a7c4322 100644 --- a/src/prolog/machine/toplevel.rs +++ b/src/prolog/machine/toplevel.rs @@ -265,34 +265,6 @@ fn setup_qualified_import(mut terms: Vec>) -> Result>) -> Result { - 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) -> 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> +) -> Result { + 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, VecDeque), Decl(TopLevel, VecDeque), @@ -743,13 +757,6 @@ impl RelationWorker { terms: Vec>, blocks_cuts: bool, ) -> Result { - /* - 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)))) -- 2.54.0