support module modification using dynamic database predicates
This commit is contained in:
@@ -136,8 +136,11 @@ impl InlinedClauseType {
|
|||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub enum SystemClauseType {
|
pub enum SystemClauseType {
|
||||||
AbolishClause,
|
AbolishClause,
|
||||||
|
AbolishModuleClause,
|
||||||
AssertDynamicPredicateToBack,
|
AssertDynamicPredicateToBack,
|
||||||
AssertDynamicPredicateToFront,
|
AssertDynamicPredicateToFront,
|
||||||
|
ModuleAssertDynamicPredicateToFront,
|
||||||
|
ModuleAssertDynamicPredicateToBack,
|
||||||
CheckCutPoint,
|
CheckCutPoint,
|
||||||
CopyToLiftedHeap,
|
CopyToLiftedHeap,
|
||||||
DeleteAttribute,
|
DeleteAttribute,
|
||||||
@@ -155,6 +158,7 @@ pub enum SystemClauseType {
|
|||||||
GetBValue,
|
GetBValue,
|
||||||
GetClause,
|
GetClause,
|
||||||
GetCurrentPredicateList,
|
GetCurrentPredicateList,
|
||||||
|
GetModuleClause,
|
||||||
GetLiftedHeapFromOffset,
|
GetLiftedHeapFromOffset,
|
||||||
GetLiftedHeapFromOffsetDiff,
|
GetLiftedHeapFromOffsetDiff,
|
||||||
GetSCCCleaner,
|
GetSCCCleaner,
|
||||||
@@ -163,6 +167,7 @@ pub enum SystemClauseType {
|
|||||||
InstallInferenceCounter,
|
InstallInferenceCounter,
|
||||||
LiftedHeapLength,
|
LiftedHeapLength,
|
||||||
ModuleOf,
|
ModuleOf,
|
||||||
|
ModuleRetractClause,
|
||||||
NoSuchPredicate,
|
NoSuchPredicate,
|
||||||
RedoAttrVarBindings,
|
RedoAttrVarBindings,
|
||||||
RemoveCallPolicyCheck,
|
RemoveCallPolicyCheck,
|
||||||
@@ -197,8 +202,11 @@ impl SystemClauseType {
|
|||||||
pub fn name(&self) -> ClauseName {
|
pub fn name(&self) -> ClauseName {
|
||||||
match self {
|
match self {
|
||||||
&SystemClauseType::AbolishClause => clause_name!("$abolish_clause"),
|
&SystemClauseType::AbolishClause => clause_name!("$abolish_clause"),
|
||||||
&SystemClauseType::AssertDynamicPredicateToBack => clause_name!("$asserta"),
|
&SystemClauseType::AbolishModuleClause => clause_name!("$abolish_module_clause"),
|
||||||
&SystemClauseType::AssertDynamicPredicateToFront => clause_name!("$assertz"),
|
&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::CheckCutPoint => clause_name!("$check_cp"),
|
||||||
&SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"),
|
&SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"),
|
||||||
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
|
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
|
||||||
@@ -219,6 +227,7 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::GetBValue => clause_name!("$get_b_value"),
|
&SystemClauseType::GetBValue => clause_name!("$get_b_value"),
|
||||||
&SystemClauseType::GetClause => clause_name!("$get_clause"),
|
&SystemClauseType::GetClause => clause_name!("$get_clause"),
|
||||||
&SystemClauseType::GetDoubleQuotes => clause_name!("$get_double_quotes"),
|
&SystemClauseType::GetDoubleQuotes => clause_name!("$get_double_quotes"),
|
||||||
|
&SystemClauseType::GetModuleClause => clause_name!("$get_module_clause"),
|
||||||
&SystemClauseType::GetSCCCleaner => clause_name!("$get_scc_cleaner"),
|
&SystemClauseType::GetSCCCleaner => clause_name!("$get_scc_cleaner"),
|
||||||
&SystemClauseType::HeadIsDynamic => clause_name!("$head_is_dynamic"),
|
&SystemClauseType::HeadIsDynamic => clause_name!("$head_is_dynamic"),
|
||||||
&SystemClauseType::InstallSCCCleaner => clause_name!("$install_scc_cleaner"),
|
&SystemClauseType::InstallSCCCleaner => clause_name!("$install_scc_cleaner"),
|
||||||
@@ -239,6 +248,7 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::GetCutPoint => clause_name!("$get_cp"),
|
&SystemClauseType::GetCutPoint => clause_name!("$get_cp"),
|
||||||
&SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"),
|
&SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"),
|
||||||
&SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"),
|
&SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"),
|
||||||
|
&SystemClauseType::ModuleRetractClause => clause_name!("$module_retract_clause"),
|
||||||
&SystemClauseType::RetractClause => clause_name!("$retract_clause"),
|
&SystemClauseType::RetractClause => clause_name!("$retract_clause"),
|
||||||
&SystemClauseType::ResetBlock => clause_name!("$reset_block"),
|
&SystemClauseType::ResetBlock => clause_name!("$reset_block"),
|
||||||
&SystemClauseType::ReturnFromAttributeGoals => clause_name!("$return_from_attribute_goals"),
|
&SystemClauseType::ReturnFromAttributeGoals => clause_name!("$return_from_attribute_goals"),
|
||||||
@@ -258,6 +268,9 @@ 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) {
|
||||||
("$abolish_clause", 2) => Some(SystemClauseType::AbolishClause),
|
("$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),
|
("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront),
|
||||||
("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack),
|
("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack),
|
||||||
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
|
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
|
||||||
@@ -274,6 +287,7 @@ impl SystemClauseType {
|
|||||||
("$get_attr_list", 2) => Some(SystemClauseType::GetAttributedVariableList),
|
("$get_attr_list", 2) => Some(SystemClauseType::GetAttributedVariableList),
|
||||||
("$get_b_value", 1) => Some(SystemClauseType::GetBValue),
|
("$get_b_value", 1) => Some(SystemClauseType::GetBValue),
|
||||||
("$get_clause", 2) => Some(SystemClauseType::GetClause),
|
("$get_clause", 2) => Some(SystemClauseType::GetClause),
|
||||||
|
("$get_module_clause", 3) => Some(SystemClauseType::GetModuleClause),
|
||||||
("$get_current_predicate_list", 1) => Some(SystemClauseType::GetCurrentPredicateList),
|
("$get_current_predicate_list", 1) => Some(SystemClauseType::GetCurrentPredicateList),
|
||||||
("$get_lh_from_offset", 2) => Some(SystemClauseType::GetLiftedHeapFromOffset),
|
("$get_lh_from_offset", 2) => Some(SystemClauseType::GetLiftedHeapFromOffset),
|
||||||
("$get_lh_from_offset_diff", 3) => Some(SystemClauseType::GetLiftedHeapFromOffsetDiff),
|
("$get_lh_from_offset_diff", 3) => Some(SystemClauseType::GetLiftedHeapFromOffsetDiff),
|
||||||
@@ -284,6 +298,7 @@ impl SystemClauseType {
|
|||||||
("$install_inference_counter", 3) => Some(SystemClauseType::InstallInferenceCounter),
|
("$install_inference_counter", 3) => Some(SystemClauseType::InstallInferenceCounter),
|
||||||
("$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),
|
||||||
("$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),
|
||||||
|
|||||||
@@ -459,15 +459,30 @@ setof(Template, Goal, Solution) :-
|
|||||||
|
|
||||||
'$clause_body_is_valid'(B) :-
|
'$clause_body_is_valid'(B) :-
|
||||||
( var(B) -> true
|
( 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))
|
||||||
)
|
)
|
||||||
; 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) :-
|
clause(H, B) :-
|
||||||
( 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))
|
||||||
|
; 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' fails if H is not callable.
|
||||||
; '$no_such_predicate'(H) -> '$fail'
|
; '$no_such_predicate'(H) -> '$fail'
|
||||||
; '$head_is_dynamic'(H) -> '$clause_body_is_valid'(B),
|
; '$head_is_dynamic'(H) -> '$clause_body_is_valid'(B),
|
||||||
@@ -478,16 +493,35 @@ clause(H, B) :-
|
|||||||
; throw(error(type_error(callable, H), clause/2))
|
; 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) :-
|
call_asserta(Head, Body, Name, Arity) :-
|
||||||
'$clause_body_is_valid'(Body),
|
'$clause_body_is_valid'(Body),
|
||||||
functor(VarHead, Name, Arity),
|
functor(VarHead, Name, Arity),
|
||||||
findall((VarHead :- VarBody), clause(VarHead, VarBody), Clauses),
|
findall((VarHead :- VarBody), clause(VarHead, VarBody), Clauses),
|
||||||
'$asserta'((Head :- Body), Clauses, Name, Arity).
|
'$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) :-
|
asserta_clause(Head, Body) :-
|
||||||
( 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 \== '.' ->
|
||||||
( '$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)
|
; '$head_is_dynamic'(Head) -> call_asserta(Head, Body, Name, Arity)
|
||||||
; throw(error(permission_error(modify, static_procedure, Name/Arity), asserta/1))
|
; throw(error(permission_error(modify, static_procedure, Name/Arity), asserta/1))
|
||||||
)
|
)
|
||||||
@@ -499,16 +533,35 @@ asserta(Clause) :-
|
|||||||
; Clause = (Head :- Body) -> asserta_clause(Head, Body)
|
; 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) :-
|
call_assertz(Head, Body, Name, Arity) :-
|
||||||
'$clause_body_is_valid'(Body),
|
'$clause_body_is_valid'(Body),
|
||||||
functor(VarHead, Name, Arity),
|
functor(VarHead, Name, Arity),
|
||||||
findall((VarHead :- VarBody), clause(VarHead, VarBody), Clauses),
|
findall((VarHead :- VarBody), clause(VarHead, VarBody), Clauses),
|
||||||
'$assertz'((Head :- Body), Clauses, Name, Arity).
|
'$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) :-
|
assertz_clause(Head, Body) :-
|
||||||
( 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 \== '.' ->
|
||||||
( '$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)
|
; '$head_is_dynamic'(Head) -> call_assertz(Head, Body, Name, Arity)
|
||||||
; throw(error(permission_error(modify, static_procedure, Name/Arity), assertz/1))
|
; 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),
|
findall((Head :- Body), clause(Head, Body), Clauses),
|
||||||
retract_clauses(Clauses, Head, Body, Name, Arity).
|
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) :-
|
retract_clause(Head, Body) :-
|
||||||
( 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_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'
|
; '$no_such_predicate'(Head) -> '$fail'
|
||||||
; throw(error(permission_error(modify, static_procedure, Name/Arity), retract/1))
|
; throw(error(permission_error(modify, static_procedure, Name/Arity), retract/1))
|
||||||
)
|
)
|
||||||
@@ -556,8 +637,27 @@ retract(Clause) :-
|
|||||||
; Clause = (Head :- Body) -> retract_clause(Head, Body)
|
; 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) :-
|
abolish(Pred) :-
|
||||||
( var(Pred) -> throw(error(instantiation_error), abolish/1)
|
( var(Pred) -> throw(error(instantiation_error), abolish/1)
|
||||||
|
; Pred = Module:InnerPred -> module_abolish(InnerPred, Module)
|
||||||
; Pred = Name/Arity ->
|
; Pred = Name/Arity ->
|
||||||
( var(Name) -> throw(error(instantiation_error, abolish/1))
|
( var(Name) -> throw(error(instantiation_error, abolish/1))
|
||||||
; var(Arity) -> 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)
|
; 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) ->
|
||||||
( '$no_such_predicate'(Head) -> '$abolish_clause'(Name, Arity)
|
( '$no_such_predicate'(Head) -> true
|
||||||
; '$head_is_dynamic'(Head) -> '$abolish_clause'(Name, Arity)
|
; '$head_is_dynamic'(Head) -> '$abolish_clause'(Name, Arity)
|
||||||
; throw(error(permission_error(modify, static_procedure, Pred), abolish/1))
|
; throw(error(permission_error(modify, static_procedure, Pred), abolish/1))
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -72,6 +72,35 @@ impl Machine {
|
|||||||
self.indices.remove_code_index((name, arity));
|
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,
|
fn handle_eval_result_from_dynamic_compile(&mut self, pred_str: String, name: ClauseName,
|
||||||
src: 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 stub = MachineError::functor_stub(place.predicate_name(), 1);
|
||||||
let pred_str = match self.machine_st.try_from_list(temp_v!(2), stub) {
|
let pred_str = match self.machine_st.try_from_list(temp_v!(2), stub) {
|
||||||
Ok(addrs) => {
|
Ok(addrs) => {
|
||||||
@@ -110,6 +138,59 @@ impl Machine {
|
|||||||
self.handle_eval_result_from_dynamic_compile(pred_str, name, place.predicate_name());
|
self.handle_eval_result_from_dynamic_compile(pred_str, name, place.predicate_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)) {
|
||||||
|
Addr::Con(Constant::Number(Number::Integer(n))) => n.to_usize().unwrap(),
|
||||||
|
_ => unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
|
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)
|
fn retract_from_dynamic_predicate(&mut self)
|
||||||
{
|
{
|
||||||
let index = self.machine_st[temp_v!(3)].clone();
|
let index = self.machine_st[temp_v!(3)].clone();
|
||||||
@@ -118,9 +199,14 @@ impl Machine {
|
|||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
let stub = MachineError::functor_stub(clause_name!("retract"), 1);
|
|
||||||
let (name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2));
|
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) {
|
let pred_str = match self.machine_st.try_from_list(temp_v!(4), stub) {
|
||||||
Ok(addrs) => {
|
Ok(addrs) => {
|
||||||
let mut addrs = VecDeque::from(addrs);
|
let mut addrs = VecDeque::from(addrs);
|
||||||
@@ -148,6 +234,12 @@ impl Machine {
|
|||||||
self.abolish_dynamic_clause(temp_v!(1), temp_v!(2)),
|
self.abolish_dynamic_clause(temp_v!(1), temp_v!(2)),
|
||||||
DynamicTransactionType::Assert(place) =>
|
DynamicTransactionType::Assert(place) =>
|
||||||
self.recompile_dynamic_predicate(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 =>
|
DynamicTransactionType::Retract =>
|
||||||
self.retract_from_dynamic_predicate()
|
self.retract_from_dynamic_predicate()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -234,6 +234,9 @@ impl DynamicAssertPlace {
|
|||||||
pub enum DynamicTransactionType {
|
pub enum DynamicTransactionType {
|
||||||
Abolish,
|
Abolish,
|
||||||
Assert(DynamicAssertPlace),
|
Assert(DynamicAssertPlace),
|
||||||
|
ModuleAbolish,
|
||||||
|
ModuleAssert(DynamicAssertPlace),
|
||||||
|
ModuleRetract,
|
||||||
Retract // dynamic index of the clause to remove.
|
Retract // dynamic index of the clause to remove.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -228,6 +228,13 @@ impl MachineState {
|
|||||||
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
},
|
},
|
||||||
|
&SystemClauseType::AbolishModuleClause => {
|
||||||
|
let p = self.cp;
|
||||||
|
let trans_type = DynamicTransactionType::ModuleAbolish;
|
||||||
|
|
||||||
|
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||||
|
return Ok(());
|
||||||
|
},
|
||||||
&SystemClauseType::AssertDynamicPredicateToFront => {
|
&SystemClauseType::AssertDynamicPredicateToFront => {
|
||||||
let p = self.cp;
|
let p = self.cp;
|
||||||
let trans_type = DynamicTransactionType::Assert(DynamicAssertPlace::Front);
|
let trans_type = DynamicTransactionType::Assert(DynamicAssertPlace::Front);
|
||||||
@@ -242,6 +249,20 @@ impl MachineState {
|
|||||||
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||||
return Ok(());
|
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 => {
|
&SystemClauseType::LiftedHeapLength => {
|
||||||
let a1 = self[temp_v!(1)].clone();
|
let a1 = self[temp_v!(1)].clone();
|
||||||
let lh_len = Addr::Con(Constant::Usize(self.lifted_heap.len()));
|
let lh_len = Addr::Con(Constant::Usize(self.lifted_heap.len()));
|
||||||
@@ -256,6 +277,44 @@ impl MachineState {
|
|||||||
_ => self.fail = true
|
_ => 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 => {
|
&SystemClauseType::HeadIsDynamic => {
|
||||||
let head = self[temp_v!(1)].clone();
|
let head = self[temp_v!(1)].clone();
|
||||||
|
|
||||||
@@ -682,6 +741,13 @@ impl MachineState {
|
|||||||
None => panic!("remove_inference_counter: requires \\
|
None => panic!("remove_inference_counter: requires \\
|
||||||
CWILCallPolicy.")
|
CWILCallPolicy.")
|
||||||
},
|
},
|
||||||
|
&SystemClauseType::ModuleRetractClause => {
|
||||||
|
let p = self.cp;
|
||||||
|
let trans_type = DynamicTransactionType::ModuleRetract;
|
||||||
|
|
||||||
|
self.p = CodePtr::DynamicTransaction(trans_type, p);
|
||||||
|
return Ok(());
|
||||||
|
},
|
||||||
&SystemClauseType::RetractClause => {
|
&SystemClauseType::RetractClause => {
|
||||||
let p = self.cp;
|
let p = self.cp;
|
||||||
let trans_type = DynamicTransactionType::Retract;
|
let trans_type = DynamicTransactionType::Retract;
|
||||||
|
|||||||
Reference in New Issue
Block a user