&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"),
("$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),
'$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) :-
!,
use_module(Module, Exports) :-
'$push_load_state_payload'(Evacuable),
( Exports == [] ->
- '$remove_module_exports'(Module, Evacuable)
+ remove_module(Module, Evacuable)
; use_module(Module, Exports, Evacuable)
).
}
}
+ 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,
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) => {
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,
Retract,
IsConsistentWithTermQueue,
FlushTermQueue,
+ RemoveModuleExports,
}
#[derive(Debug, Clone, PartialEq)]
REPLCodePtr::FlushTermQueue => {
self.flush_term_queue();
}
+ REPLCodePtr::RemoveModuleExports => {
+ self.remove_module_exports();
+ }
}
self.machine_st.p = CodePtr::Local(p);
write!(f, "REPLCodePtr::IsConsistentWithTermQueue"),
REPLCodePtr::FlushTermQueue =>
write!(f, "REPLCodePtr::FlushTermQueue"),
+ REPLCodePtr::RemoveModuleExports =>
+ write!(f, "REPLCodePtr::RemoveModuleExports"),
}
}
}