1 % (c) 2009-2019 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(proz, [open_proz_file/2]).
6
7 :- use_module(library(lists)).
8 :- use_module(library(ordsets),[ord_union/3,ord_subtract/3]).
9
10 :- use_module(probsrc(debugging_calls)).
11 :- use_module(probsrc(tools)).
12 :- use_module(probsrc(debug)).
13 :- use_module(probsrc(self_check)).
14 :- use_module(probsrc(b_state_model_check)).
15 :- use_module(probsrc(store)).
16 :- use_module(probsrc(error_manager)).
17
18 :- use_module(probsrc(bmachine_structure)).
19 :- use_module(probsrc(bsyntaxtree)).
20 :- use_module(probsrc(b_ast_cleanup),[clean_up/3,clean_up_l_wo_optimizations/4, clean_up_l_with_optimizations/4]).
21 %:- use_module(probsrc(translate),[print_machine/1]).
22
23 :- use_module(z_tools).
24 :- use_module(fuzzfile).
25 :- use_module(schemaexpansion).
26 :- use_module(dependence,[schema_dependence/2]).
27 :- use_module(zenvironment).
28 :- use_module(z_typechecker).
29 :- use_module(ztransformations).
30 :- use_module(consistencycheck).
31 :- use_module(subexpressions).
32
33 :- use_module(probsrc(module_information)).
34 :- module_info(group,proz).
35 :- module_info(description,'This is the central ProZ module for translating Z specification into B.').
36
37 /* --------------- FUZZ ----------------- */
38
39 reset_proz :-
40 reset_fuzzfile,
41 retractall(unchanged_vars_for_partial_zoperation(_,_)).
42
43 open_proz_file(File,BMachine) :-
44 reset_proz,
45 load_fuzzfile(File),
46 get_z_filename(File,Filename),
47 init_fuzz_mode(Filename,BMachine).
48 % ( translate:print_machine(BMachine) -> true
49 % ; otherwise -> write('pretty-printing the translated B machine failed.\n')).
50
51 get_z_filename(File,Filename) :-
52 get_tail_filename(File,Filename1),
53 ( split_filename(Filename1,Filename,_) -> true
54 ; otherwise -> Filename1 = Filename).
55
56
57 /* Initialize all basic types */
58 init_fuzz_mode(Filename,BMachine) :-
59 typed_specification(Dependencies,TypedSpecification),
60
61 /* initialise the z schemas */
62 ~~mnf( fuzzschemas(TypedSpecification,Schemas) ),
63 ~~mnf( classify_schemas(Schemas, Dependencies, Classification) ),
64
65 /* construct any statements for initialisation and operations */
66 ~~mnf( construct_init(Schemas,Classification,InitAny) ),
67 ~~mnf( construct_operations(Schemas,Classification,Ops) ),
68
69 ~~mnf( optimize_anys(anys(InitAny,Ops),anys(InitAny2,Ops2)) ),
70
71 ~~mnf( get_proz_settings(Schemas,Classification,Filename,TypedSpecification,Settings) ),
72
73 create_z_machine(Filename,TypedSpecification,InitAny2,Ops2,Schemas,Classification,Settings,BMachine).
74
75 :- public fuzzschemas/2, classify_schemas/3, construct_init/3, construct_operations/3,
76 optimize_anys/2, get_proz_settings/5. % because Spider cannot deal with ~~mnf
77
78 typed_specification(Dependencies,TypedSpecification) :-
79 ~~mnf( get_z_definitions(InitialZSpec) ),
80
81 ~~mnf( schema_dependence(InitialZSpec,Dependencies) ),
82
83 /* simplify without having type information */
84 ~~mnf( simplify_untyped(InitialZSpec,ZSpecification) ),
85
86 /* add type informations */
87 ~~mnf( global_environment(ZSpecification,_,TypedSpecification1) ),
88
89 /* simplify the specification */
90 ~~mnf( simplify_typed(TypedSpecification1,TypedSpecification) ).
91
92 create_z_machine(Filename, TypedSpecification, InitAny, Ops, Schemas, Classification, Settings, BMachine) :-
93 create_machine(Filename,Empty),
94
95 /* register new data types */
96 ~~mnf( set_given_sets(TypedSpecification,Empty,MSets) ),
97 ~~mnf( set_freetypes(TypedSpecification,MSets,MFreetypes) ),
98
99 /* register initialisation and operations */
100 ~~mnf( set_init(InitAny,MFreetypes,MInit) ),
101 ~~mnf( set_operations(Ops,MInit,MOps) ),
102
103 ~~mnf( set_variables(Schemas,Classification,MOps,MVars) ),
104 /* mnf( register_scope(Schemas,Classification) ), */
105 ~~mnf( set_constants(TypedSpecification,MVars,MConstants) ),
106
107 ~~mnf( set_settings(Settings, MConstants, MSettings) ),
108
109 b_global_sets:b_clear_global_set_type_definitions, % TO DO: do the full pre-compiling before cleaning up !?!?
110 % cleanup will need to get deferred sets, ...
111
112 ~~mnf( clean_up_machine(MSettings,BMachine) ).
113
114 :- public set_init/3, set_operations/3, set_given_sets/3, set_freetypes/3,
115 set_variables/4, set_constants/3, set_settings/3,
116 clean_up_machine/2. % because Spider does not deal with ~~mnf
117
118 simplify_untyped -->
119 zcheck('initial Z specification',[]),
120
121 /* replace simple freetypes with named sets */
122 freetype2namedsets, zcheck('after replacing simple freetypes by named sets',[]),
123
124 /* remove the declaration of the ignore pregen */
125 remove_ignore_decl, zcheck('after removing proz-ignore declarations',[]),
126
127 /* exchanged simple references to schemas by SEXPR(sref(...)) */
128 clearsrefs, zcheck('after clearsrefs',[]),
129
130 /* substitute references to abbreviations with their definition */
131 removeabbreviations, zcheck('after removal of abbreviations',[]),
132
133 /* flatten the specification */
134 sexpansion, zcheck('after schema expansion',[nlabel(scalc)]).
135
136 simplify_typed -->
137 /* remove schema expressions */
138 removesexpr, ztcheck('after removing schema expressions',[nlabel(scalc)]),
139
140 /* some general simplifications */
141 ggsimplify, ztcheck('after some general simplifications',[nlabel(scalc)]).
142
143 zcheck(Msg,A,Z,Z) :- check_z_structure(Z,Msg,A).
144 ztcheck(Msg,A,Z,Z) :- check_z_structuret(Z,Msg,A).
145
146 %*******************************************************************************
147 % optimization of ANY-statements
148 optimize_anys -->
149 exists_to_anys,
150 optimize_global_predicates.
151
152 optimize_global_predicates(anys(InitAny,OldOps),anys(InitAny,NewOps)) :-
153 global_predicates(InitAny,OldOps,GlobalPredicates),
154 remove_global_predicates(OldOps,GlobalPredicates,NewOps).
155
156 % if the predicate is just of one exists predicate, we
157 % merge any and exists.
158 exists_to_anys(anys(OldInitAny,OldOps),anys(NewInitAny,NewOps)) :-
159 exists_to_anys2(OldInitAny,NewInitAny),
160 exists_to_anys_ops(OldOps,NewOps).
161 exists_to_anys_ops([],[]).
162 exists_to_anys_ops([op(Op,Params,Results,OldAny,ParaTypes,ResultTypes)|ORest],
163 [op(Op,Params,Results,NewAny,ParaTypes,ResultTypes)|NRest]) :-
164 exists_to_anys2(OldAny,NewAny),
165 exists_to_anys_ops(ORest,NRest).
166 exists_to_anys2(any(Vars,Types,[ti(exists(Body,Pred),bool)],LHS,RHS),NewAny) :-
167 !,Body=ti(body(_,Wheres),set(schema(ZFields))),
168 append(Wheres,[Pred],NPreds1),
169 clean_wheret(NPreds1,NPreds),
170 % todo: not safe with name clashes
171 zfields2b(ZFields,EVars,ETypes),
172 append(Vars,EVars,NVars),
173 append(Types,ETypes,NTypes),
174 exists_to_anys2(any(NVars,NTypes,NPreds,LHS,RHS),NewAny).
175 exists_to_anys2(Any,Any).
176
177 %*******************************************************************************
178 /* extract constants, their types and properties from the specification */
179 set_constants(TypedDefs,In,Out) :-
180 write_section(abstract_constants,TypedConstants,In,M),
181 write_section(properties,Property,M,Out),
182 extract_constants2(TypedDefs, Constants, Types, Properties),
183 conjunct_predicates(Properties,Property),
184 z_translate_typed_identifiers(Constants,Types,[],TypedConstants).
185
186 extract_constants2([],[],[],[]).
187 extract_constants2([Def|Rest], Constants, Types, Properties) :-
188 extract_constants3(Def, LocalConstants, LocalTypes, ZPropertiesTi),
189 !,
190 z_translate(ZPropertiesTi,LocalProperties),
191 append(LocalConstants, RestConstants, Constants),
192 append(LocalTypes, RestTypes, Types),
193 append(LocalProperties, RestProperties, Properties),
194 extract_constants2(Rest, RestConstants, RestTypes, RestProperties).
195 extract_constants2([_|Rest], Constants, Types, Properties) :-
196 extract_constants2(Rest, Constants, Types, Properties).
197 extract_constants3(Axdef, Constants, Types, Predicates) :-
198 ti_expr(Axdef,axdef(BodyTi)),!,
199 extract_btypes(Axdef,Constants,Types),
200 ti_expr(BodyTi,body(_,Predicates)).
201 extract_constants3(PredTi, [], [], [Predicate]) :-
202 ti_expr(PredTi, pred(Predicate)).
203
204
205 /* appends a decoration to the each variable name of the given list of
206 variable names */
207 /* unused at the moment:
208 decorate([],_,[]) :- !.
209 decorate([Var|Vars], Deco, [Decorated|Rest]) :-
210 !,
211 decorate(Var, Deco, Decorated),
212 decorate(Vars, Deco, Rest).
213 decorate(Var, Deco, Decorated) :-
214 z_translate_identifier(name(Var,Deco),Decorated).
215 */
216
217
218 remove_vars(Orig,OrigTypes,[],Orig,OrigTypes) :- !.
219 remove_vars(Orig,OrigTypes,[Var|Rest],ResVars,ResTypes) :-
220 remove_var(Orig,OrigTypes,Var,Vars,Types),
221 remove_vars(Vars,Types,Rest,ResVars,ResTypes).
222 remove_var([],[],_,[],[]) :- !.
223 remove_var([Var|Orig],[_|OrigTypes],Var,ResVars,ResTypes) :-
224 remove_var(Orig,OrigTypes,Var,ResVars,ResTypes).
225 remove_var([Var|Orig],[Type|OrigTypes],OtherVar,[Var|ResVars],[Type|ResTypes]) :-
226 Var \= OtherVar,
227 remove_var(Orig,OrigTypes,OtherVar,ResVars,ResTypes).
228
229 /* Extract all schemas from the fuzz schema definitions */
230 fuzzschemas([],[]).
231 fuzzschemas([Def|Rest],FSchemas) :-
232 ( schema_id_body(Def,Id,Body) ->
233 FSchemas = [fschema(Id, Body, Vars, Types)|FRest],
234 extract_btypes(Def,Vars,Types)
235 ; otherwise ->
236 FSchemas = FRest),
237 fuzzschemas(Rest,FRest).
238
239 schema_id_body(Ti,Id,Body) :- ti_expr(Ti,Expr),schema_id_body2(Expr,Id,Body).
240 schema_id_body2(sdef(shead(Id,[]),Body),Id,Body).
241 schema_id_body2(defeq(shead(Id,[]),Body),Id,Body).
242
243 %*******************************************************************************
244 % Extract settings from specifications and put them into the meta data of
245 % a machine
246 get_proz_settings(Schemas,Classification,Filename,TypedSpecification,Settings) :-
247 findall(Setting,
248 get_proz_setting(Schemas,Classification,Filename,TypedSpecification,Setting),
249 Settings).
250 get_proz_setting(Schemas,Classification,_Filename,TypedSpecification,Setting) :-
251 get_schema_by_class(settings,Classification,Schemas,ZDef,ZVars,ZTypes),
252 get_proz_expr_setting(ZDef,ZVars,ZTypes,TypedSpecification,Setting).
253 get_proz_setting(Schemas,Classification,_Filename,_TypedSpecification,goal(BGoal)) :-
254 get_schema_by_class(goal,Classification,Schemas,ZDef,_,_),
255 ti_expr(ZDef,body(_,ZGoals)),
256 z_translate(ZGoals,BGoals1),
257 clean_up_l_wo_optimizations(BGoals1,[],BGoals,schemas),
258 conjunct_predicates(BGoals,BGoal).
259 get_proz_setting(_Schemas,_Classification,_Filename,_TypedSpecification,[]).
260 get_proz_expr_setting(ZDef,_ZVars,_ZTypes,TypedSpecification,animation_function(BAnim,BDefaultAnim,Images)) :-
261 ( extract_def_by_equality(ZDef,'animation_function',AFType,BAnim) ->
262 ( extract_def_by_equality(ZDef,'animation_function_default',DFType,BDefaultAnim) -> true
263 ; otherwise -> BDefaultAnim = none)
264 ; extract_def_by_equality(ZDef,'animation_function_default',DFType,BDefaultAnim) ->
265 BAnim = none),
266 ( AFType = DFType -> true
267 ; otherwise ->
268 add_error(proz,'animation_function and animation_function_default should be of the same type')),
269 ( AFType = set(tuple([tuple([_,_]),ImageType])) ->
270 ( extract_image_filenames(ImageType,TypedSpecification,Images) -> true
271 ; otherwise -> add_error(proz,'Unable to map animation function to images'))
272 ; otherwise ->
273 add_error(proz,'Unexpected type of animation_function'),fail).
274
275 extract_def_by_equality(ZDef,Name,Type,BExpr) :-
276 get_equality(ZDef,ti(ref(name(Name,''),[]),Type),ZExpr),
277 z_translate(ZExpr,BExpr1),
278 clean_up(BExpr1,[],BExpr).
279 get_equality(ti(body(_,ZWhere),_),Name,Equal) :-
280 !,member(A,ZWhere),get_equality(A,Name,Equal),!.
281 get_equality(ti(equal(X,Y),_),TName,Equal) :-
282 ( X=TName -> Equal=Y
283 ; Y=TName -> Equal=X).
284 extract_image_filenames(given(IName),TypedSpecification,Images) :-
285 memberchk(ti(namedset(IName,Elements),_),TypedSpecification),
286 z_translate_identifiers(Elements,PImages),
287 maplist(append_gif,PImages,Images).
288 append_gif(Name,Gif) :- atom_concat(Name,'.gif',Gif).
289
290 set_settings(Settings,In,Out) :-
291 write_section(meta,[proz_settings(Settings)],In,Out).
292
293 %*******************************************************************************
294 % Schema classification
295
296 /* Classifies each schema, i.e. assign a type (state, init, op, other)
297 to each given schema */
298 classify_schemas(Schemas,Deps,[cls(init,Init),cls(state,State)|Operations]) :-
299 ( classify_init_state(Deps, Init, State) -> true
300 ; Deps= [] ->
301 add_error(proz,'This Z specification has no schema and cannot be initialised.'),fail
302 ; otherwise ->
303 %debug:print_quoted(Deps),nl,
304 ajoin(['Was not able to identify Z state schema.\n',
305 'Please check if there is a schema called Init that\n',
306 'references exactly one other schema (the state) in its\n',
307 'declaration part.'], Msg),
308 add_error(proz,Msg),fail),
309 classify_schemas(Schemas, Schemas, Deps, Init, State, Operations).
310
311 :- use_module(library(lists),[sublist/5]).
312 classify_init_state(Deps,'Init',State) :-
313 findall(S,member(dep('Init',S),Deps),[State]).
314 classify_init_state(Deps,SchemaName,State) :-
315 % see if we can find another Schema with Init in its name, which references exactly one other atomic Schema
316 member(dep(SchemaName,_),Deps),
317 atom_codes(SchemaName,SCodes),
318 atom_codes('Init',InitCodes1), atom_codes('init',InitCodes2),
319 (sublist(SCodes,InitCodes1,_,_,_) -> true ; sublist(SCodes,InitCodes2,_,_,_)),
320 findall(S,member(dep(SchemaName,S),Deps),[State]), % we should check that State is not Delta or Xi state schema
321 add_message(proz,'Did not find Init Schema; assuming following schema to define the initialisation: ',SchemaName).
322
323 classify_schemas([], _, _, _, _, []).
324 classify_schemas([Schema|SRest], AllSchemas, Deps, Init, State, [cls(Class,Id)|CRest]) :-
325 classify_schema(Schema, AllSchemas, Deps, Init, State, Class),
326 !,Schema = fschema(Id,_,_,_),
327 classify_schemas(SRest, AllSchemas, Deps, Init, State, CRest).
328 classify_schemas([_|SRest], AllSchemas, Deps, Init, State, CRest) :-
329 classify_schemas(SRest, AllSchemas, Deps, Init, State, CRest).
330
331 classify_schema(fschema('Scope',_,ScopeVars,_), AllSchemas, _, _, State, scope) :-
332 member(fschema(State,_,StateVars,_),AllSchemas),
333 all_members(ScopeVars,StateVars),!.
334 classify_schema(fschema('ProZ_Goal',_,ScopeVars,_), AllSchemas, _, _, State, goal) :-
335 member(fschema(State,_,StateVars,_),AllSchemas),
336 all_members(ScopeVars,StateVars),!.
337 classify_schema(fschema('ProZ_Settings',_,_,_), _AllSchemas, _, _, _State, settings) :- !.
338 classify_schema(fschema('Invariant',_,InvVars,_), AllSchemas, _, _, State, inv) :-
339 member(fschema(State,_,StateVars,_),AllSchemas),
340 all_members(InvVars,StateVars),!.
341 classify_schema(Schema, AllSchemas, Deps, Init, State, op) :-
342 Schema = fschema(Id,_,_,_),
343 Id \= State, Id \= Init,
344 is_operation(AllSchemas, Deps, Schema, State),
345 !.
346
347 :- dynamic unchanged_vars_for_partial_zoperation/2.
348 :- use_module(library(ordsets),[list_to_ord_set/2,ord_member/2]).
349 /* Is the given schema an operation?
350 1) It does include all variables of the state schema
351 2) It does include all variables of the after state
352 3) No other schema includes this schema */
353 is_operation(AllSchemas, Deps, fschema(Id,_,OpVars,_), State) :-
354 \+ member(dep(_,Id),Deps), % not included by other schema
355 %format('Try operation ~w with OpVars ~w and State schema is ~w~n',[Id,OpVars,State]),
356 member(fschema(State,_,StateVars,_),AllSchemas), % get the variables of the state schema
357 !,
358 decorate_vars(StateVars,'\'',AfterStateVars),
359 append(StateVars,AfterStateVars,NeededVars),
360 (all_members(NeededVars,OpVars) -> true
361 ; %format('~nSchema not recognised as operation: ~w over state variables ~w~n',[Id,StateVars]),
362 OpVars \= [],
363 list_to_ord_set(StateVars,SVS),
364 list_to_ord_set(OpVars,OVS),
365 primed_unprimed_ok(OVS,SVS), % check that all variables that are referenced occur with and without prime
366 ord_subtract(SVS,OVS,Unchanged),
367 formatsilent('Promoting Schema ~w to Z Operation by adding unchanged variables: ~w~n',[Id,Unchanged]),
368 % TO DO: in test 1094 for System.fuzz the InitSystem operation is also recognised
369 assert(unchanged_vars_for_partial_zoperation(Id,Unchanged))
370 ).
371
372 primed_unprimed_ok([],_).
373 primed_unprimed_ok([name(ID,''),name(ID,'\'')|T],SVS) :- !,primed_unprimed_ok(T,SVS).
374 primed_unprimed_ok([NAME|T],SVS) :- \+ ord_member(NAME,SVS),primed_unprimed_ok(T,SVS).
375
376 /* unused:
377 operation_variables([],[]).
378 operation_variables([name(_,Deco)|Rest],NeededVars) :-
379 member(Deco,['?','!']),!,operation_variables(Rest,NeededVars).
380 operation_variables([Var|Rest],NeededVars) :-
381 select(Var,NeededVars,RestVars),
382 !,operation_variables(Rest,RestVars).
383 */
384
385 get_schema_by_class(Cls,Classification,Schemas,Def,Vars,Types) :-
386 memberchk(cls(Cls,Name),Classification),
387 memberchk(fschema(Name,Def,Vars,Types),Schemas).
388
389 %*******************************************************************************
390 % Initialisation
391
392 construct_init(Schemas,Classification,Any) :-
393 member(cls(init,Init),Classification),
394 member(fschema(Init,Def,_,_),Schemas),
395
396 member(cls(state,State),Classification),
397 member(fschema(State,_,StateVars,StateTypes),Schemas),!,
398
399 (translate_initialisation(Def,StateVars,StateTypes,Any) -> true
400 ; otherwise ->
401 add_error(proz,'Internal error while translating initialisation'),fail).
402
403 translate_initialisation(TDef,StateVars,StateTypes,Any) :-
404 check_z_substructuret(TDef,body,'invalid Z structure in initialisation',[nlabel(scalc)]),
405 findall(rename(name(Name,'\''),name(Name,'')),
406 member(name(Name,''), StateVars),
407 Renamings),
408 rename_variablest(TDef,Renamings,TypedDef),
409 ti_expr(TypedDef,body(_,TypedWhere)),
410
411 decorate_vars(StateVars,'\'',ZAnyVars),
412 z_translate_typed_identifiers(StateVars,StateTypes,[],Lhs),
413 z_translate_typed_identifiers(ZAnyVars,StateTypes,[],Rhs),
414 Any = any(ZAnyVars,StateTypes,TypedWhere,Lhs,Rhs).
415
416 %create_ti(Name,Type,TI) :- ti_expr(TI,Name),ti_type(TI,Type).
417
418
419 set_init(InitAny,In,Out) :-
420 write_section(initialisation,Statement,In,Out),
421 construct_any(InitAny,[],Statement).
422
423 %*******************************************************************************
424 % Variables and invariant
425
426 set_variables(Schemas,Classification,In,Out) :-
427 write_section(abstract_variables,Variables,In,M),
428 write_section(invariant,Invariant,M,Out),
429
430 member(cls(state,State),Classification),
431 member(fschema(State,_,ZVars,Types),Schemas),!,
432
433 z_translate_typed_identifiers(ZVars,Types,[],Variables),
434
435 ( memberchk(cls(inv,Inv),Classification) ->
436 memberchk(fschema(Inv,TypedDef,_,_),Schemas),
437 println_silent('Z invariant found'),
438 ti_expr(TypedDef,body(_,ZInvs))
439 ; otherwise ->
440 ZInvs = []),
441 ( z_translate(ZInvs,Invariants) -> true
442 ; otherwise -> add_error(proz, 'Internal error while translating invariant')),
443 conjunct_predicates(Invariants,Invariant).
444
445
446 %*******************************************************************************
447 % Scope
448
449 /* currently unused:
450 register_scope(Schemas,Classification) :-
451 ( memberchk(cls(scope,Scope),Classification) ->
452 ( memberchk(fschema(Scope,TypedDef,_,_),Schemas),!,
453 print('Z scope schema found'),nl,
454 ti_expr(TypedDef,body(_,ZScope)),
455 ( (z_translate(ZScope,ScopePredicates),conjunct_predicates(ScopePredicates,ScopePredicate)) ->
456 true
457 ; otherwise ->
458 add_error(proz, 'Internal error while translating scope'),ScopePredicate=none
459 )
460 )
461 ; otherwise ->
462 ScopePredicate = none),
463 set_scope_expression(ScopePredicate).
464 */
465
466 %*******************************************************************************
467 % Operations
468
469 construct_operations(Schemas,Classification,Operations) :-
470 member(cls(state,State),Classification),
471 member(fschema(State,_,StateVars,StateTypes),Schemas),!,
472 findall(Op,member(cls(op,Op),Classification),Ops),
473 construct_operations2(Ops,Schemas,StateVars,StateTypes,Operations).
474 construct_operations2([],_,_,_,[]).
475 construct_operations2([Op|ORest],Schemas,StateVars,StateTypes,[Operation|OpRest]) :-
476 member(fschema(Op,Def,Vars,Types),Schemas),!,
477 ( translate_operation(Op,Def,Vars,Types,StateVars,StateTypes,Params,ParaTypes,Results,ResultTypes,Any) ->
478 Operation = op(Op,Params,Results,Any,ParaTypes,ResultTypes),
479 OpArgs =.. [Op|Params],printsilent('Z operation: '),printsilent(OpArgs),nls
480 ; otherwise ->
481 add_error(proz,'Internal error while translating operation', Op)
482 ),
483 construct_operations2(ORest,Schemas,StateVars,StateTypes,OpRest).
484
485 set_operations(Ops,In,Out) :-
486 write_section(promoted,Promoted,In,M),
487 write_section(operation_bodies,Bodies,M,Out),
488 get_operations(Ops,Bodies,Promoted).
489 get_operations([],[],[]).
490 get_operations([Operation|ORest],[BOperation|Brest],[Promoted|PromotedRest]) :-
491 get_operation(Operation,BOperation,Promoted),
492 get_operations(ORest,Brest,PromotedRest).
493 get_operation(op(Op,Params,Results,Any,ParaTypes,ResultTypes),TOp,OpId) :-
494 OpType = op(ResultTypes,ParaTypes),
495 create_texpr(identifier(op(Op)),OpType,[],OpId),
496 create_b_identifiers(Params,ParaTypes,BParams),
497 create_b_identifiers(Results,ResultTypes,BResults),
498 create_texpr(operation(OpId,BResults,BParams,Statement),OpType,OpInfo,TOp), % [] == Info ?? extract from Statement ??
499 add_locals([BParams,BResults],[],Locals),
500 construct_any(Any,Locals,Statement),
501 get_texpr_info(Statement,StmtInfo),
502 include(is_operation_info,StmtInfo,OpInfo).
503 create_b_identifiers([],[],[]).
504 create_b_identifiers([Name|Nrest],[Type|Trest],[Id|Irest]) :-
505 create_texpr(identifier(Name),Type,[],Id),
506 create_b_identifiers(Nrest,Trest,Irest).
507
508 is_operation_info(modifies(_)).
509 is_operation_info(reads(_)).
510
511 translate_operation(OpName,Def,Vars,Types,StateVars,StateTypes,Params,ParamTypes,Result,ResultTypes,Any) :-
512 check_z_substructuret(Def,body,'invalid Z structure in operation',[nlabel(scalc)]),
513 filter_vars_by_deco(Vars,Types,'?',ZParams,ParamTypes),
514 filter_vars_by_deco(Vars,Types,'!',ZResult,ResultTypes),
515 z_translate_identifiers(ZParams,Params),
516 z_translate_identifiers(ZResult,Result),
517
518 copy_result_vars(ZResult,ZAnyResults),
519
520 find_unchanged(Def,UnchangedVars1,Def2),
521 (unchanged_vars_for_partial_zoperation(OpName,AdditionalUnchanged)
522 % check if we have an operation that does not talk about all variables, but we still classified it as an operation
523 -> append(UnchangedVars1,AdditionalUnchanged,UnchangedVars)
524 ; UnchangedVars = UnchangedVars1
525 ),
526 findall(rename(name(Name,''),name(Name,'\'')),
527 member(name(Name,''),UnchangedVars),
528 Renamings1),
529 findall(rename(name(Name,Deco),name(Name,'!')),
530 member(name(Name,Deco),ZAnyResults),
531 Renamings2),
532 append(Renamings1,Renamings2,Renamings),
533
534 rename_variablest(Def2,Renamings,TypedAnyPreconditions),
535
536 ti_expr(TypedAnyPreconditions,body(_,TypedWheres)),
537
538 append([ZParams,ZResult,UnchangedVars],NotAffectedVars),
539 remove_vars(StateVars,StateTypes,NotAffectedVars,ZChangedVars,ChangedVarTypes),
540 decorate_vars(ZChangedVars,'\'',ZChangedVarsPrimed),
541
542 % extract other vars (neither input,output nor state variables)
543 decorate_vars(StateVars,'\'',AfterStateVars),
544 append([StateVars,AfterStateVars,ZParams,ZResult],InOutStateVars),
545 remove_vars(Vars,Types,InOutStateVars,ZOther,OtherTypes),
546
547 % Z Vars and their types in the ANY declaration
548 append([ZChangedVarsPrimed,ZAnyResults,ZOther],ZAnyVars),
549 append([ChangedVarTypes,ResultTypes,OtherTypes],AnyTypes),
550
551 % References in the substitution
552 append(ZChangedVarsPrimed,ZAnyResults,ZRightHandSubst),
553 append(ZChangedVars,ZResult,ZLeftHandSubst),
554 append(ChangedVarTypes,ResultTypes,LeftRightHandTypes),
555 z_translate_typed_identifiers(ZLeftHandSubst,LeftRightHandTypes,[],Lhs),
556 z_translate_typed_identifiers(ZRightHandSubst,LeftRightHandTypes,[],Rhs),
557
558 Any = any(ZAnyVars,AnyTypes,TypedWheres,Lhs,Rhs).
559
560 copy_result_vars([],[]).
561 copy_result_vars([name(Name,Deco)|Rest],[name(Name,NewDeco)|NRest]) :-
562 z_counter(Deco,NewDeco),
563 copy_result_vars(Rest,NRest).
564
565 filter_vars_by_deco([],[],_,[],[]).
566 filter_vars_by_deco([V|VRest],[T|TRest],Deco,Param,ParamTypes) :-
567 ( V = name(_,Deco) ->
568 (Param,ParamTypes) = ([V|PRest],[T|PTRest])
569 ; otherwise ->
570 (Param,ParamTypes) = (PRest, PTRest)),
571 filter_vars_by_deco(VRest,TRest,Deco,PRest,PTRest).
572
573 %*******************************************************************************
574 % construction of B any statements from preformatted Z predicates and expressions
575 construct_any(any(Vars,Types,ZConds,LHS,RHS),Locals1,TExpr) :-
576 % Translate the guard to B:
577 z_translate(ZConds,BConds),conjunct_predicates(BConds,BCond),
578 % Translate local variables to B:
579 z_translate_typed_identifiers(Vars,Types,[],Identifiers),
580 add_locals([Identifiers],Locals1,Locals),
581 % Determine which variables have been used by the guard:
582 find_identifier_uses(BCond,Locals,GuardReads),
583 % Construct inner substitution:
584 construct_substitution(LHS,RHS,Locals,InnerSubst,Writes,SubstReads),
585 % Construct ANY or SELECT:
586 ord_union(GuardReads,SubstReads,AllReads),
587 Info = [modifies(Writes),reads(AllReads)],
588 construct_any_or_select(Identifiers,BCond,Info,InnerSubst,AnyOrSelect),
589 create_texpr(AnyOrSelect,subst,Info,TExpr).
590 construct_any_or_select([],BCond,Info,InnerSubst,select([When])) :- !,
591 create_texpr(select_when(BCond,InnerSubst),subst,Info,When).
592 construct_any_or_select(Identifiers,BCond,_Info,InnerSubst,any(Identifiers,BCond,InnerSubst)).
593
594 construct_substitution(LHS,RHS,Locals,TExpr,Writes,Reads) :-
595 create_texpr(Subst,subst,[modifies(Writes),reads(Reads)],TExpr),
596 construct_substitution2(LHS,RHS,Locals,Subst,Writes,Reads).
597 construct_substitution2([],[],_Locals,skip,[],[]) :- !.
598 construct_substitution2(LHS,RHS,Locals,assign(LHS,RHS),Writes,Reads) :-
599 get_texpr_ids(LHS,UWrites),sort(UWrites,Writes1),
600 ord_subtract(Writes1,Locals,Writes),
601 find_identifier_uses_l(RHS,Locals,Reads).
602
603 add_locals(IdentifiersL,LocalsIn,LocalsOut) :-
604 append(IdentifiersL,Identifiers),
605 get_texpr_ids(Identifiers,UIds),sort(UIds,Ids),
606 ord_union(LocalsIn,Ids,LocalsOut).
607
608 %*******************************************************************************
609 % identify predicates that are in the initialisation and in every operation
610 % on the post-state
611 global_predicates(InitAny,Ops,GlobalPreds) :-
612 pred_init(InitAny,InitPreds),
613 findall(OpAny,member(op(_,_,_,OpAny,_,_),Ops),OpAnies),
614 pred_ops(OpAnies,InitPreds,GlobalPreds).
615 pred_init(any(_,_,Preds,Lhs,Rhs),GPreds) :-
616 create_renamings(Lhs,Rhs,Renamings),
617 rename_variablest(Preds,Renamings,GPreds).
618 pred_ops([],GPreds,GPreds).
619 pred_ops([any(_,_,OpPreds,Lhs,Rhs)|ORest],OldPreds,GPreds) :-
620 create_renamings(Rhs,Lhs,Renamings),
621 filter_preds(OldPreds,OpPreds,Renamings,NewPreds),
622 pred_ops(ORest,NewPreds,GPreds).
623 filter_preds([],_,_,[]).
624 filter_preds([Old|ORest],OpPreds,Renamings,NewPreds) :-
625 rename_variablest(Old,Renamings,Comparable),
626 (exists_equalt(OpPreds,Comparable) ->
627 NewPreds = [Old|PRest];
628 NewPreds = PRest),
629 filter_preds(ORest,OpPreds,Renamings,PRest).
630 create_renamings([],[],[]).
631 create_renamings([L|LRest],[R|RRest],[rename(name(LN,LD),name(RN,RD))|Rest]) :-
632 get_texpr_info(L,LInfos),member(zname(LN,LD),LInfos),
633 get_texpr_info(R,RInfos),member(zname(RN,RD),RInfos),!,
634 create_renamings(LRest,RRest,Rest).
635
636 %*******************************************************************************
637 % remove global predicates from operations
638 remove_global_predicates(Ops,[],Ops) :- !.
639 remove_global_predicates(Ops,GlobalPredicates,NewOps) :-
640 remove_globalpreds(Ops,GlobalPredicates,NewOps).
641 remove_globalpreds([],_,[]).
642 remove_globalpreds([op(Op,Param,Results,Any,ParaTypes,ResultTypes)|ORest],GlobalPredicates,
643 [op(Op,Param,Results,NewAny,ParaTypes,ResultTypes)|NRest]) :-
644 remove_globalpreds2(Any,GlobalPredicates,NewAny),
645 remove_globalpreds(ORest,GlobalPredicates,NRest).
646 remove_globalpreds2(any(Vars,Types,Old,LHS,RHS),GlobalPredicates,
647 any(Vars,Types,New,LHS,RHS)) :-
648 remove_globalpreds3(Old,GlobalPredicates,New).
649 remove_globalpreds3([],_,[]).
650 remove_globalpreds3([Pred|ORest],GlobalPredicates,New) :-
651 ( exists_equalt(GlobalPredicates,Pred) ->
652 New = NRest
653 ; otherwise ->
654 New = [Pred|NRest]),
655 remove_globalpreds3(ORest,GlobalPredicates,NRest).
656
657 %**********************************************************************
658 % Dies und das
659
660 all_members([],_).
661 all_members([FirstMember|Members], List) :-
662 member(FirstMember, List),!,
663 all_members(Members, List).
664
665 %*******************************************************************************
666 % Z to ProB translation
667
668 z_translate([],[]) :- !.
669 z_translate([ZExpr|ZRest],[BExpr|BRest]) :-
670 !,
671 z_translate(ZExpr,BExpr),z_translate(ZRest,BRest).
672 z_translate(ti(ZExpr,ZType),BTExpr) :-
673 internal2b(ZType,BType),
674 z_translate1(ZExpr,ZType,BExpr),
675 create_typed_bexpr(BExpr,BType,BTExpr).
676
677 create_typed_bexpr(symbolic_comprehension_set(Ids, Lhs),BType,Res) :- !,
678 Res = b(comprehension_set(Ids, Lhs),BType,[prob_annotation('SYMBOLIC')]).
679 create_typed_bexpr(BExpr,BType,b(BExpr,BType,[])).
680
681 z_translate1(mu(Body,Computation), ZType, mu(BSet)) :-
682 !, ZSet = ti(comp(Body,Computation),set(ZType)),
683 z_translate(ZSet,BSet).
684 z_translate1(ZExpr,_ZType,BExpr) :-
685 z_translate2(ZExpr,BExpr).
686
687 z_translate2(falsity, falsity) :- !.
688 z_translate2(truth, truth) :- !.
689 z_translate2(forall(BodyTi, ZConsequent), forall(Ids, Lhs, Rhs)) :-
690 !, schema_to_typed_identifiers(BodyTi,Ids,Lhs),
691 z_translate(ZConsequent,Rhs).
692 z_translate2(exists(BodyTi, ZCondition), exists(Ids, BCondition)) :-
693 !, schema_to_typed_identifiers(BodyTi,Ids,Condition1),
694 z_translate(ZCondition,Rhs),
695 conjunct_predicates([Condition1,Rhs],BCondition).
696 z_translate2(lambda(BodyTi, ZExpr), lambda(Ids, Lhs, Rhs)) :-
697 !, schema_to_typed_identifiers(BodyTi,Ids,Lhs),
698 z_translate(ZExpr,Rhs).
699 z_translate2(ref(name('\\emptyset',''),[]),empty_set) :- !.
700 %z_translate2(ref(name('\\emptyset',''),[_TypeArg]),empty_set) :- !. % support constructs like \emptyset[\nat] ; currently argument removed in typing phase
701 z_translate2(ref(name('\\nat',''),[]),integer_set('NATURAL')) :- !.
702 z_translate2(ref(name('\\nat','_1'),[]),integer_set('NATURAL1')) :- !.
703 z_translate2(ref(name('\\num',''),[]),integer_set('INTEGER')) :- !.
704 /* In some special cases Schemas are refered just by ref(name(..)..), not by SEXPR(..) */
705 %z_translate2(ref(name(Name,Deco),Params), Env, BExpr) :-
706 % named_schema(Env,Name),!,
707 % z_translate(sexpr(sref(Name,Deco,Params,[])),BExpr).
708 %z_translate2(ref(FreetypeName,[]), Env, 'FreetypeSet'(Id)) :-
709 % zlookup(Env,data(FreetypeName,_)),
710 % !,z_translate_identifier(FreetypeName,Id).
711 z_translate2(ref(Name,[]), identifier(Id)) :-
712 !,z_translate_identifier(Name, Id).
713 z_translate2(inop(name('\\extract',''), Za, Zb), compaction(DomRes)) :-
714 !, create_texpr(domain_restriction(Ba,Bb),BType,[],DomRes),
715 z_translate(Za,Ba),z_translate(Zb,Bb),
716 get_texpr_type(Bb,BType).
717 z_translate2(inop(name('\\filter',''), Za, Zb), compaction(RanRes)) :-
718 !, create_texpr(range_restriction(Ba,Bb),BType,[],RanRes),
719 z_translate(Za,Ba),z_translate(Zb,Bb),
720 get_texpr_type(Ba,BType).
721 z_translate2(apply(Iteration,ZRel), Result) :-
722 % iteration of relations. The problem of this operator is that
723 % it can have negative arguments in Z but not in B
724 ti_expr(Iteration, apply(Ref,ZN)),
725 ti_expr(Ref, ref(name(iter,''),[])),
726 !, z_translate(ZN,BN), z_translate(ZRel,BRel),
727 get_texpr_type(BRel,BRelType),
728 create_texpr(reverse(BRel),BRelType,[],Inverse),
729 ( is_a_number(ZN,Value), Value >= 0 ->
730 % R^x, where x is a non-negative number, we can use it directly
731 Result = iteration(BRel,BN)
732 ; is_a_negative_number(ZN,Value), Value >= 0 ->
733 % R^-x, where x is a non-negative number, we can rewrite it into (R~)^x
734 create_texpr(integer(Value),integer,[],Negation),
735 Result = iteration(Inverse,Negation)
736 ; otherwise ->
737 % R^x, where x is an arbitrary expression, we surround it by if-then-else
738 % to negate the x if necessary
739 create_texpr(integer(0),integer,[],Zero),
740 create_texpr(less_equal(Zero,BN),pred,[],NonNegative),
741 create_texpr(iteration(BRel,BN),BRelType,[],Then),
742 create_texpr(unary_minus(BN),integer,[],Negation),
743 create_texpr(iteration(Inverse,Negation),BRelType,[],Else),
744 Result = if_then_else(NonNegative,Then,Else)).
745 z_translate2(inop(ZopName, Za, Zb), BBinOp) :-
746 z_translate_identifier(ZopName,Zop),
747 is_binary_op(Zop),!,
748 z_translate_binary_op(Zop,Za,Zb,BBinOp).
749 z_translate2(inrel(ZopName, Za, Zb), BBinOp) :-
750 z_translate_identifier(ZopName,Zop),
751 is_binary_op(Zop),!,
752 z_translate_binary_op(Zop,Za,Zb,BBinOp).
753 z_translate2(ingen(ZopName, Za, Zb), BBinOp) :-
754 z_translate_identifier(ZopName,Zop),
755 is_binary_op(Zop),!,
756 z_translate_binary_op(Zop,Za,Zb,BBinOp).
757 z_translate2(number(Value), integer(Value)) :- !.
758 z_translate2(ext(ZEntities), set_extension(BEntities)) :-
759 !, z_translate(ZEntities, BEntities).
760 z_translate2(seq(ZEntities), sequence_extension(BEntities)) :-
761 !, z_translate(ZEntities, BEntities).
762 z_translate2(apply(Items,ZExpr), bag_items(BExpr)) :-
763 ti_expr(Items,ref(name('items',''),[])),!,
764 z_translate(ZExpr,BExpr).
765 z_translate2(apply(ZFun, Zarg), BExpr) :-
766 ti_expr(ZFun,ref(Name,[])),
767 z_translate_identifier(Name,Op),
768 is_unary_op(Op),!,
769 z_translate_unary_op(Op,Zarg,BExpr).
770 z_translate2(apply(ZFun, ZArg), function(BFun,BArg)) :-
771 !, z_translate(ZFun,BFun), z_translate(ZArg,BArg).
772 z_translate2(postop(Name, Zarg), BExpr) :-
773 z_translate_identifier(Name,Op),
774 is_unary_op(Op),!,
775 z_translate_unary_op(Op,Zarg,BExpr).
776 z_translate2(prerel(Name, Zarg), BExpr) :-
777 z_translate_identifier(Name,Op),
778 is_unary_op(Op),!,
779 z_translate_unary_op(Op,Zarg,BExpr).
780 z_translate2(pregen(Name, Zarg), BExpr) :-
781 z_translate_identifier(Name,Op),
782 is_unary_op(Op),!,
783 z_translate_unary_op(Op,Zarg,BExpr).
784 z_translate2(inrel(name('\\prefix',''), Za, Zb), BExpr) :-
785 !,z_translate(Za,Ba),z_translate(Zb,Bb),
786 get_texpr_type(Ba,SeqType),
787 create_texpr(size(Ba),integer,[],SizeA),
788 create_texpr(size(Bb),integer,[],SizeB),
789 create_texpr(greater_equal(SizeB,SizeA),pred,[],GreaterEqual),
790 create_texpr(restrict_front(Bb,SizeA),SeqType,[],Prefix),
791 create_texpr(equal(Ba,Prefix),pred,[],Equal),
792 conjunct_predicates([GreaterEqual,Equal],TypedBExpr),
793 get_texpr_expr(TypedBExpr,BExpr).
794 z_translate2(inrel(name('\\suffix',''), Za, Zb), BExpr) :-
795 !,z_translate(Za,Ba),z_translate(Zb,Bb),
796 get_texpr_type(Ba,SeqType),
797 create_texpr(size(Ba),integer,[],SizeA),
798 create_texpr(size(Bb),integer,[],SizeB),
799 create_texpr(greater_equal(SizeB,SizeA),pred,[],GreaterEqual),
800 create_texpr(minus(SizeB,SizeA),integer,[],Diff),
801 create_texpr(restrict_tail(Bb,Diff),SeqType,[],Suffix),
802 create_texpr(equal(Ba,Suffix),pred,[],Equal),
803 conjunct_predicates([GreaterEqual,Equal],TypedBExpr),
804 get_texpr_expr(TypedBExpr,BExpr).
805 z_translate2(inrel(name('\\inseq',''), Za, Zb), BExpr) :-
806 !, create_in_sequence(Za,Zb,BExpr).
807 z_translate2(prerel(name('\\disjoint',''), Z), BExpr) :-
808 !, z_translate(Z,B), create_disjoint(B,BExpr).
809 z_translate2(inrel(name('\\partition',''), Za, Zb), partition(BSet,BSeq)) :-
810 ti_expr(Za,seq(ZSeq)),!,
811 z_translate(Zb,BSet),
812 z_translate(ZSeq,BSeq).
813 z_translate2(inrel(name('\\partition',''), Za, Zb), BExpr) :-
814 !, create_partition(Za,Zb,BExpr).
815 z_translate2(select(ZRecord, ZField), record_field(BRecord, FieldIdentifier)) :-
816 !, z_translate(ZRecord, BRecord),
817 z_translate_identifier(ZField, FieldIdentifier).
818 /* Comprehension set without expression */
819 z_translate2(comp(Body, Nothing),Res) :-
820 !,
821 ( ti_expr(Nothing,nothing) -> true
822 ; otherwise ->
823 add_error(proz,'Encountered comprehension set with expression in translation. Should have been replaced.'),
824 fail),
825 ti_expr(Body,body(Decls,ZWheres)),
826 ~~mnf( varlist_of_expanded_decls(Decls, Vars, Types) ),
827 z_translate_typed_identifiers(Vars,Types,[],Ids),
828 z_translate(ZWheres,Wheres),
829 conjunct_predicates(Wheres,Lhs),
830 %print(comp(Ids,Lhs)),nl,
831 (is_symbolic_set_comprehension(Ids,Lhs)
832 -> Res = symbolic_comprehension_set(Ids, Lhs) %,print(symbolic(Ids)),nl
833 ; Res = comprehension_set(Ids, Lhs)).
834 z_translate2(cross([Za,Zb]), cartesian_product(Ba,Bb)) :-
835 !, z_translate(Za,Ba), z_translate(Zb,Bb).
836 z_translate2(cross([ZExpr|ZRest]), cartesian_product(BExpr,TBRest)) :-
837 !, z_translate(ZExpr,BExpr), z_translate2(cross(ZRest),BRest),
838 BRest=cartesian_product(BL,BR),get_texpr_type(BL,set(LType)),get_texpr_type(BR,set(RType)),
839 create_texpr(BRest,set(couple(LType,RType)),[],TBRest).
840 z_translate2(tuple([Za,Zb]), couple(Ba,Bb)) :-
841 !, z_translate(Za,Ba), z_translate(Zb,Bb).
842 z_translate2(tuple([ZExpr|ZRest]), couple(BExpr,TBRest)) :-
843 !, z_translate(ZExpr,BExpr), z_translate2(tuple(ZRest),BRest),
844 BRest=couple(BL,BR),get_texpr_type(BL,LType),get_texpr_type(BR,RType),
845 create_texpr(BRest,couple(LType,RType),[],TBRest).
846 z_translate2(letexpr(ZLets,ZExpr), Result) :- %let_expression(Bids,BAssignments,BExpr)) :-
847 !, translate_lets(ZLets,Bids,BAssignments),
848 z_translate(ZExpr,BExpr),
849 create_z_let(expr,Bids,BAssignments,BExpr,[],b(Result,_,_)).
850 z_translate2(letpred(ZLets,ZExpr), Result) :- %let_predicate(Bids,BAssignments,BExpr)) :-
851 !, translate_lets(ZLets,Bids,BAssignments),
852 z_translate(ZExpr,BExpr),
853 create_z_let(pred,Bids,BAssignments,BExpr,[],b(Result,_,_)).
854 z_translate2(if(ZPred,ZIf,ZElse), if_then_else(BPred,BIf,BElse)) :-
855 !, z_translate(ZPred,BPred),
856 z_translate(ZIf,BIf), z_translate(ZElse,BElse).
857 z_translate2(inrel(Name,Za,Zb), member(Couple,Relation)) :-
858 !,z_translate(Za,Ba),z_translate(Zb,Bb),
859 z_translate_identifier(Name,Id),
860 get_texpr_type(Ba,TypeA), get_texpr_type(Bb,TypeB),
861 create_texpr(couple(Ba,Bb),couple(TypeA,TypeB),[],Couple),
862 create_texpr(identifier(Id),set(couple(TypeA,TypeB)),[],Relation).
863
864 % Internal constructs
865 z_translate2(binding(Bindings), rec(Fields)) :-
866 !, create_fields_for_binding(Bindings,Fields).
867 z_translate2(ftconstant(Freetype,Case),value(freeval(FreetypeId,ConstId,term(ConstId)))) :-
868 !,z_translate_identifier(Freetype,FreetypeId),
869 z_translate_identifier(Case,ConstId).
870 z_translate2(ftconstructor(Freetype,Case,ZExpr),
871 freetype_constructor(FreetypeId,CaseId,BExpr)) :-
872 !,z_translate(ZExpr,BExpr),
873 z_translate_identifier(Freetype,FreetypeId),
874 z_translate_identifier(Case,CaseId).
875 z_translate2(ftdestructor(Freetype,Case,ZExpr),
876 freetype_destructor(FreetypeId,CaseId,BExpr)) :-
877 !,z_translate(ZExpr,BExpr),
878 z_translate_identifier(Freetype,FreetypeId),
879 z_translate_identifier(Case,CaseId).
880 z_translate2(ftcase(Freetype,Case,ZExpr),
881 freetype_case(FreetypeId,CaseId,BExpr)) :-
882 !,z_translate(ZExpr,BExpr),
883 z_translate_identifier(Freetype,FreetypeId),
884 z_translate_identifier(Case,CaseId).
885
886 z_translate2(basetype(set(Type)), Expr) :-
887 !,translate_basetype2(Type,Expr).
888
889 z_translate2(reclet(ZId,ZSet), recursive_let(BId,BSet) ) :-
890 !,z_translate(ZId,BId),
891 % TODO: recursive_let accepts only comprehension sets as argument,
892 % maybe this should be checked here (lambda should be ok, too, because
893 % it's converted to a comprehension set
894 z_translate(ZSet,BSet1),
895 add_texpr_infos(BSet1,[prob_annotation('SYMBOLIC')],BSet).
896
897 z_translate2(ZBinOp, BBinOp) :-
898 functor(ZBinOp,ZopName,2),
899 is_binary_op(ZopName),!,
900 arg(1,ZBinOp,Za), arg(2,ZBinOp,Zb),
901 z_translate_binary_op(ZopName,Za,Zb,BBinOp).
902 z_translate2(ZUnOp, BUnOp) :-
903 functor(ZUnOp,ZopName,1),
904 is_unary_op(ZopName),!,
905 arg(1,ZUnOp,Zarg),
906 z_translate_unary_op(ZopName,Zarg,BUnOp).
907
908 z_translate2(ZExpr,_) :-
909 add_error(proz,'Unmatched Z expression',ZExpr),
910 fail.
911
912 % added by Leuschel to mark certain set comprehensions as symbolic
913 % TO DO: look with Daniel Plagge whether rec__ should always be symbolic, and whether other sets should be put symbolic
914 is_symbolic_set_comprehension([TID],_) :-
915 get_texpr_id(TID,ID),
916 atom_codes(ID,C),
917 append("rec__",_,C). % rec__ are special variables introduced in ztransformations:removesexpr2 for Schema fields
918
919 is_a_negative_number(ZExpr,N) :-
920 ti_expr(ZExpr,apply(Ref,Num)),
921 ti_expr(Ref,ref(name('(-)',''),[])),
922 is_a_number(Num,N).
923 is_a_number(ZExpr,N) :-
924 ti_expr(ZExpr,number(N)).
925
926 z_translate_binary_op(ZopName,Za,Zb,Bop) :-
927 z_binary_op(ZopName,BopName),!,
928 z_translate(Za,Ba),z_translate(Zb,Bb),
929 Bop =.. [BopName,Ba,Bb].
930
931 z_translate_unary_op(ZopName,Zarg,Bop) :-
932 z_unary_operator(ZopName, BopName),!,
933 z_translate(Zarg, Barg),
934 Bop =.. [BopName, Barg].
935
936 translate_basetype(Type,TExpr) :-
937 create_texpr(BExpr,set(BType),[],TExpr),
938 internal2b(Type,BType),
939 translate_basetype2(Type,BExpr).
940
941 translate_basetype2(num,integer_set('INTEGER')).
942 translate_basetype2(given(Name), value(global_set(Id))) :- z_translate_identifier(Name,Id).
943 translate_basetype2(freetype(Name), freetype_set(Id)) :- z_translate_identifier(Name,Id).
944 translate_basetype2(set(T), pow_subset(B)) :- translate_basetype(T,B).
945 translate_basetype2(tuple([A,B]), cartesian_product(TA,TB)) :-
946 !,translate_basetype(A,TA),
947 translate_basetype(B,TB).
948 translate_basetype2(tuple([A,B,C|Rest]), cartesian_product(TA,TBRest)) :-
949 translate_basetype(A,TA),
950 translate_basetype(tuple([B,C|Rest]),BRest),
951 BRest = cartesian_product(BL,BR),
952 get_texpr_type(BL,set(LType)),get_texpr_type(BR,set(RType)),
953 create_texpr(BRest,set(couple(LType,RType)),[],TBRest).
954 translate_basetype2(schema(ZFields),struct(Rec)) :-
955 translate_bt_fields(ZFields,BFields,FieldTypes),
956 create_texpr(rec(BFields),record(FieldTypes),[],Rec).
957 translate_bt_fields([],[],[]).
958 translate_bt_fields([ZField|ZRest],[BField|BRest],[FieldType|TRest]) :-
959 translate_bt_field(ZField,BField,FieldType),
960 translate_bt_fields(ZRest,BRest,TRest).
961 translate_bt_field(field(Name,T),field(FieldId,B),field(FieldId,set(BType))) :-
962 internal2b(T,BType),
963 z_translate_identifier(Name,FieldId),
964 translate_basetype(T,B).
965
966 schema_to_typed_identifiers(BodyTi,Ids,Condition) :-
967 ti_type(BodyTi,set(schema(ZFields))),
968 zfields2b(ZFields,Vars,Types),
969 z_translate_typed_identifiers(Vars,Types,[],Ids),
970
971 ti_expr(BodyTi,body(_,WhereTi)),
972 z_translate(WhereTi,Wheres),
973 conjunct_predicates(Wheres,Condition).
974
975 create_in_sequence(Za,Zb,BExpr) :-
976 z_translate(Za,Ba),z_translate(Zb,Bb),
977 get_texpr_type(Ba,BSeqType), BSeqType = set(couple(integer,BElemType)),
978 ti_type(Za,ZSeqType), ZSeqType = set(tuple([num,ZElemType])),
979 translate_basetype(ZElemType,BaseSet),
980 create_texpr(identifier('__card'),integer,[],C),
981 create_texpr(identifier('__i'),integer,[],I),
982 create_texpr(identifier('__la'),BSeqType,[],La),
983 create_texpr(identifier('__lb'),BSeqType,[],Lb),
984 create_texpr(identifier('__offset'),integer,[],Offset),
985 create_texpr(let_predicate([La,Lb],[Ba,Bb],Conjunction),pred,[],TypedBExpr),
986 create_texpr(seq(BaseSet),set(BSeqType),[],Sequences),
987 create_texpr(member(La,Sequences),pred,[],Asequence),
988 create_texpr(member(Lb,Sequences),pred,[],Bsequence),
989 create_texpr(card(La),integer,[],CardA),
990 create_texpr(card(Lb),integer,[],CardB),
991 create_texpr(minus(CardB,CardA),integer,[],Diff),
992 create_texpr(let_predicate([C],[Diff],Exists),pred,[],Let),
993 create_texpr(integer(0),integer,[],Zero),
994 create_texpr(interval(Zero,Diff),integer,[],Interval),
995 create_texpr(member(Offset,Interval),pred,[],InInterval),
996 create_texpr(conjunct(InInterval,Forall),pred,[],Pred),
997 create_texpr(forall([I],InDomain,Equal),pred,[],Forall),
998 create_texpr(domain(Ba),integer,[],Domain),
999 create_texpr(member(I,Domain),pred,[],InDomain),
1000 create_texpr(equal(ElemA,ElemB),pred,[],Equal),
1001 create_texpr(function(Ba,I),BElemType,[],ElemA),
1002 create_texpr(add(I,Offset),integer,[],I2),
1003 create_texpr(function(Bb,I2),BElemType,[],ElemB),
1004 create_exists([Offset],Pred,Exists),
1005 conjunct_predicates([Asequence,Bsequence,Let],Conjunction),
1006 get_texpr_expr(TypedBExpr,BExpr).
1007
1008 create_disjoint(B, let_predicate([D],[Domain],Forall)) :-
1009 get_texpr_type(B,set(couple(integer,set(ElemType)))),
1010 create_texpr(identifier('__d'),set(integer),[],D),
1011 create_texpr(identifier('__i'),integer,[],I),
1012 create_texpr(identifier('__j'),integer,[],J),
1013 create_texpr(domain(B),set(integer),[],Domain),
1014 create_texpr(forall([I,J],Pre,IsDisjunct),pred,[],Forall),
1015 create_texpr(member(I,D),pred,[],M1),
1016 create_texpr(member(J,D),pred,[],M2),
1017 create_texpr(less(I,J),pred,[],Less),
1018 conjunct_predicates([M1,M2,Less],Pre),
1019 create_texpr(function(B,I),set(ElemType),[],SetA),
1020 create_texpr(function(B,J),set(ElemType),[],SetB),
1021 create_texpr(intersection(SetA,SetB),set(ElemType),[],Intersection),
1022 create_texpr(empty_set,set(ElemType),[],Empty),
1023 create_texpr(equal(Intersection,Empty),pred,[],IsDisjunct).
1024
1025 % maybe we could in some cases use the new partition operator from Event-B (if Ba is known?) ; or maybe provide better constraint propagation support
1026 create_partition(Za,Zb,let_predicate([Seq],[Ba],Conjunct)) :-
1027 z_translate(Za,Ba),
1028 z_translate(Zb,Bb),
1029 % print('Z Partition : '), translate:print_bexpr(Ba),nl, translate:print_bexpr(Bb),nl,
1030 get_texpr_type(Ba,SeqType),
1031 get_texpr_type(Bb,set(Type)),
1032 create_texpr(identifier('__sets'),SeqType,[],Seq),
1033 create_disjoint(Seq,Disjoint1), create_texpr(Disjoint1,pred,[],Disjoint),
1034 create_texpr(general_union(Range),set(Type),[],Union),
1035 create_texpr(range(Seq),set(Type),[],Range),
1036 create_texpr(equal(Union,Bb),pred,[],Unification),
1037 create_texpr(conjunct(Disjoint, Unification),pred,[],Conjunct).
1038 % ,print('PARTITION: '), translate:print_bexpr(b(let_predicate([Seq],[Ba],Conjunct),pred,[])),nl.
1039
1040 is_binary_op(OpName) :- z_binary_op(OpName,_).
1041 is_unary_op(OpName) :- z_unary_operator(OpName,_).
1042
1043 /* Boolean binary operators */
1044 z_binary_op(and, conjunct).
1045 z_binary_op(or, disjunct).
1046 z_binary_op(implies, implication).
1047 z_binary_op(equiv, equivalence).
1048 /* Generic equals */
1049 z_binary_op(equal, equal).
1050 z_binary_op('\\neq', not_equal).
1051 /* Set binary operators */
1052 z_binary_op(member, member).
1053 z_binary_op('\\notin', not_member).
1054 z_binary_op('\\cup', union).
1055 z_binary_op('\\cap', intersection).
1056 z_binary_op('\\subseteq', subset).
1057 z_binary_op('\\subset', subset_strict).
1058 z_binary_op('\\setminus', set_subtraction).
1059 /* Arithmetic binary operators */
1060 z_binary_op('+', add).
1061 z_binary_op('-', minus).
1062 z_binary_op('*', multiplication).
1063 z_binary_op('\\div', floored_div). % not div; B and Z semantics differ
1064 z_binary_op('\\mod', modulo).
1065 z_binary_op('\\upto', interval).
1066 z_binary_op('<', less).
1067 z_binary_op('\\leq', less_equal).
1068 z_binary_op('\\geq', greater_equal).
1069 z_binary_op('>', greater).
1070 /* Relations and functions */
1071 z_binary_op('\\rel', relations).
1072 z_binary_op('\\pfun', partial_function).
1073 z_binary_op('\\fun', total_function).
1074 z_binary_op('\\pinj', partial_injection).
1075 z_binary_op('\\inj', total_injection).
1076 z_binary_op('\\psurj', partial_surjection).
1077 z_binary_op('\\surj', total_surjection).
1078 z_binary_op('\\bij', total_bijection).
1079 z_binary_op('\\ffun', partial_function).
1080 z_binary_op('\\finj', partial_injection).
1081 z_binary_op('\\mapsto', couple).
1082 z_binary_op('\\comp', composition).
1083 z_binary_op('\\dres', domain_restriction).
1084 z_binary_op('\\ndres', domain_subtraction).
1085 z_binary_op('\\rres', range_restriction).
1086 z_binary_op('\\nrres', range_subtraction).
1087 z_binary_op('_(|_|)', image).
1088 z_binary_op('\\oplus', overwrite).
1089 /* Sequences */
1090 z_binary_op('\\cat', concat).
1091
1092 z_unary_operator('(-)', unary_minus).
1093 z_unary_operator('\\dom', domain).
1094 z_unary_operator('\\ran', range).
1095 z_unary_operator(power, pow_subset).
1096 z_unary_operator('\\power_1', pow1_subset).
1097 /* In ProB all sets are treated as finite, so we use here the same as above */
1098 z_unary_operator('\\finset', fin_subset).
1099 z_unary_operator('\\finset_1', fin1_subset).
1100 z_unary_operator('\\bigcup', general_union).
1101 z_unary_operator('\\bigcap', general_intersection).
1102 z_unary_operator('\\dcat', general_concat).
1103
1104 z_unary_operator(not, negation).
1105 z_unary_operator('\\id', identity).
1106 z_unary_operator('\\inv', reverse).
1107
1108 z_unary_operator('\\plus', closure).
1109
1110 z_unary_operator('\\#', card).
1111 z_unary_operator('min', min).
1112 z_unary_operator('max', max).
1113
1114 z_unary_operator('\\seq', seq).
1115 z_unary_operator('\\seq_1', seq1).
1116 z_unary_operator('\\iseq', iseq).
1117 z_unary_operator('rev', rev).
1118 z_unary_operator('head', first).
1119 z_unary_operator('last', last).
1120 z_unary_operator('tail', tail).
1121 z_unary_operator('front', front).
1122 z_unary_operator('squash', compaction).
1123
1124 z_unary_operator('first', first_of_pair).
1125 z_unary_operator('second', second_of_pair).
1126
1127
1128 translate_lets([],[],[]).
1129 translate_lets([LetdefTi|ZRest],[Bid|IdRest],[BExpr|BRest]) :-
1130 ti_expr(LetdefTi,letdef(ZName,ZExpr)),
1131 ti_type(ZExpr,ZType),internal2b(ZType,BType),
1132 z_translate_typed_identifier(ZName,BType,[],Bid),
1133 z_translate(ZExpr,BExpr),
1134 translate_lets(ZRest,IdRest,BRest).
1135
1136 create_fields_for_binding([],[]).
1137 create_fields_for_binding([BindingTi|ZRest],
1138 [field(BField,BExpr)|BRest]) :-
1139 ti_expr(BindingTi,bindfield(Name,ZExpr)),
1140 z_translate_identifier(Name,BField),
1141 z_translate(ZExpr,BExpr),
1142 create_fields_for_binding(ZRest,BRest).
1143
1144 :- public varlist_of_expanded_decls/3. % because Spider cannot deal with ~~mnf
1145 varlist_of_expanded_decls([],[],[]).
1146 varlist_of_expanded_decls([TDecl|Drest],Vars,Types) :-
1147 ti_expr(TDecl,decl(Names,TypeDecl)),
1148 ti_type(TypeDecl,set(ZType)),
1149 internal2b(ZType,BType),
1150 varlist_of_expanded_decl(Names,BType,LTypes),
1151 append(Names,Vrest,Vars),
1152 append(LTypes,Trest,Types),
1153 varlist_of_expanded_decls(Drest,Vrest,Trest).
1154 varlist_of_expanded_decl([],_,[]).
1155 varlist_of_expanded_decl([_|Nrest],Type,[Type|Trest]) :-
1156 varlist_of_expanded_decl(Nrest,Type,Trest).
1157
1158
1159
1160
1161
1162
1163
1164 %*******************************************************************************
1165 % register_given_sets/1: registers all given sets in the specification
1166 % The specification must not include type information
1167
1168 set_given_sets(Spec,In,Out) :-
1169 findall(namedset(Name,Members),member(ti(namedset(Name,Members),_),Spec),NamedSets),
1170 findall(Sets,member(ti(given(Sets),_),Spec),ListOfSetsTmp),
1171 append(ListOfSetsTmp,ListOfSets),
1172 get_given_sets(ListOfSets,ListOfDeferredSets),
1173 get_named_sets(NamedSets,BNamedSets,BEnumeratedElems),
1174 write_section(deferred_sets,ListOfDeferredSets,In,MDsets),
1175 write_section(enumerated_sets,BNamedSets,MDsets,MEnums),
1176 write_section(enumerated_elements,BEnumeratedElems,MEnums,Out).
1177
1178 get_given_sets([],[]).
1179 get_given_sets([Setname|Rest],[BSet|Brest]) :-
1180 z_translate_identifier(Setname, Setid),
1181 print_message(given_set(Setid)),
1182 create_texpr(identifier(Setid),set(global(Setid)),[given_set],BSet),
1183 get_given_sets(Rest,Brest).
1184 get_named_sets([],[],[]).
1185 get_named_sets([namedset(Setname,Members)|Rest],[BSet|BSetRest],Enumerated) :-
1186 z_translate_identifier(Setname,Setid),
1187 create_texpr(identifier(Setid),set(global(Setid)),[given_set],BSet),
1188 z_translate_identifiers(Members,Memberids),
1189 create_enum_elements(Memberids,global(Setid),LocalEnumerated),
1190 append(LocalEnumerated,RestEnumerated,Enumerated),
1191 get_named_sets(Rest,BSetRest,RestEnumerated).
1192 create_enum_elements([],_,[]).
1193 create_enum_elements([Id|IRest],Type,[TId|TRest]) :-
1194 create_texpr(identifier(Id),Type,[enumerated_set_element],TId ),
1195 create_enum_elements(IRest,Type,TRest).
1196
1197 %*******************************************************************************
1198 % register_freetypes/2: Registers the freetypes of the given specification.
1199 % The specification must be given with type informations.
1200
1201 set_freetypes(Spec,In,Out) :-
1202 write_section(freetypes,Freetypes,In,Out),
1203 get_freetypes(Spec,Freetypes).
1204 get_freetypes([],[]).
1205 get_freetypes([ExprTi|Rest],Freetypes) :-
1206 ( ti_expr(ExprTi,data(Freetype,Arms)) ->
1207 get_freetype(Freetype,Arms,BFreetype),
1208 Freetypes = [BFreetype|FRest]
1209 ; otherwise ->
1210 Freetypes = FRest),
1211 get_freetypes(Rest,FRest).
1212 get_freetype(Freetype,ArmsTi,freetype(FreetypeId,Cases)) :-
1213 extract_cases_from_arms(ArmsTi,Cases),
1214 z_translate_identifier(Freetype,FreetypeId),
1215 print_message(freetype(FreetypeId)).
1216 extract_cases_from_arms([],[]).
1217 extract_cases_from_arms([ArmTi|RestArms],[case(CaseId,Type)|RestCases]) :-
1218 ti_expr(ArmTi,arm(Case,SwitchTi)),
1219 z_translate_identifier(Case,CaseId),
1220 ti_expr(SwitchTi,Switch),
1221 ( Switch = just(ExprTi) ->
1222 ti_type(ExprTi,set(ZType)),internal2b(ZType,Type)
1223 ; otherwise ->
1224 Type = constant([CaseId])
1225 ),
1226 extract_cases_from_arms(RestArms,RestCases).
1227
1228 %*******************************************************************************
1229 % clean up the machine
1230 clean_up_machine(Machine,Clean) :-
1231 clean_up_sections([concrete_constants,properties,
1232 abstract_variables,invariant,
1233 promoted,initialisation,operation_bodies],
1234 Machine,Clean).
1235 clean_up_sections([],M,M).
1236 clean_up_sections([Section|Rest],In,Out) :-
1237 clean_up_section(Section,In,M),
1238 clean_up_sections(Rest,M,Out).
1239 clean_up_section(Section,In,Out) :-
1240 select_section_texprs(Section,Old,New,In,Out),
1241 clean_up_l_with_optimizations(Old,[],New,Section).
1242
1243 %*******************************************************************************
1244 % test the conversion of specifications
1245 :- public startzconversiontests/0.
1246 startzconversiontests :-
1247 startzconversiontest('Z/Daniel/testcases.fuzz').
1248
1249 :- use_module(library(system),[environ/2]).
1250 startzconversiontest(Testfile) :-
1251 environ('PROB_EX_DIR',Dir),
1252 atom_concat(Dir,'/',Dir2),
1253 atom_concat(Dir2,Testfile,Fullpath),
1254 testconversion(Fullpath).
1255
1256 testconversion(File) :-
1257 ( proz:load_and_simplify(File,Tests,Specification) -> true
1258 ; otherwise ->
1259 add_error(proz,'Failed to load and simplify Z conversion test file: ',File)),
1260 runtests(Tests,Specification,Errors),
1261 ( Errors = [] ->
1262 true
1263 ; otherwise ->
1264 add_errors(Errors),
1265 fail).
1266
1267 add_errors([]).
1268 add_errors([T|Rest]) :-
1269 add_error(proz,'Z conversion testcase failed: ', T),
1270 add_errors(Rest).
1271
1272 load_and_simplify(File,Tests,Specification) :-
1273 load_fuzzfile(File),
1274 get_z_definitions(Z),
1275 findtests(Z,Tests),
1276 simplify_untyped(Z,Z2),!,
1277 global_environment(Z2,_,Z3),!,
1278 simplify_typed(Z3,Specification).
1279
1280 findtests(Z,Tests) :-
1281 findall(Name,getschema(Z,Name,_),Schemas),
1282 findall(test(N,T),(member(T,Schemas),testmark(T,N),member(N,Schemas)),Tests).
1283
1284 getschema(Z,Name,Def) :- member(sdef(shead(Name,[]),Def),Z).
1285 getschema(Z,Name,Def) :- member(defeq(shead(Name,[]),Def),Z).
1286 getschemat(Z,Name,Def) :- member(ti(sdef(shead(Name,[]),Def),_),Z).
1287 getschemat(Z,Name,Def) :- member(ti(defeq(shead(Name,[]),Def),_),Z).
1288
1289 testmark(Name,UName) :- append("Test",Rest,Complete),atom_codes(Name,Complete),atom_codes(UName,Rest).
1290
1291 runtests([],_,[]).
1292 runtests([test(N,T)|Rest],Z,Errors) :-
1293 getschemat(Z,N,Def1),
1294 getschemat(Z,T,Def2),
1295 !,
1296 write('Z transformation test '),write(N),write(': '),
1297 ( equal_expressiont(Def1,Def2) ->
1298 write(ok),
1299 Errors = RestErrors
1300 ; otherwise ->
1301 write(failed),
1302 Errors = [T|RestErrors]),
1303 !,
1304 nl,
1305 runtests(Rest,Z,RestErrors).
1306
1307 % --------------------------------
1308
1309