From 9a80d398e854c5cf4e7dab0721829c7be8f2a854 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Mon, 13 Jan 2020 20:17:22 -0700 Subject: [PATCH] add listing sources to modules --- src/prolog/forms.rs | 28 ++++++++ src/prolog/machine/compile.rs | 76 ++++++++++++++-------- src/prolog/machine/dynamic_database.rs | 6 +- src/prolog/machine/mod.rs | 90 +++++++++++++++++++++----- src/prolog/machine/modules.rs | 7 +- 5 files changed, 160 insertions(+), 47 deletions(-) diff --git a/src/prolog/forms.rs b/src/prolog/forms.rs index aa8eeec6..e60e1b4a 100644 --- a/src/prolog/forms.rs +++ b/src/prolog/forms.rs @@ -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); #[derive(Clone)] @@ -352,6 +379,7 @@ pub struct Module { pub local_goal_expansions: (Predicate, VecDeque), 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)] diff --git a/src/prolog/machine/compile.rs b/src/prolog/machine/compile.rs index d2403a87..fcdaf90a 100644 --- a/src/prolog/machine/compile.rs +++ b/src/prolog/machine/compile.rs @@ -40,9 +40,11 @@ pub fn print_code(code: &Code) { } } -fn fix_filename(atom_tbl: TabledData, filename: &str) -> Result { - let mut path = PathBuf::from(filename); - +fn fix_filename( + atom_tbl: TabledData, + mut path: PathBuf, +) -> Result +{ if !path.is_file() { if path.extension().is_none() { path.set_extension("pl"); @@ -61,7 +63,7 @@ fn load_module( wam: &mut Machine, stream: ParsingStream, suppress_warnings: bool, - listing_src: ClauseName, + listing_src: &ListingSource, ) -> Result { // 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( 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( pub(super) fn load_module_from_file( wam: &mut Machine, - filename: &str, + path_buf: PathBuf, suppress_warnings: bool, ) -> Result { - 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); @@ -330,7 +335,7 @@ pub(super) fn compile_into_module( 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, VecDeque), 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 { 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( wam: &mut Machine, src: ParsingStream, - listing_src: ClauseName, + listing_src: ListingSource, ) -> Result { 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( src: ParsingStream, 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( wam: &mut Machine, src: ParsingStream, 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)); diff --git a/src/prolog/machine/dynamic_database.rs b/src/prolog/machine/dynamic_database.rs index 17caf908..d6ffd1a3 100644 --- a/src/prolog/machine/dynamic_database.rs +++ b/src/prolog/machine/dynamic_database.rs @@ -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), } diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index b33373ca..14465337 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -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); diff --git a/src/prolog/machine/modules.rs b/src/prolog/machine/modules.rs index 0ed1c437..17c5136f 100644 --- a/src/prolog/machine/modules.rs +++ b/src/prolog/machine/modules.rs @@ -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) -> Self + pub fn new( + module_decl: ModuleDecl, + atom_tbl: TabledData, + 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, } } -- 2.54.0