From: Mark Thom Date: Thu, 18 Feb 2021 21:07:57 +0000 (-0700) Subject: add '$remove_module_exports' to loader.rs X-Git-Tag: v0.9.0~150^2~39 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=d69b7f41f210fd7544eee9ff6ea0ae7c922ebf2a;p=scryer-prolog.git add '$remove_module_exports' to loader.rs --- diff --git a/src/clause_types.rs b/src/clause_types.rs index c9cb0332..dc619a91 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -419,6 +419,9 @@ impl SystemClauseType { &SystemClauseType::REPL(REPLCodePtr::FlushTermQueue) => { clause_name!("$flush_term_queue") } + &SystemClauseType::REPL(REPLCodePtr::RemoveModuleExports) => { + clause_name!("$remove_module_exports") + } &SystemClauseType::Close => clause_name!("$close"), &SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"), &SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"), @@ -772,6 +775,9 @@ impl SystemClauseType { ("$flush_term_queue", 1) => { Some(SystemClauseType::REPL(REPLCodePtr::FlushTermQueue)) } + ("$remove_module_exports", 2) => { + Some(SystemClauseType::REPL(REPLCodePtr::RemoveModuleExports)) + } ("$variant", 2) => Some(SystemClauseType::Variant), ("$wam_instructions", 4) => Some(SystemClauseType::WAMInstructions), ("$write_term", 7) => Some(SystemClauseType::WriteTerm), diff --git a/src/loader.pl b/src/loader.pl index e1868a2c..95e0a052 100644 --- a/src/loader.pl +++ b/src/loader.pl @@ -246,19 +246,30 @@ compile_dispatch((user:goal_expansion(Term, Terms) :- Body), Evacuable) :- '$add_goal_expansion_clause'(user, (goal_expansion(Term, Terms) :- Body), Evacuable). +remove_module(Module, Evacuable) :- + ( nonvar(Module), + Module = library(ModuleName), + atom(ModuleName), + atom \== [] -> + '$remove_module_exports'(ModuleName, Evacuable) + ; atom(Module), + atom \== [] -> + '$remove_module_exports'(Module, Evacuable) + ; domain_error(module_specifier, Module, use_module/2) + ). + + compile_declaration(use_module(Module), Evacuable) :- use_module(Module, [], Evacuable). compile_declaration(use_module(Module, Exports), Evacuable) :- ( Exports == [] -> - '$remove_module_exports'(Module, Evacuable) % TODO: implement this. - ; - use_module(Module, Exports, Evacuable) + remove_module(Module, Evacuable) + ; use_module(Module, Exports, Evacuable) ). compile_declaration(module(Module, Exports), Evacuable) :- - ( atom(Module) -> - '$declare_module'(Module, Exports, Evacuable) - ; - type_error(atom, Module, load/1) + ( atom(Module) -> + '$declare_module'(Module, Exports, Evacuable) + ; type_error(atom, Module, load/1) ). compile_declaration(dynamic(Name/Arity), Evacuable) :- !, @@ -375,7 +386,7 @@ use_module(Module) :- use_module(Module, Exports) :- '$push_load_state_payload'(Evacuable), ( Exports == [] -> - '$remove_module_exports'(Module, Evacuable) + remove_module(Module, Evacuable) ; use_module(Module, Exports, Evacuable) ). diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs index c0e22473..41f39248 100644 --- a/src/machine/load_state.rs +++ b/src/machine/load_state.rs @@ -459,6 +459,94 @@ impl<'a> LoadState<'a> { } } + pub(super) fn remove_module_exports(&mut self, module_name: ClauseName) { + let removed_module = match self.wam.indices.modules.remove(&module_name) { + Some(module) => module, + None => return, + }; + + fn remove_module_exports( + removed_module: &Module, + code_dir: &mut CodeDir, + op_dir: &mut OpDir, + retraction_info: &mut RetractionInfo, + predicate_retractor: impl Fn(PredicateKey, IndexPtr) -> RetractionRecord, + op_retractor: impl Fn(OpDecl, usize, Specifier) -> RetractionRecord, + ) { + for export in removed_module.module_decl.exports.iter() { + match export { + ModuleExport::PredicateKey(ref key) => { + match (removed_module.code_dir.get(key), code_dir.get(key)) { + (Some(module_code_index), Some(target_code_index)) + if module_code_index.get() == target_code_index.get() => { + let old_index_ptr = target_code_index.replace(IndexPtr::Undefined); + + retraction_info.push_record( + predicate_retractor(key.clone(), old_index_ptr), + ); + } + _ => {} + } + } + ModuleExport::OpDecl(op_decl) => { + let op_dir_value_opt = op_dir.remove(&(op_decl.name.clone(), op_decl.fixity())); + + if let Some(op_dir_value) = op_dir_value_opt { + let (prec, spec) = op_dir_value.shared_op_desc().get(); + + retraction_info.push_record( + op_retractor(op_decl.clone(), prec, spec), + ); + } + } + } + } + } + + match &self.compilation_target { + CompilationTarget::User => { + remove_module_exports( + &removed_module, + &mut self.wam.indices.code_dir, + &mut self.wam.indices.op_dir, + &mut self.retraction_info, + RetractionRecord::ReplacedUserPredicate, + RetractionRecord::ReplacedUserOp, + ); + } + CompilationTarget::Module(ref target_module_name) + if target_module_name.as_str() != module_name.as_str() => { + let predicate_retractor = |key, index_ptr| { + RetractionRecord::ReplacedModulePredicate( + module_name.clone(), key, index_ptr, + ) + }; + + let op_retractor = |op_decl, prec, spec| { + RetractionRecord::ReplacedModuleOp( + module_name.clone(), op_decl, prec, spec, + ) + }; + + if let Some(module) = self.wam.indices.modules.get_mut(target_module_name) { + remove_module_exports( + &removed_module, + &mut module.code_dir, + &mut module.op_dir, + &mut self.retraction_info, + predicate_retractor, + op_retractor, + ); + } else { + unreachable!() + } + } + CompilationTarget::Module(_) => {}, + }; + + self.wam.indices.modules.insert(module_name, removed_module); + } + fn get_or_insert_local_code_index( &mut self, module_name: ClauseName, @@ -787,6 +875,7 @@ impl<'a> LoadState<'a> { pub(crate) fn add_module(&mut self, module_decl: ModuleDecl, listing_src: ListingSource) { let module_name = module_decl.name.clone(); + self.remove_module_exports(module_name.clone()); match self.wam.indices.modules.get_mut(&module_name) { Some(module) => { diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 2347fcfe..38797ba8 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1922,6 +1922,24 @@ impl Machine { self.restore_load_state_payload(result, evacuable_h); } + pub(crate) fn remove_module_exports(&mut self) { + let module_name = atom_from!( + self.machine_st, + self.machine_st + .store(self.machine_st.deref(self.machine_st[temp_v!(1)])) + ); + + let (mut loader, evacuable_h) = self.loader_from_heap_evacuable(temp_v!(2)); + + let remove_module_exports = || { + loader.load_state.remove_module_exports(module_name); + LiveTermStream::evacuate(loader) + }; + + let result = remove_module_exports(); + self.restore_load_state_payload(result, evacuable_h); + } + pub(crate) fn meta_predicate_property(&mut self) { let module_name = atom_from!( self.machine_st, diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 049cd5a0..43264a3f 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -448,6 +448,7 @@ pub enum REPLCodePtr { Retract, IsConsistentWithTermQueue, FlushTermQueue, + RemoveModuleExports, } #[derive(Debug, Clone, PartialEq)] diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 163c82a0..384e0daf 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -510,6 +510,9 @@ impl Machine { REPLCodePtr::FlushTermQueue => { self.flush_term_queue(); } + REPLCodePtr::RemoveModuleExports => { + self.remove_module_exports(); + } } self.machine_st.p = CodePtr::Local(p); diff --git a/src/write.rs b/src/write.rs index 49541f0b..52263c2f 100644 --- a/src/write.rs +++ b/src/write.rs @@ -83,6 +83,8 @@ impl fmt::Display for REPLCodePtr { write!(f, "REPLCodePtr::IsConsistentWithTermQueue"), REPLCodePtr::FlushTermQueue => write!(f, "REPLCodePtr::FlushTermQueue"), + REPLCodePtr::RemoveModuleExports => + write!(f, "REPLCodePtr::RemoveModuleExports"), } } }