#[derive(Copy, Clone, PartialEq)]
pub enum SystemClauseType {
CheckCutPoint,
+ DynamicModuleResolution,
ExpandGoal,
ExpandTerm,
GetBValue,
pub fn name(&self) -> ClauseName {
match self {
&SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
+ &SystemClauseType::DynamicModuleResolution => clause_name!("$module_call"),
&SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
&SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
&SystemClauseType::GetBValue => clause_name!("$get_b_value"),
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
match (name, arity) {
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
+ ("$module_call", 2) => Some(SystemClauseType::DynamicModuleResolution),
("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
("$get_b_value", 1) => Some(SystemClauseType::GetBValue),
pub enum IndexPtr {
Undefined,
Index(usize),
- Module /* This is a resolved module call. The module
- targeted is in the wrapping CodeIndex, and the name is in the ClauseType. */
}
#[derive(Clone)]
pub(crate) flags: MachineFlags
}
-fn call_at_index(machine_st: &mut MachineState, arity: usize, p: 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!(p);
-}
+impl MachineState {
+ fn call_at_index(&mut self, arity: usize, p: usize)
+ {
+ self.cp.assign_if_local(self.p.clone() + 1);
+ self.num_of_args = arity;
+ self.b0 = self.b;
+ self.p = dir_entry!(p);
+ }
-fn execute_at_index(machine_st: &mut MachineState, arity: usize, p: usize)
-{
- machine_st.num_of_args = arity;
- machine_st.b0 = machine_st.b;
- machine_st.p = dir_entry!(p);
+ fn execute_at_index(&mut self, arity: usize, p: usize)
+ {
+ self.num_of_args = arity;
+ self.b0 = self.b;
+ self.p = dir_entry!(p);
+ }
+
+ pub(super)
+ fn module_lookup(&mut self, indices: &IndexStore, key: PredicateKey, module_name: ClauseName,
+ last_call: bool)
+ -> CallResult
+ {
+ let (name, arity) = key;
+
+ if let Some(ref idx) = indices.get_code_index((name.clone(), arity), module_name.clone())
+ {
+ if let IndexPtr::Index(compiled_tl_index) = idx.0.borrow().0 {
+ if last_call {
+ self.execute_at_index(arity, compiled_tl_index);
+ } else {
+ self.call_at_index(arity, compiled_tl_index);
+ }
+
+ return Ok(());
+ }
+ }
+
+ let h = self.heap.h;
+ let stub = MachineError::functor_stub(name.clone(), arity);
+ let err = MachineError::module_resolution_error(h, module_name, name, arity);
+
+ return Err(self.error_form(err, stub));
+ }
}
fn try_in_situ_lookup(name: ClauseName, arity: usize, indices: &IndexStore)
{
if let Some(p) = try_in_situ_lookup(name.clone(), arity, indices) {
if last_call {
- execute_at_index(machine_st, arity, p);
+ machine_st.execute_at_index(arity, p);
} else {
- call_at_index(machine_st, arity, p);
+ machine_st.call_at_index(arity, p);
}
machine_st.p = in_situ_dir_entry!(p);
-> 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) = indices.get_code_index((name.clone(), arity), module_name.clone())
- {
- if let IndexPtr::Index(compiled_tl_index) = idx.0.borrow().0 {
- call_at_index(machine_st, 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 =>
return try_in_situ(machine_st, name, arity, indices, false),
IndexPtr::Index(compiled_tl_index) =>
- call_at_index(machine_st, arity, compiled_tl_index)
+ machine_st.call_at_index(arity, compiled_tl_index)
}
Ok(())
-> 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) = indices.get_code_index((name.clone(), arity), module_name.clone())
- {
- if let IndexPtr::Index(compiled_tl_index) = idx.0.borrow().0 {
- execute_at_index(machine_st, 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 =>
return try_in_situ(machine_st, name, arity, indices, true),
IndexPtr::Index(compiled_tl_index) =>
- execute_at_index(machine_st, arity, compiled_tl_index)
+ machine_st.execute_at_index(arity, compiled_tl_index)
}
Ok(())
};
if machine_st.last_call {
- execute_at_index(machine_st, arity, idx);
+ machine_st.execute_at_index(arity, idx);
} else {
- call_at_index(machine_st, arity, idx);
+ machine_st.call_at_index(arity, idx);
}
return true;
_ => self.fail = true
};
},
+ &SystemClauseType::DynamicModuleResolution => {
+ let module_name = self.store(self.deref(self[temp_v!(1)].clone()));
+
+ if let Addr::Con(Constant::Atom(module_name, _)) = module_name {
+ match self.store(self.deref(self[temp_v!(2)].clone())) {
+ Addr::Str(a) =>
+ if let HeapCellValue::NamedStr(arity, name, _) = self.heap[a].clone() {
+ for i in 1 .. arity + 1 {
+ self.registers[i] = self.heap[a+i].as_addr(a+i);
+ }
+
+ return self.module_lookup(indices, (name, arity), module_name, true);
+ },
+ Addr::Con(Constant::Atom(name, _)) =>
+ return self.module_lookup(indices, (name, 0), module_name, true),
+ addr => {
+ let stub = MachineError::functor_stub(clause_name!("(:)"), 2);
+
+ let type_error = MachineError::type_error(ValidType::Callable, addr);
+ let type_error = self.error_form(type_error, stub);
+
+ return Err(type_error);
+ }
+ }
+ };
+ },
&SystemClauseType::ExpandGoal => {
self.p = CodePtr::Local(LocalCodePtr::UserGoalExpansion(0));
return Ok(());
use std::borrow::BorrowMut;
use std::collections::{HashSet, VecDeque};
-use std::cell::{Cell, RefCell};
+use std::cell::Cell;
use std::io::Read;
use std::mem;
use std::rc::Rc;
found_cut_var
}
-fn module_resolution_call(mod_name: Term, body: Term) -> Result<QueryTerm, ParserError> {
- if let Term::Constant(_, Constant::Atom(mod_name, _)) = mod_name {
- if let Term::Clause(_, name, terms, _) = body {
- let idx = CodeIndex(Rc::new(RefCell::new((IndexPtr::Module, mod_name))));
- return Ok(QueryTerm::Clause(Cell::default(), ClauseType::Named(name, idx), terms,
- false));
- }
- }
-
- Err(ParserError::InvalidModuleResolution)
-}
-
fn flatten_hook(mut term: Term) -> Term {
if let &mut Term::Clause(_, ref mut name, ref mut terms, _) = &mut term {
match (name.as_str(), terms.len()) {
self.queue.push_back(clauses);
Ok(QueryTerm::Jump(stub))
},
- (":", 2) => {
- let callee = *terms.pop().unwrap();
- let mod_name = *terms.pop().unwrap();
-
- module_resolution_call(mod_name, callee)
- },
("->", 2) => {
let conq = *terms.pop().unwrap();
let prec = *terms.pop().unwrap();