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