515 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Prolog
		
	
	
	
	
	
			
		
		
	
	
			515 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Prolog
		
	
	
	
	
	
s%   File   : compile_foreach.pl
 | 
						|
%   Author : Neng-Fa Zhou
 | 
						|
%   Updated: June 2009, updated Dec. 2009, updated Sep. 2010
 | 
						|
%   Purpose: compile away foreach
 | 
						|
/*  compile_foreach(Cls,NCls): NCls is a list of clauses obtained by
 | 
						|
    compiling away foreach calls in Cls. The new predicate introduced
 | 
						|
    for a foreach is named p_#_i where p is the name of the predicate
 | 
						|
    in which the foreach occurs and i is a unique integer.
 | 
						|
*/
 | 
						|
 | 
						|
:- yap_flag(unknown,error).
 | 
						|
:- ensure_loaded(actionrules).
 | 
						|
:- op(560,xfx,[..,to,downto]).
 | 
						|
:- op(700,xfx,[subset,notin,in,@=]).
 | 
						|
 | 
						|
/*
 | 
						|
test:-
 | 
						|
    Cl1=(test1(L):-foreach(I in L, write(I))),
 | 
						|
    Cl2=(test2(L):-foreach(I in L, ac(S,0), S^1 is S^0+I)),
 | 
						|
    Cl3=(test3(T):-functor(T,_,N),foreach(I in 1..N, [Ti],ac(S,0), (arg(I,T,Ti),S^1 is S^0+Ti))),
 | 
						|
    Cl4=(test4(L):-foreach(I in L, ac1(C,[]), C^0=[I|C^1])),
 | 
						|
    Cl5=(test5:-foreach(I in [1,2], J in [a,b], ac(L,[]),L^1=[(I,J)|L^0]),writeln(L),fail),
 | 
						|
    Cl6=(test6:-foreach(I in [1,2], J in [a,b], ac1(L,[]),L^0=[(I,J)|L^1]),writeln(L),fail),
 | 
						|
    Cl7=(test7(L1,L2):-foreach(X in L1, (write(X),foreach(Y in L2, writeln((X,Y)))))),
 | 
						|
    Cl8=(p(D1,D3,IN,OUT):-
 | 
						|
	 foreach(E in D3,
 | 
						|
		 [INi,OUTi],
 | 
						|
		 (asp_lib_clone_rel(IN,OUT,INi,OUTi),
 | 
						|
		  (foreach(X in D1, Y in D1,(not diagY(X,Y,E)->asp_lib_add_tuples(OUTi,X,Y);true)),
 | 
						|
		   asp_lib_card_unique(2,INi,OUTi))))),
 | 
						|
    compile_foreach([Cl1,Cl2,Cl3,Cl4,Cl5,Cl6,Cl7,Cl8],NCls),   	 
 | 
						|
    (member(NCl,NCls), portray_clause(NCl),fail;true).
 | 
						|
*/
 | 
						|
compile_foreach(File):-
 | 
						|
    $getclauses_read_file(File,'$t.t.t$',0,_Singleton,_Redef,Cls,[]),
 | 
						|
    compile_foreach(Cls,NCls),
 | 
						|
    foreach(NCl in NCls, portray_clause(NCl)).
 | 
						|
 | 
						|
compile_foreach(Cls,NCls):-
 | 
						|
    new_hashtable(ProgTab),
 | 
						|
    compile_foreach(Cls,NCls,NCls1,ProgTab,0),
 | 
						|
    hashtable_values_to_list(ProgTab,Prog),
 | 
						|
    retrieve_new_cls(Prog,NCls1).
 | 
						|
 | 
						|
retrieve_new_cls([],[]).
 | 
						|
retrieve_new_cls([pred(_,_,_,_,_,Cls)|Preds],NCls):-
 | 
						|
    append_diff(Cls,NCls,NCls1),
 | 
						|
    retrieve_new_cls(Preds,NCls1).
 | 
						|
 | 
						|
compile_foreach([],NCls,NClsR,_ProgTab,_DumNo) => NCls=NClsR.
 | 
						|
compile_foreach([Cl|Cls],NCls,NClsR,ProgTab,DumNo) =>
 | 
						|
    NCls=[NCl|NCls1],
 | 
						|
    expand_constr(Cl,NCl,ProgTab,DumNo,DumNo1),
 | 
						|
    compile_foreach(Cls,NCls1,NClsR,ProgTab,DumNo1).
 | 
						|
 | 
						|
cl_contains_foreach((delay (_H:-(_G : B)))) =>
 | 
						|
    goal_contains_foreach(B,Flag),nonvar(Flag).
 | 
						|
cl_contains_foreach((_H:-_G : B)) =>
 | 
						|
    goal_contains_foreach(B,Flag),nonvar(Flag).
 | 
						|
cl_contains_foreach((_H:-_G ? B)) => 
 | 
						|
    goal_contains_foreach(B,Flag),nonvar(Flag).    
 | 
						|
cl_contains_foreach((_H:-B)) => 
 | 
						|
    goal_contains_foreach(B,Flag),nonvar(Flag).    
 | 
						|
 | 
						|
goal_contains_foreach(G):-
 | 
						|
    goal_contains_foreach(G,Flag),
 | 
						|
    nonvar(Flag).
 | 
						|
 | 
						|
goal_contains_foreach(_G,Flag), nonvar(Flag) => true.
 | 
						|
goal_contains_foreach(G,_Flag), var(G) => true.
 | 
						|
goal_contains_foreach((_G : B),Flag) =>
 | 
						|
    goal_contains_foreach(B,Flag).
 | 
						|
goal_contains_foreach((_G ? B),Flag) =>
 | 
						|
    goal_contains_foreach(B,Flag).
 | 
						|
goal_contains_foreach((A,B),Flag) =>
 | 
						|
    goal_contains_foreach(A,Flag),
 | 
						|
    goal_contains_foreach(B,Flag).
 | 
						|
goal_contains_foreach((A -> B ; C),Flag) =>
 | 
						|
    goal_contains_foreach(A,Flag),
 | 
						|
    goal_contains_foreach(B,Flag),
 | 
						|
    goal_contains_foreach(C,Flag).
 | 
						|
goal_contains_foreach((A;B),Flag) =>
 | 
						|
    goal_contains_foreach(A,Flag),
 | 
						|
    goal_contains_foreach(B,Flag).
 | 
						|
goal_contains_foreach(not(A),Flag) =>
 | 
						|
    goal_contains_foreach(A,Flag).
 | 
						|
goal_contains_foreach(\+(A),Flag) =>
 | 
						|
    goal_contains_foreach(A,Flag).
 | 
						|
goal_contains_foreach(Lhs @= Rhs,Flag) =>
 | 
						|
    exp_contains_list_comp(Lhs,Flag),
 | 
						|
    exp_contains_list_comp(Rhs,Flag).
 | 
						|
goal_contains_foreach(E1#=E2,Flag) =>
 | 
						|
    exp_contains_list_comp(E1,Flag),
 | 
						|
    exp_contains_list_comp(E2,Flag).
 | 
						|
goal_contains_foreach(E1#\=E2,Flag) => 
 | 
						|
    exp_contains_list_comp(E1,Flag),
 | 
						|
    exp_contains_list_comp(E2,Flag).
 | 
						|
goal_contains_foreach(E1#<E2,Flag) => 
 | 
						|
    exp_contains_list_comp(E1,Flag),
 | 
						|
    exp_contains_list_comp(E2,Flag).
 | 
						|
goal_contains_foreach(E1#=<E2,Flag) => 
 | 
						|
    exp_contains_list_comp(E1,Flag),
 | 
						|
    exp_contains_list_comp(E2,Flag).
 | 
						|
goal_contains_foreach(E1#>E2,Flag) => 
 | 
						|
    exp_contains_list_comp(E1,Flag),
 | 
						|
    exp_contains_list_comp(E2,Flag).
 | 
						|
goal_contains_foreach(E1#>=E2,Flag) => 
 | 
						|
    exp_contains_list_comp(E1,Flag),
 | 
						|
    exp_contains_list_comp(E2,Flag).
 | 
						|
goal_contains_foreach(G,Flag), functor(G,foreach,_) => Flag=1.
 | 
						|
goal_contains_foreach(_G,_Flag) => true.
 | 
						|
 | 
						|
exp_contains_list_comp(_,Flag), nonvar(Flag) => true.
 | 
						|
exp_contains_list_comp([(_ : _)|_],Flag) => Flag=1.
 | 
						|
exp_contains_list_comp(E1+E2,Flag) =>
 | 
						|
    exp_contains_list_comp(E1,Flag),
 | 
						|
    exp_contains_list_comp(E2,Flag).
 | 
						|
exp_contains_list_comp(E1-E2,Flag) =>
 | 
						|
    exp_contains_list_comp(E1,Flag),
 | 
						|
    exp_contains_list_comp(E2,Flag).
 | 
						|
exp_contains_list_comp(E1*E2,Flag) =>
 | 
						|
    exp_contains_list_comp(E1,Flag),
 | 
						|
    exp_contains_list_comp(E2,Flag).
 | 
						|
exp_contains_list_comp(E1/E2,Flag) =>
 | 
						|
    exp_contains_list_comp(E1,Flag),
 | 
						|
    exp_contains_list_comp(E2,Flag).
 | 
						|
exp_contains_list_comp(E1//E2,Flag) =>
 | 
						|
    exp_contains_list_comp(E1,Flag),
 | 
						|
    exp_contains_list_comp(E2,Flag).
 | 
						|
exp_contains_list_comp(-E,Flag) =>
 | 
						|
    exp_contains_list_comp(E,Flag).
 | 
						|
exp_contains_list_comp(abs(E),Flag) =>
 | 
						|
    exp_contains_list_comp(E,Flag).
 | 
						|
exp_contains_list_comp(sum([(_ : _)|_]),Flag) => Flag=1.
 | 
						|
exp_contains_list_comp(min([(_ : _)|_]),Flag) => Flag=1.
 | 
						|
exp_contains_list_comp(max([(_ : _)|_]),Flag) => Flag=1.
 | 
						|
exp_contains_list_comp(_,_) => true.
 | 
						|
 | 
						|
%%
 | 
						|
$change_list_comprehension_to_foreach_cmptime(T,I,Is,CallForeach,L):-
 | 
						|
    $retrieve_list_comp_lvars_goal_cmptime(Is,LocalVars1,Goal1,Is1),
 | 
						|
    (nonvar(T),T=_^_->  % array access
 | 
						|
        LocalVars=[TempVar|LocalVars1],
 | 
						|
        (Goal1==true->
 | 
						|
           Goal=(TempVar@=T,L^0=[TempVar|L^1])
 | 
						|
         ;
 | 
						|
           Goal=(Goal1->(TempVar@=T,L^0=[TempVar|L^1]);L^0=L^1)
 | 
						|
        )
 | 
						|
     ;
 | 
						|
        LocalVars=LocalVars1,
 | 
						|
        (Goal1==true->
 | 
						|
            Goal=(L^0=[T|L^1])
 | 
						|
         ;
 | 
						|
            Goal=(Goal1->L^0=[T|L^1];L^0=L^1)
 | 
						|
        )
 | 
						|
    ),
 | 
						|
    append(Is1,[LocalVars,ac1(L,[]),Goal],Is2),
 | 
						|
    CallForeach=..[foreach,I|Is2].
 | 
						|
 | 
						|
$retrieve_list_comp_lvars_goal_cmptime([],LocalVars,Goal,Is) =>
 | 
						|
     LocalVars=[],Goal=true,Is=[].
 | 
						|
$retrieve_list_comp_lvars_goal_cmptime([E|Es],LocalVars,Goal,Is),E = (_ in _) =>
 | 
						|
    Is=[E|IsR],
 | 
						|
    $retrieve_list_comp_lvars_goal_cmptime(Es,LocalVars,Goal,IsR).
 | 
						|
$retrieve_list_comp_lvars_goal_cmptime([LVars,G],LocalVars,Goal,Is),LVars=[] =>
 | 
						|
    Is=[],LocalVars=LVars,G=Goal.
 | 
						|
$retrieve_list_comp_lvars_goal_cmptime([LVars,G],LocalVars,Goal,Is),LVars=[_|_] =>
 | 
						|
    Is=[],LocalVars=LVars,G=Goal.
 | 
						|
$retrieve_list_comp_lvars_goal_cmptime([LVars],LocalVars,Goal,Is),LVars=[_|_] =>
 | 
						|
    Is=[],LocalVars=LVars,Goal=true.
 | 
						|
$retrieve_list_comp_lvars_goal_cmptime([LVars],LocalVars,Goal,Is),LVars=[] =>
 | 
						|
    Is=[],LocalVars=LVars,Goal=true.
 | 
						|
$retrieve_list_comp_lvars_goal_cmptime([G],LocalVars,Goal,Is),nonvar(G) =>
 | 
						|
    Is=[],LocalVars=[],G=Goal.
 | 
						|
 | 
						|
%%
 | 
						|
extract_list_comprehension_array_notation(T,NT,TempCalls,TempCallsR), var(T) =>
 | 
						|
    NT=T,TempCalls=TempCallsR.
 | 
						|
extract_list_comprehension_array_notation(T,NT,TempCalls,TempCallsR), T=(_^_) =>
 | 
						|
    TempCalls=[NT @= T|TempCallsR].
 | 
						|
extract_list_comprehension_array_notation(sum(T),NT,TempCalls,TempCallsR), T=[(_ : _)|_] =>
 | 
						|
    NT=sum(L),
 | 
						|
    TempCalls=[L @= T|TempCallsR].
 | 
						|
extract_list_comprehension_array_notation(min(T),NT,TempCalls,TempCallsR), T=[(_ : _)|_] => 
 | 
						|
    NT=min(L),
 | 
						|
    TempCalls=[L @= T|TempCallsR].
 | 
						|
extract_list_comprehension_array_notation(max(T),NT,TempCalls,TempCallsR), T=[(_ : _)|_] =>
 | 
						|
    NT=max(L),
 | 
						|
    TempCalls=[L @= T|TempCallsR].
 | 
						|
extract_list_comprehension_array_notation(X+Y,NT,TempCalls,TempCallsR) =>
 | 
						|
    NT=(NX+NY),
 | 
						|
    extract_list_comprehension_array_notation(X,NX,TempCalls,TempCalls1),
 | 
						|
    extract_list_comprehension_array_notation(Y,NY,TempCalls1,TempCallsR).
 | 
						|
extract_list_comprehension_array_notation(X-Y,NT,TempCalls,TempCallsR) =>
 | 
						|
    NT=(NX-NY),
 | 
						|
    extract_list_comprehension_array_notation(X,NX,TempCalls,TempCalls1),
 | 
						|
    extract_list_comprehension_array_notation(Y,NY,TempCalls1,TempCallsR).
 | 
						|
extract_list_comprehension_array_notation(X*Y,NT,TempCalls,TempCallsR) =>
 | 
						|
    NT=(NX*NY),
 | 
						|
    extract_list_comprehension_array_notation(X,NX,TempCalls,TempCalls1),
 | 
						|
    extract_list_comprehension_array_notation(Y,NY,TempCalls1,TempCallsR).
 | 
						|
extract_list_comprehension_array_notation(X//Y,NT,TempCalls,TempCallsR) =>
 | 
						|
    NT=(NX//NY),
 | 
						|
    extract_list_comprehension_array_notation(X,NX,TempCalls,TempCalls1),
 | 
						|
    extract_list_comprehension_array_notation(Y,NY,TempCalls1,TempCallsR).
 | 
						|
extract_list_comprehension_array_notation(X/Y,NT,TempCalls,TempCallsR) =>
 | 
						|
    NT=(NX/NY),
 | 
						|
    extract_list_comprehension_array_notation(X,NX,TempCalls,TempCalls1),
 | 
						|
    extract_list_comprehension_array_notation(Y,NY,TempCalls1,TempCallsR).
 | 
						|
extract_list_comprehension_array_notation(abs(X),NT,TempCalls,TempCallsR) =>
 | 
						|
    NT=abs(NX),
 | 
						|
    extract_list_comprehension_array_notation(X,NX,TempCalls,TempCallsR).
 | 
						|
extract_list_comprehension_array_notation(T,NT,TempCalls,TempCallsR) =>
 | 
						|
    NT=T,TempCalls=TempCallsR.
 | 
						|
 | 
						|
compile_foreach_goal(G,NG,PrefixName,ProgTab,DumNo,DumNoR):-
 | 
						|
    functor(G,_,Arity),
 | 
						|
    (compile_foreach_retrieve_iterators(G,1,Arity,Is,ACs,LocalVars,Goal)->
 | 
						|
       compile_foreach(Is,LocalVars,ACs,Goal,NG,PrefixName,ProgTab,DumNo,DumNoR)
 | 
						|
     ;
 | 
						|
       NG=G,DumNo=DumNoR  % interpreted
 | 
						|
     ).
 | 
						|
 | 
						|
compile_foreach(Iterators,LocalVars,ACs,G,NG,PrefixName,ProgTab,DumNo,DumNoR):-
 | 
						|
    initial_acs_map(ACs,ACMap,Init,Fin),
 | 
						|
    NG=(Init,G1,Fin),
 | 
						|
    compile_foreach_iterators(Iterators,LocalVars,ACMap,G,G1,PrefixName,ProgTab,DumNo,DumNoR).
 | 
						|
 | 
						|
compile_foreach_iterators([],_LocalVars,ACMap,G,NG,PrefixName,ProgTab,DumNo,DumNoR) =>
 | 
						|
    substitute_accumulators(G,G1,ACMap),
 | 
						|
    expand_constr(G1,NG,PrefixName,ProgTab,DumNo,DumNoR).
 | 
						|
compile_foreach_iterators([I in B1..Step..B2|Iterators],LocalVars,ACMap,G,NG,PrefixName,ProgTab,DumNo,DumNoR) =>
 | 
						|
    (var(I)->true; cmp_error(["wrong loop variable: ", I])),
 | 
						|
    (Step== -1 ->
 | 
						|
     compile_foreach_range_downto_1(I,B1,B2,Iterators,LocalVars,ACMap,G,NG,PrefixName,ProgTab,DumNo,DumNoR);
 | 
						|
     compile_foreach_range_step(I,B1,B2,Step,Iterators,LocalVars,ACMap,G,NG,PrefixName,ProgTab,DumNo,DumNoR)).
 | 
						|
compile_foreach_iterators([I in L..U|Iterators],LocalVars,ACMap,G,NG,PrefixName,ProgTab,DumNo,DumNoR) =>
 | 
						|
    (var(I)->true; cmp_error(["wrong loop variable: ", I])),
 | 
						|
    compile_foreach_range_upto_1(I,L,U,Iterators,LocalVars,ACMap,G,NG,PrefixName,ProgTab,DumNo,DumNoR).
 | 
						|
compile_foreach_iterators([I in Lst|Iterators],LocalVars,ACMap,G,NG,PrefixName,ProgTab,DumNo,DumNoR) =>
 | 
						|
    compile_foreach_lst(I,Lst,Iterators,LocalVars,ACMap,G,NG,PrefixName,ProgTab,DumNo,DumNoR).
 | 
						|
 | 
						|
compile_foreach_range_upto_1(I,LExp,UExp,IteratorsR,LocalVars,ACMap,G,NG,PrefixName,ProgTab,DumNo,DumNoR):-
 | 
						|
    new_pred_name_foreach(PrefixName,DumNo,NewPredName),
 | 
						|
    DumNo1 is DumNo+1,
 | 
						|
    term_variables((IteratorsR,G),AllVars),
 | 
						|
    extract_arg_vars(AllVars,I,IteratorsR,LocalVars,ACMap,GVars,[]),
 | 
						|
    foreach_accumulator_args(ACMap,ACHeadArgs,[]),
 | 
						|
    split_acs_map(ACMap,ACMap1,ACMap2),
 | 
						|
    append(GVars,ACHeadArgs,Args),
 | 
						|
    foreach_accumulator_args(ACMap2,ACTailArgs,[]),
 | 
						|
    append(GVars,ACTailArgs,TailArgs),
 | 
						|
    foreach_end_accumulator_args(ACMap,BodyR1),
 | 
						|
    CallNewPred=..[NewPredName,Lower,Upper|Args],
 | 
						|
    NG=(Lower is LExp, Upper is UExp, CallNewPred),
 | 
						|
    Head=..[NewPredName,Elm,Upper|Args],
 | 
						|
    Body1=(Elm>Upper : BodyR1),
 | 
						|
    Tail2=..[NewPredName,Elm1,Upper|TailArgs],
 | 
						|
    Body2=(G1,Elm1 is Elm+1,Tail2),
 | 
						|
    Cl1=(Head:-Body1),
 | 
						|
    copy_term(Cl1,Cl1CP),
 | 
						|
    Cl2=(Head:-true : Body2),
 | 
						|
    I=Elm,
 | 
						|
    copy_term(t(IteratorsR,LocalVars,ACMap1,G,G1,Cl2),TCopy),
 | 
						|
    TCopy=t(IteratorsRCP,LocalVarsCP,ACMap1CP,GCP,G1CP,Cl2CP),
 | 
						|
    %
 | 
						|
    compile_foreach_iterators(IteratorsRCP,LocalVarsCP,ACMap1CP,GCP,G1CP,PrefixName,ProgTab,DumNo1,DumNo2),
 | 
						|
    %
 | 
						|
    '$eliminate_disjunctions'(Cl1CP,NCl1CP,ProgTab,DumNo2,DumNo3),
 | 
						|
    '$eliminate_disjunctions'(Cl2CP,NCl2CP,ProgTab,DumNo3,DumNoR),
 | 
						|
    functor(Head,_,Arity),
 | 
						|
    PredDef=pred(NewPredName,Arity,_Mode,_Delay,_Tabled,[NCl1CP,NCl2CP]),
 | 
						|
    hashtable_put(ProgTab,NewPredName/Arity,PredDef).
 | 
						|
 | 
						|
compile_foreach_range_downto_1(I,UExp,LExp,IteratorsR,LocalVars,ACMap,G,NG,PrefixName,ProgTab,DumNo,DumNoR):-
 | 
						|
    new_pred_name_foreach(PrefixName,DumNo,NewPredName),
 | 
						|
    DumNo1 is DumNo+1,
 | 
						|
    term_variables((IteratorsR,G),AllVars),
 | 
						|
    extract_arg_vars(AllVars,I,IteratorsR,LocalVars,ACMap,GVars,[]),
 | 
						|
    foreach_accumulator_args(ACMap,ACHeadArgs,[]),
 | 
						|
    split_acs_map(ACMap,ACMap1,ACMap2), 
 | 
						|
    append(GVars,ACHeadArgs,Args),
 | 
						|
    foreach_accumulator_args(ACMap2,ACTailArgs,[]),
 | 
						|
    append(GVars,ACTailArgs,TailArgs),
 | 
						|
    foreach_end_accumulator_args(ACMap,BodyR1),
 | 
						|
    CallNewPred=..[NewPredName,Upper,Lower|Args],
 | 
						|
    NG=(Lower is LExp, Upper is UExp, CallNewPred),
 | 
						|
    Head=..[NewPredName,Elm,Lower|Args],
 | 
						|
    Body1=(Elm<Lower : BodyR1),
 | 
						|
    Tail2=..[NewPredName,Elm1,Lower|TailArgs],
 | 
						|
    Body2=(G1,Elm1 is Elm-1,Tail2),
 | 
						|
    Cl1=(Head:-Body1),
 | 
						|
    copy_term(Cl1,Cl1CP),
 | 
						|
    Cl2=(Head:-true : Body2),
 | 
						|
    I=Elm,
 | 
						|
    copy_term(t(IteratorsR,LocalVars,ACMap1,G,G1,Cl2),TCopy),
 | 
						|
    TCopy=t(IteratorsRCP,LocalVarsCP,ACMap1CP,GCP,G1CP,Cl2CP),
 | 
						|
    %
 | 
						|
    compile_foreach_iterators(IteratorsRCP,LocalVarsCP,ACMap1CP,GCP,G1CP,PrefixName,ProgTab,DumNo1,DumNo2),
 | 
						|
    %
 | 
						|
    '$eliminate_disjunctions'(Cl1CP,NCl1CP,ProgTab,DumNo2,DumNo3),
 | 
						|
    '$eliminate_disjunctions'(Cl2CP,NCl2CP,ProgTab,DumNo3,DumNoR),
 | 
						|
    functor(Head,_,Arity),
 | 
						|
    PredDef=pred(NewPredName,Arity,_Mode,_Delay,_Tabled,[NCl1CP,NCl2CP]),
 | 
						|
    hashtable_put(ProgTab,NewPredName/Arity,PredDef).
 | 
						|
 | 
						|
compile_foreach_range_step(I,B1,B2,Step,IteratorsR,LocalVars,ACMap,G,NG,PrefixName,ProgTab,DumNo,DumNoR):-
 | 
						|
    new_pred_name_foreach(PrefixName,DumNo,NewPredName),
 | 
						|
    DumNo1 is DumNo+1,
 | 
						|
    term_variables((IteratorsR,G),AllVars),
 | 
						|
    extract_arg_vars(AllVars,I,IteratorsR,LocalVars,ACMap,GVars,[]),
 | 
						|
    foreach_accumulator_args(ACMap,ACHeadArgs,[]),
 | 
						|
    split_acs_map(ACMap,ACMap1,ACMap2),
 | 
						|
    append(GVars,ACHeadArgs,Args),
 | 
						|
    foreach_accumulator_args(ACMap2,ACTailArgs,[]),
 | 
						|
    append(GVars,ACTailArgs,TailArgs),
 | 
						|
    foreach_end_accumulator_args(ACMap,BodyR1),
 | 
						|
    CallNewPred=..[NewPredName,B1Val,B2Val,StepVal|Args],
 | 
						|
    NG=(B1Val is B1, B2Val is B2, StepVal is Step, CallNewPred),
 | 
						|
    Head=..[NewPredName,Elm,B2Arg,StepArg|Args],
 | 
						|
    Body1=(StepArg>0,Elm>B2Arg : BodyR1),
 | 
						|
    Cl1=(Head:-Body1),
 | 
						|
    copy_term(Cl1,Cl1CP),
 | 
						|
    Body2=(StepArg<0,Elm<B2Arg : BodyR1),
 | 
						|
    Cl2=(Head:-Body2),
 | 
						|
    copy_term(Cl2,Cl2CP),
 | 
						|
 | 
						|
    Tail3=..[NewPredName,Elm1,B2Arg,StepArg|TailArgs],
 | 
						|
    Body3=(G1,Elm1 is Elm+StepArg,Tail3),
 | 
						|
    Cl3=(Head:-true : Body3),
 | 
						|
    I=Elm,
 | 
						|
    copy_term(t(IteratorsR,LocalVars,ACMap1,G,G1,Cl3),TCopy),
 | 
						|
    TCopy=t(IteratorsRCP,LocalVarsCP,ACMap1CP,GCP,G1CP,Cl3CP),
 | 
						|
    %
 | 
						|
    compile_foreach_iterators(IteratorsRCP,LocalVarsCP,ACMap1CP,GCP,G1CP,PrefixName,ProgTab,DumNo1,DumNo2),
 | 
						|
    %
 | 
						|
    '$eliminate_disjunctions'(Cl1CP,NCl1CP,ProgTab,DumNo2,DumNo3),
 | 
						|
    '$eliminate_disjunctions'(Cl2CP,NCl2CP,ProgTab,DumNo3,DumNo4),
 | 
						|
    '$eliminate_disjunctions'(Cl3CP,NCl3CP,ProgTab,DumNo4,DumNoR),
 | 
						|
    functor(Head,_,Arity),
 | 
						|
    PredDef=pred(NewPredName,Arity,_Mode,_Delay,_Tabled,[NCl1CP,NCl2CP,NCl3CP]),
 | 
						|
    hashtable_put(ProgTab,NewPredName/Arity,PredDef).
 | 
						|
 | 
						|
		      
 | 
						|
 | 
						|
compile_foreach_lst(I,Lst,IteratorsR,LocalVars,ACMap,G,NG,PrefixName,ProgTab,DumNo,DumNoR):-
 | 
						|
    new_pred_name_foreach(PrefixName,DumNo,NewPredName),
 | 
						|
    DumNo1 is DumNo+1,
 | 
						|
    term_variables((IteratorsR,G),AllVars),
 | 
						|
    extract_arg_vars(AllVars,I,IteratorsR,LocalVars,ACMap,GVars,[]),
 | 
						|
    foreach_accumulator_args(ACMap,ACHeadArgs,[]),
 | 
						|
    split_acs_map(ACMap,ACMap1,ACMap2),
 | 
						|
    append(GVars,ACHeadArgs,Args),
 | 
						|
    foreach_accumulator_args(ACMap2,ACTailArgs,[]),
 | 
						|
    append(GVars,ACTailArgs,TailArgs),
 | 
						|
    foreach_end_accumulator_args(ACMap,BodyR1),
 | 
						|
    NG=..[NewPredName,Lst|Args],
 | 
						|
    Head1=..[NewPredName,[]|Args],
 | 
						|
    Body1=BodyR1,
 | 
						|
    Head2=..[NewPredName,[Elm|Elms]|Args],
 | 
						|
    Tail2=..[NewPredName,Elms|TailArgs],
 | 
						|
    Head3=..[NewPredName,[_|Elms]|Args],
 | 
						|
    Tail3=..[NewPredName,Elms|Args],
 | 
						|
    Body2=(G1,Tail2),
 | 
						|
    Cl1=(Head1:-true : Body1),
 | 
						|
    copy_term(Cl1,Cl1CP),
 | 
						|
    Cl2=(Head2:-true : Body2),
 | 
						|
    I=Elm,
 | 
						|
    copy_term(t(IteratorsR,LocalVars,ACMap1,G,G1,Cl2),TCopy2),
 | 
						|
    TCopy2=t(IteratorsRCP,LocalVarsCP,ACMap1CP,GCP,G1CP,Cl2CP),
 | 
						|
    Cl3=(Head3:-true : Tail3),
 | 
						|
    copy_term(Cl3,Cl3CP),
 | 
						|
    compile_foreach_iterators(IteratorsRCP,LocalVarsCP,ACMap1CP,GCP,G1CP,PrefixName,ProgTab,DumNo1,DumNo2),
 | 
						|
    '$eliminate_disjunctions'(Cl1CP,NCl1CP,ProgTab,DumNo2,DumNo3),
 | 
						|
    '$eliminate_disjunctions'(Cl2CP,NCl2CP,ProgTab,DumNo3,DumNoR),
 | 
						|
    functor(Head1,_,Arity),
 | 
						|
    Head4=..[NewPredName,Collection|Args],
 | 
						|
    Tail4=..[NewPredName,CollectionLst|Args],
 | 
						|
    Cl4=(Head4:-true : (foreach_collection_to_lst(Collection,CollectionLst),Tail4)),
 | 
						|
    copy_term(Cl4,Cl4CP),
 | 
						|
    PredDef=pred(NewPredName,Arity,_Mode,_Delay,_Tabled,[NCl1CP,NCl2CP,Cl3CP,Cl4CP]),
 | 
						|
    hashtable_put(ProgTab,NewPredName/Arity,PredDef).
 | 
						|
 | 
						|
foreach_accumulator_args([],Args,ArgsR) => Args=ArgsR.
 | 
						|
foreach_accumulator_args([ac_inout(_Name,In,Out)|ACMap],Args,ArgsR) =>
 | 
						|
    Args=[In,Out|Args1],
 | 
						|
    foreach_accumulator_args(ACMap,Args1,ArgsR).
 | 
						|
 | 
						|
foreach_end_accumulator_args([],Body) => Body=true.
 | 
						|
foreach_end_accumulator_args([ac_inout(_Name,In,Out)|ACMap],Body) =>
 | 
						|
    Body=(In=Out,BodyR),
 | 
						|
    foreach_end_accumulator_args(ACMap,BodyR).
 | 
						|
    
 | 
						|
split_acs_map([],ACMap1,ACMap2) => ACMap1=[],ACMap2=[].
 | 
						|
split_acs_map([ac_inout(Name,In,Out)|ACMap],ACMap1,ACMap2) =>
 | 
						|
    ACMap1=[ac_inout(Name,In,Mid)|ACMap1R],
 | 
						|
    ACMap2=[ac_inout(Name,Mid,Out)|ACMap2R],
 | 
						|
    split_acs_map(ACMap,ACMap1R,ACMap2R).
 | 
						|
 | 
						|
/* utilities */
 | 
						|
extract_arg_vars([],_I,_Iterators,_LocalVars,_ACMap,Args,ArgsR) => Args=ArgsR.
 | 
						|
extract_arg_vars([Var|Vars],I,Iterators,LocalVars,ACMap,Args,ArgsR):-true ?
 | 
						|
    ($occur(Var,I);
 | 
						|
     is_a_loop_var(Var,Iterators);
 | 
						|
     membchk(Var,LocalVars);
 | 
						|
     foreach_lookup_acmap(Var,1,_,ACMap);
 | 
						|
     foreach_lookup_acmap(Var,0,_,ACMap)),!,
 | 
						|
    extract_arg_vars(Vars,I,Iterators,LocalVars,ACMap,Args,ArgsR).
 | 
						|
extract_arg_vars([Var|Vars],I,Iterators,LocalVars,ACMap,Args,ArgsR) =>
 | 
						|
    Args=[Var|Args1],
 | 
						|
    extract_arg_vars(Vars,I,Iterators,LocalVars,ACMap,Args1,ArgsR).
 | 
						|
 | 
						|
is_a_loop_var(Var,(I in _)):-true ? $occur(Var,I),!.
 | 
						|
is_a_loop_var(Var,(Iterators1,_)):-true ?
 | 
						|
    is_a_loop_var(Var,Iterators1),!.
 | 
						|
is_a_loop_var(Var,(_,Iterators2)) =>
 | 
						|
    is_a_loop_var(Var,Iterators2).
 | 
						|
 | 
						|
initial_acs_map([],ACMap,InitCode,FinCode) => ACMap=[],InitCode=true,FinCode=true.
 | 
						|
initial_acs_map([AC],ACMap,InitCode,FinCode) =>
 | 
						|
    ACMap=[Triplet],
 | 
						|
    initial_ac_map(AC,Triplet,InitCode,FinCode).
 | 
						|
initial_acs_map([AC|ACs],[Triplet|ACMap],InitCode,FinCode):-
 | 
						|
    InitCode=(InitCode1,InitCodeR),
 | 
						|
    FinCode=(FinCode1,FinCodeR),
 | 
						|
    initial_ac_map(AC,Triplet,InitCode1,FinCode1),
 | 
						|
    initial_acs_map(ACs,ACMap,InitCodeR,FinCodeR).
 | 
						|
initial_acs_map(AC,ACMap,InitCode,FinCode) =>
 | 
						|
    ACMap=[Triplet],
 | 
						|
    initial_ac_map(AC,Triplet,InitCode,FinCode).
 | 
						|
 | 
						|
initial_ac_map(ac(Name,InitVal),ac_inout(Name,NameIn,NameOut),(NameIn=InitVal),(Name=NameOut)).
 | 
						|
initial_ac_map(ac1(Name,FinVal),ac_inout(Name,NameIn,NameOut),(Name=NameIn),(NameOut=FinVal)).
 | 
						|
 | 
						|
% Replace inputs and outputs in recurrences: A^0 is input and A^1 is output.
 | 
						|
substitute_accumulators(Term,NTerm,_ACMap):-var(Term) :
 | 
						|
    NTerm=Term.
 | 
						|
substitute_accumulators(Term,NTerm,_ACMap):-atomic(Term) :
 | 
						|
    NTerm=Term.
 | 
						|
substitute_accumulators(Term,NTerm,ACMap):-Term=(Var^Tail) :
 | 
						|
    (foreach_lookup_acmap(Var,Tail,NTerm,ACMap)->true;
 | 
						|
     NTerm=Term).
 | 
						|
substitute_accumulators([E|Es],Lst,ACMap) =>
 | 
						|
    Lst=[E1|Es1],
 | 
						|
    substitute_accumulators(E,E1,ACMap),
 | 
						|
    substitute_accumulators(Es,Es1,ACMap).
 | 
						|
substitute_accumulators(Term,NTerm,ACMap) =>
 | 
						|
    functor(Term,F,N),
 | 
						|
    functor(NTerm,F,N),
 | 
						|
    substitute_accumulators(Term,NTerm,1,N,ACMap).
 | 
						|
 | 
						|
substitute_accumulators(_Term,_NTerm,I,N,_), I>N => true.
 | 
						|
substitute_accumulators(Term,NTerm,I,N,ACMap) =>
 | 
						|
    arg(I,Term,A),
 | 
						|
    arg(I,NTerm,NA),
 | 
						|
    substitute_accumulators(A,NA,ACMap),
 | 
						|
    I1 is I+1,
 | 
						|
    substitute_accumulators(Term,NTerm,I1,N,ACMap).
 | 
						|
     
 | 
						|
foreach_lookup_acmap(Term,Tail,NTerm,[ac_inout(Term1,In,Out)|_]), Term==Term1 => 
 | 
						|
    (Tail==0->NTerm=In;
 | 
						|
     Tail==1->NTerm=Out).
 | 
						|
foreach_lookup_acmap(Term,Tail,NTerm,[_|ACMap]) =>
 | 
						|
    foreach_lookup_acmap(Term,Tail,NTerm,ACMap).
 | 
						|
 | 
						|
new_pred_name_foreach(PrefixName,DumNo,NewPredName):-
 | 
						|
    number_codes(DumNo,DumNoCodes),
 | 
						|
    append(PrefixName,[0'_,0'#,0'_|DumNoCodes],NewPredNameCodes),
 | 
						|
    atom_codes(NewPredName,NewPredNameCodes).
 | 
						|
    
 | 
						|
compile_foreach_retrieve_iterators(G,I,Arity,Iterators,ACs,LocalVars,Goal), I==Arity =>
 | 
						|
    arg(I,G,Goal),
 | 
						|
    Iterators=[],
 | 
						|
    (var(ACs)->ACs=[];true),
 | 
						|
    (var(LocalVars)->LocalVars=[];true).
 | 
						|
compile_foreach_retrieve_iterators(G,I,Arity,Iterators,ACs,LocalVars,Goal) =>
 | 
						|
    arg(I,G,A),
 | 
						|
    (nonvar(A),A=(_ in _) ->
 | 
						|
       Iterators=[A|Iterators1]
 | 
						|
    ;I>=Arity-2 ->
 | 
						|
       (cmp_foreach_check_accumulators(A) ->
 | 
						|
          Iterators=Iterators1,
 | 
						|
          (var(ACs)->ACs=A;cmp_error(["two accumulators given separately in foreach"]),fail)
 | 
						|
	;cmp_foreach_check_lvars(A)->
 | 
						|
          Iterators=Iterators1,
 | 
						|
          (var(LocalVars)->LocalVars=A;cmp_error(["invalid local variables given in foreach"]),fail)
 | 
						|
	;fail
 | 
						|
	)
 | 
						|
    ;fail
 | 
						|
    ),
 | 
						|
    I1 is I+1,
 | 
						|
    compile_foreach_retrieve_iterators(G,I1,Arity,Iterators1,ACs,LocalVars,Goal).
 | 
						|
 | 
						|
cmp_foreach_check_lvars([]) => true.
 | 
						|
cmp_foreach_check_lvars([X|Xs]) => var(X),cmp_foreach_check_lvars(Xs).
 | 
						|
 | 
						|
cmp_foreach_check_accumulators(ac1(_,_)) => true.
 | 
						|
cmp_foreach_check_accumulators(ac(_,_)) => true.
 | 
						|
cmp_foreach_check_accumulators(Accumulators), Accumulators=[_|_] =>
 | 
						|
    cmp_foreach_check_accumulator_lst(Accumulators).
 | 
						|
 | 
						|
cmp_foreach_check_accumulator_lst([]) => true.
 | 
						|
cmp_foreach_check_accumulator_lst([X|_]), var(X) => fail.
 | 
						|
cmp_foreach_check_accumulator_lst([ac(_,_)|L]) =>
 | 
						|
    cmp_foreach_check_accumulator_lst(L).
 | 
						|
cmp_foreach_check_accumulator_lst([ac1(_,_)|L]) =>
 | 
						|
    cmp_foreach_check_accumulator_lst(L).
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    
 | 
						|
    
 | 
						|
    
 | 
						|
    
 |