% File 'meta_assert.pl'
%----
:- ensure_loaded(typeops_meta).

% meta programming
% examples for typing of the predicates
% assert/1, retract/1, retractall/1

 
%+++++++++++++++++++++++++++++ type definitions +++++++++++++++++++++++ 

:- import_pred(prolog_meta,'='/2).
:- import_pred(prolog_meta,':-'/2).
:- import_pred(prolog_meta,':-'/1).
:- import_pred(prolog_meta,'?-'/1).
:- import_pred(prolog_meta,','/2).
:- import_pred(prolog_meta,';'/2).
:- import_pred(prolog_meta,'->'/2).
:- import_pred(prolog_meta,callable/1).
:- import_pred(prolog_meta,functor/3).

:- import_type(prolog_meta).


%+++++++++++++++++++++++++++++ predicates  +++++++++++++++++++++++ 

:- pred assert(meta((trmFull of mclause))).

:- pred assert_wrong1(goal).	         % includes "meta((trmFull of mpred))"
assert_wrong1(X) :- assert(X).
:- pred assert_wrong2(meta).
assert_wrong2(X) :- assert(X).	         % ill-typed (not meta-generic)
:- pred assert_wrong3(meta(mpred)).
assert_wrong3(X) :- assert(X).           % ill-typed
:- pred assert_wrong4(meta(trmFull)).
assert_wrong4(X) :- assert(X).           % ill-typed (not meta-generic)
:- pred assert_wrong5(meta((trmFull of mpred))).
assert_wrong5(X) :- assert(X).           % ok because mpred is part of mclause 

:- pred assert_clause(goal).
assert_clause(A) :- callable(A), functor(A,':-',2), assert(A).

:- pred retract(meta((trmFull of mclause))).
:- pred retractall(meta((trmFull of mpred))).   % needed: mliteral

:- pred hello.
hello.

:- pred test(top).
test(_).

%+++++++++++++++++++++++++++++ tests +++++++++++++++++++++++++++++ 

?- assert(A). 
?- A = hello, assert(A). 
?- A = test(t), assert(A).

?- assert(test(k)).
?- assert((test(rk) :- hello)).

?- retract((test(rk) :- hello)).
?- retractall(test(_)).
?- retract(hello).

?- retract((:- hello)).               % ill-typed
?- retractall((test(rk) :- hello)).   % ok !!!  needed: mliteral

%----------

?- assert(hello).

?- assert(A), A = test.	     % ill-typed, because "test" is only a functor 

?- assert((:- hello)).	     % ill-typed, no directives may be asserted
?- assert((?- hello)).	     % ill-typed, no queries may be asserted
?- assert((hello, hello)).   % ill-typed, no conjunction may be asserted
?- assert((hello; hello)).   % ill-typed, no disjunction may be asserted
?- assert((hello -> hello)). % ill-typed, no if-then construct may be asserted

%----------

?- assert_wrong1(hello).

?- assert_wrong1(A), A = test.         % ok !!! A*simpleterm

?- assert_wrong1((:- hello)).	       % ok !!!
?- assert_wrong1((?- hello)).	       % ok !!!
?- assert_wrong1((hello, hello)).      % ok !!!
?- assert_wrong1((hello; hello)).      % ok !!!
?- assert_wrong1((hello -> hello)).    % ok !!!

%----------

?- assert_wrong2(hello).             % ok !!!  (meta21)

?- assert_wrong2(A), A = test.	% ok !!! A*meta((trmName([top])of mpred))

?- assert_wrong2((:- hello)).	     % ok !!!  (meta21)
?- assert_wrong2((?- hello)).	     % ok !!!  (meta21)
?- assert_wrong2((hello, hello)).    % ok !!!  (meta21)
?- assert_wrong2((hello; hello)).    % ok !!!  (meta21)
?- assert_wrong2((hello -> hello)).  % ok !!!  (meta21)

%----------

?- assert_wrong3(hello).

?- assert_wrong3(A), A = test.	% ok !!! A*meta((trmName([top])of mpred)) 

?- assert_wrong3((:- hello)).	     % ok !!!
?- assert_wrong3((?- hello)).	     % ok !!!
?- assert_wrong3((hello, hello)).    % ok !!!
?- assert_wrong3((hello; hello)).    % ok !!!
?- assert_wrong3((hello -> hello)).  % ok !!!

%----------

?- assert_wrong4(hello).             % ok !!!  (meta21)

?- assert_wrong4(A), A = test.	% ill-typed, because test is no trmFull

?- assert_wrong4((:- hello)).	     % ok !!!  (meta21)
?- assert_wrong4((?- hello)).	     % ok !!!  (meta21)
?- assert_wrong4((hello, hello)).    % ok !!!  (meta21)
?- assert_wrong4((hello; hello)).    % ok !!!  (meta21)
?- assert_wrong4((hello -> hello)).  % ok !!!  (meta21)

%----------

?- assert_wrong5(hello).

?- assert_wrong5(A), A = test.	% ill-typed, because test is no trmFull

?- assert_wrong5((:- hello)).	     % ok !!!
?- assert_wrong5((?- hello)).	     % ok !!!
?- assert_wrong5((hello, hello)).    % ok !!!
?- assert_wrong5((hello; hello)).    % ok !!!
?- assert_wrong5((hello -> hello)).  % ok !!!





