finalize the module resolution operator.

This commit is contained in:
Mark Thom
2018-07-08 15:21:09 -06:00
parent 073a8888f3
commit cd03b7795f
12 changed files with 158 additions and 70 deletions

View File

@@ -35,6 +35,22 @@ impl MachineError {
MachineError { stub, from: ErrorProvenance::Received }
}
pub(super)
fn module_resolution_error(h: usize, mod_name: ClauseName, name: ClauseName, arity: usize) -> Self
{
let mod_name = HeapCellValue::Addr(Addr::Con(Constant::Atom(mod_name)));
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name)));
let mut stub = functor!("evaluation_error", 1, [HeapCellValue::Addr(Addr::HeapCell(h + 2))]);
stub.append(&mut functor!("/", 2, [HeapCellValue::Addr(Addr::HeapCell(h + 2 + 3)),
heap_integer!(arity)],
Fixity::In));
stub.append(&mut functor!(":", 2, [mod_name, name], Fixity::In));
MachineError { stub, from: ErrorProvenance::Constructed }
}
pub(super) fn existence_error(h: usize, name: ClauseName, arity: usize) -> Self {
let mut stub = functor!("existence_error", 2, [heap_atom!("procedure"), heap_str!(3 + h)]);
stub.append(&mut Self::functor_stub(name, arity));

View File

@@ -33,7 +33,7 @@ impl Ball {
pub(crate) struct CodeDirs<'a> {
code_dir: &'a CodeDir,
modules: &'a HashMap<ClauseName, Module>
modules: &'a ModuleDir
}
impl<'a> CodeDirs<'a> {
@@ -225,6 +225,21 @@ pub struct MachineState {
pub(super) last_call: bool
}
fn call_at_index(machine_st: &mut MachineState, module_name: ClauseName, arity: usize, idx: usize)
{
machine_st.cp.assign_if_local(machine_st.p.clone() + 1);
machine_st.num_of_args = arity;
machine_st.b0 = machine_st.b;
machine_st.p = dir_entry!(idx, module_name);
}
fn execute_at_index(machine_st: &mut MachineState, module_name: ClauseName, arity: usize, idx: usize)
{
machine_st.num_of_args = arity;
machine_st.b0 = machine_st.b;
machine_st.p = dir_entry!(idx, module_name);
}
pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
pub(crate) trait CallPolicy: Any {
@@ -352,35 +367,46 @@ pub(crate) trait CallPolicy: Any {
}
fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName, arity: usize,
idx: CodeIndex)
idx: CodeIndex, code_dirs: CodeDirs)
-> CallResult
{
if machine_st.last_call {
self.try_execute(machine_st, name, arity, idx)
self.try_execute(machine_st, name, arity, idx, code_dirs)
} else {
self.try_call(machine_st, name, arity, idx)
self.try_call(machine_st, name, arity, idx, code_dirs)
}
}
fn try_call(&mut self, machine_st: &mut MachineState, name: ClauseName,
arity: usize, idx: CodeIndex)
fn try_call(&mut self, machine_st: &mut MachineState, name: ClauseName, arity: usize,
idx: CodeIndex, code_dirs: CodeDirs)
-> CallResult
{
{
match idx.0.borrow().0 {
IndexPtr::Module => {
let stub = MachineError::functor_stub(name.clone(), arity);
let module_name = idx.0.borrow().1.clone();
let h = machine_st.heap.h;
if let Some(ref idx) = code_dirs.get(name.clone(), arity, module_name.clone()) {
if let IndexPtr::Index(compiled_tl_index) = idx.0.borrow().0 {
call_at_index(machine_st, module_name, arity, compiled_tl_index);
return Ok(());
}
}
let err = MachineError::module_resolution_error(h, module_name, name, arity);
return Err(machine_st.error_form(err, stub));
},
IndexPtr::Undefined => {
let stub = MachineError::functor_stub(name.clone(), arity);
let h = machine_st.heap.h;
return Err(machine_st.error_form(MachineError::existence_error(h, name, arity),
stub));
},
IndexPtr::Index(compiled_tl_index) => {
let module_name = idx.0.borrow().1.clone();
machine_st.cp.assign_if_local(machine_st.p.clone() + 1);
machine_st.num_of_args = arity;
machine_st.b0 = machine_st.b;
machine_st.p = dir_entry!(compiled_tl_index, module_name);
call_at_index(machine_st, module_name, arity, compiled_tl_index)
}
}
@@ -388,23 +414,35 @@ pub(crate) trait CallPolicy: Any {
}
fn try_execute<'a>(&mut self, machine_st: &mut MachineState, name: ClauseName,
arity: usize, idx: CodeIndex)
arity: usize, idx: CodeIndex, code_dirs: CodeDirs)
-> CallResult
{
match idx.0.borrow().0 {
IndexPtr::Module => {
let stub = MachineError::functor_stub(name.clone(), arity);
let module_name = idx.0.borrow().1.clone();
let h = machine_st.heap.h;
if let Some(ref idx) = code_dirs.get(name.clone(), arity, module_name.clone()) {
if let IndexPtr::Index(compiled_tl_index) = idx.0.borrow().0 {
execute_at_index(machine_st, module_name, arity, compiled_tl_index);
return Ok(());
}
}
let err = MachineError::module_resolution_error(h, module_name, name, arity);
return Err(machine_st.error_form(err, stub));
},
IndexPtr::Undefined => {
let stub = MachineError::functor_stub(name.clone(), arity);
let h = machine_st.heap.h;
return Err(machine_st.error_form(MachineError::existence_error(h, name, arity),
stub));
},
IndexPtr::Index(compiled_tl_index) => {
let module_name = idx.0.borrow().1.clone();
machine_st.num_of_args = arity;
machine_st.b0 = machine_st.b;
machine_st.p = dir_entry!(compiled_tl_index, module_name);
execute_at_index(machine_st, module_name, arity, compiled_tl_index);
}
}
@@ -552,7 +590,7 @@ pub(crate) trait CallPolicy: Any {
machine_st.execute_inlined(&inlined),
ClauseType::Op(..) | ClauseType::Named(..) =>
if let Some(idx) = code_dirs.get(name.clone(), arity, user) {
self.context_call(machine_st, name, arity, idx)?;
self.context_call(machine_st, name, arity, idx, code_dirs)?;
} else {
let h = machine_st.heap.h;
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
@@ -562,7 +600,7 @@ pub(crate) trait CallPolicy: Any {
ClauseType::System(_) => {
let name = Addr::Con(Constant::Atom(name));
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
return Err(machine_st.error_form(MachineError::type_error(ValidType::Callable,
name),
stub));
@@ -576,10 +614,10 @@ pub(crate) trait CallPolicy: Any {
impl CallPolicy for CallWithInferenceLimitCallPolicy {
fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName,
arity: usize, idx: CodeIndex)
arity: usize, idx: CodeIndex, code_dirs: CodeDirs)
-> CallResult
{
self.prev_policy.context_call(machine_st, name, arity, idx)?;
self.prev_policy.context_call(machine_st, name, arity, idx, code_dirs)?;
self.increment()
}
@@ -747,7 +785,7 @@ impl CutPolicy for SCCCutPolicy {
let b = machine_st.b;
if let Addr::Con(Constant::Usize(b0)) = machine_st[r].clone() {
if b > b0 {
if b > b0 {
machine_st.b = b0;
machine_st.tidy_trail();
machine_st.or_stack.truncate(machine_st.b);
@@ -755,8 +793,8 @@ impl CutPolicy for SCCCutPolicy {
} else {
machine_st.fail = true;
return;
}
}
if let Some(&(_, b_cutoff, prev_block)) = self.cont_pts.last() {
if machine_st.b < b_cutoff {
machine_st.block = prev_block;

View File

@@ -1832,7 +1832,8 @@ impl MachineState {
&ControlInstruction::CallClause(ClauseType::Named(ref name, ref idx), arity, _, lco)
| &ControlInstruction::CallClause(ClauseType::Op(ref name, _, ref idx), arity, _, lco) => {
self.last_call = lco;
try_or_fail!(self, call_policy.context_call(self, name.clone(), arity, idx.clone()));
try_or_fail!(self, call_policy.context_call(self, name.clone(), arity, idx.clone(),
code_dirs));
},
&ControlInstruction::CallClause(ClauseType::System(ref ct), _, _, lco) => {
self.last_call = lco;

View File

@@ -17,13 +17,12 @@ use std::mem::swap;
use std::ops::Index;
use std::rc::Rc;
pub struct MachineCodeIndex<'a> {
pub code_dir: &'a mut CodeDir,
pub op_dir: &'a mut OpDir,
// pub modules: &'a ModuleDir
pub struct MachineCodeIndices<'a> {
pub(super) code_dir: &'a mut CodeDir,
pub(super) op_dir: &'a mut OpDir,
}
impl<'a> MachineCodeIndex<'a> {
impl<'a> MachineCodeIndices<'a> {
pub(super)
fn lookup(&mut self, name: ClauseName, arity: usize, fixity: Option<Fixity>) -> ClauseType
{
@@ -73,7 +72,7 @@ impl Index<LocalCodePtr> for Machine {
}
}
impl<'a> SubModuleUser for MachineCodeIndex<'a> {
impl<'a> SubModuleUser for MachineCodeIndices<'a> {
fn op_dir(&mut self) -> &mut OpDir {
self.op_dir
}
@@ -111,7 +110,7 @@ impl Machine {
cached_query: None
};
let indices = machine_code_index!(&mut CodeDir::new(), &mut default_op_dir());
let indices = machine_code_indices!(&mut CodeDir::new(), &mut default_op_dir());
compile_listing(&mut wam, BUILTINS, indices);
compile_user_module(&mut wam, LISTS);
@@ -178,14 +177,14 @@ impl Machine {
self.ms.atom_tbl.clone()
}
pub fn use_qualified_module_in_toplevel(&mut self, name: ClauseName, exports: Vec<PredicateKey>) -> EvalSession
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_index!(&mut self.code_dir, &mut self.op_dir);
//&self.modules);
let mut indices = machine_code_indices!(&mut self.code_dir, &mut self.op_dir);
indices.use_qualified_module(&mut module, &exports)
};
@@ -202,8 +201,7 @@ impl Machine {
if let Some(mut module) = self.modules.remove(&name) {
let result = {
let mut indices = machine_code_index!(&mut self.code_dir, &mut self.op_dir);
//&self.modules);
let mut indices = machine_code_indices!(&mut self.code_dir, &mut self.op_dir);
indices.use_module(&mut module)
};