add qualified imports
This commit is contained in:
@@ -264,3 +264,11 @@ prolog> :{{
|
|||||||
local_member(X, Xs) :- member(X, Xs).
|
local_member(X, Xs) :- member(X, Xs).
|
||||||
}}:
|
}}:
|
||||||
```
|
```
|
||||||
|
`use_module` directives can be qualified by adding a list of imports:
|
||||||
|
|
||||||
|
```
|
||||||
|
prolog> :- use_module(library(lists), [member/2]).
|
||||||
|
```
|
||||||
|
|
||||||
|
A qualified `use_module` can be used to remove imports from the
|
||||||
|
toplevel by giving it an empty import list.
|
||||||
|
|||||||
@@ -172,8 +172,8 @@ pub trait SubModuleUser {
|
|||||||
fn op_dir(&mut self) -> &mut OpDir;
|
fn op_dir(&mut self) -> &mut OpDir;
|
||||||
fn code_dir(&mut self) -> &mut CodeDir;
|
fn code_dir(&mut self) -> &mut CodeDir;
|
||||||
|
|
||||||
fn use_module(&mut self, submodule: &Module) -> EvalSession {
|
// returns true on successful import.
|
||||||
for (name, arity) in submodule.module_decl.exports.iter().cloned() {
|
fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool {
|
||||||
let name = name.defrock_brackets();
|
let name = name.defrock_brackets();
|
||||||
|
|
||||||
if arity == 1 {
|
if arity == 1 {
|
||||||
@@ -196,7 +196,30 @@ pub trait SubModuleUser {
|
|||||||
|
|
||||||
if let Some(code_data) = submodule.code_dir.get(&(name.clone(), arity)) {
|
if let Some(code_data) = submodule.code_dir.get(&(name.clone(), arity)) {
|
||||||
self.code_dir().insert((name, arity), code_data.clone());
|
self.code_dir().insert((name, arity), code_data.clone());
|
||||||
|
true
|
||||||
} else {
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn use_qualified_module(&mut self, submodule: &Module, exports: Vec<PredicateKey>) -> EvalSession
|
||||||
|
{
|
||||||
|
for (name, arity) in exports {
|
||||||
|
if !submodule.module_decl.exports.contains(&(name.clone(), arity)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.import_decl(name, arity, submodule) {
|
||||||
|
return EvalSession::from(EvalError::ModuleDoesNotContainExport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EvalSession::EntrySuccess
|
||||||
|
}
|
||||||
|
|
||||||
|
fn use_module(&mut self, submodule: &Module) -> EvalSession {
|
||||||
|
for (name, arity) in submodule.module_decl.exports.iter().cloned() {
|
||||||
|
if !self.import_decl(name, arity, submodule) {
|
||||||
return EvalSession::from(EvalError::ModuleDoesNotContainExport);
|
return EvalSession::from(EvalError::ModuleDoesNotContainExport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -208,7 +231,8 @@ pub trait SubModuleUser {
|
|||||||
pub enum Declaration {
|
pub enum Declaration {
|
||||||
Module(ModuleDecl),
|
Module(ModuleDecl),
|
||||||
Op(OpDecl),
|
Op(OpDecl),
|
||||||
UseModule(ClauseName)
|
UseModule(ClauseName),
|
||||||
|
UseQualifiedModule(ClauseName, Vec<PredicateKey>)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum TopLevel {
|
pub enum TopLevel {
|
||||||
|
|||||||
@@ -551,6 +551,8 @@ fn compile_decl(wam: &mut Machine, tl: TopLevel, queue: Vec<TopLevel>) -> EvalSe
|
|||||||
},
|
},
|
||||||
TopLevel::Declaration(Declaration::UseModule(name)) =>
|
TopLevel::Declaration(Declaration::UseModule(name)) =>
|
||||||
wam.use_module_in_toplevel(name),
|
wam.use_module_in_toplevel(name),
|
||||||
|
TopLevel::Declaration(Declaration::UseQualifiedModule(name, exports)) =>
|
||||||
|
wam.use_qualified_module_in_toplevel(name, exports),
|
||||||
TopLevel::Declaration(_) =>
|
TopLevel::Declaration(_) =>
|
||||||
EvalSession::from(ParserError::InvalidModuleDecl),
|
EvalSession::from(ParserError::InvalidModuleDecl),
|
||||||
_ => {
|
_ => {
|
||||||
@@ -629,6 +631,18 @@ pub fn compile_listing(wam: &mut Machine, src_str: &str) -> EvalSession
|
|||||||
|
|
||||||
wam.use_module_in_toplevel(name);
|
wam.use_module_in_toplevel(name);
|
||||||
},
|
},
|
||||||
|
TopLevelPacket::Decl(TopLevel::Declaration(Declaration::UseQualifiedModule(name, exports)), _) => {
|
||||||
|
if let Some(ref submodule) = wam.get_module(name.clone()) {
|
||||||
|
if let Some(ref mut module) = module {
|
||||||
|
module.use_qualified_module(submodule, exports);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return EvalSession::from(EvalError::ModuleNotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
wam.use_qualified_module_in_toplevel(name, exports);
|
||||||
|
},
|
||||||
TopLevelPacket::Decl(TopLevel::Declaration(Declaration::Op(..)), _) => {},
|
TopLevelPacket::Decl(TopLevel::Declaration(Declaration::Op(..)), _) => {},
|
||||||
TopLevelPacket::Decl(decl, queue) => {
|
TopLevelPacket::Decl(decl, queue) => {
|
||||||
let p = code.len() + wam.code_size();
|
let p = code.len() + wam.code_size();
|
||||||
|
|||||||
@@ -125,6 +125,22 @@ impl Machine {
|
|||||||
self.ms.atom_tbl.clone()
|
self.ms.atom_tbl.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn use_qualified_module_in_toplevel(&mut self, name: ClauseName, exports: Vec<PredicateKey>)
|
||||||
|
-> EvalSession
|
||||||
|
{
|
||||||
|
self.remove_module(name.clone());
|
||||||
|
|
||||||
|
match self.modules.get(&name) {
|
||||||
|
Some(ref module) => {
|
||||||
|
let mut indices = MachineCodeIndex { code_dir: &mut self.code_dir,
|
||||||
|
op_dir: &mut self.op_dir };
|
||||||
|
|
||||||
|
indices.use_qualified_module(module, exports)
|
||||||
|
},
|
||||||
|
None => EvalSession::from(EvalError::ModuleNotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn use_module_in_toplevel(&mut self, name: ClauseName) -> EvalSession {
|
pub fn use_module_in_toplevel(&mut self, name: ClauseName) -> EvalSession {
|
||||||
self.remove_module(name.clone());
|
self.remove_module(name.clone());
|
||||||
|
|
||||||
|
|||||||
Submodule src/prolog/parser updated: e95c45f411...54c9d9394b
Reference in New Issue
Block a user