:- export call_all/1, scanVars/3, init_basic/0, toggle_mode/0, trmode/1.
:- export delete_all/1, deletelist/1, getlist/3.
:- export on_backtracking/1, insertbase/1, deletebase/1, inserting/1, deleting/1.
:- import assert/1, retract/1 from assert.
:- import create/2, destroy/2 from keys_basics1.
init_basic :- assert(trmode(compile)).

toggle_mode :-
	retract(trmode(compile)),
	assert(trmode(database)).
toggle_mode :-
	retract(trmode(database)),
	assert(trmode(compile)).

call_all([]).
call_all([Pred|Rest]) :-
	call(Pred),
	call_all(Rest).

delete_all(Value) :-
	getlist(Value,Value,List),
	deletelist(List).
deletelist([]).
deletelist([Pred|Rest]) :-
	deletebase(Pred),
	deletelist(Rest).

% weak assert and retract X with backtracking.
%
/*
inserting(X) :-
	assert(X), on_backtracking(retract(X)).
deleting(X) :-
	call(X) ->
		( retract(X), on_backtracking(asserta(X)) )
	;
	true.
*/
inserting(tr) :- create(tr,[]).
deleting(tr) :- destroy(tr,[]).
insertbase(X) :- assert(X), !, on_backtracking((retract(X))).
deletebase(X) :- retract(X), !, on_backtracking((asserta(X))).

on_backtracking(_).
on_backtracking(X) :-
	call(X), !, fail.

% Same as built-in predicate findall except that it is always true.
%
getlist(Fun1,Fun2,List) :-
	(
	setof(Fun1,Fun2,List) -> true
	;
	List = []).

scanVars([],X,X).
scanVars([X|L],InList,OutList) :-
	var(X),
	checkrepeat(X,InList,InList,NewList),
	scanVars(L,NewList,OutList).
scanVars([X|L],InList,OutList) :-
	atomic(X), nonvar(X),
	scanVars(L,InList,OutList).
scanVars([X|L],InList,OutList) :-
	not atomic(X), 
	X =.. [_|MoreArgs],
	scanVars(MoreArgs,InList,NewList),
	scanVars(L,NewList,OutList).

checkrepeat(X,[],List,[Y|List]) :-
	Y = X.

checkrepeat(X,[Y|_],List,List) :-
	X == Y.
checkrepeat(X,[Y|L],List,List2) :-
	X \== Y, 
	checkrepeat(X,L,List,List2).

