]> Repositorios git - scryer-prolog.git/commitdiff
add listing sources to modules
authorMark Thom <[email protected]>
Tue, 14 Jan 2020 03:17:22 +0000 (20:17 -0700)
committerMark Thom <[email protected]>
Tue, 14 Jan 2020 03:17:22 +0000 (20:17 -0700)
src/prolog/forms.rs
src/prolog/machine/compile.rs
src/prolog/machine/dynamic_database.rs
src/prolog/machine/mod.rs
src/prolog/machine/modules.rs

index aa8eeec656c5ed9b77cb145ad31842a9eb825df8..e60e1b4a8c4ed0546b6235484420996bbd2d3127 100644 (file)
@@ -12,6 +12,7 @@ use indexmap::IndexMap;
 
 use std::cell::Cell;
 use std::collections::VecDeque;
+use std::path::PathBuf;
 use std::rc::Rc;
 
 pub type PredicateKey = (ClauseName, usize); // name, arity.
@@ -132,6 +133,32 @@ impl Predicate {
     }
 }
 
+#[derive(Clone)]
+pub enum ListingSource {
+    File(ClauseName, PathBuf), // filename, path
+    User,
+}
+
+impl ListingSource {
+    pub fn from_file_and_path(filename: ClauseName, path_buf: PathBuf) -> Self {
+        ListingSource::File(filename, path_buf)
+    }
+
+    pub fn name(&self) -> ClauseName {
+        match self {
+            ListingSource::File(ref filename, _) => filename.clone(),
+            ListingSource::User => clause_name!("[user]")
+        }
+    }
+
+    pub fn path(&self) -> PathBuf {
+        match self {
+            ListingSource::File(_, ref path) => path.clone(),
+            ListingSource::User => std::env::current_dir().unwrap(),
+        }
+    }
+}
+
 pub type CompiledResult = (Predicate, VecDeque<TopLevel>);
 
 #[derive(Clone)]
@@ -352,6 +379,7 @@ pub struct Module {
     pub local_goal_expansions: (Predicate, VecDeque<TopLevel>),
     pub inserted_expansions: bool, // has the module been successfully inserted into toplevel??
     pub is_impromptu_module: bool,
+    pub listing_src: ListingSource,
  }
 
 #[derive(Clone, PartialEq, Eq)]
index d2403a8786659842e88b1b68f88f6f3fccfb1ddd..fcdaf90aff19033fa41cc9d445aa619c3c99eb90 100644 (file)
@@ -40,9 +40,11 @@ pub fn print_code(code: &Code) {
     }
 }
 
-fn fix_filename(atom_tbl: TabledData<Atom>, filename: &str) -> Result<PathBuf, SessionError> {
-    let mut path = PathBuf::from(filename);
-
+fn fix_filename(
+    atom_tbl: TabledData<Atom>,
+    mut path: PathBuf,
+) -> Result<PathBuf, SessionError>
+{
     if !path.is_file() {
         if path.extension().is_none() {
             path.set_extension("pl");
@@ -61,7 +63,7 @@ fn load_module<R: Read>(
     wam: &mut Machine,
     stream: ParsingStream<R>,
     suppress_warnings: bool,
-    listing_src: ClauseName,
+    listing_src: &ListingSource,
 ) -> Result<ClauseName, SessionError> {
     // follow the operation of compile_user_module, but before
     // compiling, check that a module is declared in the file. if not,
@@ -81,9 +83,9 @@ fn load_module<R: Read>(
         module.module_decl.name.clone()
     } else {
         // this impromptu definition (namely, its exports) will be filled out later.
-        let module_decl = ModuleDecl { name: listing_src, exports: vec![] };
+        let module_decl = ModuleDecl { name: listing_src.name(), exports: vec![] };
 
-        let mut module  = Module::new(module_decl, wam.indices.atom_tbl.clone());
+        let mut module  = Module::new(module_decl, wam.indices.atom_tbl.clone(), listing_src.clone());
         let module_name = module.module_decl.name.clone();
 
         module.is_impromptu_module = true;
@@ -105,17 +107,20 @@ fn load_module<R: Read>(
 pub(super)
 fn load_module_from_file(
     wam: &mut Machine,
-    filename: &str,
+    path_buf: PathBuf,
     suppress_warnings: bool,
 ) -> 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);
+    let mut path_buf = fix_filename(wam.indices.atom_tbl.clone(), path_buf)?;
+    let filename = clause_name!(path_buf.to_string_lossy().to_string(), wam.indices.atom_tbl);
 
-    let file_handle = File::open(&path).or_else(|_| {
+    let file_handle = File::open(&path_buf).or_else(|_| {
         Err(SessionError::InvalidFileName(filename.clone()))
     })?;
 
-    load_module(wam, parsing_stream(file_handle), suppress_warnings, filename)
+    path_buf.pop();
+
+    let listing_src = ListingSource::from_file_and_path(filename, path_buf);
+    load_module(wam, parsing_stream(file_handle), suppress_warnings, &listing_src)
 }
 
 pub type PredicateCompileQueue = (Predicate, VecDeque<TopLevel>);
@@ -330,7 +335,7 @@ pub(super) fn compile_into_module<R: Read>(
     indices.op_dir   = module.op_dir.clone();
     indices.atom_tbl = module.atom_tbl.clone();
 
-    let mut compiler = ListingCompiler::new(&wam.code_repo, true, module_name.clone());
+    let mut compiler = ListingCompiler::new(&wam.code_repo, true, module.listing_src.clone());
 
     match compile_into_module_impl(wam, &mut compiler, module, src, indices) {
         Ok(()) => EvalSession::EntrySuccess,
@@ -481,7 +486,7 @@ pub struct ListingCompiler {
     orig_goal_expansion_lens: (usize, usize),
     initialization_goals: (Vec<QueryTerm>, VecDeque<TopLevel>),
     suppress_warnings: bool,
-    listing_src: ClauseName // a file? a module?
+    listing_src: ListingSource, // a file? a module?
 }
 
 fn add_toplevel_code(wam: &mut Machine, code: Code, indices: IndexStore) {
@@ -523,8 +528,19 @@ fn load_library(
 ) -> Result<ClauseName, SessionError> {
     match LIBRARIES.borrow().get(name.as_str()) {
         Some(code) => {
-            load_module(wam, parsing_stream(code.as_bytes()),
-                        suppress_warnings, name.clone())
+            let mut lib_path = current_dir();
+
+            lib_path.pop();
+            lib_path.push("lib");
+            
+            let listing_src = ListingSource::from_file_and_path(name, lib_path);
+
+            load_module(
+                wam,
+                parsing_stream(code.as_bytes()),
+                suppress_warnings,
+                &listing_src,
+            )
         }
         None => Err(SessionError::ModuleNotFound)
     }
@@ -535,7 +551,7 @@ impl ListingCompiler {
     pub fn new(
         code_repo: &CodeRepo,
         suppress_warnings: bool,
-        listing_src: ClauseName,
+        listing_src: ListingSource,
     ) -> Self {
         ListingCompiler {
             non_counted_bt_preds: IndexSet::new(),
@@ -838,17 +854,25 @@ impl ListingCompiler {
                         }
                     }
 
-                    Ok(self.module = Some(Module::new(module_decl, atom_tbl)))
+                    let listing_src = self.listing_src.clone();
+
+                    Ok(self.module = Some(Module::new(module_decl, atom_tbl, listing_src)))
                 } else {
                     Err(SessionError::from(ParserError::InvalidModuleDecl))
                 }
             }
             Declaration::UseModule(ModuleSource::File(filename)) => {
-                let name = load_module_from_file(wam, filename.as_str(), true)?;
+                let mut path_buf = self.listing_src.path();
+                path_buf.push(filename.as_str());
+
+                let name = load_module_from_file(wam, path_buf, true)?;
                 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)?;
+                let mut path_buf = self.listing_src.path();
+                path_buf.push(filename.as_str());
+
+                let name = load_module_from_file(wam, path_buf, true)?;
 
                 self.use_qualified_module(
                     name,
@@ -967,7 +991,7 @@ impl ListingCompiler {
     fn print_error(&self, e: &SessionError) {
         if let &SessionError::ParserError(ref e) = e {
             if let Some((line_num, _col_num)) = e.line_and_col_num() {
-                println!("{}:{}: {}", self.listing_src, line_num, e.as_str());
+                println!("{}:{}: {}", self.listing_src.name(), line_num, e.as_str());
             }
         }
     }
@@ -1040,7 +1064,7 @@ fn compile_work_impl(
         if module.is_impromptu_module {
             add_module_code(wam, module, module_code, indices);
 
-            let module = wam.indices.take_module(compiler.listing_src.clone()).unwrap();
+            let module = wam.indices.take_module(compiler.listing_src.name()).unwrap();
 
             wam.indices.use_module(&mut wam.code_repo, wam.machine_st.flags, &module)?;
             wam.indices.insert_module(module);
@@ -1066,13 +1090,13 @@ fn compile_work_impl(
     if init_goal_code.len() > 0 {
        if !wam.run_init_code(init_goal_code) {
             println!("Warning: initialization goal for {} failed",
-                     compiler.listing_src);
+                     compiler.listing_src.name());
         }
     }
 
     if !compiler.suppress_warnings {
         issue_singleton_warnings(
-            compiler.listing_src.clone(),
+            compiler.listing_src.name(),
             results.top_level_terms,
         );
     }
@@ -1097,7 +1121,7 @@ M:verify_attributes on attributed variables. */
 pub fn compile_special_form<R: Read>(
     wam: &mut Machine,
     src: ParsingStream<R>,
-    listing_src: ClauseName,
+    listing_src: ListingSource,
 ) -> Result<usize, SessionError> {
     let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
     setup_indices(wam, clause_name!("builtins"), &mut indices)?;
@@ -1119,7 +1143,7 @@ pub fn compile_listing<R: Read>(
     src: ParsingStream<R>,
     indices: IndexStore,
     suppress_warnings: bool,
-    listing_src: ClauseName,
+    listing_src: ListingSource,
 ) -> EvalSession {
     let mut compiler = ListingCompiler::new(&wam.code_repo, suppress_warnings, listing_src);
 
@@ -1154,7 +1178,7 @@ pub fn compile_user_module<R: Read>(
     wam: &mut Machine,
     src: ParsingStream<R>,
     suppress_warnings: bool,
-    listing_src: ClauseName,
+    listing_src: ListingSource,
 ) -> EvalSession {
     let mut indices = default_index_store!(wam.indices.atom_tbl.clone());
     try_eval_session!(setup_indices(wam, clause_name!("builtins"), &mut indices));
index 17caf908f8290474cd5a16dba21d4fc4328265ce..d6ffd1a3319cf71ecab286600ba0784e1f247593 100644 (file)
@@ -21,19 +21,17 @@ impl Machine {
         name: ClauseName,
         arity: usize,
     ) -> EvalSession {
-        let user_src = clause_name!("user");
-
         match name.owning_module().as_str() {
             "user" => match self.indices.code_dir.get(&(name.clone(), arity)).cloned() {
                 Some(idx) => {
                     let module = idx.0.borrow().1.clone();
 
                     match module.as_str() {
-                        "user" => compile_user_module(self, src, true, user_src),
+                        "user" => compile_user_module(self, src, true, ListingSource::User),
                         _ => compile_into_module(self, module, src, name)
                     }
                 }
-                None => compile_user_module(self, src, true, user_src),
+                None => compile_user_module(self, src, true, ListingSource::User),
             },
             _ => compile_into_module(self, name.owning_module(), src, name),
         }
index b33373ca8c9f49fc88bd09e64261e1de4f07c9bc..14465337c59af35dc3eb3c991ad73f4c1d8dc74f 100644 (file)
@@ -43,6 +43,7 @@ use std::fs::File;
 use std::io::Read;
 use std::mem;
 use std::ops::Index;
+use std::path::PathBuf;
 use std::rc::Rc;
 use std::sync::atomic::AtomicBool;
 
@@ -165,14 +166,26 @@ impl SubModuleUser for IndexStore {
     }
 }
 
+#[inline]
+fn current_dir() -> std::path::PathBuf {
+    let mut path_buf = std::path::PathBuf::from(file!());
+    path_buf.pop();
+    path_buf
+}
+
 include!(concat!(env!("OUT_DIR"), "/libraries.rs"));
 
 static TOPLEVEL: &str = include_str!("../toplevel.pl");
 
 impl Machine {
-    fn compile_special_forms(&mut self) {
-        let verify_attrs_src = clause_name!("verify_attrs.pl");
-        let project_attrs_src = clause_name!("project_attributes.pl");
+    fn compile_special_forms(&mut self)
+    {
+        let current_dir = current_dir();
+
+        let verify_attrs_src = ListingSource::from_file_and_path(
+            clause_name!("attributed_variables.pl"),
+            current_dir.clone(),
+        );
 
         match compile_special_form(self, parsing_stream(VERIFY_ATTRS.as_bytes()), verify_attrs_src)
         {
@@ -183,6 +196,11 @@ impl Machine {
                 panic!("Machine::compile_special_forms() failed at VERIFY_ATTRS"),
         }
 
+        let project_attrs_src = ListingSource::from_file_and_path(
+            clause_name!("project_attributes.pl"),
+            current_dir,
+        );
+
         match compile_special_form(self, parsing_stream(PROJECT_ATTRS.as_bytes()), project_attrs_src)
         {
             Ok(p) => {
@@ -196,8 +214,21 @@ impl Machine {
     fn compile_top_level(&mut self) -> Result<(), SessionError>
     {
         self.toplevel_idx = self.code_repo.code.len();
-        compile_user_module(self, parsing_stream(TOPLEVEL.as_bytes()),
-                            true, clause_name!("toplevel.pl"));
+
+        let mut current_dir = current_dir();
+        current_dir.pop();
+
+        let top_lvl_src = ListingSource::from_file_and_path(
+            clause_name!("toplevel.pl"),
+            current_dir,
+        );
+
+        compile_user_module(
+            self,
+            parsing_stream(TOPLEVEL.as_bytes()),
+            true,
+            top_lvl_src,
+        );
 
         if let Some(module) = self.indices.take_module(clause_name!("$toplevel")) {
             self.indices.use_module(
@@ -226,8 +257,12 @@ impl Machine {
                 Err(_) => return,
             };
 
-            compile_user_module(self, file_src, true,
-                                clause_name!("$HOME/.scryerrc"));
+            let rc_src = ListingSource::from_file_and_path(
+                clause_name!(".scryerrc"),
+                path.to_path_buf(),
+            );
+
+            compile_user_module(self, file_src, true, rc_src);
         }
     }
 
@@ -285,27 +320,50 @@ impl Machine {
         };
 
         let atom_tbl = wam.indices.atom_tbl.clone();
+        let mut lib_path = current_dir();
+
+        lib_path.pop();
+        lib_path.push("lib");
 
         wam.indices.add_term_and_goal_expansion_indices();
-        
+
         compile_listing(
             &mut wam,
             parsing_stream(BUILTINS.as_bytes()),
             default_index_store!(atom_tbl.clone()),
             true,
-            clause_name!("builtins.pl"),
+            ListingSource::from_file_and_path(
+                clause_name!("builtins.pl"), 
+                lib_path.clone(),
+            ),
         );
 
         wam.compile_special_forms();
 
         compile_user_module(&mut wam, parsing_stream(ERROR.as_bytes()), true,
-                            clause_name!("error"));
+                            ListingSource::from_file_and_path(
+                                clause_name!("error"),
+                                lib_path.clone(),
+                            )
+        );
         compile_user_module(&mut wam, parsing_stream(LISTS.as_bytes()), true,
-                            clause_name!("lists"));
+                            ListingSource::from_file_and_path(
+                                clause_name!("lists"), 
+                                lib_path.clone(),
+                            ),
+        );
         compile_user_module(&mut wam, parsing_stream(NON_ISO.as_bytes()), true,
-                            clause_name!("non_iso"));
+                            ListingSource::from_file_and_path(
+                                clause_name!("non_iso"),
+                                lib_path.clone(),
+                            )
+        );
         compile_user_module(&mut wam, parsing_stream(SI.as_bytes()), true,
-                            clause_name!("si"));
+                            ListingSource::from_file_and_path(
+                                clause_name!("si"), 
+                                lib_path.clone(),
+                            )
+        );
 
         if wam.compile_top_level().is_err() {
             panic!("Loading '$toplevel' module failed");
@@ -494,7 +552,7 @@ impl Machine {
                    load_library(self, name, false)
                },
            ModuleSource::File(name) =>
-                load_module_from_file(self, name.as_str(), false)
+                load_module_from_file(self, PathBuf::from(name.as_str()), false)
        };
 
        let result = load_result.and_then(|name| {
@@ -545,7 +603,7 @@ impl Machine {
                    load_library(self, name, false)
                },
            ModuleSource::File(name) =>
-                load_module_from_file(self, name.as_str(), false)
+                load_module_from_file(self, PathBuf::from(name.as_str()), false)
        };
 
        let result = load_result.and_then(|name| {
@@ -571,7 +629,7 @@ impl Machine {
     fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr) {
         match code_ptr {
             REPLCodePtr::CompileBatch => {
-                let user_src = clause_name!("user");
+                let user_src = ListingSource::User;
 
                 let src = readline::input_stream();
                 readline::set_prompt(false);
index 0ed1c437158514d9af67311aa7b8aef5462120db..17c5136f69cae494f61ac5ef55042f3fc501f325 100644 (file)
@@ -11,7 +11,11 @@ use std::mem;
 
 // Module's and related types are defined in forms.
 impl Module {
-    pub fn new(module_decl: ModuleDecl, atom_tbl: TabledData<Atom>) -> Self
+    pub fn new(
+        module_decl: ModuleDecl,
+        atom_tbl: TabledData<Atom>,
+        listing_src: ListingSource,
+    ) -> Self
     {
         Module {
             module_decl,
@@ -26,6 +30,7 @@ impl Module {
             op_dir: default_op_dir(),
             inserted_expansions: false,
             is_impromptu_module: false,
+            listing_src,
         }
     }