split dynamic database keys across modules
This commit is contained in:
@@ -159,6 +159,7 @@ pub enum SystemClauseType {
|
|||||||
GetClause,
|
GetClause,
|
||||||
GetCurrentPredicateList,
|
GetCurrentPredicateList,
|
||||||
GetModuleClause,
|
GetModuleClause,
|
||||||
|
ModuleHeadIsDynamic,
|
||||||
GetLiftedHeapFromOffset,
|
GetLiftedHeapFromOffset,
|
||||||
GetLiftedHeapFromOffsetDiff,
|
GetLiftedHeapFromOffsetDiff,
|
||||||
GetSCCCleaner,
|
GetSCCCleaner,
|
||||||
@@ -233,6 +234,7 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::InstallSCCCleaner => clause_name!("$install_scc_cleaner"),
|
&SystemClauseType::InstallSCCCleaner => clause_name!("$install_scc_cleaner"),
|
||||||
&SystemClauseType::InstallInferenceCounter => clause_name!("$install_inference_counter"),
|
&SystemClauseType::InstallInferenceCounter => clause_name!("$install_inference_counter"),
|
||||||
&SystemClauseType::LiftedHeapLength => clause_name!("$lh_length"),
|
&SystemClauseType::LiftedHeapLength => clause_name!("$lh_length"),
|
||||||
|
&SystemClauseType::ModuleHeadIsDynamic => clause_name!("$module_head_is_dynamic"),
|
||||||
&SystemClauseType::ModuleOf => clause_name!("$module_of"),
|
&SystemClauseType::ModuleOf => clause_name!("$module_of"),
|
||||||
&SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"),
|
&SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"),
|
||||||
&SystemClauseType::RedoAttrVarBindings => clause_name!("$redo_attr_var_bindings"),
|
&SystemClauseType::RedoAttrVarBindings => clause_name!("$redo_attr_var_bindings"),
|
||||||
@@ -299,6 +301,7 @@ impl SystemClauseType {
|
|||||||
("$lh_length", 1) => Some(SystemClauseType::LiftedHeapLength),
|
("$lh_length", 1) => Some(SystemClauseType::LiftedHeapLength),
|
||||||
("$module_of", 2) => Some(SystemClauseType::ModuleOf),
|
("$module_of", 2) => Some(SystemClauseType::ModuleOf),
|
||||||
("$module_retract_clause", 5) => Some(SystemClauseType::ModuleRetractClause),
|
("$module_retract_clause", 5) => Some(SystemClauseType::ModuleRetractClause),
|
||||||
|
("$module_head_is_dynamic", 2) => Some(SystemClauseType::ModuleHeadIsDynamic),
|
||||||
("$no_such_predicate", 1) => Some(SystemClauseType::NoSuchPredicate),
|
("$no_such_predicate", 1) => Some(SystemClauseType::NoSuchPredicate),
|
||||||
("$redo_attr_var_bindings", 0) => Some(SystemClauseType::RedoAttrVarBindings),
|
("$redo_attr_var_bindings", 0) => Some(SystemClauseType::RedoAttrVarBindings),
|
||||||
("$remove_call_policy_check", 1) => Some(SystemClauseType::RemoveCallPolicyCheck),
|
("$remove_call_policy_check", 1) => Some(SystemClauseType::RemoveCallPolicyCheck),
|
||||||
|
|||||||
@@ -222,7 +222,6 @@ impl OpDecl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ModuleCodeDir = HashMap<PredicateKey, ModuleCodeIndex>;
|
|
||||||
pub type ModuleDir = HashMap<ClauseName, Module>;
|
pub type ModuleDir = HashMap<ClauseName, Module>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -234,12 +233,9 @@ pub struct ModuleDecl {
|
|||||||
pub struct Module {
|
pub struct Module {
|
||||||
pub atom_tbl: TabledData<Atom>,
|
pub atom_tbl: TabledData<Atom>,
|
||||||
pub module_decl: ModuleDecl,
|
pub module_decl: ModuleDecl,
|
||||||
pub code_dir: ModuleCodeDir,
|
pub code_dir: CodeDir,
|
||||||
pub op_dir: OpDir,
|
pub op_dir: OpDir,
|
||||||
pub term_expansions: (Predicate, VecDeque<TopLevel>),
|
pub term_expansions: (Predicate, VecDeque<TopLevel>),
|
||||||
pub goal_expansions: (Predicate, VecDeque<TopLevel>),
|
pub goal_expansions: (Predicate, VecDeque<TopLevel>),
|
||||||
pub inserted_expansions: bool // has the module been successfully inserted into toplevel??
|
pub inserted_expansions: bool // has the module been successfully inserted into toplevel??
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct ModuleCodeIndex(pub IndexPtr, pub ClauseName);
|
|
||||||
|
|||||||
@@ -468,7 +468,8 @@ setof(Template, Goal, Solution) :-
|
|||||||
'$module_clause'(H, B, Module) :-
|
'$module_clause'(H, B, Module) :-
|
||||||
( var(H) -> throw(error(instantiation_error, clause/2))
|
( var(H) -> throw(error(instantiation_error, clause/2))
|
||||||
; functor(H, Name, Arity) -> ( Name == '.' -> throw(error(type_error(callable, H), clause/2))
|
; functor(H, Name, Arity) -> ( Name == '.' -> throw(error(type_error(callable, H), clause/2))
|
||||||
; '$head_is_dynamic'(H) -> '$clause_body_is_valid'(B),
|
; '$module_head_is_dynamic'(H, Module) ->
|
||||||
|
'$clause_body_is_valid'(B),
|
||||||
'$get_module_clause'(H, B, Module)
|
'$get_module_clause'(H, B, Module)
|
||||||
; throw(error(permission_error(access, private_procedure, Name/Arity),
|
; throw(error(permission_error(access, private_procedure, Name/Arity),
|
||||||
clause/2))
|
clause/2))
|
||||||
@@ -508,7 +509,7 @@ call_asserta(Head, Body, Name, Arity) :-
|
|||||||
module_asserta_clause(Head, Body, Module) :-
|
module_asserta_clause(Head, Body, Module) :-
|
||||||
( var(Head) -> throw(error(instantiation_error, asserta/1))
|
( var(Head) -> throw(error(instantiation_error, asserta/1))
|
||||||
; functor(Head, Name, Arity), atom(Name), Name \== '.' ->
|
; 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(permission_error(modify, static_procedure, Name/Arity), asserta/1))
|
||||||
)
|
)
|
||||||
; throw(error(type_error(callable, Head), asserta/1))
|
; throw(error(type_error(callable, Head), asserta/1))
|
||||||
@@ -548,7 +549,7 @@ call_assertz(Head, Body, Name, Arity) :-
|
|||||||
module_assertz_clause(Head, Body, Module) :-
|
module_assertz_clause(Head, Body, Module) :-
|
||||||
( var(Head) -> throw(error(instantiation_error, assertz/1))
|
( var(Head) -> throw(error(instantiation_error, assertz/1))
|
||||||
; functor(Head, Name, Arity), atom(Name), Name \== '.' ->
|
; 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(permission_error(modify, static_procedure, Name/Arity), assertz/1))
|
||||||
)
|
)
|
||||||
; throw(error(type_error(callable, Head), assertz/1))
|
; throw(error(type_error(callable, Head), assertz/1))
|
||||||
@@ -612,7 +613,8 @@ call_module_retract(Head, Body, Name, Arity, Module) :-
|
|||||||
retract_module_clause(Head, Body, Module) :-
|
retract_module_clause(Head, Body, Module) :-
|
||||||
( var(Head) -> throw(error(instantiation_error, retract/1))
|
( var(Head) -> throw(error(instantiation_error, retract/1))
|
||||||
; functor(Head, Name, Arity), atom(Name), Name \== '.' ->
|
; 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(permission_error(modify, static_procedure, Name/Arity), retract/1))
|
||||||
)
|
)
|
||||||
; throw(error(type_error(callable, Head), retract/1))
|
; throw(error(type_error(callable, Head), retract/1))
|
||||||
@@ -646,7 +648,8 @@ module_abolish(Pred, Module) :-
|
|||||||
; Arity < 0 -> throw(domain_error(not_less_than_zero, Arity), abolish/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)
|
; max_arity(N), Arity > N -> throw(representation_error(max_arity), abolish/1)
|
||||||
; functor(Head, Name, Arity) ->
|
; 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))
|
; throw(error(permission_error(modify, static_procedure, Pred), abolish/1))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ pub fn compile_term(wam: &mut Machine, packet: TopLevelPacket) -> EvalSession
|
|||||||
let mut compiler = ListingCompiler::new(&wam.code_repo);
|
let mut compiler = ListingCompiler::new(&wam.code_repo);
|
||||||
let indices = try_eval_session!(compile_decl(wam, &mut compiler, decl));
|
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);
|
add_toplevel_code(wam, vec![], indices);
|
||||||
|
|
||||||
EvalSession::EntrySuccess
|
EvalSession::EntrySuccess
|
||||||
@@ -173,14 +173,13 @@ fn compile_into_module<R: Read>(wam: &mut Machine, module_name: ClauseName, src:
|
|||||||
&mut indices.code_dir, 0));
|
&mut indices.code_dir, 0));
|
||||||
|
|
||||||
let mut clause_code_generator = ClauseCodeGenerator::new(module_code.len());
|
let mut clause_code_generator = ClauseCodeGenerator::new(module_code.len());
|
||||||
try_eval_session!(clause_code_generator.generate_clause_code(module_name.clone(),
|
try_eval_session!(clause_code_generator.generate_clause_code(results.dynamic_clause_map,
|
||||||
results.dynamic_clause_map,
|
|
||||||
wam));
|
wam));
|
||||||
|
|
||||||
match wam.indices.modules.get_mut(&module_name) {
|
match wam.indices.modules.get_mut(&module_name) {
|
||||||
Some(module) => {
|
Some(module) => {
|
||||||
let code_dir = mem::replace(&mut indices.code_dir, CodeDir::new());
|
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 module.module_decl.exports.contains(&(name.clone(), arity)) {
|
||||||
if let Some(idx) = wam.indices.code_dir.get(&(name.clone(), arity)) {
|
if let Some(idx) = wam.indices.code_dir.get(&(name.clone(), arity)) {
|
||||||
@@ -199,7 +198,7 @@ fn compile_into_module<R: Read>(wam: &mut Machine, module_name: ClauseName, src:
|
|||||||
};
|
};
|
||||||
|
|
||||||
wam.code_repo.code.extend(module_code.into_iter());
|
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
|
EvalSession::EntrySuccess
|
||||||
}
|
}
|
||||||
@@ -224,8 +223,7 @@ impl ClauseCodeGenerator {
|
|||||||
ClauseCodeGenerator { len_offset, code: vec![], pi_to_loc: HashMap::new() }
|
ClauseCodeGenerator { len_offset, code: vec![], pi_to_loc: HashMap::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_clause_code(&mut self, module: ClauseName, dynamic_clause_map: DynamicClauseMap,
|
fn generate_clause_code(&mut self, dynamic_clause_map: DynamicClauseMap, wam: &Machine)
|
||||||
wam: &Machine)
|
|
||||||
-> Result<(), SessionError>
|
-> Result<(), SessionError>
|
||||||
{
|
{
|
||||||
for ((name, arity), heads_and_tails) in dynamic_clause_map {
|
for ((name, arity), heads_and_tails) in dynamic_clause_map {
|
||||||
@@ -233,8 +231,6 @@ impl ClauseCodeGenerator {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
wam.check_dynamic_clause_overwrite(name.clone(), arity, module.clone())?;
|
|
||||||
|
|
||||||
let predicate = Predicate(heads_and_tails.into_iter().map(|(head, tail)| {
|
let predicate = Predicate(heads_and_tails.into_iter().map(|(head, tail)| {
|
||||||
let clause = Term::Clause(Cell::default(), clause_name!("clause"),
|
let clause = Term::Clause(Cell::default(), clause_name!("clause"),
|
||||||
vec![Box::new(head), Box::new(tail)],
|
vec![Box::new(head), Box::new(tail)],
|
||||||
@@ -255,15 +251,14 @@ impl ClauseCodeGenerator {
|
|||||||
Ok(())
|
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());
|
wam.code_repo.code.extend(self.code.into_iter());
|
||||||
|
|
||||||
for ((name, arity), p) in self.pi_to_loc {
|
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());
|
.or_insert(DynamicPredicateInfo::default());
|
||||||
|
|
||||||
entry.clauses_subsection_p = p;
|
entry.clauses_subsection_p = p;
|
||||||
entry.module_src = module.clone();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -291,7 +286,7 @@ fn add_module_code(wam: &mut Machine, mut module: Module, code: Code, mut indice
|
|||||||
let code_dir = mem::replace(&mut indices.code_dir, CodeDir::new());
|
let code_dir = mem::replace(&mut indices.code_dir, CodeDir::new());
|
||||||
let op_dir = mem::replace(&mut indices.op_dir, OpDir::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());
|
module.op_dir.extend(op_dir.into_iter());
|
||||||
|
|
||||||
wam.add_module(module, code);
|
wam.add_module(module, code);
|
||||||
@@ -301,13 +296,13 @@ fn add_non_module_code(wam: &mut Machine, dynamic_clause_map: DynamicClauseMap,
|
|||||||
indices: IndexStore)
|
indices: IndexStore)
|
||||||
-> Result<(), SessionError>
|
-> Result<(), SessionError>
|
||||||
{
|
{
|
||||||
wam.check_toplevel_code(&indices, &dynamic_clause_map)?;
|
wam.check_toplevel_code(&indices)?;
|
||||||
|
|
||||||
let mut clause_code_generator = ClauseCodeGenerator::new(code.len());
|
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);
|
add_toplevel_code(wam, code, indices);
|
||||||
clause_code_generator.add_clause_code(clause_name!("user"), wam);
|
clause_code_generator.add_clause_code(wam);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -609,17 +604,15 @@ fn compile_work<R: Read>(compiler: &mut ListingCompiler, wam: &mut Machine, src:
|
|||||||
|
|
||||||
if let Some(module) = compiler.module.take() {
|
if let Some(module) = compiler.module.take() {
|
||||||
let mut clause_code_generator = ClauseCodeGenerator::new(module_code.len() + toplvl_code.len());
|
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!(wam.check_toplevel_code(&results.toplevel_indices));
|
||||||
try_eval_session!(clause_code_generator.generate_clause_code(module_name.clone(),
|
try_eval_session!(clause_code_generator.generate_clause_code(results.dynamic_clause_map,
|
||||||
results.dynamic_clause_map,
|
|
||||||
wam));
|
wam));
|
||||||
|
|
||||||
add_module_code(wam, module, module_code, indices);
|
add_module_code(wam, module, module_code, indices);
|
||||||
add_toplevel_code(wam, toplvl_code, results.toplevel_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 {
|
} else {
|
||||||
try_eval_session!(add_non_module_code(wam, results.dynamic_clause_map, module_code,
|
try_eval_session!(add_non_module_code(wam, results.dynamic_clause_map, module_code,
|
||||||
indices));
|
indices));
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.indices.remove_code_index((name.clone(), arity));
|
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)
|
fn abolish_dynamic_clause_in_module(&mut self, name: RegType, arity: RegType, module: RegType)
|
||||||
@@ -110,7 +110,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.indices.remove_code_index((name.clone(), arity));
|
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,
|
fn handle_eval_result_from_dynamic_compile(&mut self, pred_str: String, name: ClauseName,
|
||||||
|
|||||||
@@ -66,8 +66,7 @@ impl MachineError {
|
|||||||
pub(super) fn session_error(h: usize, err: SessionError) -> Self {
|
pub(super) fn session_error(h: usize, err: SessionError) -> Self {
|
||||||
match err {
|
match err {
|
||||||
SessionError::ParserError(err) => Self::syntax_error(h, 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) =>
|
| SessionError::CannotOverwriteImport(pred_str) =>
|
||||||
Self::permission_error(PermissionError::Modify, pred_str),
|
Self::permission_error(PermissionError::Modify, pred_str),
|
||||||
SessionError::ModuleDoesNotContainExport =>
|
SessionError::ModuleDoesNotContainExport =>
|
||||||
@@ -372,7 +371,6 @@ impl MachineState {
|
|||||||
|
|
||||||
pub enum SessionError {
|
pub enum SessionError {
|
||||||
CannotOverwriteBuiltIn(ClauseName),
|
CannotOverwriteBuiltIn(ClauseName),
|
||||||
CannotOverwriteDynamicClause(ClauseName),
|
|
||||||
CannotOverwriteImport(ClauseName),
|
CannotOverwriteImport(ClauseName),
|
||||||
ModuleDoesNotContainExport,
|
ModuleDoesNotContainExport,
|
||||||
ModuleNotFound,
|
ModuleNotFound,
|
||||||
|
|||||||
@@ -193,6 +193,13 @@ impl CodeIndex {
|
|||||||
pub fn module_name(&self) -> ClauseName {
|
pub fn module_name(&self) -> ClauseName {
|
||||||
self.0.borrow().1.clone()
|
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 {
|
impl Default for CodeIndex {
|
||||||
@@ -371,18 +378,17 @@ pub type AllocVarDict = HashMap<Rc<Var>, VarData>;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct DynamicPredicateInfo {
|
pub struct DynamicPredicateInfo {
|
||||||
pub(super) clauses_subsection_p: usize, // a LocalCodePtr::DirEntry value.
|
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 {
|
impl Default for DynamicPredicateInfo {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
DynamicPredicateInfo { clauses_subsection_p: 0,
|
DynamicPredicateInfo { clauses_subsection_p: 0 }
|
||||||
module_src: clause_name!("user") }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type InSituCodeDir = HashMap<PredicateKey, usize>;
|
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 struct IndexStore {
|
||||||
pub(super) atom_tbl: TabledData<Atom>,
|
pub(super) atom_tbl: TabledData<Atom>,
|
||||||
@@ -421,8 +427,16 @@ impl IndexStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_clause_subsection(&self, name: ClauseName, arity: usize) -> Option<DynamicPredicateInfo> {
|
pub fn remove_clause_subsection(&mut self, module: ClauseName, name: ClauseName, arity: usize)
|
||||||
self.dynamic_code_dir.get(&(name, arity)).cloned()
|
{
|
||||||
|
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]
|
#[inline]
|
||||||
@@ -458,8 +472,7 @@ impl IndexStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_internal(&self, name: ClauseName, arity: usize, in_mod: ClauseName)
|
fn get_internal(&self, name: ClauseName, arity: usize, in_mod: ClauseName) -> Option<CodeIndex>
|
||||||
-> Option<ModuleCodeIndex>
|
|
||||||
{
|
{
|
||||||
self.modules.get(&in_mod)
|
self.modules.get(&in_mod)
|
||||||
.and_then(|ref module| module.code_dir.get(&(name, arity)))
|
.and_then(|ref module| module.code_dir.get(&(name, arity)))
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ use prolog::machine::machine_errors::*;
|
|||||||
use prolog::machine::machine_indices::*;
|
use prolog::machine::machine_indices::*;
|
||||||
use prolog::machine::machine_state::*;
|
use prolog::machine::machine_state::*;
|
||||||
use prolog::machine::modules::*;
|
use prolog::machine::modules::*;
|
||||||
use prolog::machine::toplevel::*;
|
|
||||||
|
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
@@ -105,20 +104,22 @@ impl SubModuleUser for IndexStore {
|
|||||||
fn remove_code_index(&mut self, key: PredicateKey)
|
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() {
|
if !code_idx.is_undefined() {
|
||||||
println!("warning: overwriting {}/{}", &name, arity);
|
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;
|
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,
|
fn use_qualified_module(&mut self, code_repo: &mut CodeRepo, flags: MachineFlags,
|
||||||
@@ -210,23 +211,7 @@ impl Machine {
|
|||||||
self.machine_st.flags
|
self.machine_st.flags
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_dynamic_clause_overwrite(&self, name: ClauseName, arity: usize, module: ClauseName)
|
pub fn check_toplevel_code(&self, indices: &IndexStore) -> Result<(), SessionError>
|
||||||
-> 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>
|
|
||||||
{
|
{
|
||||||
for (key, idx) in &indices.code_dir {
|
for (key, idx) in &indices.code_dir {
|
||||||
match ClauseType::from(key.0.clone(), key.1, None) {
|
match ClauseType::from(key.0.clone(), key.1, None) {
|
||||||
@@ -240,11 +225,6 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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) {
|
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.
|
// ensure we don't try to overwrite an existing predicate from a different module.
|
||||||
if !existing_idx.is_undefined() && !idx.is_undefined() {
|
if !existing_idx.is_undefined() && !idx.is_undefined() {
|
||||||
|
|||||||
@@ -6,24 +6,7 @@ use prolog::machine::code_repo::*;
|
|||||||
use prolog::machine::machine_errors::*;
|
use prolog::machine::machine_errors::*;
|
||||||
use prolog::machine::machine_indices::*;
|
use prolog::machine::machine_indices::*;
|
||||||
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::{VecDeque};
|
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.
|
// Module's and related types are defined in forms.
|
||||||
impl Module {
|
impl Module {
|
||||||
@@ -31,7 +14,7 @@ impl Module {
|
|||||||
Module { module_decl, atom_tbl,
|
Module { module_decl, atom_tbl,
|
||||||
term_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
term_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
||||||
goal_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(),
|
op_dir: default_op_dir(),
|
||||||
inserted_expansions: false }
|
inserted_expansions: false }
|
||||||
}
|
}
|
||||||
@@ -69,7 +52,7 @@ pub trait SubModuleUser
|
|||||||
fn remove_code_index(&mut self, PredicateKey);
|
fn remove_code_index(&mut self, PredicateKey);
|
||||||
fn get_code_index(&self, PredicateKey, ClauseName) -> Option<CodeIndex>;
|
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)
|
fn remove_module(&mut self, mod_name: ClauseName, module: &Module)
|
||||||
{
|
{
|
||||||
@@ -141,9 +124,6 @@ pub trait SubModuleUser
|
|||||||
|
|
||||||
atom_tbl.borrow_mut().insert(name.to_rc());
|
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());
|
self.insert_dir_entry(name, arity, code_data.clone());
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
@@ -203,7 +183,7 @@ impl SubModuleUser for Module {
|
|||||||
self.code_dir.remove(&key);
|
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);
|
self.code_dir.insert((name, arity), idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,12 +216,3 @@ impl SubModuleUser for Module {
|
|||||||
Ok(())
|
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()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -294,27 +294,47 @@ impl MachineState {
|
|||||||
Addr::Str(s) =>
|
Addr::Str(s) =>
|
||||||
match self.heap[s].clone() {
|
match self.heap[s].clone() {
|
||||||
HeapCellValue::NamedStr(arity, name, ..) =>
|
HeapCellValue::NamedStr(arity, name, ..) =>
|
||||||
indices.get_clause_subsection(name, arity),
|
indices.get_clause_subsection(module, name, arity),
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
},
|
},
|
||||||
Addr::Con(Constant::Atom(name, _)) =>
|
Addr::Con(Constant::Atom(name, _)) =>
|
||||||
indices.get_clause_subsection(name, 0),
|
indices.get_clause_subsection(module, name, 0),
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
match subsection {
|
match subsection {
|
||||||
Some(dynamic_predicate_info) => {
|
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(());
|
return Ok(());
|
||||||
},
|
},
|
||||||
None => self.fail = true
|
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 => {
|
&SystemClauseType::HeadIsDynamic => {
|
||||||
let head = self[temp_v!(1)].clone();
|
let head = self[temp_v!(1)].clone();
|
||||||
|
|
||||||
@@ -322,11 +342,11 @@ impl MachineState {
|
|||||||
Addr::Str(s) =>
|
Addr::Str(s) =>
|
||||||
match self.heap[s].clone() {
|
match self.heap[s].clone() {
|
||||||
HeapCellValue::NamedStr(arity, name, ..) =>
|
HeapCellValue::NamedStr(arity, name, ..) =>
|
||||||
indices.get_clause_subsection(name, arity).is_some(),
|
indices.get_clause_subsection(name.owning_module(), name, arity).is_some(),
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
},
|
},
|
||||||
Addr::Con(Constant::Atom(name, _)) =>
|
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!()
|
_ => unreachable!()
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -877,11 +897,11 @@ impl MachineState {
|
|||||||
Addr::Str(s) =>
|
Addr::Str(s) =>
|
||||||
match self.heap[s].clone() {
|
match self.heap[s].clone() {
|
||||||
HeapCellValue::NamedStr(arity, name, ..) =>
|
HeapCellValue::NamedStr(arity, name, ..) =>
|
||||||
indices.get_clause_subsection(name, arity),
|
indices.get_clause_subsection(name.owning_module(), name, arity),
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
},
|
},
|
||||||
Addr::Con(Constant::Atom(name, _)) =>
|
Addr::Con(Constant::Atom(name, _)) =>
|
||||||
indices.get_clause_subsection(name, 0),
|
indices.get_clause_subsection(name.owning_module(), name, 0),
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -45,12 +45,6 @@ impl fmt::Display for IndexPtr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ModuleCodeIndex {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{}", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for FactInstruction {
|
impl fmt::Display for FactInstruction {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
@@ -249,8 +243,6 @@ impl fmt::Display for IndexingInstruction {
|
|||||||
impl fmt::Display for SessionError {
|
impl fmt::Display for SessionError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
&SessionError::CannotOverwriteDynamicClause(ref msg) =>
|
|
||||||
write!(f, "cannot overwrite dynamic predicate {}", msg),
|
|
||||||
&SessionError::CannotOverwriteBuiltIn(ref msg) =>
|
&SessionError::CannotOverwriteBuiltIn(ref msg) =>
|
||||||
write!(f, "cannot overwrite {}", msg),
|
write!(f, "cannot overwrite {}", msg),
|
||||||
&SessionError::CannotOverwriteImport(ref msg) =>
|
&SessionError::CannotOverwriteImport(ref msg) =>
|
||||||
|
|||||||
Reference in New Issue
Block a user