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(schemaexpansion,[sexpansion/2,rename_variables/3]).
6
7 :- use_module(library(lists)).
8
9 :- use_module(probsrc(tools)).
10
11 :- use_module(prozsrc(subexpressions)).
12 :- use_module(prozsrc(z_tools)).
13 :- use_module(prozsrc(schemavars)).
14 :- use_module(prozsrc(zenvironment)).
15 :- use_module(prozsrc(zparameters)).
16
17 :- use_module(probsrc(module_information)).
18 :- module_info(group,proz).
19 :- module_info(description,'This module includes code for expanding Z schemas, i.e. removing references to other schemas by their content and evaluating schema calculus expressions').
20
21 sexpansion(In,Out) :-
22 create_initial_zenvironment(In,Env),
23 add_simple_types_info(Env,SEnv),
24 ? sexpansion(In,SEnv,Out).
25
26 sexpansion([],_,[]) :- !.
27 sexpansion([E|Rest],Env,[Exp|ERest]) :-
28 ? !,sexpansion(E,Env,Exp),
29 ? sexpansion(Rest,Env,ERest).
30
31 sexpansion(sref(Name,Deco,ParamValues,Renamings),Env,Result) :-
32 !,
33 lookup(Env,Name,Params,Expr),
34 ? sexpansion(Expr,Env,Expansion),
35 same_length(ParamValues,Params),
36 insert_parameter(Expansion,Params,ParamValues,PExp),
37 decorate(PExp,Deco,DExp),
38 rename_variables(DExp,Renamings,Result).
39 sexpansion(body(Decls,Where),Env,body(EDecl,EWhere)) :-
40 ? !,expand_decls(Decls,Env,ExpandedDeclsD,NWhere),
41 clean_decl(ExpandedDeclsD,EDecl),
42 append(NWhere,ExWhere,DWhere),
43 ? sexpansion(Where,Env,ExWhere),
44 clean_where(DWhere,EWhere).
45 sexpansion(text(S),Env,Expansion) :-
46 ? !,sexpansion(S,Env,Expansion).
47 sexpansion(sand(A,B),Env,Expanded) :-
48 ? !,sexpansion(body([sdecl(A),sdecl(B)],[]),Env,Expanded).
49 sexpansion(sor(A,B),Env,body(EDecl,EWhere)) :-
50 ? !,expand_and_split(A,Env,DA,WA),
51 ? expand_and_split(B,Env,DB,WB),
52 append_decls(DA,DB,EDecl),
53 find_common(WA,WB,UA,UB,Common),
54 z_conjunction(UA,AExpr),
55 z_conjunction(UB,BExpr),
56 z_disjunction([AExpr,BExpr],Or),
57 append(Common,[Or],EWhere).
58 sexpansion(simplies(A,B),Env,Expansion) :-
59 !,sexpansion_logic(implies,A,B,Env,Expansion).
60 sexpansion(sequiv(A,B),Env,Expansion) :-
61 !,sexpansion_logic(equiv,A,B,Env,Expansion).
62 sexpansion(snot(S),Env,body(Decls,[not(Condition)])) :-
63 !,expand_and_split(S,Env,Decls,Where),
64 z_conjunction(Where,Condition).
65
66 sexpansion(sforall(Body,S),Env,Expansion) :-
67 !,sexpansion_quantifier(forall,Body,S,Env,Expansion).
68 sexpansion(sexists(Body,S),Env,Expansion) :-
69 !,sexpansion_quantifier(exists,Body,S,Env,Expansion).
70 sexpansion(sexists1(Body,S),Env,Expansion) :-
71 !,sexpansion_quantifier(exists1,Body,S,Env,Expansion).
72
73 sexpansion(pre(S),Env,Expansion) :-
74 !,sexpansion(S,Env,SE),zsplit(SE,Decls,_),
75 find_vars_with_deco(Decls,['\'','!'],PostVars),
76 sexpansion(hide(SE,PostVars),Env,Expansion).
77
78 sexpansion(hide(S,VarsToHide),Env,body(NewDecls,[Exists])) :-
79 !,Exists = exists(body(ExistsDecls,Where),truth),
80 ? expand_and_split(S,Env,Decls,Where),
81 remove_vars_from_decls(Decls,VarsToHide,NewDecls,ExistsDecls).
82
83 sexpansion(project(A,B),Env,Expansion) :-
84 !,sexpansion(A,Env,AE),sexpansion(B,Env,BE),
85 zsplit(AE,AD,_),zsplit(BE,BD,_),
86 vars_of_decls(AD,VarsA),
87 vars_of_decls(BD,VarsB),
88 remove_all(VarsA,VarsB,VarsToRemove),
89 sexpansion(hide(sand(AE,BE),VarsToRemove),Env,Expansion).
90
91 sexpansion(fatsemi(A,B),Env,Expansion) :-
92 !,combine_schemas(A,B,'\'','',Env,Expansion).
93
94 sexpansion(pipe(A,B),Env,Expansion) :-
95 ? !,combine_schemas(A,B,'!','?',Env,Expansion).
96
97 sexpansion(spred(S),Env,Expansion) :-
98 ? !,expand_and_split(S,Env,_,Where),
99 z_conjunction(Where,Expansion).
100
101 sexpansion(comp(Body,nothing),Env,Expansion) :-
102 contains_sdecl(Body),!,
103 add_char_tuple(comp,Body,Env,Expansion).
104
105 sexpansion(mu(Body,nothing),Env,Expansion) :-
106 contains_sdecl(Body),!,
107 add_char_tuple(mu,Body,Env,Expansion).
108
109 sexpansion(lambda(Body,Result),Env,comp(ExpBody,just(Expression))) :-
110 Expression = tuple([Argument,ExpResult]),
111 contains_sdecl(Body),!,
112 sexpansion(Result,Env,ExpResult),
113 sexpansion(comp(Body,nothing),Env,comp(ExpBody,just(Argument))).
114
115 sexpansion(theta(Name,Deco,Renamings),Env,binding(Bindings)) :-
116 ? !,schema_vars(sref(Name,'',[],[]),Env,Vars),
117 generate_bindings(Vars,Deco,Renamings,Bindings).
118
119 sexpansion(Expr,Env,Expansion) :-
120 zexpr_conversion(Expr,Subs,ESubs,Expansion),
121 ? sexpansion(Subs,Env,ESubs).
122
123 sexpansion_quantifier(Quantifier,QBody,S,Env,body(NewSDecls,[Quant])) :-
124 functor(Quant,Quantifier,2),
125 arg(1,Quant,body(QDecls,QWhere)), arg(2,Quant,Expr),
126 %Quant =.. [Quantifier,body(QDecls,QWhere),Expr],
127 expand_and_split(QBody,Env,QDecls,QWhere),
128 expand_and_split(S,Env,SDecls,SWhere),
129 vars_of_decls(QDecls,QVars), remove_vars_from_decls(SDecls,QVars,NewSDecls,_),
130 z_conjunction(SWhere,Expr).
131
132 sexpansion_logic(Junctor,A,B,Env,body(Decl,[Condition])) :-
133 expand_and_split(A,Env,DA,WA),
134 expand_and_split(B,Env,DB,WB),
135 append_decls(DA,DB,Decl),
136 z_conjunction(WA,ExprA),
137 z_conjunction(WB,ExprB),
138 Condition =.. [Junctor,ExprA,ExprB].
139
140 expand_and_split(Expr,Env,Decl,Where) :-
141 ? sexpansion(Expr,Env,Expanded),
142 zsplit(Expanded,Decl,Where).
143 zsplit(body(Decl,Where),Decl,Where).
144
145
146 append_decls(A,B,R) :- append(A,B,M),clean_decl(M,R).
147 %append_where(A,B,R) :- append(A,B,M),clean_where(M,R).
148
149
150 %*******************************************************************************
151 % expand_decls removes all references to other schemas from a declaration
152 expand_decls([],_,[],[]).
153 expand_decls([D|DRest],Env,DExpanded,WExpanded) :-
154 ? expand_decls2(D,Env,DE,WE),
155 append(DE,DERest,DExpanded),
156 append(WE,WERest,WExpanded),
157 ? expand_decls(DRest,Env,DERest,WERest).
158 expand_decls2(decl(Vars,Type),Env,[decl(Vars,EType)],Where) :-
159 ? sexpansion(Type,Env,EType),
160 generate_membership(Vars,EType,Where).
161 expand_decls2(sdecl(S),Env,Decls,Where) :-
162 ? expand_and_split(S,Env,Decls,Where).
163
164 generate_membership([],_,[]).
165 generate_membership([Var|VRest],Set,[member(ref(Var,[]),Set)|MRest]) :-
166 generate_membership(VRest,Set,MRest).
167
168
169 %*******************************************************************************
170 % clean_decl removes double variable declarations
171 clean_decl(Decls,Cleaned) :-
172 clean_decl2(Decls,[],Cleaned).
173 clean_decl2([],_,[]).
174 clean_decl2([decl(Vars,Type)|Rest],Before,Cleaned) :-
175 filter_vars(Vars,Before,UniqueVars),
176 (UniqueVars = [] ->
177 Cleaned = RestCleaned;
178 Cleaned = [decl(UniqueVars,Type)|RestCleaned]),
179 append(UniqueVars,Before,NBefore),
180 clean_decl2(Rest,NBefore,RestCleaned).
181 filter_vars([],_,[]).
182 filter_vars([Var|Rest],Existing,Result) :-
183 ? (member(Var,Existing) -> Result = RestResult ; Result = [Var|RestResult]),
184 filter_vars(Rest,Existing,RestResult).
185
186
187 %*******************************************************************************
188 % find all vars with one of the given decorations
189 find_vars_with_deco(Decls,Decos,Postvars) :-
190 findall(name(N,D),
191 (member(decl(Vars,_),Decls),
192 member(name(N,D),Vars),
193 member(D,Decos)),
194 Postvars).
195
196 %*******************************************************************************
197 % combine two schemas: use pairs of matching vars which link both schemas
198 combine_schemas(A,B,DecoOut,DecoIn,Env,Expansion) :-
199 ? sexpansion(A,Env,AE),sexpansion(B,Env,BE),
200 zsplit(AE,AD,_),zsplit(BE,BD,_),
201
202 find_vars_with_deco(AD,[DecoOut],OutVars),
203 find_vars_with_deco(BD,[DecoIn],InVars),
204 find_matching_vars(OutVars,InVars,DecoOut,DecoIn,RenamingsA,RenamingsB,LocalVars),
205 rename_variables(AE,RenamingsA,AC),
206 rename_variables(BE,RenamingsB,BC),
207 sexpansion(hide(sand(AC,BC),LocalVars),Env,Expansion).
208
209 find_matching_vars([],_,_,_,[],[],[]).
210 find_matching_vars([name(Name,DecoOut)|OutRest],InVars,
211 DecoOut,DecoIn,
212 [rename(New,name(Name,DecoOut))|ARest],
213 [rename(New,name(Name,DecoIn))|BRest],
214 [New|NewRest]) :-
215 member(name(Name,DecoIn),InVars),!,
216 z_counter('match__',NewName),New=name(NewName,''),
217 find_matching_vars(OutRest,InVars,DecoOut,DecoIn,ARest,BRest,NewRest).
218
219 %*******************************************************************************
220 % find_common finds common terms in two lists
221 % find_common(ListA,ListB,UniqueA,UniqueB,Common).
222 find_common(ListA,ListB,UniqueA,UniqueB,Common) :-
223 find_common2(ListA,ListB,ListA,UniqueA,UniqueB,Common).
224 find_common2([A|Rest],ListB,ListA,UniqueA,UniqueB,Common) :-
225 ? ( member(A,ListB) ->
226 (UniqueA = RUniqueA, Common = [A|RCommon])
227 ;
228 (UniqueA = [A|RUniqueA], Common = RCommon)),
229 find_common2(Rest,ListB,ListA,RUniqueA,UniqueB,RCommon).
230 find_common2([],ListB,ListA,[],UniqueB,Common) :-
231 find_common3(ListB,ListA,UniqueB,Common).
232 find_common3([B|Rest],ListA,UniqueB,Common) :-
233 ? ( member(B,ListA) ->
234 (UniqueB = RUniqueB, Common = [B|RCommon])
235 ;
236 (UniqueB = [B|RUniqueB], Common = RCommon)),
237 find_common3(Rest,ListA,RUniqueB,RCommon).
238 find_common3([],_,[],[]).
239
240 %*******************************************************************************
241 rename_variables(Exprs,[],Exprs) :- !.
242 rename_variables(body(Decls,Where),Renamings,body(RDecls,RWhere)) :-
243 !,
244 rename_decls(Decls,Renamings,RDecls),
245 rename_variables2(Where,Renamings,RWhere).
246 rename_variables(Expr,Renamings,Result) :- rename_variables2(Expr,Renamings,Result).
247
248 rename_variables2([],_,[]) :- !.
249 rename_variables2([E|ERest],Renamings,[P|PRest]) :-
250 !,rename_variables2(E,Renamings,P),
251 rename_variables2(ERest,Renamings,PRest).
252 rename_variables2(ref(Name,P),Renamings,ref(New,P)) :-
253 !,
254 ? (member(rename(New,Name),Renamings) ->
255 !,true;
256 New = Name).
257 rename_variables2(Expr,Renamings,Result) :-
258 znamespace(Expr,Outer,Inner,Names,NOuter,NInner,Result),
259 !,
260 rename_variables2(Outer,Renamings,NOuter),
261 remove_renamings(Renamings,Names,NRenamings),
262 rename_variables2(Inner,NRenamings,NInner).
263 rename_variables2(Expr,Renamings,Result) :-
264 zexpr_conversion(Expr,Subs,PSubs,Result),
265 rename_variables2(Subs,Renamings,PSubs).
266
267 rename_decls([],_,[]).
268 rename_decls([sdecl(S)|DRest],Renamings,[sdecl(S)|RRest]) :-
269 !,rename_decls(DRest,Renamings,RRest).
270 rename_decls([decl(Vars,Type)|DRest],Renamings,[decl(RVars,Type)|RRest]) :-
271 !,rename_decl_vars(Vars,Renamings,RVars),
272 rename_decls(DRest,Renamings,RRest).
273 rename_decl_vars([],_,[]).
274 rename_decl_vars([Old|ORest],Renamings,[New|NRest]) :-
275 (memberchk(rename(New,Old),Renamings) -> true ; Old = New),
276 rename_decl_vars(ORest,Renamings,NRest).
277
278 remove_renamings([],_,[]).
279 remove_renamings([rename(New,Old)|RRest],Names,Renamings) :-
280 ? ( member(Old,Names) ->
281 Renamings = ORenamings
282 ;
283 Renamings = [rename(New,Old)|ORenamings]),
284 remove_renamings(RRest,Names,ORenamings).
285
286 %********************************************************************************
287 % decorates all variables of the given schema by renaming its variables
288 decorate(Expr,'',Expr) :- !.
289 decorate(Expr,Deco,Result) :-
290 zsplit(Expr,Decls,Where),
291 decorate_renamings(Decls,Deco,Renamings),
292 rename_variables(body(Decls,Where),Renamings,Result).
293 decorate_renamings([],_,[]).
294 decorate_renamings([decl(Vars,_)|DRest],Deco,Renamings) :-
295 findall(rename(name(Name,NewDeco),name(Name,OldDeco)),
296 (member(name(Name,OldDeco),Vars),atom_concat(OldDeco,Deco,NewDeco)),
297 LRenamings),
298 append(LRenamings,ORenamings,Renamings),
299 decorate_renamings(DRest,Deco,ORenamings).
300
301 %********************************************************************************
302 % returns all variables of a declaration as a list
303 vars_of_decls(Decls,Vars) :-
304 findall(V,(member(decl(Vs,_),Decls),member(V,Vs)),Vars).
305
306 remove_vars_from_decls([],_,[],[]).
307 remove_vars_from_decls([decl(Vars,Type)|Rest],ToRemove,RestDecls,RemovedDecls) :-
308 split_found_and_rest(Vars,ToRemove,RestVars,RemovedVars),
309 append_nonempty_decl(RestVars,Type,RRestDecls,RestDecls),
310 append_nonempty_decl(RemovedVars,Type,RRemovedDecls,RemovedDecls),
311 remove_vars_from_decls(Rest,ToRemove,RRestDecls,RRemovedDecls).
312 append_nonempty_decl(Vars,Type,Rest,Result) :-
313 (Vars = [] ->
314 Result = Rest;
315 Result = [decl(Vars,Type)|Rest]).
316 split_found_and_rest([],_,[],[]).
317 split_found_and_rest([Var|VRest],ToRemove,RRest,[Var|RRemoved]) :-
318 ? member(Var,ToRemove),!,
319 split_found_and_rest(VRest,ToRemove,RRest,RRemoved).
320 split_found_and_rest([Var|VRest],ToRemove,[Var|RRest],RRemoved) :-
321 split_found_and_rest(VRest,ToRemove,RRest,RRemoved).
322
323
324
325 %********************************************************************************
326 % generate bindings for a list of given variables
327 generate_bindings([],_,_,[]).
328 generate_bindings([Fieldname|FRest],Deco,Renamings,[bindfield(Fieldname,ref(Refname,[]))|BRest]) :-
329 Fieldname = name(OldName,OldDeco),
330 atom_concat(OldDeco,Deco,NewDeco),
331 ? (member(rename(Refname,name(OldName,NewDeco)),Renamings) ->
332 !,true;
333 Refname = name(OldName,NewDeco)),
334 generate_bindings(FRest,Deco,Renamings,BRest).
335
336 %********************************************************************************
337
338
339 add_simple_types_info(Env,env(Env,STypes)) :-
340 env_z_defs(Env,Def),
341 findall(Name,(member(given(L),Def),member(Name,L)),Givens),
342 findall(Name,member(namedset(Name,_),Def),Namedsets),
343 append(Givens,Namedsets,STypes).
344
345 lookup(env(Env,_),Name,Params,Expr) :- zlookup_schema(Env,Name,Params,Expr).
346
347 %**********************************************************************
348 % generation of characteristic tuple
349 contains_sdecl(body(Decl,_)) :-
350 contains_sdecl2(Decl).
351 contains_sdecl2([sdecl(_)|_]) :- !.
352 contains_sdecl2([_|R]) :- contains_sdecl(R).
353
354 add_char_tuple(Functor,Body,Env,Result) :-
355 Body=body(Decl,_),
356 characteristic_tuple(Decl,Env,Exprlist),
357 maybetuple(Exprlist,Expression),
358 functor(R,Functor,2),
359 arg(1,R,Body),
360 arg(2,R,just(Expression)),
361 sexpansion(R,Env,Result).
362 characteristic_tuple([],_,[]).
363 characteristic_tuple([D|Rest],Env,Exprlist) :-
364 characteristic_tuple2(D,Env,Exprs),
365 append(Exprs,Restlist,Exprlist),
366 characteristic_tuple(Rest,Env,Restlist).
367 characteristic_tuple2(decl(Vars,_),_,References) :-
368 names_to_references(Vars,References).
369 characteristic_tuple2(sdecl(sref(Name,Deco,Params,Renamings)),Env,[binding(Bindings)]) :-
370 sexpansion(sref(Name,'',Params,[]),Env,body(Decls,_)),
371 vars_of_decls(Decls,Vars),
372 generate_bindings(Vars,Deco,Renamings,Bindings).
373 maybetuple([E],E) :- !.
374 maybetuple([A,B|R],tuple([A,B|R])).
375
376 names_to_references([],[]).
377 names_to_references([Name|Nrest],[ref(Name,[])|Rrest]) :-
378 names_to_references(Nrest,Rrest).