add the initialization directive
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "scryer-prolog"
|
||||
version = "0.8.96"
|
||||
version = "0.8.97"
|
||||
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
||||
build = "build.rs"
|
||||
repository = "https://github.com/mthom/scryer-prolog"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -281,7 +281,7 @@ impl SubModuleUser for Module {
|
||||
self.user_goal_expansions
|
||||
.1
|
||||
.extend(submodule.goal_expansions.1.iter().cloned());
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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))))
|
||||
|
||||
Reference in New Issue
Block a user