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).
 | |
| 
 | |
| 
 | |
| 
 | |
|     
 | |
|     
 | |
|     
 | |
|     
 |