1 % (c) 2009-2022 Lehrstuhl fuer Softwaretechnik und Programmiersprachen,
2 % Heinrich Heine Universitaet Duesseldorf
3 % This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html)
4
5 :- module(csp_sequences,[is_null_list/2, is_empty_list/2,
6 is_elem_list/2,
7 tail_list/2, head_list/2,
8 concat_lists/2, append_list/3,
9 length_list/2,
10
11 expand_sequence/2,
12 expand_listcomprehension/3,
13
14 convert_seq_to_set/2, convert_set_to_seq/2]).
15
16 :- use_module(probsrc(module_information)).
17 :- module_info(group,csp).
18 :- module_info(description,'Operations on CSP sequences.').
19
20 /*********** PROB modules **********/
21 :- use_module(probsrc(error_manager),[add_error/3,add_internal_error/2]).
22 :- use_module(probsrc(self_check)).
23 :- use_module(probsrc(tools),[remove_variables/3,ajoin/2]).
24 :- use_module(probsrc(translate),[translate_csp_value/2]).
25 %------- CSP modules:
26 :- use_module(probcspsrc(csp_sets)).
27 :- use_module(probcspsrc(haskell_csp),[force_evaluate_argument/2]).
28 /*********** ----------- **********/
29
30 /* ------------------------------------- */
31 /* SEQUENCES */
32 /* ------------------------------------- */
33
34 :- assert_must_succeed(csp_sequences:is_null_list(listFromTo(22,21),true) ).
35 :- assert_must_succeed(csp_sequences:is_null_list(list([]),true) ).
36 :- assert_must_succeed((csp_sequences:is_null_list(listFromTo(22,22),R), R==false )).
37 :- assert_must_fail(csp_sequences:is_null_list(listFrom(22),true) ).
38 :- assert_must_fail(csp_sequences:is_null_list(listFromTo(22,22),true) ).
39 :- assert_must_fail(csp_sequences:is_null_list(listFromTo(22,23),true) ).
40 :- assert_must_fail(csp_sequences:is_null_list(list([int(22),int(21)]),true) ).
41
42 :- block is_null_list(-,?).
43 is_null_list(list(Y),R) :- !, is_empty_list(Y,R).
44 is_null_list(listFrom(_),R) :- !,R=false.
45 is_null_list(listFromTo(F,T),R) :- number(F),number(T), !,
46 (F>T -> R=true ; R=false).
47 is_null_list(X,_) :- add_error(csp_sequences,'Unexpected argument to null: ',X),fail.
48
49 :- block is_empty_list(-,?).
50 is_empty_list([],R) :- !, R=true.
51 is_empty_list(_,false).
52
53 :- assert_must_fail(csp_sequences:is_elem_list(int(22),listFromTo(22,21)) ).
54 :- assert_must_succeed(csp_sequences:is_elem_list(int(22),listFromTo(22,22)) ).
55 :- assert_must_succeed(csp_sequences:is_elem_list(int(22),listFrom(22)) ).
56 :- assert_must_succeed(csp_sequences:is_elem_list(int(22),list([int(23),int(22)])) ).
57
58 is_elem_list(E,X) :-
59 (X=list(Y)
60 -> elem(Y,E)
61 ; X=listFrom(F) -> E=int(EV), mygeq(EV,F)
62 ; X=listFromTo(F,T) -> E=int(EV), mygeq(EV,F), mygeq(T,EV)
63 ; add_error(csp_sequences,'Unexpected argument to elem: ',X),fail
64 ).
65
66 :- block mygeq(-,?), mygeq(?,-).
67 mygeq(EV,F) :- EV>=F.
68
69 :- block elem(-,?).
70 elem([H|T],E) :- (E=H ; (/*dif(E,H),*/elem(T,E))).
71
72 :- assert_must_succeed((csp_sequences:tail_list(listFrom(22),R), R=listFrom(23) )).
73 :- assert_must_succeed((csp_sequences:tail_list(listFromTo(22,22),R), R=list([]) )).
74 :- assert_must_succeed((csp_sequences:tail_list(listFromTo(22,23),R), R=listFromTo(23,23) )).
75 :- assert_must_succeed((csp_sequences:tail_list(list([int(22),int(21)]),R), R=list([int(21)]) )).
76
77 tail_list(listFrom(F),Res) :- number(F),!,
78 F1 is F+1, Res= listFrom(F1).
79 tail_list(listFromTo(F,T),Res) :- number(F),number(T), T >=F, !,
80 (T>F -> F1 is F+1, Res=listFromTo(F1,T) ; Res=list([])).
81 tail_list(List,Res) :-
82 (List=list([_H|T]) -> Res = list(T)
83 ; (add_error(csp_sequences,'Unexpected argument to tail of sequence: ',List),fail)).
84
85 :- assert_must_succeed((csp_sequences:head_list(listFrom(22),R), R=int(22) )).
86 :- assert_must_succeed((csp_sequences:head_list(listFromTo(22,22),R), R=int(22) )).
87 :- assert_must_succeed((csp_sequences:head_list(list([int(22),int(21)]),R), R=int(22) )).
88
89 head_list(listFrom(F),Res) :- !, Res=int(F).
90 head_list(listFromTo(F,T),Res) :- number(F),number(T), T >=F, !, Res=int(F).
91 head_list(List,Res) :-
92 (List=list([H|_T]) -> Res = H
93 ; (add_error(csp_sequences,'Unexpected argument to head of sequence: ',List),fail)).
94
95 :- assert_must_succeed((csp_sequences:append_list(listFromTo(1,2),listFromTo(4,6),R), R==list([int(1),int(2),int(4),int(5),int(6)]))).
96 :- assert_must_succeed((csp_sequences:append_list(listFrom(2),listFromTo(4,6),R), R==listFrom(2) )).
97 :- assert_must_succeed((csp_sequences:append_list(list([int(1),int(2)]),listFromTo(4,6),R), R==list([int(1),int(2),int(4),int(5),int(6)]) )).
98 :- assert_must_succeed((csp_sequences:append_list(list([int(1)]),list([int(1)]),R), R==list([int(1),int(1)]) )).
99
100 append_list(listFrom(F),_,Res) :- !, Res=listFrom(F).
101 append_list(listFromTo(F,T),Y,Res) :- expand_sequence(Y,list(EY)),!, Res=list(ZL),
102 expand_seq_from_to(F,T,EX), app1(EX,EY,ZL).
103 append_list(list(XL),Y,list(ZL)) :- expand_sequence(Y,list(YL)),!,
104 app1(XL,YL,ZL).
105 append_list(X,Y,Z) :-
106 translate_csp_value(X,TX),translate_csp_value(Y,TY),
107 (var(Z) -> ajoin([TX,' ^ ',TY],Text)
108 ; translate_csp_value(Z,TZ), ajoin([TX,' ^ ',TY,' = ', TZ],Text)),
109 add_error(csp_sequences,'Illegal arguments for sequence catenation ^ : ',Text),fail.
110 % Note: we do not allow mixed explicit lists and symbolic listFrom
111 :- block app1(-,?,?).
112 %app1(listFrom(F),_,R) :- !, R= listFrom(F).
113 app1([],Y,R) :- !,Y=R.
114 app1([H|X],Y,R) :- !,R=[H|Z], app1(X,Y,Z).
115 app1(X,Y,Z) :- add_internal_error(/*csp_sequences,*/'Unexpected arguments to append: ',app1(X,Y,Z)),fail.
116
117
118 :- assert_must_succeed((csp_sequences:concat_lists(list([list([int(1),int(2)]),listFromTo(4,6)]),R), R==list([int(1),int(2),int(4),int(5),int(6)]) )).
119 :- assert_must_succeed((csp_sequences:concat_lists(list([list([]),list([int(1)]),list([]),list([int(1)]),list([])]),R), R==list([int(1),int(1)]) )).
120
121 concat_lists(X,Y) :-
122 ((X=list(XL),Y=list(YL))
123 -> conc(XL,YL)
124 ; add_error(csp_sequences,'Unexpected arguments to concat of sequences: ',concat(X,Y)),fail
125 ).
126
127 :- block conc(-,?).
128 conc([],Res) :- !, Res=[].
129 conc([HL|X],Res) :- expand_sequence(HL,list(H)),!,
130 conc(X,RX), app1(H,RX,Res).
131 conc(X,Y) :-
132 add_error(csp_sequences,'Unexpected arguments to conc:',conc(X,Y)),fail.
133
134
135 :- assert_must_succeed((csp_sequences:length_list(list([]),R), R==int(0) )).
136 :- assert_must_succeed((csp_sequences:length_list(list([int(22)]),R), R==int(1) )).
137 :- assert_must_succeed((csp_sequences:length_list(list([int(22),int(22)]),R), R==int(2) )).
138 :- assert_must_succeed((csp_sequences:length_list(listFromTo(1,10),R), R==int(10) )).
139 :- assert_must_succeed((csp_sequences:length_list(listFromTo(2,100001),R), R==int(100000) )).
140 :- assert_must_succeed((csp_sequences:length_list(listFromTo(3,1),R), R==int(0) )).
141
142
143 length_list(listFrom(X),R) :- !,
144 add_internal_error('Internal Error: Trying to get length of infinite list: ',length_list(listFrom(X),R)),fail.
145 length_list(list(Y),int(R)) :- !, length2(Y,R).
146 length_list(listFromTo(F,T),int(R)) :- !, (T<F -> R=0 ; R is T+1-F).
147 length_list(X,Res) :-
148 add_error(csp_sequences,'Unexpected arguments to length: ',length(X,Res)),
149 fail.
150
151 :- block length2(-,?).
152 length2([],0).
153 length2([_H|T],R) :-length3(T,1,R). %when(nonvar(T),(length2(T,RT), R is RT+1)).
154
155 :- block length3(-,?,?).
156 length3([],R,R).
157 length3([_|T],SF,R) :- SF1 is SF+1, length3(T,SF1,R).
158
159
160
161 /* ------------------------------------- */
162 /* SEQUENCE EXPRESSIONS */
163 /* ------------------------------------- */
164
165 :- assert_must_succeed((csp_sequences:expand_sequence(listFromTo(3,1),R), R==list([]) )).
166 :- assert_must_succeed((csp_sequences:expand_sequence(listFromTo(33,33),R), R==list([int(33)]) )).
167 :- assert_must_succeed((csp_sequences:expand_sequence(list([int(33)]),R), R==list([int(33)]) )).
168 :- assert_must_succeed((csp_sequences:expand_sequence(listExp(rangeEnum([_x5]),[comprehensionGenerator(_x5,listExp(rangeEnum([int(1),int(2),int(3)])))]),R), R == list([int(1),int(2),int(3)]))).
169 :- assert_must_succeed((csp_sequences:expand_sequence(listExp(rangeEnum([_x5]),[comprehensionGenerator(_x5,listExp(rangeEnum([int(1),int(2),int(1)])))]),R), R == list([int(1),int(2),int(1)]))).
170
171 expand_sequence(list(X),Res) :- !, Res=list(X).
172 expand_sequence(listFromTo(X,Y),Res) :- !, Res=list(R),expand_seq_from_to(X,Y,R).
173 expand_sequence(listExp(RangeExpr,GeneratorList),R) :- !,
174 expand_listcomprehension(RangeExpr,GeneratorList,R).
175 expand_sequence(listFrom(X),_R) :- !,
176 translate_csp_value(X,TX),
177 add_error(csp_sequences,'Trying to expand infinite list: ',TX),fail.
178 expand_sequence(X,_Y) :-
179 translate_csp_value(X,TX),
180 add_error(csp_sequences,'Illegal argument, this is not a list: ',TX),fail.
181
182 expand_seq_from_to(X,Y,R) :- X>Y,!, R=[].
183 expand_seq_from_to(X,Y,[int(X)|T]) :- X1 is X+1, expand_seq_from_to(X1,Y,T).
184
185
186 :- assert_must_succeed((csp_sequences:convert_seq_to_set(listFrom(333),R), R==setFrom(333) )).
187 :- assert_must_succeed((csp_sequences:convert_seq_to_set(listFromTo(33,33),R), R==setFromTo(33,33) )).
188 :- assert_must_succeed((csp_sequences:convert_seq_to_set(list([int(1),int(3),int(2),int(1)]),R), R==setValue([int(1),int(2),int(3)]) )).
189 :- assert_must_succeed((csp_sequences:convert_seq_to_set(listExp(rangeEnum([_x5]),[comprehensionGenerator(_x5,listExp(rangeEnum([int(1),int(2),int(3)])))]),R), R == setValue([int(1),int(2),int(3)]))).
190
191 convert_seq_to_set(listExp(E,GeneratorList),Res) :- !,
192 expand_sequence(listExp(E,GeneratorList),list(ESeq)),
193 evaluate_set(ESeq,Res).%evaluate_set(ESeq,Res,evaluate_argument).
194 convert_seq_to_set(listFromTo(X,Y),Res) :- !, Res = setFromTo(X,Y).
195 convert_seq_to_set(listFrom(X),Res) :- !, Res = setFrom(X).
196 convert_seq_to_set(list(L),Res) :- !, evaluate_set(L,Res).%evaluate_set(L,Res,evaluate_argument).
197 convert_seq_to_set(X,_R) :- add_error(csp_sequences,'Unexpected argument for the seq(-) built-in function: ',X),fail.
198
199 :- assert_must_succeed((csp_sequences:convert_set_to_seq(setFromTo(1,10),R), R == listFromTo(1,10))).
200 :- assert_must_succeed((csp_sequences:convert_set_to_seq(setFrom(1),R), R == listFrom(1))).
201 :- assert_must_succeed((csp_sequences:convert_set_to_seq(setValue([int(1),int(3),int(2)]),R), R == list([int(1),int(3),int(2)]))).
202 :- assert_must_succeed((csp_sequences:convert_set_to_seq(setExp(rangeEnum([_x6]),[comprehensionGenerator(_x6,setExp(rangeEnum([int(1),int(2),int(3)])))]), R),
203 R == list([int(1),int(2),int(3)]))).
204
205 convert_set_to_seq(setExp(E,Generators),Res) :- !,
206 expand_set_comprehension(E,Generators,setValue(R)),
207 %print(expand_set(Generators,E,R)),nl,
208 Res=list(R).
209 convert_set_to_seq(setFromTo(X,Y),Res) :- !, Res = listFromTo(X,Y).
210 convert_set_to_seq(setFrom(X),Res) :- !, Res = listFrom(X).
211 convert_set_to_seq(setValue(S),Res) :- !, Res = list(S).
212 convert_set_to_seq(X,_R) :- add_error(csp_sequences,'Unexpected argument for the set(-) built-in function: ',X),fail.
213
214 /* ------------------- */
215 /* LIST COMPREHENSIONS */
216 /* ------------------- */
217
218 expand_listcomprehension(RangeExpr,GeneratorList,Res) :-
219 %% print(expand_listComp(RangeExpr,GeneratorList)),nl, %%
220 csp_sets:extract_variables_from_generator_list(GeneratorList,Vars),
221 term_variables(GeneratorList,GVars),
222 remove_variables(GVars,Vars,WaitVars),
223 when(ground(WaitVars), (
224 %print(waitVars(WaitVars)),nl,
225 findall(EExpr,(treat_list_generators(GeneratorList,Vars,Seqs,Guard),
226 %% print(treated_generators(Vars,Sets,Guard)),nl, %%
227 haskell_csp:check_boolean_expression(Guard),
228 generator_list_sol(Vars,Seqs),
229 csp_sets:member_range_expr(RangeExpr,EExpr)),Expressions),
230 Res=list(Expressions)
231 %,print(expanded(Res)),nl
232 )).
233
234
235 generator_list_sol([],[]).
236 generator_list_sol([Var|VT],[Seq|ST]) :-
237 force_evaluate_argument(Seq,EvSeq),expand_sequence(EvSeq,ESeq),
238 (ground(ESeq) -> true ; add_error(expand_set_comprehension,'Non-ground Seq: ',Seq)),
239 is_elem_list(Var,ESeq), generator_list_sol(VT,ST).
240
241 treat_list_generators([],V,S,G) :- !, V=[], S=[], G=true.
242 treat_list_generators([comprehensionGenerator(Var,Seq)|T],Vars,Seqs,TG) :- !, Vars=[Var|VT], Seqs=[Seq|ST],
243 treat_list_generators(T,VT,ST,TG).
244 treat_list_generators([comprehensionGuard(Guard)|T],VT,ST,bool_and(Guard,TGuard)) :- !,
245 treat_list_generators(T,VT,ST,TGuard).
246 treat_list_generators(G,_,_,_) :- add_internal_error('Could not treat Seq Comprehension Generator List: ',G),fail.
247