| 1 |  | % (c) 2009-2025 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(bsyntaxtree, | 
| 6 |  | [is_texpr/1, % checks if the given argument is a typed expression | 
| 7 |  |  | 
| 8 |  | get_texpr_expr/2, % get the expression part of a typed expression | 
| 9 |  | get_texpr_type/2, % get the type of a typed expression | 
| 10 |  | get_texpr_info/2, % get the list of information of a typed expression | 
| 11 |  | get_texpr_id/2, % get the id of a typed identifier, fails if it's not an identifier | 
| 12 |  | def_get_texpr_id/2, % same as above, but raises error if arg1 is not an identifier | 
| 13 |  | def_get_texpr_ids/2, % maplist of the above, i.e., translate a typed id list into a plain list of id names | 
| 14 |  | create_typed_id/3, % create a typed identifier | 
| 15 |  | create_typed_ids/3, % create a list of typed identifiers from list of names and types | 
| 16 |  | same_id/3, % true if two typed identifiers have the same id | 
| 17 |  | same_ids/2, % true if two lists of typed identifiers have the same ids | 
| 18 |  | same_ids_and_types/2, % also check types | 
| 19 |  | split_names_and_types/3, % split list of typed ids into ids and types | 
| 20 |  | get_texpr_exprs/2, % list variant of the above | 
| 21 |  | get_texpr_types/2, % list variant of the above | 
| 22 |  | get_texpr_infos/2, % list variant of the above | 
| 23 |  | get_texpr_ids/2,   % list variant of the above | 
| 24 |  | get_texpr_pos/2,   % get the position of a typed expression | 
| 25 |  | get_texpr_pos_infos/2, % the a list containing the position infos, sublist of get_texpr_infos | 
| 26 |  | extract_pos_infos/2, % get the position info sub list of an info list | 
| 27 |  | copy_pos_infos/3, % copy position infos from one typed expression to another | 
| 28 |  | delete_pos_info/2, % delete position info from an info list | 
| 29 |  | propagate_pos_info_if_useful/3, % propagate position info from second list if useful | 
| 30 |  | merge_info/3, % merge two information lists as well as possible | 
| 31 |  | update_infos/3, % provide updates to an existing info list | 
| 32 |  | get_info_pos/2,    % get the position directly from info field | 
| 33 |  | contains_info_pos/1, % true if info field contains position infos | 
| 34 |  |  | 
| 35 |  | same_texpr/2, % check if two typed expressions are equal modulo Info fields | 
| 36 |  | different_texpr_values/2, % check if two type expressions are WD and definitely denote different values | 
| 37 |  |  | 
| 38 |  | create_texpr/4, % creates a typed expression by giving expression, type and infos | 
| 39 |  | add_texpr_infos/3, % adds some more information to a typed expression at front | 
| 40 |  | add_texpr_info_if_new/3, % adds one info field to typed B expression info list at front if it is new | 
| 41 |  | add_texpr_infos_if_new/3, % ditto but list of infos can be added | 
| 42 |  | add_info_if_new/3, % adds to info list | 
| 43 |  | add_infos_if_new/3, % same for list of info items | 
| 44 |  | safe_create_texpr/3, % a version of create_texpr which extracts wd-info from sub-expressionssafe_create_texpr | 
| 45 |  | safe_create_texpr/4, | 
| 46 |  | texpr_contains_wd_condition/1, | 
| 47 |  | sub_expression_contains_wd_condition/1, % utility to check if sub-expression contains wd condition | 
| 48 |  |  | 
| 49 |  | get_rodin_name/2, get_rodin_model_name/2, | 
| 50 |  | is_rodin_label_info/1, | 
| 51 |  | get_texpr_label/2, get_texpr_labels/2, | 
| 52 |  | get_info_labels/2, select_info_labels/3, | 
| 53 |  | add_labels_to_texpr/3, | 
| 54 |  | get_texpr_description/2, % get @desc pragma for typed expression | 
| 55 |  | add_texpr_description/3, % add an additional description by hand | 
| 56 |  | info_has_ignore_pragma/1, % check if an info list has an ignore pragma | 
| 57 |  | predicate_has_ignore_pragma/1, % ditto for the info list of a predicate | 
| 58 |  | always_well_defined/1, always_well_defined_or_disprover_mode/1, | 
| 59 |  | always_well_defined_or_wd_reorderings_allowed/1, | 
| 60 |  | always_well_defined_or_wd_improvements_allowed/1, | 
| 61 |  | finite_wd_set_value/1, finite_set_or_disprover_mode/1, | 
| 62 |  | is_truth/1, is_falsity/1, | 
| 63 |  | conjunct_predicates/2, | 
| 64 |  | conjunct_predicates_with_pos_info/3, conjunct_predicates_with_pos_info/2, | 
| 65 |  | is_a_conjunct/3, is_a_conjunct_without_label/3, decompose_conjunct/3, | 
| 66 |  | is_a_disjunct/3, is_an_implication/3, is_an_equivalence/3, is_a_negation/2, | 
| 67 |  | conjunction_to_list/2, | 
| 68 |  | conjunction_to_list_with_rodin_labels/2, % a variation which propagates labels down to conjuncts | 
| 69 |  | member_in_conjunction/2, select_member_in_conjunction/3, | 
| 70 |  | flatten_conjunctions/2, | 
| 71 |  | size_of_conjunction/2, | 
| 72 |  | member_in_conjunction_cse/3, | 
| 73 |  | disjunct_predicates/2, | 
| 74 |  | disjunct_predicates_with_pos_info/3, | 
| 75 |  | disjunction_to_list/2, | 
| 76 |  | is_a_disjunct_or_implication/4, | 
| 77 |  | is_a_conjunct_or_neg_disj/3, | 
| 78 |  |  | 
| 79 |  | predicate_components/2, % split a predicate into components which use distinct identifiers | 
| 80 |  | predicate_components_in_scope/3, % ditto with an optional list of local variables | 
| 81 |  | predicate_components_with_restriction/4, | 
| 82 |  | predicate_identifiers/2, predicate_identifiers_in_scope/3, | 
| 83 |  |  | 
| 84 |  | project_predicate_on_identifiers/5, | 
| 85 |  |  | 
| 86 |  | find_identifier_uses_top_level/2, % not including global sets and constants | 
| 87 |  | find_identifier_uses/3, find_identifier_uses_if_necessary/3, | 
| 88 |  | find_identifier_uses_l/3, | 
| 89 |  | find_typed_identifier_uses/3, | 
| 90 |  | find_typed_identifier_uses/2, % not including global sets and constants | 
| 91 |  | find_typed_identifier_uses_l/3, | 
| 92 |  | find_identifier_uses_for_quantifier_body/3, | 
| 93 |  | get_global_identifiers/1, get_global_identifiers/2, | 
| 94 |  | occurs_in_expr/2, some_id_occurs_in_expr/2, | 
| 95 |  | single_usage_identifier/3, | 
| 96 |  | update_used_ids/3, | 
| 97 |  | check_computed_used_ids/2, | 
| 98 |  |  | 
| 99 |  | create_exists/3, create_or_merge_exists/3, | 
| 100 |  | create_exists_or_let_predicate/3, | 
| 101 |  | create_exists_opt_liftable/3, | 
| 102 |  | create_exists_opt/3, create_exists_opt/4, create_exists_opt/5, | 
| 103 |  | not_generated_exists_paras/1, | 
| 104 |  | create_forall/3, | 
| 105 |  | create_negation/2, is_negation_of/2, get_negated_operator_expr/2, | 
| 106 |  | create_implication/3, | 
| 107 |  | create_equivalence/3, | 
| 108 |  | is_equality/3, | 
| 109 |  | create_equality/3, split_equality/3, get_texpr_couple/3, | 
| 110 |  | create_couple/3, create_couple/2, nested_couple_to_list/2, | 
| 111 |  | create_cartesian_product/3, | 
| 112 |  | create_comprehension_set/4, | 
| 113 |  | is_eventb_comprehension_set/4, is_eventb_comprehension_set/6, | 
| 114 |  | singleton_set_extension/2, | 
| 115 |  | is_membership/3, is_membership_or_equality/3, | 
| 116 |  | get_lambda_equality/4, | 
| 117 |  | is_pow_subset/2, is_pow1_subset/2, | 
| 118 |  |  | 
| 119 |  | detect_global_predicates/4, | 
| 120 |  |  | 
| 121 |  | definitely_not_empty_set/1, definitely_empty_set/1, definitely_not_empty_finite_value/1, | 
| 122 |  | get_integer/2, | 
| 123 |  | get_interval/3, | 
| 124 |  |  | 
| 125 |  | replace_id_by_expr/4, | 
| 126 |  | replace_id_by_expr_with_count/5, % also count number of replacements | 
| 127 |  | replace_ids_by_exprs/4, | 
| 128 |  | remove_used_id_from_info/3, % remove an id from used_id info field if it exists | 
| 129 |  | remove_used_ids_from_info/3, % remove list of ids (order of args different !) | 
| 130 |  |  | 
| 131 |  | rename_bt/3, % a simplified version of replace_ids_by_exprs, which assumes target of renamings are variables | 
| 132 |  | rename_bt_l/3, | 
| 133 |  | remove_bt/4, | 
| 134 |  | syntaxtransformation/5, | 
| 135 |  | syntaxtransformation_det/5, % faster, non-backtracking version | 
| 136 |  | syntaxtransformation_for_renaming/5, | 
| 137 |  |  | 
| 138 |  | map_over_bexpr/2, map_over_typed_bexpr/2, map_over_typed_bexpr/3, | 
| 139 |  | map_over_typed_bexpr_with_names/2, | 
| 140 |  | map_over_bexpr_top_down_acc/3, map_over_typed_bexpr_top_down_acc/3, | 
| 141 |  | reduce_over_bexpr/4, | 
| 142 |  | transform_bexpr/3, % transform a typed B expression bottom-up | 
| 143 |  | transform_bexpr_with_scoping/3, % ditto, but we also provide info about local ids | 
| 144 |  | transform_bexpr_td_with_scoping/3, % top-down with scoping | 
| 145 |  | transform_bexpr_with_bup_accs/5, transform_bexpr_with_acc/5, | 
| 146 |  | non_det_transform_bexpr_with_acc/5, % can be used to generate several transformed expressions | 
| 147 |  | uses_implementable_integers/1, | 
| 148 |  | min_max_integer_value_used/3, min_max_integer_value_used/5, | 
| 149 |  | syntaxtraversion/6, | 
| 150 |  | safe_syntaxelement/5, | 
| 151 |  | safe_syntaxelement_det/5, % a deterministic, non-backtracking version | 
| 152 |  | is_subst_syntaxelement/1, | 
| 153 |  | is_syntax_constant/1, | 
| 154 |  |  | 
| 155 |  | expand_all_lets/2, | 
| 156 |  |  | 
| 157 |  | remove_all_infos/2, extract_info/2, extract_info/3, extract_info_wo_used_ids/2, | 
| 158 |  | bsyntax_pattern/2, | 
| 159 |  |  | 
| 160 |  | remove_all_infos_and_ground/2, | 
| 161 |  |  | 
| 162 |  | check_if_typed_predicate/1, | 
| 163 |  | check_if_typed_expression/1, | 
| 164 |  | check_if_typed_substitution/1, | 
| 165 |  |  | 
| 166 |  | strip_and_norm_ast/2, | 
| 167 |  | same_norm_texpr/2, | 
| 168 |  | get_texpr_functor/3, | 
| 169 |  |  | 
| 170 |  | is_set_type/2, get_set_type/2, get_texpr_set_type/2, | 
| 171 |  | is_just_type/1, is_just_type/2, | 
| 172 |  |  | 
| 173 |  | create_recursive_compset/6, | 
| 174 |  | unique_typed_id/3, | 
| 175 |  | mark_bexpr_as_symbolic/2, | 
| 176 |  |  | 
| 177 |  | identifier_sub_ast/3, exchange_ast_position/5, | 
| 178 |  |  | 
| 179 |  | has_declared_identifier/2, add_declaration_for_identifier/3, | 
| 180 |  | check_ast/1, check_ast/2, | 
| 181 |  | repair_used_ids/3, | 
| 182 |  | print_ast/1, | 
| 183 |  | rewrite_if_then_else_expr_to_b/2, | 
| 184 |  | normalise_bexpr_for_ml/2 | 
| 185 |  | ]). | 
| 186 |  |  | 
| 187 |  | % meta_predicate annotations should appear before loading any code: | 
| 188 |  |  | 
| 189 |  | :- meta_predicate map_over_full_bexpr_no_fail(1,?). | 
| 190 |  |  | 
| 191 |  | :- meta_predicate map_over_bexpr(1,?). | 
| 192 |  | :- meta_predicate map_over_typed_bexpr(1,?). | 
| 193 |  | :- meta_predicate map_over_typed_bexpr(2,?,?). | 
| 194 |  | :- meta_predicate map_over_bexpr_top_down_acc(3,?,?). | 
| 195 |  | :- meta_predicate map_over_typed_bexpr_top_down_acc(3,?,?). | 
| 196 |  |  | 
| 197 |  | :- meta_predicate reduce_over_bexpr(3,?,?,?). | 
| 198 |  | :- meta_predicate transform_bexpr(2,?,?). | 
| 199 |  | :- meta_predicate l_transform_bexpr(?,2,?). | 
| 200 |  | :- meta_predicate transform_bexpr_with_scoping(3,?,?). | 
| 201 |  | :- meta_predicate transform_bexpr_td_with_scoping(3,?,?). | 
| 202 |  | :- meta_predicate transform_bexpr_with_scoping2(3,?,?,?). | 
| 203 |  | :- meta_predicate l_transform_bexpr_with_scoping(?,3,?,?). | 
| 204 |  | :- meta_predicate transform_bexpr_with_bup_accs(4,?,?,?,?). | 
| 205 |  | :- meta_predicate l_transform_bexpr_with_bup_accs(?,4,?,?,?). | 
| 206 |  | :- meta_predicate transform_bexpr_with_acc(4,?,?,?,?). | 
| 207 |  | :- meta_predicate l_transform_bexpr_with_acc(?,4,?,?,?). | 
| 208 |  | :- meta_predicate non_det_transform_bexpr_with_acc(4,?,?,?,?). | 
| 209 |  | :- meta_predicate l_nd_transform_bexpr_with_acc(?,4,?,?,?). | 
| 210 |  |  | 
| 211 |  | % ----------- | 
| 212 |  |  | 
| 213 |  |  | 
| 214 |  | :- use_module(tools). | 
| 215 |  |  | 
| 216 |  | :- use_module(module_information,[module_info/2]). | 
| 217 |  | :- module_info(group,typechecker). | 
| 218 |  | :- module_info(description,'This module provides operations on the type-checked AST.'). | 
| 219 |  |  | 
| 220 |  | :- use_module(library(lists)). | 
| 221 |  | :- use_module(library(ordsets)). | 
| 222 |  | :- use_module(library(avl)). | 
| 223 |  | :- use_module(library(terms)). | 
| 224 |  |  | 
| 225 |  | :- use_module(self_check). | 
| 226 |  | :- use_module(error_manager). | 
| 227 |  | :- use_module(translate,[print_bexpr/1,translate_bexpression/2]). | 
| 228 |  | :- use_module(gensym,[gensym/2]). | 
| 229 |  | :- use_module(preferences,[get_preference/2,preference/2]). | 
| 230 |  | :- use_module(debug,[debug_mode/1,debug_format/3]). | 
| 231 |  |  | 
| 232 |  | :- use_module(typing_tools,[is_finite_type_in_context/2,normalize_type/2]). | 
| 233 |  | :- use_module(tools_lists,[convlist_max/4]). | 
| 234 |  |  | 
| 235 |  | :- set_prolog_flag(double_quotes, codes). | 
| 236 |  |  | 
| 237 |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
| 238 |  | % basic access to enriched syntax tree | 
| 239 |  |  | 
| 240 |  | is_texpr(b(_,_,_)). | 
| 241 |  |  | 
| 242 |  | get_texpr_expr(b(Name,_,_),R) :- !,R=Name. | 
| 243 |  | get_texpr_expr(E,_) :- add_error_fail(get_texpr_expr,'B Expression not properly wrapped: ',E). | 
| 244 |  |  | 
| 245 |  | get_texpr_type(b(_,Type,_),R) :- !, R=Type. | 
| 246 |  | get_texpr_type(E,_) :- add_error_fail(get_texpr_type,'B Expression not properly wrapped: ',E). | 
| 247 |  | get_texpr_info(b(_,_,Info),R) :- !, R=Info. | 
| 248 |  | get_texpr_info(E,_) :- add_error_fail(get_texpr_info,'B Expression not properly wrapped: ',E). | 
| 249 |  |  | 
| 250 |  | %! get_texpr_id(+Texpr,-Id) | 
| 251 |  | get_texpr_id(b(N,_,_),Id) :- !, N=identifier(Id). | 
| 252 |  | get_texpr_id(E,_) :- add_error_fail(get_texpr_id,'B Expression not properly wrapped: ',E). | 
| 253 |  | /* same as above: but must succeed */ | 
| 254 |  | def_get_texpr_id(b(identifier(Id),_,_),R) :- !,R=Id. | 
| 255 |  | def_get_texpr_id(b(E,_,_),_) :- !, | 
| 256 |  | add_error_fail(def_get_texpr_id,'Could not extract identifier from typed expression: ',E). | 
| 257 |  | def_get_texpr_id(ID,_) :- add_error_fail(def_get_texpr_id,'Could not extract identifier, not properly wrapped: ',ID). | 
| 258 |  |  | 
| 259 |  | % translate a list of ids with the b/3 wrapper into a plain id list; throw error if not an identifier | 
| 260 |  | % used to also be called get_texpr_id_names | 
| 261 |  | def_get_texpr_ids(L,Ids) :- maplist(def_get_texpr_id,L,Ids). | 
| 262 |  |  | 
| 263 |  | create_typed_id(IDName,Type,b(identifier(IDName),Type,[])). | 
| 264 |  |  | 
| 265 |  | create_typed_ids([],[],[]). | 
| 266 |  | create_typed_ids([ID|TI],[Type|TT],[TID| TRes]) :- | 
| 267 |  | create_typed_id(ID,Type,TID), | 
| 268 |  | create_typed_ids(TI,TT,TRes). | 
| 269 |  |  | 
| 270 |  | same_id(X,Y,ID) :- get_texpr_id(X,ID), get_texpr_id(Y,ID). | 
| 271 |  |  | 
| 272 |  | same_ids([],[]). | 
| 273 |  | same_ids([X|Xs],[Y|Ys]) :- same_id(X,Y,_), same_ids(Xs,Ys). | 
| 274 |  |  | 
| 275 |  | % check if two lists of identifiers have the same name and types | 
| 276 |  | same_ids_and_types([],[]). | 
| 277 |  | same_ids_and_types([b(identifier(Id),T1,_)|Xs],[b(identifier(Id),T2,_)|Ys]) :- unify_types_strict(T1,T2), | 
| 278 |  | same_ids_and_types(Xs,Ys). | 
| 279 |  |  | 
| 280 |  | % split a list of typed identifiers into atomic ids and types | 
| 281 |  | split_names_and_types([],N,T) :- !, N=[], T=[]. | 
| 282 |  | split_names_and_types([Identifier|IdRest],[Name|NRest],[Type|TRest]) :- !, | 
| 283 |  | def_get_texpr_id(Identifier,Name), | 
| 284 |  | get_texpr_type(Identifier,Type), | 
| 285 |  | split_names_and_types(IdRest,NRest,TRest). | 
| 286 |  | split_names_and_types(TIDS,N,R) :- | 
| 287 |  | add_internal_error('Illegal call to:',split_names_and_types(TIDS,N,R)),fail. | 
| 288 |  |  | 
| 289 |  |  | 
| 290 |  |  | 
| 291 |  | % check if two wrapped expressions are equal (modulo associated Info, e.g. source loc info) | 
| 292 |  | same_texpr(b(E1,Type,_),b(E2,Type,_)) :- % should we do a == check first ?? probably not as it may traverse the entire structure (see email exchange with SICStus 28.1.2015) | 
| 293 |  | same_functor(E1,E2), | 
| 294 |  | safe_syntaxelement_det(E1,Subs1,_Names1,_List1,Constant), | 
| 295 |  | safe_syntaxelement_det(E2,Subs2,_Names2,_List2,Constant2), | 
| 296 |  | Constant==Constant2, % in case we have values with variables inside ! | 
| 297 |  | same_sub_expressions(Subs1,Subs2). | 
| 298 |  |  | 
| 299 |  | same_sub_expressions([],[]). | 
| 300 |  | same_sub_expressions([H1|T1],[H2|T2]) :- same_texpr(H1,H2), same_sub_expressions(T1,T2). | 
| 301 |  |  | 
| 302 |  | % check if two wrapped expressions definitely denote a different value (and are well-defined) | 
| 303 |  | % only detects certain cases ! | 
| 304 |  | different_texpr_values(b(E1,Type,I1),b(E2,Type,I2)) :- | 
| 305 |  | different_value(E1,E2,CheckWD), | 
| 306 |  | (CheckWD=false -> true | 
| 307 |  | ; always_well_defined_or_wd_improvements_allowed(b(E1,Type,I1)), | 
| 308 |  | always_well_defined_or_wd_improvements_allowed(b(E2,Type,I2))). | 
| 309 |  | different_value(boolean_false,boolean_true,false) :- !. | 
| 310 |  | different_value(boolean_true,boolean_false,false) :- !. | 
| 311 |  | different_value(integer(X),IY,false) :- get_integer_aux(IY,Y),!, X\=Y. | 
| 312 |  | different_value(string(X),string(Y),false) :- !, X\=Y. | 
| 313 |  | different_value(value(VX),Y,false) :- !, different_val_from(VX,Y). | 
| 314 |  | different_value(empty_set,S,check_wd) :- !, non_empty_set(S). | 
| 315 |  | different_value(S,empty_set,check_wd) :- !, non_empty_set(S). | 
| 316 |  | % should we compare two set_extensions ? couples ? records ? reals/floats? | 
| 317 |  |  | 
| 318 |  | different_val_from(Var,_) :- var(Var),!,fail. | 
| 319 |  | different_val_from(int(X),IY) :- integer(X), get_integer_aux(IY,Y), X\=Y. | 
| 320 |  | different_val_from(fd(X,Gs),value(FY)) :- nonvar(X), nonvar(FY), FY=fd(Y,Gs), nonvar(Y), X\=Y. | 
| 321 |  | different_val_from(pred_false,boolean_true). | 
| 322 |  | different_val_from(pred_false,value(BY)) :- BY==pred_true. | 
| 323 |  | different_val_from(pred_true,boolean_false). | 
| 324 |  | different_val_from(pred_true,value(BY)) :- BY==pred_false. | 
| 325 |  | different_val_from(string(X),string(Y)) :- !, X\=Y. | 
| 326 |  | different_val_from(string(X),value(VY)) :- nonvar(VY), VY=string(Y), nonvar(Y), !, X\=Y. | 
| 327 |  | different_val_from(avl_set(node(_,_,_,_,_)),empty_set). | 
| 328 |  |  | 
| 329 |  | non_empty_set(set_extension([_|_])). | 
| 330 |  | non_empty_set(sequence_extension([_|_])). | 
| 331 |  |  | 
| 332 |  |  | 
| 333 |  | get_texpr_exprs([],[]). | 
| 334 |  | get_texpr_exprs([E|Rest],[N|NRest]) :- get_texpr_expr(E,N),get_texpr_exprs(Rest,NRest). | 
| 335 |  | get_texpr_exprs(b(E,_,_),Res) :- add_internal_error('Illegal call:',get_texpr_infos(b(E,_,_),Res)), Res=[E]. | 
| 336 |  | get_texpr_types([],[]). | 
| 337 |  | get_texpr_types([E|Rest],[T|TRest]) :- get_texpr_type(E,T),get_texpr_types(Rest,TRest). | 
| 338 |  | get_texpr_types(b(_,T,_),Res) :- add_internal_error('Illegal call:',get_texpr_infos(b(_,T,_),Res)), Res=[T]. | 
| 339 |  | get_texpr_infos([],[]). | 
| 340 |  | get_texpr_infos([E|Rest],[I|IRest]) :- get_texpr_info(E,I),get_texpr_infos(Rest,IRest). | 
| 341 |  | get_texpr_infos(b(_,_,I),Res) :- add_internal_error('Illegal call:',get_texpr_infos(b(_,_,I),Res)), Res=[I]. | 
| 342 |  | get_texpr_ids([],[]). | 
| 343 |  | get_texpr_ids([E|Rest],[I|IRest]) :- get_texpr_id(E,I),get_texpr_ids(Rest,IRest). | 
| 344 |  |  | 
| 345 |  | get_texpr_pos(TExpr,Pos) :- | 
| 346 |  | get_texpr_info(TExpr,Infos), | 
| 347 | ? | ( member(nodeid(Pos1),Infos) -> !,Pos=Pos1 | 
| 348 |  | ; Pos = none). | 
| 349 |  |  | 
| 350 |  | get_texpr_pos_infos(b(_,_,Infos),PosInfos) :- extract_pos_infos(Infos,PosInfos). | 
| 351 |  |  | 
| 352 |  | % similar to get_texpr_pos, but returns sub-list of infos relating to position | 
| 353 |  | extract_pos_infos(Infos,InfoRes) :- | 
| 354 | ? | ( member(nodeid(Pos1),Infos) -> !,InfoRes=[nodeid(Pos1)] | 
| 355 |  | ; InfoRes = []). | 
| 356 |  |  | 
| 357 |  | % copy position info from first arg to second argument | 
| 358 |  | copy_pos_infos(b(_,_,Infos1),Arg2,Res) :- | 
| 359 |  | member(nodeid(Pos1),Infos1),!, | 
| 360 |  | Arg2 = b(E,T,Infos2), Res = b(E,T,Infos3), | 
| 361 |  | delete_pos_info(Infos2,Infos2d), | 
| 362 |  | Infos3 = [nodeid(Pos1)|Infos2d]. | 
| 363 |  | copy_pos_infos(_,TE,TE). | 
| 364 |  |  | 
| 365 |  | delete_pos_info(Infos1,Infos2) :- | 
| 366 |  | select(nodeid(_),Infos1,D),!, Infos2=D. | 
| 367 |  | %delete(Infos1,nodeid(_),Infos2). | 
| 368 |  | delete_pos_info(I,I). | 
| 369 |  |  | 
| 370 |  | % propagate position info from second list to first one if it has better position info | 
| 371 |  | propagate_pos_info_if_useful(Infos,AuxInfos,NewInfos) :- | 
| 372 |  | member(nodeid(Pos2),AuxInfos), | 
| 373 |  | \+ derived_pos(Pos2),!, % potentially useful position info to propagate | 
| 374 |  | (select(nodeid(Pos1),Infos,Infos2) | 
| 375 |  | ->  (derived_pos(Pos1) | 
| 376 |  | -> NewInfos = [nodeid(Pos2)|Infos2] % we have better position info now | 
| 377 |  | ; NewInfos = Infos % we already have a position info | 
| 378 |  | ) | 
| 379 |  | ;  NewInfos = [nodeid(Pos2)|Infos] | 
| 380 |  | ). | 
| 381 |  | propagate_pos_info_if_useful(Infos,_,Infos). | 
| 382 |  |  | 
| 383 |  | % derived position; not precise instrinsic label at top-level | 
| 384 |  | derived_pos(rodin_derived_context_pos(_,_,_)). | 
| 385 |  |  | 
| 386 |  |  | 
| 387 |  | get_info_pos(Infos,Pos) :- (member(nodeid(Pos1),Infos) -> Pos=Pos1 ; Pos=none). | 
| 388 |  | contains_info_pos(Infos) :- (member(nodeid(NI),Infos) -> NI \= none). | 
| 389 |  |  | 
| 390 |  | create_texpr(Expr,Type,Info,b(Expr,Type,Info)). | 
| 391 |  |  | 
| 392 |  | add_texpr_infos(b(Expr,Type,Old),Infos,b(Expr,Type,New)) :- !, | 
| 393 |  | append(Infos,Old,New). | 
| 394 |  | add_texpr_infos(Other,Infos,Res) :- | 
| 395 |  | add_internal_error('Illegal call, not BExpr:',add_texpr_infos(Other,Infos,Res)),fail. | 
| 396 |  |  | 
| 397 |  | add_texpr_info_if_new(b(Expr,Type,Old),Info,b(Expr,Type,New)) :- !, | 
| 398 |  | add_info_if_new(Old,Info,New). | 
| 399 |  | add_texpr_info_if_new(Other,Infos,Res) :- | 
| 400 |  | add_internal_error('Illegal call, not BExpr:',add_texpr_info_if_new(Other,Infos,Res)),fail. | 
| 401 |  | % add multiple infos: | 
| 402 |  | add_texpr_infos_if_new(b(Expr,Type,Old),Infos,b(Expr,Type,New)) :- | 
| 403 |  | add_infos_if_new(Infos,Old,New). | 
| 404 |  |  | 
| 405 |  | % add to info list: | 
| 406 |  | add_info_if_new(Old,Info,New) :- | 
| 407 |  | (member(Info,Old) -> New=Old ; New = [Info|Old]). | 
| 408 |  |  | 
| 409 |  | add_infos_if_new([]) --> []. | 
| 410 |  | add_infos_if_new([Info|T]) --> add_info(Info), add_infos_if_new(T). | 
| 411 |  | add_info(Info,Old,New) :- | 
| 412 |  | (member(Info,Old) -> New=Old ; New = [Info|Old]). | 
| 413 |  |  | 
| 414 |  |  | 
| 415 |  | % try and extract the Rodin name of a predicate or expression | 
| 416 |  | get_rodin_name(Expression,Name) :- get_texpr_pos(Expression,rodinpos(Name,_)), Name \= []. | 
| 417 |  | get_rodin_name(Expression,Name) :- get_texpr_pos(Expression,rodinpos(_Model,Name,_)), Name \= []. % new rodinpos | 
| 418 |  |  | 
| 419 |  | get_rodin_model_name(Expression,Model) :- | 
| 420 |  | get_texpr_pos(Expression,rodinpos(Model,Name,_)), Name \= []. % new rodinpos | 
| 421 |  | % Note: only precise position label, not rodin_derived_context_pos | 
| 422 |  |  | 
| 423 |  | % try and extract the Rodin name or label pragma of a predicate or expression | 
| 424 |  | get_texpr_labels(TExpr,Label) :- | 
| 425 |  | get_texpr_info(TExpr,Infos), | 
| 426 |  | member(I,Infos), info_label(I,Label). | 
| 427 |  | get_info_labels(Infos,LabelList) :- | 
| 428 | ? | member(I,Infos), info_label(I,LabelList). | 
| 429 |  | select_info_labels(LabelList,Infos,Rest) :- | 
| 430 |  | select(I,Infos,Rest), info_label(I,LabelList). | 
| 431 |  | info_label(nodeid(NodeID),[Name]) :- nodeid_info_label(NodeID,Name). | 
| 432 |  | info_label(label(LabelList),LabelList). | 
| 433 |  |  | 
| 434 |  | nodeid_info_label(rodinpos(Name,_),Name) :- Name \= []. | 
| 435 |  | nodeid_info_label(rodinpos(Model,Name,_),FullName) :- Name \= [], % new rodinpos | 
| 436 |  | ajoin([Model,':',Name], FullName). % TO DO: if only one level; don't do this | 
| 437 |  | % TODO: provide separate way to access this derived information: | 
| 438 |  | %nodeid_info_label(rodin_derived_context_pos(Model,Context,Label),FullName) :- | 
| 439 |  | %    ajoin([Model,'.',Context,':',Label], FullName). | 
| 440 |  |  | 
| 441 |  |  | 
| 442 |  | add_labels_to_texpr(E,[],R) :- !, R=E. % no labels to add | 
| 443 |  | add_labels_to_texpr(b(E,T,I),Labels,b(E,T,NewI)) :- | 
| 444 |  | (select(label(OldList),I,Rest) | 
| 445 |  | -> append(Labels,OldList,NewList), NewI=[label(NewList)|Rest] | 
| 446 |  | % TO DO: what if we have Rodin labels | 
| 447 |  | ; NewI = [label(Labels)|I] | 
| 448 |  | ). | 
| 449 |  |  | 
| 450 |  | get_texpr_label(TExpr,Label) :- get_texpr_labels(TExpr,Labels), member(Label,Labels). | 
| 451 |  |  | 
| 452 |  | get_texpr_description(TExpr,Description) :- | 
| 453 |  | get_texpr_info(TExpr,Infos), | 
| 454 |  | memberchk(description(Description),Infos). | 
| 455 |  |  | 
| 456 |  | add_texpr_description(b(E,T,I),Description,b(E,T,[description(Description)|I])) :- | 
| 457 |  | (atom(Description) -> true ; | 
| 458 |  | add_error(add_texpr_description,'Non-atomic description:',Description)). | 
| 459 |  |  | 
| 460 |  | % check if an info list has an ignore pragma | 
| 461 |  | info_has_ignore_pragma(Infos) :- | 
| 462 |  | member(description('prob-ignore'),Infos). | 
| 463 |  | % detect_prob_ignore ast_cleanup rule also generates this description annotation | 
| 464 |  |  | 
| 465 |  | predicate_has_ignore_pragma(b(_E,pred,I)) :- | 
| 466 |  | %add_message(check_prob_ignore,'Pred: ',b(_E,pred,I),I), | 
| 467 |  | info_has_ignore_pragma(I). | 
| 468 |  |  | 
| 469 |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
| 470 |  |  | 
| 471 |  | :- assert_must_succeed( (E = "1/2", | 
| 472 |  | bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err), | 
| 473 |  | Type==integer, Err==none, always_well_defined(ET) ) ). | 
| 474 |  | :- assert_must_succeed( (E = "3 mod 2", | 
| 475 |  | bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err), | 
| 476 |  | Type==integer, Err==none, always_well_defined(ET) ) ). | 
| 477 |  | :- assert_must_succeed( (E = "1/0", | 
| 478 |  | bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err), | 
| 479 |  | Type==integer, Err==none, \+ always_well_defined(ET) ) ). | 
| 480 |  | :- assert_must_succeed( (E = "2*(3 mod card({}))", | 
| 481 |  | bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err), | 
| 482 |  | Type==integer, Err==none, \+ always_well_defined(ET) ) ). | 
| 483 |  | :- assert_must_succeed( (E = "1/(2+1-3)", | 
| 484 |  | bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err), | 
| 485 |  | Type==integer, Err==none, \+ always_well_defined(ET) ) ). | 
| 486 |  | :- assert_must_succeed( (E = "max({1,2,3,0})", | 
| 487 |  | bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err), | 
| 488 |  | Type==integer, Err==none, always_well_defined(ET) ) ). | 
| 489 |  | :- assert_must_succeed( (E = "min({1,2,3,0})", | 
| 490 |  | bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err), | 
| 491 |  | Type==integer, Err==none, always_well_defined(ET) ) ). | 
| 492 |  | :- assert_must_succeed( (E = "min({1,2,3,0}-(0..4))", | 
| 493 |  | bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err), | 
| 494 |  | Type==integer, Err==none, \+ always_well_defined(ET) ) ). | 
| 495 |  | :- assert_must_succeed( (E = "2+max({1,2,3, 1/0})", | 
| 496 |  | bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err), | 
| 497 |  | Type==integer, Err==none,\+ always_well_defined(ET) ) ). | 
| 498 |  | :- assert_must_succeed( (E = "2-card({1,2,3})", | 
| 499 |  | bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err), | 
| 500 |  | Type==integer, Err==none, always_well_defined(ET) ) ). | 
| 501 |  | :- assert_must_succeed( (E = "2-card({1,2,3, 1/0})", | 
| 502 |  | bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err), | 
| 503 |  | Type==integer, Err==none,\+ always_well_defined(ET) ) ). | 
| 504 |  | :- assert_must_succeed( (E = "bool(2-size([1,2,3, 1/0])=3)", | 
| 505 |  | bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err), | 
| 506 |  | Type==boolean, Err==none, \+ always_well_defined(ET) ) ). | 
| 507 |  | :- assert_must_succeed( (E = "bool(2-size([1,2,3, 1/2, 3 mod 2, 3**2])=size([]))", | 
| 508 |  | bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err), | 
| 509 |  | Type==boolean, Err==none, always_well_defined(ET) ) ). | 
| 510 |  |  | 
| 511 |  | always_well_defined_or_wd_reorderings_allowed(BE) :- % allow re-ordering to improve Left-to-right WD | 
| 512 |  | (preferences:preference(disprover_mode,true) -> true % we can assume all calls are well-defined | 
| 513 |  | ; preferences:preference(allow_improving_wd_mode,true) -> true | 
| 514 |  | ; preferences:preference(data_validation_mode,true) -> true | 
| 515 |  | ; always_well_defined_or_discharged(BE)). | 
| 516 |  | always_well_defined_or_wd_improvements_allowed(BE) :- % allow to remove useless calls which could be non-WD | 
| 517 |  | % example #x(x = f(...)) -> btrue   or  f[{}]  --> {} | 
| 518 |  | always_well_defined_or_wd_reorderings_allowed(BE). % we currently use the same definition | 
| 519 |  | always_well_defined_or_disprover_mode(BE) :- | 
| 520 |  | (preferences:preference(disprover_mode,true) -> true % we can assume all calls are well-defined | 
| 521 |  | ; always_well_defined_or_discharged(BE)). | 
| 522 |  |  | 
| 523 |  | always_well_defined_or_discharged(b(E,_,Infos)) :- !, | 
| 524 |  | (nonmember(contains_wd_condition,Infos) -> true | 
| 525 |  | ; always_wd(E) -> true  % some special rules | 
| 526 |  | ; member(discharged_wd_po,Infos) -> true | 
| 527 |  | %; nl, functor(E,F,N), F \= function, print(non_wd(F,N)),nl,nl,fail | 
| 528 |  | ). | 
| 529 |  | always_well_defined_or_discharged(E) :- | 
| 530 |  | add_error_fail(always_well_defined,'Illegal call: ',always_well_defined_or_discharged(E)). | 
| 531 |  |  | 
| 532 |  | % should ensure that there is no failure and no error raised | 
| 533 |  | always_well_defined(b(E,_,Infos)) :- !, | 
| 534 |  | (nonmember(contains_wd_condition,Infos) -> true | 
| 535 |  | ; always_wd(E) -> true  % some special rules | 
| 536 |  | %; nl, functor(E,F,N), F \= function, print(non_wd(F,N)),nl,nl,fail | 
| 537 |  | ). | 
| 538 |  | always_well_defined(E) :- add_error_fail(always_well_defined,'Illegal call: ',always_well_defined(E)). | 
| 539 |  |  | 
| 540 |  |  | 
| 541 |  | :- assert_must_succeed( always_wd(div( b(integer(2),integer,[]), b(integer(2),integer,[]) )) ). | 
| 542 |  | :- assert_must_fail( always_wd(div( b(integer(2),integer,[]), b(integer(0),integer,[]) )) ). | 
| 543 |  | :- assert_must_succeed( always_wd(modulo( b(integer(2),integer,[]), b(integer(2),integer,[]) )) ). | 
| 544 |  | :- assert_must_fail( always_wd(modulo( b(integer(2),integer,[]), b(integer(0),integer,[]) )) ). | 
| 545 |  | :- assert_must_fail( always_wd(modulo( b(integer(2),integer,[]), b(integer(-2),integer,[]) )) ). | 
| 546 |  | :- assert_must_fail( always_wd(modulo( b(integer(-1),integer,[]), b(integer(2),integer,[]) )) ). | 
| 547 |  | :- assert_must_succeed( always_wd(power_of( b(integer(2),integer,[]), b(integer(3),integer,[]) )) ). | 
| 548 |  | :- assert_must_succeed( always_wd(power_of( b(integer(2),integer,[]), b(integer(0),integer,[]) )) ). | 
| 549 |  | :- assert_must_fail( always_wd(power_of( b(integer(2),integer,[]), b(integer(-1),integer,[]) )) ). | 
| 550 |  |  | 
| 551 |  | % catch cases where the construct is currently so instantiated that we can determine that it is well-defined | 
| 552 |  | % can happen e.g. during closure compilation | 
| 553 |  | :- use_module(custom_explicit_sets,[check_unique_in_domain_of_avlset/2]). | 
| 554 |  | :- use_module(kernel_tools,[ground_value/1]). | 
| 555 |  | always_wd(power_of(X,Y)) :- get_integer(Y,Val), Val>=0, | 
| 556 |  | (eventb_mode -> get_integer(X,ValX), ValX >=0 | 
| 557 |  | ; always_well_defined(X)). | 
| 558 |  | always_wd(div(X,Y)) :-  get_integer(Y,Val), Val\=0, always_well_defined(X). | 
| 559 |  | always_wd(modulo(X,Y)) :- get_integer(Y,Val), Val>0, % Z Live allows negative numbers here it seems, cf modulo2 | 
| 560 |  | (z_or_tla_minor_mode -> true % in Z, TLA we can have negative numbers here | 
| 561 |  | ; get_integer(X,ValX), ValX>=0). | 
| 562 |  | always_wd(function(X,Y)) :- nonvar(X), | 
| 563 |  | X= b(value(AVLSET),_,_), nonvar(AVLSET), AVLSET=avl_set(AVL), | 
| 564 |  | always_wd_avl_function(AVL,Y). | 
| 565 |  | always_wd(min(X)) :- non_empty_finite_wd_set_value(X). | 
| 566 |  | always_wd(max(X)) :- non_empty_finite_wd_set_value(X). | 
| 567 |  | always_wd(card(X)) :- finite_wd_set_value(X). | 
| 568 |  | always_wd(size(X)) :- finite_wd_seq_value(X). | 
| 569 |  | always_wd(first(X)) :- non_empty_wd_seq_value(X). | 
| 570 |  | always_wd(front(X)) :- non_empty_wd_seq_value(X). | 
| 571 |  | always_wd(last(X)) :- non_empty_wd_seq_value(X). | 
| 572 |  | always_wd(tail(X)) :- non_empty_wd_seq_value(X). % TO DO: add restrict_front, restrict_tail ? | 
| 573 |  | always_wd(general_intersection(X)) :- non_empty_finite_wd_set_value(X). | 
| 574 |  | always_wd(value(_)). % we have already computed the value and will raise WD error; to be 100 % safe we could restrict this to ground values | 
| 575 |  | % other candidates: size(_), first(_) last(_) tail(_) front(_) restrict_front(_,_) restrict_tail(_,_) rel_iterate(_,_) | 
| 576 |  | always_wd(typeset). | 
| 577 |  | % operators that are always wd on their own: | 
| 578 |  | always_wd(record_field(RecEx,FieldName)) :- ground(FieldName), | 
| 579 |  | always_well_defined(RecEx). | 
| 580 |  | always_wd(unary_minus(A)) :- always_well_defined(A). | 
| 581 |  | always_wd(unary_minus_real(A)) :- always_well_defined(A). | 
| 582 |  | always_wd(first_of_pair(A)) :- always_well_defined(A). | 
| 583 |  | always_wd(add(A,B)) :- always_well_defined(A),always_well_defined(B). | 
| 584 |  | always_wd(add_real(A,B)) :- always_well_defined(A),always_well_defined(B). | 
| 585 |  | always_wd(minus(A,B)) :- always_well_defined(A),always_well_defined(B). | 
| 586 |  | always_wd(minus_real(A,B)) :- always_well_defined(A),always_well_defined(B). | 
| 587 |  | always_wd(multiplication(A,B)) :- always_well_defined(A),always_well_defined(B). | 
| 588 |  | always_wd(multiplication_real(A,B)) :- always_well_defined(A),always_well_defined(B). | 
| 589 |  | always_wd(equal(A,B)) :- always_well_defined(A),always_well_defined(B). | 
| 590 |  | always_wd(not_equal(A,B)) :- always_well_defined(A),always_well_defined(B). | 
| 591 |  | always_wd(less_equal(A,B)) :- always_well_defined(A),always_well_defined(B). | 
| 592 |  | always_wd(less_equal_real(A,B)) :- always_well_defined(A),always_well_defined(B). | 
| 593 |  | always_wd(greater_equal(A,B)) :- always_well_defined(A),always_well_defined(B). | 
| 594 |  | always_wd(less(A,B)) :- always_well_defined(A),always_well_defined(B). | 
| 595 |  | always_wd(less_real(A,B)) :- always_well_defined(A),always_well_defined(B). | 
| 596 |  | always_wd(greater(A,B)) :- always_well_defined(A),always_well_defined(B). | 
| 597 |  | always_wd(couple(A,B)) :- always_well_defined(A),always_well_defined(B). | 
| 598 |  | % TO DO: add more/all other operators ? | 
| 599 |  |  | 
| 600 |  | always_wd_avl_function(AVL,Y) :- nonvar(Y), Y= b(value(Val),_,_), | 
| 601 |  | ground_value(Val), !, | 
| 602 |  | % Warning: this does not check that the whole AVL is a function; just this particular lookup is ok | 
| 603 |  | check_unique_in_domain_of_avlset(Val,AVL). % ,print(ok),nl. | 
| 604 |  | always_wd_avl_function(AVL,Y) :- always_well_defined(Y), | 
| 605 |  | custom_explicit_sets:quick_definitely_maximal_total_function_avl(AVL). | 
| 606 |  |  | 
| 607 |  | % non empty set with WD elements | 
| 608 |  | non_empty_finite_wd_set_value(b(E,_,_)) :- non_empty_fin_wd_set2(E). | 
| 609 |  | non_empty_fin_wd_set2(bool_set). | 
| 610 |  | non_empty_fin_wd_set2(value(X)) :- definitely_not_empty_finite_value(X). | 
| 611 |  | non_empty_fin_wd_set2(set_extension(S)) :- l_always_well_defined(S). % the set_extension could contain wd_errors !! | 
| 612 |  | non_empty_fin_wd_set2(sequence_extension(S)) :- l_always_well_defined(S). % ditto | 
| 613 |  | non_empty_fin_wd_set2(interval(A,B)) :- get_integer(A,IA), get_integer(B,IB), IA =< IB. | 
| 614 |  | % see not_empty_set_aux | 
| 615 |  | definitely_not_empty_finite_value(X) :- var(X),!,fail. | 
| 616 |  | definitely_not_empty_finite_value(avl_set(_)). | 
| 617 |  | definitely_not_empty_finite_value([_|_]). | 
| 618 |  | definitely_not_empty_finite_value(closure(P,T,B)) :- | 
| 619 |  | custom_explicit_sets:is_interval_closure(P,T,B,LOW,UP), integer(LOW),integer(UP), LOW =< UP. | 
| 620 |  | % TODO: pow_subset of finite values | 
| 621 |  |  | 
| 622 |  | non_empty_wd_seq_value(b(E,_,_)) :- non_empty_seq2(E). | 
| 623 |  | non_empty_seq2(value(X)) :- definitely_not_empty_seq(X). | 
| 624 |  | non_empty_seq2(sequence_extension(S)) :- l_always_well_defined(S), S=[_|_]. | 
| 625 |  |  | 
| 626 |  | definitely_not_empty_seq(X) :- var(X),!,fail. | 
| 627 |  | definitely_not_empty_seq(avl_set(A)) :- custom_explicit_sets:is_avl_sequence(A). | 
| 628 |  | definitely_not_empty_seq([El1|T]) :- T==[],nonvar(El1), El1=(IDX,_), IDX==int(1). % TO DO: add more cases ? | 
| 629 |  |  | 
| 630 |  |  | 
| 631 |  | finite_set_or_disprover_mode(Set) :- | 
| 632 |  | (preferences:preference(disprover_mode,true) -> true % we can assume all calls are well-defined | 
| 633 |  | ; finite_wd_set_value(Set)). | 
| 634 |  |  | 
| 635 |  | :- use_module(typing_tools,[is_provably_finite_type/1]). | 
| 636 |  | % we could also use is_finite_type_in_context to allow deferred sets to be counted as finite | 
| 637 |  | finite_wd_set_value(b(E,T,_)) :- !, (finite_set2(E) -> true ; is_provably_finite_type(T)). | 
| 638 |  | finite_wd_set_value(E) :- add_internal_error('Not a BExpr: ',E),fail. | 
| 639 |  | finite_set2(empty_set). | 
| 640 |  | finite_set2(empty_sequence). | 
| 641 |  | finite_set2(value(X)) :- X==[] -> true ; definitely_not_empty_finite_value(X). | 
| 642 |  | finite_set2(set_extension(S)) :- l_always_well_defined(S). % the set_extension could contain wd_errors !! | 
| 643 |  | finite_set2(sequence_extension(S)) :- l_always_well_defined(S). % ditto | 
| 644 |  |  | 
| 645 |  | finite_wd_seq_value(b(E,_,_)) :- finite_seq2(E). | 
| 646 |  | finite_seq2(empty_set). | 
| 647 |  | finite_seq2(empty_sequence). | 
| 648 |  | finite_seq2(value(X)) :- finite_seq_value(X). | 
| 649 |  | finite_seq2(sequence_extension(S)) :- l_always_well_defined(S). | 
| 650 |  |  | 
| 651 |  | finite_seq_value(X) :- var(X),!,fail. | 
| 652 |  | finite_seq_value([]). | 
| 653 |  | finite_seq_value(avl_set(A)) :- custom_explicit_sets:is_avl_sequence(A). | 
| 654 |  | % it could be expensive to check if non empty list is a B sequence ?? | 
| 655 |  |  | 
| 656 |  | l_always_well_defined([]). | 
| 657 |  | l_always_well_defined([H|T]) :- always_well_defined(H), l_always_well_defined(T). | 
| 658 |  |  | 
| 659 |  | is_truth(b(F,pred,_)) :- is_truth_aux(F). | 
| 660 |  | is_truth_aux(truth). | 
| 661 |  | is_truth_aux(value(V)) :- V==pred_true. % can occur in CSE mode | 
| 662 |  |  | 
| 663 |  | is_falsity(b(F,pred,_)) :- is_falsity_aux(F). | 
| 664 |  | is_falsity_aux(falsity). | 
| 665 |  | is_falsity_aux(value(V)) :- V==pred_false. % can occur in CSE mode | 
| 666 |  |  | 
| 667 |  | % conjunction of a list of predicates | 
| 668 |  | % NOTE: bsyntaxtree:conjunct_predicates([P1,P2,P3],R).  -->  generates R = b(conjunct(b(conjunct(P1,P2),pred,[]),P3),pred,[]) | 
| 669 |  | conjunct_predicates(V,R) :- var(V),!, add_internal_error('Variable conjunction list: ',conjunct_predicates(V,R)),fail. | 
| 670 |  | conjunct_predicates([],b(truth,pred,[])). | 
| 671 |  | conjunct_predicates([P|Rest],Result) :- conjunct2(Rest,P,Result). | 
| 672 |  | conjunct2([],P,P). | 
| 673 |  | conjunct2([Q|Rest],P,Result) :- conjunct3(P,Q,R), conjunct2(Rest,R,Result). | 
| 674 |  | conjunct3(b(truth,_,_),P,P) :- !. | 
| 675 |  | conjunct3(P,b(truth,_,_),P) :- !. | 
| 676 |  | conjunct3(A,B,b(conjunct(A,B),pred,NewInfo)) :- extract_info(A,B,NewInfo). | 
| 677 |  |  | 
| 678 |  | % disjunction of a list of predicates | 
| 679 |  | disjunct_predicates([],b(falsity,pred,[])). | 
| 680 |  | disjunct_predicates([P|Rest],Result) :- disjunct2(Rest,P,Result). | 
| 681 |  | disjunct2([],P,P). | 
| 682 |  | disjunct2([Q|Rest],P,Result) :- disjunct3(P,Q,R), disjunct2(Rest,R,Result). | 
| 683 |  | disjunct3(b(falsity,_,_),P,R) :- !, R=P. | 
| 684 |  | disjunct3(b(truth,T,I),_,R) :- !, R=b(truth,T,I). | 
| 685 |  | disjunct3(P,b(falsity,_,_),R) :- !, R=P. | 
| 686 |  | disjunct3(_,b(truth,T,I),R) :- !, R=b(truth,T,I). | 
| 687 |  | disjunct3(A,B,b(disjunct(A,B),pred,NewInfo)) :- extract_info(A,B,NewInfo). | 
| 688 |  |  | 
| 689 |  | % conjunct two predicates and try and construct position information | 
| 690 |  | conjunct_predicates_with_pos_info(A,B,AB) :- is_truth(B),!, AB=A. | 
| 691 |  | conjunct_predicates_with_pos_info(A,B,AB) :- is_truth(A),!, AB=B. | 
| 692 |  | conjunct_predicates_with_pos_info(A,B,AB) :- | 
| 693 |  | conjunct_predicates([A,B],AB0),  % this may contain position info if B is truth; hence we do check above | 
| 694 |  | (try_get_merged_position_info(A,B,ABI) | 
| 695 |  | -> add_texpr_infos(AB0,[ABI],AB)  %,print(abi(ABI)),nl | 
| 696 |  | ; AB=AB0). | 
| 697 |  |  | 
| 698 |  | % disjunct two predicates and try and construct position information | 
| 699 |  | disjunct_predicates_with_pos_info(A,B,AB) :- | 
| 700 |  | disjunct_predicates([A,B],AB0), | 
| 701 |  | (try_get_merged_position_info(A,B,ABI) | 
| 702 |  | -> add_texpr_infos(AB0,[ABI],AB)  %,print(abi(ABI)),nl | 
| 703 |  | ; AB=AB0). | 
| 704 |  |  | 
| 705 |  | try_get_merged_position_info(b(_,_,I1),b(_,_,I2),PosInfo) :- | 
| 706 |  | (try_get_merged_position_info_aux(I1,I2,MergedInfo) -> PosInfo = MergedInfo | 
| 707 |  | ; get_non_label_posinfo(Pos1,I1) -> PosInfo=nodeid(Pos1) | 
| 708 |  | ; get_non_label_posinfo(Pos2,I2) -> PosInfo=nodeid(Pos2) | 
| 709 |  | ). | 
| 710 |  | try_get_merged_position_info_aux(I1,I2,nodeid(pos(C,Filenumber,Srow,Scol,Erow,Ecol))) :- | 
| 711 |  | member(nodeid(pos(C1,Filenumber,Srow1,Scol1,Erow1,Ecol1)),I1), | 
| 712 |  | (number(C1),number(Srow1),number(Scol1),number(Erow1),number(Ecol1) | 
| 713 |  | -> true ; add_internal_error('Info field 1 not yet instantiated: ',try_get_merged_position_info(I1)),fail), | 
| 714 |  | !, | 
| 715 |  | member(nodeid(pos(C2,Filenumber,Srow2,Scol2,Erow2,Ecol2)),I2), | 
| 716 |  | (number(C2),number(Srow2),number(Scol2),number(Erow2),number(Ecol2) | 
| 717 |  | -> true ; add_internal_error('Info field 2 not yet instantiated: ',try_get_merged_position_info(I2)),fail), | 
| 718 |  | !, | 
| 719 |  | % merge position info if in same file | 
| 720 |  | (C1 =< C2 -> C=C1, Srow=Srow1,Scol=Scol1 ; C=C2, Srow=Srow2,Scol=Scol2), | 
| 721 |  | ((Erow1 > Erow2 ; Erow1=Erow2, Ecol1 >= Ecol2) | 
| 722 |  | -> Erow =Erow1, Ecol=Ecol1 | 
| 723 |  | ;  Erow =Erow2, Ecol=Ecol2). | 
| 724 |  |  | 
| 725 |  | % get position info which is not a label; label info should not be propagated to outer conjuncts/disjuncts/... | 
| 726 |  | get_non_label_posinfo(Pos,Infos) :- member(nodeid(Pos),Infos), | 
| 727 |  | \+ functor(Pos,rodinpos,_). | 
| 728 |  |  | 
| 729 |  | get_texpr_non_label_posinfo(b(_,_,Infos),nodeid(Pos)) :- get_non_label_posinfo(Pos,Infos). | 
| 730 |  |  | 
| 731 |  | % conjunct list of predicates and try and construct position information | 
| 732 |  | conjunct_predicates_with_pos_info([H|T],Res) :- is_truth(H),!, | 
| 733 |  | (T=[] -> Res = H ; conjunct_predicates_with_pos_info(T,Res)). | 
| 734 |  | conjunct_predicates_with_pos_info([H|T],Res) :- | 
| 735 |  | last_non_truth(T,none,Last), % the truth elements will be removed and are not relevant; get last relevant predicate | 
| 736 |  | Last \= none, | 
| 737 |  | try_get_merged_position_info(H,Last,MergedPosInfo), % try and merge position of first and last element | 
| 738 |  | !, | 
| 739 |  | conjunct_predicates([H|T],Res0), | 
| 740 |  | add_texpr_infos(Res0,[MergedPosInfo],Res). % Res0 should have no nodeid field | 
| 741 |  | conjunct_predicates_with_pos_info(L,Res) :- conjunct_predicates(L,Res). | 
| 742 |  |  | 
| 743 |  | :- assert_must_succeed((bsyntaxtree:last_non_truth([a,b,c],none,L),L==c)). | 
| 744 |  | :- assert_must_succeed((bsyntaxtree:last_non_truth([a,b,c,b(truth,pred,[])],none,L),L==c)). | 
| 745 |  |  | 
| 746 |  | % get last non-truth element and filter out all truth elements | 
| 747 |  | last_non_truth([],Acc,Acc). | 
| 748 |  | last_non_truth([H|T],NonTruth,Last) :- is_truth(H),!, last_non_truth(T,NonTruth,Last). | 
| 749 |  | last_non_truth([H|T],_,Last) :- last_non_truth(T,H,Last). | 
| 750 |  |  | 
| 751 |  |  | 
| 752 |  | texpr_contains_wd_condition(b(_,_,Info)) :- !, memberchk(contains_wd_condition,Info). | 
| 753 |  | texpr_contains_wd_condition(E) :- add_internal_error('Not a texpr: ',texpr_contains_wd_condition(E)). | 
| 754 |  |  | 
| 755 |  | % a version of create_texpr which collects automatically important infos from sub-expressions | 
| 756 |  | safe_create_texpr(Expr,Type,b(Expr,Type,Info)) :- % | 
| 757 | ? | (sub_expression_contains_wd_condition(Expr) -> Info = [contains_wd_condition] ; Info=[]). | 
| 758 |  |  | 
| 759 |  | safe_create_texpr(Expr,Type,Info,b(Expr,Type,FullInfo)) :- % | 
| 760 |  | ((sub_expression_contains_wd_condition(Expr), nonmember(contains_wd_condition, Info)) -> FullInfo = [contains_wd_condition|Info] ; FullInfo=Info). | 
| 761 |  |  | 
| 762 | ? | sub_expression_contains_wd_condition(Expr) :- sub_expression_contains_wd_condition(Expr,_). | 
| 763 |  | sub_expression_contains_wd_condition(Expr,Sub) :- | 
| 764 |  | safe_syntaxelement_det(Expr,Subs,_Names,_L,_C), | 
| 765 | ? | member(b(Sub,_,Infos),Subs), | 
| 766 |  | (var(Infos) | 
| 767 |  | -> add_internal_error('Typed expression not sufficiently instantiated (variable Infos): ',sub_expression_contains_wd_condition(Expr)), | 
| 768 |  | fail | 
| 769 |  | ; memberchk(contains_wd_condition,Infos)). | 
| 770 |  |  | 
| 771 |  | % provide updated infos (e.g., reads(...)) and remove any old info fields with same functor | 
| 772 |  | update_infos([],Infos,Infos). | 
| 773 |  | update_infos([Update|T],OldInfos,NewInfos) :- | 
| 774 |  | functor(Update,F,N), | 
| 775 |  | functor(Old,F,N), | 
| 776 |  | delete(OldInfos,Old,OldInfos1), | 
| 777 |  | update_infos(T,[Update|OldInfos1],NewInfos). | 
| 778 |  |  | 
| 779 |  | % merge two info lists and try to reconcile position information: | 
| 780 |  | merge_info(Info1,Info2,Res) :- | 
| 781 |  | merge_imp_info2(Info2,Info1,NewInfo), | 
| 782 |  | (try_get_merged_position_info_aux(Info1,Info2,NewPos) | 
| 783 |  | -> delete_pos_info(NewInfo,NI2), | 
| 784 |  | Res = [NewPos|NI2] | 
| 785 |  | ; Res = NewInfo). | 
| 786 |  |  | 
| 787 |  | % extract important info but without used_ids: | 
| 788 |  | extract_info_wo_used_ids(b(_,_,Info1),Info) :- | 
| 789 |  | extract_pos_infos(Info1,PosInfos), | 
| 790 |  | extract_just_important_info_aux(Info1,[],I1), | 
| 791 |  | append(PosInfos,I1,Info). | 
| 792 |  | extract_info_wo_used_ids_and_pos(b(_,_,Info1),b(_,_,Info2),Info) :- | 
| 793 |  | extract_just_important_info_aux(Info1,[],I1), | 
| 794 |  | extract_just_important_info_aux(Info2,I1,Info). | 
| 795 |  |  | 
| 796 |  | % extract important info from one sub-expression: | 
| 797 |  | extract_info(b(_,_,Info1),NewInfo) :- | 
| 798 |  | extract_imp_info1(Info1,I1),!, NewInfo = I1. | 
| 799 |  | extract_info(A,R) :- | 
| 800 |  | add_internal_error('Could not extract info: ',extract_info(A,R)), | 
| 801 |  | R=[]. | 
| 802 |  | % extract imortant info fields from two (sub-)expressions | 
| 803 |  | extract_info(b(_,_,Info1),b(_,_,Info2),NewInfo) :- | 
| 804 |  | merge_imp_info2(Info1,Info2,II),!, NewInfo = II. | 
| 805 |  | %:- use_module(library(ordsets),[ord_intersection/3]). | 
| 806 |  | %   ord_intersection(Info1,Info2,NewInfo),!. | 
| 807 |  | % TO DO: should we merge nodeid position information !? | 
| 808 |  | extract_info(A,B,R) :- add_internal_error('Could not extract info: ',extract_info(A,B,R)), | 
| 809 |  | R=[]. | 
| 810 |  |  | 
| 811 |  | % extract important info and used_ids | 
| 812 |  | extract_imp_info1([],[]). | 
| 813 |  | extract_imp_info1([H|T],Res) :- | 
| 814 |  | ((important_info(H); H=used_ids(_)) -> Res=[H|ET], extract_imp_info1(T,ET) | 
| 815 |  | ; extract_imp_info1(T,Res) | 
| 816 |  | ). | 
| 817 |  |  | 
| 818 |  | % extract and merge important info and try to merge used_ids from two info lists | 
| 819 |  | merge_imp_info2(Info1,Info2,ResInfos) :- | 
| 820 |  | extract_imp_info1(Info1,I1), | 
| 821 |  | extract_imp_info1(Info2,I2), | 
| 822 |  | merge_aux(I1,I2,ResInfos). | 
| 823 |  |  | 
| 824 |  | merge_aux([],I2,Res) :- !, delete(I2,used_ids(_),Res). % used_ids not valid for new construct | 
| 825 |  | merge_aux(I1,[],Res) :- !, delete(I1,used_ids(_),Res). % ditto | 
| 826 |  | merge_aux(I1,I2,ResInfos) :- | 
| 827 | ? | (select(used_ids(Ids1),I1,II1) | 
| 828 | ? | -> (select(used_ids(Ids2),I2,II2) | 
| 829 |  | ->  ord_union(Ids1,Ids2,Ids3), | 
| 830 |  | append(II1,[used_ids(Ids3)|II2],II) | 
| 831 |  | ;  append(II1,I2,II) | 
| 832 |  | ) | 
| 833 |  | ;  delete(I2,used_ids(_),II2), | 
| 834 |  | append(I1,II2,II) | 
| 835 |  | ), | 
| 836 |  | sort(II,ResInfos). % TO DO: sort sublists ? and use ord_union? | 
| 837 |  |  | 
| 838 |  | important_info(contains_wd_condition). | 
| 839 |  | important_info(prob_annotation(_)). | 
| 840 |  | important_info(allow_to_lift_exists). | 
| 841 |  | important_info(removed_typing). | 
| 842 |  | %important_info(lambda_result(_)). % should probably not be copied | 
| 843 |  |  | 
| 844 |  | % variation of above which does not extract and merge used_ids: | 
| 845 |  | extract_just_important_info_aux([],Acc,Acc). | 
| 846 |  | extract_just_important_info_aux([H|T],Acc,Res) :- | 
| 847 |  | (important_info(H), \+ member(H,Acc) -> extract_just_important_info_aux(T,[H|Acc],Res) | 
| 848 |  | ; extract_just_important_info_aux(T,Acc,Res)). | 
| 849 |  |  | 
| 850 |  |  | 
| 851 |  | is_a_conjunct(b(conjunct(A,B),pred,_),A,B). | 
| 852 |  | % use is_a_conjunct_without_label if you want to avoid decomposing conjunction associated with a single label | 
| 853 |  | is_a_conjunct_without_label(b(conjunct(A,B),pred,I),A,B) :- \+ get_info_labels(I,_). | 
| 854 |  | % use decompose conjunct if you want to propagate labels down to the conjuncts | 
| 855 |  | decompose_conjunct(b(conjunct(A,B),pred,I),ResA,ResB) :- | 
| 856 |  | (get_info_labels(I,Labels) | 
| 857 |  | -> add_labels_to_texpr(A,Labels,ResA), add_labels_to_texpr(B,Labels,ResB) | 
| 858 |  | ; ResA=A, ResB=B). | 
| 859 |  |  | 
| 860 |  | size_of_conjunction(C,Size) :- size_of_conjunction(C,0,Size). | 
| 861 |  | size_of_conjunction(C,Acc,Res) :- is_a_conjunct(C,A,B),!, | 
| 862 |  | size_of_conjunction(B,Acc,A1), | 
| 863 |  | size_of_conjunction(A,A1,Res). | 
| 864 |  | size_of_conjunction(_,Acc,Size) :- Size is Acc+1. | 
| 865 |  |  | 
| 866 |  | conjunction_to_list(C,L) :- var(C),!, | 
| 867 |  | add_error_fail(conjunction_to_list,'Internal error: var :',conjunction_to_list(C,L)). | 
| 868 |  | conjunction_to_list(C,List) :- | 
| 869 |  | conjunction_to_list2(C,List,[]). | 
| 870 |  | conjunction_to_list2(X,I,O) :- X=b(E,_,_), | 
| 871 |  | (E=conjunct(LHS,RHS) -> conjunction_to_list2(LHS,I,Inter), | 
| 872 |  | conjunction_to_list2(RHS,Inter,O) | 
| 873 |  | ; E = truth -> I=O | 
| 874 |  | ; I = [X|O]). | 
| 875 |  |  | 
| 876 |  | % a variation of conjunction_to_list which propagates Rodin and pragma label infos down | 
| 877 |  | % important for proof info; maybe we should only propagate Rodin labels ? | 
| 878 |  | conjunction_to_list_with_rodin_labels(C,L) :- var(C),!, | 
| 879 |  | add_error_fail(conjunction_to_list,'Internal error: var :',conjunction_to_list_with_rodin_labels(C,L)). | 
| 880 |  | conjunction_to_list_with_rodin_labels(C,List) :- | 
| 881 |  | conjunction_to_list_with_labels2(C,List,[]). | 
| 882 |  | conjunction_to_list_with_labels2(b(conjunct(A,B),pred,Infos),I,O) :- !, | 
| 883 |  | copy_rodin_label(Infos,A,B,LHS,RHS), | 
| 884 |  | conjunction_to_list_with_labels2(LHS,I,Inter), | 
| 885 |  | conjunction_to_list_with_labels2(RHS,Inter,O). | 
| 886 |  | conjunction_to_list_with_labels2(X,I,O) :- X=b(E,_,_), | 
| 887 |  | (  E = truth -> I=O | 
| 888 |  | ; I = [X|O]). | 
| 889 |  |  | 
| 890 |  |  | 
| 891 |  | copy_rodin_label(Infos,A,B,NewA,NewB) :- member(Pos,Infos), is_rodin_label_info(Pos),!, | 
| 892 |  | add_rodin_label_info(A,Pos,NewA), | 
| 893 |  | add_rodin_label_info(B,Pos,NewB). | 
| 894 |  | copy_rodin_label(_,A,B,A,B). | 
| 895 |  |  | 
| 896 |  | add_rodin_label_info(b(E,T,I),Pos,b(E,T,I2)) :- | 
| 897 |  | (member(Pos,I), is_rodin_label_info(Pos) -> I2=I | 
| 898 |  | ; I2 = [Pos|I]). | 
| 899 |  |  | 
| 900 |  | is_rodin_label_info(nodeid(Pos)) :-  functor(Pos,rodinpos,_). | 
| 901 |  |  | 
| 902 |  |  | 
| 903 |  | flatten_conjunctions(List,FlattenedList) :- flatten_conj_aux(List,FlattenedList,[]). | 
| 904 |  | flatten_conj_aux([]) --> !, []. | 
| 905 |  | flatten_conj_aux([H|T]) --> !, flatten_conj_aux(H),flatten_conj_aux(T). | 
| 906 |  | flatten_conj_aux(C) --> {is_a_conjunct(C,LHS,RHS)}, | 
| 907 |  | !, | 
| 908 |  | flatten_conj_aux(LHS), flatten_conj_aux(RHS). | 
| 909 |  | flatten_conj_aux(Truth) --> {is_truth(Truth)},!,[]. | 
| 910 |  | flatten_conj_aux(C) --> [C]. | 
| 911 |  |  | 
| 912 |  | member_in_conjunction(M,Conj) :- is_a_conjunct(Conj,LHS,RHS),!, | 
| 913 | ? | (member_in_conjunction(M,LHS) ; member_in_conjunction(M,RHS)). | 
| 914 |  | member_in_conjunction(M,M). | 
| 915 |  |  | 
| 916 |  | % a version of member_in_conjunction which can deal with lazy_let_pred : | 
| 917 |  | % member_in_conjunction_cse(FullConjunctWithLets,InnerConjunctNotALet,  Conjunction) | 
| 918 |  | member_in_conjunction_cse(M,InnerConj,Conj) :- is_a_conjunct(Conj,LHS,RHS),!, | 
| 919 |  | (member_in_conjunction_cse(M,InnerConj,LHS) ; member_in_conjunction_cse(M,InnerConj,RHS)). | 
| 920 |  | member_in_conjunction_cse(Conj,InnerConj,b(lazy_let_pred(ID,Share,Body),pred,Info)) :- | 
| 921 |  | Conj = b(lazy_let_pred(ID,Share,BConj),pred,Info),!, | 
| 922 |  | member_in_conjunction_cse(BConj,InnerConj,Body). | 
| 923 |  | member_in_conjunction_cse(M,M,M). | 
| 924 |  |  | 
| 925 |  | % not terribly efficient way to select and remove a conjunct from a predicate | 
| 926 |  | select_member_in_conjunction(M,Conj,Rest) :- is_a_conjunct(Conj,LHS,RHS),!, | 
| 927 |  | (select_member_in_conjunction(M,LHS,RL), conjunct_predicates([RL,RHS],Rest) | 
| 928 |  | ; select_member_in_conjunction(M,RHS,RR), conjunct_predicates([LHS,RR],Rest)). | 
| 929 |  | select_member_in_conjunction(M,M,b(truth,pred,[])). | 
| 930 |  |  | 
| 931 |  | is_a_disjunct(b(disjunct(A,B),pred,_),A,B). | 
| 932 |  | is_a_negation(b(negation(A),pred,_),A). | 
| 933 |  |  | 
| 934 |  | disjunction_to_list(C,L) :- var(C),!, | 
| 935 |  | add_error_fail(disjunction_to_list,'Internal error: var :',disjunction_to_list(C,L)). | 
| 936 |  | disjunction_to_list(C,List) :- | 
| 937 |  | disjunction_to_list2(C,List,[]). | 
| 938 |  | disjunction_to_list2(C,I,O) :- is_a_disjunct(C,LHS,RHS),!, | 
| 939 |  | disjunction_to_list2(LHS,I,Inter), | 
| 940 |  | disjunction_to_list2(RHS,Inter,O). | 
| 941 |  | disjunction_to_list2(X,[X|R],R). | 
| 942 |  |  | 
| 943 |  | is_an_implication(b(implication(A,B),pred,_),A,B). | 
| 944 |  |  | 
| 945 |  | is_an_equivalence(b(equivalence(A,B),pred,_),A,B). | 
| 946 |  |  | 
| 947 |  |  | 
| 948 |  | is_a_disjunct_or_implication(b(DI,pred,_),Type,A,B) :- is_a_disj_or_impl_aux(DI,Type,A,B). | 
| 949 |  | is_a_disj_or_impl_aux(disjunct(A,B),'disjunction',A,B). | 
| 950 |  | is_a_disj_or_impl_aux(implication(A,B),'implication',NA,B) :- | 
| 951 |  | create_negation(A,NA). | 
| 952 |  | is_a_disj_or_impl_aux(negation(b(conjunct(A,B),pred,_)),'negated conjunction',NA,NB) :- | 
| 953 |  | create_negation(A,NA),create_negation(B,NB). | 
| 954 |  |  | 
| 955 |  | % a more liberal version of is_a_conjunct/2 which also detects negated disjunctions/implications | 
| 956 |  | is_a_conjunct_or_neg_disj(b(DI,pred,I),A,B) :- is_conjunct_aux(DI,I,A,B). | 
| 957 |  |  | 
| 958 |  | is_conjunct_aux(conjunct(LHS,RHS),_,LHS,RHS). | 
| 959 |  | is_conjunct_aux(negation(DISJ),_,NegLHS,NegRHS) :- | 
| 960 |  | is_a_disjunct_or_implication(DISJ,_Type,LHS,RHS), | 
| 961 |  | create_negation(LHS,NegLHS), | 
| 962 |  | create_negation(RHS,NegRHS). | 
| 963 |  | is_conjunct_aux(equal(TA,TB),I,b(equal(TA1,TB1),pred,I),b(equal(TA2,TB2),pred,I)) :- | 
| 964 |  | % split TA1|->TA2 = TB1|->TB2, cf, split_equality/3; useful for enumeration order analysis | 
| 965 |  | get_texpr_couple(TA,TA1,TA2), | 
| 966 |  | get_texpr_couple(TB,TB1,TB2). | 
| 967 |  | % print('Splitting equality in is_a_conjunct_or_neg_disj: '), translate:print_bexpr(b(equal(TA,TB),pred,I)),nl. | 
| 968 |  |  | 
| 969 |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
| 970 |  | % remove all info fields by fresh variables | 
| 971 |  | % typically the result will be unified with AST terms which contain full info fields | 
| 972 |  | remove_all_infos(TExpr,TNExpr) :- | 
| 973 |  | var(TExpr),!,TExpr=TNExpr. | 
| 974 |  | % in contrast to remove_all_infos_and_ground we provide no special treatment of values with closures here; | 
| 975 |  | % there could be a problem if we unify with a free variable as value | 
| 976 |  | remove_all_infos(TExpr,TNExpr) :- | 
| 977 |  | get_texpr_expr(TExpr,Expr), | 
| 978 |  | get_texpr_type(TExpr,Type), | 
| 979 |  | syntaxtransformation(Expr,Subs,_,NSubs,NExpr), | 
| 980 |  | create_texpr(NExpr,Type,_,TNExpr), | 
| 981 |  | maplist(remove_all_infos,Subs,NSubs). | 
| 982 |  |  | 
| 983 |  | % replace all info fields | 
| 984 |  | remove_all_infos_and_ground(TExpr,TNExpr) :- | 
| 985 |  | var(TExpr),!,TExpr=TNExpr. | 
| 986 |  | remove_all_infos_and_ground(b(value(Value),Type,_),TNExpr) :- | 
| 987 |  | % special case for closure(_,_,_) since it is not covered by syntraxtransformation/5 | 
| 988 |  | % most useful for intervals | 
| 989 |  | !, | 
| 990 |  | remove_all_infos_from_bvalue(Value,NValue), | 
| 991 |  | TNExpr = b(value(NValue),Type,[]). | 
| 992 |  | remove_all_infos_and_ground(TExpr,TNExpr) :- | 
| 993 |  | get_texpr_expr(TExpr,Expr), | 
| 994 |  | get_texpr_type(TExpr,Type), | 
| 995 |  | syntaxtransformation(Expr,Subs,_,NSubs,NExpr), | 
| 996 |  | create_texpr(NExpr,Type,[],TNExpr), | 
| 997 |  | maplist(remove_all_infos_and_ground,Subs,NSubs). | 
| 998 |  |  | 
| 999 |  | remove_all_infos_from_bvalue(Var,Res) :- var(Var),!, Res=Var. | 
| 1000 |  | remove_all_infos_from_bvalue((A,B),(RA,RB)) :- !, | 
| 1001 |  | remove_all_infos_from_bvalue(A,RA), | 
| 1002 |  | remove_all_infos_from_bvalue(B,RB). | 
| 1003 |  | remove_all_infos_from_bvalue(closure(P,T,Body),Res) :- !, | 
| 1004 |  | remove_all_infos_and_ground(Body,RBody), | 
| 1005 |  | Res = closure(P,T,RBody). | 
| 1006 |  | % TODO: we could provide more cases like records, sets as lists, freetype values | 
| 1007 |  | remove_all_infos_from_bvalue(Val,Val). | 
| 1008 |  |  | 
| 1009 |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
| 1010 |  |  | 
| 1011 |  | % a version of create_exists_opt which also detects top-level disjunctions | 
| 1012 |  | % and marks the exists as generated and as allow_to_lift_exists | 
| 1013 |  | create_exists_opt_liftable(Ids,b(disjunct(A,B),pred,Info1),NewPred) :- !, | 
| 1014 |  | create_exists_opt_liftable(Ids,A,PA), | 
| 1015 |  | create_exists_opt_liftable(Ids,B,PB), | 
| 1016 |  | disjunct_predicates_with_pos_info(PA,PB,b(NP,pred,Info2)), | 
| 1017 |  | NewPred=b(NP,pred,NewInfo), | 
| 1018 |  | extract_just_important_info_aux(Info1,Info2,NewInfo). % copy symbolic or other relevant info | 
| 1019 |  | create_exists_opt_liftable(Ids,Pred,NewPred) :- conjunction_to_list(Pred,L), | 
| 1020 |  | create_exists_opt(Ids,L,[allow_to_lift_exists],NewPred,_Modified). | 
| 1021 |  |  | 
| 1022 |  | % create_exists_opt(TIds,Preds,NewPred) | 
| 1023 |  | %   creating an existential quantification with some optimisations. | 
| 1024 |  | % TIds: The typed identifiers that are quantified | 
| 1025 |  | % Preds: A list of predicates | 
| 1026 |  | % NewPred: The (optimised) quantified expression | 
| 1027 |  | % Basically two optimisations are performed: | 
| 1028 |  | %  - identifiers that are not used at all are removed from the quantifier | 
| 1029 |  | %  - predicates that do not use one of the quantified identifiers are moved | 
| 1030 |  | %    outside the quantification, resulting in a predicate of the form "P & #x.Q(x)" | 
| 1031 |  |  | 
| 1032 |  | create_exists_opt(TIds,Preds,NewPred) :- | 
| 1033 |  | create_exists_opt(TIds,Preds,[],NewPred,_). | 
| 1034 |  |  | 
| 1035 |  | create_exists_opt(TIds,Preds,NewPred,Modified) :- | 
| 1036 |  | create_exists_opt(TIds,Preds,[],NewPred,Modified). | 
| 1037 |  |  | 
| 1038 |  | create_exists_opt([],Preds,_,NewPred,Modified) :- !, Modified = false, | 
| 1039 |  | conjunct_predicates(Preds,NewPred). | 
| 1040 |  | create_exists_opt(TIds,Preds,AdditionalInfos,Res,Mod) :- | 
| 1041 |  | get_texpr_ids(TIds,UnsortedIds), sort(UnsortedIds,Ids), | 
| 1042 |  | (create_exists_opt1(TIds,Ids,Preds,AdditionalInfos,NewPred2,Modified) -> Res = NewPred2, Mod=Modified | 
| 1043 |  | ; add_internal_error('Call failed:',create_exists_opt(TIds,Preds,AdditionalInfos,_,_)),fail). | 
| 1044 |  | %create_exists_opt1(TIds,_,Preds,AdditionalInfos,NewPred,Modified) :- preference(data_validation_mode,true), | 
| 1045 |  | %   % do not lift predicates outside of existential quantifiers and change order; see rule_avec_DV.mch ClearSy example (N_ITERa_avec_DV_sans_DV) and test 1945 | 
| 1046 |  | create_exists_opt1(TIds,Ids,Preds,AdditionalInfos,NewPred2,Modified) :- | 
| 1047 |  | create_exists_opt2(Preds,first,Ids,[],Inner,Outer,UsedIds), | 
| 1048 |  | % Inner: quantified part, Outer: part which does not have to be quantified | 
| 1049 |  | ( Inner = [] -> AllPreds=Outer % no exists needed | 
| 1050 |  | ; % Inner = [_|_] -> | 
| 1051 |  | create_filtered_exists(TIds,UsedIds,Inner,AdditionalInfos,Exists,IModified), | 
| 1052 |  | append(Outer,[Exists],AllPreds) | 
| 1053 |  | ), | 
| 1054 |  | (Outer=[_|_] -> Modified=true % TO DO: check if TIds=UsedTIds | 
| 1055 |  | ; IModified==true -> Modified=true | 
| 1056 |  | ; UsedIds == Ids -> Modified= false | 
| 1057 |  | ; Modified=true), | 
| 1058 |  | conjunct_predicates(AllPreds,NewPred2). | 
| 1059 |  |  | 
| 1060 |  | % create an exists for the used Ids only | 
| 1061 |  | create_filtered_exists(TIds,UsedIds,Inner,AdditionalInfos,Exists,_) :- | 
| 1062 |  | ceo_filter_used_ids(TIds,UsedIds,UsedTIds), % filter out unused variables | 
| 1063 |  | conjunct_predicates_with_pos_info(Inner,I), % we could store used_ids info | 
| 1064 |  | create_exists_detect_tautology_aux(UsedTIds,I,AdditionalInfos,Exists). | 
| 1065 |  | % remove_typing also added in create_exists_detect_tautology_aux | 
| 1066 |  |  | 
| 1067 |  |  | 
| 1068 |  | % return Inner: predicates inside quantifier and Outer: predicates that can be moved out of the quantifier | 
| 1069 |  | create_exists_opt2([],_,_Ids,UsedIds,[],[],UsedIds) :- !. | 
| 1070 |  | create_exists_opt2([Pred|Prest],First,Ids,UsedIdsIn,Inner,Outer,UsedIdsOut) :- !, | 
| 1071 |  | find_identifier_uses_if_necessary(Pred, [], LocalUses), % TODO: add used_ids(LocalUses) to Pred | 
| 1072 |  | ord_intersection(Ids,LocalUses,ExistsIdsUsed), | 
| 1073 |  | ( ExistsIdsUsed = [], % Pred uses none of the quantified ids: we can move it out | 
| 1074 |  | (First==first -> true | 
| 1075 |  | ; preference(data_validation_mode,false), % see test 1945; step 39 in trace replay | 
| 1076 |  | always_well_defined_or_disprover_mode(Pred) % TODO: we should probably also check this ! | 
| 1077 |  | ) | 
| 1078 |  | -> | 
| 1079 |  | Inner = Irest, | 
| 1080 |  | Outer = [Pred|Orest], % move Pred out of existential quantifier as it does not depend on quantified variables | 
| 1081 |  | % format('MOVED out of #(~w): ',[Ids]),translate:print_bexpr(Pred), format('  Uses ~w   [~w]~n',[LocalUses,ExistsIdsUsed]), | 
| 1082 |  | create_exists_opt2(Prest,first,Ids,UsedIdsIn,Irest,Orest,UsedIdsOut) | 
| 1083 |  | ; | 
| 1084 |  | update_used_ids(Pred,LocalUses,Pred2), | 
| 1085 |  | Inner = [Pred2|Irest], | 
| 1086 |  | Outer = Orest, | 
| 1087 |  | ord_union(UsedIdsIn,ExistsIdsUsed,Urest), | 
| 1088 |  | create_exists_opt2(Prest,not_first_anymore,Ids,Urest,Irest,Orest,UsedIdsOut) | 
| 1089 |  | ). | 
| 1090 |  | create_exists_opt2(Pred,First,Ids,UsedIdsIn,Inner,Outer,UsedIdsOut) :- | 
| 1091 |  | add_error(create_exists_opt,'Expecting predicate list: ',Pred), | 
| 1092 |  | create_exists_opt2([Pred],First,Ids,UsedIdsIn,Inner,Outer,UsedIdsOut). | 
| 1093 |  |  | 
| 1094 |  | % construct exists optimized: keep only used TIds | 
| 1095 |  | ceo_filter_used_ids([],_UsedIds,[]). | 
| 1096 |  | ceo_filter_used_ids([TId|Irest],UsedIds,Filtered) :- | 
| 1097 |  | get_texpr_id(TId,Id), | 
| 1098 |  | ( ord_member(Id,UsedIds) -> Filtered = [TId|Frest] % id used: keep it | 
| 1099 |  | ; Filtered = Frest), | 
| 1100 |  | ceo_filter_used_ids(Irest,UsedIds,Frest). | 
| 1101 |  |  | 
| 1102 |  | % a version of create_exists which also detects x=E and x:E, x>E, not(x>E) tautologies | 
| 1103 |  | % we could replace this by a more generic prover | 
| 1104 |  | create_exists_detect_tautology_aux([TID],b(member(LHS,RHS),pred,_),_,Truth) :- | 
| 1105 |  | get_texpr_id(LHS,ID), get_texpr_id(TID,ID), | 
| 1106 |  | definitely_not_empty_set(RHS), | 
| 1107 |  | always_well_defined_or_disprover_mode(RHS), | 
| 1108 |  | !, % replace #x.(x:RHS) by TRUTH | 
| 1109 |  | debug_format(19,'Detected tautology exists membership over ~w~n',[ID]), | 
| 1110 |  | Truth=b(truth,pred,[]). | 
| 1111 |  | create_exists_detect_tautology_aux([TID],b(Pred,_,_),_,Truth) :- | 
| 1112 |  | is_comparison(Pred,pos_neg(pos,TID),L,R), get_texpr_id(TID,ID), | 
| 1113 |  | ((LHS,RHS)=(L,R) ; (LHS,RHS)=(R,L)), | 
| 1114 |  | get_texpr_id(LHS,ID), | 
| 1115 |  | \+ occurs_in_expr(ID,RHS), | 
| 1116 |  | always_well_defined_or_disprover_mode(RHS), | 
| 1117 |  | !, % replace #x.(x COMP E) by TRUTH | 
| 1118 |  | debug_format(19,'Detected tautology comparison over ~w~n',[ID]), | 
| 1119 |  | Truth=b(truth,pred,[]). | 
| 1120 |  | %create_exists_detect_tautology_aux(Ids,b(disjunct(A,B),pred,Info1),AdditionalInfos,NewPred) :- !, | 
| 1121 |  | %    create_exists(Ids,A,PA), create_exists(Ids,B,PB), | 
| 1122 |  | %    disjunct_predicates_with_pos_info(PA,PB,b(NP,pred,Info2)), | 
| 1123 |  | %    NewPred=b(NP,pred,NewInfo), | 
| 1124 |  | %    extract_just_important_info_aux(Info1,Info2,NewInfo). % copy symbolic or other relevant info | 
| 1125 |  | create_exists_detect_tautology_aux(Ids,Pred,AdditionalInfos,NewPred2) :- | 
| 1126 |  | create_exists_or_let_predicate(Ids,Pred,NewPred), | 
| 1127 |  | add_texpr_infos_if_new(NewPred,[removed_typing|AdditionalInfos],NewPred2). | 
| 1128 |  | % removed_typing to avoid spurious exists_body_warning, see test 1681, 625 | 
| 1129 |  |  | 
| 1130 |  |  | 
| 1131 |  | is_eventb_comprehension_set(b(comprehension_set(TopIds,Body),_,Info),Ids,PRED,EXPR) :- | 
| 1132 |  | is_eventb_comprehension_set(TopIds,Body,Info,Ids,PRED,EXPR). | 
| 1133 |  | is_eventb_comprehension_set([TID1],Body,Info,Ids,PRED,EXPR) :- | 
| 1134 |  | Body = b(exists(Ids,InnerBody),pred,_), | 
| 1135 |  | conjunction_to_list(InnerBody,Inner), | 
| 1136 |  | append(Inner1,[b(equal(TID2,EXPR),pred,EqInfo)],Inner), | 
| 1137 |  | (member(was(event_b_comprehension_set),Info) -> true ; | 
| 1138 |  | member(prob_annotation('LAMBDA-EQUALITY'),EqInfo) % relevant for TLA2B | 
| 1139 |  | ), | 
| 1140 |  | same_id(TID1,TID2,_), | 
| 1141 |  | conjunct_predicates(Inner1,PRED), | 
| 1142 |  | % we check that TID1 is not being used in P1 and not just rely on was(event_b_comprehension_set) | 
| 1143 |  | not_occurs_in_expr(PRED,TID1). | 
| 1144 |  |  | 
| 1145 |  | % ------------------- | 
| 1146 |  |  | 
| 1147 |  | is_equal(b(equal(LHS,RHS),pred,_),A,B) :- | 
| 1148 |  | ((A,B)=(LHS,RHS) ; (A,B)=(RHS,LHS)). | 
| 1149 |  |  | 
| 1150 |  | :- use_module(typing_tools,[type_has_at_least_two_elements/1]). | 
| 1151 |  | is_comparison(greater(A,B),_,A,B). | 
| 1152 |  | is_comparison(less(A,B),_,A,B). | 
| 1153 |  | is_comparison(greater_equal(A,B),_,A,B). | 
| 1154 |  | is_comparison(less_equal(A,B),_,A,B). | 
| 1155 |  | is_comparison(equal(A,B),pos_neg(P,TID),A,B) :- | 
| 1156 |  | % for neg: we need to make sure there is more than one value in the type (otherwise we cannot make equal false) | 
| 1157 |  | % for pos: assuming the RHS expression above is well-defined there must be at least one element; no need to check non_empty_type(Type) | 
| 1158 |  | (P=pos -> true ; get_texpr_type(TID,Type),type_has_at_least_two_elements(Type)). | 
| 1159 |  | is_comparison(not_equal(A,B),pos_neg(P,TID),A,B) :- % ditto but with pos and neg reversed | 
| 1160 |  | (P=neg -> true ; get_texpr_type(TID,Type),type_has_at_least_two_elements(Type)). | 
| 1161 |  | is_comparison(negation(b(Comp,pred,_)),PosNeg,A,B) :- negate(PosNeg,P2), | 
| 1162 |  | is_comparison(Comp,P2,A,B). | 
| 1163 |  | negate(pos_neg(pos,T),pos_neg(neg,T)). | 
| 1164 |  | negate(pos_neg(neg,T),pos_neg(pos,T)). | 
| 1165 |  |  | 
| 1166 |  |  | 
| 1167 |  |  | 
| 1168 |  | % is true if a predicate Pred can be split into two parts: | 
| 1169 |  | % Outer which does not depend on LocalIds (can be lifted out) and Inner which does | 
| 1170 |  | detect_global_predicates(LocalIds,Pred,Outer,Inner) :- | 
| 1171 |  | get_texpr_ids(LocalIds,UnsortedIds), sort(UnsortedIds,Ids), | 
| 1172 |  | conjunction_to_list(Pred,Preds), | 
| 1173 |  | split_predicate_local_global(Preds,Ids,OuterL,InnerL), | 
| 1174 |  | OuterL \= [], | 
| 1175 |  | conjunct_predicates(OuterL,Outer), | 
| 1176 |  | conjunct_predicates(InnerL,Inner). | 
| 1177 |  | split_predicate_local_global([],_Ids,[],[]). | 
| 1178 |  | split_predicate_local_global([P|Ps],Ids,Outer,Inner) :- | 
| 1179 |  | (is_local_predicate(Ids,P) | 
| 1180 |  | -> Inner = [P|Is], split_predicate_local_global(Ps,Ids,Outer,Is) | 
| 1181 |  | ;  Outer = [P|Os], split_predicate_local_global(Ps,Ids,Os,Inner)). | 
| 1182 |  | is_local_predicate(Ids,Pred) :- | 
| 1183 |  | find_identifier_uses_if_necessary(Pred, [], LocalUses), | 
| 1184 |  | ord_intersect(Ids,LocalUses). | 
| 1185 |  |  | 
| 1186 |  | %:- use_module(b_global_sets,[b_global_set/1]). | 
| 1187 |  | definitely_not_empty_set(b(SET,T,_)) :- not_empty_set_aux(SET,T). | 
| 1188 |  | not_empty_set_aux(bool_set,_). | 
| 1189 |  | not_empty_set_aux(integer_set(_),_). | 
| 1190 |  | not_empty_set_aux(float_set,_). | 
| 1191 |  | not_empty_set_aux(real_set,_). | 
| 1192 |  | not_empty_set_aux(string_set,_). | 
| 1193 |  | not_empty_set_aux(set_extension(X),_) :- dif(X,[]). | 
| 1194 |  | not_empty_set_aux(sequence_extension(X),_) :- dif(X,[]). | 
| 1195 |  | not_empty_set_aux(pow_subset(_),_). % always contains at least the empty set | 
| 1196 |  | not_empty_set_aux(fin_subset(_),_). % ditto | 
| 1197 |  | not_empty_set_aux(seq(_),_). % ditto | 
| 1198 |  | not_empty_set_aux(iseq(_),_). % ditto | 
| 1199 |  | not_empty_set_aux(pow1_subset(A),_) :- definitely_not_empty_set(A). | 
| 1200 |  | not_empty_set_aux(fin1_subset(A),_) :- definitely_not_empty_set(A). | 
| 1201 |  | not_empty_set_aux(seq1(A),_) :- definitely_not_empty_set(A). | 
| 1202 |  | not_empty_set_aux(iseq1(A),_) :- definitely_not_empty_set(A). | 
| 1203 |  | not_empty_set_aux(cartesian_product(A,B),_) :- definitely_not_empty_set(A), definitely_not_empty_set(B). | 
| 1204 |  | not_empty_set_aux(partial_function(_A,_B),_). % always contains at least the empty set | 
| 1205 |  | not_empty_set_aux(partial_injection(_A,_B),_). % ditto | 
| 1206 |  | not_empty_set_aux(relations(_A,_B),_). % ditto | 
| 1207 |  | not_empty_set_aux(total_function(A,B),_) :- | 
| 1208 |  | (definitely_not_empty_set(B) -> true | 
| 1209 |  | ; definitely_empty_set(A)). % if A is empty, then the set of total functions is {{}} | 
| 1210 |  | not_empty_set_aux(union(A,B),_) :- (definitely_not_empty_set(A) -> true ; definitely_not_empty_set(B)). | 
| 1211 |  | not_empty_set_aux(overwrite(A,B),_) :- (definitely_not_empty_set(A) -> true ; definitely_not_empty_set(B)). | 
| 1212 |  | % TODO: add a few more function rules | 
| 1213 |  | not_empty_set_aux(value(S),_) :- not_empty_value(S). | 
| 1214 |  | %not_empty_set_aux(identifier(X),set(global(X))) :- bmachine:b_get_machine_set(X). % what if we have a local variable ? ENSURE THAT WE DO NOT ALLOW identifier X to stand for global set X; see ExistentialGlobalSetIDTest in Tester % also: b_global_set not yet computed when ast_cleanup runs on startup ! | 
| 1215 |  | % TO DO: determine which identifier(X) refer to global set names | 
| 1216 |  | not_empty_set_aux(interval(A,B),_) :- get_integer(A,IA), get_integer(B,IB), IA =< IB. | 
| 1217 |  |  | 
| 1218 |  | :- use_module(b_global_sets,[b_non_empty_global_set/1]). | 
| 1219 |  | :- use_module(kernel_freetypes,[is_non_empty_freetype/1]). | 
| 1220 |  | not_empty_value(S) :- var(S),!,fail. | 
| 1221 |  | not_empty_value(avl_set(_)). | 
| 1222 |  | not_empty_value([_|_]). | 
| 1223 |  | not_empty_value(global_set(G)) :- b_non_empty_global_set(G). % always true | 
| 1224 |  | not_empty_value(freetype(G)) :- is_non_empty_freetype(G). % always true | 
| 1225 |  | not_empty_value(closure(P,T,B)) :- | 
| 1226 |  | custom_explicit_sets:is_interval_closure(P,T,B,LOW,UP), integer(LOW),integer(UP), LOW =< UP. | 
| 1227 |  | %TODO: more closures; see also definitely_not_empty_finite_value | 
| 1228 |  |  | 
| 1229 |  | definitely_empty_set(b(ES,_,_)) :- is_empty_set_aux(ES). | 
| 1230 |  | is_empty_set_aux(empty_set). | 
| 1231 |  | is_empty_set_aux(empty_sequence). | 
| 1232 |  | is_empty_set_aux(domain(D)) :- definitely_empty_set(D). | 
| 1233 |  | is_empty_set_aux(range(D)) :- definitely_empty_set(D). | 
| 1234 |  | is_empty_set_aux(domain_subtraction(_,Rel)) :- definitely_empty_set(Rel). | 
| 1235 |  | is_empty_set_aux(domain_restriction(Dom,Rel)) :- (definitely_empty_set(Dom) -> true ; definitely_empty_set(Rel)). | 
| 1236 |  | is_empty_set_aux(range_restriction(Rel,Ran)) :- (definitely_empty_set(Ran) -> true ; definitely_empty_set(Rel)). | 
| 1237 |  | is_empty_set_aux(range_subtraction(Rel,_)) :- definitely_empty_set(Rel). | 
| 1238 |  | is_empty_set_aux(interval(A,B)) :- get_integer(A,IA), get_integer(B,IB), IA > IB. | 
| 1239 |  | is_empty_set_aux(intersection(A,B)) :- (definitely_empty_set(A) -> true ; definitely_empty_set(B)). | 
| 1240 |  | is_empty_set_aux(set_subtraction(A,_)) :- definitely_empty_set(A). | 
| 1241 |  | is_empty_set_aux(union(A,B)) :- definitely_empty_set(A), definitely_empty_set(B). | 
| 1242 |  | is_empty_set_aux(overwrite(A,B)) :- definitely_empty_set(A), definitely_empty_set(B). | 
| 1243 |  | is_empty_set_aux(value(V)) :- V==[]. | 
| 1244 |  |  | 
| 1245 |  |  | 
| 1246 |  | get_integer(b(B,_,_),I) :- get_integer_aux(B,I). | 
| 1247 |  | get_integer_aux(integer(I),I). | 
| 1248 |  | get_integer_aux(value(V),I) :- get_integer_value(V,I). | 
| 1249 |  | get_integer_value(V,I) :- nonvar(V),V=int(I), integer(I). | 
| 1250 |  |  | 
| 1251 |  |  | 
| 1252 |  |  | 
| 1253 |  | :- use_module(probsrc(custom_explicit_sets),[avl_is_interval/3]). | 
| 1254 |  | get_interval(b(I,set(integer),_),Low,Up) :- | 
| 1255 |  | is_interval_aux(I,Low,Up). | 
| 1256 |  | is_interval_aux(interval(Low,Up),Low,Up). | 
| 1257 |  | is_interval_aux(value(CS),Low,Up) :- nonvar(CS), CS=avl_set(AVL), % occurs in Leftpad_i.imp | 
| 1258 |  | Low = b(integer(LI),integer,[]), Up = b(integer(UI),integer,[]), | 
| 1259 |  | avl_is_interval(AVL,LI,UI). | 
| 1260 |  | is_interval_aux(set_extension(List),Low,Up) :- print(l(List)),nl, | 
| 1261 |  | sort(List,SList), | 
| 1262 |  | SList = [Low|Rest], get_integer(Low,LI), | 
| 1263 |  | last(SList,Up),  get_integer(Up,UI), | 
| 1264 |  | length(List,Len), | 
| 1265 |  | Len is UI-LI+1, | 
| 1266 |  | maplist(get_integer,Rest,_). | 
| 1267 |  |  | 
| 1268 |  | % a simple let-detection | 
| 1269 |  | create_exists_or_let_predicate([H|T],b(conjunct(LHS,RHS),pred,I),NewPred) :- get_texpr_id(H,ID), | 
| 1270 | ? | is_equal(LHS,TID,IDEXPR), % TO DO: should we do a more complicated check here ? exist technique useful for SLOT-24 codespeed test | 
| 1271 |  | get_texpr_id(TID,ID), \+ occurs_in_expr(ID,IDEXPR), | 
| 1272 |  | maplist(not_occurs_in_expr(IDEXPR),T), | 
| 1273 |  | !, | 
| 1274 |  | NewPred = b(let_predicate([TID],[IDEXPR],Body),pred,I), | 
| 1275 |  | %print('LET: '),translate:print_bexpr(NewPred),nl, | 
| 1276 |  | create_exists_or_let_predicate(T,RHS,Body). | 
| 1277 |  | create_exists_or_let_predicate(Ids,Pred,NewPred) :- create_exists(Ids,Pred,NewPred). | 
| 1278 |  |  | 
| 1279 |  | not_occurs_in_expr(IDEXPR,TID) :- get_texpr_id(TID,ID), \+ occurs_in_expr(ID,IDEXPR). | 
| 1280 |  |  | 
| 1281 |  | create_exists([],Pred,NewPred) :- !,Pred=NewPred. | 
| 1282 |  | create_exists(Ids,Pred,NewPred) :- | 
| 1283 |  | find_identifier_uses_for_quantifier_body(Ids,Pred, Used), | 
| 1284 |  | extract_info_wo_used_ids(Pred,NewImportantInfo), | 
| 1285 |  | create_texpr(exists(Ids,Pred),pred,[used_ids(Used)|NewImportantInfo],NewPred). | 
| 1286 |  |  | 
| 1287 |  | % a version of create_exists which can merge with an already present exists if possible | 
| 1288 |  | % possibly more expensive as identfiers used are recomputed for the moment (TODO: reuse used_ids and subtract) | 
| 1289 |  | create_or_merge_exists(IDs, Condition, Exists):- | 
| 1290 |  | get_texpr_expr(Condition,exists(InnerVars,InnerCond)),!, | 
| 1291 |  | % fuse two exists together | 
| 1292 |  | append(IDs,InnerVars,Vars), | 
| 1293 |  | create_or_merge_exists(Vars,InnerCond,Exists). | 
| 1294 |  | create_or_merge_exists(IDs, Condition, Exists):- | 
| 1295 |  | create_exists(IDs,Condition,Exists). | 
| 1296 |  |  | 
| 1297 |  | % see create_unsimplified_exists | 
| 1298 |  | not_generated_exists_paras([b(_,_,Infos)|_]) :- nonmember(generated_exists_parameter,Infos). | 
| 1299 |  |  | 
| 1300 |  |  | 
| 1301 |  | create_forall([],Pred,NewPred) :- !,Pred=NewPred. | 
| 1302 |  | create_forall(Ids,Pred,NewPred) :- | 
| 1303 |  | find_identifier_uses_for_quantifier_body(Ids,Pred, Used), | 
| 1304 |  | split_forall_body(Pred,LHS,RHS), | 
| 1305 |  | extract_info_wo_used_ids_and_pos(LHS,RHS,NewImportantInfo), | 
| 1306 |  | create_texpr(forall(Ids,LHS,RHS),pred,[used_ids(Used)|NewImportantInfo],NewPred). | 
| 1307 |  | split_forall_body(b(implication(LHS,RHS),_,_),LHS,RHS) :- !. | 
| 1308 |  | split_forall_body(RHS,b(truth,pred,[]),RHS). | 
| 1309 |  |  | 
| 1310 |  | create_implication(b(truth,pred,_),P,Res) :- !, Res=P. | 
| 1311 |  | create_implication(b(falsity,pred,_),P,Res) :- !, create_negation(P,Res). | 
| 1312 |  | create_implication(Lhs,Rhs,b(implication(Lhs,Rhs),pred,NewInfo)) :- | 
| 1313 |  | extract_info(Lhs,Rhs,NewInfo). | 
| 1314 |  |  | 
| 1315 |  | create_equivalence(Lhs,Rhs, b(equivalence(Lhs,Rhs),pred,NewInfo)) :- | 
| 1316 |  | extract_info(Lhs,Rhs,NewInfo). | 
| 1317 |  |  | 
| 1318 |  | create_negation(b(P,pred,I),Res) :- create_negation_aux(P,I,R),!,Res=R. | 
| 1319 |  | create_negation(Pred,b(negation(Pred),pred,NewInfo)) :- | 
| 1320 |  | extract_info(Pred,Infos), | 
| 1321 |  | (get_texpr_non_label_posinfo(Pred,Pos) -> NewInfo = [Pos|Infos] ; NewInfo=Infos). | 
| 1322 |  |  | 
| 1323 |  | create_negation_aux(truth,I,R) :- !, R=b(falsity,pred,I). | 
| 1324 |  | create_negation_aux(falsity,I,R) :- !, R=b(truth,pred,I). | 
| 1325 |  | create_negation_aux(negation(Pred),_,R) :- R=Pred. % not(not(P)) = P | 
| 1326 |  | %create_negation_aux(equal(A,B),I,R) :- !, R=b(not_equal(A,B),pred,I). | 
| 1327 |  | %create_negation_aux(not_equal(A,B),I,R) :- !, R=b(equal(A,B),pred,I). | 
| 1328 |  | % we could add some rules about negating member <-> not_member, ... but be careful with effects on is_negation_of | 
| 1329 |  |  | 
| 1330 |  | % check if something is the negation of something else (quite stupid at the moment) | 
| 1331 |  | % used, e.g., to detect IF-THEN-ELSE constructs in b_ast_cleanup | 
| 1332 |  | is_negation_of(P,NP) :- | 
| 1333 |  | create_negation(P,NotP), % works both with not(A),A  or A,not(A) | 
| 1334 |  | same_texpr(NotP,NP). | 
| 1335 |  | is_negation_of(b(P,pred,_),b(NP,pred,_)) :- is_negation_aux(P,NP). | 
| 1336 |  |  | 
| 1337 |  | is_negation_aux(equal(A,B),NP) :- is_negation_of_equality(NP,A,B). | 
| 1338 |  | is_negation_aux(not_equal(A,B),NP) :- is_negation_of_disequality(NP,A,B). | 
| 1339 |  | is_negation_aux(subset(XA,SA),not_subset(XB,SB)) :- same_texpr(XA,XB), same_texpr(SA,SB). | 
| 1340 |  | is_negation_aux(not_subset(XA,SA),subset(XB,SB)) :- same_texpr(XA,XB), same_texpr(SA,SB). | 
| 1341 |  | is_negation_aux(subset_strict(XA,SA),not_subset_strict(XB,SB)) :- same_texpr(XA,XB), same_texpr(SA,SB). | 
| 1342 |  | is_negation_aux(not_subset_strict(XA,SA),subset_strict(XB,SB)) :- same_texpr(XA,XB), same_texpr(SA,SB). | 
| 1343 |  | is_negation_aux(member(XA,SA),not_member(XB,SB)) :- same_texpr(XA,XB), same_texpr(SA,SB). | 
| 1344 |  | is_negation_aux(not_member(XA,SA),member(XB,SB)) :- same_texpr(XA,XB), same_texpr(SA,SB). | 
| 1345 |  | is_negation_aux(less(A,B),greater_equal(AA,BB)) :- same_texpr(A,AA), same_texpr(B,BB). | 
| 1346 |  | is_negation_aux(less(A,B),less_equal(BB,AA)) :- same_texpr(A,AA), same_texpr(B,BB). | 
| 1347 |  | is_negation_aux(less_equal(B,A),less(AA,BB)) :- same_texpr(A,AA), same_texpr(B,BB). | 
| 1348 |  | is_negation_aux(less_equal(A,B),greater(AA,BB)) :- same_texpr(A,AA), same_texpr(B,BB). | 
| 1349 |  | is_negation_aux(greater_equal(A,B),NP) :- is_negation_aux(less_equal(B,A),NP). | 
| 1350 |  | is_negation_aux(greater(A,B),NP) :- is_negation_aux(less(B,A),NP). | 
| 1351 |  | is_negation_aux(less_equal_real(B,A),less_real(AA,BB)) :- same_texpr(A,AA), same_texpr(B,BB). | 
| 1352 |  | is_negation_aux(less_real(B,A),less_equal_real(AA,BB)) :- same_texpr(A,AA), same_texpr(B,BB). | 
| 1353 |  | is_negation_aux(negation(A),negation(B)) :- is_negation_of(A,B). | 
| 1354 |  | is_negation_aux(truth,falsity). | 
| 1355 |  | is_negation_aux(falsity,truth). | 
| 1356 |  | % TO DO: detect more ?? x < y   <=>  not ( x > y-1 ) | 
| 1357 |  |  | 
| 1358 |  | is_negation_of_equality(not_equal(AA,BB),A,B) :- same_texpr(A,AA), same_texpr(B,BB). | 
| 1359 |  | is_negation_of_equality(equal(AA,BB),A,B) :- same_texpr(A,AA), neg_value(BB,B). | 
| 1360 |  |  | 
| 1361 |  | neg_value(b(boolean_true,_,_),b(boolean_false,_,_)). | 
| 1362 |  | neg_value(b(boolean_false,_,_),b(boolean_true,_,_)). | 
| 1363 |  |  | 
| 1364 |  | is_negation_of_disequality(equal(AA,BB),A,B) :- same_texpr(A,AA), same_texpr(B,BB). | 
| 1365 |  | is_negation_of_disequality(not_equal(AA,BB),A,B) :- same_texpr(A,AA), neg_value(BB,B). | 
| 1366 |  |  | 
| 1367 |  |  | 
| 1368 |  | % another version which is simpler can can be used to get the negation of some operators | 
| 1369 |  |  | 
| 1370 |  | get_negated_operator_expr(b(E,pred,_),Res) :- negate_expr_aux(E,Res). | 
| 1371 |  | negate_expr_aux(falsity,truth). | 
| 1372 |  | negate_expr_aux(truth,falsity). | 
| 1373 |  | negate_expr_aux(member(X,S),not_member(X,S)). | 
| 1374 |  | negate_expr_aux(not_member(X,S),member(X,S)). | 
| 1375 |  | negate_expr_aux(subset(X,S),not_subset(X,S)). | 
| 1376 |  | negate_expr_aux(not_subset(X,S),subset(X,S)). | 
| 1377 |  | negate_expr_aux(subset_strict(X,S),not_subset_strict(X,S)). | 
| 1378 |  | negate_expr_aux(not_subset_strict(X,S),subset_strict(X,S)). | 
| 1379 |  | negate_expr_aux(equal(X,S),not_equal(X,S)). | 
| 1380 |  | negate_expr_aux(not_equal(X,S),equal(X,S)). | 
| 1381 |  | negate_expr_aux(less(X,S),greater_equal(X,S)). | 
| 1382 |  | negate_expr_aux(greater_equal(X,S),less(X,S)). | 
| 1383 |  | negate_expr_aux(less_equal(X,S),greater(X,S)). | 
| 1384 |  | negate_expr_aux(greater(X,S),less_equal(X,S)). | 
| 1385 |  | negate_expr_aux(less_equal_real(X,S),less_real(S,X)). | 
| 1386 |  | negate_expr_aux(less_real(X,S),less_equal_real(S,X)). | 
| 1387 |  | % TO DO: negation() | 
| 1388 |  |  | 
| 1389 |  |  | 
| 1390 |  | % a liberal version for finding equalities | 
| 1391 |  | is_equality(TP,TA,TB) :- get_texpr_expr(TP,P), is_equality_aux(P,TA,TB). | 
| 1392 |  |  | 
| 1393 |  | is_equality_aux(Var,TA,TB) :- var(Var),!, add_internal_error('Illegal call: ', is_equality_aux(Var,TA,TB)),fail. | 
| 1394 |  | is_equality_aux(equal(TA,TB),TA,TB). | 
| 1395 |  | is_equality_aux(not_equal(TA,TB),NTA,NTB) :- | 
| 1396 |  | (negate_boolean_value(TB,NTB) -> NTA=TA | 
| 1397 |  | ; NTB=TB, negate_boolean_value(TA,NTA)). % TA /= TRUE  ---> TA = FALSE | 
| 1398 |  | is_equality_aux(partition(TA,[TB]),TA,TB). | 
| 1399 |  | is_equality_aux(member(TA,TSet),TA,TB) :- singleton_set_extension(TSet,TB). % TA:{TB} | 
| 1400 |  | is_equality_aux(negation(TExpr),TA,TB) :- get_negated_operator_expr(TExpr,NT), is_equality_aux(NT,TA,TB). | 
| 1401 |  |  | 
| 1402 |  | negate_boolean_value(b(B,T,I),b(NB,T,I)) :- neg_bool_aux(B,NB). | 
| 1403 |  | neg_bool_aux(boolean_true,boolean_false). | 
| 1404 |  | neg_bool_aux(boolean_false,boolean_true). | 
| 1405 |  | % TODO: should we also detect value(pred_true), .... | 
| 1406 |  |  | 
| 1407 |  | singleton_set_extension(b(SONE,Type,_),El) :- singleton_set_extension_aux(SONE,Type,El). | 
| 1408 |  | singleton_set_extension_aux(set_extension([El]),_,El). | 
| 1409 |  | singleton_set_extension_aux(value(Set),set(Type),b(value(El),Type,[])) :- custom_explicit_sets:singleton_set(Set,El). | 
| 1410 |  | singleton_set_extension_aux(sequence_extension([El]),_,Couple) :- | 
| 1411 |  | ONE = b(integer(1),integer,[]), | 
| 1412 |  | create_couple(ONE,El,Couple). | 
| 1413 |  |  | 
| 1414 |  |  | 
| 1415 |  | % detect various forms of membership: | 
| 1416 |  | is_membership(b(Expr,pred,_),TID,Set) :- is_membership_aux(Expr,TID,Set). | 
| 1417 |  | is_membership_aux(member(TID,Set),TID,Set). | 
| 1418 |  | is_membership_aux(subset(SONE,Set),TID,Set) :- singleton_set_extension(SONE,TID). % {TID} <: Set | 
| 1419 |  |  | 
| 1420 |  | % detect even more forms of membership: | 
| 1421 |  | is_membership_or_equality(b(Expr,pred,_),TID,Set) :- | 
| 1422 |  | (is_membership_aux(Expr,TID,Set) -> true ; is_mem_eq_aux(Expr,TID,Set)). | 
| 1423 |  |  | 
| 1424 |  | is_mem_eq_aux(equal(TID,VAL),TID,Set) :- % x=VAL  <==>  x:{VAL} | 
| 1425 |  | get_texpr_type(VAL,Type), | 
| 1426 |  | safe_create_texpr(set_extension([VAL]),set(Type),Set). | 
| 1427 |  |  | 
| 1428 |  | % extract a lambda equality from a body; we suppose the equality is the last conjunct | 
| 1429 |  | get_lambda_equality(b(equal(TID,ResultExpr),pred,_),ID,[],ResultExpr) :- get_texpr_id(TID,ID). | 
| 1430 |  | get_lambda_equality(b(conjunct(LHS,RHS),pred,_),ID,[LHS|T],ResultExpr) :- | 
| 1431 |  | get_lambda_equality(RHS,ID,T,ResultExpr). | 
| 1432 |  |  | 
| 1433 |  | % --------------------------------- | 
| 1434 |  |  | 
| 1435 |  | is_pow_subset(B,Set) :- | 
| 1436 |  | (   B = b(pow_subset(Set),_,_) | 
| 1437 |  | ;   B = b(fin_subset(Set),_,_), | 
| 1438 |  | finite_wd_set_value(Set) | 
| 1439 |  | ). | 
| 1440 |  | is_pow1_subset(B,Set) :- | 
| 1441 |  | (   B = b(pow1_subset(Set),_,_) | 
| 1442 |  | ;   B = b(fin1_subset(Set),_,_), | 
| 1443 |  | finite_wd_set_value(Set) | 
| 1444 |  | ). | 
| 1445 |  |  | 
| 1446 |  | % --------------------------------- | 
| 1447 |  |  | 
| 1448 |  | get_texpr_couple(b(couple(TA1,TA2),_,_),TA1,TA2). | 
| 1449 |  |  | 
| 1450 |  | % detect TA1|->TA2 = TB1|->TB2  and split into two | 
| 1451 |  | split_equality(b(equal(TA,TB),pred,I),b(equal(TA1,TB1),pred,I),b(equal(TA2,TB2),pred,I)) :- | 
| 1452 |  | get_texpr_couple(TA,TA1,TA2), | 
| 1453 |  | get_texpr_couple(TB,TB1,TB2). | 
| 1454 |  |  | 
| 1455 |  | create_equality(b(_,TA,_),b(_,TB,_),_) :- TA \= TB, \+ unify_types_strict(TA,TB),!, | 
| 1456 |  | add_internal_error('Creating equality with incompatible types:',equal(TA,TB)),fail. | 
| 1457 |  | create_equality(A,B,Equality) :- | 
| 1458 |  | safe_create_texpr(equal(A,B),pred,Equality). | 
| 1459 |  |  | 
| 1460 |  | create_couple(A,B,b(couple(A,B),couple(TA,TB),Infos)) :- | 
| 1461 |  | get_texpr_type(A,TA), get_texpr_type(B,TB), | 
| 1462 |  | extract_info(A,B,Infos). | 
| 1463 |  |  | 
| 1464 |  | % couplise_list for typed expression list | 
| 1465 |  | create_couple([A],Couple) :- !,A=Couple. | 
| 1466 |  | create_couple([A,B|Rest],Couple) :- | 
| 1467 |  | create_couple(A,B,Couple1), | 
| 1468 |  | create_couple([Couple1|Rest],Couple). | 
| 1469 |  |  | 
| 1470 |  | create_cartesian_product(A,B,CartAB) :- | 
| 1471 |  | get_texpr_types([A,B],[STA,STB]), | 
| 1472 |  | is_set_type(STA,TypeA), is_set_type(STB,TypeB), | 
| 1473 |  | safe_create_texpr(cartesian_product(A,B),set(couple(TypeA,TypeB)),CartAB). | 
| 1474 |  |  | 
| 1475 |  | % derive typing from Ids | 
| 1476 |  | create_comprehension_set(Ids,Pred,Info,CompSet) :- | 
| 1477 |  | get_texpr_types(Ids,Types), | 
| 1478 |  | couplise_list(Types,ElementType), | 
| 1479 |  | create_texpr(comprehension_set(Ids,Pred),set(ElementType),Info,CompSet). | 
| 1480 |  |  | 
| 1481 |  |  | 
| 1482 |  | :- assert_must_succeed(bsyntaxtree:nested_couple_to_list(b(couple(b(couple(a,b),x,[]),c),xx,[]),[a,b,c])). | 
| 1483 |  | :- assert_must_succeed(bsyntaxtree:nested_couple_to_list(b(couple(a,c),x,[]),[a,c])). | 
| 1484 |  | :- assert_must_succeed(bsyntaxtree:nested_couple_to_list(b(couple(a,b(couple(b,c),x,[])),xx,[]),[a,b(couple(b,c),x,[])])). | 
| 1485 |  | nested_couple_to_list(NC,L) :- nested_couple_to_list_dcg(NC,L,[]). | 
| 1486 |  | nested_couple_to_list_dcg(b(couple(A,B),_,_)) --> !, | 
| 1487 |  | nested_couple_to_list_dcg(A), [B]. | 
| 1488 |  | nested_couple_to_list_dcg(E) --> [E]. | 
| 1489 |  |  | 
| 1490 |  | % -------------------------------------- | 
| 1491 |  |  | 
| 1492 |  |  | 
| 1493 |  | % check if identifier(s) occur in typed expressions | 
| 1494 |  |  | 
| 1495 |  | occurs_in_expr(ID,TExpr) :- var(ID),!, | 
| 1496 |  | add_internal_error('Variable id: ',occurs_in_expr(ID,TExpr)),fail. | 
| 1497 |  | occurs_in_expr(ID,TExpr) :- ID=b(_,_,_),!, add_internal_error('Non-atomic identifier: ',occurs_in_expr(ID,TExpr)),fail. | 
| 1498 |  | occurs_in_expr(ID,TExpr) :- ID=[_|_],!, | 
| 1499 |  | add_internal_error('List instead of identifier: ',occurs_in_expr(ID,TExpr)),fail. | 
| 1500 |  | occurs_in_expr(ID,TExpr) :- occurs_in_expr1(TExpr,ID). | 
| 1501 |  |  | 
| 1502 |  | % treat a few common operators here; possibly avoid traversing whole term if we find ID in a sub-tree | 
| 1503 |  | occurs_in_expr1(TExpr,ID) :- TExpr = b(Expr,_,_),!, | 
| 1504 |  | occurs_in_expr2(Expr,TExpr,ID). | 
| 1505 |  | occurs_in_expr1(TExpr,ID) :- add_internal_error('Illegal typed expression:',occurs_in_expr1(TExpr,ID)). | 
| 1506 |  |  | 
| 1507 |  | occurs_in_expr2(add(A,B),_,ID) :- !, | 
| 1508 |  | (occurs_in_expr1(A,ID) -> true ; occurs_in_expr1(B,ID)). | 
| 1509 |  | occurs_in_expr2(conjunct(A,B),_,ID) :- !, | 
| 1510 |  | (occurs_in_expr1(A,ID) -> true ; occurs_in_expr1(B,ID)). | 
| 1511 |  | occurs_in_expr2(couple(A,B),_,ID) :- !, | 
| 1512 |  | (occurs_in_expr1(A,ID) -> true ; occurs_in_expr1(B,ID)). | 
| 1513 |  | occurs_in_expr2(member(A,B),_,ID) :- !, | 
| 1514 |  | (occurs_in_expr1(A,ID) -> true ; occurs_in_expr1(B,ID)). | 
| 1515 |  | occurs_in_expr2(equal(A,B),_,ID) :- !, | 
| 1516 |  | (occurs_in_expr1(A,ID) -> true ; occurs_in_expr1(B,ID)). | 
| 1517 |  | occurs_in_expr2(function(A,B),_,ID) :- !, | 
| 1518 |  | (occurs_in_expr1(A,ID) -> true ; occurs_in_expr1(B,ID)). | 
| 1519 |  | occurs_in_expr2(image(A,B),_,ID) :- !, | 
| 1520 |  | (occurs_in_expr1(A,ID) -> true ; occurs_in_expr1(B,ID)). | 
| 1521 |  | occurs_in_expr2(intersection(A,B),_,ID) :- !, | 
| 1522 |  | (occurs_in_expr1(A,ID) -> true ; occurs_in_expr1(B,ID)). | 
| 1523 |  | occurs_in_expr2(interval(A,B),_,ID) :- !, | 
| 1524 |  | (occurs_in_expr1(A,ID) -> true ; occurs_in_expr1(B,ID)). | 
| 1525 |  | occurs_in_expr2(not_equal(A,B),_,ID) :- !, | 
| 1526 |  | (occurs_in_expr1(A,ID) -> true ; occurs_in_expr1(B,ID)). | 
| 1527 |  | occurs_in_expr2(assertion_expression(A,_Msg,B),_,ID) :- !, | 
| 1528 |  | (occurs_in_expr1(A,ID) -> true ; occurs_in_expr1(B,ID)). | 
| 1529 |  | occurs_in_expr2(domain(A),_,ID) :- !, occurs_in_expr1(A,ID). | 
| 1530 |  | occurs_in_expr2(range(A),_,ID) :- !, occurs_in_expr1(A,ID). | 
| 1531 |  | occurs_in_expr2(record_field(A,_FieldName),_,ID) :- !, occurs_in_expr1(A,ID). | 
| 1532 |  | occurs_in_expr2(identifier(ID1),_,ID) :- !, | 
| 1533 |  | ID1 = ID. | 
| 1534 |  | occurs_in_expr2(integer(_),_,_ID) :- !,fail. | 
| 1535 |  | occurs_in_expr2(string(_),_,_ID) :- !,fail. | 
| 1536 |  | occurs_in_expr2(value(_),_,_ID) :- !,fail. | 
| 1537 |  | occurs_in_expr2(truth,_,_ID) :- !,fail. | 
| 1538 |  | occurs_in_expr2(if_then_else(A,B,C),_,ID) :- !, | 
| 1539 |  | (occurs_in_expr1(A,ID) -> true ; occurs_in_expr1(B,ID) -> true ; occurs_in_expr1(C,ID)). | 
| 1540 |  | occurs_in_expr2(rec(Fields),_,ID) :- !, | 
| 1541 |  | l_field_occurs_in_expr1(Fields,ID). | 
| 1542 |  | occurs_in_expr2(set_extension(Elements),_,ID) :- !, | 
| 1543 |  | l_occurs_in_expr1(Elements,ID). | 
| 1544 |  | occurs_in_expr2(sequence_extension(Elements),_,ID) :- !, | 
| 1545 |  | l_occurs_in_expr1(Elements,ID). | 
| 1546 |  | occurs_in_expr2(Expr,_,ID) :- | 
| 1547 |  | syntaxelement(Expr,List,[], [], [], _), % no bound quantifiers; TO DO: treat bound quantifiers | 
| 1548 |  | !, | 
| 1549 |  | l_occurs_in_expr1(List,ID). | 
| 1550 |  | occurs_in_expr2(_E,TExpr,ID) :- | 
| 1551 |  | %functor(_E,F,N), print(occurs_in_expr2(F,N,ID)),nl, | 
| 1552 |  | (find_identifier_uses_if_necessary(TExpr,[],Used) | 
| 1553 |  | -> %check_sorted(Used), | 
| 1554 |  | %add_message(bsyntaxtree,'Occurs check: ',ID:Used,TExpr), translate:nested_print_bexpr(TExpr),nl, | 
| 1555 |  | ord_member(ID,Used) | 
| 1556 |  | ; add_failed_call_error(find_identifier_uses(TExpr,[],_)),fail). | 
| 1557 |  | % TO DO: optimize so that we only look for ID; we don't have to keep track of other IDs | 
| 1558 |  |  | 
| 1559 |  | l_occurs_in_expr1([H|T],ID) :- !, | 
| 1560 |  | (occurs_in_expr1(H,ID) -> true ; l_occurs_in_expr1(T,ID)). | 
| 1561 |  | l_occurs_in_expr1(L,ID) :- L \= [], | 
| 1562 |  | add_internal_error('Illegal typed expression list:',l_occurs_in_expr1(L,ID)). | 
| 1563 |  | l_field_occurs_in_expr1([field(_,H)|T],ID) :- !, | 
| 1564 |  | (occurs_in_expr1(H,ID) -> true ; l_field_occurs_in_expr1(T,ID)). | 
| 1565 |  | l_field_occurs_in_expr1(L,ID) :- L \= [], | 
| 1566 |  | add_internal_error('Illegal record field list:',l_field_occurs_in_expr1(L,ID)). | 
| 1567 |  |  | 
| 1568 |  | %check_sorted(List) :- sort(List,SL), (SL \= List -> add_internal_error('Not sorted:',List) ; true). | 
| 1569 |  |  | 
| 1570 |  | some_id_occurs_in_expr([H|T],TExpr) :- (var(H) ; \+ atomic(H) ; var(T) ; T=[H2|_], H2 @< H), | 
| 1571 |  | add_internal_error('Must be (sorted) atomic identifiers: ',some_id_occurs_in_expr([H|T],TExpr)), | 
| 1572 |  | fail. | 
| 1573 |  | some_id_occurs_in_expr([Id],TExpr) :- !, % use version without complete find_identifier_uses | 
| 1574 |  | occurs_in_expr(Id,TExpr). | 
| 1575 |  | some_id_occurs_in_expr(SortedIDs,TExpr) :- | 
| 1576 |  | find_identifier_uses_if_necessary(TExpr,[],Used), | 
| 1577 |  | list_to_ord_set(Used,UsedSorted), | 
| 1578 |  | ord_intersect(UsedSorted,SortedIDs). | 
| 1579 |  |  | 
| 1580 |  | % ----------------------------- | 
| 1581 |  |  | 
| 1582 |  | % find used identifiers in typed expressions | 
| 1583 |  |  | 
| 1584 |  | % a special version for quantifier bodies, attempting to reuse used_ids info | 
| 1585 |  | find_identifier_uses_for_quantifier_body(TIds,Body,Res) :- | 
| 1586 |  | get_texpr_ids(TIds,Ids), | 
| 1587 |  | list_to_ord_set(Ids,Ignore), | 
| 1588 |  | find_identifier_uses_if_necessary(Body,Ignore,Res). | 
| 1589 |  |  | 
| 1590 |  | % only run find_identifier_uses if necessary because no used_ids Info field present | 
| 1591 |  | % TO DO: we could consider using used_ids within find_typed_identifier_uses: drawback: we would need to store types | 
| 1592 |  | find_identifier_uses_if_necessary(Expr,Ignore,Res) :- | 
| 1593 |  | get_texpr_info(Expr,I), | 
| 1594 | ? | member(used_ids(UIds),I),!, %print('+'),nl, | 
| 1595 |  | find_with_reuse(Expr,UIds,Ignore,Res). | 
| 1596 |  | find_identifier_uses_if_necessary(Expr,Ignore,Res) :- find_identifier_uses(Expr,Ignore,Res). | 
| 1597 |  |  | 
| 1598 |  | find_with_reuse(Expr,UIds,Ignore,Res) :- preference(prob_safe_mode,true), | 
| 1599 |  | !, | 
| 1600 |  | (is_ordset(Ignore) -> true ; add_internal_error('Not ordset: ',Ignore)), | 
| 1601 |  | (is_ordset(UIds) -> true ; add_internal_error('Not ordset: ',UIds)), | 
| 1602 |  | ord_subtract(UIds,Ignore,Res0), | 
| 1603 |  | find_identifier_uses(Expr,Ignore,Res1), | 
| 1604 |  | (Res1=Res0 -> true | 
| 1605 |  | ; ord_subtract(Res1,Res0,Miss), % missing | 
| 1606 |  | ord_subtract(Res0,Res1,Res01), % too much | 
| 1607 |  | (Miss=[] -> add_message(find_identifier_uses_if_necessary,'Suboptimal used_ids: ',Res01,Expr) | 
| 1608 |  | ; add_internal_error('Incorrect used_ids:',used_ids(missing(Miss),toomuch(Res01),usedids(UIds), | 
| 1609 |  | ignore(Ignore),real(Res1))), | 
| 1610 |  | translate:print_bexpr(Expr),nl | 
| 1611 |  | ) | 
| 1612 |  | ), | 
| 1613 |  | Res=Res1. | 
| 1614 |  | find_with_reuse(_,UIds,Ignore,Res) :- | 
| 1615 |  | %(is_ordset(Ignore) -> true ; add_internal_error('Not ordset: ',Ignore)), | 
| 1616 |  | ord_subtract(UIds,Ignore,Res). | 
| 1617 |  |  | 
| 1618 |  |  | 
| 1619 |  | find_identifier_uses_top_level(TExpr,Ids) :- | 
| 1620 |  | % get_global_identifiers(Ignored), % ignore all global sets and global constants; | 
| 1621 |  | % hence find_identifier_uses_top_level/2 usually should only be called for top level expressions | 
| 1622 |  | Ignored = [], % much  more efficient to exclude afterwards for long lists of Ignored ids | 
| 1623 |  | find_identifier_uses(TExpr,Ignored,Ids0), | 
| 1624 |  | exclude_global_identifiers(Ids0,Ids). | 
| 1625 |  |  | 
| 1626 |  | :- use_module(tools,[safe_sort/3]). | 
| 1627 |  | find_identifier_uses(TExpr,Ignored,Ids) :- | 
| 1628 |  | %tools_printing:print_term_summary(find_identifier_uses(TExpr,Ignored,Ids)),nl, | 
| 1629 |  | check_is_texpr(TExpr,find_identifier_uses), | 
| 1630 |  | (find_typed_identifier_uses(TExpr,Ignored,TIds) | 
| 1631 |  | -> get_texpr_ids(TIds,RIds), | 
| 1632 |  | % in case of type errors, or when type checking is not yet complete, we can have multiple entries of the same identifier with different types ! | 
| 1633 |  | sort(RIds,Ids) % was remove_dups, but remove_dups just calls sort; TODO: implement get_sorted_texpr_ids | 
| 1634 |  | ;  add_internal_error('Call failed:',find_typed_identifier_uses(TExpr,Ignored,_)), | 
| 1635 |  | Ids=[] | 
| 1636 |  | ). | 
| 1637 |  | find_identifier_uses_l(TExprs,Ignored,Ids) :- | 
| 1638 |  | find_typed_identifier_uses_l(TExprs,Ignored,TIds), | 
| 1639 |  | get_texpr_ids(TIds,RIds), | 
| 1640 |  | sort(RIds,Ids).  % see above | 
| 1641 |  |  | 
| 1642 |  | check_is_texpr(X,Context) :- | 
| 1643 |  | (get_texpr_expr(X,_) -> true ; add_internal_error('Expected TExpr: ', check_is_texpr(X,Context))). | 
| 1644 |  |  | 
| 1645 |  | find_typed_identifier_uses(TExpr,Ids) :- | 
| 1646 |  | % get_global_identifiers(Ignored), % ignore all global sets and global constants; hence find_typed_identifier_uses/2 usually should only be called for top level expressions | 
| 1647 |  | Ignored = [], | 
| 1648 |  | find_typed_identifier_uses(TExpr,Ignored,Ids0), | 
| 1649 |  | exclude_global_identifiers(Ids0,Ids). | 
| 1650 |  |  | 
| 1651 |  | find_typed_identifier_uses(TExpr,Ignored,Ids) :- var(TExpr),!, | 
| 1652 |  | add_internal_error('Variable typed expression: ', find_typed_identifier_uses(TExpr,Ignored,Ids)), | 
| 1653 |  | Ids = []. | 
| 1654 |  | find_typed_identifier_uses(TExpr,Ignored,Ids) :- | 
| 1655 |  | find_typed_identifier_uses_l([TExpr],Ignored,Ids). | 
| 1656 |  |  | 
| 1657 |  | find_typed_identifier_uses2(TExpr,Ignored,Ids,Rest) :- | 
| 1658 |  | get_texpr_expr(TExpr,Expr), | 
| 1659 |  | safe_syntaxelement_det(Expr,Subs,TNames,_,_), % QSubs=[], | 
| 1660 |  | ( uses_an_identifier(Expr,Id,TExpr,Ignored) -> | 
| 1661 |  | ( ord_member(Id,Ignored) -> Ids=Rest | 
| 1662 |  | ; | 
| 1663 |  | get_texpr_type(TExpr,Type), | 
| 1664 |  | normalize_type(Type,NType), % replace seq by set; | 
| 1665 |  | % warning: when type-check not yet complete we have variables here | 
| 1666 |  | create_texpr(identifier(Id),NType,[],TId), | 
| 1667 |  | %print(adding(Id,NType,Ignored)),nl, | 
| 1668 |  | Ids = [TId|Rest] | 
| 1669 |  | ) | 
| 1670 |  | % ; (Expr = becomes_such(TIds,_)), nl,print(uses_primes(Expr)),nl,fail | 
| 1671 |  | ; indirectly_uses_identifiers(Expr,Ignored,IndirectIds) -> | 
| 1672 |  | add_typed_ids(IndirectIds,Ids,Rest2), | 
| 1673 |  | find_typed_identifier_uses2_l(Subs,Ignored,Rest2,Rest) | 
| 1674 |  | ; TNames = [] -> find_typed_identifier_uses2_l(Subs,Ignored,Ids,Rest) | 
| 1675 |  | ; | 
| 1676 |  | %find_typed_identifier_uses2_l(QSubs,Ignored,Ids,Ids2), % useless here as QSubs=[] | 
| 1677 |  | get_texpr_ids(TNames,Names), | 
| 1678 |  | list_to_ord_set(Names,SNames), ord_union(SNames,Ignored,Ignored2), | 
| 1679 |  | find_typed_identifier_uses2_l(Subs,Ignored2,Ids,Rest)). | 
| 1680 |  | find_typed_identifier_uses2_l([],_) --> !, []. | 
| 1681 |  | find_typed_identifier_uses2_l([Expr|Rest],Ignored) --> !, | 
| 1682 |  | find_typed_identifier_uses2(Expr,Ignored), | 
| 1683 |  | find_typed_identifier_uses2_l(Rest,Ignored). | 
| 1684 |  | find_typed_identifier_uses2_l(E,Ignored) --> | 
| 1685 |  | {add_internal_error('Illegal arguments (not a list):',find_typed_identifier_uses2_l(E,Ignored)),fail}. | 
| 1686 |  |  | 
| 1687 |  | %Note: above we do not remap uses of Id$0 to Id in becomes_such; | 
| 1688 |  | %      this is done in find_read_vars_for_becomes_such in b_read_write_info | 
| 1689 |  |  | 
| 1690 |  |  | 
| 1691 |  | uses_an_identifier(Expr,Id) :- uses_an_identifier(Expr,Id,none,[]). | 
| 1692 |  |  | 
| 1693 |  | uses_an_identifier(identifier(Id),Id,_,_). | 
| 1694 |  | uses_an_identifier(lazy_lookup_pred(Id),Id,_,_). | 
| 1695 |  | uses_an_identifier(lazy_lookup_expr(Id),Id,_,_). | 
| 1696 |  | uses_an_identifier(value(_),Id,b(_,_,Info),Ignored) :- Ignored \= [], | 
| 1697 |  | member(was_identifier(Id),Info), | 
| 1698 |  | member('$examine_value_was_identifier_info',Ignored),!. | 
| 1699 |  |  | 
| 1700 |  | % uses multiple ids and we also need to inspect subs (operation call arguments) | 
| 1701 |  | indirectly_uses_identifiers(operation_call_in_expr(Operation,_),Ignored,IndirectIds) :- | 
| 1702 |  | get_texpr_info(Operation,Info), | 
| 1703 |  | (memberchk(reads(Vars),Info) | 
| 1704 |  | -> (var(Vars)  % can happen during initial computation of read_write info for recursive operation calls in expr | 
| 1705 |  | -> add_message(bsyntaxtree,'Operation reads info not yet computed (probably recursive call): ',Operation,Info), | 
| 1706 |  | fail % Assume this is a direct recursive call which adds no used ids, | 
| 1707 |  | % case happens in test 1960 for recursive call to Fact; TODO: more robust solution or disallow recursion | 
| 1708 |  | ; true) | 
| 1709 |  | ; add_warning(bsyntaxtree,'Operation call contains no read infos:',Operation,Info),fail), | 
| 1710 |  | ord_subtract(Vars,Ignored,IndirectIds), | 
| 1711 |  | IndirectIds \= []. | 
| 1712 |  | %indirectly_uses_identifiers(external_pred_call(FunName,_),Ignored,IndirectIds) :- | 
| 1713 |  | %   expects_state(FunName), TODO: check for which external functions/predicates we need to add ids | 
| 1714 |  |  | 
| 1715 |  |  | 
| 1716 |  | % this is to convert untyped ids in operation call reads infos to typed ids | 
| 1717 |  | add_typed_ids([]) --> []. | 
| 1718 |  | add_typed_ids([Id|T]) --> {var_cst_type(Id,Type)},!, | 
| 1719 |  | {create_texpr(identifier(Id),Type,[],TId)}, [TId], add_typed_ids(T). | 
| 1720 |  | add_typed_ids([Id|T]) --> {debug_println(19,ignoring_used_id(Id))}, add_typed_ids(T). | 
| 1721 |  |  | 
| 1722 |  | :- use_module(bmachine,[bmachine_is_precompiled/0, b_is_variable/2,b_is_constant/2]). | 
| 1723 |  | var_cst_type(Name,Type) :- bmachine_is_precompiled,!, | 
| 1724 |  | (b_is_variable(Name,Type) ; b_is_constant(Name,Type)),!. | 
| 1725 |  | var_cst_type(_,any). % TODO: provide a better solution; maybe only allow untyped find_identifier_uses ?? | 
| 1726 |  |  | 
| 1727 |  | % ------------- | 
| 1728 |  |  | 
| 1729 |  | find_typed_identifier_uses_l(TExprs,Ignored,Ids) :- | 
| 1730 |  | check_atomic_ids(Ignored), | 
| 1731 |  | list_to_ord_set(Ignored,SIgnored), | 
| 1732 |  | find_typed_identifier_uses2_l(TExprs,SIgnored,Unsorted,[]),!, | 
| 1733 |  | safe_sort(find_typed_identifier_uses,Unsorted,Ids), | 
| 1734 |  | (preference(prob_safe_mode,true) -> check_typed_ids(Ids) ; true). | 
| 1735 |  | find_typed_identifier_uses_l(TExprs,Ignored,Ids) :- | 
| 1736 |  | add_internal_error('Call failed:',find_typed_identifier_uses_l(TExprs,Ignored,Ids)), | 
| 1737 |  | fail. | 
| 1738 |  |  | 
| 1739 |  | check_typed_ids([]) :- !. | 
| 1740 |  | check_typed_ids([b(identifier(ID),T,_)|Tail]) :- !, check_ids3(Tail,ID,T). | 
| 1741 |  | check_typed_ids(Other) :- add_internal_error('Unexpected typed id list:',check_typed_ids(Other)). | 
| 1742 |  |  | 
| 1743 |  |  | 
| 1744 |  | check_atomic_ids([]) :- !. | 
| 1745 |  | check_atomic_ids([Id|_]) :- atomic(Id),!. | 
| 1746 |  | check_atomic_ids(Other) :- add_internal_error('Expected atomic id list:',check_atomic_ids(Other)). | 
| 1747 |  |  | 
| 1748 |  |  | 
| 1749 |  | check_ids3([],_,_) :- !. | 
| 1750 |  | check_ids3([b(identifier(ID),T,_)|Tail],ID1,T1) :- !, | 
| 1751 |  | (ID=ID1 -> add_internal_error('Identifier appears multiple times with types:',id(ID,T1,T)) ; true), | 
| 1752 |  | check_ids3(Tail,ID,T). | 
| 1753 |  | check_ids3(Other,ID1,T1) :- add_internal_error('Unexpected typed id list:',check_ids3(Other,ID1,T1)). | 
| 1754 |  |  | 
| 1755 |  |  | 
| 1756 |  | update_used_ids(b(Pred,T,OInfo),UsedIds,b(Pred,T,[used_ids(UsedIds)|NInfo])) :- | 
| 1757 |  | delete(OInfo,used_ids(_),NInfo). | 
| 1758 |  |  | 
| 1759 |  | % check if some pre-computed used ids are valid wrt find_typed_identifier_uses | 
| 1760 |  | check_computed_used_ids(TExpr,CompUsedIds) :- | 
| 1761 |  | find_identifier_uses(TExpr,[],RealUsedIds), | 
| 1762 |  | (RealUsedIds=CompUsedIds -> print(ok(CompUsedIds)),nl | 
| 1763 |  | ; add_error(range,'Unexpected used ids:',CompUsedIds,TExpr), | 
| 1764 |  | format('Real: ~w~nComp: ~w~n',[RealUsedIds,CompUsedIds]),trace | 
| 1765 |  | ). | 
| 1766 |  |  | 
| 1767 |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
| 1768 |  | % break predicate into components with disjunct identifiers | 
| 1769 |  | %  Pred: a predicate | 
| 1770 |  | %  Components: a list of terms component/2 where the first argument | 
| 1771 |  | %    is a predicate, the second is the set of used identifiers | 
| 1772 |  | predicate_components(Pred,Res) :- predicate_components_in_scope(Pred,[],Res). | 
| 1773 |  | predicate_components_in_scope(Pred,LocalVars,Res) :- | 
| 1774 |  | predicate_components_with_restriction(Pred,LocalVars,all,Res). | 
| 1775 |  |  | 
| 1776 |  | predicate_components_with_restriction(Pred,LocalVars,RestrictionList,Res) :- | 
| 1777 |  | conjunction_to_list(Pred,Preds), | 
| 1778 |  | l_predicate_identifiers(Preds,LocalVars,PredIds), | 
| 1779 |  | (RestrictionList=all -> R=all ; list_to_ord_set(RestrictionList,R)), | 
| 1780 |  | try_find_and_remove_equalities(PredIds,PredIds2), | 
| 1781 |  | % print(find_components(R)),nl,nl, | 
| 1782 |  | %%(member(pred(P,Ids,X),PredIds2), nl,print(pred(Ids,X)),nl,translate:print_bexpr(P),nl,fail ; true), | 
| 1783 |  | find_components(PredIds2,R,Components), | 
| 1784 |  | !, | 
| 1785 |  | %maplist(print_component,Components), | 
| 1786 |  | Components=Res. | 
| 1787 |  | predicate_components_with_restriction(Pred,_,_,[component(Pred,[])]) :- | 
| 1788 |  | add_internal_error('predicate_components failed: ',predicate_components_with_restriction(Pred,_,_,_)). | 
| 1789 |  |  | 
| 1790 |  | % print_component(component(Pred,Ids)) :- format('Component over ~w :~n',[Ids]), translate:print_bexpr(Pred),nl. | 
| 1791 |  |  | 
| 1792 |  | % get the list of used identifiers for each predicate | 
| 1793 |  | l_predicate_identifiers([],_LocalVars,[]). | 
| 1794 |  | l_predicate_identifiers([Pred|PRest],LocalVars,[pred(Pred,Ids,_Selected)|IRest]) :- | 
| 1795 |  | predicate_identifiers_in_scope(Pred,LocalVars,Ids),  % Do not ignore local variables; used instead of enumerate set elements | 
| 1796 |  | l_predicate_identifiers(PRest,LocalVars,IRest). | 
| 1797 |  |  | 
| 1798 |  |  | 
| 1799 |  | try_find_and_remove_equalities(PredAndIds,PredAndIds2) :- | 
| 1800 |  | preferences:get_preference(partition_predicates_inline_equalities,true), | 
| 1801 |  | \+ preferences:get_preference(use_solver_on_load,kodkod), | 
| 1802 | ? | find_and_remove_equalities(PredAndIds,RR), | 
| 1803 |  | !, PredAndIds2=RR. | 
| 1804 |  | try_find_and_remove_equalities(Ps,Ps). | 
| 1805 |  |  | 
| 1806 |  | :- use_module(debug,[debug_println/2]). | 
| 1807 |  | % find and apply obvious equalities so that they do not interfere with partitioning into components | 
| 1808 |  | % example:  c = 1 &  f: 1..c --> A  &  g: 1..c --> B | 
| 1809 |  | % TO DO: preprocess and do one pass to detect potential equalities | 
| 1810 |  | find_and_remove_equalities([],[]). | 
| 1811 |  | find_and_remove_equalities(List,[pred(P,PIds,Sel)|FT]) :- | 
| 1812 | ? | select(pred(P,PIds,Sel),List,Rest), | 
| 1813 |  | %PIds = [Id], | 
| 1814 |  | identifier_equality(P,Id,Value), | 
| 1815 |  | %(value_which_can_be_replaced(Value) -> true ; nl,print('Not replaced: '),translate:print_bexpr(Value),nl,fail), | 
| 1816 |  | (get_texpr_id(Value,Id2) | 
| 1817 |  | -> Id2 \= Id %,print(inline_id(Id,Id2)),nl | 
| 1818 |  | % Note: this inlining does *not* help with partitioning; but does help ProB detect common predicates/expressions | 
| 1819 |  | ; PIds=[Id],value_which_can_be_replaced(Value)), | 
| 1820 |  | debug_println(9,replace_simple_equality(Id,PIds)), | 
| 1821 |  | maplist(apply_to_pred(Id,Value),Rest,RT), | 
| 1822 |  | !, | 
| 1823 | ? | find_and_remove_equalities(RT,FT). | 
| 1824 |  | % TO DO: detect equalityes x = EXPR, where EXPR does not contain x and where x occurs in no other predicate | 
| 1825 |  | % we can then annotate x as not to enumerate | 
| 1826 |  | find_and_remove_equalities(R,R). | 
| 1827 |  |  | 
| 1828 |  | identifier_equality(b(equal(LHS,RHS),_,_),Id,EqTerm) :- | 
| 1829 |  | (get_texpr_id(LHS,Id) -> EqTerm = RHS | 
| 1830 |  | ; get_texpr_id(RHS,Id) -> EqTerm = LHS). | 
| 1831 |  | % TO DO: should we detect other equalities? | 
| 1832 |  |  | 
| 1833 |  | value_which_can_be_replaced(b(E,T,_)) :- value_which_can_be_replaced2(E,T). | 
| 1834 |  | %(value_which_can_be_replaced2(E,T) -> true ; print(not_val(E)),nl,fail). | 
| 1835 |  | value_which_can_be_replaced2(value(_),_). | 
| 1836 |  | value_which_can_be_replaced2(integer(_),_). | 
| 1837 |  | %value_which_can_be_replaced2(identifier(I),global(G)) :- b_global_constant(G), id_not_used_anywhere(I). | 
| 1838 |  | value_which_can_be_replaced2(integer_set(_),_). | 
| 1839 |  | value_which_can_be_replaced2(unary_minus(A),_) :- value_which_can_be_replaced(A). | 
| 1840 |  | value_which_can_be_replaced2(add(A,B),_) :- value_which_can_be_replaced(A), value_which_can_be_replaced(B). | 
| 1841 |  | % we could compute the value | 
| 1842 |  | value_which_can_be_replaced2(minus(A,B),_) :- value_which_can_be_replaced(A), value_which_can_be_replaced(B). | 
| 1843 |  | value_which_can_be_replaced2(multiplication(A,B),_) :- value_which_can_be_replaced(A), value_which_can_be_replaced(B). | 
| 1844 |  | value_which_can_be_replaced2(div(A,B),_) :- | 
| 1845 |  | get_integer(B,IB), IB \= 0, | 
| 1846 |  | value_which_can_be_replaced(A). | 
| 1847 |  | value_which_can_be_replaced2(floored_div(A,B),T) :- value_which_can_be_replaced2(div(A,B),T). | 
| 1848 |  | % should we add:  with WD check: division, modulo, .... ? see also simple2 in b_ast_cleanup | 
| 1849 |  | value_which_can_be_replaced2(max_int,_). | 
| 1850 |  | value_which_can_be_replaced2(min_int,_). | 
| 1851 |  | value_which_can_be_replaced2(float_set,_). | 
| 1852 |  | value_which_can_be_replaced2(real(_),_). | 
| 1853 |  | value_which_can_be_replaced2(real_set,_). | 
| 1854 |  | value_which_can_be_replaced2(string(_),_). | 
| 1855 |  | value_which_can_be_replaced2(string_set,_). | 
| 1856 |  | value_which_can_be_replaced2(boolean_true,_). | 
| 1857 |  | value_which_can_be_replaced2(boolean_false,_). | 
| 1858 |  | value_which_can_be_replaced2(bool_set,_). | 
| 1859 |  | value_which_can_be_replaced2(empty_set,_). | 
| 1860 |  | value_which_can_be_replaced2(empty_sequence,_). | 
| 1861 |  | value_which_can_be_replaced2(couple(A,B),_) :- value_which_can_be_replaced(A), value_which_can_be_replaced(B). | 
| 1862 |  | value_which_can_be_replaced2(interval(A,B),_) :- value_which_can_be_replaced(A), value_which_can_be_replaced(B). | 
| 1863 |  | value_which_can_be_replaced2(set_extension(L),_) :- maplist(value_which_can_be_replaced,L). | 
| 1864 |  | value_which_can_be_replaced2(sequence_extension(L),_) :- maplist(value_which_can_be_replaced,L). | 
| 1865 |  | value_which_can_be_replaced2(cartesian_product(A,B),_) :- % typing equations, like t_float = INTEGER*NATURAL1 | 
| 1866 |  | simple_value_set(A), simple_value_set(B). | 
| 1867 |  | value_which_can_be_replaced2(pow_subset(A),_) :- simple_value_set(A). | 
| 1868 |  | %value_which_can_be_replaced2(identifier(_),_). % TO DO: check that this is not the LHS identifier which we replace !! | 
| 1869 |  | % identifiers can also be replaced: we check above that the only identifier in the predicate is the equality identifier | 
| 1870 |  | % TO DO: enable this but then we need to fix replace_id_by_expr2 to updated the used_ids info ! + we can have scoping issues !?; see test 1358 | 
| 1871 |  |  | 
| 1872 |  | % TO DO: also allow inlining of prj1/prj2 of simple_value_set: | 
| 1873 |  | % not_val(comprehension_set([b(identifier(_zzzz_unary),integer,[generated(first)]),b(identifier(_zzzz_binary),integer,[generated(first)]),b(identifier(_lambda_result_),integer,[lambda_result])],b(equal(b(identifier(_lambda_result_),integer,[lambda_result]),b(identifier(_zzzz_unary),integer,[generated(first)])),pred,[prob_annotation(LAMBDA),lambda_result]))) | 
| 1874 |  | % not_val(comprehension_set([b(identifier(_zzzz_unary),integer,[generated(second)]),b(identifier(_zzzz_binary),integer,[generated(second)]),b(identifier(_lambda_result_),integer,[lambda_result])],b(equal(b(identifier(_lambda_result_),integer,[lambda_result]),b(identifier(_zzzz_binary),integer,[generated(second)])),pred,[prob_annotation(LAMBDA),lambda_result]))) | 
| 1875 |  |  | 
| 1876 |  | % TO DO: maybe check if it is an infinite type which cannot be evaluated anyway | 
| 1877 |  | simple_value_set(b(E,_,_)) :- simple_value_set2(E). | 
| 1878 |  | %simple_value_set2(bool_set). % Warning: we could have a finite construct which gets evaluated multiple times | 
| 1879 |  | simple_value_set2(string_set). | 
| 1880 |  | simple_value_set2(integer_set(_)). | 
| 1881 |  | simple_value_set2(float_set). | 
| 1882 |  | simple_value_set2(real_set). | 
| 1883 |  | simple_value_set2(cartesian_product(A,B)) :- simple_value_set(A), simple_value_set(B). | 
| 1884 |  | simple_value_set2(pow_subset(A)) :- simple_value_set(A). | 
| 1885 |  | % POW, records struct(_) set ? | 
| 1886 |  |  | 
| 1887 |  | % apply a substiution of ID/Expr on a pred(EXPR,VarList,X) term | 
| 1888 |  | % Expr must either be a variable or contain no variables at all | 
| 1889 |  | apply_to_pred(ID,Expr,pred(E1,PIds1,X),pred(E2,PIds3,X)) :- | 
| 1890 | ? | (select(ID,PIds1,PIds2) | 
| 1891 |  | -> replace_id_by_expr(E1,ID,Expr,E2),  %,print(applied(ID)),nl,translate:print_bexpr(E2),nl | 
| 1892 |  | % TO DO: replace_id_by_expr does not seem to update used_ids info !! check_used_ids_info fails for test 1358 if we allow identifiers inside Expr | 
| 1893 |  | (get_texpr_id(Expr,NewID) | 
| 1894 |  | -> ord_add_element(PIds2,NewID,PIds3) | 
| 1895 |  | ; PIds3 = PIds2) | 
| 1896 |  | %, format('Apply ~w -> ~w : ',[ID,NewID]),translate:print_bexpr(E2),nl | 
| 1897 |  | ; E1=E2,PIds1=PIds3). | 
| 1898 |  |  | 
| 1899 |  |  | 
| 1900 |  | % project a predicate : keep only those Predicates that are directly or | 
| 1901 |  | %  indirectly relevant for Ids; FullIds are all identifiers used by ProjectedPredicate | 
| 1902 |  | project_predicate_on_identifiers(Pred,Ids,ProjectedPredicate,FullIds, RestList) :- | 
| 1903 |  | (debug_mode(on) | 
| 1904 |  | -> print('project: '),print_bexpr(Pred),nl, print('  on : '), print(Ids),nl | 
| 1905 |  | ;  true), | 
| 1906 |  | conjunction_to_list(Pred,Preds), | 
| 1907 |  | l_predicate_identifiers(Preds,[],PredIds), % TO DO: allow LocalVariables to be passed | 
| 1908 |  | % print(predids(PredIds)),nl, | 
| 1909 |  | try_find_and_remove_equalities(PredIds,PredIds2), | 
| 1910 |  | extract_all_predicates(Ids,all,Ids,PredIds2,ProjectedPredicates, RestList,FullIds), | 
| 1911 |  | conjunct_predicates(ProjectedPredicates,ProjectedPredicate), | 
| 1912 |  | (debug_mode(on) | 
| 1913 |  | -> print('*result: '),print_bexpr(ProjectedPredicate),nl, | 
| 1914 |  | print('  on : '),    print(FullIds),nl | 
| 1915 |  | ; true). | 
| 1916 |  |  | 
| 1917 |  | %print_preds([]). | 
| 1918 |  | %print_preds([pred(P,_IDs,_)|T]) :- translate:print_bexpr(P), nl, print('   '), print_preds(T). | 
| 1919 |  |  | 
| 1920 |  | :- use_module(b_global_sets,[b_get_global_constants/1, b_get_enumerated_set_constants/1, | 
| 1921 |  | b_get_global_sets/1, exclude_global_identifiers/2, exclude_global_identifiers/3]). | 
| 1922 |  | predicate_identifiers(Pred,Ids) :- predicate_identifiers_in_scope(Pred,[],Ids). | 
| 1923 |  | predicate_identifiers_in_scope(Pred,LocalVariables,Ids) :- | 
| 1924 |  | %get_global_identifiers(IS), | 
| 1925 |  | list_to_ord_set(LocalVariables,LV), | 
| 1926 |  | %ord_subtract(IS,LV,Ignore2), % Do not ignore any local variable; it will be used instead of enumerate set element | 
| 1927 |  | find_identifier_uses_if_necessary(Pred,[],Ids1),  % Ignore enumerated set names | 
| 1928 |  | exclude_global_identifiers(Ids1,LV,Ids2), | 
| 1929 |  | list_to_ord_set(Ids2,Ids). | 
| 1930 |  |  | 
| 1931 |  | % see also b_global_constant_or_set_identifier and exclude_global_identifiers | 
| 1932 |  | get_global_identifiers(IDs) :- get_global_identifiers(IDs,all). | 
| 1933 |  | % get global set and constant identifiers which you usually want to exclude for find_identifier_uses | 
| 1934 |  | get_global_identifiers(IDs,Option) :- | 
| 1935 |  | (Option=ignore_promoted_constants | 
| 1936 |  | % do not include those constants that have been automatically promoted as enumerated set elements | 
| 1937 |  | -> b_get_enumerated_set_constants(EnumeratedSetCsts) | 
| 1938 |  | ; b_get_global_constants(EnumeratedSetCsts) | 
| 1939 |  | ), | 
| 1940 |  | % b_global_sets:b_get_global_enumerated_sets(GSets), % is there a reason to exclude deferred sets ??; cardinality inference,... are all done before partitioning ? | 
| 1941 |  | b_get_global_sets(GSets), | 
| 1942 |  | append(GSets,EnumeratedSetCsts,GE), | 
| 1943 |  | list_to_ord_set(GE,IDs). | 
| 1944 |  |  | 
| 1945 |  | % find_components(ListOf_pred, Restrict, Out:ListOfComponents) | 
| 1946 |  | % role of Restrict: all if we do normal partition or List of VariableIDs on which we restrict our attention to (for Existential quantifier construction) | 
| 1947 |  | find_components([],_,[]). | 
| 1948 |  | find_components([pred(P,PIds,true)|PRest],Restrict,[component(Pred,Ids)|CRest]) :- | 
| 1949 |  | % find all predicates which are using identifiers occuring in PIds | 
| 1950 |  | % (and additionally those which use common identifiers ) | 
| 1951 |  | ord_restrict(Restrict,PIds,InterIDs), | 
| 1952 |  | %format('Treating predicate with ids ~w; restr. intersect = ~w~n',[PIds,InterIDs]), | 
| 1953 |  | ( InterIDs =[] -> | 
| 1954 |  | % we simply copy this predicate into a single component; not with the scope of Restricted IDs | 
| 1955 |  | % print(skip(PIds,P)),nl, % | 
| 1956 |  | Pred=P, Ids=PIds, PRest=Rest | 
| 1957 |  | ; | 
| 1958 |  | extract_all_predicates(InterIDs,Restrict,PIds,PRest,Preds,Rest,Ids), | 
| 1959 |  | %length([P|Preds],Len), format('Detected component with ~w conjuncts over ~w~n',[Len,Ids]), | 
| 1960 |  | conjunct_predicates_with_pos_info([P|Preds],Pred) | 
| 1961 |  | ), | 
| 1962 |  | find_components(Rest,Restrict,CRest). | 
| 1963 |  | extract_all_predicates([],_,_,Preds,Found,Rest,[]) :- !,  % selecting done at end: keep same order of conjuncts | 
| 1964 |  | select_predicates(Preds,Found,Rest). | 
| 1965 |  | extract_all_predicates(Ids,Restrict,OldIds,Preds,Found,Rest,ResultIds) :- | 
| 1966 |  | % search for all predicates that directly use one of the | 
| 1967 |  | % identifiers in "Ids" | 
| 1968 |  | select_all_using_preds(Preds,Ids,FoundIds), | 
| 1969 |  | ord_subtract(FoundIds,OldIds,NewIds), | 
| 1970 |  | ord_restrict(Restrict,NewIds,NewIdsToExtract), | 
| 1971 |  | ord_union(OldIds,FoundIds,OldIds2), | 
| 1972 |  | % now recursively do this which the new identifiers that we have found | 
| 1973 |  | extract_all_predicates(NewIdsToExtract,Restrict,OldIds2,Preds,Found,Rest,RestIds), | 
| 1974 |  | ord_union([Ids,NewIds,RestIds],ResultIds). | 
| 1975 |  |  | 
| 1976 |  | % mark all predicates which intersect with ComponentIds and compute new ids to be added to the component | 
| 1977 |  | select_all_using_preds([],_,[]). | 
| 1978 |  | select_all_using_preds([pred(_P,PIds,Selected)|PRest],ComponentIds,NewFoundIds) :- | 
| 1979 |  | ( (Selected==true ; ord_disjoint(PIds,ComponentIds)) -> | 
| 1980 |  | NewFoundIds1 = [] | 
| 1981 |  | ; % we select the predicate for the component | 
| 1982 |  | ord_subtract(PIds,ComponentIds,NewFoundIds1), | 
| 1983 |  | Selected=true | 
| 1984 |  | ), | 
| 1985 |  | select_all_using_preds(PRest,ComponentIds,NewFoundIds2), | 
| 1986 |  | ord_union(NewFoundIds1,NewFoundIds2,NewFoundIds). | 
| 1987 |  |  | 
| 1988 |  | % ord_intersection with special case for all term | 
| 1989 |  | ord_restrict(all,Ids,Res) :- !, Res=Ids. | 
| 1990 |  | ord_restrict(Restrict,Ids,Res) :- ord_intersection(Ids,Restrict,Res). | 
| 1991 |  |  | 
| 1992 |  | select_predicates(Predicates,FoundPreds,OtherPreds) :- | 
| 1993 |  | split_list(is_selected_predicate,Predicates,FoundPredIds,OtherPreds), | 
| 1994 |  | maplist(extract_found_predicate,FoundPredIds,FoundPreds). | 
| 1995 |  | is_selected_predicate(pred(_P,_PIds,Selected)) :- ground(Selected). | 
| 1996 |  | extract_found_predicate(pred(P,_PIds,_Selected),P). | 
| 1997 |  |  | 
| 1998 |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
| 1999 |  | % replace (simultaneously) multiple identifiers by expressions | 
| 2000 |  | % this could be used to replace the predicate replace_id_by_expr by mapping everything in a | 
| 2001 |  | % singleton list. however, that would involve list operations instead of unifications | 
| 2002 |  | parse_pred(Codes,TExpr) :- %format('Parsing ~s~n',[Codes]), | 
| 2003 |  | bmachine:b_parse_machine_predicate_from_codes_open(no_quantifier,Codes,[],[],TExpr). | 
| 2004 |  | parse_expr(Codes,TExpr) :- bmachine:b_parse_machine_expression_from_codes(Codes,[],TExpr,_Type,true,_Error). | 
| 2005 |  | test_result(1,b(equal(b(comprehension_set([b(identifier(__FRESH____),integer,_)], | 
| 2006 |  | b(greater(b(identifier(__FRESH____2),integer,_),b(identifier(x),integer,_)),pred,_)),set(integer),_), | 
| 2007 |  | b(empty_set,set(integer),_)),pred,_)). | 
| 2008 |  |  | 
| 2009 |  | :- assert_must_succeed((bsyntaxtree:parse_pred("{x|x:INTEGER & x>y}={}",T1), replace_ids_by_exprs(T1,[],[],T1))). | 
| 2010 |  | :- assert_must_succeed((bsyntaxtree:parse_pred("{x|x:INTEGER & x>y}={}",T1), bsyntaxtree:parse_expr("100",T2), | 
| 2011 |  | replace_ids_by_exprs(T1,[y],[T2],R),bsyntaxtree:parse_pred("{x|x>100}={}",T3),same_texpr(R,T3) )). | 
| 2012 |  | :- assert_must_succeed((bsyntaxtree:parse_pred("{x|x:INTEGER & x>y}={}",T1), | 
| 2013 |  | replace_ids_by_exprs(T1,[y],[b(identifier(x),integer,[])],R), | 
| 2014 |  | bsyntaxtree:test_result(1,R),bsyntaxtree:parse_pred("{x|x:INTEGER & x>x}={}",T3),\+ same_texpr(R,T3) )). | 
| 2015 |  | :- assert_must_succeed((bsyntaxtree:parse_pred("{x,y|x:INTEGER & y:INTEGER & x>v & y>w}={}",T1), | 
| 2016 |  | replace_ids_by_exprs(T1,[v,w],[b(identifier(w),integer,[]),b(identifier(v),integer,[])],R), | 
| 2017 |  | bsyntaxtree:parse_pred("{x,y|x:INTEGER & y:INTEGER & x>w & y>v}={}",T3), same_texpr(R,T3) )). | 
| 2018 |  | :- assert_must_succeed((gensym:reset_gensym, bsyntaxtree:parse_pred("{x,y|x:INTEGER & y:INTEGER & x>v & y>w}={}",T1), | 
| 2019 |  | replace_ids_by_exprs(T1,[v,w],[b(identifier(w),integer,[]),b(identifier(x),integer,[])],R), | 
| 2020 |  | translate:translate_bexpression(R,TR), | 
| 2021 |  | TR = '{`__FRESH____1`,y|`__FRESH____1` > w & y > x} = {}')). %'{__FRESH____1,y|(__FRESH____1 : INTEGER & y : INTEGER) & (__FRESH____1 > w & y > x)} = {}' )). | 
| 2022 |  |  | 
| 2023 |  | replace_ids_by_exprs(TExpr,[TId],[Inserted],Replaced) :- !, % better, more robust and efficient version | 
| 2024 |  | check_ids([TId],[Id]), | 
| 2025 |  | replace_id_by_expr(TExpr,Id,Inserted,Replaced). | 
| 2026 |  | replace_ids_by_exprs(TExpr,[],[],Replaced) :- !, Replaced=TExpr. % Nothing to do | 
| 2027 |  | replace_ids_by_exprs(TExpr,Ids,Exprs,Replaced) :- | 
| 2028 |  | check_ids(Ids,Ids2), % convert to atomic identifiers | 
| 2029 |  | find_identifier_uses_l(Exprs,[],ExprsUsedIds), | 
| 2030 |  | sort(ExprsUsedIds,SExprsUsedIds), | 
| 2031 |  | generate_rename_list(Ids2,Exprs,RenameList), | 
| 2032 |  | %print(replace(RenameList,SExprsUsedIds)),nl, | 
| 2033 |  | replace_ids_by_exprs2(RenameList,SExprsUsedIds,TExpr,Replaced,_). %, nl,print(done),nl. | 
| 2034 |  | % a version of replace_ids_by_exprs2 for maplist: | 
| 2035 |  | %replace_ids_by_exprs1(RenameList,SExprsUsedIds,TExpr,Replaced) :- | 
| 2036 |  | %   replace_ids_by_exprs2(RenameList,SExprsUsedIds,TExpr,Replaced,_). %, print('Rep: '), translate:print_bexpr(Replaced),nl. | 
| 2037 |  |  | 
| 2038 |  | generate_rename_list([],[],[]). | 
| 2039 |  | generate_rename_list([ID1|T],[Expr1|TE],[rename(ID1,Expr1)|RT]) :- generate_rename_list(T,TE,RT). | 
| 2040 |  |  | 
| 2041 |  | check_ids([],[]). | 
| 2042 |  | check_ids([H|T],[ID|IT]) :- (atomic(H) -> ID=H ; def_get_texpr_id(H,ID)), check_ids(T,IT). | 
| 2043 |  | replace_ids_by_exprs2(RenameList,ExprsUsedIds,TExpr,Replaced,WDC) :- | 
| 2044 |  | remove_bt(TExpr,Expr,NewExpr,TNewExpr), | 
| 2045 | ? | ( Expr = identifier(Id), member(rename(Id,Inserted),RenameList) -> | 
| 2046 |  | Replaced = Inserted, | 
| 2047 |  | get_texpr_info(Inserted,Infos), | 
| 2048 |  | (memberchk(contains_wd_condition,Infos) | 
| 2049 |  | -> WDC = true ; WDC = false) % WDC = true means we have added a wd-condition where previously there was none | 
| 2050 |  | ; contains_no_ids(Expr) -> Replaced=TExpr, WDC=false | 
| 2051 |  | ; | 
| 2052 |  | syntaxtransformation_det(Expr,Subs1,Names,NSubs,NewExpr), | 
| 2053 |  | find_variable_clashes(Names,ExprsUsedIds,RenameNames),    % check for variable caputure | 
| 2054 |  | (RenameNames = [] | 
| 2055 |  | -> Subs = Subs1 % no variable capture occured | 
| 2056 |  | ; %format('*** VARIABLE CAPTURE : ~w~n~n',[RenameNames]), | 
| 2057 |  | rename_bt_l(Subs1,RenameNames,Subs) % replace affected names by fresh ids in sub arguments (will also change list of quantified variables itself) | 
| 2058 |  | ), | 
| 2059 |  | %l_replace_ids_by_exprs2(QSubs,RenameList,ExprsUsedIds,NQSubs,WDC1), % QSubs are like RHS of let expression, where Names are not in scope | 
| 2060 |  | remove_hidden_names(Names,RenameList,UpdatedRenameList), | 
| 2061 |  | ( UpdatedRenameList = [] -> % all Ids are now hidden for the inner expressions | 
| 2062 |  | NSubs=Subs, WDC=false | 
| 2063 |  | ; | 
| 2064 |  | l_replace_ids_by_exprs2(Subs,UpdatedRenameList,ExprsUsedIds,NSubs,WDC) | 
| 2065 |  | ), | 
| 2066 |  | TNewExpr = b(E1,T1,Info1), | 
| 2067 |  | rename_update_used_ids_info(RenameList,Info1,Info2), | 
| 2068 |  | add_wd_if_needed(WDC,b(E1,T1,Info2),Replaced) | 
| 2069 |  | ). | 
| 2070 |  |  | 
| 2071 |  | contains_no_ids(integer(_)). | 
| 2072 |  | contains_no_ids(string(_)). | 
| 2073 |  | contains_no_ids(value(_)). | 
| 2074 |  |  | 
| 2075 |  |  | 
| 2076 |  | % check if we have to rename any quantified variable to avoid variable capture of RHS of renamings | 
| 2077 |  | % example, suppose we rename x/y+1  and we enter {y|y>x}  we have to generate {fresh|fresh>y+1} and *not* {y|y>y+1} | 
| 2078 |  | find_variable_clashes([],_,[]). | 
| 2079 |  | find_variable_clashes([Name|Names],ExprsUsedIds,[rename(ID,FRESHID)|Renaming] ) :- | 
| 2080 |  | def_get_texpr_id(Name,ID), | 
| 2081 |  | ord_member(ID,ExprsUsedIds), % the quantified name is also introduced by the renaming | 
| 2082 |  | !, | 
| 2083 |  | gensym('__FRESH__',FRESHID), | 
| 2084 |  | find_variable_clashes(Names,ExprsUsedIds,Renaming). | 
| 2085 |  | find_variable_clashes([_|Names],ExprsUsedIds,Renaming) :- | 
| 2086 |  | find_variable_clashes(Names,ExprsUsedIds,Renaming). | 
| 2087 |  |  | 
| 2088 |  |  | 
| 2089 |  | l_replace_ids_by_exprs2([],_,_,[],false). | 
| 2090 |  | l_replace_ids_by_exprs2([H|T],UpdatedRenameList,ExprsUsedIds,[IH|IT],WDC) :- | 
| 2091 |  | replace_ids_by_exprs2(UpdatedRenameList,ExprsUsedIds,H,IH,WDC1), | 
| 2092 |  | l_replace_ids_by_exprs2(T,UpdatedRenameList,ExprsUsedIds,IT,WDC2), | 
| 2093 |  | and_wdc(WDC1,WDC2,WDC). | 
| 2094 |  |  | 
| 2095 |  | % remove any identifiers that are now "invisible" because they are masked by quantified names | 
| 2096 |  | % e.g.,  when we enter #x.(P)  then a renaming of x will be "hidden" inside P | 
| 2097 |  | remove_hidden_names([],RenameList,RenameList). | 
| 2098 |  | remove_hidden_names([Name|Names],RenameList,NewRenameList) :- | 
| 2099 |  | def_get_texpr_id(Name,ID), | 
| 2100 |  | delete(RenameList,rename(ID,_),RenameList1), | 
| 2101 |  | !, % only one rename should exist | 
| 2102 |  | %print(del(ID,RenameList1)),nl, | 
| 2103 |  | remove_hidden_names(Names,RenameList1,NewRenameList). | 
| 2104 |  |  | 
| 2105 |  | find_rhs_ids(rename(Id,TExpr),rename_ids(Id,InsUsedIds)) :- find_identifier_uses(TExpr,[],InsUsedIds). | 
| 2106 |  |  | 
| 2107 |  | % apply a rename list to the used_ids,... information fields | 
| 2108 |  | % this is more tricky than applying a single identifier, as we first have to deleted all ids | 
| 2109 |  | % and remember which ones were deleted, and only then insert the corresponding ids | 
| 2110 |  | % e.g., we could have a RenameList = [rename(p,q),rename(q,p)] ; see test 1776 M1_Internal_v3.mch | 
| 2111 |  | rename_update_used_ids_info(RenameList,IIn,IOut) :- | 
| 2112 |  | l_find_rhs_ids(RenameList,RenameList2), | 
| 2113 |  | %maplist(apply_rename_list(RenameList2),IIn,IOut). | 
| 2114 |  | l_apply_rename_list(IIn,RenameList2,IOut). | 
| 2115 |  |  | 
| 2116 |  | l_find_rhs_ids([],[]). | 
| 2117 |  | l_find_rhs_ids([R1|T],[NR1|NTR]) :- | 
| 2118 |  | find_rhs_ids(R1,NR1), | 
| 2119 |  | l_find_rhs_ids(T,NTR). | 
| 2120 |  |  | 
| 2121 |  | l_apply_rename_list([],_,[]). | 
| 2122 |  | l_apply_rename_list([Info1|T],RenameList2,[NewInfo1|NTI]) :- | 
| 2123 |  | apply_rename_list(RenameList2,Info1,NewInfo1), | 
| 2124 |  | l_apply_rename_list(T,RenameList2,NTI). | 
| 2125 |  |  | 
| 2126 |  | apply_rename_list(RenameList,I,NI) :- | 
| 2127 |  | apply_rename_list2(I,RenameList,NI). | 
| 2128 |  | apply_rename_list2(used_ids(IDS),RenameList,used_ids(NewIDS)) :- !, apply_rename_list_to_ids(RenameList,IDS,[],NewIDS). | 
| 2129 |  | apply_rename_list2(reads(IDS),RenameList,reads(NewIDS)) :- !, apply_rename_list_to_ids(RenameList,IDS,[],NewIDS). | 
| 2130 |  | apply_rename_list2(modifies(IDS),RenameList,modifies(NewIDS)) :- !, apply_rename_list_to_ids(RenameList,IDS,[],NewIDS). | 
| 2131 |  | apply_rename_list2(Info,_,Info). | 
| 2132 |  |  | 
| 2133 |  | % apply a rename list to a sorted list of ids | 
| 2134 |  | apply_rename_list_to_ids([],Acc,ToInsert,Res) :- ord_union(Acc,ToInsert,Res). | 
| 2135 |  | apply_rename_list_to_ids([rename_ids(Id,NewIds)|T],Acc,ToInsert,Res) :- | 
| 2136 |  | (ord_delete_existing_element(Acc,Id,Acc2) % the Id occurs and is deleted | 
| 2137 |  | ->  ord_union(NewIds,ToInsert,ToInsert2), | 
| 2138 |  | apply_rename_list_to_ids(T,Acc2,ToInsert2,Res) | 
| 2139 |  | ;   apply_rename_list_to_ids(T,Acc,ToInsert,Res)). | 
| 2140 |  |  | 
| 2141 |  | ord_delete_existing_element(List,El,ResList) :- % ord_del_element also succeeds if El is not in the list ! | 
| 2142 |  | ord_intersection([El],List,[El],ResList). | 
| 2143 |  | % ----------------------- | 
| 2144 |  | % remove an Identifier from used_ids Info field if it exists | 
| 2145 |  | remove_used_id_from_info(I,ID_to_remove,NI) :- | 
| 2146 |  | update_used_ids_info(I,ID_to_remove,[],NI). | 
| 2147 |  |  | 
| 2148 |  | remove_used_ids_from_info([],I,I). | 
| 2149 |  | remove_used_ids_from_info([ID_to_remove|T],I,NI) :- remove_used_id_from_info(I,ID_to_remove,I2), | 
| 2150 |  | remove_used_ids_from_info(T,I2,NI). | 
| 2151 |  |  | 
| 2152 |  | % remove a single Identifier from used_ids Info field if it exists and insert sorted list of ids instead | 
| 2153 |  | % a simpler version of rename_update_used_ids_info for a single identifier | 
| 2154 |  | update_used_ids_info([],_,_,[]). | 
| 2155 |  | update_used_ids_info([InfoField|T],ID_to_remove,IDsInserted,[NewInfoField|NT]) :- | 
| 2156 |  | (update_id_from_info_field(ID_to_remove,IDsInserted,InfoField,R) | 
| 2157 |  | -> NewInfoField=R | 
| 2158 |  | ; NewInfoField=InfoField), | 
| 2159 |  | update_used_ids_info(T,ID_to_remove,IDsInserted,NT). | 
| 2160 |  |  | 
| 2161 |  | update_id_from_info_field(ID_to_remove,IDsInserted,I,NI) :- | 
| 2162 |  | update_id_from_info_field2(I,ID_to_remove,IDsInserted,NI). | 
| 2163 |  | update_id_from_info_field2(used_ids(IDS),ID,IDsInserted,used_ids(NewIDS)) :- update_id(IDS,ID,IDsInserted,NewIDS). | 
| 2164 |  | update_id_from_info_field2(reads(IDS),ID,IDsInserted,reads(NewIDS)) :- update_id(IDS,ID,IDsInserted,NewIDS). | 
| 2165 |  | update_id_from_info_field2(modifies(IDS),ID,IDsInserted,modifies(NewIDS)) :- update_id(IDS,ID,IDsInserted,NewIDS). | 
| 2166 |  |  | 
| 2167 |  | update_id(IDS,ID_to_remove,IDsInserted,NewIDS) :- | 
| 2168 |  | ord_delete_existing_element(IDS,ID_to_remove,IDS2), % the Id occurs and is deleted | 
| 2169 |  | ord_union(IDsInserted,IDS2,NewIDS). | 
| 2170 |  | %if ord_del_element fails we do not add IDsInserted: we assume the used_ids info is correct and ID_to_remove does not occur ! | 
| 2171 |  | % We could use this info to avoid traversing subtree ! | 
| 2172 |  | % print(projecting_away_unknown_id(ID_to_remove,IDS)),nl, | 
| 2173 |  |  | 
| 2174 |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
| 2175 |  |  | 
| 2176 |  | :- assert_must_succeed((gensym:reset_gensym, bsyntaxtree:exists_ast(A), replace_id_by_expr(A,y,b(identifier(x),integer,[]),RA),translate:translate_bexpression(RA,TR), | 
| 2177 |  | TR = 'r = {`__FRESH____1`|`__FRESH____1` : 1 .. x & `__FRESH____1` mod 2 = 1}' )). | 
| 2178 |  | :- assert_must_succeed((bsyntaxtree:parse_pred("{x|x:INTEGER & x>y}={}",T1), | 
| 2179 |  | replace_id_by_expr(T1,y,b(identifier(x),integer,[]),R), | 
| 2180 |  | bsyntaxtree:test_result(1,R),bsyntaxtree:parse_pred("{x|x:INTEGER & x>x}={}",T3), | 
| 2181 |  | \+ same_texpr(R,T3) )). | 
| 2182 |  | :- assert_must_succeed((bsyntaxtree:parse_pred("{x|x:INTEGER & x>y}={}",T1), bsyntaxtree:parse_expr("100",T2), | 
| 2183 |  | replace_id_by_expr(T1,y,T2,R),bsyntaxtree:parse_pred("{x|x>100}={}",T3),same_texpr(R,T3) )). | 
| 2184 |  |  | 
| 2185 |  | % replace an identifier Id by an expression Inserted | 
| 2186 |  | replace_id_by_expr(TExpr,Id,Inserted,Replaced) :- | 
| 2187 |  | replace_id_by_expr_with_count(TExpr,Id,Inserted,Replaced,_). | 
| 2188 |  |  | 
| 2189 |  | replace_id_by_expr_with_count(TExpr,Id,Inserted,Replaced,NrReplacements) :- \+ atomic(Id),!, | 
| 2190 |  | add_internal_error('Id not atomic: ',replace_id_by_expr(TExpr,Id,Inserted,Replaced)), | 
| 2191 |  | Replaced = TExpr, NrReplacements=0. | 
| 2192 |  | replace_id_by_expr_with_count(TExpr,Id,Inserted,Replaced,NrReplacements) :- | 
| 2193 |  | %find_all_relevant_quantified_vars(Id,TExpr,QVars), | 
| 2194 |  | find_identifier_uses(Inserted,[],SInsUsedIds), % SInsUsedIds is sorted | 
| 2195 |  | replace_id_by_expr2(Id,Inserted,SInsUsedIds,TExpr,Replaced,_WDC,0,NrReplacements). | 
| 2196 |  |  | 
| 2197 |  | replace_id_by_expr2(Id,Inserted,InsUsedIds,TExpr,Replaced,WDC,InR,OutR) :- | 
| 2198 |  | remove_bt(TExpr,Expr,NewExpr,TNewExpr), | 
| 2199 |  | ( Expr = identifier(Id) ->  % TODO: count number of replacements | 
| 2200 |  | Replaced = Inserted, | 
| 2201 |  | OutR is InR+1, | 
| 2202 |  | get_texpr_info(Inserted,Infos), | 
| 2203 |  | (memberchk(contains_wd_condition,Infos) | 
| 2204 |  | -> WDC = true ; WDC = false) % WDC = true means we have added a wd-condition where previously there was none | 
| 2205 |  | ; contains_no_ids(Expr) -> Replaced=TExpr, WDC=false, OutR=InR | 
| 2206 |  | ; | 
| 2207 |  | syntaxtransformation_det(Expr,Subs,Names,NSubs,NewExpr), | 
| 2208 |  | get_texpr_id(TId,Id), | 
| 2209 |  | ( memberchk(TId,Names) -> % the Id is now hidden for the inner expressions | 
| 2210 |  | NSubs=Subs, WDC=false, OutR = InR | 
| 2211 |  | ; (InsUsedIds \= [], | 
| 2212 |  | get_texpr_ids(Names,Ns),sort(Ns,SNs), | 
| 2213 |  | ord_intersection(SNs,InsUsedIds,Captured), | 
| 2214 |  | Captured \= [] %, print(inter(SNs,InsUsedIds,Captured)),nl | 
| 2215 |  | ) | 
| 2216 |  | % The Names introduced clash with variables used in the Inserted expression | 
| 2217 |  | ->  findall(rename(X,FRESHID),(member(X,Captured),gensym:gensym('__FRESH__',FRESHID)),RenameList), | 
| 2218 |  | %print(rename(RenameList)),nl, | 
| 2219 |  | rename_bt_l(Subs,RenameList,RenSubs), | 
| 2220 |  | l_replace_id_by_expr2(RenSubs,Id,Inserted,InsUsedIds,NSubs,WDC,InR,OutR) | 
| 2221 |  | ; | 
| 2222 |  | l_replace_id_by_expr2(Subs,Id,Inserted,InsUsedIds,NSubs,WDC,InR,OutR) | 
| 2223 |  | ), | 
| 2224 |  | TNewExpr = b(E1,T1,Info1), | 
| 2225 |  | update_used_ids_info(Info1,Id,InsUsedIds,Info2), | 
| 2226 |  | %(E1 = exists(P,_) -> print(exists(P,Id,Info1,Info2)),nl ; true), | 
| 2227 |  | add_wd_if_needed(WDC,b(E1,T1,Info2),Replaced) | 
| 2228 |  | ). | 
| 2229 |  |  | 
| 2230 |  | l_replace_id_by_expr2([],_,_,_,[],false,R,R). | 
| 2231 |  | l_replace_id_by_expr2([H|T],Id,Inserted,InsUsedIds,[IH|IT],WDC,InR,OutR) :- | 
| 2232 |  | replace_id_by_expr2(Id,Inserted,InsUsedIds,H,IH,WDC1,InR,InR2), | 
| 2233 |  | l_replace_id_by_expr2(T,Id,Inserted,InsUsedIds,IT,WDC2,InR2,OutR), | 
| 2234 |  | and_wdc(WDC1,WDC2,WDC). | 
| 2235 |  |  | 
| 2236 |  | % conjunct wd condition added flag | 
| 2237 |  | and_wdc(true,_,R) :- !,R=true. | 
| 2238 |  | and_wdc(_,true,R) :- !, R=true. | 
| 2239 |  | and_wdc(_,_,false). | 
| 2240 |  |  | 
| 2241 |  | % add contains_wd_condition if a change occured during replacement of id by expression | 
| 2242 |  | add_wd_if_needed(true,b(E,T,Infos),Replaced) :- | 
| 2243 |  | nonmember(contains_wd_condition,Infos), | 
| 2244 |  | !, | 
| 2245 |  | Replaced = b(E,T,[contains_wd_condition|Infos]). | 
| 2246 |  | add_wd_if_needed(_,T,T). | 
| 2247 |  |  | 
| 2248 |  |  | 
| 2249 |  |  | 
| 2250 |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
| 2251 |  |  | 
| 2252 |  |  | 
| 2253 |  | % syntaxtransformation_fixed/7 is the same as syntaxtransformation/5 with the exception | 
| 2254 |  | % that we distinguish between subexpressions that have the newly introduced identifiers (Names) | 
| 2255 |  | % in scope (OSubs) and those who don't (OExprs). The only expressions where the latter case is relevant | 
| 2256 |  | % are let_expression and let_predicate. | 
| 2257 |  | % TODO: This is a quick'n dirty fix for only some cases. | 
| 2258 |  | % NO LONGER REQUIRED: let_expression and let_predicate now obey another semantic, not the Z semantics anymore | 
| 2259 |  | %syntaxtransformation_fixed(OExpr,OExprs,OSubs,Names,NExprs,NSubs,NExpr) :- | 
| 2260 |  | %syntaxtransformation_fixed(Expr,[],Subs,Names,[],NSubs,NExpr) :- | 
| 2261 |  | %    syntaxtransformation_det(Expr,Subs,Names,NSubs,NExpr). | 
| 2262 |  |  | 
| 2263 |  |  | 
| 2264 |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
| 2265 |  | % rename identifier | 
| 2266 |  |  | 
| 2267 |  | % r = {x|x : 1..y & x mod 2 = 1} | 
| 2268 |  | exists_ast(AST) :- AST = | 
| 2269 |  | b(equal(b(identifier(r),set(integer),[nodeid(none)]), | 
| 2270 |  | b(comprehension_set([b(identifier(x),integer,[nodeid(none)])], | 
| 2271 |  | b(conjunct(b(member(b(identifier(x),integer,[nodeid(none)]), | 
| 2272 |  | b(interval(b(integer(1),integer,[nodeid(none)]),b(identifier(y),integer,[nodeid(none)])), | 
| 2273 |  | set(integer),[nodeid(none)])),pred,[nodeid(none)]), | 
| 2274 |  | b(equal(b(modulo(b(identifier(x),integer,[nodeid(none)]), | 
| 2275 |  | b(integer(2),integer,[nodeid(none)])),integer,[contains_wd_condition,nodeid(none)]), | 
| 2276 |  | b(integer(1),integer,[nodeid(none)])),pred, | 
| 2277 |  | [contains_wd_condition,nodeid(none)])),pred,[contains_wd_condition,nodeid(none)])), | 
| 2278 |  | set(integer),[contains_wd_condition,nodeid(none)])), | 
| 2279 |  | pred,[contains_wd_condition,nodeid(none)]). | 
| 2280 |  |  | 
| 2281 |  | :- assert_must_succeed((bsyntaxtree:exists_ast(A), rename_bt(A,[rename(x,xx)],RA), RA==A )). | 
| 2282 |  | :- assert_must_succeed((bsyntaxtree:exists_ast(A), rename_bt(A,[rename(r,v)],RA), | 
| 2283 |  | translate:translate_bexpression(RA,TR), TR='v = {x|x : 1 .. y & x mod 2 = 1}' )). | 
| 2284 |  | :- assert_must_succeed((gensym:reset_gensym, bsyntaxtree:exists_ast(A), rename_bt(A,[rename(y,x)],RA), RA \= A, | 
| 2285 |  | translate:translate_bexpression(RA,TR), | 
| 2286 |  | TR = 'r = {`__FRESH____1`|`__FRESH____1` : 1 .. x & `__FRESH____1` mod 2 = 1}' )). | 
| 2287 |  |  | 
| 2288 |  | % a simplified version of replace_ids_by_exprs, which assumes target of renamings are variables | 
| 2289 |  | rename_bt(Expr,[],Res) :- !,Res=Expr. | 
| 2290 |  | rename_bt(OExpr,Renamings,NExpr) :- | 
| 2291 |  | create_texpr(Old,Type,OInfo,OExpr), | 
| 2292 |  | create_texpr(New,Type,NInfo,NExpr), | 
| 2293 |  | rename_in_infos(OInfo,Renamings,NInfo), | 
| 2294 |  | rename_bt2(Old,Renamings,New). | 
| 2295 |  | rename_bt2(identifier(Old),Renamings,identifier(New)) :- | 
| 2296 |  | !, rename_id(Old,Renamings,New). | 
| 2297 |  | rename_bt2(lazy_lookup_expr(Old),Renamings,lazy_lookup_expr(New)) :- | 
| 2298 |  | !, rename_id(Old,Renamings,New). | 
| 2299 |  | rename_bt2(lazy_lookup_pred(Old),Renamings,lazy_lookup_pred(New)) :- | 
| 2300 |  | !, rename_id(Old,Renamings,New). | 
| 2301 |  | rename_bt2(OExpr,Renamings,NExpr) :- | 
| 2302 |  | syntaxtransformation_for_renaming(OExpr,Subs,TNames,NSubs,NExpr), | 
| 2303 |  | get_texpr_exprs(TNames,Names), | 
| 2304 |  | remove_renamings(Names,Renamings,NRenamings), | 
| 2305 |  | rename_bt_l(Subs,NRenamings,NSubs). | 
| 2306 |  | rename_bt_l([],_,[]). | 
| 2307 |  | rename_bt_l([Old|ORest],Renamings,[New|NRest]) :- | 
| 2308 |  | rename_bt(Old,Renamings,New), | 
| 2309 |  | rename_bt_l(ORest,Renamings,NRest). | 
| 2310 |  |  | 
| 2311 |  | % syntaxtransformation rule for operation_call_in_expr does not show Id field in sub expressions | 
| 2312 |  | % (to avoid issues with find_identifier_uses, see below) | 
| 2313 |  | %  so here we explicitly also rename the operation name if required, relevant for bmachine_construction, test 2504 | 
| 2314 |  | % TODO: avoid this special case and fix find_identifier_uses instead | 
| 2315 |  | syntaxtransformation_for_renaming(operation_call_in_expr(ID,Subs1),Subs,TNames,NSubs,NExpr) :- !, | 
| 2316 |  | NExpr = operation_call_in_expr(NID,NSubs1), | 
| 2317 |  | Subs = [ID|Subs1], | 
| 2318 |  | NSubs = [NID|NSubs1], TNames = []. | 
| 2319 |  | syntaxtransformation_for_renaming(OExpr,Subs,TNames,NSubs,NExpr) :- | 
| 2320 |  | syntaxtransformation(OExpr,Subs,TNames,NSubs,NExpr). | 
| 2321 |  |  | 
| 2322 |  | remove_renamings([],Renamings,Renamings). | 
| 2323 |  | remove_renamings([identifier(Name)|Rest],Old,New) :- | 
| 2324 | ? | ( select(rename(Name,_),Old,Inter1) -> true  % Name no longer visible to renaming | 
| 2325 |  | ; Old = Inter1), | 
| 2326 |  | (member(rename(_OldName,Name),Inter1) -> | 
| 2327 |  | gensym('__FRESH__',FRESHID), | 
| 2328 |  | %print(variable_capture_in_rename(Name,from(OldName),FRESHID)),nl, | 
| 2329 |  | Inter2 = [rename(Name,FRESHID)|Inter1] | 
| 2330 |  | ; Inter2 = Inter1), | 
| 2331 |  | remove_renamings(Rest,Inter2,New). | 
| 2332 |  |  | 
| 2333 |  | rename_in_infos(Old,Renamings,New) :- | 
| 2334 |  | ( has_info_to_rename(Old) -> | 
| 2335 |  | maplist(rename_in_infos2(Renamings),Old,New) | 
| 2336 |  | ; | 
| 2337 |  | Old = New). | 
| 2338 |  | rename_in_infos2(Renamings,OInfo,NInfo) :- | 
| 2339 |  | ( infos_to_rename(OInfo,OIds,SortedNIds,NInfo) -> | 
| 2340 |  | rename_ids(OIds,Renamings,NIds), | 
| 2341 |  | sort(NIds,SortedNIds) | 
| 2342 |  | ; | 
| 2343 |  | OInfo = NInfo). | 
| 2344 |  |  | 
| 2345 |  | rename_ids([],_,[]). | 
| 2346 |  | rename_ids([OId|Orest],Renamings,[NId|Nrest]) :- | 
| 2347 |  | rename_id(OId,Renamings,NId), | 
| 2348 |  | rename_ids(Orest,Renamings,Nrest). | 
| 2349 |  | rename_id(Old,Renamings,New) :- | 
| 2350 |  | ( memberchk(rename(Old,New),Renamings) -> true  % we could use ord_member if we sort ! | 
| 2351 |  | ; Old=New). | 
| 2352 |  |  | 
| 2353 |  | has_info_to_rename(Infos) :- | 
| 2354 | ? | member(I,Infos),infos_to_rename(I,_,_,_),!. | 
| 2355 |  |  | 
| 2356 |  | infos_to_rename(modifies(O),O,N,modifies(N)). | 
| 2357 |  | infos_to_rename(reads(O),O,N,reads(N)). | 
| 2358 |  | infos_to_rename(non_det_modifies(O),O,N,non_det_modifies(N)). | 
| 2359 |  | infos_to_rename(modifies_locals(O),O,N,modifies_locals(N)). | 
| 2360 |  | infos_to_rename(reads_locals(O),O,N,reads_locals(N)). | 
| 2361 |  | infos_to_rename(used_ids(O),O,N,used_ids(N)). | 
| 2362 |  | %infos_to_rename(lambda_result(O),[O],[N],lambda_result(N)). % whould we no longer assume that we have lambda result, as predicate has possibly changed!? | 
| 2363 |  |  | 
| 2364 |  |  | 
| 2365 |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
| 2366 |  | % remove type information for transformations | 
| 2367 |  |  | 
| 2368 |  | remove_bt(b(Expr,Type,Infos),Expr,NExpr,b(NExpr,Type,Infos)). | 
| 2369 |  |  | 
| 2370 |  | remove_bt_and_used_ids(b(OldExpr,T,Infos),OldExpr,NewExpr,b(NewExpr,T,NewInfos)) :- | 
| 2371 |  | delete(Infos,used_ids(_),NewInfos). % invalidate used_ids info | 
| 2372 |  |  | 
| 2373 |  | %remove_bt_l([],[],[],[]). | 
| 2374 |  | %remove_bt_l([OT|OTRest],[O|ORest],[N|NRest],[NT|NTRest]) :- | 
| 2375 |  | %   remove_bt(OT,O,N,NT), | 
| 2376 |  | %    remove_bt_l(OTRest,ORest,NRest,NTRest). | 
| 2377 |  |  | 
| 2378 |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
| 2379 |  | % traversations | 
| 2380 |  | % Takes a predicate or expression or substitution and extracts: | 
| 2381 |  | %  the expression itself Expr, its type Type, the syntaxnode information Infos | 
| 2382 |  | %  + the subexpressions as a list Subs and the local identifiers declared | 
| 2383 |  | syntaxtraversion(b(Expr,Type,Infos),Expr,Type,Infos,Subs,Names) :- !, | 
| 2384 |  | safe_syntaxelement(Expr,Subs,Names,_,_). | 
| 2385 |  | syntaxtraversion(IExpr,Expr,Type,Infos,Subs,Names) :- | 
| 2386 |  | add_internal_error('Not properly wrapped', syntaxtraversion(IExpr,Expr,Type,Infos,Subs,Names)), | 
| 2387 |  | fail. | 
| 2388 |  |  | 
| 2389 |  |  | 
| 2390 |  | map_over_full_bexpr_no_fail(P,BExpr) :- | 
| 2391 |  | syntaxtraversion(BExpr,Expr,_,_,Subs,_TNames), | 
| 2392 |  | call(P,Expr), % the predicate should not fail | 
| 2393 |  | (Subs=[] -> true ; maplist(map_over_full_bexpr_no_fail(P),Subs)). | 
| 2394 |  |  | 
| 2395 |  | map_over_bexpr(P,BExpr) :- | 
| 2396 |  | syntaxtraversion(BExpr,Expr,_,_,Subs,_TNames), | 
| 2397 |  | (call(P,Expr) % should probably fail so that by backtrack we recurse | 
| 2398 |  | ; | 
| 2399 |  | member(Sub,Subs), map_over_bexpr(P,Sub) | 
| 2400 |  | ). | 
| 2401 |  | % same as above but gets typed expressions: | 
| 2402 |  | map_over_typed_bexpr(P,BExpr) :- | 
| 2403 |  | syntaxtraversion(BExpr,_Expr,_,_,Subs,_TNames), | 
| 2404 |  | (call(P,BExpr) | 
| 2405 |  | ; | 
| 2406 | ? | member(Sub,Subs), map_over_typed_bexpr(P,Sub) | 
| 2407 |  | ). | 
| 2408 |  | % same as above but returns value: | 
| 2409 |  | map_over_typed_bexpr(P,BExpr,Result) :- | 
| 2410 |  | syntaxtraversion(BExpr,_Expr,_,_,Subs,_TNames), | 
| 2411 |  | (call(P,BExpr,Result) | 
| 2412 |  | ; | 
| 2413 | ? | member(Sub,Subs), map_over_typed_bexpr(P,Sub,Result) | 
| 2414 |  | ). | 
| 2415 |  | % this one gets TNames (locally introduced variables as parameter) | 
| 2416 |  | map_over_typed_bexpr_with_names(P,BExpr) :- | 
| 2417 |  | syntaxtraversion(BExpr,_Expr,_,_,Subs,TNames), | 
| 2418 |  | (call(P,BExpr,TNames) | 
| 2419 |  | ; | 
| 2420 |  | member(Sub,Subs), map_over_typed_bexpr_with_names(P,Sub) | 
| 2421 |  | ). | 
| 2422 |  |  | 
| 2423 |  | % same as map_over_expr but provides an accumulator passed top-down to children; needs to be used by failure driven loop | 
| 2424 |  |  | 
| 2425 |  | map_over_bexpr_top_down_acc(P,BExpr,TDAcc) :- | 
| 2426 |  | syntaxtraversion(BExpr,Expr,_,_,Subs,_TNames), | 
| 2427 |  | (call(P,Expr,TDAcc,NewAcc) | 
| 2428 |  | -> member(Sub,Subs), map_over_bexpr_top_down_acc(P,Sub,NewAcc) | 
| 2429 |  | ;  member(Sub,Subs), map_over_bexpr_top_down_acc(P,Sub,TDAcc) | 
| 2430 |  | ). | 
| 2431 |  | % now a version which gets the typed predicate as argument | 
| 2432 |  |  | 
| 2433 |  | map_over_typed_bexpr_top_down_acc(P,BExpr,TDAcc) :- | 
| 2434 |  | syntaxtraversion(BExpr,_Expr,_,_,Subs,_TNames), | 
| 2435 |  | (call(P,BExpr,TDAcc,NewAcc) | 
| 2436 |  | -> member(Sub,Subs), map_over_typed_bexpr_top_down_acc(P,Sub,NewAcc) | 
| 2437 |  | ;  member(Sub,Subs), map_over_typed_bexpr_top_down_acc(P,Sub,TDAcc) | 
| 2438 |  | ). | 
| 2439 |  |  | 
| 2440 |  | % predicate P has 3 arguments: (Expr,ValueSoFar,NewValue) | 
| 2441 |  | reduce_over_bexpr(P,BExpr,InitialValue,ResultValue) :- | 
| 2442 |  | syntaxtraversion(BExpr,Expr,_,_,Subs,_TNames), | 
| 2443 |  | call(P,Expr,InitialValue,I1), % print(reduce(P,Expr,InitialValue,I1)),nl, | 
| 2444 |  | scanlist(reduce_over_bexpr(P),Subs,I1,ResultValue). | 
| 2445 |  |  | 
| 2446 |  | % apply a predicate over a syntax tree (bottom-up) | 
| 2447 |  |  | 
| 2448 |  | transform_bexpr(Pred,b(Expr,Type,Info),NewBExpr) :- !, | 
| 2449 |  | syntaxtransformation(Expr,Subs,_Names,NSubs,NewExpr1), | 
| 2450 |  | l_transform_bexpr(Subs,Pred,NSubs), | 
| 2451 |  | (call(Pred,b(NewExpr1,Type,Info),NewBExpr) -> true ; NewBExpr = b(NewExpr1,Type,Info)). | 
| 2452 |  | transform_bexpr(Pred,Expr,NewBExpr) :- | 
| 2453 |  | add_internal_error('Expression not properly wrapped:',transform_bexpr(Pred,Expr,NewBExpr)), | 
| 2454 |  | fail. | 
| 2455 |  |  | 
| 2456 |  | l_transform_bexpr([],_,[]). | 
| 2457 |  | l_transform_bexpr([SubH|T],Pred,[TSubH|TT]) :- | 
| 2458 |  | transform_bexpr(Pred,SubH,TSubH), | 
| 2459 |  | l_transform_bexpr(T,Pred,TT). | 
| 2460 |  |  | 
| 2461 |  | % apply a predicate over a syntax tree (bottom-up), and provide scoping info about local ids | 
| 2462 |  |  | 
| 2463 |  | transform_bexpr_with_scoping(Pred,BExpr,NewBExpr) :- | 
| 2464 |  | transform_bexpr_with_scoping2(Pred,BExpr,NewBExpr,[]). | 
| 2465 |  | transform_bexpr_with_scoping2(Pred,b(Expr,Type,Info),NewBExpr,LocalIds) :- | 
| 2466 |  | syntaxtransformation(Expr,Subs,Names,NSubs,NewExpr1), | 
| 2467 |  | get_texpr_ids(Names,QuantifiedNewIds), list_to_ord_set(QuantifiedNewIds,SQuantifiedNewIds), | 
| 2468 |  | ord_union(LocalIds,SQuantifiedNewIds,NewLocalIds), | 
| 2469 |  | l_transform_bexpr_with_scoping(Subs,Pred,NSubs,NewLocalIds), | 
| 2470 |  | (call(Pred,b(NewExpr1,Type,Info),NewBExpr,LocalIds) -> true ; NewBExpr = b(NewExpr1,Type,Info)). | 
| 2471 |  |  | 
| 2472 |  | l_transform_bexpr_with_scoping([],_,[],_). | 
| 2473 |  | l_transform_bexpr_with_scoping([SubH|T],Pred,[TSubH|TT],LocalIds) :- | 
| 2474 |  | transform_bexpr_with_scoping2(Pred,SubH,TSubH,LocalIds), | 
| 2475 |  | l_transform_bexpr_with_scoping(T,Pred,TT,LocalIds). | 
| 2476 |  |  | 
| 2477 |  | % transform a predicate top-down with scoping infos | 
| 2478 |  | % if Pred succeeds the top-down traversal stops | 
| 2479 |  | transform_bexpr_td_with_scoping(Pred,BExpr,NewBExpr) :- | 
| 2480 |  | transform_bexpr_td_with_scoping2(Pred,BExpr,NewBExpr,[]). | 
| 2481 |  | transform_bexpr_td_with_scoping2(Pred,b(Expr,Type,Info),b(NewExpr1,Type,Info),LocalIds) :- | 
| 2482 | ? | (call(Pred,Expr,NewExpr1,LocalIds) | 
| 2483 |  | -> true | 
| 2484 |  | ; syntaxtransformation(Expr,Subs,Names,NSubs,NewExpr1), | 
| 2485 |  | get_texpr_ids(Names,QuantifiedNewIds), list_to_ord_set(QuantifiedNewIds,SQuantifiedNewIds), | 
| 2486 |  | ord_union(LocalIds,SQuantifiedNewIds,NewLocalIds), | 
| 2487 |  | l_transform_bexpr_td_with_scoping(Subs,Pred,NSubs,NewLocalIds) | 
| 2488 |  | ). | 
| 2489 |  |  | 
| 2490 |  | l_transform_bexpr_td_with_scoping([],_,[],_). | 
| 2491 |  | l_transform_bexpr_td_with_scoping([SubH|T],Pred,[TSubH|TT],LocalIds) :- | 
| 2492 |  | transform_bexpr_td_with_scoping2(Pred,SubH,TSubH,LocalIds), | 
| 2493 |  | l_transform_bexpr_td_with_scoping(T,Pred,TT,LocalIds). | 
| 2494 |  |  | 
| 2495 |  |  | 
| 2496 |  | % apply a predicate over a syntax tree (bottom-up) with Accumulator result | 
| 2497 |  | % Accumulator is constructed bottom up; Pred receives *all* accumulators of sub expressions | 
| 2498 |  |  | 
| 2499 |  | transform_bexpr_with_bup_accs(Pred,b(Expr,Type,Info),NewBExpr,EmptyAcc,Acc) :- | 
| 2500 |  | syntaxtransformation(Expr,Subs,_Names,NSubs,NewExpr1), | 
| 2501 |  | l_transform_bexpr_with_bup_accs(Subs,Pred,NSubs,EmptyAcc,SubAccs), | 
| 2502 |  | (call(Pred,b(NewExpr1,Type,Info),NewBExpr,SubAccs,Acc) -> true | 
| 2503 |  | ; NewBExpr = b(NewExpr1,Type,Info), Acc = EmptyAcc). | 
| 2504 |  |  | 
| 2505 |  | l_transform_bexpr_with_bup_accs([],_,[],_,[]). | 
| 2506 |  | l_transform_bexpr_with_bup_accs([SubH|T],Pred,[TSubH|TT],EmptyAcc,[Acc1|RestAcc]) :- | 
| 2507 |  | transform_bexpr_with_bup_accs(Pred,SubH,TSubH,EmptyAcc,Acc1), | 
| 2508 |  | l_transform_bexpr_with_bup_accs(T,Pred,TT,EmptyAcc,RestAcc). | 
| 2509 |  |  | 
| 2510 |  | % apply a predicate over a syntax tree (bottom-up) with Accumulator result | 
| 2511 |  | % a single Accumulator is passed along | 
| 2512 |  |  | 
| 2513 |  | transform_bexpr_with_acc(_Pred,E,NewBExpr,InAcc,Acc) :- var(E),!, | 
| 2514 |  | NewBExpr=E, Acc=InAcc. | 
| 2515 |  | transform_bexpr_with_acc(Pred,b(Expr,Type,Info),NewBExpr,InAcc,Acc) :- | 
| 2516 |  | syntaxtransformation(Expr,Subs,_Names,NSubs,NewExpr1), | 
| 2517 |  | l_transform_bexpr_with_acc(Subs,Pred,NSubs,InAcc,SubAcc), | 
| 2518 |  | (call(Pred,b(NewExpr1,Type,Info),NewBExpr,SubAcc,Acc) -> true | 
| 2519 |  | ; NewBExpr = b(NewExpr1,Type,Info), Acc = SubAcc). | 
| 2520 |  |  | 
| 2521 |  | l_transform_bexpr_with_acc([],_,[],Acc,Acc). | 
| 2522 |  | l_transform_bexpr_with_acc([SubH|T],Pred,[TSubH|TT],InAcc,ResAcc) :- | 
| 2523 |  | transform_bexpr_with_acc(Pred,SubH,TSubH,InAcc,Acc1), | 
| 2524 |  | l_transform_bexpr_with_acc(T,Pred,TT,Acc1,ResAcc). | 
| 2525 |  |  | 
| 2526 |  | % a non-deterministic version of this | 
| 2527 |  | non_det_transform_bexpr_with_acc(_Pred,E,NewBExpr,InAcc,Acc) :- var(E),!, | 
| 2528 |  | NewBExpr=E, Acc=InAcc. | 
| 2529 |  | non_det_transform_bexpr_with_acc(Pred,b(Expr,Type,Info),NewBExpr,InAcc,Acc) :- | 
| 2530 |  | syntaxtransformation(Expr,Subs,_Names,NSubs,NewExpr1), | 
| 2531 |  | l_nd_transform_bexpr_with_acc(Subs,Pred,NSubs,InAcc,SubAcc), | 
| 2532 |  | if(call(Pred,b(NewExpr1,Type,Info),NewBExpr,SubAcc,Acc), | 
| 2533 |  | true, | 
| 2534 |  | (NewBExpr = b(NewExpr1,Type,Info), Acc = SubAcc)). | 
| 2535 |  |  | 
| 2536 |  | l_nd_transform_bexpr_with_acc([],_,[],Acc,Acc). | 
| 2537 |  | l_nd_transform_bexpr_with_acc([SubH|T],Pred,[TSubH|TT],InAcc,ResAcc) :- | 
| 2538 |  | non_det_transform_bexpr_with_acc(Pred,SubH,TSubH,InAcc,Acc1), | 
| 2539 |  | l_nd_transform_bexpr_with_acc(T,Pred,TT,Acc1,ResAcc). | 
| 2540 |  |  | 
| 2541 |  |  | 
| 2542 |  | % ------------------------- | 
| 2543 |  |  | 
| 2544 |  | min_max_integer_value_used(BExpr,Min,Max) :- | 
| 2545 |  | min_max_integer_value_used(BExpr,none,none,Min,Max). | 
| 2546 |  | min_max_integer_value_used(BExpr,IMin,IMax,Min,Max) :- | 
| 2547 |  | reduce_over_bexpr(min_max_aux,BExpr,minmax(IMin,IMax),minmax(Min,Max)). | 
| 2548 |  |  | 
| 2549 |  | min_max_aux(sequence_extension(L),minmax(Min,Max),minmax(NMin,NMax)) :- !, | 
| 2550 |  | length(L,Len), % we use implicitly numbers from 1..Len | 
| 2551 |  | (number(Min),1>Min -> NMin=Min ; NMin=1), | 
| 2552 |  | (number(Max),Len<Max -> NMax=Max ; NMax=Len). | 
| 2553 |  | min_max_aux(integer(N),minmax(Min,Max),minmax(NMin,NMax)) :- !, | 
| 2554 |  | (number(Min),N>Min -> NMin=Min ; NMin=N), | 
| 2555 |  | (number(Max),N<Max -> NMax=Max ; NMax=N). | 
| 2556 |  | min_max_aux(_,V,V). | 
| 2557 |  |  | 
| 2558 |  | % check if a B expression uses something like NAT,NAT1,INT, MAXINT or MININT. | 
| 2559 |  | uses_implementable_integers(BExpr) :- | 
| 2560 |  | map_over_bexpr(uses_implementable_integers_aux,BExpr). | 
| 2561 |  |  | 
| 2562 |  | uses_implementable_integers_aux(maxint). | 
| 2563 |  | uses_implementable_integers_aux(minint). | 
| 2564 |  | uses_implementable_integers_aux(integer_set(X)) :- | 
| 2565 |  | (X='NAT1' ; X='NAT' ; X='INT'). | 
| 2566 |  |  | 
| 2567 |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
| 2568 |  | % some checks | 
| 2569 |  | check_if_typed_predicate(b(Pred,X,_)) :- ground(X), X=pred,  % at runtime there can be value(X) with variables inside ! | 
| 2570 |  | syntaxelement(Pred,_,_,_,_,TypePred), (TypePred=pred -> true ; TypePred = pred/only_typecheck). | 
| 2571 |  | check_if_typed_expression(b(Expr,Type,_)) :- | 
| 2572 |  | syntaxelement(Expr,_,_,_,_,TypeExpr), | 
| 2573 |  | (TypeExpr=expr -> true ; TypeExpr = expr/only_typecheck), | 
| 2574 |  | Type \== pred, Type \== subst, ground(Type). | 
| 2575 |  | check_if_typed_substitution(b(Subst,X,_)) :- ground(X), X=subst, | 
| 2576 |  | syntaxelement(Subst,_,_,_,_,subst). | 
| 2577 |  |  | 
| 2578 |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
| 2579 |  | % transformations | 
| 2580 |  |  | 
| 2581 |  | syntaxtransformation(Expr,Subs,Names,NSubs,NExpr) :- | 
| 2582 |  | functor(Expr,F,Arity), | 
| 2583 |  | functor(NExpr,F,Arity), | 
| 2584 |  | safe_syntaxelement(Expr,Subs,Names,Lists,Constant), | 
| 2585 |  | all_same_length(Lists,NLists), | 
| 2586 |  | syntaxelement(NExpr,NSubs,_,NLists,Constant,_). | 
| 2587 |  | % a faster non-backtracking version: | 
| 2588 |  | syntaxtransformation_det(Expr,Subs,Names,NSubs,NExpr) :- | 
| 2589 |  | functor(Expr,F,Arity), | 
| 2590 |  | functor(NExpr,F,Arity), | 
| 2591 |  | safe_syntaxelement_det(Expr,Subs,Names,Lists,Constant), | 
| 2592 |  | all_same_length(Lists,NLists), | 
| 2593 |  | syntaxelement(NExpr,NSubs,_,NLists,Constant,_). | 
| 2594 |  |  | 
| 2595 |  |  | 
| 2596 |  | safe_syntaxelement(Expr,Subs,Names,Lists,Constant) :- | 
| 2597 |  | ( syntaxelement(Expr,SubsX,NamesX,Lists,ConstantX,_) -> | 
| 2598 |  | Subs=SubsX, Names=NamesX, Constant=ConstantX | 
| 2599 |  | %(Subs,Names,Constant)=(SubsX,NamesX,ConstantX) | 
| 2600 |  | ; | 
| 2601 |  | functor(Expr,F,Arity), | 
| 2602 |  | add_error_fail(bsyntaxtree,'Uncovered syntax element: ', F/Arity) | 
| 2603 |  | ). | 
| 2604 |  | % a faster non-backtracking version of safe_syntaxelement, assuming Subs, Names, ... are fresh vars | 
| 2605 |  | safe_syntaxelement_det(Expr,Subs,Names,Lists,Constant) :- | 
| 2606 |  | (syntaxelement(Expr,Subs,Names,Lists,Constant,_) -> true | 
| 2607 |  | ; functor(Expr,F,Arity), | 
| 2608 |  | add_error_fail(bsyntaxtree,'Uncovered syntax element: ', F/Arity)). | 
| 2609 |  |  | 
| 2610 |  | is_subst_syntaxelement(Subst) :- | 
| 2611 |  | syntaxelement(Subst,_,_,_,_,subst). | 
| 2612 |  |  | 
| 2613 |  | % check if we have a syntax node without parameters | 
| 2614 |  | is_syntax_constant(Expr) :- atom(Expr), syntaxelement(Expr,_,_,_,_,_). | 
| 2615 |  |  | 
| 2616 |  | % syntaxelement(Expr,SubExprs,Identifiers,Lists,Constant,Type): | 
| 2617 |  | % Expr: the expression itself | 
| 2618 |  | % SubExprs: a list of sub-expressions | 
| 2619 |  | % Identifiers: a list of identifiers that are newly introduced (e.g. by a quantifier) | 
| 2620 |  | % Lists: A list of lists in the expression, to prevent infinite loops when having variable parts | 
| 2621 |  | % Constant: A part of the expression that is not a sub-expression (e.g. the number in integer(...)) | 
| 2622 |  | % Type: Fundamental type of the element (predicate, expression, etc) | 
| 2623 |  |  | 
| 2624 |  | % predicates | 
| 2625 |  | syntaxelement(truth,                 [],   [], [], [], pred). | 
| 2626 |  | syntaxelement(falsity,               [],   [], [], [], pred). | 
| 2627 |  | syntaxelement(unknown_truth_value(Msg),[],   [], [], Msg, pred). % artificial, e.g., created by well_def_analyser | 
| 2628 |  | syntaxelement(conjunct(A,B),         [A,B],[], [], [], pred). | 
| 2629 |  | %syntaxelement(conjunct(As),          As,   [], [], [], pred). % TO DO: support associative version of conjunct | 
| 2630 |  | syntaxelement(negation(A),           [A],  [], [], [], pred). | 
| 2631 |  | syntaxelement(disjunct(A,B),         [A,B],[], [], [], pred). | 
| 2632 |  | syntaxelement(implication(A,B),      [A,B],[], [], [], pred). | 
| 2633 |  | syntaxelement(equivalence(A,B),      [A,B],[], [], [], pred). | 
| 2634 |  | syntaxelement(equal(A,B),            [A,B],[], [], [], pred). | 
| 2635 |  | syntaxelement(not_equal(A,B),        [A,B],[], [], [], pred). | 
| 2636 |  | syntaxelement(member(A,B),           [A,B],[], [], [], pred). | 
| 2637 |  | syntaxelement(not_member(A,B),       [A,B],[], [], [], pred). | 
| 2638 |  | syntaxelement(subset(A,B),           [A,B],[], [], [], pred). | 
| 2639 |  | syntaxelement(subset_strict(A,B),    [A,B],[], [], [], pred). | 
| 2640 |  | syntaxelement(not_subset(A,B),       [A,B],[], [], [], pred). | 
| 2641 |  | syntaxelement(not_subset_strict(A,B),[A,B],[], [], [], pred). | 
| 2642 |  | syntaxelement(less_equal(A,B),       [A,B],[], [], [], pred). | 
| 2643 |  | syntaxelement(less(A,B),             [A,B],[], [], [], pred). | 
| 2644 |  | syntaxelement(less_equal_real(A,B),  [A,B],[], [], [], pred). | 
| 2645 |  | syntaxelement(less_real(A,B),        [A,B],[], [], [], pred). | 
| 2646 |  | syntaxelement(greater_equal(A,B),    [A,B],[], [], [], pred). | 
| 2647 |  | syntaxelement(greater(A,B),          [A,B],[], [], [], pred). | 
| 2648 |  | syntaxelement(forall(Ids,D,P),       [D,P|Ids],Ids,[Ids], [], pred). | 
| 2649 |  | syntaxelement(exists(Ids,P),         [P|Ids],  Ids,[Ids], [], pred). | 
| 2650 |  | syntaxelement(finite(A),             [A],  [], [], [], pred/only_typecheck). | 
| 2651 |  | syntaxelement(partition(S,Es),       [S|Es],[],[Es],[],pred). | 
| 2652 |  | syntaxelement(kodkod(PId,Ids),       Ids,[],[Ids],PId, pred). | 
| 2653 |  | syntaxelement(external_pred_call(F,Args),Args,[],[Args],F,pred). | 
| 2654 |  |  | 
| 2655 |  | % expressions | 
| 2656 |  | syntaxelement(value(V),                [],   [], [], V,  expr). | 
| 2657 |  | syntaxelement(operation_call_in_expr(Id,As), As, [], [As], Id, expr). % Do not treat Id as a sub-expression for find_identifier_uses, ... | 
| 2658 |  | %syntaxelement(operation_call_in_expr(Id,As), [Id|As], [], [As], [], expr). % was like this, but changed to avoid op(.) ids in find_identifier_uses | 
| 2659 |  | syntaxelement(boolean_true,            [],   [], [], [], expr). | 
| 2660 |  | syntaxelement(boolean_false,           [],   [], [], [], expr). | 
| 2661 |  | syntaxelement(max_int,                 [],   [], [], [], expr). | 
| 2662 |  | syntaxelement(min_int,                 [],   [], [], [], expr). | 
| 2663 |  | syntaxelement(empty_set,               [],   [], [], [], expr). | 
| 2664 |  | syntaxelement(bool_set,                [],   [], [], [], expr). | 
| 2665 |  | syntaxelement(float_set,                [],   [], [], [], expr). | 
| 2666 |  | syntaxelement(real(I),                 [],   [], [], I,  expr). | 
| 2667 |  | syntaxelement(real_set,                [],   [], [], [], expr). | 
| 2668 |  | syntaxelement(string_set,              [],   [], [], [], expr). | 
| 2669 |  | syntaxelement(convert_bool(A),         [A],  [], [], [], expr). | 
| 2670 |  | syntaxelement(convert_real(A),         [A],  [], [], [], expr). | 
| 2671 |  | syntaxelement(convert_int_floor(A),    [A],  [], [], [], expr). | 
| 2672 |  | syntaxelement(convert_int_ceiling(A),  [A],  [], [], [], expr). | 
| 2673 |  | syntaxelement(add(A,B),                [A,B],[], [], [], expr). | 
| 2674 |  | syntaxelement(add_real(A,B),           [A,B],[], [], [], expr). | 
| 2675 |  | syntaxelement(minus(A,B),              [A,B],[], [], [], expr). | 
| 2676 |  | syntaxelement(minus_real(A,B),         [A,B],[], [], [], expr). | 
| 2677 |  | syntaxelement(minus_or_set_subtract(A,B),[A,B],[], [], [], expr/only_typecheck). | 
| 2678 |  | syntaxelement(unary_minus(A),          [A],  [], [], [], expr). | 
| 2679 |  | syntaxelement(unary_minus_real(A),     [A],  [], [], [], expr). | 
| 2680 |  | syntaxelement(multiplication(A,B),     [A,B],[], [], [], expr). | 
| 2681 |  | syntaxelement(multiplication_real(A,B),[A,B],[], [], [], expr). | 
| 2682 |  | syntaxelement(mult_or_cart(A,B),       [A,B],[], [], [], expr/only_typecheck). | 
| 2683 |  | syntaxelement(cartesian_product(A,B),  [A,B],[], [], [], expr). | 
| 2684 |  | syntaxelement(div(A,B),                [A,B],[], [], [], expr). | 
| 2685 |  | syntaxelement(div_real(A,B),           [A,B],[], [], [], expr). | 
| 2686 |  | syntaxelement(floored_div(A,B),        [A,B],[], [], [], expr). | 
| 2687 |  | syntaxelement(modulo(A,B),             [A,B],[], [], [], expr). | 
| 2688 |  | syntaxelement(power_of(A,B),           [A,B],[], [], [], expr). | 
| 2689 |  | syntaxelement(power_of_real(A,B),      [A,B],[], [], [], expr). | 
| 2690 |  | syntaxelement(successor,               [],   [], [], [], expr). | 
| 2691 |  | syntaxelement(predecessor,             [],   [], [], [], expr). | 
| 2692 |  | syntaxelement(max(A),                  [A],  [], [], [], expr). | 
| 2693 |  | syntaxelement(max_real(A),             [A],  [], [], [], expr). | 
| 2694 |  | syntaxelement(min(A),                  [A],  [], [], [], expr). | 
| 2695 |  | syntaxelement(min_real(A),             [A],  [], [], [], expr). | 
| 2696 |  | syntaxelement(card(A),                 [A],  [], [], [], expr). | 
| 2697 |  | syntaxelement(couple(A,B),             [A,B],[], [], [], expr). | 
| 2698 |  | syntaxelement(pow_subset(A),           [A],  [], [], [], expr). | 
| 2699 |  | syntaxelement(pow1_subset(A),          [A],  [], [], [], expr). | 
| 2700 |  | syntaxelement(fin_subset(A),           [A],  [], [], [], expr). | 
| 2701 |  | syntaxelement(fin1_subset(A),          [A],  [], [], [], expr). | 
| 2702 |  | syntaxelement(interval(A,B),           [A,B],[], [], [], expr). | 
| 2703 |  | syntaxelement(union(A,B),              [A,B],[], [], [], expr). | 
| 2704 |  | syntaxelement(intersection(A,B),       [A,B],[], [], [], expr). | 
| 2705 |  | syntaxelement(set_subtraction(A,B),    [A,B],[], [], [], expr). | 
| 2706 |  | syntaxelement(general_union(A),        [A],  [], [], [], expr). | 
| 2707 |  | syntaxelement(general_intersection(A), [A] , [], [], [], expr). | 
| 2708 |  | syntaxelement(relations(A,B),          [A,B],[], [], [], expr). | 
| 2709 |  | syntaxelement(identity(A),             [A],  [], [], [], expr). | 
| 2710 |  | syntaxelement(event_b_identity,        [],  [], [], [], expr). % for Rodin 1.0, TO DO: Daniel please check | 
| 2711 |  | syntaxelement(reverse(A),              [A],  [], [], [], expr). | 
| 2712 |  | syntaxelement(first_projection(A,B),   [A,B],[], [], [], expr/only_typecheck). | 
| 2713 |  | syntaxelement(first_of_pair(A),        [A],  [], [], [], expr). | 
| 2714 |  | syntaxelement(event_b_first_projection(A),[A],  [], [], [], expr/only_typecheck). | 
| 2715 |  | syntaxelement(event_b_first_projection_v2,[],  [], [], [], expr/only_typecheck). % for Rodin 1.0, TO DO: Daniel please check | 
| 2716 |  | syntaxelement(second_projection(A,B),  [A,B],[], [], [], expr/only_typecheck). | 
| 2717 |  | syntaxelement(event_b_second_projection_v2,[],  [], [], [], expr/only_typecheck). % for Rodin 1.0, TO DO: Daniel please check | 
| 2718 |  | syntaxelement(second_of_pair(A),       [A],  [], [], [], expr). | 
| 2719 |  | syntaxelement(event_b_second_projection(A),[A],  [], [], [], expr/only_typecheck). | 
| 2720 |  | syntaxelement(composition(A,B),        [A,B],[], [], [], expr). | 
| 2721 |  | syntaxelement(ring(A,B),               [A,B],[], [], [], expr/only_typecheck). | 
| 2722 |  | syntaxelement(direct_product(A,B),     [A,B],[], [], [], expr). | 
| 2723 |  | syntaxelement(parallel_product(A,B),   [A,B],[], [], [], expr). | 
| 2724 |  | syntaxelement(trans_function(A),       [A],  [], [], [], expr). | 
| 2725 |  | syntaxelement(trans_relation(A),       [A],  [], [], [], expr). | 
| 2726 |  | syntaxelement(iteration(A,B),          [A,B],[], [], [], expr). | 
| 2727 |  | syntaxelement(reflexive_closure(A),    [A],  [], [], [], expr). | 
| 2728 |  | syntaxelement(closure(A),              [A],  [], [], [], expr). | 
| 2729 |  | syntaxelement(domain(A),               [A],  [], [], [], expr). | 
| 2730 |  | syntaxelement(range(A),                [A],  [], [], [], expr). | 
| 2731 |  | syntaxelement(image(A,B),              [A,B],[], [], [], expr). | 
| 2732 |  | syntaxelement(domain_restriction(A,B), [A,B],[], [], [], expr). | 
| 2733 |  | syntaxelement(domain_subtraction(A,B), [A,B],[], [], [], expr). | 
| 2734 |  | syntaxelement(range_restriction(A,B),  [A,B],[], [], [], expr). | 
| 2735 |  | syntaxelement(range_subtraction(A,B), [A,B],[], [], [], expr). | 
| 2736 |  | syntaxelement(overwrite(A,B),          [A,B],[], [], [], expr). | 
| 2737 |  | syntaxelement(partial_function(A,B),   [A,B],[], [], [], expr). | 
| 2738 |  | syntaxelement(total_function(A,B),     [A,B],[], [], [], expr). | 
| 2739 |  | syntaxelement(partial_injection(A,B),  [A,B],[], [], [], expr). | 
| 2740 |  | syntaxelement(total_injection(A,B),    [A,B],[], [], [], expr). | 
| 2741 |  | syntaxelement(partial_surjection(A,B), [A,B],[], [], [], expr). | 
| 2742 |  | syntaxelement(total_surjection(A,B),   [A,B],[], [], [], expr). | 
| 2743 |  | syntaxelement(total_bijection(A,B),    [A,B],[], [], [], expr). | 
| 2744 |  | syntaxelement(partial_bijection(A,B),  [A,B],[], [], [], expr). | 
| 2745 |  | syntaxelement(total_relation(A,B),     [A,B],[], [], [], expr). | 
| 2746 |  | syntaxelement(surjection_relation(A,B),[A,B],[], [], [], expr). | 
| 2747 |  | syntaxelement(total_surjection_relation(A,B),[A,B],[], [], [], expr). | 
| 2748 |  | syntaxelement(seq(A),                  [A],  [], [], [], expr). | 
| 2749 |  | syntaxelement(seq1(A),                 [A],  [], [], [], expr). | 
| 2750 |  | syntaxelement(iseq(A),                 [A],  [], [], [], expr). | 
| 2751 |  | syntaxelement(iseq1(A),                [A],  [], [], [], expr). | 
| 2752 |  | syntaxelement(perm(A),                 [A],  [], [], [], expr). | 
| 2753 |  | syntaxelement(empty_sequence,          [],   [], [], [], expr). | 
| 2754 |  | syntaxelement(size(A),                 [A],  [], [], [], expr). | 
| 2755 |  | syntaxelement(first(A),                [A],  [], [], [], expr). | 
| 2756 |  | syntaxelement(last(A),                 [A],  [], [], [], expr). | 
| 2757 |  | syntaxelement(front(A),                [A],  [], [], [], expr). | 
| 2758 |  | syntaxelement(tail(A),                 [A],  [], [], [], expr). | 
| 2759 |  | syntaxelement(rev(A),                  [A],  [], [], [], expr). | 
| 2760 |  | syntaxelement(concat(A,B),             [A,B],[], [], [], expr). | 
| 2761 |  | syntaxelement(insert_front(A,B),       [A,B],[], [], [], expr). | 
| 2762 |  | syntaxelement(insert_tail(A,B),        [A,B],[], [], [], expr). | 
| 2763 |  | syntaxelement(restrict_front(A,B),     [A,B],[], [], [], expr). | 
| 2764 |  | syntaxelement(restrict_tail(A,B),      [A,B],[], [], [], expr). | 
| 2765 |  | syntaxelement(general_concat(A),       [A],  [], [], [], expr). | 
| 2766 |  | syntaxelement(function(A,B),           [A,B],[], [], [], expr). | 
| 2767 |  | syntaxelement(external_function_call(F,Args),Args,[],[Args],F,expr). | 
| 2768 |  | syntaxelement(identifier(I),           [],   [], [], I,  expr). | 
| 2769 |  | syntaxelement(lazy_lookup_expr(I),           [],   [], [], I,  expr). | 
| 2770 |  | syntaxelement(lazy_lookup_pred(I),           [],   [], [], I,  pred). | 
| 2771 |  | syntaxelement(integer(I),              [],   [], [], I,  expr). | 
| 2772 |  | syntaxelement(integer_set(T),          [],   [], [], T,  expr). | 
| 2773 |  | syntaxelement(string(S),               [],   [], [], S,  expr). | 
| 2774 |  | syntaxelement(set_extension(L),        L,    [], [L], [], expr). | 
| 2775 |  | syntaxelement(sequence_extension(L),   L,    [], [L], [], expr). | 
| 2776 |  | syntaxelement(comprehension_set(Ids,P),[P|Ids],  Ids,[Ids], [], expr). | 
| 2777 |  | syntaxelement(event_b_comprehension_set(Ids,E,P),[E,P|Ids],  Ids,[Ids], [], expr/only_typecheck). | 
| 2778 |  | syntaxelement(lambda(Ids,P,E),         [P,E|Ids],Ids,[Ids], [], expr). | 
| 2779 |  | syntaxelement(general_sum(Ids,P,E),             [P,E|Ids],Ids,[Ids], [], expr). | 
| 2780 |  | syntaxelement(general_product(Ids,P,E),         [P,E|Ids],Ids,[Ids], [], expr). | 
| 2781 |  | syntaxelement(quantified_union(Ids,P,E),        [P,E|Ids],Ids,[Ids], [], expr). | 
| 2782 |  | syntaxelement(quantified_intersection(Ids,P,E), [P,E|Ids],Ids,[Ids], [], expr). | 
| 2783 |  | syntaxelement(struct(Rec), [Rec], [], [], [], expr). | 
| 2784 |  | syntaxelement(rec(Fields), FContent, [], [FContent], FNames, expr) :- syntaxfields(Fields,FContent, FNames). | 
| 2785 |  | syntaxelement(record_field(R,I), [R], [], [], I, expr). | 
| 2786 |  | syntaxelement(assertion_expression(Cond,ErrMsg,Expr), [Cond,Expr], [], [], ErrMsg, expr). | 
| 2787 |  | syntaxelement(typeset, [], [], [], [], expr/only_typecheck). | 
| 2788 |  |  | 
| 2789 |  | syntaxelement(tree(A),                 [A],  [], [], [], expr). | 
| 2790 |  | syntaxelement(btree(A),                [A],  [], [], [], expr). | 
| 2791 |  | syntaxelement(const(A,B),              [A,B],[], [], [], expr). | 
| 2792 |  | syntaxelement(top(A),                  [A],  [], [], [], expr). | 
| 2793 |  | syntaxelement(sons(A),                 [A],  [], [], [], expr). | 
| 2794 |  | syntaxelement(prefix(A),               [A],  [], [], [], expr). | 
| 2795 |  | syntaxelement(postfix(A),              [A],  [], [], [], expr). | 
| 2796 |  | syntaxelement(sizet(A),                [A],  [], [], [], expr). | 
| 2797 |  | syntaxelement(mirror(A),               [A],  [], [], [], expr). | 
| 2798 |  | syntaxelement(rank(A,B),               [A,B],[], [], [], expr). | 
| 2799 |  | syntaxelement(father(A,B),             [A,B],[], [], [], expr). | 
| 2800 |  | syntaxelement(son(A,B,C),              [A,B,C],[], [], [], expr). | 
| 2801 |  | syntaxelement(subtree(A,B),            [A,B],[], [], [], expr). | 
| 2802 |  | syntaxelement(arity(A,B),              [A,B],[], [], [], expr). | 
| 2803 |  | syntaxelement(bin(A),                  [A],[], [], [], expr). | 
| 2804 |  | syntaxelement(bin(A,B,C),              [A,B,C],[], [], [], expr). | 
| 2805 |  | syntaxelement(infix(A),                [A],  [], [], [], expr). | 
| 2806 |  | syntaxelement(left(A),                 [A],  [], [], [], expr). | 
| 2807 |  | syntaxelement(right(A),                [A],  [], [], [], expr). | 
| 2808 |  |  | 
| 2809 |  | % substitutions | 
| 2810 |  | syntaxelement(skip,                    [],   [], [], [], subst). | 
| 2811 |  | syntaxelement(precondition(A,B),       [A,B],[], [], [], subst). | 
| 2812 |  | syntaxelement(assertion(A,B),          [A,B],[], [], [], subst). | 
| 2813 |  | syntaxelement(witness_then(A,B),       [A,B],[], [], [], subst). | 
| 2814 |  | syntaxelement(if_elsif(A,B),           [A,B],[], [], [], subst/elsif). | 
| 2815 |  | syntaxelement(while(A,B,C,D),          [A,B,C,D],[], [], [], subst). | 
| 2816 |  | % used only internally in the interpreter, contains last value of variant: | 
| 2817 |  | syntaxelement(while1(A,B,C,D,E),          [A,B,C,D],[], [], E, subst). | 
| 2818 |  | syntaxelement(select_when(A,B),        [A,B],[], [], [], subst/when). | 
| 2819 |  | syntaxelement(block(S),[S],[],[],[], subst/only_typecheck). | 
| 2820 |  | syntaxelement(assign(Lhs,Rhs),Exprs,[],[Lhs,Rhs], [], subst) :- append(Lhs,Rhs,Exprs). | 
| 2821 |  | syntaxelement(assign_single_id(Id,Rhs),[Id,Rhs],[],[], [], subst). | 
| 2822 |  | syntaxelement(any(Ids,P,S),[P,S|Ids],Ids,[Ids], [], subst). | 
| 2823 |  | syntaxelement(var(Ids,S),  [S|Ids],  Ids,[Ids], [], subst). | 
| 2824 |  | syntaxelement(if(Ifs),   Ifs,  [], [Ifs], [], subst). | 
| 2825 |  | syntaxelement(parallel(Ss), Ss, [], [Ss], [], subst). | 
| 2826 |  | syntaxelement(sequence(Ss), Ss, [], [Ss], [], subst). | 
| 2827 |  | syntaxelement(becomes_element_of(Ids,E), [E|Ids], [], [Ids], [], subst). | 
| 2828 |  | syntaxelement(becomes_such(Ids,P), [P|Ids], [], [Ids], [], subst).  % Ids are new value, Ids$0 is old value | 
| 2829 |  | syntaxelement(evb2_becomes_such(Ids,P), [P|Ids], [], [Ids], [], subst/only_typecheck). | 
| 2830 |  | syntaxelement(let(Ids,P,S), [P,S|Ids], Ids, [Ids], [], subst). | 
| 2831 |  | syntaxelement(operation_call(Id,Rs,As), [Id|Exprs], [], [Rs,As], [], subst) :- append(Rs,As,Exprs). | 
| 2832 |  | syntaxelement(case(E,Eithers,Else), [E,Else|Eithers], [], [Eithers], [], subst). | 
| 2833 |  | syntaxelement(case_or(Es,S), [S|Es], [], [Es], [], subst/caseor). | 
| 2834 |  | syntaxelement(choice(Ss), Ss, [], [Ss], [], subst). | 
| 2835 |  | syntaxelement(select(Whens), Whens, [], [Whens], [], subst). | 
| 2836 |  | syntaxelement(select(Whens,Else), [Else|Whens], [], [Whens], [], subst). | 
| 2837 |  | syntaxelement(operation(I,Rs,As,B), [I,B|Ids], Ids, [Rs,As], [], subst) :- append(Rs,As,Ids). | 
| 2838 |  | syntaxelement(external_subst_call(F,Args),Args,[],[Args],F,subst). | 
| 2839 |  |  | 
| 2840 |  | % elements of a VALUES clause | 
| 2841 |  | syntaxelement(values_entry(I,E),[I,E],[],[],[],values_entry). | 
| 2842 |  |  | 
| 2843 |  | % syntax for Event-B events | 
| 2844 |  | syntaxelement(rlevent(I,Sec,St,Ps,G,Ts,As,VWs,PWs,Ums,Rs), Subs, [], [Ps,Ts,As,VWs,PWs,Ums,Rs], [I,Sec], subst) :- | 
| 2845 |  | append([[St],Ps,[G],Ts,As,VWs,PWs,Ums,Rs],Subs). | 
| 2846 |  | syntaxelement(witness(I,P), [I,P], [], [], [], witness). | 
| 2847 |  |  | 
| 2848 |  | % extended syntax for Z | 
| 2849 |  | syntaxelement(let_predicate(Ids,As,Pred),  Exprs, Ids, [Ids,As], [], pred) :- append([Ids,As,[Pred]],Exprs). | 
| 2850 |  | syntaxelement(let_expression(Ids,As,Expr), Exprs, Ids, [Ids,As], [], expr) :- append([Ids,As,[Expr]],Exprs). | 
| 2851 |  | syntaxelement(let_expression_global(Ids,As,Expr), Exprs, Ids, [Ids,As], [], expr) :-  % version used by b_compiler | 
| 2852 |  | append([Ids,As,[Expr]],Exprs). | 
| 2853 |  | syntaxelement(lazy_let_expr(TID,A,Expr),  [TID, A, Expr], [TID], [[TID],[A]], [], expr). | 
| 2854 |  | syntaxelement(lazy_let_pred(TID,A,Expr),  [TID, A, Expr], [TID], [[TID],[A]], [], pred). | 
| 2855 |  | syntaxelement(lazy_let_subst(TID,A,Expr), [TID, A, Expr], [TID], [[TID],[A]], [], subst). | 
| 2856 |  | syntaxelement(if_then_else(If,Then,Else),[If,Then,Else], [], [], [], expr). | 
| 2857 |  | syntaxelement(compaction(A), [A],  [], [], [], expr). | 
| 2858 |  | syntaxelement(mu(A),         [A],  [], [], [], expr). | 
| 2859 |  | syntaxelement(bag_items(A),  [A],  [], [], [], expr). | 
| 2860 |  |  | 
| 2861 |  | syntaxelement(freetype_set(Id), [], [], [], Id, expr). | 
| 2862 |  | syntaxelement(freetype_case(Type,Case,Expr), [Expr], [], [], [Type,Case], pred). | 
| 2863 |  | syntaxelement(freetype_constructor(Type,Case,Expr), [Expr], [], [], [Type,Case], expr). | 
| 2864 |  | syntaxelement(freetype_destructor(Type,Case,Expr), [Expr], [], [], [Type,Case], expr). | 
| 2865 |  |  | 
| 2866 |  | syntaxelement(ordinary,    [], [], [], [], status). | 
| 2867 |  | syntaxelement(anticipated(Variant), [Variant], [], [], [], status). | 
| 2868 |  | syntaxelement(convergent(Variant),  [Variant], [], [], [], status). | 
| 2869 |  |  | 
| 2870 |  | % Just one ID expected | 
| 2871 |  | syntaxelement(recursive_let(Id,C),[Id,C],[Id],[],[], expr). % Note: Id is not really introduced ! | 
| 2872 |  |  | 
| 2873 |  |  | 
| 2874 |  | % fields of records | 
| 2875 |  | %syntaxfields(Fields,C,_) :- var(Fields),var(C),var(N),!, add_internal_error('Illegal call: ',syntaxfields(Fields,C,N)),fail. | 
| 2876 |  | syntaxfields([],[],[]). | 
| 2877 |  | syntaxfields([field(N,C)|Rest],[C|CRest],[N|NRest]) :- syntaxfields(Rest,CRest,NRest). | 
| 2878 |  |  | 
| 2879 |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
| 2880 |  | % helper for declaration of quantified identifiers | 
| 2881 |  |  | 
| 2882 |  | % has_declared_identifier/2 returns a list of identifiers which are declared in | 
| 2883 |  | % this AST node. The main difference to the Names variable when doing a | 
| 2884 |  | % syntaxtraversion/6 or similiar is that the identifiers are described by | 
| 2885 |  | % predicates. | 
| 2886 |  | has_declared_identifier(TExpr,Ids) :- | 
| 2887 |  | get_texpr_expr(TExpr,Expr), | 
| 2888 |  | ( default_declaration(Expr,_,Ids,_) | 
| 2889 |  | ; non_default_declaration(Expr,Ids)). | 
| 2890 |  |  | 
| 2891 |  | add_declaration_for_identifier(b(Expr,Type,Infos),Decl,b(NExpr,Type,NewInfos)) :- | 
| 2892 |  | %delete(Infos,used_ids(_),NewInfos), % we cannot | 
| 2893 |  | ( default_declaration(Expr,Predicate,Ids,Constant) -> | 
| 2894 |  | same_functor(Expr,NExpr), | 
| 2895 |  | conjunct_predicates([Decl,Predicate],NPredicate), | 
| 2896 |  | default_declaration(NExpr,NPredicate,Ids,Constant) | 
| 2897 |  | ; non_default_declaration(Expr,Ids) -> | 
| 2898 |  | add_non_default_declaration(Expr,Decl,NExpr) | 
| 2899 |  | ), | 
| 2900 |  | add_used_ids(Infos,Ids,Decl,NewInfos). | 
| 2901 |  |  | 
| 2902 |  | % add used ids of a predicate within quantification of Ids to current used_ids info; if it is there | 
| 2903 |  | add_used_ids(Infos,Ids,Pred,NewInfos) :- update_used_ids(Infos,OldUsed,NewInfos,NewUsed), | 
| 2904 |  | !, % a field needs updating | 
| 2905 |  | find_identifier_uses(Pred,[],NewIds), get_texpr_ids(Ids,UnsortedIds),sort(UnsortedIds,SIds), | 
| 2906 |  | ord_subtract(NewIds,SIds,NewIds2), | 
| 2907 |  | ord_union(NewIds2,OldUsed,NewUsed). | 
| 2908 |  | add_used_ids(I,_,_,I). | 
| 2909 |  |  | 
| 2910 |  | % just update used_ids field (e.g., when just computed to store it for later) | 
| 2911 |  | update_used_ids(Infos,OldUsed,NewInfos,NewUsed) :- select(OldInfo,Infos,I1), | 
| 2912 |  | used_ids_like_info(OldInfo,F,OldUsed),!, | 
| 2913 |  | used_ids_like_info(NewInfo,F,NewUsed),NewInfos = [NewInfo|I1]. | 
| 2914 |  |  | 
| 2915 |  | % info fields which contain used_ids information | 
| 2916 |  | used_ids_like_info(used_ids(UsedIds),used_ids,UsedIds). | 
| 2917 |  | used_ids_like_info(reads(UsedIds),reads,UsedIds). | 
| 2918 |  |  | 
| 2919 |  | :- use_module(probsrc(btypechecker), [prime_identifiers/2]). | 
| 2920 |  |  | 
| 2921 |  | % default_declaration(Expr,Predicate,Ids,Constant) | 
| 2922 |  | default_declaration(forall(Ids,D,P),D,Ids,P). | 
| 2923 |  | default_declaration(exists(Ids,P),P,Ids,[]). | 
| 2924 |  | default_declaration(comprehension_set(Ids,P),P,Ids,[]). | 
| 2925 |  | default_declaration(event_b_comprehension_set(Ids,E,P),P,Ids,E). % translated !? | 
| 2926 |  | default_declaration(lambda(Ids,P,E),P,Ids,E). | 
| 2927 |  | default_declaration(general_sum(Ids,P,E),P,Ids,E). | 
| 2928 |  | default_declaration(general_product(Ids,P,E),P,Ids,E). | 
| 2929 |  | default_declaration(quantified_union(Ids,P,E),P,Ids,E). | 
| 2930 |  | default_declaration(quantified_intersection(Ids,P,E),P,Ids,E). | 
| 2931 |  | default_declaration(any(Ids,P,S),P,Ids,S). | 
| 2932 |  | default_declaration(becomes_such(Ids,P),P,Ids,[]). | 
| 2933 |  | default_declaration(evb2_becomes_such(Ids,P),P,Primed,[]) :- | 
| 2934 |  | nl,print(evb2(Ids,Primed)),nl,nl, % no longer used, as it is translated to becomes_such | 
| 2935 |  | prime_identifiers(Ids,Primed). | 
| 2936 |  | default_declaration(rlevent(I,Sec,St,Ps,G,Ts,As,VWs,PWs,Ums,Rs),G,Ps, | 
| 2937 |  | [I,Sec,St,Ps,Ts,As,VWs,PWs,Ums,Rs]). | 
| 2938 |  | default_declaration(let_predicate(Ids,Ps,Body),Ps,Ids,Body) :- print(let(Ids)),nl. % TODO: check format of Ps | 
| 2939 |  | default_declaration(let_expression(Ids,Ps,Body),Ps,Ids,Body) :- print(let(Ids)),nl. % TODO: check format of Ps | 
| 2940 |  | default_declaration(let_expression_global(Ids,Ps,Body),Ps,Ids,Body) :- print(let(Ids)),nl. % TODO: check format of Ps | 
| 2941 |  | % TODO: lazy let  ? | 
| 2942 |  |  | 
| 2943 |  | non_default_declaration(operation(_I,Rs,As,_TBody),Ids) :- | 
| 2944 |  | append(Rs,As,Ids). | 
| 2945 |  |  | 
| 2946 |  | add_non_default_declaration(operation(I,Rs,As,TBody),Decl,operation(I,Rs,As,NTBody)) :- | 
| 2947 |  | ( get_guard_and_copy(TBody,P,NP,NTBody) -> | 
| 2948 |  | conjunct_predicates([Decl,P],NP) | 
| 2949 |  | ;   create_texpr(precondition(Decl,TBody),subst,[],NTBody)). | 
| 2950 |  |  | 
| 2951 |  | get_guard_and_copy(TBody,P,NP,NTBody) :- remove_bt(TBody,Body,NBody,NTBody), | 
| 2952 |  | get_guard_copy2(Body,P,NP,NBody). | 
| 2953 |  |  | 
| 2954 |  | get_guard_copy2(precondition(P,S),P,NP,precondition(NP,S)). | 
| 2955 |  | get_guard_copy2(rlevent(I,Sec,St,Ps, G,Ts,As,VWs,PWs,Ums,Rs), G, NG, | 
| 2956 |  | rlevent(I,Sec,St,Ps,NG,Ts,As,VWs,PWs,Ums,Rs)). | 
| 2957 |  |  | 
| 2958 |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
| 2959 |  | % pattern definitions (not yet finished) | 
| 2960 |  |  | 
| 2961 |  | bsyntax_pattern(Expr,TExpr) :- | 
| 2962 |  | var(Expr),!,Expr=TExpr. | 
| 2963 |  | bsyntax_pattern(-Expr,TExpr) :- | 
| 2964 |  | !,remove_all_infos(Expr,TExpr). | 
| 2965 |  | bsyntax_pattern(Expr,TExpr) :- | 
| 2966 |  | functor(Expr,b,3),!,Expr=TExpr. | 
| 2967 |  | bsyntax_pattern(Expr:Type/Info,TExpr) :- | 
| 2968 |  | !,bsyntax_pattern2(Expr,Type,Info,TExpr). | 
| 2969 |  | bsyntax_pattern(Expr:Type,TExpr) :- | 
| 2970 |  | !,bsyntax_pattern2(Expr,Type,_Info,TExpr). | 
| 2971 |  | bsyntax_pattern(Expr/Info,TExpr) :- | 
| 2972 |  | !,bsyntax_pattern2(Expr,_Type,Info,TExpr). | 
| 2973 |  | bsyntax_pattern(Expr,TExpr) :- | 
| 2974 |  | !,bsyntax_pattern2(Expr,_Type,_Info,TExpr). | 
| 2975 |  |  | 
| 2976 |  | bsyntax_pattern2(Pattern,Type,Info,TExpr) :- | 
| 2977 |  | functor(Pattern,Functor,Arity), | 
| 2978 |  | functor(R,Functor,Arity), | 
| 2979 |  | create_texpr(R,Type,Info,TExpr), | 
| 2980 |  | syntaxelement(Pattern,PSubs,_,PLists,Const,EType), | 
| 2981 |  | syntaxelement(R,RSubs,_,RLists,Const,EType), | 
| 2982 |  | ( EType==pred -> Type=pred | 
| 2983 |  | ; EType==subst -> Type=subst | 
| 2984 |  | ; true), | 
| 2985 |  | all_same_length(PLists,RLists), | 
| 2986 |  | maplist(bsyntax_pattern,PSubs,RSubs). | 
| 2987 |  |  | 
| 2988 |  | all_same_length([],[]). | 
| 2989 |  | all_same_length([A|Arest],[B|Brest]) :- | 
| 2990 |  | ( var(A),var(B) -> | 
| 2991 |  | add_error_fail(bsyntaxtree,'At least one list should contain nonvar elements for all_same_length',[A,B]) | 
| 2992 |  | ; | 
| 2993 |  | same_length(A,B)), | 
| 2994 |  | all_same_length(Arest,Brest). | 
| 2995 |  |  | 
| 2996 |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
| 2997 |  | % strip an AST into a more compact form (without b/3 terms) | 
| 2998 |  |  | 
| 2999 |  | strip_and_norm_ast(TExpr,SNExpr) :- | 
| 3000 |  | get_texpr_expr(TExpr,Expr), | 
| 3001 |  | strip_and_norm_ast_aux(Expr,SNExpr). | 
| 3002 |  |  | 
| 3003 |  | :- use_module(tools,[safe_univ_no_cutoff/2]). | 
| 3004 |  | strip_and_norm_ast_aux(Expr,Res) :- | 
| 3005 |  | comm_assoc_subs(Expr,Op,Subs,[]), !, % associative & commutative operator detected | 
| 3006 |  | maplist(strip_and_norm_ast_aux,Subs,NSubs), % Subs are already unwrapped | 
| 3007 |  | sort(NSubs,Sorted), % in case there are associative operators that are not commutative: insert is_commutative check | 
| 3008 |  | safe_univ_no_cutoff(Res,[Op|Sorted]). | 
| 3009 |  | strip_and_norm_ast_aux(Expr,Res) :- | 
| 3010 |  | assoc_subs(Expr,Op,Subs,[]), !, % associative operator detected | 
| 3011 |  | maplist(strip_and_norm_ast_aux,Subs,NSubs), % Subs are already unwrapped | 
| 3012 |  | safe_univ_no_cutoff(Res,[Op|NSubs]). | 
| 3013 |  | strip_and_norm_ast_aux(Expr,SNExpr) :- | 
| 3014 |  | syntaxtransformation(Expr,Subs,_,NSubs,SExpr), | 
| 3015 |  | strip_and_norm_ast_l(Subs,NSubs), | 
| 3016 |  | norm_strip(SExpr,SNExpr). | 
| 3017 |  |  | 
| 3018 |  | strip_and_norm_ast_l([],[]). | 
| 3019 |  | strip_and_norm_ast_l([TExpr|Trest],[NExpr|Nrest]) :- | 
| 3020 |  | strip_and_norm_ast(TExpr,NExpr), | 
| 3021 |  | strip_and_norm_ast_l(Trest,Nrest). | 
| 3022 |  |  | 
| 3023 |  | norm_strip(greater_equal(A,B),less_equal(B,A)) :- !. | 
| 3024 |  | norm_strip(greater(A,B),less(B,A)) :- !. | 
| 3025 |  | norm_strip(set_extension(NL),set_extension(SNL)) :- !, | 
| 3026 |  | sort(NL,SNL). | 
| 3027 |  | norm_strip(Old,New) :- | 
| 3028 |  | functor(Old,Functor,2), | 
| 3029 |  | is_commutative(Functor),!, | 
| 3030 |  | arg(1,Old,OA), | 
| 3031 |  | arg(2,Old,OB), | 
| 3032 |  | ( OA @> OB -> New =.. [Functor,OB,OA] | 
| 3033 |  | ; New=Old). | 
| 3034 |  | norm_strip(Old,Old). | 
| 3035 |  | % TO DO: flatten associative operators into lists ! | 
| 3036 |  |  | 
| 3037 |  | comm_assoc_subs(conjunct(TA,TB),conjunct) --> !, | 
| 3038 |  | {get_texpr_expr(TA,A), get_texpr_expr(TB,B)}, | 
| 3039 |  | comm_assoc_subs(A,conjunct), comm_assoc_subs(B,conjunct). | 
| 3040 |  | comm_assoc_subs(disjunct(TA,TB),disjunct) --> !, | 
| 3041 |  | {get_texpr_expr(TA,A), get_texpr_expr(TB,B)}, | 
| 3042 |  | comm_assoc_subs(A,disjunct), comm_assoc_subs(B,disjunct). | 
| 3043 |  | comm_assoc_subs(add(TA,TB),add) --> !, | 
| 3044 |  | {get_texpr_expr(TA,A), get_texpr_expr(TB,B)}, | 
| 3045 |  | comm_assoc_subs(A,add), comm_assoc_subs(B,add). | 
| 3046 |  | comm_assoc_subs(multiplication(TA,TB),multiplication) --> !, | 
| 3047 |  | {get_texpr_expr(TA,A), get_texpr_expr(TB,B)}, | 
| 3048 |  | comm_assoc_subs(A,multiplication), comm_assoc_subs(B,multiplication). | 
| 3049 |  | comm_assoc_subs(union(TA,TB),union) --> !, | 
| 3050 |  | {get_texpr_expr(TA,A), get_texpr_expr(TB,B)}, | 
| 3051 |  | comm_assoc_subs(A,union), comm_assoc_subs(B,union). | 
| 3052 |  | comm_assoc_subs(intersection(TA,TB),intersection) --> !, | 
| 3053 |  | {get_texpr_expr(TA,A), get_texpr_expr(TB,B)}, | 
| 3054 |  | comm_assoc_subs(A,intersection), comm_assoc_subs(B,intersection). | 
| 3055 |  | comm_assoc_subs(Expr,Op) --> {nonvar(Op)},[Expr]. % base case for other operators | 
| 3056 |  |  | 
| 3057 |  | % detect just associative operators | 
| 3058 |  | assoc_subs(concat(TA,TB),concat) --> !, | 
| 3059 |  | {get_texpr_expr(TA,A), get_texpr_expr(TB,B)}, | 
| 3060 |  | assoc_subs(A,concat), assoc_subs(B,concat). | 
| 3061 |  | assoc_subs(composition(TA,TB),composition) --> !, | 
| 3062 |  | {get_texpr_expr(TA,A), get_texpr_expr(TB,B)}, | 
| 3063 |  | assoc_subs(A,composition), assoc_subs(B,composition). | 
| 3064 |  | assoc_subs(Expr,Op) --> {nonvar(Op)},[Expr]. % base case for other operators | 
| 3065 |  |  | 
| 3066 |  | is_commutative(conjunct). | 
| 3067 |  | is_commutative(disjunct). | 
| 3068 |  | is_commutative(equivalence). | 
| 3069 |  | is_commutative(equal). | 
| 3070 |  | is_commutative(not_equal). | 
| 3071 |  | is_commutative(add). | 
| 3072 |  | is_commutative(multiplication). | 
| 3073 |  | is_commutative(union). | 
| 3074 |  | is_commutative(intersection). | 
| 3075 |  |  | 
| 3076 |  | % check if two type expressions are same modulo info fields and reordering of commutative operators | 
| 3077 |  | % same_texpr does not reorder wrt commutativity. | 
| 3078 |  | same_norm_texpr(TExpr1,TExpr2) :- | 
| 3079 |  | strip_and_norm_ast(TExpr1,N1), | 
| 3080 |  | strip_and_norm_ast(TExpr2,N1). | 
| 3081 |  |  | 
| 3082 |  |  | 
| 3083 |  | % small utility to get functor of texpr: | 
| 3084 |  | get_texpr_functor(b(E,_,_),F,N) :- !, functor(E,F,N). | 
| 3085 |  | get_texpr_functor(E,_,+) :- add_error_fail(get_texpr_functor,'Not a typed expression: ',E). | 
| 3086 |  |  | 
| 3087 |  | % ------------------------- | 
| 3088 |  |  | 
| 3089 |  | % check if a ProB type is a set type: | 
| 3090 |  | is_set_type(set(Type),Type). | 
| 3091 |  | is_set_type(seq(Type),couple(integer,Type)). | 
| 3092 |  | % should we have a rule for any ?? : in all cases using is_set_type any seems not possible; better that we generate error message in get_set_type or get_texpr_set_type | 
| 3093 |  | % is_set_type(any,any). | 
| 3094 |  |  | 
| 3095 |  | get_set_type(TypeX,Res) :- | 
| 3096 | ? | (is_set_type(TypeX,SetType) -> Res=SetType ; add_error_fail(get_set_type,'Not a set type: ',TypeX)). | 
| 3097 |  |  | 
| 3098 |  | get_texpr_set_type(X,Res) :- get_texpr_type(X,TypeX), | 
| 3099 |  | get_set_type(TypeX,Res). | 
| 3100 |  |  | 
| 3101 |  |  | 
| 3102 |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
| 3103 |  | % check if a set contains all elements of a type, i.e., maximal type | 
| 3104 |  | is_just_type(Expr) :- is_just_type(Expr,[]). | 
| 3105 |  | % is_just_type(+Expr,+RTT): | 
| 3106 |  | %  like is_just_type/1 but RTT is a list of identifiers (without type information) | 
| 3107 |  | %  of variables or constants that are known to be types, too. | 
| 3108 |  | %  E.g. is_just_type(a ** INTEGER) would fail but is_just_type(a ** INTEGER,[a]) would | 
| 3109 |  | %  succeed. | 
| 3110 |  | is_just_type(b(E,T,I),RTT) :- is_just_type3(E,T,I,RTT). | 
| 3111 |  |  | 
| 3112 |  |  | 
| 3113 |  | is_just_type3(identifier(G),SType,Infos,RefsToTypes) :- | 
| 3114 |  | nonvar(SType), SType = set(Type), nonvar(Type), | 
| 3115 |  | ( Type = global(G), | 
| 3116 |  | memberchk(given_set,Infos) % no accidental local variable G that hides global G | 
| 3117 |  | ; memberchk(G,RefsToTypes) -> true | 
| 3118 |  | %; Type = freetype(G), | 
| 3119 |  | %  memberchk(given_set,Infos) % no accidental local variable G that hides global G | 
| 3120 |  | % TODO: we do not know if the Freetype has restrictions (which are encoded in the PROPERTIES) | 
| 3121 |  | ),!. | 
| 3122 |  | is_just_type3(freetype_set(_),_,_,_). | 
| 3123 |  | is_just_type3(pow_subset(E),_,_,RTT) :- is_just_type(E,RTT). | 
| 3124 |  | is_just_type3(fin_subset(E),T,_,RTT) :- | 
| 3125 |  | is_finite_type_in_context(proving,T), % animation or proving | 
| 3126 |  | is_just_type(E,RTT). | 
| 3127 |  | is_just_type3(integer_set('INTEGER'),set(integer),_,_). | 
| 3128 |  | is_just_type3(bool_set,set(boolean),_,_). | 
| 3129 |  | is_just_type3(real_set,set(real),_,_). | 
| 3130 |  | is_just_type3(string_set,set(string),_,_). | 
| 3131 |  | is_just_type3(cartesian_product(A,B),_,_,RTT) :- | 
| 3132 |  | is_just_type(A,RTT),is_just_type(B,RTT). | 
| 3133 |  | is_just_type3(mult_or_cart(A,B),_,_,RTT) :-    % is_just_type/1 could be called before the cleanup | 
| 3134 |  | is_just_type(A,RTT),is_just_type(B,RTT).   % of an expression has finished | 
| 3135 |  | is_just_type3(relations(A,B),_,_,RTT) :- | 
| 3136 |  | is_just_type(A,RTT),is_just_type(B,RTT). | 
| 3137 |  | is_just_type3(struct(b(rec(Fields),_,_)),_,_,RTT) :- | 
| 3138 |  | maplist(field_is_just_type(RTT),Fields). | 
| 3139 |  | is_just_type3(typeset,_,_,_). | 
| 3140 |  | is_just_type3(comprehension_set(_,b(truth,_,_)),_,_,_). | 
| 3141 |  | is_just_type3(value(Val),ST,_,_) :-  is_set_type(ST,Type), is_maximal_value(Val,Type). % also see: quick_is_definitely_maximal_set(Val). | 
| 3142 |  |  | 
| 3143 |  | field_is_just_type(RTT,field(_,Set)) :- is_just_type(Set,RTT). | 
| 3144 |  |  | 
| 3145 |  | is_maximal_value(V,_) :- var(V),!,fail. | 
| 3146 |  | is_maximal_value(global_set(GS),Type) :-  (GS=='INTEGER' -> true ; Type==global(GS)). % we could call is_maximal_global_set(GS) or b_global_set (but requires compiled) | 
| 3147 |  |  | 
| 3148 |  | % Generate a custom matching / visitor predicate | 
| 3149 |  | % bsyntaxtree:gen_visitor(bexpr_variables_aux,bexpr_variables) | 
| 3150 |  | /* | 
| 3151 |  | gen_visitor(Pred, BodyPred) :- syntaxelement(Expr,SubsX,_NamesX,_Lists,_ConstantX,_), | 
| 3152 |  | print_clause(Pred,BodyPred,Expr,SubsX), | 
| 3153 |  | fail. | 
| 3154 |  | gen_visitor(Pred, BodyPred) :- nl. | 
| 3155 |  |  | 
| 3156 |  | print_clause(Pred,BodyPred,Expr,SubsX) :- E=..[Op|SubsX], format('~w(~w) :- ',[Pred,Expr]). | 
| 3157 |  | */ | 
| 3158 |  |  | 
| 3159 |  | /* | 
| 3160 |  | * create_recursive_compset(+Ids,+Cond,+Type,+Infos,-RecId,-TCompSet) | 
| 3161 |  | *  creates a recursive comprehension set: | 
| 3162 |  | *   Ids      is the list of the introduced typed identifiers | 
| 3163 |  | *   Cond     is the condition (a typed predicate) | 
| 3164 |  | *   Infos    are additional informations for the comprehension set syntax element | 
| 3165 |  | *   RecId    is the identifier (untyped, an atom) that can be used in Cond to refer to the | 
| 3166 |  | *            comprehension set recursively. Usually RecId is used in Cond as a variable | 
| 3167 |  | *   TCompSet is the generated recursive comprehension set, the recursion parameter is introduced | 
| 3168 |  | *            by a recusive(Id,CompSet) syntax element | 
| 3169 |  | */ | 
| 3170 |  | create_recursive_compset(Ids,Cond,Type,Infos,RecId,TCompSet) :- | 
| 3171 |  | unique_id("recursive.",RecId), | 
| 3172 |  | add_symbolic_annotation(Infos,RInfos), | 
| 3173 |  | create_texpr(comprehension_set(Ids,Cond),Type,RInfos,TCompSet1), | 
| 3174 |  | create_typed_id(RecId,Type,TRecId), | 
| 3175 |  | create_texpr(recursive_let(TRecId,TCompSet1),Type,[],TCompSet). | 
| 3176 |  |  | 
| 3177 |  | unique_typed_id(Prefix,Type,TId) :- | 
| 3178 |  | unique_id(Prefix,Id), | 
| 3179 |  | create_typed_id(Id,Type,TId). | 
| 3180 |  |  | 
| 3181 |  |  | 
| 3182 |  | mark_bexpr_as_symbolic(b(E,T,I),b(E2,T,RI)) :- | 
| 3183 |  | add_symbolic_annotation(I,RI), | 
| 3184 |  | mark_aux(E,E2). | 
| 3185 |  | mark_aux(union(A,B),R) :- !, R=union(SA,SB), | 
| 3186 |  | mark_bexpr_as_symbolic(A,SA), mark_bexpr_as_symbolic(B,SB). | 
| 3187 |  | % union is currently the only operator that is kept symbolically | 
| 3188 |  | mark_aux(A,A). | 
| 3189 |  |  | 
| 3190 |  | add_symbolic_annotation([H|I],R) :- H == prob_annotation('SYMBOLIC'),!, R=[H|I]. | 
| 3191 |  | add_symbolic_annotation(I,R) :- !, R=[prob_annotation('SYMBOLIC')|I]. | 
| 3192 |  |  | 
| 3193 |  | % identifier_sub_ast(+TExpr,+Identifier,-SubPosition): | 
| 3194 |  | % Find occurences of an identifier "Identifier" in an expression "TExpr" | 
| 3195 |  | % Returns a list of positions (beginning with 0) that describes the position of a sub-expression | 
| 3196 |  | % that contains all occurrences of Identifier in TExpr. | 
| 3197 |  | % E.g. [1,0,1] means "second sub-expression of TExpr, then the first sub-expression of that, | 
| 3198 |  | % then the second sub-expression of that". | 
| 3199 |  | % When an identifier has multiple occurences, the position of the sub-expression is returned | 
| 3200 |  | % where all occurences of it are located. | 
| 3201 |  | % If the identifier is not found, the call fails. | 
| 3202 |  | % Sub-expressions are meant like the ones syntaxtraversion or syntaxtransformation return. | 
| 3203 |  | identifier_sub_ast(TExpr,Identifier,SubPosition) :- | 
| 3204 |  | syntaxtraversion(TExpr,Expr,_Type,_Infos,AllSubs,Names), | 
| 3205 |  | identifier_sub_ast_aux(Expr,AllSubs,Names,Identifier,SubPosition). | 
| 3206 |  | identifier_sub_ast_aux(identifier(Identifier),[],[],Identifier,[]) :- !. | 
| 3207 |  | identifier_sub_ast_aux(_Expr,AllSubs,Names,Identifier,SubPosition) :- | 
| 3208 |  | get_texpr_id(TId,Identifier),nonmember(TId,Names), | 
| 3209 |  | % For each sub-expression E in the list AllSubs create a term Pos-E | 
| 3210 |  | % where Pos is E's position (starting with 0) in AllSubs | 
| 3211 |  | foldl(annotate_pos,AllSubs,AllAnnotatedSubs,0,_), | 
| 3212 |  | % Introduced identifiers occur alsa as sub-expressions, remove those | 
| 3213 |  | foldl(select_sub,Names,AllAnnotatedSubs,RealAnnSubs), | 
| 3214 |  | convlist_max(identifier_sub_ast_aux2(Identifier),2,RealAnnSubs,SubPositions), % find at most 2 sols | 
| 3215 |  | ( SubPositions = [SubPosition] -> true | 
| 3216 |  | ; SubPositions = [_,_|_] -> % More then one occurrences - make this the found node | 
| 3217 |  | SubPosition = []). | 
| 3218 |  | identifier_sub_ast_aux2(Identifier,Pos-TExpr,[Pos|SubPosition]) :- | 
| 3219 |  | identifier_sub_ast(TExpr,Identifier,SubPosition). | 
| 3220 |  | annotate_pos(TExpr,I-TExpr,I,I2) :- I2 is I+1. | 
| 3221 |  | select_sub(Name,AnnotatedSubs,Result) :- | 
| 3222 |  | selectchk(_Pos-Name,AnnotatedSubs,Result). | 
| 3223 |  |  | 
| 3224 |  |  | 
| 3225 |  |  | 
| 3226 |  | % exchange_ast_position(+SubPosition,+OldTExpr,-OldInner,+NewInner,-NewTExpr): | 
| 3227 |  | % exchanges a sub-expression in the expression "OldTExpr". | 
| 3228 |  | % SubPosition is a list of positions like identifier_sub_ast/3 returns it. | 
| 3229 |  | % OldInner is the sub-expression found in OldTExpr. | 
| 3230 |  | % NewInner is the new sub-expression. | 
| 3231 |  | % NewTExpr is the new expression that originates from replacing OldInner by NewInner. | 
| 3232 |  | exchange_ast_position([],Old,Old,New,New). | 
| 3233 |  | exchange_ast_position([Pos|RestPos],OldTExpr,OldInner,NewInner,NewTExpr) :- | 
| 3234 |  | remove_bt_and_used_ids(OldTExpr,OldExpr,NewExpr,NewTExpr), % also invalidates used_ids info | 
| 3235 |  | syntaxtransformation(OldExpr,Subs,_Names,NSubs,NewExpr), | 
| 3236 |  | nth0(Pos,Subs, OldSelected,Rest), | 
| 3237 |  | nth0(Pos,NSubs,NewSelected,Rest), | 
| 3238 |  | exchange_ast_position(RestPos,OldSelected,OldInner,NewInner,NewSelected). | 
| 3239 |  |  | 
| 3240 |  |  | 
| 3241 |  | % ----------------------- | 
| 3242 |  | % utility to expand / inline all let expressions and let predicates: | 
| 3243 |  | % useful for tools that cannot handle the lets | 
| 3244 |  |  | 
| 3245 |  | expand_all_lets(Expr,NewExpr) :- | 
| 3246 |  | transform_bexpr(tl_expand_lets,Expr,NewExpr). | 
| 3247 |  |  | 
| 3248 |  | tl_expand_lets(b(E,_,_),Res) :- tl_expand_lets2(E,Res). | 
| 3249 |  | tl_expand_lets2(let_expression(Ids,Exprs,Body),NewBody) :-  % expand LET expression | 
| 3250 |  | replace_ids_by_exprs(Body,Ids,Exprs,NewBody). | 
| 3251 |  | tl_expand_lets2(let_predicate(Ids,Exprs,Body),NewBody) :-  % expand LET predicate | 
| 3252 |  | replace_ids_by_exprs(Body,Ids,Exprs,NewBody). | 
| 3253 |  |  | 
| 3254 |  | % ----------------------- | 
| 3255 |  |  | 
| 3256 |  | :- public check_used_ids/2. | 
| 3257 |  | % a simple checker, only checks used_ids info fields for entire typed expression: | 
| 3258 |  | check_used_ids(TExpr,PP) :- %format('CHECK AST for ~w~n',[PP]), | 
| 3259 |  | map_over_typed_bexpr(check_used_ids_texpr_fail(PP),TExpr). | 
| 3260 |  | check_used_ids(_,_). | 
| 3261 |  | check_used_ids_texpr_fail(PP,E) :- check_used_ids_texpr(PP,E),!,fail. | 
| 3262 |  | check_used_ids_texpr(PP,b(P,T,I)) :-  member(used_ids(UIds1),I),!, | 
| 3263 |  | (find_identifier_uses(b(P,T,I),[],UIds2) -> true | 
| 3264 |  | ; add_internal_error('find_identifier_uses failed',PP),fail), | 
| 3265 |  | (UIds1==UIds2 -> true | 
| 3266 |  | ; format('*** Wrong used_ids Info (~w)!!~n  Used_ids: ~w~n  Comp_ids: ~w~n',[PP,UIds1,UIds2]), | 
| 3267 |  | translate:print_bexpr(b(P,T,I)),nl, | 
| 3268 |  | add_error(check_used_ids,'Wrong used_ids: ',PP,I) | 
| 3269 |  | ). | 
| 3270 |  | check_used_ids_texpr(_,_). | 
| 3271 |  |  | 
| 3272 |  | % repair any broken used_ids info in typed expression TExpr and re-compute used_ids if necessary | 
| 3273 |  | % PP is a program point, will be reported in case of an error | 
| 3274 |  | repair_used_ids(PP,TExpr,Res) :- | 
| 3275 |  | (transform_bexpr(bsyntaxtree:repair_used_ids_info(PP),TExpr,NewTExpr) -> Res=NewTExpr | 
| 3276 |  | ; add_internal_error('Repairing used_ids failed:',PP), | 
| 3277 |  | Res=TExpr). | 
| 3278 |  |  | 
| 3279 |  | % we could also simply call recompute_used_ids_inf; but it would not generate any messages | 
| 3280 |  | repair_used_ids_info(PP,b(P,T,I),b(P,T,NI)) :- %functor(P,FF,_), print(repair(FF)),nl, | 
| 3281 |  | select(used_ids(OldUsed),I,I2),!, | 
| 3282 |  | (find_identifier_uses(b(P,T,I),[],NewUsed) | 
| 3283 |  | -> (NewUsed=OldUsed -> NI=I | 
| 3284 |  | ; NI = [used_ids(NewUsed)|I2], | 
| 3285 |  | add_message(repair_used_ids,'Updating used_ids for: ',b(P,T,I),I2) | 
| 3286 |  | ) | 
| 3287 |  | ; add_internal_error('find_identifier_uses failed',PP), | 
| 3288 |  | NI=I | 
| 3289 |  | ). | 
| 3290 |  | repair_used_ids_info(PP,b(P,T,I),b(P,T,NI)) :- | 
| 3291 |  | requires_used_ids(P), | 
| 3292 |  | (find_identifier_uses(b(P,T,I),[],NewUsed) -> true | 
| 3293 |  | ; add_internal_error('find_identifier_uses failed',PP),fail | 
| 3294 |  | ), | 
| 3295 |  | !, | 
| 3296 |  | NI=[used_ids(NewUsed)|I]. | 
| 3297 |  | repair_used_ids_info(_,B,B). | 
| 3298 |  |  | 
| 3299 |  | requires_used_ids(exists(_,_)). | 
| 3300 |  | requires_used_ids(forall(_,_,_)). | 
| 3301 |  |  | 
| 3302 |  | % a simple checker to see if an AST is well-formed: | 
| 3303 |  | % can be tested e.g. as follows: b_get_invariant_from_machine(I), check_ast(I). | 
| 3304 |  | % called in prob_safe_mode by clean_up_section | 
| 3305 |  |  | 
| 3306 |  | check_ast(TE) :- check_ast(false,TE). | 
| 3307 |  | check_ast(AllowVars,TExpr) :- %nl,print('CHECK AST'),nl, | 
| 3308 |  | map_over_typed_bexpr(check_ast_texpr(AllowVars),TExpr). | 
| 3309 |  | check_ast(_,_). | 
| 3310 |  |  | 
| 3311 |  | :- use_module(typing_tools,[valid_ground_type/1]). | 
| 3312 |  | %check_ast_texpr(X) :- print(check(X)),nl,fail. | 
| 3313 |  | check_ast_texpr(AllowVars,AST) :- AST = b(E,Type,Infos), | 
| 3314 |  | (debug:debug_level_active_for(9) -> write(' check_ast: '),print_bexpr(AST), write(' :: '), write(Type), nl ; true), | 
| 3315 |  | (check_expr(E,Type,Infos) -> true | 
| 3316 |  | ; add_error(check_ast_texpr,'Invalid Expr: ', AST) %, trace, check_expr(E,Type,Infos) | 
| 3317 |  | ), | 
| 3318 |  | (check_type(Type,AllowVars) -> true | 
| 3319 |  | ; add_error(check_ast_texpr,'Invalid Type for: ',AST,Infos)), | 
| 3320 |  | safe_functor(E,F), | 
| 3321 |  | check_ast_typing(E,Type,Infos), | 
| 3322 |  | (check_infos(Infos,F) -> true ; add_error(check_ast_texpr,'Invalid Infos: ',AST)), | 
| 3323 |  | check_special_rules(E,Type,Infos), | 
| 3324 |  | fail. % to force backtracking in map_over_typed_bexpr | 
| 3325 |  |  | 
| 3326 |  |  | 
| 3327 |  | check_special_rules(operation_call_in_expr(Operation,_),_,OInfos) :- !, | 
| 3328 |  | get_texpr_info(Operation,Info), % reads info important for used_ids computation | 
| 3329 |  | (memberchk(reads(_V),Info) -> true | 
| 3330 |  | ; add_error(check_ast_texpr,'Missing reads info: ',Operation,OInfos)). | 
| 3331 |  |  | 
| 3332 |  |  | 
| 3333 |  | safe_functor(V,R) :- var(V),!,R='$VAR'. | 
| 3334 |  | safe_functor(E,F/N) :- functor(E,F,N). | 
| 3335 |  |  | 
| 3336 |  | % check whether the type term is ok | 
| 3337 |  | check_type(X,AllowVars) :- var(X),!, | 
| 3338 |  | (AllowVars==true -> true ; add_error(check_type,'Variable type: ',X),fail). | 
| 3339 |  | check_type(pred,_) :- !. | 
| 3340 |  | check_type(subst,_) :- !. | 
| 3341 |  | check_type(op(Paras,Returns),AllowVars) :- !, | 
| 3342 |  | maplist(check_normal_type(AllowVars),Paras), | 
| 3343 |  | maplist(check_normal_type(AllowVars),Returns). | 
| 3344 |  | check_type(T,AllowVars) :- check_normal_type(AllowVars,T). | 
| 3345 |  |  | 
| 3346 |  | check_normal_type(AllowVars,T) :- | 
| 3347 |  | (AllowVars \== true -> valid_ground_type(T) | 
| 3348 |  | ; ground(T) -> valid_ground_type(T) | 
| 3349 |  | ; true).  % TO DO: call valid_ground_type but pass AllowVars | 
| 3350 |  |  | 
| 3351 |  | :- use_module(probsrc(btypechecker), [lookup_type_for_expr/2, unify_types_werrors/4]). | 
| 3352 |  | % check whether type is compatible with operators | 
| 3353 |  | check_ast_typing(member(A,B),Type,Pos) :- !, | 
| 3354 |  | get_texpr_type(B,TB), check_set_type(TB,member,Pos), | 
| 3355 |  | check_type(Type,pred,member), | 
| 3356 |  | get_texpr_type(A,TA), | 
| 3357 |  | unify_types_werrors(set(TA),TB,Pos,member). | 
| 3358 |  | check_ast_typing(not_equal(A,B),Type,Pos) :- !, check_ast_typing(equal(A,B),Type,Pos). | 
| 3359 |  | check_ast_typing(equal(A,B),Type,Pos) :- !, | 
| 3360 |  | get_texpr_type(B,TB), | 
| 3361 |  | get_texpr_type(A,TA), | 
| 3362 |  | unify_types_werrors(TA,TB,Pos,'='), | 
| 3363 |  | (non_value_type(TA) | 
| 3364 |  | -> add_error(check_ast_typing,'Binary predicate has to have values as arguments:',TA,Pos) | 
| 3365 |  | ; Type=pred ->  true | 
| 3366 |  | ; add_error(check_ast_typing,'Illegal type for binary predicate:',Type,Pos) | 
| 3367 |  | ). | 
| 3368 |  | check_ast_typing(greater_equal(A,B),Type,_) :- !, | 
| 3369 |  | get_texpr_type(A,TA),check_type(TA,integer,greater_equal), | 
| 3370 |  | get_texpr_type(B,TB),check_type(TB,integer,greater_equal), check_type(Type,pred,member). | 
| 3371 |  | check_ast_typing(Expr,Type,Pos) :- | 
| 3372 |  | syntaxtransformation(Expr,Subs,Names,NSubs,NewExpr), | 
| 3373 |  | check_names(Names,Pos), | 
| 3374 |  | (lookup_type(NewExpr,T) -> true | 
| 3375 |  | ; add_warning(check_ast_typing,'Unable to lookup type for: ',NewExpr), | 
| 3376 |  | fail | 
| 3377 |  | ), | 
| 3378 |  | !, | 
| 3379 |  | (unify_types_werrors(Type,T,Pos,'check_ast') | 
| 3380 |  | -> maplist(check_sub_type(Expr,Pos),Subs,NSubs) | 
| 3381 |  | ; add_error(check_ast_typing,'Type mismatch for expression:',Expr,Pos) | 
| 3382 |  | ). | 
| 3383 |  | check_ast_typing(_,subst,_) :- !. % ignore subst for the moment | 
| 3384 |  | check_ast_typing(operation(_TName,_Res,_Params,_TBody),_,_) :- !. % ignore operations for the moment | 
| 3385 |  | check_ast_typing(Expr,_,Pos) :- | 
| 3386 |  | syntaxtransformation(Expr,_,_Names,_,_NewExpr),!, | 
| 3387 |  | add_message(check_ast_typing,'Cannot lookup type for expression: ',Expr,Pos). | 
| 3388 |  | check_ast_typing(Expr,_,Pos) :- | 
| 3389 |  | add_message(check_ast_typing,'No applicable type rule for expression: ',Expr,Pos). | 
| 3390 |  |  | 
| 3391 |  | non_value_type(X) :- var(X),!,fail. | 
| 3392 |  | non_value_type(pred). | 
| 3393 |  | non_value_type(subst). | 
| 3394 |  | non_value_type(op(_)). | 
| 3395 |  |  | 
| 3396 |  |  | 
| 3397 |  | check_names([],_). | 
| 3398 |  | check_names([H|T],Pos) :- | 
| 3399 |  | (member(H,T) -> add_error(check_ast_name,'Duplicate name:',H,Pos) ; check_names(T,Pos)). | 
| 3400 |  |  | 
| 3401 |  | check_sub_type(OuterExpr,Pos,Arg,Type) :- get_texpr_type(Arg,T),!, | 
| 3402 |  | (unify_types_werrors(Type,T,Pos,'check_sub_type') -> true | 
| 3403 |  | ; add_error(check_ast_typing,'Type mismatch for sub-expression:',Arg,Pos), | 
| 3404 |  | write('Outer expression: '),translate:print_bexpr(OuterExpr),nl, | 
| 3405 |  | write('Outer type: '),write(Type),nl, | 
| 3406 |  | write('Arg type:   '),write(T),nl,print(type(T)),nl, tools_printing:print_term_summary(Arg),nl,trace | 
| 3407 |  | ). | 
| 3408 |  | check_sub_type(_,Pos,Arg,_) :- | 
| 3409 |  | add_error(check_ast_typing,'Cannot extract type: ',Arg,Pos). | 
| 3410 |  |  | 
| 3411 |  | lookup_type(identifier(_),_) :- !. % ignore typing issues for identifiers | 
| 3412 |  | lookup_type(Expr,Type) :- lookup_type_for_expr(Expr,Type). | 
| 3413 |  |  | 
| 3414 |  | check_set_type(Var,_,_) :- var(Var),!. | 
| 3415 |  | check_set_type(set(_),_,_) :- !. | 
| 3416 |  | check_set_type(seq(_),_,_) :- !. | 
| 3417 |  | check_set_type(Type,Func,Pos) :- add_error(check_ast_typing,'Invalid type for operator: ',Func:Type,Pos). | 
| 3418 |  |  | 
| 3419 |  | check_type(Type,Type,_) :- !. | 
| 3420 |  | check_type(Type,_,Func) :- add_error(check_ast_typing,'Unexpected type for operator: ',Func:Type). | 
| 3421 |  |  | 
| 3422 |  | check_infos(X,F) :- var(X),!, add_error(check_infos,'Info field list not terminated: ',F:X),fail. | 
| 3423 |  | check_infos([],_). | 
| 3424 |  | check_infos([H|_],F) :- \+ ground(H),!, add_error(check_infos,'Info field not ground: ',F:H),fail. | 
| 3425 |  | check_infos([[H|T]|_],F) :- !, add_error(check_infos,'Info field contains nested list: ',F:[H|T]),fail. | 
| 3426 |  | check_infos([cse_used_ids(H)|T],F) :- member(cse_used_ids(H2),T),!, | 
| 3427 |  | add_error(check_infos,'Multiple cse_used_ids entries: ',F:[H,H2]),fail. | 
| 3428 |  | check_infos([used_ids(H)|T],F) :- member(used_ids(H2),T),!, | 
| 3429 |  | add_error(check_infos,'Multiple used_ids entries: ',F:[H,H2]),fail. | 
| 3430 |  | check_infos([nodeid(N1)|T],F) :- member(nodeid(N2),T),!, | 
| 3431 |  | add_error(check_infos,'Multiple nodeid entries: ',F:[N1,N2],[nodeid(N1)]),fail. | 
| 3432 |  | check_infos([removed_typing|T],F) :- member(removed_typing,T),!, | 
| 3433 |  | add_error(check_infos,'Multiple removed_typing entries: ',F,T),fail. | 
| 3434 |  | check_infos([_|T],F) :- check_infos(T,F). | 
| 3435 |  |  | 
| 3436 |  | check_expr(Expr,Type,Infos) :- nonmember(contains_wd_condition,Infos), | 
| 3437 |  | sub_expression_contains_wd_condition(Expr,Sub), | 
| 3438 |  | TE = b(Expr,Type,Infos), | 
| 3439 |  | (Type = subst | 
| 3440 |  | -> fail % AST cleanup is not called for substitutions; WD-info not available for substitutions at the moment | 
| 3441 |  | ; translate_bexpression(TE,PS)), | 
| 3442 |  | functor(Expr,Functor,_), | 
| 3443 |  | functor(Sub,SubFunctor,_), | 
| 3444 |  | tools:ajoin(['Node for AST node ',Functor,' does not contain WD info from Subexpression ',SubFunctor,' :'],Msg), | 
| 3445 |  | add_warning(check_expr,Msg,PS,TE). | 
| 3446 |  | % well_def_analyser:nested_print_wd_bexpr(TE),nl. | 
| 3447 |  | % TODO: check when we have an unnecessary WD condition | 
| 3448 |  | check_expr(Expr,Type,Infos) :- nonmember(contains_wd_condition,Infos), | 
| 3449 |  | always_not_wd_top(Expr), | 
| 3450 |  | add_warning(check_expr,'AST is not well-defined but does not contain WD info: ',b(Expr,Type,Infos),Infos). | 
| 3451 |  | check_expr(member(LHS,RHS),Type,Infos) :- is_just_type(RHS), | 
| 3452 |  | get_preference(optimize_ast,true), | 
| 3453 |  | !, | 
| 3454 |  | TE = b(member(LHS,RHS),Type,Infos), | 
| 3455 |  | translate:translate_bexpression(TE,PS), | 
| 3456 |  | add_warning(check_expr,'AST contains redundant typing predicate: ',PS,TE). | 
| 3457 |  | check_expr(identifier(ID),_,_) :- illegal_id(ID),!, | 
| 3458 |  | add_error(check_infos,'Illegal identifier: ', identifier(ID)). | 
| 3459 |  | check_expr(lazy_lookup_expr(ID),_,_) :- illegal_id(ID),!, | 
| 3460 |  | add_error(check_infos,'Illegal identifier: ', lazy_lookup_expr(ID)). | 
| 3461 |  | check_expr(lazy_lookup_pred(ID),_,_) :- illegal_id(ID),!, | 
| 3462 |  | add_error(check_infos,'Illegal identifier: ', lazy_lookup_pred(ID)). | 
| 3463 |  | check_expr(exists(Parameters,Condition),pred,Infos) :- !, | 
| 3464 |  | check_used_ids(exists,Parameters,Condition,Infos,_Used). | 
| 3465 |  | check_expr(forall(Parameters,LHS,RHS),pred,Infos) :- !, | 
| 3466 |  | create_implication(LHS,RHS,Condition), | 
| 3467 |  | check_used_ids(forall,Parameters,Condition,Infos,_Used). % | 
| 3468 |  | check_expr(value(V),Type,_) :- !, check_bvalue(V,Type). | 
| 3469 |  | check_expr(_,_,_). | 
| 3470 |  |  | 
| 3471 |  | % will check all used_ids fields (not just for exists and forall) | 
| 3472 |  | :- public check_used_ids_in_ast/1. | 
| 3473 |  | check_used_ids_in_ast(closure(_,_,TExpr)) :- !, (map_over_typed_bexpr(check_used_ids_aux,TExpr) ; true). | 
| 3474 |  | check_used_ids_in_ast(TExpr) :- map_over_typed_bexpr(check_used_ids_aux,TExpr). | 
| 3475 |  | check_used_ids_in_ast(_). | 
| 3476 |  |  | 
| 3477 |  | check_used_ids_aux(AST) :- AST = b(_,_,Infos), | 
| 3478 |  | member(used_ids(_),Infos),!, | 
| 3479 |  | find_identifier_uses_if_necessary(AST,[],_), % will perform check | 
| 3480 |  | fail. | 
| 3481 |  |  | 
| 3482 |  | % -------------------- | 
| 3483 |  |  | 
| 3484 |  | :- use_module(specfile,[eventb_mode/0, z_or_tla_minor_mode/0]). | 
| 3485 |  | % check if an expression is definitely not WD; looking at the top-level operator only | 
| 3486 |  | always_not_wd_top(function(X,_)) :- definitely_empty_set(X). % TODO: detect a few more cases, e.g., arg not in dom | 
| 3487 |  | always_not_wd_top(power_of(X,Y)) :- (get_integer(Y,VY), VY < 0 -> true | 
| 3488 |  | ;  eventb_mode, get_integer(X,VX), VX < 0). | 
| 3489 |  | always_not_wd_top(div(_,Val)) :- get_integer(Val,VV), VV==0. | 
| 3490 |  | always_not_wd_top(modulo(X,Y)) :- | 
| 3491 |  | (get_integer(Y,VY), VY=<0 | 
| 3492 |  | -> true % there seems to be a def for Z in Z Live, cf modulo2 | 
| 3493 |  | ; get_integer(X,VX), VX<0, \+ z_or_tla_minor_mode). | 
| 3494 |  | always_not_wd_top(min(X)) :- definitely_empty_set(X). | 
| 3495 |  | always_not_wd_top(max(X)) :- definitely_empty_set(X). | 
| 3496 |  | always_not_wd_top(size(X)) :- definitely_not_sequence(X). % TODO: detect infinite sets; also for card(_) | 
| 3497 |  | always_not_wd_top(first(X)) :- definitely_not_non_empty_sequence(X). | 
| 3498 |  | always_not_wd_top(front(X)) :- definitely_not_non_empty_sequence(X). | 
| 3499 |  | always_not_wd_top(last(X)) :- definitely_not_non_empty_sequence(X). | 
| 3500 |  | always_not_wd_top(tail(X)) :- definitely_not_non_empty_sequence(X). | 
| 3501 |  | always_not_wd_top(general_intersection(X)) :- definitely_empty_set(X). | 
| 3502 |  |  | 
| 3503 |  | definitely_not_non_empty_sequence(X) :- | 
| 3504 |  | (definitely_empty_set(X) -> true ; definitely_not_sequence(X)). | 
| 3505 |  |  | 
| 3506 |  | :- use_module(avl_tools,[avl_min_pair/3]). | 
| 3507 |  | definitely_not_sequence(b(value(A),_,_)) :- nonvar(A), A=avl_set(AVL), | 
| 3508 |  | avl_min_pair(AVL,int(StartIndex),_), StartIndex \= 1. | 
| 3509 |  | % TODO: treat set_extension | 
| 3510 |  |  | 
| 3511 |  | :- use_module(b_ast_cleanup,[check_used_ids_info/4]). | 
| 3512 |  | check_used_ids(Quantifier,Parameters,Condition,Infos,Used) :- | 
| 3513 |  | select(used_ids(Used),Infos,Rest) | 
| 3514 |  | -> check_used_ids_info(Parameters,Condition,Used,Quantifier), %% comment in to check used_ids field | 
| 3515 |  | (member(used_ids(_),Rest) | 
| 3516 |  | -> add_internal_error('Multiple used_ids info fields:',Parameters:Infos) ; true) | 
| 3517 |  | ; | 
| 3518 |  | add_internal_error( | 
| 3519 |  | 'Expected information of used identifiers information',Quantifier:Parameters:Infos). | 
| 3520 |  |  | 
| 3521 |  | illegal_id(ID) :- var(ID),!. | 
| 3522 |  | illegal_id(op(ID)) :- !, \+ atom(ID). | 
| 3523 |  | illegal_id(ID) :- \+ atom(ID). | 
| 3524 |  |  | 
| 3525 |  | :- use_module(btypechecker, [unify_types_strict/2, couplise_list/2]). | 
| 3526 |  | :- use_module(avl_tools,[check_is_non_empty_avl/1]). | 
| 3527 |  | % TO DO: we could check type more | 
| 3528 |  | check_bvalue(V,_) :- var(V),!. | 
| 3529 |  | check_bvalue(avl_set(A),Type) :- !, unify_types_strict(Type,set(_)), | 
| 3530 |  | check_is_non_empty_avl(A). | 
| 3531 |  | check_bvalue(closure(_,T,B),Type) :- !, | 
| 3532 |  | couplise_list(T,CT), unify_types_strict(set(CT),Type), | 
| 3533 |  | check_ast(B). | 
| 3534 |  | check_bvalue(_,_). | 
| 3535 |  |  | 
| 3536 |  | % ----------------------- | 
| 3537 |  |  | 
| 3538 |  |  | 
| 3539 |  | indent_ws(X) :- X<1,!. | 
| 3540 |  | indent_ws(X) :- print('  '), X1 is X-1, indent_ws(X1). | 
| 3541 |  |  | 
| 3542 |  | print_ast_td(b(E,T,I),Level,L1) :- | 
| 3543 |  | indent_ws(Level), | 
| 3544 |  | (E=identifier(_) | 
| 3545 |  | -> format('~w (~w) -> ~w~n',[E,T,I]) | 
| 3546 |  | ;  functor(E,F,N), | 
| 3547 |  | format('~w/~w (~w) -> ~w~n',[F,N,T,I]) | 
| 3548 |  | ), | 
| 3549 |  | L1 is Level+1. | 
| 3550 |  | print_ast(TExpr) :- | 
| 3551 |  | (map_over_typed_bexpr_top_down_acc(print_ast_td,TExpr,0),fail ; true). | 
| 3552 |  |  | 
| 3553 |  | % --------------------- | 
| 3554 |  |  | 
| 3555 |  | :- dynamic count_id_usage/2. | 
| 3556 |  | single_usage_id_count(Expr) :- uses_an_identifier(Expr,Id), | 
| 3557 |  | retract(count_id_usage(Id,Count)), | 
| 3558 |  | !, | 
| 3559 |  | Count=0, | 
| 3560 |  | C1 is Count+1, | 
| 3561 |  | assertz(count_id_usage(Id,C1)). | 
| 3562 |  | single_usage_id_count(_). | 
| 3563 |  |  | 
| 3564 |  | % check if an identifier is used at most once | 
| 3565 |  | single_usage_identifier(ID,ExprOrPredicates,Count) :- | 
| 3566 |  | retractall(count_id_usage(_,_)), | 
| 3567 |  | assertz(count_id_usage(ID,0)), | 
| 3568 |  | % TO DO: take care of naming; do not count occurences when we enter scope defining ID | 
| 3569 |  | maplist(single_usage_cnt,ExprOrPredicates), | 
| 3570 |  | retract(count_id_usage(ID,Count)). | 
| 3571 |  |  | 
| 3572 |  | single_usage_cnt(ExprOrPredicate) :- map_over_full_bexpr_no_fail(single_usage_id_count,ExprOrPredicate). | 
| 3573 |  |  | 
| 3574 |  | gen_fresh_id_if_necessary(Default,Expr,FreshID) :- | 
| 3575 |  | occurs_in_expr(Default,Expr),!, | 
| 3576 |  | gensym('__FRESH_ID__',FreshID). % assumes _Fresh_XXX not used | 
| 3577 |  | gen_fresh_id_if_necessary(Default,_,Default). | 
| 3578 |  |  | 
| 3579 |  | %% rewrite_if_then_else_expr_to_b(IfThenElseExpr, NExpr). | 
| 3580 |  | % Rewrite if-then-else expr to B as understood by Atelier-B. | 
| 3581 |  | % {d,x| d:BOOL & If => x=Then & not(if) => x=Else}(TRUE) | 
| 3582 |  | rewrite_if_then_else_expr_to_b(if_then_else(If,Then,Else), NExpr) :- | 
| 3583 |  | get_texpr_type(Then,Type), | 
| 3584 |  | ARG = b(boolean_true,boolean,[]), AT=boolean, % we could use unit type or BOOL here | 
| 3585 |  | gen_fresh_id_if_necessary('_zzzz_unary',b(if_then_else(If,Then,Else),Type,[]),AID1), | 
| 3586 |  | gen_fresh_id_if_necessary('_zzzz_binary',b(if_then_else(If,Then,Else),Type,[]),AID2), | 
| 3587 |  | safe_create_texpr(identifier(AID1), AT, [], Id1), % a dummy argument | 
| 3588 |  | safe_create_texpr(identifier(AID2), Type, [], Id2), % The result | 
| 3589 |  | safe_create_texpr(equal(Id2,Then), pred, [], Eq1), | 
| 3590 |  | safe_create_texpr(equal(Id2,Else), pred, [], Eq2), | 
| 3591 |  | safe_create_texpr(implication(If,Eq1), pred, [], Pred1), | 
| 3592 |  | safe_create_texpr(negation(If), pred, [], NIf), | 
| 3593 |  | safe_create_texpr(implication(NIf,Eq2), pred, [], Pred2), | 
| 3594 |  | safe_create_texpr(conjunct(Pred1,Pred2), pred, [], Pred), | 
| 3595 |  | safe_create_texpr(comprehension_set([Id1,Id2],Pred), set(couple(AT,Type)), [], FUN), | 
| 3596 |  | NExpr = function(FUN,ARG). | 
| 3597 |  |  | 
| 3598 |  |  | 
| 3599 |  | % -------------------- | 
| 3600 |  |  | 
| 3601 |  | % apply normalisation rules from Atlier-B PP/ML provers | 
| 3602 |  | % see chapter 3 of Atelier-B prover manual | 
| 3603 |  |  | 
| 3604 |  | normalise_bexpr_for_ml(TExpr,Res) :- | 
| 3605 |  | transform_bexpr(normalise_bexpr,TExpr,Res). | 
| 3606 |  |  | 
| 3607 |  | normalise_bexpr(b(E,T,I),b(E2,T,I)) :- norm2(E,E2),!. | 
| 3608 |  |  | 
| 3609 |  | norm2(equivalence(A,B),conjunct(TIMP1,TIMP2)) :- !, | 
| 3610 |  | safe_create_texpr(implication(A,B),pred,TIMP1), | 
| 3611 |  | safe_create_texpr(implication(B,A),pred,TIMP2). | 
| 3612 |  | norm2(subset_strict(A,B),conjunct(TMEM,TNEQ)) :- !, | 
| 3613 |  | norm2(subset(A,B),MEM), safe_create_texpr(MEM,pred,TMEM), | 
| 3614 |  | safe_create_not_equal(A,B,TNEQ). | 
| 3615 |  | norm2(subset(A,B),member(A,PowB)) :-  !,  % A <: B  <===>  A:POW(B) | 
| 3616 |  | get_texpr_type(A,TA), | 
| 3617 |  | safe_create_texpr(pow_subset(B),TA,PowB). | 
| 3618 |  | norm2(not_equal(A,B),negation(TEQ)) :- !, | 
| 3619 |  | safe_create_texpr(equal(A,B),pred,TEQ). | 
| 3620 |  | norm2(not_member(A,B),negation(TMEM)) :- !, | 
| 3621 |  | safe_create_texpr(member(A,B),pred,TMEM). | 
| 3622 |  | norm2(not_subset(A,B),negation(TMEM)) :- !, | 
| 3623 |  | norm2(subset(A,B),MEM),safe_create_texpr(MEM,pred,TMEM). | 
| 3624 |  | norm2(not_subset_strict(A,B),implication(TMEM,TEQ)) :- !, % A /<< : B   <===>   A:POW(B) => A=B | 
| 3625 |  | norm2(subset(A,B),MEM),safe_create_texpr(MEM,pred,TMEM), | 
| 3626 |  | safe_create_texpr(equal(A,B),pred,TEQ). | 
| 3627 |  | norm2(POW1,set_subtraction(TPOW,TSEMPTY)) :-  not_empty_pow(POW1,A,POW), !, | 
| 3628 |  | % POW1(A)  <===>  POW(A) - {{}}, FIN1(A)  <===>  FIN(A) - {{}}, ... | 
| 3629 |  | safe_create_texpr(POW,pred,TPOW), | 
| 3630 |  | get_texpr_type(A,TA), TEMPTY = b(empty_set,TA,[]), | 
| 3631 |  | safe_create_texpr(set_extension([TEMPTY]),set(TA),TSEMPTY). | 
| 3632 |  | norm2(member(A,b(integer_set('NATURAL'),_,_)),conjunct(TMEM,TLEQ)) :-  !,  % A <: NATURAL  <===>  A:INTEGER & 0 <= A | 
| 3633 |  | INTEGER = b(integer_set('INTEGER'),set(integer),[]), | 
| 3634 |  | safe_create_texpr(member(A,INTEGER),pred,TMEM), | 
| 3635 |  | Zero = b(integer(0),integer,[]), | 
| 3636 |  | safe_create_texpr(less_equal(Zero,A),pred,TLEQ). | 
| 3637 |  | norm2(set_extension(List),Union) :-  List = [H|T], T=[_|_], !, %  {A,B}   <===> {A} \/ {B} | 
| 3638 |  | get_texpr_type(H,Type), | 
| 3639 |  | set_extension_to_union(H,T,set(Type),b(Union,_,_)). | 
| 3640 |  | norm2(greater_equal(A,B),less_equal(B,A)) :-  !. | 
| 3641 |  | norm2(greater(A,B),less_equal(B1,A)) :-  !, plus1(B,B1). | 
| 3642 |  | norm2(less(A,B),less_equal(A,B1)) :- !, minus1(B,B1). % the normalisation rule in chapter 3 is actually false | 
| 3643 |  | norm2(integer_set(NAT1),set_subtraction(TNAT,TSZero)) :-  nat1(NAT1,NAT), !,  %  NATURAL1 <===> NATURAL - {0} | 
| 3644 |  | TNAT = b(integer_set(NAT),set(integer),[]), | 
| 3645 |  | set_with_zero(TSZero). | 
| 3646 |  | norm2(empty_sequence,empty_set) :-  !. | 
| 3647 |  | norm2(perm(A),intersection(ISEQ,PSURJ)) :- !, % perm(A) <===> iseq(A) /\ (NATURAL-{0} +->> A) | 
| 3648 |  | get_texpr_type(A,TA), | 
| 3649 |  | safe_create_texpr(iseq(A),set(seq(TA)),ISEQ), | 
| 3650 |  | set_with_zero(TSZero), | 
| 3651 |  | NATURAL = b(integer_set('NATURAL'),set(integer),[]), | 
| 3652 |  | safe_create_texpr(set_subtraction(NATURAL,TSZero),set(integer),DOM), | 
| 3653 |  | safe_create_texpr(partial_surjection(DOM,A),set(seq(TA)),PSURJ). | 
| 3654 |  | % TODO: total_relation, if_then_else, ...? | 
| 3655 |  |  | 
| 3656 |  | set_with_zero(TSZero) :- % {0} | 
| 3657 |  | TZero = b(integer(0),TA,[]), | 
| 3658 |  | safe_create_texpr(set_extension([TZero]),set(TA),TSZero). | 
| 3659 |  |  | 
| 3660 |  | % TODO: more intelligent versions like x-1  ==>  x ... | 
| 3661 |  | plus1(A,Plus1) :- One = b(integer(1),integer,[]), | 
| 3662 |  | safe_create_texpr(add(A,One),integer,Plus1). | 
| 3663 |  | minus1(A,Plus1) :- One = b(integer(1),integer,[]), | 
| 3664 |  | safe_create_texpr(minus(A,One),integer,Plus1). | 
| 3665 |  |  | 
| 3666 |  | not_empty_pow(pow1_subset(A),A,pow_subset(A)). | 
| 3667 |  | not_empty_pow(fin1_subset(A),A,fin_subset(A)). | 
| 3668 |  | not_empty_pow(seq1(A),A,seq(A)). | 
| 3669 |  | not_empty_pow(iseq1(A),A,iseq(A)). | 
| 3670 |  |  | 
| 3671 |  | nat1('NATURAL1','NATURAL'). | 
| 3672 |  | nat1('NAT1','NAT'). | 
| 3673 |  |  | 
| 3674 |  | safe_create_not_equal(A,B,TNEQ) :- | 
| 3675 |  | safe_create_texpr(equal(A,B),pred,TEQ), | 
| 3676 |  | safe_create_texpr(negation(TEQ),pred,TNEQ). | 
| 3677 |  |  | 
| 3678 |  | set_extension_to_union(H,[],Type,Res) :- !, | 
| 3679 |  | safe_create_texpr(set_extension([H]),Type,Res). | 
| 3680 |  | set_extension_to_union(H,[H2|T],Type,Res) :- | 
| 3681 |  | safe_create_texpr(set_extension([H]),Type,TH), | 
| 3682 |  | set_extension_to_union(H2,T,Type,TUnion), | 
| 3683 |  | safe_create_texpr(union(TH,TUnion),Type,Res). |