[package]
name = "scryer-prolog"
-version = "0.8.96"
+version = "0.8.97"
build = "build.rs"
repository = "https://github.com/mthom/scryer-prolog"
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),
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 {
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) {
.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![]))
}
}
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),
.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>,
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(()),
}
}
wam: &mut Machine,
mut indices: IndexStore,
mut results: GatherResult,
-) -> EvalSession {
+) -> EvalSession {
let module_code = try_eval_session!(compiler.generate_code(
results.worker_results,
wam,
));
}
+ 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
}
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) => {
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;
// 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 {
self.user_goal_expansions
.1
.extend(submodule.goal_expansions.1.iter().cloned());
-
+
Ok(())
}
}
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,
}
}
-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(),
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>),
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,
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))))