1% Operations on the Acc and Pass data structures:
    2
    3:- ['generic-util.pl'].    4:- ['special-util.pl'].    5
    6% Create the Acc and Pass data structures:
    7% Acc contains terms of the form acc(A,LeftA,RightA) where A is the name of an
    8% accumulator, and RightA and LeftA are the accumulating parameters.
    9% Pass contains terms of the form pass(A,Arg) where A is the name of a passed
   10% argument, and Arg is the argument.
   11'_create_acc_pass'([], _, _, [], []).
   12'_create_acc_pass'([A|AList], Index, TGoal, [acc(A,LeftA,RightA)|Acc], Pass) :-
   13    '_is_acc'(A), !,
   14    Index1 is Index+1,
   15    arg(Index1, TGoal, LeftA),
   16    Index2 is Index+2,
   17    arg(Index2, TGoal, RightA),
   18    '_create_acc_pass'(AList, Index2, TGoal, Acc, Pass).
   19'_create_acc_pass'([A|AList], Index, TGoal, Acc, [pass(A,Arg)|Pass]) :-
   20    '_is_pass'(A), !,
   21    Index1 is Index+1,
   22    arg(Index1, TGoal, Arg),
   23    '_create_acc_pass'(AList, Index1, TGoal, Acc, Pass).
   24'_create_acc_pass'([A|_AList], _Index, _TGoal, _Acc, _Pass) :-
   25    \+'_is_acc'(A),
   26    \+'_is_pass'(A),
   27    print_message(error,not_a_hidden_param(A)).
   28
   29
   30% Use the Acc and Pass data structures to create the arguments of a body goal:
   31% Add the hidden parameters named in GList to the goal.
   32'_use_acc_pass'([], _, _, Acc, Acc, _).
   33% 1a. The accumulator A is used in the head:
   34'_use_acc_pass'([A|GList], Index, TGoal, Acc, NewAcc, Pass) :-
   35    '_replace_acc'(A, LeftA, RightA, MidA, RightA, Acc, MidAcc), !,
   36    Index1 is Index+1,
   37    arg(Index1, TGoal, LeftA),
   38    Index2 is Index+2,
   39    arg(Index2, TGoal, MidA),
   40    '_use_acc_pass'(GList, Index2, TGoal, MidAcc, NewAcc, Pass).
   41% 1b. The accumulator A is not used in the head:
   42'_use_acc_pass'([A|GList], Index, TGoal, Acc, NewAcc, Pass) :-
   43    '_acc_info'(A, LStart, RStart), !,
   44    Index1 is Index+1,
   45    arg(Index1, TGoal, LStart),
   46    Index2 is Index+2,
   47    arg(Index2, TGoal, RStart),
   48    '_use_acc_pass'(GList, Index2, TGoal, Acc, NewAcc, Pass).
   49% 2a. The passed argument A is used in the head:
   50'_use_acc_pass'([A|GList], Index, TGoal, Acc, NewAcc, Pass) :-
   51    '_is_pass'(A),
   52    member(pass(A,Arg), Pass), !,
   53    Index1 is Index+1,
   54    arg(Index1, TGoal, Arg),
   55    '_use_acc_pass'(GList, Index1, TGoal, Acc, NewAcc, Pass).
   56% 2b. The passed argument A is not used in the head:
   57'_use_acc_pass'([A|GList], Index, TGoal, Acc, NewAcc, Pass) :-
   58    '_pass_info'(A, AStart), !,
   59    Index1 is Index+1,
   60    arg(Index1, TGoal, AStart),
   61    '_use_acc_pass'(GList, Index1, TGoal, Acc, NewAcc, Pass).
   62% 3. Defaulty case when A does not exist:
   63'_use_acc_pass'([A|_GList], _Index, _TGoal, Acc, Acc, _Pass) :-
   64    print_message(error,not_a_hidden_param(A)).
   65
   66% Finish the Acc data structure:
   67% Link its Left and Right accumulation variables together in pairs:
   68'_finish_acc'([]).
   69'_finish_acc'([acc(_,Link,Link)|Acc]) :- '_finish_acc'(Acc).
   70
   71% Replace elements in the Acc data structure:
   72% Succeeds iff replacement is successful.
   73'_replace_acc'(A, L1, R1, L2, R2, Acc, NewAcc) :-
   74    member(acc(A,L1,R1), Acc), !,
   75    '_replace'(acc(A,_,_), acc(A,L2,R2), Acc, NewAcc).
   76
   77% Combine two accumulator lists ('or'ing their values)
   78'_merge_acc'([], [], G1, G1, [], G2, G2, []) :- !.
   79'_merge_acc'([acc(Acc,OL,R)|Accs], [acc(Acc,L1,R)|Accs1], G1, NG1,
   80         [acc(Acc,L2,R)|Accs2], G2, NG2, [acc(Acc,NL,R)|NewAccs]) :- !,
   81    ( ( OL == L1, OL \== L2 ) ->
   82      MG1 = (G1,L1=L2), MG2 = G2, NL = L2
   83        ; ( OL == L2, OL \== L1 ) ->
   84      MG2 = (G2,L2=L1), MG1 = G1, NL = L1
   85        ; MG1 = G1, MG2 = G2, L1 = L2, L2 = NL ),
   86    '_merge_acc'(Accs, Accs1, MG1, NG1, Accs2, MG2, NG2, NewAccs)