allow paths in use_module(library(..)) (#604)
This commit is contained in:
@@ -600,31 +600,45 @@ fn load_library(
|
|||||||
name: ClauseName,
|
name: ClauseName,
|
||||||
suppress_warnings: bool,
|
suppress_warnings: bool,
|
||||||
) -> Result<ClauseName, SessionError> {
|
) -> Result<ClauseName, SessionError> {
|
||||||
match LIBRARIES.borrow().get(name.as_str()) {
|
|
||||||
Some(code) => {
|
|
||||||
let mut lib_path = current_dir();
|
let mut lib_path = current_dir();
|
||||||
|
|
||||||
lib_path.pop();
|
lib_path.pop();
|
||||||
lib_path.push("lib");
|
lib_path.push("lib");
|
||||||
|
|
||||||
|
let (stream, listing_src) =
|
||||||
|
match LIBRARIES.borrow().get(name.as_str()) {
|
||||||
|
Some(code) => {
|
||||||
let listing_src = ListingSource::from_file_and_path(name, lib_path);
|
let listing_src = ListingSource::from_file_and_path(name, lib_path);
|
||||||
|
(Stream::from(*code), listing_src)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// assume that name is a path.
|
||||||
|
lib_path.push(name.as_str());
|
||||||
|
lib_path.set_extension("pl");
|
||||||
|
|
||||||
|
let file =
|
||||||
|
match File::open(&lib_path) {
|
||||||
|
Ok(file) => {
|
||||||
|
file
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
let err = ExistenceError::ModuleSource(ModuleSource::Library(name));
|
||||||
|
return Err(SessionError::ExistenceError(err));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let listing_src = ListingSource::from_file_and_path(name.clone(), lib_path);
|
||||||
|
(Stream::from_file_as_input(name, file), listing_src)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
load_module(
|
load_module(
|
||||||
wam,
|
wam,
|
||||||
Stream::from(*code),
|
stream,
|
||||||
suppress_warnings,
|
suppress_warnings,
|
||||||
&listing_src,
|
&listing_src,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
None => {
|
|
||||||
let err = ExistenceError::ModuleSource(ModuleSource::Library(
|
|
||||||
name.clone()
|
|
||||||
));
|
|
||||||
|
|
||||||
Err(SessionError::ExistenceError(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ListingCompiler {
|
impl ListingCompiler {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|||||||
@@ -666,21 +666,27 @@ impl Machine {
|
|||||||
Ok(exports)
|
Ok(exports)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn use_module<ToSource>(&mut self, to_src: ToSource)
|
fn use_module(&mut self, to_src: impl Fn(ClauseName) -> ModuleSource)
|
||||||
where ToSource: Fn(ClauseName) -> ModuleSource
|
|
||||||
{
|
{
|
||||||
// the term expander will overwrite the cached query, so save it here.
|
// the term expander will overwrite the cached query, so save it here.
|
||||||
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
||||||
|
|
||||||
let module_spec = self.machine_st[temp_v!(1)].clone();
|
let module_spec = self.machine_st[temp_v!(1)].clone();
|
||||||
let name = {
|
let (name, is_path) = {
|
||||||
let addr = self.machine_st.store(self.machine_st.deref(module_spec));
|
let addr = self.machine_st.store(self.machine_st.deref(module_spec));
|
||||||
|
|
||||||
match self.machine_st.heap.index_addr(&addr).as_ref() {
|
match self.machine_st.heap.index_addr(&addr).as_ref() {
|
||||||
HeapCellValue::Atom(name, _) =>
|
HeapCellValue::Atom(name, _) =>
|
||||||
name.clone(),
|
(name.clone(), name.as_str().contains('/')),
|
||||||
HeapCellValue::Addr(Addr::Char(c)) =>
|
HeapCellValue::Addr(Addr::Char(c)) =>
|
||||||
clause_name!(c.to_string(), self.indices.atom_tbl),
|
(clause_name!(c.to_string(), self.indices.atom_tbl), false),
|
||||||
|
HeapCellValue::Addr(addr @ Addr::PStrLocation(..)) => {
|
||||||
|
let mut heap_pstr_iter = self.machine_st.heap_pstr_iter(*addr);
|
||||||
|
let filename = heap_pstr_iter.to_string();
|
||||||
|
let is_path = filename.contains('/');
|
||||||
|
|
||||||
|
(clause_name!(filename, self.indices.atom_tbl), is_path)
|
||||||
|
}
|
||||||
_ =>
|
_ =>
|
||||||
unreachable!(),
|
unreachable!(),
|
||||||
}
|
}
|
||||||
@@ -688,6 +694,9 @@ impl Machine {
|
|||||||
|
|
||||||
let load_result = match to_src(name) {
|
let load_result = match to_src(name) {
|
||||||
ModuleSource::Library(name) =>
|
ModuleSource::Library(name) =>
|
||||||
|
if is_path {
|
||||||
|
load_library(self, name, false)
|
||||||
|
} else {
|
||||||
if let Some(module) = self.indices.take_module(name.clone()) {
|
if let Some(module) = self.indices.take_module(name.clone()) {
|
||||||
self.indices.remove_module(clause_name!("user"), &module);
|
self.indices.remove_module(clause_name!("user"), &module);
|
||||||
self.indices.modules.insert(name.clone(), module);
|
self.indices.modules.insert(name.clone(), module);
|
||||||
@@ -695,7 +704,8 @@ impl Machine {
|
|||||||
Ok(name)
|
Ok(name)
|
||||||
} else {
|
} else {
|
||||||
load_library(self, name, false)
|
load_library(self, name, false)
|
||||||
},
|
}
|
||||||
|
}
|
||||||
ModuleSource::File(name) =>
|
ModuleSource::File(name) =>
|
||||||
load_module_from_file(self, PathBuf::from(name.as_str()), false)
|
load_module_from_file(self, PathBuf::from(name.as_str()), false)
|
||||||
};
|
};
|
||||||
@@ -717,21 +727,27 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn use_qualified_module<ToSource>(&mut self, to_src: ToSource)
|
fn use_qualified_module(&mut self, to_src: impl Fn(ClauseName) -> ModuleSource)
|
||||||
where ToSource: Fn(ClauseName) -> ModuleSource
|
|
||||||
{
|
{
|
||||||
// the term expander will overwrite the cached query, so save it here.
|
// the term expander will overwrite the cached query, so save it here.
|
||||||
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
let cached_query = mem::replace(&mut self.code_repo.cached_query, vec![]);
|
||||||
|
|
||||||
let module_spec = self.machine_st[temp_v!(1)].clone();
|
let module_spec = self.machine_st[temp_v!(1)].clone();
|
||||||
let name = {
|
let (name, is_path) = {
|
||||||
let addr = self.machine_st.store(self.machine_st.deref(module_spec));
|
let addr = self.machine_st.store(self.machine_st.deref(module_spec));
|
||||||
|
|
||||||
match self.machine_st.heap.index_addr(&addr).as_ref() {
|
match self.machine_st.heap.index_addr(&addr).as_ref() {
|
||||||
HeapCellValue::Atom(name, _) =>
|
HeapCellValue::Atom(name, _) =>
|
||||||
name.clone(),
|
(name.clone(), name.as_str().contains('/')),
|
||||||
HeapCellValue::Addr(Addr::Char(c)) =>
|
HeapCellValue::Addr(Addr::Char(c)) =>
|
||||||
clause_name!(c.to_string(), self.indices.atom_tbl),
|
(clause_name!(c.to_string(), self.indices.atom_tbl), false),
|
||||||
|
HeapCellValue::Addr(addr @ Addr::PStrLocation(..)) => {
|
||||||
|
let mut heap_pstr_iter = self.machine_st.heap_pstr_iter(*addr);
|
||||||
|
let filename = heap_pstr_iter.to_string();
|
||||||
|
let is_path = filename.contains('/');
|
||||||
|
|
||||||
|
(clause_name!(filename, self.indices.atom_tbl), is_path)
|
||||||
|
}
|
||||||
_ =>
|
_ =>
|
||||||
unreachable!(),
|
unreachable!(),
|
||||||
}
|
}
|
||||||
@@ -747,6 +763,9 @@ impl Machine {
|
|||||||
|
|
||||||
let load_result = match to_src(name) {
|
let load_result = match to_src(name) {
|
||||||
ModuleSource::Library(name) =>
|
ModuleSource::Library(name) =>
|
||||||
|
if is_path {
|
||||||
|
load_library(self, name, false)
|
||||||
|
} else {
|
||||||
if let Some(module) = self.indices.take_module(name.clone()) {
|
if let Some(module) = self.indices.take_module(name.clone()) {
|
||||||
self.indices.remove_module(clause_name!("user"), &module);
|
self.indices.remove_module(clause_name!("user"), &module);
|
||||||
self.indices.modules.insert(name.clone(), module);
|
self.indices.modules.insert(name.clone(), module);
|
||||||
@@ -754,6 +773,7 @@ impl Machine {
|
|||||||
Ok(name)
|
Ok(name)
|
||||||
} else {
|
} else {
|
||||||
load_library(self, name, false)
|
load_library(self, name, false)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
ModuleSource::File(name) =>
|
ModuleSource::File(name) =>
|
||||||
load_module_from_file(self, PathBuf::from(name.as_str()), false)
|
load_module_from_file(self, PathBuf::from(name.as_str()), false)
|
||||||
|
|||||||
@@ -340,16 +340,39 @@ fn setup_module_decl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_use_module_decl(mut terms: Vec<Box<Term>>) -> Result<ModuleSource, ParserError> {
|
fn read_library_path(term: Term, atom_tbl: TabledData<Atom>) -> Option<ClauseName> {
|
||||||
|
match term {
|
||||||
|
Term::Constant(_, Constant::Atom(atom, _)) => {
|
||||||
|
Some(atom.defrock_brackets())
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let mut atoms = vec![];
|
||||||
|
|
||||||
|
for term in unfold_by_str(term, "/") {
|
||||||
|
match term {
|
||||||
|
Term::Constant(_, Constant::Atom(atom, _)) => {
|
||||||
|
atoms.push(atom.as_str().to_owned());
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(clause_name!(atoms.join("/"), atom_tbl))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_use_module_decl(
|
||||||
|
mut terms: Vec<Box<Term>>,
|
||||||
|
atom_tbl: TabledData<Atom>,
|
||||||
|
) -> Result<ModuleSource, ParserError> {
|
||||||
match *terms.pop().unwrap() {
|
match *terms.pop().unwrap() {
|
||||||
Term::Clause(_, ref name, ref mut terms, None)
|
Term::Clause(_, ref name, ref mut terms, None)
|
||||||
if name.as_str() == "library" && terms.len() == 1 =>
|
if name.as_str() == "library" && terms.len() == 1 =>
|
||||||
{
|
{
|
||||||
terms
|
read_library_path(*terms.pop().unwrap(), atom_tbl)
|
||||||
.pop()
|
|
||||||
.unwrap()
|
|
||||||
.to_constant()
|
|
||||||
.and_then(|c| c.to_atom())
|
|
||||||
.map(|c| ModuleSource::Library(c))
|
.map(|c| ModuleSource::Library(c))
|
||||||
.ok_or(ParserError::InvalidUseModuleDecl)
|
.ok_or(ParserError::InvalidUseModuleDecl)
|
||||||
}
|
}
|
||||||
@@ -396,11 +419,7 @@ fn setup_qualified_import(
|
|||||||
Term::Clause(_, ref name, ref mut terms, None)
|
Term::Clause(_, ref name, ref mut terms, None)
|
||||||
if name.as_str() == "library" && terms.len() == 1 =>
|
if name.as_str() == "library" && terms.len() == 1 =>
|
||||||
{
|
{
|
||||||
terms
|
read_library_path(*terms.pop().unwrap(), atom_tbl.clone())
|
||||||
.pop()
|
|
||||||
.unwrap()
|
|
||||||
.to_constant()
|
|
||||||
.and_then(|c| c.to_atom())
|
|
||||||
.map(|c| ModuleSource::Library(c))
|
.map(|c| ModuleSource::Library(c))
|
||||||
.ok_or(ParserError::InvalidUseModuleDecl)
|
.ok_or(ParserError::InvalidUseModuleDecl)
|
||||||
}
|
}
|
||||||
@@ -685,7 +704,7 @@ fn setup_declaration<'a, 'b, 'c>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
("use_module", 1) => {
|
("use_module", 1) => {
|
||||||
Ok(Declaration::UseModule(setup_use_module_decl(terms)?))
|
Ok(Declaration::UseModule(setup_use_module_decl(terms, indices.atom_tbl())?))
|
||||||
}
|
}
|
||||||
("use_module", 2) => {
|
("use_module", 2) => {
|
||||||
let (name, exports) = setup_qualified_import(terms, indices.atom_tbl())?;
|
let (name, exports) = setup_qualified_import(terms, indices.atom_tbl())?;
|
||||||
|
|||||||
@@ -387,8 +387,11 @@ consult(Item) :-
|
|||||||
|
|
||||||
use_module(Module) :-
|
use_module(Module) :-
|
||||||
( nonvar(Module) ->
|
( nonvar(Module) ->
|
||||||
( Module = library(Filename) -> '$use_module'(Filename)
|
( Module = library(Filename) ->
|
||||||
; atom(Module) -> '$use_module_from_file'(Module)
|
write_term_to_chars(Filename, [], FilenameString),
|
||||||
|
'$use_module'(FilenameString)
|
||||||
|
; atom(Module) ->
|
||||||
|
'$use_module_from_file'(Module)
|
||||||
; throw(error(invalid_module_specifier, use_module/1))
|
; throw(error(invalid_module_specifier, use_module/1))
|
||||||
)
|
)
|
||||||
; throw(error(instantiation_error, use_module/1))
|
; throw(error(instantiation_error, use_module/1))
|
||||||
@@ -399,7 +402,8 @@ use_module(Module, QualifiedExports) :-
|
|||||||
( list_si(QualifiedExports) ->
|
( list_si(QualifiedExports) ->
|
||||||
maplist('$module_export'(use_module/2), QualifiedExports) ->
|
maplist('$module_export'(use_module/2), QualifiedExports) ->
|
||||||
( Module = library(Filename) ->
|
( Module = library(Filename) ->
|
||||||
'$use_qualified_module'(Filename, QualifiedExports)
|
write_term_to_chars(Filename, [], FilenameString),
|
||||||
|
'$use_qualified_module'(FilenameString, QualifiedExports)
|
||||||
; atom(Module) ->
|
; atom(Module) ->
|
||||||
'$use_qualified_module_from_file'(Module, QualifiedExports)
|
'$use_qualified_module_from_file'(Module, QualifiedExports)
|
||||||
; throw(error(invalid_module_specifier, use_module/2))
|
; throw(error(invalid_module_specifier, use_module/2))
|
||||||
|
|||||||
Reference in New Issue
Block a user