reload files properly (re: #213)
This commit is contained in:
@@ -338,6 +338,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??
|
||||
pub is_impromptu_module: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
|
||||
@@ -62,25 +62,34 @@ fn load_module<R: Read>(
|
||||
stream: ParsingStream<R>,
|
||||
suppress_warnings: bool,
|
||||
listing_src: ClauseName,
|
||||
) -> Result<Option<ClauseName>, SessionError> {
|
||||
) -> Result<ClauseName, SessionError> {
|
||||
// follow the operation of compile_user_module, but before
|
||||
// compiling, check that a module is declared in the file. if not,
|
||||
// throw an exception.
|
||||
let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
|
||||
setup_indices(wam, clause_name!("builtins"), &mut indices)?;
|
||||
|
||||
|
||||
let mut compiler = ListingCompiler::new(
|
||||
&wam.code_repo,
|
||||
suppress_warnings,
|
||||
listing_src,
|
||||
listing_src.clone(),
|
||||
);
|
||||
|
||||
let results = compiler.gather_items(wam, stream, &mut indices);
|
||||
|
||||
|
||||
let module_name = if let Some(ref module) = &compiler.module {
|
||||
Some(module.module_decl.name.clone())
|
||||
module.module_decl.name.clone()
|
||||
} else {
|
||||
None
|
||||
// this impromptu definition (namely, its exports) will be filled out later.
|
||||
let module_decl = ModuleDecl { name: listing_src, exports: vec![] };
|
||||
|
||||
let mut module = Module::new(module_decl, wam.indices.atom_tbl.clone());
|
||||
let module_name = module.module_decl.name.clone();
|
||||
|
||||
module.is_impromptu_module = true;
|
||||
|
||||
compiler.module = Some(module);
|
||||
module_name
|
||||
};
|
||||
|
||||
results.and_then(|results| compile_work_impl(&mut compiler, wam, indices, results))
|
||||
@@ -97,7 +106,7 @@ fn load_module_from_file(
|
||||
wam: &mut Machine,
|
||||
filename: &str,
|
||||
suppress_warnings: bool,
|
||||
) -> Result<Option<ClauseName>, SessionError> {
|
||||
) -> Result<ClauseName, SessionError> {
|
||||
let path = fix_filename(wam.indices.atom_tbl.clone(), filename)?;
|
||||
let filename = clause_name!(path.to_string_lossy().to_string(), wam.indices.atom_tbl);
|
||||
|
||||
@@ -491,12 +500,9 @@ pub struct ListingCompiler {
|
||||
listing_src: ClauseName // a file? a module?
|
||||
}
|
||||
|
||||
fn add_toplevel_code(wam: &mut Machine, code: Code, mut indices: IndexStore) {
|
||||
let code_dir = mem::replace(&mut indices.code_dir, CodeDir::new());
|
||||
let op_dir = mem::replace(&mut indices.op_dir, OpDir::new());
|
||||
|
||||
wam.add_batched_code(code, code_dir);
|
||||
wam.add_batched_ops(op_dir);
|
||||
fn add_toplevel_code(wam: &mut Machine, code: Code, indices: IndexStore) {
|
||||
wam.add_batched_code(code, indices.code_dir);
|
||||
wam.add_batched_ops(indices.op_dir);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -510,8 +516,8 @@ fn add_module_code(wam: &mut Machine, mut module: Module, code: Code, mut indice
|
||||
for (name, arity) in indices.code_dir.keys().cloned() {
|
||||
if name.owning_module() == module.module_decl.name {
|
||||
wam.indices
|
||||
.dynamic_code_dir
|
||||
.swap_remove(&(name.owning_module(), name, arity));
|
||||
.dynamic_code_dir
|
||||
.swap_remove(&(name.owning_module(), name, arity));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -543,9 +549,8 @@ fn load_library(
|
||||
) -> Result<ClauseName, SessionError> {
|
||||
match LIBRARIES.borrow().get(name.as_str()) {
|
||||
Some(code) => {
|
||||
let module_name = load_module(wam, parsing_stream(code.as_bytes()),
|
||||
suppress_warnings, name.clone())?;
|
||||
module_name.ok_or(SessionError::NoModuleDeclaration(name))
|
||||
load_module(wam, parsing_stream(code.as_bytes()),
|
||||
suppress_warnings, name.clone())
|
||||
}
|
||||
None => Err(SessionError::ModuleNotFound)
|
||||
}
|
||||
@@ -848,28 +853,19 @@ impl ListingCompiler {
|
||||
}
|
||||
Declaration::UseModule(ModuleSource::File(filename)) => {
|
||||
let name = load_module_from_file(wam, filename.as_str(), true)?;
|
||||
|
||||
if let Some(name) = name {
|
||||
self.use_module(name, &mut wam.code_repo, flags, &mut wam.indices, indices)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
self.use_module(name, &mut wam.code_repo, flags, &mut wam.indices, indices)
|
||||
}
|
||||
Declaration::UseQualifiedModule(ModuleSource::File(filename), exports) => {
|
||||
let name = load_module_from_file(wam, filename.as_str(), true)?;
|
||||
|
||||
if let Some(name) = name {
|
||||
self.use_qualified_module(
|
||||
name,
|
||||
&mut wam.code_repo,
|
||||
flags,
|
||||
&exports,
|
||||
&mut wam.indices,
|
||||
indices,
|
||||
)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
self.use_qualified_module(
|
||||
name,
|
||||
&mut wam.code_repo,
|
||||
flags,
|
||||
&exports,
|
||||
&mut wam.indices,
|
||||
indices,
|
||||
)
|
||||
}
|
||||
Declaration::ModuleInitialization(query_terms, queue) => {
|
||||
self.initialization_goals.0.extend(query_terms.into_iter());
|
||||
@@ -901,7 +897,7 @@ impl ListingCompiler {
|
||||
CodeIndex::dynamic_undefined(self.get_module_name()));
|
||||
}
|
||||
&Declaration::Hook(hook, _, ref queue) if self.module.is_none() => worker
|
||||
.term_stream
|
||||
.term_stream
|
||||
.incr_expansion_lens(hook.user_scope(), 1, queue.len()),
|
||||
&Declaration::Hook(hook, _, ref queue) if !hook.has_module_scope() => {
|
||||
worker.term_stream.incr_expansion_lens(hook, 1, queue.len())
|
||||
@@ -996,6 +992,7 @@ fn compile_work_impl(
|
||||
&mut indices.code_dir,
|
||||
0
|
||||
)?;
|
||||
|
||||
let toplvl_code = compiler.generate_code(
|
||||
results.toplevel_results,
|
||||
wam,
|
||||
@@ -1004,8 +1001,10 @@ fn compile_work_impl(
|
||||
)?;
|
||||
|
||||
if let Some(ref mut module) = &mut compiler.module {
|
||||
module.user_term_expansions = results.addition_results.take_term_expansions();
|
||||
module.user_goal_expansions = results.addition_results.take_goal_expansions();
|
||||
if !module.is_impromptu_module {
|
||||
module.user_term_expansions = results.addition_results.take_term_expansions();
|
||||
module.user_goal_expansions = results.addition_results.take_goal_expansions();
|
||||
}
|
||||
}
|
||||
|
||||
let flags = wam.machine_flags();
|
||||
@@ -1013,7 +1012,13 @@ fn compile_work_impl(
|
||||
wam.code_repo.compile_hook(CompileTimeHook::UserTermExpansion, flags)?;
|
||||
wam.code_repo.compile_hook(CompileTimeHook::UserGoalExpansion, flags)?;
|
||||
|
||||
if let Some(module) = compiler.module.take() {
|
||||
if let Some(mut module) = compiler.module.take() {
|
||||
if module.is_impromptu_module {
|
||||
module.module_decl.exports = indices.code_dir.keys().cloned()
|
||||
.filter(|(name, _)| name.owning_module().as_str() != "builtins")
|
||||
.collect();
|
||||
}
|
||||
|
||||
let mut clause_code_generator =
|
||||
ClauseCodeGenerator::new(module_code.len() + toplvl_code.len(),
|
||||
module.module_decl.name.clone());
|
||||
@@ -1021,6 +1026,10 @@ fn compile_work_impl(
|
||||
wam.check_toplevel_code(&results.toplevel_indices)?;
|
||||
clause_code_generator.generate_clause_code(&results.dynamic_clause_map, wam)?;
|
||||
|
||||
if let Some(ref module) = wam.indices.modules.swap_remove(&module.module_decl.name) {
|
||||
wam.indices.remove_module(clause_name!("user"), module);
|
||||
}
|
||||
|
||||
add_module_code(wam, module, module_code, indices);
|
||||
add_toplevel_code(wam, toplvl_code, results.toplevel_indices);
|
||||
|
||||
|
||||
@@ -143,9 +143,6 @@ impl MachineError {
|
||||
"private_procedure",
|
||||
clause_name!("module_does_not_exist"),
|
||||
),
|
||||
SessionError::NoModuleDeclaration(name) => {
|
||||
Self::existence_error(h, ExistenceError::Module(name))
|
||||
}
|
||||
SessionError::OpIsInfixAndPostFix(op) => {
|
||||
Self::permission_error(PermissionError::Create, "operator", op)
|
||||
}
|
||||
@@ -538,7 +535,6 @@ pub enum SessionError {
|
||||
ModuleDoesNotContainExport,
|
||||
ModuleNotFound,
|
||||
NamelessEntry,
|
||||
NoModuleDeclaration(ClauseName),
|
||||
OpIsInfixAndPostFix(ClauseName),
|
||||
ParserError(ParserError),
|
||||
UserPrompt,
|
||||
|
||||
@@ -128,7 +128,7 @@ impl SubModuleUser for IndexStore {
|
||||
fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: CodeIndex) {
|
||||
if let Some(ref code_idx) = self.code_dir.get(&(name.clone(), arity)) {
|
||||
if !code_idx.is_undefined() {
|
||||
println!("warning: overwriting {}/{}", &name, arity);
|
||||
println!("Warning: overwriting {}/{}", &name, arity);
|
||||
}
|
||||
|
||||
let (p, module_name) = idx.0.borrow().clone();
|
||||
@@ -444,28 +444,22 @@ impl Machine {
|
||||
let load_result = match to_src(name) {
|
||||
ModuleSource::Library(name) =>
|
||||
if !self.indices.modules.contains_key(&name) {
|
||||
load_library(self, name, false).map(Some)
|
||||
load_library(self, name, false)
|
||||
} else {
|
||||
Ok(Some(name))
|
||||
Ok(name)
|
||||
},
|
||||
ModuleSource::File(name) =>
|
||||
load_module_from_file(self, name.as_str(), false)
|
||||
};
|
||||
|
||||
let result = load_result.and_then(|name|
|
||||
if let Some(name) = name {
|
||||
let module = self.indices.take_module(name).unwrap();
|
||||
let result = load_result.and_then(|name| {
|
||||
let module = self.indices.take_module(name.clone()).unwrap();
|
||||
|
||||
// remove previous exports.
|
||||
self.indices.remove_module(clause_name!("user"), &module);
|
||||
self.indices.use_module(&mut self.code_repo, self.machine_st.flags,
|
||||
&module)?;
|
||||
self.indices.use_module(&mut self.code_repo, self.machine_st.flags,
|
||||
&module)?;
|
||||
|
||||
Ok(self.indices.insert_module(module))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
);
|
||||
Ok(self.indices.insert_module(module))
|
||||
});
|
||||
|
||||
self.code_repo.cached_query = cached_query;
|
||||
|
||||
@@ -490,31 +484,28 @@ impl Machine {
|
||||
|
||||
let load_result = match to_src(name) {
|
||||
ModuleSource::Library(name) =>
|
||||
if !self.indices.modules.contains_key(&name) {
|
||||
load_library(self, name, false).map(Some)
|
||||
} else {
|
||||
Ok(Some(name))
|
||||
if let Some(module) = self.indices.take_module(name.clone()) {
|
||||
self.indices.remove_module(clause_name!("user"), &module);
|
||||
self.indices.modules.insert(name.clone(), module);
|
||||
|
||||
Ok(name)
|
||||
} else {
|
||||
load_library(self, name, false)
|
||||
},
|
||||
ModuleSource::File(name) =>
|
||||
load_module_from_file(self, name.as_str(), false)
|
||||
};
|
||||
|
||||
let result = load_result.and_then(|name|
|
||||
if let Some(name) = name {
|
||||
let module = self.indices.take_module(name).unwrap();
|
||||
let result = load_result.and_then(|name| {
|
||||
let module = self.indices.take_module(name.clone()).unwrap();
|
||||
|
||||
// remove previous exports.
|
||||
self.indices.remove_module(clause_name!("user"), &module);
|
||||
self.indices.use_qualified_module(&mut self.code_repo,
|
||||
self.machine_st.flags,
|
||||
&module,
|
||||
&exports)?;
|
||||
self.indices.use_qualified_module(&mut self.code_repo,
|
||||
self.machine_st.flags,
|
||||
&module,
|
||||
&exports)?;
|
||||
|
||||
Ok(self.indices.insert_module(module))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
);
|
||||
Ok(self.indices.insert_module(module))
|
||||
});
|
||||
|
||||
self.code_repo.cached_query = cached_query;
|
||||
|
||||
@@ -648,7 +639,7 @@ impl Machine {
|
||||
|
||||
self.inner_heap = self.machine_st.heap.take();
|
||||
self.inner_heap.truncate(0);
|
||||
|
||||
|
||||
self.machine_st.heap = snapshot.heap.take();
|
||||
self.machine_st.mode = snapshot.mode;
|
||||
self.machine_st.and_stack = snapshot.and_stack.take();
|
||||
@@ -683,7 +674,7 @@ impl Machine {
|
||||
};
|
||||
|
||||
let attr_goals = self.attribute_goals();
|
||||
|
||||
|
||||
if !(self.machine_st.b > 0) {
|
||||
if bindings.is_empty() {
|
||||
let space = if requires_space(&attr_goals, ".") {
|
||||
@@ -810,7 +801,7 @@ impl Machine {
|
||||
|
||||
self.machine_st.p = top_level_code_ptr!(cn, p);
|
||||
}
|
||||
|
||||
|
||||
self.machine_st.query_stepper(
|
||||
&mut self.indices,
|
||||
&mut self.policies,
|
||||
@@ -1112,7 +1103,7 @@ impl MachineState {
|
||||
|
||||
match self.p {
|
||||
CodePtr::VerifyAttrInterrupt(_) => {
|
||||
self.p = CodePtr::Local(self.attr_var_init.cp);
|
||||
self.p = CodePtr::Local(self.attr_var_init.cp);
|
||||
|
||||
let instigating_p = CodePtr::Local(self.attr_var_init.instigating_p);
|
||||
let instigating_instr = code_repo.lookup_instr(false, &instigating_p).unwrap();
|
||||
|
||||
@@ -22,6 +22,7 @@ impl Module {
|
||||
code_dir: CodeDir::new(),
|
||||
op_dir: default_op_dir(),
|
||||
inserted_expansions: false,
|
||||
is_impromptu_module: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +163,7 @@ pub trait SubModuleUser {
|
||||
self.insert_dir_entry(name, arity, code_data.clone());
|
||||
true
|
||||
} else {
|
||||
found_op
|
||||
found_op || submodule.is_impromptu_module
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -268,9 +268,6 @@ impl fmt::Display for SessionError {
|
||||
&SessionError::ModuleDoesNotContainExport => {
|
||||
write!(f, "module does not contain claimed export.")
|
||||
}
|
||||
&SessionError::NoModuleDeclaration(ref name) => {
|
||||
write!(f, "file {}.pl lacks an expected module declaration.", name)
|
||||
}
|
||||
&SessionError::OpIsInfixAndPostFix(_) => {
|
||||
write!(f, "cannot define an op to be both postfix and infix.")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user