GetClause,
GetCurrentPredicateList,
GetModuleClause,
+ ModuleHeadIsDynamic,
GetLiftedHeapFromOffset,
GetLiftedHeapFromOffsetDiff,
GetSCCCleaner,
&SystemClauseType::InstallSCCCleaner => clause_name!("$install_scc_cleaner"),
&SystemClauseType::InstallInferenceCounter => clause_name!("$install_inference_counter"),
&SystemClauseType::LiftedHeapLength => clause_name!("$lh_length"),
+ &SystemClauseType::ModuleHeadIsDynamic => clause_name!("$module_head_is_dynamic"),
&SystemClauseType::ModuleOf => clause_name!("$module_of"),
&SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"),
&SystemClauseType::RedoAttrVarBindings => clause_name!("$redo_attr_var_bindings"),
("$lh_length", 1) => Some(SystemClauseType::LiftedHeapLength),
("$module_of", 2) => Some(SystemClauseType::ModuleOf),
("$module_retract_clause", 5) => Some(SystemClauseType::ModuleRetractClause),
+ ("$module_head_is_dynamic", 2) => Some(SystemClauseType::ModuleHeadIsDynamic),
("$no_such_predicate", 1) => Some(SystemClauseType::NoSuchPredicate),
("$redo_attr_var_bindings", 0) => Some(SystemClauseType::RedoAttrVarBindings),
("$remove_call_policy_check", 1) => Some(SystemClauseType::RemoveCallPolicyCheck),
}
}
-pub type ModuleCodeDir = HashMap<PredicateKey, ModuleCodeIndex>;
pub type ModuleDir = HashMap<ClauseName, Module>;
#[derive(Clone)]
pub struct Module {
pub atom_tbl: TabledData<Atom>,
pub module_decl: ModuleDecl,
- pub code_dir: ModuleCodeDir,
+ pub code_dir: CodeDir,
pub op_dir: OpDir,
pub term_expansions: (Predicate, VecDeque<TopLevel>),
pub goal_expansions: (Predicate, VecDeque<TopLevel>),
pub inserted_expansions: bool // has the module been successfully inserted into toplevel??
}
-
-#[derive(Clone)]
-pub struct ModuleCodeIndex(pub IndexPtr, pub ClauseName);
'$module_clause'(H, B, Module) :-
( var(H) -> throw(error(instantiation_error, clause/2))
; functor(H, Name, Arity) -> ( Name == '.' -> throw(error(type_error(callable, H), clause/2))
- ; '$head_is_dynamic'(H) -> '$clause_body_is_valid'(B),
- '$get_module_clause'(H, B, Module)
+ ; '$module_head_is_dynamic'(H, Module) ->
+ '$clause_body_is_valid'(B),
+ '$get_module_clause'(H, B, Module)
; throw(error(permission_error(access, private_procedure, Name/Arity),
clause/2))
)
module_asserta_clause(Head, Body, Module) :-
( var(Head) -> throw(error(instantiation_error, asserta/1))
; functor(Head, Name, Arity), atom(Name), Name \== '.' ->
- ( '$head_is_dynamic'(Head) -> call_module_asserta(Head, Body, Name, Arity, Module)
+ ( '$module_head_is_dynamic'(Head, Module) -> call_module_asserta(Head, Body, Name, Arity, Module)
; throw(error(permission_error(modify, static_procedure, Name/Arity), asserta/1))
)
; throw(error(type_error(callable, Head), asserta/1))
module_assertz_clause(Head, Body, Module) :-
( var(Head) -> throw(error(instantiation_error, assertz/1))
; functor(Head, Name, Arity), atom(Name), Name \== '.' ->
- ( '$head_is_dynamic'(Head) -> call_module_assertz(Head, Body, Name, Arity, Module)
+ ( '$module_head_is_dynamic'(Head, Module) -> call_module_assertz(Head, Body, Name, Arity, Module)
; throw(error(permission_error(modify, static_procedure, Name/Arity), assertz/1))
)
; throw(error(type_error(callable, Head), assertz/1))
retract_module_clause(Head, Body, Module) :-
( var(Head) -> throw(error(instantiation_error, retract/1))
; functor(Head, Name, Arity), atom(Name), Name \== '.' ->
- ( '$head_is_dynamic'(Head) -> call_module_retract(Head, Body, Name, Arity, Module)
+ ( '$module_head_is_dynamic'(Head, Module) ->
+ call_module_retract(Head, Body, Name, Arity, Module)
; throw(error(permission_error(modify, static_procedure, Name/Arity), retract/1))
)
; throw(error(type_error(callable, Head), retract/1))
; Arity < 0 -> throw(domain_error(not_less_than_zero, Arity), abolish/1)
; max_arity(N), Arity > N -> throw(representation_error(max_arity), abolish/1)
; functor(Head, Name, Arity) ->
- ( '$head_is_dynamic'(Head) -> '$abolish_module_clause'(Name, Arity, Module)
+ ( '$module_head_is_dynamic'(Head, Module) ->
+ '$abolish_module_clause'(Name, Arity, Module)
; throw(error(permission_error(modify, static_procedure, Pred), abolish/1))
)
)
let mut compiler = ListingCompiler::new(&wam.code_repo);
let indices = try_eval_session!(compile_decl(wam, &mut compiler, decl));
- try_eval_session!(wam.check_toplevel_code(&indices, &DynamicClauseMap::new()));
+ try_eval_session!(wam.check_toplevel_code(&indices));
add_toplevel_code(wam, vec![], indices);
EvalSession::EntrySuccess
&mut indices.code_dir, 0));
let mut clause_code_generator = ClauseCodeGenerator::new(module_code.len());
- try_eval_session!(clause_code_generator.generate_clause_code(module_name.clone(),
- results.dynamic_clause_map,
+ try_eval_session!(clause_code_generator.generate_clause_code(results.dynamic_clause_map,
wam));
match wam.indices.modules.get_mut(&module_name) {
Some(module) => {
let code_dir = mem::replace(&mut indices.code_dir, CodeDir::new());
- module.code_dir.extend(as_module_code_dir(code_dir));
+ module.code_dir.extend(code_dir);
if module.module_decl.exports.contains(&(name.clone(), arity)) {
if let Some(idx) = wam.indices.code_dir.get(&(name.clone(), arity)) {
};
wam.code_repo.code.extend(module_code.into_iter());
- clause_code_generator.add_clause_code(module_name, wam);
+ clause_code_generator.add_clause_code(wam);
EvalSession::EntrySuccess
}
ClauseCodeGenerator { len_offset, code: vec![], pi_to_loc: HashMap::new() }
}
- fn generate_clause_code(&mut self, module: ClauseName, dynamic_clause_map: DynamicClauseMap,
- wam: &Machine)
+ fn generate_clause_code(&mut self, dynamic_clause_map: DynamicClauseMap, wam: &Machine)
-> Result<(), SessionError>
{
for ((name, arity), heads_and_tails) in dynamic_clause_map {
continue;
}
- wam.check_dynamic_clause_overwrite(name.clone(), arity, module.clone())?;
-
let predicate = Predicate(heads_and_tails.into_iter().map(|(head, tail)| {
let clause = Term::Clause(Cell::default(), clause_name!("clause"),
vec![Box::new(head), Box::new(tail)],
Ok(())
}
- fn add_clause_code(self, module: ClauseName, wam: &mut Machine) {
+ fn add_clause_code(self, wam: &mut Machine) {
wam.code_repo.code.extend(self.code.into_iter());
for ((name, arity), p) in self.pi_to_loc {
- let entry = wam.indices.dynamic_code_dir.entry((name, arity))
+ let entry = wam.indices.dynamic_code_dir.entry((name.owning_module(), name, arity))
.or_insert(DynamicPredicateInfo::default());
entry.clauses_subsection_p = p;
- entry.module_src = module.clone();
}
}
}
let code_dir = mem::replace(&mut indices.code_dir, CodeDir::new());
let op_dir = mem::replace(&mut indices.op_dir, OpDir::new());
- module.code_dir.extend(as_module_code_dir(code_dir));
+ module.code_dir.extend(code_dir);
module.op_dir.extend(op_dir.into_iter());
wam.add_module(module, code);
indices: IndexStore)
-> Result<(), SessionError>
{
- wam.check_toplevel_code(&indices, &dynamic_clause_map)?;
+ wam.check_toplevel_code(&indices)?;
let mut clause_code_generator = ClauseCodeGenerator::new(code.len());
- clause_code_generator.generate_clause_code(clause_name!("user"), dynamic_clause_map, wam)?;
+ clause_code_generator.generate_clause_code(dynamic_clause_map, wam)?;
add_toplevel_code(wam, code, indices);
- clause_code_generator.add_clause_code(clause_name!("user"), wam);
+ clause_code_generator.add_clause_code(wam);
Ok(())
}
if let Some(module) = compiler.module.take() {
let mut clause_code_generator = ClauseCodeGenerator::new(module_code.len() + toplvl_code.len());
- let module_name = module.module_decl.name.clone();
- try_eval_session!(wam.check_toplevel_code(&results.toplevel_indices, &results.dynamic_clause_map));
- try_eval_session!(clause_code_generator.generate_clause_code(module_name.clone(),
- results.dynamic_clause_map,
+ try_eval_session!(wam.check_toplevel_code(&results.toplevel_indices));
+ try_eval_session!(clause_code_generator.generate_clause_code(results.dynamic_clause_map,
wam));
add_module_code(wam, module, module_code, indices);
add_toplevel_code(wam, toplvl_code, results.toplevel_indices);
- clause_code_generator.add_clause_code(module_name, wam);
+ clause_code_generator.add_clause_code(wam);
} else {
try_eval_session!(add_non_module_code(wam, results.dynamic_clause_map, module_code,
indices));
}
self.indices.remove_code_index((name.clone(), arity));
- self.indices.dynamic_code_dir.remove(&(name, arity));
+ self.indices.remove_clause_subsection(name.owning_module(), name, arity);
}
fn abolish_dynamic_clause_in_module(&mut self, name: RegType, arity: RegType, module: RegType)
}
self.indices.remove_code_index((name.clone(), arity));
- self.indices.dynamic_code_dir.remove(&(name, arity));
+ self.indices.remove_clause_subsection(module_name, name, arity);
}
fn handle_eval_result_from_dynamic_compile(&mut self, pred_str: String, name: ClauseName,
pub(super) fn session_error(h: usize, err: SessionError) -> Self {
match err {
SessionError::ParserError(err) => Self::syntax_error(h, err),
- SessionError::CannotOverwriteDynamicClause(pred_str)
- | SessionError::CannotOverwriteBuiltIn(pred_str)
+ SessionError::CannotOverwriteBuiltIn(pred_str)
| SessionError::CannotOverwriteImport(pred_str) =>
Self::permission_error(PermissionError::Modify, pred_str),
SessionError::ModuleDoesNotContainExport =>
pub enum SessionError {
CannotOverwriteBuiltIn(ClauseName),
- CannotOverwriteDynamicClause(ClauseName),
CannotOverwriteImport(ClauseName),
ModuleDoesNotContainExport,
ModuleNotFound,
pub fn module_name(&self) -> ClauseName {
self.0.borrow().1.clone()
}
+
+ pub fn local(&self) -> Option<usize> {
+ match self.0.borrow().0 {
+ IndexPtr::Index(i) => Some(i),
+ _ => None
+ }
+ }
}
impl Default for CodeIndex {
#[derive(Clone)]
pub struct DynamicPredicateInfo {
pub(super) clauses_subsection_p: usize, // a LocalCodePtr::DirEntry value.
- pub(super) module_src: ClauseName // the module the predicate is defined within.
}
impl Default for DynamicPredicateInfo {
fn default() -> Self {
- DynamicPredicateInfo { clauses_subsection_p: 0,
- module_src: clause_name!("user") }
+ DynamicPredicateInfo { clauses_subsection_p: 0 }
}
}
pub type InSituCodeDir = HashMap<PredicateKey, usize>;
-pub type DynamicCodeDir = HashMap<PredicateKey, DynamicPredicateInfo>;
+// key type: module name, predicate indicator.
+pub type DynamicCodeDir = HashMap<(ClauseName, ClauseName, usize), DynamicPredicateInfo>;
pub struct IndexStore {
pub(super) atom_tbl: TabledData<Atom>,
}
#[inline]
- pub fn get_clause_subsection(&self, name: ClauseName, arity: usize) -> Option<DynamicPredicateInfo> {
- self.dynamic_code_dir.get(&(name, arity)).cloned()
+ pub fn remove_clause_subsection(&mut self, module: ClauseName, name: ClauseName, arity: usize)
+ {
+ self.dynamic_code_dir.remove(&(module, name, arity));
+ }
+
+ #[inline]
+ pub fn get_clause_subsection(&self, module: ClauseName, name: ClauseName, arity: usize)
+ -> Option<DynamicPredicateInfo>
+ {
+ self.dynamic_code_dir.get(&(module, name, arity)).cloned()
}
-
+
#[inline]
pub fn take_module(&mut self, name: ClauseName) -> Option<Module> {
self.modules.remove(&name)
}
#[inline]
- fn get_internal(&self, name: ClauseName, arity: usize, in_mod: ClauseName)
- -> Option<ModuleCodeIndex>
+ fn get_internal(&self, name: ClauseName, arity: usize, in_mod: ClauseName) -> Option<CodeIndex>
{
self.modules.get(&in_mod)
.and_then(|ref module| module.code_dir.get(&(name, arity)))
use prolog::machine::machine_indices::*;
use prolog::machine::machine_state::*;
use prolog::machine::modules::*;
-use prolog::machine::toplevel::*;
use std::collections::{HashMap, VecDeque};
use std::mem;
fn remove_code_index(&mut self, key: PredicateKey)
{
- self.code_dir.remove(&key);
+ self.code_dir.remove(&key);
+ self.dynamic_code_dir.remove(&(key.0.owning_module(), key.0, key.1));
}
- fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: ModuleCodeIndex)
+ fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: CodeIndex)
{
- if let Some(ref mut code_idx) = self.code_dir.get_mut(&(name.clone(), arity)) {
+ if let Some(ref code_idx) = self.code_dir.get(&(name.clone(), arity)) {
if !code_idx.is_undefined() {
println!("warning: overwriting {}/{}", &name, arity);
}
- set_code_index!(code_idx, idx.0, idx.1);
+ let (p, module_name) = idx.0.borrow().clone();
+ set_code_index!(code_idx, p, module_name);
return;
}
- self.code_dir.insert((name, arity), CodeIndex::from(idx));
+ self.code_dir.insert((name, arity), idx);
}
fn use_qualified_module(&mut self, code_repo: &mut CodeRepo, flags: MachineFlags,
self.machine_st.flags
}
- pub fn check_dynamic_clause_overwrite(&self, name: ClauseName, arity: usize, module: ClauseName)
- -> Result<(), SessionError>
- {
- if let Some(info) = self.indices.dynamic_code_dir.get(&(name.clone(), arity)) {
- if info.module_src != module {
- let err_str = format!("{}/{}", name.as_str(), arity);
- let err_str = clause_name!(err_str, self.indices.atom_tbl());
-
- return Err(SessionError::CannotOverwriteDynamicClause(err_str));
- }
- }
-
- Ok(())
- }
-
- pub fn check_toplevel_code(&self, indices: &IndexStore, dynamic_clause_map: &DynamicClauseMap)
- -> Result<(), SessionError>
+ pub fn check_toplevel_code(&self, indices: &IndexStore) -> Result<(), SessionError>
{
for (key, idx) in &indices.code_dir {
match ClauseType::from(key.0.clone(), key.1, None) {
return Err(SessionError::CannotOverwriteBuiltIn(err_str));
}
};
-
- if dynamic_clause_map.contains_key(&key) {
- let module = idx.0.borrow().1.clone();
- self.check_dynamic_clause_overwrite(key.0.clone(), key.1, module)?;
- }
if let Some(ref existing_idx) = self.indices.code_dir.get(&key) {
// ensure we don't try to overwrite an existing predicate from a different module.
use prolog::machine::machine_errors::*;
use prolog::machine::machine_indices::*;
-use std::cell::RefCell;
use std::collections::{VecDeque};
-use std::rc::Rc;
-
-impl ModuleCodeIndex {
- pub fn local(&self) -> Option<usize> {
- match self.0 {
- IndexPtr::Index(i) => Some(i),
- _ => None
- }
- }
-}
-
-impl From<ModuleCodeIndex> for CodeIndex {
- fn from(value: ModuleCodeIndex) -> Self {
- CodeIndex(Rc::new(RefCell::new((value.0, value.1))))
- }
-}
// Module's and related types are defined in forms.
impl Module {
Module { module_decl, atom_tbl,
term_expansions: (Predicate::new(), VecDeque::from(vec![])),
goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
- code_dir: ModuleCodeDir::new(),
+ code_dir: CodeDir::new(),
op_dir: default_op_dir(),
inserted_expansions: false }
}
fn remove_code_index(&mut self, PredicateKey);
fn get_code_index(&self, PredicateKey, ClauseName) -> Option<CodeIndex>;
- fn insert_dir_entry(&mut self, ClauseName, usize, ModuleCodeIndex);
+ fn insert_dir_entry(&mut self, ClauseName, usize, CodeIndex);
fn remove_module(&mut self, mod_name: ClauseName, module: &Module)
{
atom_tbl.borrow_mut().insert(name.to_rc());
- let mut code_data = code_data.clone();
- code_data.1 = submodule.module_decl.name.clone();
-
self.insert_dir_entry(name, arity, code_data.clone());
true
} else {
self.code_dir.remove(&key);
}
- fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: ModuleCodeIndex) {
+ fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: CodeIndex) {
self.code_dir.insert((name, arity), idx);
}
Ok(())
}
}
-
-pub fn as_module_code_dir(code_dir: CodeDir) -> ModuleCodeDir {
- code_dir.into_iter()
- .map(|(k, code_idx)| {
- let (idx, module_name) = code_idx.0.borrow().clone();
- (k, ModuleCodeIndex(idx, module_name))
- })
- .collect()
-}
Addr::Str(s) =>
match self.heap[s].clone() {
HeapCellValue::NamedStr(arity, name, ..) =>
- indices.get_clause_subsection(name, arity),
+ indices.get_clause_subsection(module, name, arity),
_ => unreachable!()
},
Addr::Con(Constant::Atom(name, _)) =>
- indices.get_clause_subsection(name, 0),
+ indices.get_clause_subsection(module, name, 0),
_ => unreachable!()
};
match subsection {
Some(dynamic_predicate_info) => {
- if dynamic_predicate_info.module_src != module {
- self.fail = true;
- } else {
- self.execute_at_index(2, dynamic_predicate_info.clauses_subsection_p);
- }
-
+ self.execute_at_index(2, dynamic_predicate_info.clauses_subsection_p);
return Ok(());
},
None => self.fail = true
}
},
+ &SystemClauseType::ModuleHeadIsDynamic => {
+ let module = self[temp_v!(2)].clone();
+ let head = self[temp_v!(1)].clone();
+
+ let module = match self.store(self.deref(module)) {
+ Addr::Con(Constant::Atom(module, _)) =>
+ module,
+ _ => {
+ self.fail = true;
+ return Ok(());
+ }
+ };
+
+ self.fail = !match self.store(self.deref(head)) {
+ Addr::Str(s) =>
+ match self.heap[s].clone() {
+ HeapCellValue::NamedStr(arity, name, ..) =>
+ indices.get_clause_subsection(module, name, arity).is_some(),
+ _ => unreachable!()
+ },
+ Addr::Con(Constant::Atom(name, _)) =>
+ indices.get_clause_subsection(module, name, 0).is_some(),
+ _ => unreachable!()
+ };
+ },
&SystemClauseType::HeadIsDynamic => {
let head = self[temp_v!(1)].clone();
Addr::Str(s) =>
match self.heap[s].clone() {
HeapCellValue::NamedStr(arity, name, ..) =>
- indices.get_clause_subsection(name, arity).is_some(),
+ indices.get_clause_subsection(name.owning_module(), name, arity).is_some(),
_ => unreachable!()
},
Addr::Con(Constant::Atom(name, _)) =>
- indices.get_clause_subsection(name, 0).is_some(),
+ indices.get_clause_subsection(name.owning_module(), name, 0).is_some(),
_ => unreachable!()
};
},
Addr::Str(s) =>
match self.heap[s].clone() {
HeapCellValue::NamedStr(arity, name, ..) =>
- indices.get_clause_subsection(name, arity),
+ indices.get_clause_subsection(name.owning_module(), name, arity),
_ => unreachable!()
},
Addr::Con(Constant::Atom(name, _)) =>
- indices.get_clause_subsection(name, 0),
+ indices.get_clause_subsection(name.owning_module(), name, 0),
_ => unreachable!()
};
}
}
-impl fmt::Display for ModuleCodeIndex {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{}", self.0)
- }
-}
-
impl fmt::Display for FactInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
impl fmt::Display for SessionError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
- &SessionError::CannotOverwriteDynamicClause(ref msg) =>
- write!(f, "cannot overwrite dynamic predicate {}", msg),
&SessionError::CannotOverwriteBuiltIn(ref msg) =>
write!(f, "cannot overwrite {}", msg),
&SessionError::CannotOverwriteImport(ref msg) =>