add dynamic module resolution calls
This commit is contained in:
@@ -238,6 +238,7 @@ pub struct Module {
|
|||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub enum SystemClauseType {
|
pub enum SystemClauseType {
|
||||||
CheckCutPoint,
|
CheckCutPoint,
|
||||||
|
DynamicModuleResolution,
|
||||||
ExpandGoal,
|
ExpandGoal,
|
||||||
ExpandTerm,
|
ExpandTerm,
|
||||||
GetBValue,
|
GetBValue,
|
||||||
@@ -276,6 +277,7 @@ impl SystemClauseType {
|
|||||||
pub fn name(&self) -> ClauseName {
|
pub fn name(&self) -> ClauseName {
|
||||||
match self {
|
match self {
|
||||||
&SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
|
&SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
|
||||||
|
&SystemClauseType::DynamicModuleResolution => clause_name!("$module_call"),
|
||||||
&SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
|
&SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
|
||||||
&SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
|
&SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
|
||||||
&SystemClauseType::GetBValue => clause_name!("$get_b_value"),
|
&SystemClauseType::GetBValue => clause_name!("$get_b_value"),
|
||||||
@@ -313,6 +315,7 @@ impl SystemClauseType {
|
|||||||
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
|
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
|
||||||
match (name, arity) {
|
match (name, arity) {
|
||||||
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
|
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
|
||||||
|
("$module_call", 2) => Some(SystemClauseType::DynamicModuleResolution),
|
||||||
("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
|
("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
|
||||||
("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
|
("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
|
||||||
("$get_b_value", 1) => Some(SystemClauseType::GetBValue),
|
("$get_b_value", 1) => Some(SystemClauseType::GetBValue),
|
||||||
@@ -857,8 +860,6 @@ impl HeapCellValue {
|
|||||||
pub enum IndexPtr {
|
pub enum IndexPtr {
|
||||||
Undefined,
|
Undefined,
|
||||||
Index(usize),
|
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)]
|
#[derive(Clone)]
|
||||||
|
|||||||
@@ -60,6 +60,13 @@ true.
|
|||||||
|
|
||||||
false :- '$fail'.
|
false :- '$fail'.
|
||||||
|
|
||||||
|
% dynamic module resolution.
|
||||||
|
|
||||||
|
Module : Predicate :-
|
||||||
|
( atom(Module) -> '$module_call'(Module, Predicate)
|
||||||
|
; throw(error(type_error(atom, Module), (:)))
|
||||||
|
).
|
||||||
|
|
||||||
% flags.
|
% flags.
|
||||||
|
|
||||||
current_prolog_flag(Flag, false) :- Flag == bounded, !.
|
current_prolog_flag(Flag, false) :- Flag == bounded, !.
|
||||||
|
|||||||
@@ -224,19 +224,48 @@ pub struct MachineState {
|
|||||||
pub(crate) flags: MachineFlags
|
pub(crate) flags: MachineFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_at_index(machine_st: &mut MachineState, arity: usize, p: usize)
|
impl MachineState {
|
||||||
{
|
fn call_at_index(&mut self, arity: usize, p: usize)
|
||||||
machine_st.cp.assign_if_local(machine_st.p.clone() + 1);
|
{
|
||||||
machine_st.num_of_args = arity;
|
self.cp.assign_if_local(self.p.clone() + 1);
|
||||||
machine_st.b0 = machine_st.b;
|
self.num_of_args = arity;
|
||||||
machine_st.p = dir_entry!(p);
|
self.b0 = self.b;
|
||||||
}
|
self.p = dir_entry!(p);
|
||||||
|
}
|
||||||
|
|
||||||
fn execute_at_index(machine_st: &mut MachineState, arity: usize, p: usize)
|
fn execute_at_index(&mut self, arity: usize, p: usize)
|
||||||
{
|
{
|
||||||
machine_st.num_of_args = arity;
|
self.num_of_args = arity;
|
||||||
machine_st.b0 = machine_st.b;
|
self.b0 = self.b;
|
||||||
machine_st.p = dir_entry!(p);
|
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)
|
fn try_in_situ_lookup(name: ClauseName, arity: usize, indices: &IndexStore)
|
||||||
@@ -261,9 +290,9 @@ fn try_in_situ(machine_st: &mut MachineState, name: ClauseName, arity: usize,
|
|||||||
{
|
{
|
||||||
if let Some(p) = try_in_situ_lookup(name.clone(), arity, indices) {
|
if let Some(p) = try_in_situ_lookup(name.clone(), arity, indices) {
|
||||||
if last_call {
|
if last_call {
|
||||||
execute_at_index(machine_st, arity, p);
|
machine_st.execute_at_index(arity, p);
|
||||||
} else {
|
} else {
|
||||||
call_at_index(machine_st, arity, p);
|
machine_st.call_at_index(arity, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_st.p = in_situ_dir_entry!(p);
|
machine_st.p = in_situ_dir_entry!(p);
|
||||||
@@ -451,26 +480,10 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
-> CallResult
|
-> CallResult
|
||||||
{
|
{
|
||||||
match idx.0.borrow().0 {
|
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 =>
|
IndexPtr::Undefined =>
|
||||||
return try_in_situ(machine_st, name, arity, indices, false),
|
return try_in_situ(machine_st, name, arity, indices, false),
|
||||||
IndexPtr::Index(compiled_tl_index) =>
|
IndexPtr::Index(compiled_tl_index) =>
|
||||||
call_at_index(machine_st, arity, compiled_tl_index)
|
machine_st.call_at_index(arity, compiled_tl_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -481,26 +494,10 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
-> CallResult
|
-> CallResult
|
||||||
{
|
{
|
||||||
match idx.0.borrow().0 {
|
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 =>
|
IndexPtr::Undefined =>
|
||||||
return try_in_situ(machine_st, name, arity, indices, true),
|
return try_in_situ(machine_st, name, arity, indices, true),
|
||||||
IndexPtr::Index(compiled_tl_index) =>
|
IndexPtr::Index(compiled_tl_index) =>
|
||||||
execute_at_index(machine_st, arity, compiled_tl_index)
|
machine_st.execute_at_index(arity, compiled_tl_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -923,9 +920,9 @@ impl SCCCutPolicy {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if machine_st.last_call {
|
if machine_st.last_call {
|
||||||
execute_at_index(machine_st, arity, idx);
|
machine_st.execute_at_index(arity, idx);
|
||||||
} else {
|
} else {
|
||||||
call_at_index(machine_st, arity, idx);
|
machine_st.call_at_index(arity, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ impl IndexStore {
|
|||||||
mem::swap(&mut self.modules, &mut other.modules);
|
mem::swap(&mut self.modules, &mut other.modules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn get_internal(&self, name: ClauseName, arity: usize, in_mod: ClauseName)
|
fn get_internal(&self, name: ClauseName, arity: usize, in_mod: ClauseName)
|
||||||
-> Option<ModuleCodeIndex>
|
-> Option<ModuleCodeIndex>
|
||||||
{
|
{
|
||||||
@@ -86,7 +87,7 @@ impl IndexStore {
|
|||||||
.and_then(|ref module| module.code_dir.get(&(name, arity)))
|
.and_then(|ref module| module.code_dir.get(&(name, arity)))
|
||||||
.cloned()
|
.cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn get_cleaner_sites(&self) -> (usize, usize) {
|
pub(super) fn get_cleaner_sites(&self) -> (usize, usize) {
|
||||||
let r_w_h = clause_name!("run_cleaners_with_handling");
|
let r_w_h = clause_name!("run_cleaners_with_handling");
|
||||||
let r_wo_h = clause_name!("run_cleaners_without_handling");
|
let r_wo_h = clause_name!("run_cleaners_without_handling");
|
||||||
|
|||||||
@@ -203,6 +203,32 @@ impl MachineState {
|
|||||||
_ => self.fail = 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 => {
|
&SystemClauseType::ExpandGoal => {
|
||||||
self.p = CodePtr::Local(LocalCodePtr::UserGoalExpansion(0));
|
self.p = CodePtr::Local(LocalCodePtr::UserGoalExpansion(0));
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use prolog::num::*;
|
|||||||
|
|
||||||
use std::borrow::BorrowMut;
|
use std::borrow::BorrowMut;
|
||||||
use std::collections::{HashSet, VecDeque};
|
use std::collections::{HashSet, VecDeque};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::Cell;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@@ -355,18 +355,6 @@ fn mark_cut_variables(terms: &mut Vec<Term>) -> bool {
|
|||||||
found_cut_var
|
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 {
|
fn flatten_hook(mut term: Term) -> Term {
|
||||||
if let &mut Term::Clause(_, ref mut name, ref mut terms, _) = &mut term {
|
if let &mut Term::Clause(_, ref mut name, ref mut terms, _) = &mut term {
|
||||||
match (name.as_str(), terms.len()) {
|
match (name.as_str(), terms.len()) {
|
||||||
@@ -517,12 +505,6 @@ impl RelationWorker {
|
|||||||
self.queue.push_back(clauses);
|
self.queue.push_back(clauses);
|
||||||
Ok(QueryTerm::Jump(stub))
|
Ok(QueryTerm::Jump(stub))
|
||||||
},
|
},
|
||||||
(":", 2) => {
|
|
||||||
let callee = *terms.pop().unwrap();
|
|
||||||
let mod_name = *terms.pop().unwrap();
|
|
||||||
|
|
||||||
module_resolution_call(mod_name, callee)
|
|
||||||
},
|
|
||||||
("->", 2) => {
|
("->", 2) => {
|
||||||
let conq = *terms.pop().unwrap();
|
let conq = *terms.pop().unwrap();
|
||||||
let prec = *terms.pop().unwrap();
|
let prec = *terms.pop().unwrap();
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ fn error_string(e: &String) -> String {
|
|||||||
impl fmt::Display for IndexPtr {
|
impl fmt::Display for IndexPtr {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
&IndexPtr::Module =>
|
|
||||||
write!(f, ""),
|
|
||||||
&IndexPtr::Undefined =>
|
&IndexPtr::Undefined =>
|
||||||
write!(f, "undefined"),
|
write!(f, "undefined"),
|
||||||
&IndexPtr::Index(i) =>
|
&IndexPtr::Index(i) =>
|
||||||
|
|||||||
Reference in New Issue
Block a user