]> Repositorios git - scryer-prolog.git/commitdiff
add '$remove_module_exports' to loader.rs
authorMark Thom <[email protected]>
Thu, 18 Feb 2021 21:07:57 +0000 (14:07 -0700)
committerMark Thom <[email protected]>
Thu, 18 Feb 2021 21:08:25 +0000 (14:08 -0700)
src/clause_types.rs
src/loader.pl
src/machine/load_state.rs
src/machine/loader.rs
src/machine/machine_indices.rs
src/machine/mod.rs
src/write.rs

index c9cb033280fbe4b418c184d519b4878f8be9dbd8..dc619a91828cb047c46a9aebbd5662c1f825f46e 100644 (file)
@@ -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),
index e1868a2c9bb92582f948415e4ef847339274a557..95e0a052883ba894c4e5dacbdce7ecf0a865b5e1 100644 (file)
@@ -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)
     ).
 
index c0e224739c0620cc6931cf2902e18337153c198b..41f392481e2d3faac5e4d357e15f3c86752bf316 100644 (file)
@@ -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) => {
index 2347fcfed8eef27b4a94d086ed30cd08046d8a32..38797ba8d71b143ba9856d4c069dc011d6008aec 100644 (file)
@@ -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,
index 049cd5a020dcc40e3741aeba63a966b3a382bb5f..43264a3f1b37d8eedf24da01a3ebd982a62599ab 100644 (file)
@@ -448,6 +448,7 @@ pub enum REPLCodePtr {
     Retract,
     IsConsistentWithTermQueue,
     FlushTermQueue,
+    RemoveModuleExports,
 }
 
 #[derive(Debug, Clone, PartialEq)]
index 163c82a0210bce37326dfc84bc06fd0333607bbf..384e0daf7e88c442a0bf50372b9e24701b43aafc 100644 (file)
@@ -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);
index 49541f0be9fe8cd50528112b7c725976a0421431..52263c2fcbec7bd4dfcefbfa49f6de6da5c38094 100644 (file)
@@ -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"),
         }
     }
 }