// name and fixity -> operator type and precedence.
pub type OpDir = HashMap<OpDirKey, (Specifier, usize, ClauseName)>;
+pub type ModuleCodeDir = HashMap<PredicateKey, ModuleCodeIndex>;
+
pub type CodeDir = HashMap<PredicateKey, CodeIndex>;
pub type TermDir = HashMap<PredicateKey, Predicate>;
pub struct Module {
pub module_decl: ModuleDecl,
- pub code_dir: CodeDir,
+ pub code_dir: ModuleCodeDir,
pub op_dir: OpDir
}
impl Module {
pub fn new(module_decl: ModuleDecl) -> Self {
Module { module_decl,
- code_dir: CodeDir::new(),
+ code_dir: ModuleCodeDir::new(),
op_dir: OpDir::new() }
}
}
+pub fn as_module_code_dir(code_dir: CodeDir) -> ModuleCodeDir {
+ code_dir.into_iter()
+ .map(|(k, code_idx)| (k, ModuleCodeIndex(code_idx.0.get(), code_idx.1)))
+ .collect()
+}
+
impl SubModuleUser for Module {
fn op_dir(&mut self) -> &mut OpDir {
&mut self.op_dir
}
- fn code_dir(&mut self) -> &mut CodeDir {
- &mut self.code_dir
+ fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: ModuleCodeIndex) {
+ self.code_dir.insert((name, arity), idx);
}
}
pub trait SubModuleUser {
fn op_dir(&mut self) -> &mut OpDir;
- fn code_dir(&mut self) -> &mut CodeDir;
+ fn insert_dir_entry(&mut self, ClauseName, usize, ModuleCodeIndex);
// returns true on successful import.
fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool {
let name = name.defrock_brackets();
-
- if arity == 1 {
- if let Some(op_data) = submodule.op_dir.get(&(name.clone(), Fixity::Pre)) {
- self.op_dir().insert((name.clone(), Fixity::Pre), op_data.clone());
- }
-
- if let Some(op_data) = submodule.op_dir.get(&(name.clone(), Fixity::Post)) {
- self.op_dir().insert((name.clone(), Fixity::Post), op_data.clone());
- }
- } else if arity == 2 {
- if let Some(op_data) = submodule.op_dir.get(&(name.clone(), Fixity::In)) {
- self.op_dir().insert((name.clone(), Fixity::In), op_data.clone());
+
+ {
+ let mut insert_op_dir = |fix| {
+ if let Some(op_data) = submodule.op_dir.get(&(name.clone(), fix)) {
+ self.op_dir().insert((name.clone(), fix), op_data.clone());
+ }
+ };
+
+ if arity == 1 {
+ insert_op_dir(Fixity::Pre);
+ insert_op_dir(Fixity::Post);
+ } else if arity == 2 {
+ insert_op_dir(Fixity::In);
}
}
-
- if self.code_dir().contains_key(&(name.clone(), arity)) {
- println!("warning: overwriting {}/{}", &name, arity);
- }
-
+
if let Some(code_data) = submodule.code_dir.get(&(name.clone(), arity)) {
- if let Some(ref mut global_code_data) = self.code_dir().get_mut(&(name.clone(), arity)) {
- global_code_data.1 = code_data.1.clone();
- global_code_data.0.set(code_data.0.get());
-
- return true; // done to appease the borrow checker.
- }
-
- self.code_dir().insert((name, arity), code_data.clone());
+ self.insert_dir_entry(name, arity, code_data.clone());
+ true
} else {
- return false;
+ false
}
-
- true
}
fn use_qualified_module(&mut self, submodule: &Module, exports: Vec<PredicateKey>) -> EvalSession
#[derive(Clone)]
pub struct CodeIndex(pub Rc<Cell<IndexPtr>>, pub ClauseName);
+#[derive(Clone)]
+pub struct ModuleCodeIndex(pub IndexPtr, pub ClauseName);
+
+impl From<ModuleCodeIndex> for CodeIndex {
+ fn from(value: ModuleCodeIndex) -> Self {
+ CodeIndex(Rc::new(Cell::new(value.0)), value.1.clone())
+ }
+}
+
impl Default for CodeIndex {
fn default() -> Self {
CodeIndex(Rc::new(Cell::new(IndexPtr::Undefined)), clause_name!(""))
module_decl.exports.push((clause_name!("call"), arity));
}
- Module { module_decl, code_dir, op_dir }
+ Module { module_decl, code_dir: as_module_code_dir(code_dir), op_dir }
}
} else {
return EvalSession::from(EvalError::ModuleNotFound);
}
-
+
wam.use_module_in_toplevel(name);
},
TopLevelPacket::Decl(TopLevel::Declaration(Declaration::UseQualifiedModule(name, exports)), _) => {
}
if let Some(mut module) = module {
- module.code_dir.extend(code_dir.into_iter());
+ module.code_dir.extend(as_module_code_dir(code_dir));
module.op_dir.extend(op_dir.into_iter());
wam.add_module(module, code);
CodeDirs { code_dir, modules }
}
- fn get_current_code_dir(&self, p: &CodePtr) -> &CodeDir {
- let module_name = p.module_name();
-
- match module_name {
- ClauseName::BuiltIn("user") | ClauseName::BuiltIn("builtin") => self.code_dir,
- _ => &self.modules.get(&module_name).unwrap().code_dir
+ pub(super) fn get(&self, name: ClauseName, arity: usize, in_mod: ClauseName) -> Option<CodeIndex>
+ {
+ match in_mod.as_str() {
+ "user" | "builtin" => self.code_dir.get(&(name, arity)).cloned(),
+ _ => match self.modules.get(&in_mod) {
+ Some(&Module { ref code_dir, .. }) =>
+ code_dir.get(&(name, arity)).cloned().map(CodeIndex::from),
+ None => None
+ }
}
}
-
- pub(super) fn get(&self, name: ClauseName, arity: usize, p: &CodePtr) -> Option<CodeIndex> {
- let code_dir = self.get_current_code_dir(p);
- code_dir.get(&(name, arity)).cloned()
- }
}
pub(super) struct DuplicateTerm<'a> {
},
&ClauseType::CallN =>
if let Some((name, arity)) = machine_st.setup_call_n(arity) {
- if let Some(idx) = code_dirs.get(name.clone(), arity, &machine_st.p.clone()) {
+ if let Some(idx) = code_dirs.get(name.clone(), arity, machine_st.p.module_name())
+ {
self.context_call(machine_st, name, arity, idx, lco)
} else {
Err(predicate_existence_error(name, arity, machine_st.heap.h))
self.registers[arity - 1] = pred;
if let Some((name, arity)) = self.setup_call_n(arity - 1) {
- if let Some(idx) = code_dirs.get(name.clone(), arity, &self.p.clone()) {
+ if let Some(idx) = code_dirs.get(name.clone(), arity, self.p.module_name()) {
try_or_fail!(self, call_policy.try_execute(self, name, arity, idx));
return;
}
self.op_dir
}
- fn code_dir(&mut self) -> &mut CodeDir {
- self.code_dir
+ fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: ModuleCodeIndex) {
+ if let Some(ref mut code_idx) = self.code_dir.get_mut(&(name.clone(), arity)) {
+ println!("warning: overwriting {}/{}", &name, arity);
+
+ code_idx.0.set(idx.0);
+ code_idx.1 = idx.1;
+
+ return;
+ }
+
+ self.code_dir.insert((name, arity), CodeIndex::from(idx));
}
}
{
self.remove_module(name.clone());
- match self.modules.get(&name) {
- Some(ref module) => {
+ match self.modules.get_mut(&name) {
+ Some(ref mut module) => {
let mut indices = MachineCodeIndex { code_dir: &mut self.code_dir,
op_dir: &mut self.op_dir };
pub fn use_module_in_toplevel(&mut self, name: ClauseName) -> EvalSession {
self.remove_module(name.clone());
- match self.modules.get(&name) {
- Some(ref module) => {
+ match self.modules.get_mut(&name) {
+ Some(ref mut module) => {
let mut indices = MachineCodeIndex { code_dir: &mut self.code_dir,
op_dir: &mut self.op_dir };
entry.0.set(IndexPtr::Index(offset));
entry.1 = clause_name!("user");
-
+
EvalSession::EntrySuccess
}
let e = self.ms.e;
let r = var_data.as_reg_type().reg_num();
let addr = self.ms.and_stack[e][r].clone();
-
- heap_locs.insert(var.clone(), addr);
+
+ heap_locs.insert(var.clone(), addr);
},
&VarData::Temp(cn, _, _) if cn == chunk_num => {
let r = var_data.as_reg_type();
-Subproject commit 0e9dd3a01f21c6457bd1bcb35518ccdb502c82bd
+Subproject commit 1b3bcc77f2b9d264c9753653ae87bfa3b4c11081