:- export bulkins/2, bulkdel/1, assign/2, simple_assign/2.
:- import insertnewdbrule/1, do_insert/1, do_delete/1
	  from tr_basics1.
:- import inserting/1, deleting/1, getlist/3 from basic_funs1.

:- op(900,xfy,[assign]).

% bulk insertion (always true, i.e. weak)
%
bulkins(FromFun,ToFun) :- 
        (
          predicate_property(ToFun,(dynamic)) -> true
          ;
          insertnewdbrule(ToFun), !
	),
	do_bulkinsert(FromFun,ToFun).

do_bulkinsert(FromFun,ToFun) :-
	deleting(tr),
	getlist(ToFun,FromFun,List),
	inserting(tr),
	do_insertlist(List).

% weak insert all predicates in the list
do_insertlist([]).
do_insertlist([ToDBFun|Rest]) :-
	do_weakinsert(ToDBFun),
	do_insertlist(Rest).

% weak insert, i.e. it succeeds if Pred is already in the database
do_weakinsert(Pred) :-
	call(database(Pred)).
do_weakinsert(Pred) :-
	do_insert(Pred).

% bulk deletion (always true)
%
bulkdel(X) :-
        (
          predicate_property(X,(dynamic)) -> true
          ;
          insertnewdbrule(X), !
        ),
	bulk_erase(X).

% Unlike bulkins, there is only one term for bulk_erase, so database(Term)
% works the same as removing tr flag first.
bulk_erase(Term) :-
	getlist(Term,database(Term),List),
	do_deletelist(List).

% Delete all predicate in the list.
% Note: We can use strong delete because these predicates should already be
% in the database. 
do_deletelist([]).
do_deletelist([Pred|Rest]) :-
	do_delete(Pred),
	do_deletelist(Rest).


% assignments
% For example,  assign q(X,Y) from p(X,Y)
assign(OutPred,TestPred) :-
	(
	  predicate_property(OutPred,(dynamic)) -> simple_assign(OutPred,TestPred)
	  ;
	  insertnewdbrule(OutPred),
	  simple_assign(OutPred,TestPred)
	).

% bulk delete OutPred first and then bulk insert from TestPred to OutPred
simple_assign(OutPred,TestPred) :-
	deleting(tr),
	getlist(OutPred,TestPred,BufferList), % copy output to buffer
	inserting(tr), 
	bulk_erase(OutPred),
	do_insertlist(BufferList). % copy into output 

