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