provisional changes to module insertion

This commit is contained in:
Mark Thom
2018-09-12 20:46:15 -06:00
parent 79da405d38
commit fbf16e2aea
10 changed files with 380 additions and 417 deletions

View File

@@ -27,8 +27,18 @@ pub struct MachineCodeIndices<'a> {
}
impl<'a> MachineCodeIndices<'a> {
#[inline]
pub(super) fn copy_and_swap(&mut self, other: &mut MachineCodeIndices<'a>) {
*self.code_dir = other.code_dir.clone();
*self.op_dir = other.op_dir.clone();
swap(&mut self.code_dir, &mut other.code_dir);
swap(&mut self.op_dir, &mut other.op_dir);
swap(&mut self.modules, &mut other.modules);
}
pub(super)
fn lookup(&mut self, name: ClauseName, arity: usize, fixity: Option<Fixity>) -> ClauseType
fn get_clause_type(&mut self, name: ClauseName, arity: usize, fixity: Option<Fixity>) -> ClauseType
{
match ClauseType::from(name, arity, fixity) {
ClauseType::Named(name, _) => {
@@ -67,6 +77,17 @@ pub struct Machine {
cached_query: Option<Code>
}
fn get_code_index(code_dir: &CodeDir, modules: &ModuleDir, key: PredicateKey, module: ClauseName)
-> Option<CodeIndex>
{
match module.as_str() {
"user" | "builtin" => code_dir.get(&key).cloned(),
_ => modules.get(&module).and_then(|ref module| {
module.code_dir.get(&key).cloned().map(CodeIndex::from)
})
}
}
impl Index<LocalCodePtr> for Machine {
type Output = Line;
@@ -88,6 +109,14 @@ impl<'a> SubModuleUser for MachineCodeIndices<'a> {
self.op_dir
}
fn get_code_index(&self, key: PredicateKey, module: ClauseName) -> Option<CodeIndex> {
get_code_index(&self.code_dir, &self.modules, key, module)
}
fn remove_code_index(&mut self, key: PredicateKey) {
self.code_dir.remove(&key);
}
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)) {
if !code_idx.is_undefined() {
@@ -116,22 +145,19 @@ impl Machine {
code: Code::new(),
code_dir: CodeDir::new(),
op_dir: default_op_dir(),
// term_dir: TermDir::new(),
// term_dir: TermDir::new(),
modules: HashMap::new(),
cached_query: None
};
let indices = machine_code_indices!(&mut CodeDir::new(), &mut default_op_dir(),
&mut HashMap::new());
compile_listing(&mut wam, BUILTINS.as_bytes(), indices);
compile_listing(&mut wam, BUILTINS.as_bytes(),
default_machine_code_indices!(),
default_machine_code_indices!());
compile_user_module(&mut wam, LISTS.as_bytes());
compile_user_module(&mut wam, CONTROL.as_bytes());
compile_user_module(&mut wam, QUEUES.as_bytes());
wam.use_module_in_toplevel(clause_name!("builtins"));
wam
}
@@ -139,53 +165,6 @@ impl Machine {
pub fn machine_flags(&self) -> MachineFlags {
self.ms.flags
}
fn remove_module(&mut self, module_name: ClauseName) {
let iter = if let Some(submodule) = self.modules.get(&module_name) {
submodule.module_decl.exports.iter().cloned()
} else {
return;
};
for (name, arity) in iter {
let name = name.defrock_brackets();
match self.code_dir.get(&(name.clone(), arity)).cloned() {
Some(CodeIndex (ref code_idx)) => {
if &code_idx.borrow().1 != &module_name {
continue;
}
self.code_dir.remove(&(name.clone(), arity));
// remove or respecify ops.
if arity == 2 {
if let Some((_, _, mod_name)) = self.op_dir.get(&(name.clone(), Fixity::In)).cloned()
{
if mod_name == module_name {
self.op_dir.remove(&(name.clone(), Fixity::In));
}
}
} else if arity == 1 {
if let Some((_, _, mod_name)) = self.op_dir.get(&(name.clone(), Fixity::Pre)).cloned()
{
if mod_name == module_name {
self.op_dir.remove(&(name.clone(), Fixity::Pre));
}
}
if let Some((_, _, mod_name)) = self.op_dir.get(&(name.clone(), Fixity::Post)).cloned()
{
if mod_name == module_name {
self.op_dir.remove(&(name.clone(), Fixity::Post));
}
}
}
},
_ => {}
};
}
}
#[inline]
pub fn failed(&self) -> bool {
@@ -196,86 +175,70 @@ impl Machine {
pub fn atom_tbl(&self) -> TabledData<Atom> {
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());
if let Some(mut module) = self.modules.remove(&name) {
let result = {
let mut indices = machine_code_indices!(&mut self.code_dir, &mut self.op_dir,
&mut self.modules);
indices.use_qualified_module(&mut module, &exports)
};
self.modules.insert(name, module);
result
} else {
EvalSession::from(SessionError::ModuleNotFound)
}
}
pub fn use_module_in_toplevel(&mut self, name: ClauseName) -> EvalSession
{
self.remove_module(name.clone());
if let Some(mut module) = self.modules.remove(&name) {
let result = {
let mut indices = machine_code_indices!(&mut self.code_dir, &mut self.op_dir,
&mut self.modules);
indices.use_module(&mut module)
};
self.modules.insert(name, module);
result
} else {
EvalSession::from(SessionError::ModuleNotFound)
}
}
pub fn get_module(&self, name: ClauseName) -> Option<&Module> {
self.modules.get(&name)
}
pub fn add_batched_code(&mut self, mut code: Code, code_dir: CodeDir) {
self.code.append(&mut code);
self.code_dir.extend(code_dir.into_iter());
pub fn add_batched_code(&mut self, code: Code, code_dir: CodeDir) -> Result<(), SessionError>
{
for (ref key, ref idx) in code_dir.iter() {
match ClauseType::from(key.0.clone(), key.1, None) {
ClauseType::Named(..) | ClauseType::Op(..) => {},
_ => {
// ensure we don't try to overwrite the name/arity of a builtin.
let err_str = format!("{}/{}", key.0, key.1);
return Err(SessionError::CannotOverwriteBuiltIn(err_str));
}
};
if idx.module_name().as_str() == "builtins" {
continue;
}
if let Some(ref existing_idx) = self.code_dir.get(&key) {
// ensure we don't try to overwrite an existing predicate from a different module.
if !existing_idx.is_undefined() {
if existing_idx.module_name() != idx.module_name() {
let err_str = format!("{}/{} from module {}", key.0, key.1,
existing_idx.module_name().as_str());
return Err(SessionError::CannotOverwriteImport(err_str));
}
}
}
}
self.code.extend(code.into_iter());
Ok(self.code_dir.extend(code_dir.into_iter()))
}
#[inline]
pub fn add_batched_ops(&mut self, op_dir: OpDir) {
self.op_dir.extend(op_dir.into_iter());
}
#[inline]
pub fn remove_module(&mut self, module: &Module) {
let mut indices = machine_code_indices!(&mut self.code_dir, &mut self.op_dir, &mut self.modules);
indices.remove_module(clause_name!("user"), module);
}
#[inline]
pub fn take_module(&mut self, name: ClauseName) -> Option<Module> {
self.modules.remove(&name)
}
#[inline]
pub fn insert_module(&mut self, module: Module) {
self.modules.insert(module.module_decl.name.clone(), module);
}
#[inline]
pub fn add_module(&mut self, module: Module, code: Code) {
self.modules.insert(module.module_decl.name.clone(), module);
self.code.extend(code.into_iter());
}
pub fn add_user_code(&mut self, name: ClauseName, arity: usize, code: Code) -> EvalSession
{
match self.code_dir.get(&(name.clone(), arity)) {
Some(&CodeIndex (ref idx)) if idx.borrow().1 != clause_name!("user") =>
if !(&CodeIndex(idx.clone())).is_undefined() {
return EvalSession::from(SessionError::ImpermissibleEntry(format!("{}/{}",
name,
arity)))
},
_ => {}
};
let offset = self.code.len();
self.code.extend(code.into_iter());
//self.term_dir.insert((name.clone(), arity), pred);
let idx = self.code_dir.entry((name, arity))
.or_insert(CodeIndex::from((offset, clause_name!("user"))));
set_code_index!(idx, IndexPtr::Index(offset), clause_name!("user"));
EvalSession::EntrySuccess
}
pub fn code_size(&self) -> usize {
self.code.len()
}
@@ -422,7 +385,7 @@ impl Machine {
while self.ms.p < end_ptr {
if let CodePtr::Local(LocalCodePtr::TopLevel(mut cn, p)) = self.ms.p {
match &self[LocalCodePtr::TopLevel(cn, p)] {
&Line::Control(ref ctrl_instr) if ctrl_instr.is_jump_instr() => {
&Line::Control(ref ctrl_instr) if ctrl_instr.is_jump_instr() => {
self.record_var_places(cn, alloc_locs, heap_locs);
cn += 1;
},
@@ -506,7 +469,7 @@ impl Machine {
{
let mut sorted_vars: Vec<(&Rc<Var>, &Addr)> = var_dir.iter().collect();
sorted_vars.sort_by_key(|ref v| v.0);
for (var, addr) in sorted_vars {
let fmt = TermFormatter {};
output = self.ms.print_var_eq(var.clone(), addr.clone(), var_dir, fmt, output);