support module modification using dynamic database predicates
This commit is contained in:
@@ -136,8 +136,11 @@ impl InlinedClauseType {
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum SystemClauseType {
|
||||
AbolishClause,
|
||||
AbolishModuleClause,
|
||||
AssertDynamicPredicateToBack,
|
||||
AssertDynamicPredicateToFront,
|
||||
ModuleAssertDynamicPredicateToFront,
|
||||
ModuleAssertDynamicPredicateToBack,
|
||||
CheckCutPoint,
|
||||
CopyToLiftedHeap,
|
||||
DeleteAttribute,
|
||||
@@ -155,6 +158,7 @@ pub enum SystemClauseType {
|
||||
GetBValue,
|
||||
GetClause,
|
||||
GetCurrentPredicateList,
|
||||
GetModuleClause,
|
||||
GetLiftedHeapFromOffset,
|
||||
GetLiftedHeapFromOffsetDiff,
|
||||
GetSCCCleaner,
|
||||
@@ -163,6 +167,7 @@ pub enum SystemClauseType {
|
||||
InstallInferenceCounter,
|
||||
LiftedHeapLength,
|
||||
ModuleOf,
|
||||
ModuleRetractClause,
|
||||
NoSuchPredicate,
|
||||
RedoAttrVarBindings,
|
||||
RemoveCallPolicyCheck,
|
||||
@@ -197,8 +202,11 @@ impl SystemClauseType {
|
||||
pub fn name(&self) -> ClauseName {
|
||||
match self {
|
||||
&SystemClauseType::AbolishClause => clause_name!("$abolish_clause"),
|
||||
&SystemClauseType::AssertDynamicPredicateToBack => clause_name!("$asserta"),
|
||||
&SystemClauseType::AssertDynamicPredicateToFront => clause_name!("$assertz"),
|
||||
&SystemClauseType::AbolishModuleClause => clause_name!("$abolish_module_clause"),
|
||||
&SystemClauseType::AssertDynamicPredicateToBack => clause_name!("$assertz"),
|
||||
&SystemClauseType::AssertDynamicPredicateToFront => clause_name!("$asserta"),
|
||||
&SystemClauseType::ModuleAssertDynamicPredicateToFront => clause_name!("$module_asserta"),
|
||||
&SystemClauseType::ModuleAssertDynamicPredicateToBack => clause_name!("$module_assertz"),
|
||||
&SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
|
||||
&SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"),
|
||||
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
|
||||
@@ -219,6 +227,7 @@ impl SystemClauseType {
|
||||
&SystemClauseType::GetBValue => clause_name!("$get_b_value"),
|
||||
&SystemClauseType::GetClause => clause_name!("$get_clause"),
|
||||
&SystemClauseType::GetDoubleQuotes => clause_name!("$get_double_quotes"),
|
||||
&SystemClauseType::GetModuleClause => clause_name!("$get_module_clause"),
|
||||
&SystemClauseType::GetSCCCleaner => clause_name!("$get_scc_cleaner"),
|
||||
&SystemClauseType::HeadIsDynamic => clause_name!("$head_is_dynamic"),
|
||||
&SystemClauseType::InstallSCCCleaner => clause_name!("$install_scc_cleaner"),
|
||||
@@ -239,6 +248,7 @@ impl SystemClauseType {
|
||||
&SystemClauseType::GetCutPoint => clause_name!("$get_cp"),
|
||||
&SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"),
|
||||
&SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"),
|
||||
&SystemClauseType::ModuleRetractClause => clause_name!("$module_retract_clause"),
|
||||
&SystemClauseType::RetractClause => clause_name!("$retract_clause"),
|
||||
&SystemClauseType::ResetBlock => clause_name!("$reset_block"),
|
||||
&SystemClauseType::ReturnFromAttributeGoals => clause_name!("$return_from_attribute_goals"),
|
||||
@@ -254,10 +264,13 @@ impl SystemClauseType {
|
||||
&SystemClauseType::WriteTerm => clause_name!("$write_term"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
|
||||
match (name, arity) {
|
||||
("$abolish_clause", 2) => Some(SystemClauseType::AbolishClause),
|
||||
("$abolish_module_clause", 3) => Some(SystemClauseType::AbolishModuleClause),
|
||||
("$module_asserta", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToFront),
|
||||
("$module_assertz", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToBack),
|
||||
("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront),
|
||||
("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack),
|
||||
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
|
||||
@@ -274,6 +287,7 @@ impl SystemClauseType {
|
||||
("$get_attr_list", 2) => Some(SystemClauseType::GetAttributedVariableList),
|
||||
("$get_b_value", 1) => Some(SystemClauseType::GetBValue),
|
||||
("$get_clause", 2) => Some(SystemClauseType::GetClause),
|
||||
("$get_module_clause", 3) => Some(SystemClauseType::GetModuleClause),
|
||||
("$get_current_predicate_list", 1) => Some(SystemClauseType::GetCurrentPredicateList),
|
||||
("$get_lh_from_offset", 2) => Some(SystemClauseType::GetLiftedHeapFromOffset),
|
||||
("$get_lh_from_offset_diff", 3) => Some(SystemClauseType::GetLiftedHeapFromOffsetDiff),
|
||||
@@ -284,6 +298,7 @@ impl SystemClauseType {
|
||||
("$install_inference_counter", 3) => Some(SystemClauseType::InstallInferenceCounter),
|
||||
("$lh_length", 1) => Some(SystemClauseType::LiftedHeapLength),
|
||||
("$module_of", 2) => Some(SystemClauseType::ModuleOf),
|
||||
("$module_retract_clause", 5) => Some(SystemClauseType::ModuleRetractClause),
|
||||
("$no_such_predicate", 1) => Some(SystemClauseType::NoSuchPredicate),
|
||||
("$redo_attr_var_bindings", 0) => Some(SystemClauseType::RedoAttrVarBindings),
|
||||
("$remove_call_policy_check", 1) => Some(SystemClauseType::RemoveCallPolicyCheck),
|
||||
|
||||
@@ -459,15 +459,30 @@ setof(Template, Goal, Solution) :-
|
||||
|
||||
'$clause_body_is_valid'(B) :-
|
||||
( var(B) -> true
|
||||
; functor(B, Name, _) -> ( atom(Name), Name \= '.' -> true
|
||||
; functor(B, Name, _) -> ( atom(Name), Name \== '.' -> true
|
||||
; throw(error(type_error(callable, B), clause/2))
|
||||
)
|
||||
; throw(error(type_error(callable, B), clause/2))
|
||||
).
|
||||
|
||||
'$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)
|
||||
; throw(error(permission_error(access, private_procedure, Name/Arity),
|
||||
clause/2))
|
||||
)
|
||||
; throw(error(type_error(callable, H), clause/2))
|
||||
).
|
||||
|
||||
clause(H, B) :-
|
||||
( var(H) -> throw(error(instantiation_error, clause/2))
|
||||
; functor(H, Name, Arity) -> ( Name == '.' -> throw(error(type_error(callable, H), clause/2))
|
||||
; Name == (:), Arity =:= 2 ->
|
||||
arg(1, H, Module),
|
||||
arg(2, H, F),
|
||||
'$module_clause'(F, B, Module)
|
||||
%% '$no_such_predicate' fails if H is not callable.
|
||||
; '$no_such_predicate'(H) -> '$fail'
|
||||
; '$head_is_dynamic'(H) -> '$clause_body_is_valid'(B),
|
||||
@@ -478,16 +493,35 @@ clause(H, B) :-
|
||||
; throw(error(type_error(callable, H), clause/2))
|
||||
).
|
||||
|
||||
call_module_asserta(Head, Body, Name, Arity, Module) :-
|
||||
'$clause_body_is_valid'(Body),
|
||||
functor(VarHead, Name, Arity),
|
||||
findall((VarHead :- VarBody), clause(Module:VarHead, VarBody), Clauses),
|
||||
'$module_asserta'((Head :- Body), Clauses, Name, Arity, Module).
|
||||
|
||||
call_asserta(Head, Body, Name, Arity) :-
|
||||
'$clause_body_is_valid'(Body),
|
||||
functor(VarHead, Name, Arity),
|
||||
findall((VarHead :- VarBody), clause(VarHead, VarBody), Clauses),
|
||||
'$asserta'((Head :- Body), Clauses, Name, Arity).
|
||||
|
||||
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)
|
||||
; throw(error(permission_error(modify, static_procedure, Name/Arity), asserta/1))
|
||||
)
|
||||
; throw(error(type_error(callable, Head), asserta/1))
|
||||
).
|
||||
|
||||
asserta_clause(Head, Body) :-
|
||||
( var(Head) -> throw(error(instantiation_error, asserta/1))
|
||||
; functor(Head, Name, Arity), atom(Name), Name \== '.' ->
|
||||
( '$no_such_predicate'(Head) -> call_asserta(Head, Body, Name, Arity)
|
||||
( Name == (:), Arity =:= 2 ->
|
||||
arg(1, Head, Module),
|
||||
arg(2, Head, F),
|
||||
module_asserta_clause(F, Body, Module)
|
||||
; '$no_such_predicate'(Head) -> call_asserta(Head, Body, Name, Arity)
|
||||
; '$head_is_dynamic'(Head) -> call_asserta(Head, Body, Name, Arity)
|
||||
; throw(error(permission_error(modify, static_procedure, Name/Arity), asserta/1))
|
||||
)
|
||||
@@ -499,16 +533,35 @@ asserta(Clause) :-
|
||||
; Clause = (Head :- Body) -> asserta_clause(Head, Body)
|
||||
).
|
||||
|
||||
call_module_assertz(Head, Body, Name, Arity, Module) :-
|
||||
'$clause_body_is_valid'(Body),
|
||||
functor(VarHead, Name, Arity),
|
||||
findall((VarHead :- VarBody), clause(Module:VarHead, VarBody), Clauses),
|
||||
'$module_assertz'((Head :- Body), Clauses, Name, Arity, Module).
|
||||
|
||||
call_assertz(Head, Body, Name, Arity) :-
|
||||
'$clause_body_is_valid'(Body),
|
||||
functor(VarHead, Name, Arity),
|
||||
findall((VarHead :- VarBody), clause(VarHead, VarBody), Clauses),
|
||||
'$assertz'((Head :- Body), Clauses, Name, Arity).
|
||||
|
||||
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)
|
||||
; throw(error(permission_error(modify, static_procedure, Name/Arity), assertz/1))
|
||||
)
|
||||
; throw(error(type_error(callable, Head), assertz/1))
|
||||
).
|
||||
|
||||
assertz_clause(Head, Body) :-
|
||||
( var(Head) -> throw(error(instantiation_error, assertz/1))
|
||||
; functor(Head, Name, Arity), atom(Name), Name \== '.' ->
|
||||
( '$no_such_predicate'(Head) -> call_assertz(Head, Body, Name, Arity)
|
||||
( Name == (:), Arity =:= 2 ->
|
||||
arg(1, Head, Module),
|
||||
arg(2, Head, F),
|
||||
module_assertz_clause(F, Body, Module)
|
||||
; '$no_such_predicate'(Head) -> call_assertz(Head, Body, Name, Arity)
|
||||
; '$head_is_dynamic'(Head) -> call_assertz(Head, Body, Name, Arity)
|
||||
; throw(error(permission_error(modify, static_procedure, Name/Arity), assertz/1))
|
||||
)
|
||||
@@ -541,10 +594,38 @@ call_retract(Head, Body, Name, Arity) :-
|
||||
findall((Head :- Body), clause(Head, Body), Clauses),
|
||||
retract_clauses(Clauses, Head, Body, Name, Arity).
|
||||
|
||||
module_retract_clauses([Clause|Clauses0], Head, Body, Name, Arity, Module) :-
|
||||
functor(VarHead, Name, Arity),
|
||||
findall((VarHead :- VarBody), clause(Module:VarHead, VarBody), Clauses1),
|
||||
first_match_index(Clauses1, (Head :- Body), 0, N),
|
||||
( Clauses0 == [] -> !
|
||||
; true
|
||||
),
|
||||
'$module_retract_clause'(Name, Arity, N, Clauses1, Module).
|
||||
module_retract_clauses([_|Clauses0], Head, Body, Name, Arity, Module) :-
|
||||
module_retract_clauses(Clauses0, Head, Body, Name, Arity, Module).
|
||||
|
||||
call_module_retract(Head, Body, Name, Arity, Module) :-
|
||||
findall((Head :- Body), clause(Module:Head, Body), Clauses),
|
||||
module_retract_clauses(Clauses, Head, Body, Name, Arity, Module).
|
||||
|
||||
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)
|
||||
; throw(error(permission_error(modify, static_procedure, Name/Arity), retract/1))
|
||||
)
|
||||
; throw(error(type_error(callable, Head), retract/1))
|
||||
).
|
||||
|
||||
retract_clause(Head, Body) :-
|
||||
( var(Head) -> throw(error(instantiation_error, retract/1))
|
||||
; functor(Head, Name, Arity), atom(Name), Name \== '.' ->
|
||||
( '$head_is_dynamic'(Head) -> call_retract(Head, Body, Name, Arity)
|
||||
( Name == (:), Arity =:= 2 ->
|
||||
arg(1, Head, Module),
|
||||
arg(2, Head, F),
|
||||
retract_module_clause(F, Body, Module)
|
||||
; '$head_is_dynamic'(Head) -> call_retract(Head, Body, Name, Arity)
|
||||
; '$no_such_predicate'(Head) -> '$fail'
|
||||
; throw(error(permission_error(modify, static_procedure, Name/Arity), retract/1))
|
||||
)
|
||||
@@ -556,8 +637,27 @@ retract(Clause) :-
|
||||
; Clause = (Head :- Body) -> retract_clause(Head, Body)
|
||||
).
|
||||
|
||||
module_abolish(Pred, Module) :-
|
||||
( var(Pred) -> throw(error(instantiation_error), abolish/1)
|
||||
; Pred = Name/Arity ->
|
||||
( var(Name) -> throw(error(instantiation_error, abolish/1))
|
||||
; integer(Arity) ->
|
||||
( \+ atom(Name) -> throw(error(type_error(atom, Name), 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)
|
||||
; functor(Head, Name, Arity) ->
|
||||
( '$head_is_dynamic'(Head) -> '$abolish_module_clause'(Name, Arity, Module)
|
||||
; throw(error(permission_error(modify, static_procedure, Pred), abolish/1))
|
||||
)
|
||||
)
|
||||
; throw(error(type_error(integer, Arity), abolish/1))
|
||||
)
|
||||
; throw(error(type_error(predicate_indicator, Module:Pred), abolish/1))
|
||||
).
|
||||
|
||||
abolish(Pred) :-
|
||||
( var(Pred) -> throw(error(instantiation_error), abolish/1)
|
||||
; Pred = Module:InnerPred -> module_abolish(InnerPred, Module)
|
||||
; Pred = Name/Arity ->
|
||||
( var(Name) -> throw(error(instantiation_error, abolish/1))
|
||||
; var(Arity) -> throw(error(instantiation_error, abolish/1))
|
||||
@@ -566,7 +666,7 @@ abolish(Pred) :-
|
||||
; 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) ->
|
||||
( '$no_such_predicate'(Head) -> '$abolish_clause'(Name, Arity)
|
||||
( '$no_such_predicate'(Head) -> true
|
||||
; '$head_is_dynamic'(Head) -> '$abolish_clause'(Name, Arity)
|
||||
; throw(error(permission_error(modify, static_procedure, Pred), abolish/1))
|
||||
)
|
||||
|
||||
@@ -16,7 +16,7 @@ impl Machine {
|
||||
_ => self.indices.atom_tbl()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn compile_into_machine<R: Read>(&mut self, src: R, name: ClauseName) -> EvalSession
|
||||
{
|
||||
match name.owning_module().as_str() {
|
||||
@@ -72,6 +72,35 @@ impl Machine {
|
||||
self.indices.remove_code_index((name, arity));
|
||||
}
|
||||
|
||||
fn abolish_dynamic_clause_in_module(&mut self, name: RegType, arity: RegType, module: RegType)
|
||||
{
|
||||
let (name, arity) = self.get_predicate_key(name, arity);
|
||||
let module_addr = self.machine_st[module].clone();
|
||||
|
||||
let module_name = match self.machine_st.store(self.machine_st.deref(module_addr)) {
|
||||
Addr::Con(Constant::Atom(module, _)) =>
|
||||
match self.indices.modules.get_mut(&module) {
|
||||
Some(ref mut module) => {
|
||||
module.code_dir.remove(&(name.clone(), arity));
|
||||
module.module_decl.name.clone()
|
||||
},
|
||||
_ => {
|
||||
self.machine_st.fail = true;
|
||||
return;
|
||||
}
|
||||
},
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
if let Some(idx) = self.indices.code_dir.get(&(name.clone(), arity)) {
|
||||
if idx.module_name() == module_name {
|
||||
set_code_index!(idx, IndexPtr::Undefined, clause_name!("user"));
|
||||
}
|
||||
}
|
||||
|
||||
self.indices.remove_code_index((name, arity));
|
||||
}
|
||||
|
||||
fn handle_eval_result_from_dynamic_compile(&mut self, pred_str: String, name: ClauseName,
|
||||
src: ClauseName)
|
||||
{
|
||||
@@ -90,10 +119,9 @@ impl Machine {
|
||||
}
|
||||
}
|
||||
|
||||
fn recompile_dynamic_predicate(&mut self, place: DynamicAssertPlace)
|
||||
fn recompile_dynamic_predicate_impl(&mut self, place: DynamicAssertPlace, name: ClauseName,
|
||||
arity: usize)
|
||||
{
|
||||
let (name, arity) = self.get_predicate_key(temp_v!(3), temp_v!(4));
|
||||
|
||||
let stub = MachineError::functor_stub(place.predicate_name(), 1);
|
||||
let pred_str = match self.machine_st.try_from_list(temp_v!(2), stub) {
|
||||
Ok(addrs) => {
|
||||
@@ -110,7 +138,44 @@ impl Machine {
|
||||
self.handle_eval_result_from_dynamic_compile(pred_str, name, place.predicate_name());
|
||||
}
|
||||
|
||||
fn retract_from_dynamic_predicate(&mut self)
|
||||
fn set_module_atom_tbl(&mut self, module_addr: Addr, name: &mut ClauseName) -> bool
|
||||
{
|
||||
let atom_tbl = match self.machine_st.store(self.machine_st.deref(module_addr)) {
|
||||
Addr::Con(Constant::Atom(module, _)) =>
|
||||
match self.indices.modules.get(&module) {
|
||||
Some(ref module) => module.atom_tbl.clone(),
|
||||
None => {
|
||||
self.machine_st.fail = true;
|
||||
return false;
|
||||
}
|
||||
},
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
if let &mut ClauseName::User(ref mut rc) = name {
|
||||
rc.table = atom_tbl;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn recompile_dynamic_predicate_in_module(&mut self, place: DynamicAssertPlace)
|
||||
{
|
||||
let (mut name, arity) = self.get_predicate_key(temp_v!(3), temp_v!(4));
|
||||
let module_addr = self.machine_st[temp_v!(5)].clone();
|
||||
|
||||
if self.set_module_atom_tbl(module_addr, &mut name) {
|
||||
self.recompile_dynamic_predicate_impl(place, name, arity);
|
||||
}
|
||||
}
|
||||
|
||||
fn recompile_dynamic_predicate(&mut self, place: DynamicAssertPlace)
|
||||
{
|
||||
let (name, arity) = self.get_predicate_key(temp_v!(3), temp_v!(4));
|
||||
self.recompile_dynamic_predicate_impl(place, name, arity);
|
||||
}
|
||||
|
||||
fn retract_from_dynamic_predicate_in_module(&mut self)
|
||||
{
|
||||
let index = self.machine_st[temp_v!(3)].clone();
|
||||
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
||||
@@ -118,9 +183,30 @@ impl Machine {
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
let stub = MachineError::functor_stub(clause_name!("retract"), 1);
|
||||
let (mut name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2));
|
||||
let module_addr = self.machine_st[temp_v!(5)].clone();
|
||||
|
||||
if self.set_module_atom_tbl(module_addr, &mut name) {
|
||||
self.retract_from_dynamic_predicate_impl(name, arity, index);
|
||||
}
|
||||
}
|
||||
|
||||
fn retract_from_dynamic_predicate(&mut self)
|
||||
{
|
||||
let index = self.machine_st[temp_v!(3)].clone();
|
||||
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
||||
Addr::Con(Constant::Number(Number::Integer(n))) => n.to_usize().unwrap(),
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
let (name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2));
|
||||
|
||||
self.retract_from_dynamic_predicate_impl(name, arity, index);
|
||||
}
|
||||
|
||||
fn retract_from_dynamic_predicate_impl(&mut self, name: ClauseName, arity: usize, index: usize)
|
||||
{
|
||||
let stub = MachineError::functor_stub(clause_name!("retract"), 1);
|
||||
let pred_str = match self.machine_st.try_from_list(temp_v!(4), stub) {
|
||||
Ok(addrs) => {
|
||||
let mut addrs = VecDeque::from(addrs);
|
||||
@@ -148,6 +234,12 @@ impl Machine {
|
||||
self.abolish_dynamic_clause(temp_v!(1), temp_v!(2)),
|
||||
DynamicTransactionType::Assert(place) =>
|
||||
self.recompile_dynamic_predicate(place),
|
||||
DynamicTransactionType::ModuleAbolish =>
|
||||
self.abolish_dynamic_clause_in_module(temp_v!(1), temp_v!(2), temp_v!(3)),
|
||||
DynamicTransactionType::ModuleAssert(place) =>
|
||||
self.recompile_dynamic_predicate_in_module(place),
|
||||
DynamicTransactionType::ModuleRetract =>
|
||||
self.retract_from_dynamic_predicate_in_module(),
|
||||
DynamicTransactionType::Retract =>
|
||||
self.retract_from_dynamic_predicate()
|
||||
}
|
||||
|
||||
@@ -234,6 +234,9 @@ impl DynamicAssertPlace {
|
||||
pub enum DynamicTransactionType {
|
||||
Abolish,
|
||||
Assert(DynamicAssertPlace),
|
||||
ModuleAbolish,
|
||||
ModuleAssert(DynamicAssertPlace),
|
||||
ModuleRetract,
|
||||
Retract // dynamic index of the clause to remove.
|
||||
}
|
||||
|
||||
@@ -421,7 +424,7 @@ impl IndexStore {
|
||||
pub fn get_clause_subsection(&self, name: ClauseName, arity: usize) -> Option<DynamicPredicateInfo> {
|
||||
self.dynamic_code_dir.get(&(name, arity)).cloned()
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
pub fn take_module(&mut self, name: ClauseName) -> Option<Module> {
|
||||
self.modules.remove(&name)
|
||||
|
||||
@@ -228,6 +228,13 @@ impl MachineState {
|
||||
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||
return Ok(());
|
||||
},
|
||||
&SystemClauseType::AbolishModuleClause => {
|
||||
let p = self.cp;
|
||||
let trans_type = DynamicTransactionType::ModuleAbolish;
|
||||
|
||||
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||
return Ok(());
|
||||
},
|
||||
&SystemClauseType::AssertDynamicPredicateToFront => {
|
||||
let p = self.cp;
|
||||
let trans_type = DynamicTransactionType::Assert(DynamicAssertPlace::Front);
|
||||
@@ -242,6 +249,20 @@ impl MachineState {
|
||||
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||
return Ok(());
|
||||
},
|
||||
&SystemClauseType::ModuleAssertDynamicPredicateToFront => {
|
||||
let p = self.cp;
|
||||
let trans_type = DynamicTransactionType::ModuleAssert(DynamicAssertPlace::Front);
|
||||
|
||||
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||
return Ok(());
|
||||
},
|
||||
&SystemClauseType::ModuleAssertDynamicPredicateToBack => {
|
||||
let p = self.cp;
|
||||
let trans_type = DynamicTransactionType::ModuleAssert(DynamicAssertPlace::Back);
|
||||
|
||||
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||
return Ok(());
|
||||
},
|
||||
&SystemClauseType::LiftedHeapLength => {
|
||||
let a1 = self[temp_v!(1)].clone();
|
||||
let lh_len = Addr::Con(Constant::Usize(self.lifted_heap.len()));
|
||||
@@ -256,6 +277,44 @@ impl MachineState {
|
||||
_ => self.fail = true
|
||||
};
|
||||
},
|
||||
&SystemClauseType::GetModuleClause => {
|
||||
let module = self[temp_v!(3)].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(());
|
||||
}
|
||||
};
|
||||
|
||||
let subsection = match self.store(self.deref(head)) {
|
||||
Addr::Str(s) =>
|
||||
match self.heap[s].clone() {
|
||||
HeapCellValue::NamedStr(arity, name, ..) =>
|
||||
indices.get_clause_subsection(name, arity),
|
||||
_ => unreachable!()
|
||||
},
|
||||
Addr::Con(Constant::Atom(name, _)) =>
|
||||
indices.get_clause_subsection(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);
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
},
|
||||
None => self.fail = true
|
||||
}
|
||||
},
|
||||
&SystemClauseType::HeadIsDynamic => {
|
||||
let head = self[temp_v!(1)].clone();
|
||||
|
||||
@@ -682,6 +741,13 @@ impl MachineState {
|
||||
None => panic!("remove_inference_counter: requires \\
|
||||
CWILCallPolicy.")
|
||||
},
|
||||
&SystemClauseType::ModuleRetractClause => {
|
||||
let p = self.cp;
|
||||
let trans_type = DynamicTransactionType::ModuleRetract;
|
||||
|
||||
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||
return Ok(());
|
||||
},
|
||||
&SystemClauseType::RetractClause => {
|
||||
let p = self.cp;
|
||||
let trans_type = DynamicTransactionType::Retract;
|
||||
|
||||
Reference in New Issue
Block a user