]> Repositorios git - scryer-prolog.git/commitdiff
reload files properly (re: #213)
authorMark Thom <[email protected]>
Sat, 26 Oct 2019 07:34:41 +0000 (01:34 -0600)
committerMark Thom <[email protected]>
Sat, 26 Oct 2019 07:34:41 +0000 (01:34 -0600)
src/prolog/forms.rs
src/prolog/machine/compile.rs
src/prolog/machine/machine_errors.rs
src/prolog/machine/mod.rs
src/prolog/machine/modules.rs
src/prolog/write.rs

index 12ec273821c28c2d305a6dc6340dd2ce4b687432..ed64a67f61c79844f1f47212f053d2b22e02cd06 100644 (file)
@@ -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)]
index 5b0666393f87458f4ab2faec98964f99ef260380..07569ef3d5fbb3ad87567b6a2114b1ba6e12c06c 100644 (file)
@@ -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);
 
index 982a2eb84139171c7f5e1a3164a3d35bdbd2f894..fe6483032620430d65ce36116d5c8e22d18610a2 100644 (file)
@@ -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,
index c8ea15c49ef57c371c971d5864b153fc2cd4273f..6bf23eb4becc5729386c6655570f5e41813c5e1e 100644 (file)
@@ -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();
index a7299c350ea6052c7c0d8ae4bb16e8df0752e125..ace04f65d4690423d83564a762c376d5807ef316 100644 (file)
@@ -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
         }
     }
 
index fff5f2c17425c8f7ae40d597b936ef53d284c13b..84df600cbd06ef82bdab9647aee95703d211fcc3 100644 (file)
@@ -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.")
             }