515 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
		
		
			
		
	
	
			515 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
|   | 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). | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  |      | ||
|  |      | ||
|  |      | ||
|  |      |