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