From a358431d30230124a162a0fd2559966be807e824 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 26 Oct 2019 01:34:41 -0600 Subject: [PATCH] reload files properly (re: #213) --- src/prolog/forms.rs | 1 + src/prolog/machine/compile.rs | 89 +++++++++++++++------------- src/prolog/machine/machine_errors.rs | 4 -- src/prolog/machine/mod.rs | 65 +++++++++----------- src/prolog/machine/modules.rs | 3 +- src/prolog/write.rs | 3 - 6 files changed, 80 insertions(+), 85 deletions(-) diff --git a/src/prolog/forms.rs b/src/prolog/forms.rs index 12ec2738..ed64a67f 100644 --- a/src/prolog/forms.rs +++ b/src/prolog/forms.rs @@ -338,6 +338,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?? + pub is_impromptu_module: bool, } #[derive(Clone, PartialEq, Eq)] diff --git a/src/prolog/machine/compile.rs b/src/prolog/machine/compile.rs index 5b066639..07569ef3 100644 --- a/src/prolog/machine/compile.rs +++ b/src/prolog/machine/compile.rs @@ -62,25 +62,34 @@ fn load_module( stream: ParsingStream, suppress_warnings: bool, listing_src: ClauseName, -) -> Result, SessionError> { +) -> Result { // 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, SessionError> { +) -> Result { 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 { 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); diff --git a/src/prolog/machine/machine_errors.rs b/src/prolog/machine/machine_errors.rs index 982a2eb8..fe648303 100644 --- a/src/prolog/machine/machine_errors.rs +++ b/src/prolog/machine/machine_errors.rs @@ -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, diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index c8ea15c4..6bf23eb4 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -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(); diff --git a/src/prolog/machine/modules.rs b/src/prolog/machine/modules.rs index a7299c35..ace04f65 100644 --- a/src/prolog/machine/modules.rs +++ b/src/prolog/machine/modules.rs @@ -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 } } diff --git a/src/prolog/write.rs b/src/prolog/write.rs index fff5f2c1..84df600c 100644 --- a/src/prolog/write.rs +++ b/src/prolog/write.rs @@ -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.") } -- 2.54.0