1 % (c) 2009-2019 Lehrstuhl fuer Softwaretechnik und Programmiersprachen,
2 % Heinrich Heine Universitaet Duesseldorf
3 % This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html)
4
5 :- module(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 same_id/3, % true if two typed identifiers have the same id
16 get_texpr_exprs/2, % list variant of the above
17 get_texpr_types/2, % list variant of the above
18 get_texpr_infos/2, % list variant of the above
19 get_texpr_ids/2, % list variant of the above
20 get_texpr_pos/2, % get the position of a typed expression
21 extract_pos_infos/2, % get the position info sub list of an info list
22 copy_pos_infos/3, % copy position infos from one typed expression to another
23 merge_info/3, % merge two information lists as well as possible
24 update_infos/3, % provide updates to an existing info list
25 get_info_pos/2, % get the position directly from info field
26 contains_info_pos/1, % true if info field contains position infos
27
28 same_texpr/2, % check if two typed expressions are equal modulo Info fields
29 different_texpr_values/2, % check if two type expressions are WD and definitely denote different values
30
31 create_texpr/4, % creates a typed expression by giving expression, type and infos
32 add_texpr_infos/3, % adds some more information to a typed expression at front
33 add_texpr_info_if_new/3, % adds one info field to typed B expression info list at front if it is new
34 add_texpr_infos_if_new/3, % ditto but list of infos can be added
35 add_info_if_new/3, % adds to info list
36 safe_create_texpr/3, % a version of create_texpr which extracts wd-info from sub-expressionssafe_create_texpr
37 safe_create_texpr/4,
38 sub_expression_contains_wd_condition/1, % utility to check if sub-expression contains wd condition
39
40 get_rodin_name/2, get_rodin_model_name/2, get_texpr_label/2, get_texpr_labels/2,
41 get_texpr_description/2, % get @desc pragma for typed expression
42 info_has_ignore_pragma/1, % check if an info list has an ignore pragma
43 always_well_defined/1, always_well_defined_or_disprover_mode/1,
44 is_truth/1, is_falsity/1,
45 conjunct_predicates/2,
46 conjunct_predicates_with_pos_info/3,
47 is_a_conjunct/3, is_a_conjunct_without_label/3, decompose_conjunct/3,
48 is_a_disjunct/3, is_an_implication/3, is_an_equivalence/3, is_a_negation/2,
49 conjunction_to_list/2, member_in_conjunction/2, select_member_in_conjunction/3,
50 member_in_conjunction_cse/3,
51 disjunct_predicates/2,
52 disjunction_to_list/2,
53 is_a_disjunct_or_implication/4,
54
55 predicate_components/2, % split a predicate into components which use distinct identifiers
56 predicate_components_in_scope/3, % ditto with an optional list of local variables
57 predicate_components_with_restriction/4,
58 predicate_identifiers/2, predicate_identifiers_in_scope/3,
59
60 project_predicate_on_identifiers/5,
61
62 find_identifier_uses/3, find_identifier_uses_l/3,
63 find_typed_identifier_uses/3, find_typed_identifier_uses/2,
64 find_typed_identifier_uses_l/3,
65 get_global_identifiers/1,
66 occurs_in_expr/2, some_id_occurs_in_expr/2,
67 single_usage_identifier/3,
68
69 create_exists/3, create_exists_or_let_predicate/3,
70 create_exists_opt/3, create_exists_opt/4, create_exists_opt/5,
71 create_forall/3,
72 create_negation/2, is_negation_of/2,
73 create_implication/3,
74 create_equivalence/3,
75 create_couple/3, create_couple/2,
76
77 detect_global_predicates/4,
78
79 definitely_not_empty_set/1,
80
81 replace_id_by_expr/4,
82 replace_ids_by_exprs/4,
83 remove_used_id_from_info/3, % remove an id from used_id info field if it exists
84 remove_used_ids_from_info/3, % remove list of ids (order of args different !)
85
86 rename_bt/3, % a simplified version of replace_ids_by_exprs, which assumes target of renamings are variables
87 rename_bt_l/3,
88 remove_bt/4,
89 syntaxtransformation/5,
90
91 map_over_bexpr/2, map_over_typed_bexpr/2, map_over_typed_bexpr/3,
92 map_over_bexpr_top_down_acc/3, map_over_type_bexpr_top_down_acc/3,
93 reduce_over_bexpr/4,
94 transform_bexpr/3, transform_bexpr_with_bup_accs/5, transform_bexpr_with_acc/5,
95 uses_implementable_integers/1,
96 min_max_integer_value_used/3, min_max_integer_value_used/5,
97 syntaxtraversion/6,
98 safe_syntaxelement/5,
99
100 remove_all_infos/2, extract_info/2, extract_info/3,
101 bsyntax_pattern/2,
102
103 remove_all_infos_and_ground/2,
104
105 check_if_typed_predicate/1,
106 check_if_typed_expression/1,
107 check_if_typed_substitution/1,
108
109 strip_and_norm_ast/2,
110 same_norm_texpr/2,
111
112 is_set_type/2, get_set_type/2, get_texpr_set_type/2,
113 is_just_type/1, is_just_type/2,
114
115 create_recursive_compset/6,
116 unique_typed_id/3,
117 mark_bexpr_as_symbolic/2,
118
119 identifier_sub_ast/3, exchange_ast_position/5,
120
121 has_declared_identifier/2, add_declaration_for_identifier/3,
122 check_ast/1, check_ast/2,
123 print_ast/1
124 ]).
125
126 % meta_predicate annotations should appear before loading any code:
127
128 :- meta_predicate map_over_full_bexpr_no_fail(1,?).
129
130 :- meta_predicate map_over_bexpr(1,?).
131 :- meta_predicate map_over_typed_bexpr(1,?).
132 :- meta_predicate map_over_typed_bexpr(2,?,?).
133 :- meta_predicate map_over_bexpr_top_down_acc(3,?,?).
134 :- meta_predicate map_over_type_bexpr_top_down_acc(3,?,?).
135
136 :- meta_predicate reduce_over_bexpr(3,?,?,?).
137 :- meta_predicate transform_bexpr(2,?,?).
138 :- meta_predicate l_transform_bexpr(?,2,?).
139 :- meta_predicate transform_bexpr_with_bup_accs(4,?,?,?,?).
140 :- meta_predicate l_transform_bexpr_with_bup_accs(?,4,?,?,?).
141 :- meta_predicate transform_bexpr_with_acc(4,?,?,?,?).
142 :- meta_predicate l_transform_bexpr_with_acc(?,4,?,?,?).
143
144 % -----------
145
146
147 :- use_module(tools).
148
149 :- use_module(module_information,[module_info/2]).
150 :- module_info(group,typechecker).
151 :- module_info(description,'This module provides operations on the type-checked AST.').
152
153 :- use_module(library(lists)).
154 :- use_module(library(ordsets)).
155 :- use_module(library(avl)).
156 :- use_module(library(terms)).
157
158 :- use_module(self_check).
159 :- use_module(error_manager).
160 :- use_module(translate,[print_bexpr/1,translate_bexpression/2]).
161 :- use_module(gensym,[gensym/2,reset_gensym/0]).
162 :- use_module(preferences,[get_preference/2,preference/2]).
163 :- use_module(debug,[debug_format/3]).
164
165 :- use_module(typing_tools,[is_infinite_type/1,normalize_type/2]).
166
167 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
168 % basic access to enriched syntax tree
169
170 is_texpr(b(_,_,_)).
171
172 get_texpr_expr(b(Name,_,_),R) :- !,R=Name.
173 get_texpr_expr(E,_) :- add_error_fail(get_texpr_expr,'B Expression not properly wrapped: ',E).
174
175 get_texpr_type(b(_,Type,_),R) :- !, R=Type.
176 get_texpr_type(E,_) :- add_error_fail(get_texpr_type,'B Expression not properly wrapped: ',E).
177 get_texpr_info(b(_,_,Info),R) :- !, R=Info.
178 get_texpr_info(E,_) :- add_error_fail(get_texpr_info,'B Expression not properly wrapped: ',E).
179
180 get_texpr_id(b(N,_,_),Id) :- !, N=identifier(Id).
181 get_texpr_id(E,_) :- add_error_fail(get_texpr_id,'B Expression not properly wrapped: ',E).
182 /* same as above: but must succeed */
183 def_get_texpr_id(b(identifier(Id),_,_),R) :- !,R=Id.
184 def_get_texpr_id(ID,_) :- add_error(def_get_texpr_id,'Could not extract identifier: ',ID,ID),fail.
185
186 % translate a list of ids with the b/3 wrapper into a plain id list; throw error if not an identifier
187 % used to also be called get_texpr_id_names
188 def_get_texpr_ids(L,Ids) :- maplist(def_get_texpr_id,L,Ids).
189
190 create_typed_id(IDName,Type,b(identifier(IDName),Type,[])).
191
192 same_id(X,Y,ID) :- get_texpr_id(X,ID), get_texpr_id(Y,ID).
193
194
195 % check if two wrapped expressions are equal (modulo associated Info, e.g. source loc info)
196 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)
197 same_functor(E1,E2),
198 safe_syntaxelement(E1,Subs1,_Names1,_List1,Constant),
199 safe_syntaxelement(E2,Subs2,_Names2,_List2,Constant2),
200 Constant==Constant2, % in case we have values with variables inside !
201 same_sub_expressions(Subs1,Subs2).
202
203 same_sub_expressions([],[]).
204 same_sub_expressions([H1|T1],[H2|T2]) :- same_texpr(H1,H2), same_sub_expressions(T1,T2).
205
206 % check if two wrapped expressions definitely denote a different value (and are well-defined)
207 % only detects certain cases !
208 different_texpr_values(b(E1,Type,I1),b(E2,Type,I2)) :-
209 different_value(E1,E2,CheckWD),
210 (CheckWD=false -> true
211 ; always_well_defined_or_disprover_mode(b(E1,Type,I1)),
212 always_well_defined_or_disprover_mode(b(E2,Type,I2))).
213 different_value(boolean_false,boolean_true,false) :- !.
214 different_value(boolean_true,boolean_false,false) :- !.
215 different_value(integer(X),integer(Y),false) :- !, X\=Y.
216 different_value(string(X),string(Y),false) :- !, X\=Y.
217 different_value(empty_set,S,check_wd) :- !, non_empty_set(S).
218 different_value(S,empty_set,check_wd) :- !, non_empty_set(S).
219 % should we compare two set_extensions ? couples ? records ?
220
221 non_empty_set(set_extension([_|_])).
222 non_empty_set(sequence_extension([_|_])).
223 %non_empty_set(value(avl_set(node....
224
225
226 get_texpr_exprs([],[]).
227 get_texpr_exprs([E|Rest],[N|NRest]) :- get_texpr_expr(E,N),get_texpr_exprs(Rest,NRest).
228 get_texpr_types([],[]).
229 get_texpr_types([E|Rest],[T|TRest]) :- get_texpr_type(E,T),get_texpr_types(Rest,TRest).
230 get_texpr_infos([],[]).
231 get_texpr_infos([E|Rest],[I|IRest]) :- get_texpr_info(E,I),get_texpr_infos(Rest,IRest).
232 get_texpr_ids([],[]).
233 get_texpr_ids([E|Rest],[I|IRest]) :- get_texpr_id(E,I),get_texpr_ids(Rest,IRest).
234
235 get_texpr_pos(TExpr,Pos) :-
236 get_texpr_info(TExpr,Infos),
237 ? ( member(nodeid(Pos1),Infos) -> !,Pos=Pos1
238 ; Pos = none).
239
240 % similar to get_texpr_pos, but returns sub-list of infos relating to position
241 extract_pos_infos(Infos,InfoRes) :-
242 ? ( member(nodeid(Pos1),Infos) -> !,InfoRes=[nodeid(Pos1)]
243 ; InfoRes = []).
244
245 % copy position info from first arg to second argument
246 copy_pos_infos(b(_,_,Infos1),b(E,T,Infos2),b(E,T,Infos3)) :-
247 ? member(nodeid(Pos1),Infos1),!,
248 delete_pos_info(Infos2,Infos2d),
249 Infos3 = [nodeid(Pos1)|Infos2d].
250 copy_pos_infos(_,TE,TE).
251
252 delete_pos_info(Infos1,Infos2) :- delete(Infos1,nodeid(_),Infos2).
253
254 get_info_pos(Infos,Pos) :- (member(nodeid(Pos1),Infos) -> Pos=Pos1 ; Pos=none).
255 contains_info_pos(Infos) :- (member(nodeid(_),Infos) -> true).
256
257 create_texpr(Expr,Type,Info,b(Expr,Type,Info)).
258
259 add_texpr_infos(b(Expr,Type,Old),Infos,b(Expr,Type,New)) :- !,
260 append(Infos,Old,New).
261 add_texpr_infos(Other,Infos,Res) :-
262 add_internal_error('Illegal call, not BExpr:',add_texpr_infos(Other,Infos,Res)),fail.
263
264 add_texpr_info_if_new(b(Expr,Type,Old),Info,b(Expr,Type,New)) :- !,
265 add_info_if_new(Old,Info,New).
266 add_texpr_info_if_new(Other,Infos,Res) :-
267 add_internal_error('Illegal call, not BExpr:',add_texpr_info_if_new(Other,Infos,Res)),fail.
268 % add multiple infos:
269 add_texpr_infos_if_new(b(Expr,Type,Old),Infos,b(Expr,Type,New)) :-
270 add_infos(Infos,Old,New).
271
272 % add to info list:
273 add_info_if_new(Old,Info,New) :-
274 (member(Info,Old) -> New=Old ; New = [Info|Old]).
275
276 add_infos([]) --> [].
277 add_infos([Info|T]) --> add_info(Info), add_infos(T).
278 add_info(Info,Old,New) :-
279 ? (member(Info,Old) -> New=Old ; New = [Info|Old]).
280
281
282 % try and extract the Rodin name of a predicate or expression
283 get_rodin_name(Expression,Name) :- get_texpr_pos(Expression,rodinpos(Name,_)), Name \= [].
284 get_rodin_name(Expression,Name) :- get_texpr_pos(Expression,rodinpos(_Model,Name,_)), Name \= []. % new rodinpos
285
286 get_rodin_model_name(Expression,Model) :-
287 get_texpr_pos(Expression,rodinpos(Model,Name,_)), Name \= []. % new rodinpos
288
289 % try and extract the Rodin name or label pragma of a predicate or expression
290 get_texpr_labels(TExpr,Label) :-
291 get_texpr_info(TExpr,Infos),
292 ? member(I,Infos), info_label(I,Label).
293 get_info_labels(Infos,Label) :-
294 ? member(I,Infos), info_label(I,Label).
295 info_label(nodeid(rodinpos(Name,_)),[Name]) :- Name \= [].
296 info_label(nodeid(rodinpos(Model,Name,_)),[FullName]) :- Name \= [], % new rodinpos
297 ajoin([Model,':',Name], FullName). % TO DO: if only one level; don't do this
298 info_label(label(LabelList),LabelList).
299
300 add_labels_to_texpr(b(E,T,I),Labels,b(E,T,NewI)) :-
301 (select(label(OldList),I,Rest)
302 -> append(Labels,OldList,NewList), NewI=[label(NewList)|Rest]
303 % TO DO: what if we have Rodin labels
304 ; NewI = [label(Labels)|I]
305 ).
306
307 get_texpr_label(TExpr,Label) :- get_texpr_labels(TExpr,Labels), member(Label,Labels).
308
309 get_texpr_description(TExpr,Description) :-
310 get_texpr_info(TExpr,Infos),
311 memberchk(description(Description),Infos).
312
313 % check if an info list has an ignore pragma
314 info_has_ignore_pragma(Infos) :-
315 member(description(D),Infos), D='prob-ignore'.
316
317
318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
319
320 :- assert_must_succeed( (E = "1/2",
321 bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err),
322 Type==integer, Err==none, always_well_defined(ET) ) ).
323 :- assert_must_succeed( (E = "3 mod 2",
324 bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err),
325 Type==integer, Err==none, always_well_defined(ET) ) ).
326 :- assert_must_succeed( (E = "1/0",
327 bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err),
328 Type==integer, Err==none, \+ always_well_defined(ET) ) ).
329 :- assert_must_succeed( (E = "2*(3 mod card({}))",
330 bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err),
331 Type==integer, Err==none, \+ always_well_defined(ET) ) ).
332 :- assert_must_succeed( (E = "1/(2+1-3)",
333 bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err),
334 Type==integer, Err==none, \+ always_well_defined(ET) ) ).
335 :- assert_must_succeed( (E = "max({1,2,3,0})",
336 bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err),
337 Type==integer, Err==none, always_well_defined(ET) ) ).
338 :- assert_must_succeed( (E = "min({1,2,3,0})",
339 bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err),
340 Type==integer, Err==none, always_well_defined(ET) ) ).
341 :- assert_must_succeed( (E = "min({1,2,3,0}-(0..4))",
342 bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err),
343 Type==integer, Err==none, \+ always_well_defined(ET) ) ).
344 :- assert_must_succeed( (E = "2+max({1,2,3, 1/0})",
345 bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err),
346 Type==integer, Err==none,\+ always_well_defined(ET) ) ).
347 :- assert_must_succeed( (E = "2-card({1,2,3})",
348 bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err),
349 Type==integer, Err==none, always_well_defined(ET) ) ).
350 :- assert_must_succeed( (E = "2-card({1,2,3, 1/0})",
351 bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err),
352 Type==integer, Err==none,\+ always_well_defined(ET) ) ).
353 :- assert_must_succeed( (E = "bool(2-size([1,2,3, 1/0])=3)",
354 bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err),
355 Type==boolean, Err==none, \+ always_well_defined(ET) ) ).
356 :- assert_must_succeed( (E = "bool(2-size([1,2,3, 1/2, 3 mod 2, 3**2])=size([]))",
357 bmachine:b_parse_machine_expression_from_codes(E,ET,Type,false,Err),
358 Type==boolean, Err==none, always_well_defined(ET) ) ).
359
360 always_well_defined_or_disprover_mode(BE) :-
361 (preferences:preference(disprover_mode,true) -> true % we can assume all calls are well-defined
362 ; always_well_defined(BE)).
363
364 always_well_defined(b(E,_,Infos)) :- !,
365 (nonmember(contains_wd_condition,Infos) -> true
366 ; always_wd(E) -> true % some special rules
367 %; nl, functor(E,F,N), F \= function, print(non_wd(F,N)),nl,nl,fail
368 ).
369 always_well_defined(E) :- add_error_fail(always_well_defined,'Illegal call: ',always_well_defined(E)).
370
371
372 :- assert_must_succeed( always_wd(div( b(integer(2),integer,[]), b(integer(2),integer,[]) )) ).
373 :- assert_must_fail( always_wd(div( b(integer(2),integer,[]), b(integer(0),integer,[]) )) ).
374 :- assert_must_succeed( always_wd(modulo( b(integer(2),integer,[]), b(integer(2),integer,[]) )) ).
375 :- assert_must_fail( always_wd(modulo( b(integer(2),integer,[]), b(integer(0),integer,[]) )) ).
376 :- assert_must_fail( always_wd(modulo( b(integer(2),integer,[]), b(integer(-2),integer,[]) )) ).
377 :- assert_must_fail( always_wd(modulo( b(integer(-1),integer,[]), b(integer(2),integer,[]) )) ).
378 :- assert_must_succeed( always_wd(power_of( b(integer(2),integer,[]), b(integer(3),integer,[]) )) ).
379 :- assert_must_succeed( always_wd(power_of( b(integer(2),integer,[]), b(integer(0),integer,[]) )) ).
380 :- assert_must_fail( always_wd(power_of( b(integer(2),integer,[]), b(integer(-1),integer,[]) )) ).
381
382 % catch cases where the construct is currently so instantiated that we can determine that it is well-defined
383 % can happen e.g. during closure compilation
384 :- use_module(custom_explicit_sets,[check_in_domain_of_avlset/2]).
385 :- use_module(kernel_tools,[ground_value/1]).
386 always_wd(power_of(X,Y)) :- integer_value(Y,Val), number(Val),Val>=0, always_well_defined(X).
387 always_wd(div(X,Y)) :- integer_value(Y,Val), number(Val),Val\=0, always_well_defined(X).
388 always_wd(modulo(X,Y)) :- integer_value(Y,Val), number(Val),Val>0,
389 integer_value(X,ValX), number(ValX), ValX>=0. % TO DO: maybe treat this differently in TLA / Event-B minor mode ?
390 always_wd(function(X,Y)) :- nonvar(X),
391 X= b(value(AVLSET),_,_), nonvar(AVLSET), AVLSET=avl_set(AVL),
392 always_wd_avl_function(AVL,Y).
393 always_wd(min(X)) :- non_empty_wd_set_value(X).
394 always_wd(max(X)) :- non_empty_wd_set_value(X).
395 always_wd(card(X)) :- finite_wd_set_value(X).
396 always_wd(size(X)) :- finite_wd_seq_value(X).
397 always_wd(first(X)) :- non_empty_wd_seq_value(X).
398 always_wd(front(X)) :- non_empty_wd_seq_value(X).
399 always_wd(last(X)) :- non_empty_wd_seq_value(X).
400 always_wd(tail(X)) :- non_empty_wd_seq_value(X). % TO DO: add restrict_front, restrict_tail ?
401 always_wd(general_intersection(X)) :- non_empty_wd_set_value(X).
402 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
403 % other candidates: size(_), first(_) last(_) tail(_) front(_) restrict_front(_,_) restrict_tail(_,_) rel_iterate(_,_)
404 always_wd(typeset).
405 % operators that are always wd on their own:
406 always_wd(record_field(RecEx,FieldName)) :- ground(FieldName),
407 always_well_defined(RecEx).
408 always_wd(unary_minus(A)) :- always_well_defined(A).
409 always_wd(first_of_pair(A)) :- always_well_defined(A).
410 always_wd(add(A,B)) :- always_well_defined(A),always_well_defined(B).
411 always_wd(minus(A,B)) :- always_well_defined(A),always_well_defined(B).
412 always_wd(equal(A,B)) :- always_well_defined(A),always_well_defined(B).
413 always_wd(not_equal(A,B)) :- always_well_defined(A),always_well_defined(B).
414 always_wd(less_equal(A,B)) :- always_well_defined(A),always_well_defined(B).
415 always_wd(greater_equal(A,B)) :- always_well_defined(A),always_well_defined(B).
416 always_wd(less(A,B)) :- always_well_defined(A),always_well_defined(B).
417 always_wd(greater(A,B)) :- always_well_defined(A),always_well_defined(B).
418 always_wd(couple(A,B)) :- always_well_defined(A),always_well_defined(B).
419 % TO DO: add more/all other operators ?
420
421 always_wd_avl_function(AVL,Y) :- nonvar(Y), Y= b(value(Val),_,_),
422 ground_value(Val), !,
423 check_in_domain_of_avlset(Val,AVL). % ,print(ok),nl.
424 always_wd_avl_function(AVL,Y) :- always_well_defined(Y),
425 custom_explicit_sets:quick_definitely_maximal_total_function_avl(AVL).
426
427 integer_value(b(E,integer,_),Val) :- integer_value2(E,Val).
428 integer_value2(integer(X),R) :- !, R=X.
429 integer_value2(value(int(X)),R) :- !, R=X.
430 %integer_value2(X,_) :- print(not_integer_value2(X)),nl,fail.
431
432 non_empty_wd_set_value(b(E,_,_)) :- non_empty_set2(E).
433 non_empty_set2(value(X)) :- definitely_not_empty(X).
434 non_empty_set2(set_extension(S)) :- l_always_well_defined(S). % the set_extension could contain wd_errors !!
435 non_empty_set2(sequence_extension(S)) :- l_always_well_defined(S). % ditto
436 definitely_not_empty(X) :- var(X),!,fail.
437 definitely_not_empty(avl_set(_)).
438 definitely_not_empty([_|_]).
439
440 non_empty_wd_seq_value(b(E,_,_)) :- non_empty_seq2(E).
441 non_empty_seq2(value(X)) :- definitely_not_empty_seq(X).
442 non_empty_seq2(sequence_extension(S)) :- l_always_well_defined(S), S=[_|_].
443
444 definitely_not_empty_seq(X) :- var(X),!,fail.
445 definitely_not_empty_seq(avl_set(A)) :- custom_explicit_sets:is_avl_sequence(A).
446 definitely_not_empty_seq([El1|T]) :- T==[],nonvar(El1), El1=(IDX,_), IDX==int(1). % TO DO: add more cases ?
447
448
449 finite_wd_set_value(b(E,_,_)) :- finite_set2(E).
450 finite_set2(empty_set).
451 finite_set2(empty_sequence).
452 finite_set2(value(X)) :- X==[] -> true ; definitely_not_empty(X).
453 finite_set2(set_extension(S)) :- l_always_well_defined(S). % the set_extension could contain wd_errors !!
454 finite_set2(sequence_extension(S)) :- l_always_well_defined(S). % ditto
455
456 finite_wd_seq_value(b(E,_,_)) :- finite_seq2(E).
457 finite_seq2(empty_set).
458 finite_seq2(empty_sequence).
459 finite_seq2(value(X)) :- finite_seq_value(X).
460 finite_seq2(sequence_extension(S)) :- l_always_well_defined(S).
461
462 finite_seq_value(X) :- var(X),!,fail.
463 finite_seq_value([]).
464 finite_seq_value(avl_set(A)) :- custom_explicit_sets:is_avl_sequence(A).
465 % it could be expensive to check if non empty list is a B sequence ??
466
467 l_always_well_defined([]).
468 l_always_well_defined([H|T]) :- always_well_defined(H), l_always_well_defined(T).
469
470 is_truth(b(F,pred,_)) :- is_truth_aux(F).
471 is_truth_aux(truth).
472 is_truth_aux(value(V)) :- V==pred_true. % can occur in CSE mode
473
474 is_falsity(b(F,pred,_)) :- is_falsity_aux(F).
475 is_falsity_aux(falsity).
476 is_falsity_aux(value(V)) :- V==pred_false. % can occur in CSE mode
477
478 % conjunction of a list of predicates
479 % NOTE: bsyntaxtree:conjunct_predicates([P1,P2,P3],R). --> generates R = b(conjunct(b(conjunct(P1,P2),pred,[]),P3),pred,[])
480 conjunct_predicates(V,R) :- var(V),!, add_internal_error('Variable conjunction list: ',conjunct_predicates(V,R)),fail.
481 conjunct_predicates([],b(truth,pred,[])).
482 conjunct_predicates([P|Rest],Result) :- conjunct2(Rest,P,Result).
483 conjunct2([],P,P).
484 conjunct2([Q|Rest],P,Result) :- conjunct3(P,Q,R), conjunct2(Rest,R,Result).
485 conjunct3(b(truth,_,_),P,P) :- !.
486 conjunct3(P,b(truth,_,_),P) :- !.
487 conjunct3(A,B,b(conjunct(A,B),pred,NewInfo)) :- extract_info(A,B,NewInfo).
488
489 % disjunction of a list of predicates
490 disjunct_predicates([],b(falsity,pred,[])).
491 disjunct_predicates([P|Rest],Result) :- disjunct2(Rest,P,Result).
492 disjunct2([],P,P).
493 disjunct2([Q|Rest],P,Result) :- disjunct3(P,Q,R), disjunct2(Rest,R,Result).
494 disjunct3(b(falsity,_,_),P,R) :- !, R=P.
495 disjunct3(b(truth,T,I),_,R) :- !, R=b(truth,T,I).
496 disjunct3(P,b(falsity,_,_),R) :- !, R=P.
497 disjunct3(_,b(truth,T,I),R) :- !, R=b(truth,T,I).
498 disjunct3(A,B,b(disjunct(A,B),pred,NewInfo)) :- extract_info(A,B,NewInfo).
499
500 % conjunct two predicates and try and construct position information
501 conjunct_predicates_with_pos_info(A,B,AB) :-
502 conjunct_predicates([A,B],AB0),
503 (try_get_merged_position_info(A,B,ABI)
504 -> add_texpr_infos(AB0,[ABI],AB) %,print(abi(ABI)),nl
505 ; AB=AB0).
506
507 try_get_merged_position_info(b(_,_,I1),b(_,_,I2),PosInfo) :-
508 try_get_merged_position_info_aux(I1,I2,PosInfo).
509 try_get_merged_position_info_aux(I1,I2,nodeid(pos(C,Filenumber,Srow,Scol,Erow,Ecol))) :-
510 ? member(nodeid(pos(C1,Filenumber,Srow1,Scol1,Erow1,Ecol1)),I1),!,
511 ? member(nodeid(pos(C2,Filenumber,Srow2,Scol2,Erow2,Ecol2)),I2),!,
512 % merge position info if in same file
513 (C1 =< C2 -> C=C1, Srow=Srow1,Scol=Scol1 ; C=C2, Srow=Srow2,Scol=Scol2),
514 ? ((Erow1 > Erow2 ; Erow1=Erow2, Ecol1 >= Ecol2)
515 -> Erow =Erow1, Ecol=Ecol1
516 ; Erow =Erow2, Ecol=Ecol2).
517
518
519 % a version of create_texpr which collects automatically important infos from sub-expressions
520 safe_create_texpr(Expr,Type,b(Expr,Type,Info)) :- %
521 ? (sub_expression_contains_wd_condition(Expr) -> Info = [contains_wd_condition] ; Info=[]).
522
523 safe_create_texpr(Expr,Type,Info,b(Expr,Type,FullInfo)) :- %
524 ? (sub_expression_contains_wd_condition(Expr) -> FullInfo = [contains_wd_condition|Info] ; FullInfo=Info).
525
526 ?sub_expression_contains_wd_condition(Expr) :- sub_expression_contains_wd_condition(Expr,_).
527 sub_expression_contains_wd_condition(Expr,Sub) :-
528 ? safe_syntaxelement(Expr,Subs,_Names,_L,_C),
529 ? member(b(Sub,_,Infos),Subs),
530 (var(Infos)
531 -> add_internal_error('Expression not sufficiently instantiated: ',sub_expression_contains_wd_condition(Expr)),
532 fail
533 ; memberchk(contains_wd_condition,Infos)).
534
535 % provide updated infos (e.g., reads(...)) and remove any old info fields with same functor
536 update_infos([],Infos,Infos).
537 update_infos([Update|T],OldInfos,NewInfos) :-
538 functor(Update,F,N),
539 functor(Old,F,N),
540 delete(OldInfos,Old,OldInfos1),
541 update_infos(T,[Update|OldInfos1],NewInfos).
542
543 % merge two info lists and try to reconcile position information:
544 merge_info(Info1,Info2,Res) :-
545 extract_info_aux(Info2,Info1,NewInfo),
546 (try_get_merged_position_info_aux(Info1,Info2,NewPos)
547 -> delete_pos_info(NewInfo,NI2),
548 Res = [NewPos|NI2]
549 ; Res = NewInfo).
550
551 % extract important info but without used_ids:
552 extract_info_wo_used_ids(BExpr,Info) :- extract_info(BExpr,Info1),
553 ? (select(used_ids(_),Info1,Rest) -> Info=Rest ; Info=Info1).
554 extract_info_wo_used_ids(BExpr1,BExpr2,Info) :- extract_info(BExpr1,BExpr2,Info1),
555 (select(used_ids(_),Info1,Rest) -> Info=Rest ; Info=Info1).
556
557 % extract important info from one sub-expression:
558 extract_info(b(_,_,Info1),NewInfo) :-
559 extract_info_aux(Info1,[],I1),!, NewInfo = I1.
560 extract_info(A,R) :- add_internal_error('Could not extract info: ',extract_info(A,R)),
561 R=[].
562 % extract imortant info fields from two (sub-)expressions
563 extract_info(b(_,_,Info1),b(_,_,Info2),NewInfo) :-
564 extract_info_aux(Info1,[],I1),
565 ? extract_info_aux(Info2,I1,I2),!, NewInfo = I2.
566 %:- use_module(library(ordsets),[ord_intersection/3]).
567 % ord_intersection(Info1,Info2,NewInfo),!.
568 % TO DO: should we merge nodeid position information !?
569 extract_info(A,B,R) :- add_internal_error('Could not extract info: ',extract_info(A,B,R)),
570 R=[].
571
572 extract_info_aux([],Acc,Acc).
573 extract_info_aux([used_ids(Ids)|T],Acc,Res) :- !,
574 ? (select(used_ids(Ids2),Acc,Acc2) -> ord_union(Ids,Ids2,Ids3) ; Ids3 = Ids,Acc2=Acc), % merge used identifeirs
575 extract_info_aux(T,[used_ids(Ids3)|Acc2],Res).
576 extract_info_aux([H|T],Acc,Res) :-
577 ? (important_info(H), \+ member(H,Acc) -> extract_info_aux(T,[H|Acc],Res)
578 ; extract_info_aux(T,Acc,Res)).
579 important_info(contains_wd_condition).
580 important_info(prob_annotation(_)).
581 important_info(allow_to_lift_exists).
582 important_info(removed_typing).
583
584 is_a_conjunct(b(conjunct(A,B),pred,_),A,B).
585 % use is_a_conjunct_without_label if you want to avoid decomposing conjunction associated with a single label
586 is_a_conjunct_without_label(b(conjunct(A,B),pred,I),A,B) :- \+ get_info_labels(I,_).
587 % use decompose conjunct if you want to propagate labels down to the conjuncts
588 decompose_conjunct(b(conjunct(A,B),pred,I),ResA,ResB) :-
589 (get_info_labels(I,Labels)
590 -> add_labels_to_texpr(A,Labels,ResA), add_labels_to_texpr(B,Labels,ResB)
591 ; ResA=A, ResB=B).
592
593 conjunction_to_list(C,L) :- var(C),!,
594 add_error_fail(conjunction_to_list,'Internal error: var :',conjunction_to_list(C,L)).
595 conjunction_to_list(C,List) :-
596 conjunction_to_list2(C,List,[]).
597 conjunction_to_list2(X,I,O) :- X=b(E,_,_),
598 (E=conjunct(LHS,RHS) -> conjunction_to_list2(LHS,I,Inter),
599 conjunction_to_list2(RHS,Inter,O)
600 ; E = truth -> I=O
601 ; I = [X|O]).
602
603 ?member_in_conjunction(M,Conj) :- is_a_conjunct(Conj,LHS,RHS),!,
604 ? (member_in_conjunction(M,LHS) ; member_in_conjunction(M,RHS)).
605 member_in_conjunction(M,M).
606
607 % a version of member_in_conjunction which can deal with lazy_let_pred :
608 % member_in_conjunction_cse(FullConjunctWithLets,InnerConjunctNotALet, Conjunction)
609 member_in_conjunction_cse(M,InnerConj,Conj) :- is_a_conjunct(Conj,LHS,RHS),!,
610 (member_in_conjunction_cse(M,InnerConj,LHS) ; member_in_conjunction_cse(M,InnerConj,RHS)).
611 member_in_conjunction_cse(Conj,InnerConj,b(lazy_let_pred(ID,Share,Body),pred,Info)) :-
612 Conj = b(lazy_let_pred(ID,Share,BConj),pred,Info),!,
613 member_in_conjunction_cse(BConj,InnerConj,Body).
614 member_in_conjunction_cse(M,M,M).
615
616 % not terribly efficient way to select and remove a conjunct from a predicate
617 ?select_member_in_conjunction(M,Conj,Rest) :- is_a_conjunct(Conj,LHS,RHS),!,
618 ? (select_member_in_conjunction(M,LHS,RL), conjunct_predicates([RL,RHS],Rest)
619 ; select_member_in_conjunction(M,RHS,RR), conjunct_predicates([LHS,RR],Rest)).
620 select_member_in_conjunction(M,M,b(truth,pred,[])).
621
622 is_a_disjunct(b(disjunct(A,B),pred,_),A,B).
623 is_a_negation(b(negation(A),pred,_),A).
624
625 disjunction_to_list(C,L) :- var(C),!,
626 add_error_fail(disjunction_to_list,'Internal error: var :',disjunction_to_list(C,L)).
627 disjunction_to_list(C,List) :-
628 disjunction_to_list2(C,List,[]).
629 disjunction_to_list2(C,I,O) :- is_a_disjunct(C,LHS,RHS),!,
630 disjunction_to_list2(LHS,I,Inter),
631 disjunction_to_list2(RHS,Inter,O).
632 disjunction_to_list2(X,[X|R],R).
633
634 is_an_implication(b(implication(A,B),pred,_),A,B).
635
636 is_an_equivalence(b(equivalence(A,B),pred,_),A,B).
637
638
639 is_a_disjunct_or_implication(b(DI,pred,_),Type,A,B) :- is_a_disj_or_impl_aux(DI,Type,A,B).
640 is_a_disj_or_impl_aux(disjunct(A,B),'disjunction',A,B).
641 is_a_disj_or_impl_aux(implication(A,B),'implication',NA,B) :-
642 create_negation(A,NA).
643 is_a_disj_or_impl_aux(negation(b(conjunct(A,B),pred,_)),'negated conjunction',NA,NB) :-
644 create_negation(A,NA),create_negation(B,NB).
645
646 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
647 % remove all info fields
648 remove_all_infos(TExpr,TNExpr) :-
649 var(TExpr),!,TExpr=TNExpr.
650 remove_all_infos(TExpr,TNExpr) :-
651 get_texpr_expr(TExpr,Expr),
652 get_texpr_type(TExpr,Type),
653 syntaxtransformation(Expr,Subs,_,NSubs,NExpr),
654 create_texpr(NExpr,Type,_,TNExpr),
655 maplist(remove_all_infos,Subs,NSubs).
656
657 % replace all info fields
658 remove_all_infos_and_ground(TExpr,TNExpr) :-
659 var(TExpr),!,TExpr=TNExpr.
660 remove_all_infos_and_ground(TExpr,TNExpr) :-
661 get_texpr_expr(TExpr,Expr),
662 get_texpr_type(TExpr,Type),
663 syntaxtransformation(Expr,Subs,_,NSubs,NExpr),
664 create_texpr(NExpr,Type,[],TNExpr),
665 maplist(remove_all_infos_and_ground,Subs,NSubs).
666
667 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
668
669 % create_exists_opt(TIds,Preds,NewPred)
670 % creating an existential quantification with some optimisations.
671 % TIds: The typed identifiers that are quantified
672 % Preds: A list of predicates
673 % NewPred: The (optimised) quantified expression
674 % Basically two optimisations are performed:
675 % - identifiers that are not used at all are removed from the quantifier
676 % - predicates that do not use one of the quantified identifiers are moved
677 % outside the quantification, resulting in a predicate of the form "P & #x.Q(x)"
678
679 create_exists_opt(TIds,Preds,NewPred) :-
680 create_exists_opt(TIds,Preds,[],NewPred,_).
681 create_exists_opt(TIds,Preds,NewPred,Modified) :-
682 create_exists_opt(TIds,Preds,[],NewPred,Modified).
683 create_exists_opt([],Preds,_,NewPred,Modified) :- !, Modified = false,
684 conjunct_predicates(Preds,NewPred).
685 create_exists_opt(TIds,Preds,AdditionalInfos,NewPred,Modified) :-
686 preference(data_validation_mode,true),
687 % no not lift predicates outside of existential quantifiers and change order; see rule_avec_DV.mch ClearSy example
688 !, Modified=false, % print(not_optimizing_exists(TIds)),nl,
689 conjunct_predicates(Preds,P),
690 create_exists_detect_tautology_aux(TIds,P,AdditionalInfos,NewPred).
691 create_exists_opt(TIds,Preds,AdditionalInfos,NewPred2,Modified) :-
692 get_texpr_ids(TIds,UnsortedIds), sort(UnsortedIds,Ids),
693 create_exists_opt2(Preds,Ids,[],Inner,Outer,UsedIds),
694 % Inner: quantified part, Outer: part which does not have to be quantified
695 ( Inner = [] -> AllPreds=Outer % no exists needed
696 ; % Inner = [_|_] ->
697 ceo_filter_used_ids(TIds,UsedIds,UsedTIds), % filter out unused variables
698 conjunct_predicates(Inner,I),
699 create_exists_detect_tautology_aux(UsedTIds,I,AdditionalInfos,Exists),
700 % remove_typing also added in create_exists_detect_tautology_aux
701 append(Outer,[Exists],AllPreds)
702 ),
703 (Outer=[_|_] -> Modified=true % TO DO: check if TIds=UsedTIds
704 ; UsedIds == Ids -> Modified= false
705 ; Modified=true),
706 conjunct_predicates(AllPreds,NewPred2).
707 create_exists_opt2([],_Ids,UsedIds,[],[],UsedIds) :- !.
708 create_exists_opt2([Pred|Prest],Ids,UsedIdsIn,Inner,Outer,UsedIdsOut) :- !,
709 find_identifier_uses(Pred, [], LocalUses),
710 ord_intersection(Ids,LocalUses,LocalExUses),
711 %translate:print_bexpr(Pred), format(' Uses ~w [~w]~n',[LocalUses,LocalExUses]),
712 ( LocalExUses = [] ->
713 Inner = Irest,
714 Outer = [Pred|Orest], % move outside of existential quantifier
715 UsedIdsIn = Urest
716 ; LocalExUses = [_|_] ->
717 Inner = [Pred|Irest],
718 Outer = Orest,
719 ord_union(UsedIdsIn,LocalExUses,Urest)
720 ),
721 create_exists_opt2(Prest,Ids,Urest,Irest,Orest,UsedIdsOut).
722 create_exists_opt2(Pred,Ids,UsedIdsIn,Inner,Outer,UsedIdsOut) :-
723 add_error(create_exists_opt,'Expecting predicate list: ',Pred),
724 create_exists_opt2([Pred],Ids,UsedIdsIn,Inner,Outer,UsedIdsOut).
725
726 ceo_filter_used_ids([],_UsedIds,[]).
727 ceo_filter_used_ids([TId|Irest],UsedIds,Filtered) :-
728 get_texpr_id(TId,Id),
729 ( ord_member(Id,UsedIds) -> Filtered = [TId|Frest] % id used: keep it
730 ; otherwise -> Filtered = Frest),
731 ceo_filter_used_ids(Irest,UsedIds,Frest).
732
733 % a version of create_exists which also detects x=E and x:E and x>E tautologies
734 % we could replace this by a more generic prover
735 create_exists_detect_tautology_aux([TID],Pred,_,Truth) :- % print(create(TID,Pred)),nl,
736 ? is_equal(Pred,LHS,RHS),
737 get_texpr_id(LHS,ID), get_texpr_id(TID,ID),
738 \+ occurs_in_expr(ID,RHS),
739 always_well_defined_or_disprover_mode(RHS),
740 !, % replace #x.(x=E) by TRUTH
741 debug_format(19,'Detected tautology exists equality over ~w~n',[ID]),
742 Truth=b(truth,pred,[]).
743 create_exists_detect_tautology_aux([TID],Pred,_,Truth) :-
744 Pred = b(member(LHS,RHS),pred,_),
745 get_texpr_id(LHS,ID), get_texpr_id(TID,ID),
746 definitely_not_empty_set(RHS),
747 always_well_defined_or_disprover_mode(RHS),
748 !, % replace #x.(x=E) by TRUTH
749 debug_format(19,'Detected tautology exists membership over ~w~n',[ID]),
750 Truth=b(truth,pred,[]).
751 create_exists_detect_tautology_aux([TID],b(Pred,_,_),_,Truth) :-
752 is_comparison(Pred,L,R), get_texpr_id(TID,ID),
753 ((LHS,RHS)=(L,R) ; (LHS,RHS)=(R,L)),
754 get_texpr_id(LHS,ID),
755 \+ occurs_in_expr(ID,RHS),
756 always_well_defined_or_disprover_mode(RHS),
757 !, % replace #x.(x COMP E) by TRUTH
758 debug_format(19,'Detected tautology comparison over ~w~n',[ID]),
759 Truth=b(truth,pred,[]).
760 create_exists_detect_tautology_aux(Ids,Pred,AdditionalInfos,NewPred2) :-
761 create_exists_or_let_predicate(Ids,Pred,NewPred),
762 add_texpr_infos_if_new(NewPred,[removed_typing|AdditionalInfos],NewPred2).
763 % removed_typing to avoid spurious exists_body_warning, see test 1681, 625
764
765 is_equal(b(equal(LHS,RHS),pred,_),A,B) :-
766 ? ((A,B)=(LHS,RHS) ; (A,B)=(RHS,LHS)).
767
768 is_comparison(greater(A,B),A,B).
769 is_comparison(less(A,B),A,B).
770 is_comparison(greater_equal(A,B),A,B).
771 is_comparison(less_equal(A,B),A,B).
772
773 % is true if a predicate Pred can be split into two parts:
774 % Outer which does not depend on LocalIds and Inner which does
775 detect_global_predicates(LocalIds,Pred,Outer,Inner) :-
776 get_texpr_ids(LocalIds,UnsortedIds), sort(UnsortedIds,Ids),
777 conjunction_to_list(Pred,Preds),
778 split_predicate(Preds,Ids,OuterL,InnerL),
779 OuterL \= [],
780 conjunct_predicates(OuterL,Outer),
781 conjunct_predicates(InnerL,Inner).
782 split_predicate([],_Ids,[],[]).
783 split_predicate([P|Ps],Ids,Outer,Inner) :-
784 (is_local_predicate(Ids,P)
785 -> Inner = [P|Is], split_predicate(Ps,Ids,Outer,Is)
786 ; Outer = [P|Os], split_predicate(Ps,Ids,Os,Inner)).
787 is_local_predicate(Ids,Pred) :-
788 find_identifier_uses(Pred, [], LocalUses),
789 ord_intersect(Ids,LocalUses).
790
791 %:- use_module(b_global_sets,[b_global_set/1]).
792 definitely_not_empty_set(b(SET,T,_)) :- not_empty_set_aux(SET,T).
793 not_empty_set_aux(bool_set(_),_).
794 not_empty_set_aux(integer_set(_),_).
795 not_empty_set_aux(string_set,_).
796 not_empty_set_aux(set_extension(X),_) :- dif(X,[]).
797 not_empty_set_aux(sequence_extension(X),_) :- dif(X,[]).
798 not_empty_set_aux(value(S),_) :- nonvar(S), (S=avl_set(_) -> true ; S=[_|_]).
799 %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 !
800 % TO DO: determine which identifier(X) refer to global set names
801 not_empty_set_aux(interval(A,B),_) :- get_texpr_expr(A,integer(IA)), get_texpr_expr(B,integer(IB)), IA =< IB.
802
803
804 % a simple let-detection
805 create_exists_or_let_predicate([H|T],b(conjunct(LHS,RHS),pred,I),NewPred) :- get_texpr_id(H,ID),
806 ? is_equal(LHS,TID,IDEXPR), % TO DO: should we do a more complicated check here ? exist technique useful for SLOT-24 codespeed test
807 get_texpr_id(TID,ID), \+ occurs_in_expr(ID,IDEXPR),
808 maplist(not_occurs_in_expr(IDEXPR),T),
809 !,
810 NewPred = b(let_predicate([TID],[IDEXPR],Body),pred,I),
811 %print('LET: '),translate:print_bexpr(NewPred),nl,
812 create_exists_or_let_predicate(T,RHS,Body).
813 create_exists_or_let_predicate(Ids,Pred,NewPred) :- create_exists(Ids,Pred,NewPred).
814
815 not_occurs_in_expr(IDEXPR,TID) :- get_texpr_id(TID,ID), \+ occurs_in_expr(ID,IDEXPR).
816
817 create_exists([],Pred,NewPred) :- !,Pred=NewPred.
818 create_exists(Ids,Pred,NewPred) :-
819 Ex = exists(Ids,Pred),
820 find_identifier_uses(b(Ex,pred,[]), [], Used),
821 extract_info_wo_used_ids(Pred,NewImportantInfo),
822 create_texpr(Ex,pred,[used_ids(Used)|NewImportantInfo],NewPred).
823
824
825 create_forall([],Pred,NewPred) :- !,Pred=NewPred.
826 create_forall(Ids,Pred,NewPred) :-
827 split_forall_body(Pred,LHS,RHS),
828 For = forall(Ids,LHS,RHS),
829 find_identifier_uses(b(For,pred,[]), [], Used),
830 extract_info_wo_used_ids(LHS,RHS,NewImportantInfo),
831 create_texpr(For,pred,[used_ids(Used)|NewImportantInfo],NewPred).
832 split_forall_body(b(implication(LHS,RHS),_,_),LHS,RHS) :- !.
833 split_forall_body(RHS,b(truth,pred,[]),RHS).
834
835 create_implication(b(truth,pred,_),P,Res) :- !, Res=P.
836 create_implication(b(falsity,pred,_),P,Res) :- !, create_negation(P,Res).
837 create_implication(Lhs,Rhs,b(implication(Lhs,Rhs),pred,NewInfo)) :-
838 extract_info(Lhs,Rhs,NewInfo).
839
840 create_equivalence(Lhs,Rhs, b(equivalence(Lhs,Rhs),pred,NewInfo)) :-
841 extract_info(Lhs,Rhs,NewInfo).
842
843 create_negation(b(truth,pred,I),R) :- !, R=b(falsity,pred,I).
844 create_negation(b(falsity,pred,I),R) :- !, R=b(truth,pred,I).
845 create_negation(b(negation(Pred),pred,_),R) :- !, R=Pred. % not(not(P)) = P
846 % we could add some rules about negating member <-> not_member, ...
847 create_negation(Pred,b(negation(Pred),pred,NewInfo)) :- extract_info(Pred,NewInfo).
848
849 % check if something is the negation of something else (quite stupid at the moment)
850 is_negation_of(P,NP) :-
851 create_negation(P,NotP),
852 same_texpr(NotP,NP).
853 is_negation_of(b(P,pred,_),b(NP,pred,_)) :- is_negation_aux(P,NP).
854
855 is_negation_aux(equal(A,B),NP) :-
856 is_negation_of_equality(NP,A,B).
857 is_negation_aux(subset(XA,SA),not_subset(XB,SB)) :- same_texpr(XA,XB), same_texpr(SA,SB).
858 is_negation_aux(not_subset(XA,SA),subset(XB,SB)) :- same_texpr(XA,XB), same_texpr(SA,SB).
859 is_negation_aux(subset_strict(XA,SA),not_subset_strict(XB,SB)) :- same_texpr(XA,XB), same_texpr(SA,SB).
860 is_negation_aux(not_subset_strict(XA,SA),subset_strict(XB,SB)) :- same_texpr(XA,XB), same_texpr(SA,SB).
861 is_negation_aux(member(XA,SA),not_member(XB,SB)) :- same_texpr(XA,XB), same_texpr(SA,SB).
862 is_negation_aux(not_member(XA,SA),member(XB,SB)) :- same_texpr(XA,XB), same_texpr(SA,SB).
863 is_negation_aux(less(A,B),greater_equal(AA,BB)) :- same_texpr(A,AA), same_texpr(B,BB).
864 is_negation_aux(less(A,B),less_equal(BB,AA)) :- same_texpr(A,AA), same_texpr(B,BB).
865 is_negation_aux(less_equal(B,A),less(AA,BB)) :- same_texpr(A,AA), same_texpr(B,BB).
866 is_negation_aux(less_equal(A,B),greater(AA,BB)) :- same_texpr(A,AA), same_texpr(B,BB).
867 is_negation_aux(greater_equal(A,B),NP) :- is_negation_aux(less_equal(B,A),NP).
868 is_negation_aux(greater(A,B),NP) :- is_negation_aux(less(B,A),NP).
869 % TO DO: detect more ?? x < y <=> not ( x > y-1 )
870
871 is_negation_of_equality(not_equal(AA,BB),A,B) :- same_texpr(A,AA), same_texpr(B,BB).
872 is_negation_of_equality(equal(AA,BB),A,B) :- same_texpr(A,AA), neg_value(BB,B).
873
874 neg_value(b(boolean_true,_,_),b(boolean_false,_,_)).
875 neg_value(b(boolean_false,_,_),b(boolean_true,_,_)).
876
877
878 create_couple(A,B,b(couple(A,B),couple(TA,TB),Infos)) :-
879 get_texpr_type(A,TA), get_texpr_type(B,TB),
880 extract_info(A,B,Infos).
881
882 create_couple([A],Couple) :- !,A=Couple.
883 create_couple([A,B|Rest],Couple) :-
884 create_couple(A,B,Couple1),
885 create_couple([Couple1|Rest],Couple).
886
887
888 % --------------------------------------
889
890
891 % find uses of identifiers
892
893 occurs_in_expr(ID,TExpr) :- var(ID),!,
894 add_internal_error('Variable id: ',occurs_in_expr(ID,TExpr)),fail.
895 occurs_in_expr(ID,TExpr) :- ID=b(_,_,_),!, add_internal_error('Non-atomic identifier: ',occurs_in_expr(ID,TExpr)),fail.
896 occurs_in_expr(ID,TExpr) :-
897 (find_identifier_uses(TExpr,[],Used)
898 -> %check_sorted(Used),
899 ord_member(ID,Used)
900 ; add_failed_call_error(find_identifier_uses(TExpr,[],_)),fail).
901 % TO DO: optimize so that we only look for ID; we don't have to keep track of other IDs
902
903 %check_sorted(List) :- sort(List,SL), (SL \= List -> add_internal_error('Not sorted:',List) ; true).
904
905 some_id_occurs_in_expr([H|T],TExpr) :- (var(H) ; \+ atomic(H)),
906 add_internal_error('Must be (sorted) atomic identifiers: ',some_id_occurs_in_expr([H|T],TExpr)),
907 fail.
908 some_id_occurs_in_expr(SortedIDs,TExpr) :-
909 find_identifier_uses(TExpr,[],Used),
910 list_to_ord_set(Used,UsedSorted),
911 ord_intersect(UsedSorted,SortedIDs).
912
913 :- use_module(tools,[safe_sort/3]).
914 find_identifier_uses(TExpr,Ignored,Ids) :-
915 %tools_printing:print_term_summary(find_identifier_uses(TExpr,Ignored,Ids)),nl,
916 check_is_texpr(TExpr,find_identifier_uses),
917 find_typed_identifier_uses(TExpr,Ignored,TIds),
918 get_texpr_ids(TIds,Ids).
919 find_identifier_uses_l(TExprs,Ignored,Ids) :-
920 find_typed_identifier_uses_l(TExprs,Ignored,TIds),
921 get_texpr_ids(TIds,Ids).
922
923 check_is_texpr(X,Context) :-
924 (get_texpr_expr(X,_) -> true ; add_internal_error('Expected TExpr: ', check_is_texpr(X,Context))).
925
926 find_typed_identifier_uses(TExpr,Ids) :-
927 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
928 find_typed_identifier_uses(TExpr,Ignored,Ids).
929
930 find_typed_identifier_uses(TExpr,Ignored,Ids) :- var(TExpr),!,
931 add_internal_error('Variable typed expression: ', find_typed_identifier_uses(TExpr,Ignored,Ids)),
932 Ids = [].
933 find_typed_identifier_uses(TExpr,Ignored,Ids) :-
934 find_typed_identifier_uses_l([TExpr],Ignored,Ids).
935 find_typed_identifier_uses2(TExpr,Ignored,Ids,Rest) :-
936 %syntaxtraversion_fixed(TExpr,Expr,QSubs,Subs,TNames),
937 get_texpr_expr(TExpr,Expr),safe_syntaxelement(Expr,Subs,TNames,_,_), QSubs=[],
938 ( uses_an_identifier(Expr,Id,TExpr,Ignored) ->
939 ( memberchk(Id,Ignored) -> Ids=Rest % TO DO: use ord_member and ensure Ignored always sorted or use avl_set
940 ; otherwise ->
941 get_texpr_type(TExpr,Type),
942 normalize_type(Type,NType), % replace seq by set
943 create_texpr(identifier(Id),NType,[],TId),
944 Ids = [TId|Rest])
945 ; otherwise ->
946 find_typed_identifier_uses2_l(QSubs,Ignored,Ids,Ids2),
947 get_texpr_ids(TNames,Names),
948 append(Names,Ignored,Ignored2),
949 find_typed_identifier_uses2_l(Subs,Ignored2,Ids2,Rest)).
950 find_typed_identifier_uses2_l([],_) --> [].
951 find_typed_identifier_uses2_l([Expr|Rest],Ignored) -->
952 find_typed_identifier_uses2(Expr,Ignored),
953 find_typed_identifier_uses2_l(Rest,Ignored).
954
955
956 uses_an_identifier(Expr,Id) :- uses_an_identifier(Expr,Id,none,[]).
957
958 uses_an_identifier(identifier(Id),Id,_,_).
959 uses_an_identifier(lazy_lookup_pred(Id),Id,_,_).
960 uses_an_identifier(lazy_lookup_expr(Id),Id,_,_).
961 ?uses_an_identifier(value(_),Id,b(_,_,Info),Ignored) :- member(was_identifier(Id),Info),
962 member('$examine_value_was_identifier_info',Ignored),!.
963
964 find_typed_identifier_uses_l(TExprs,Ignored,Ids) :-
965 find_typed_identifier_uses2_l(TExprs,Ignored,Unsorted,[]),
966 safe_sort(find_typed_identifier_uses,Unsorted,Ids).
967
968 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
969 % break predicate into components with disjunct identifiers
970 % Pred: a predicate
971 % Components: a list of terms component/2 where the first argument
972 % is a predicate, the second is the set of used identifiers
973 predicate_components(Pred,Res) :- predicate_components_in_scope(Pred,[],Res).
974 predicate_components_in_scope(Pred,LocalVars,Res) :-
975 predicate_components_with_restriction(Pred,LocalVars,all,Res).
976
977 predicate_components_with_restriction(Pred,LocalVars,RestrictionList,Res) :-
978 conjunction_to_list(Pred,Preds),
979 l_predicate_identifiers(Preds,LocalVars,PredIds),
980 ( RestrictionList=all -> R=all
981 ; otherwise -> list_to_ord_set(RestrictionList,R)),
982 try_find_and_remove_equalities(PredIds,PredIds2),
983 % print(find_components(R)),nl,nl,
984 %%(member(pred(P,Ids,X),PredIds2), nl,print(pred(Ids,X)),nl,translate:print_bexpr(P),nl,fail ; true),
985 find_components(PredIds2,R,Components),
986 !,
987 %maplist(print_component,Components),
988 Components=Res.
989 predicate_components_with_restriction(Pred,_,_,[component(Pred,[])]) :-
990 add_internal_error('predicate_components failed: ',predicate_components_with_restriction(Pred,_,_,_)).
991
992 % print_component(component(Pred,Ids)) :- format('Component over ~w :~n',[Ids]), translate:print_bexpr(Pred),nl.
993
994 % get the list of used identifiers for each predicate
995 l_predicate_identifiers([],_LocalVars,[]).
996 l_predicate_identifiers([Pred|PRest],LocalVars,[pred(Pred,Ids,_Selected)|IRest]) :-
997 predicate_identifiers_in_scope(Pred,LocalVars,Ids),
998 l_predicate_identifiers(PRest,LocalVars,IRest).
999
1000
1001 try_find_and_remove_equalities(PredAndIds,PredAndIds2) :-
1002 preferences:get_preference(partition_predicates_inline_equalities,true),
1003 preferences:get_preference(try_kodkod_on_load,false),
1004 ? find_and_remove_equalities(PredAndIds,RR),
1005 !, PredAndIds2=RR.
1006 try_find_and_remove_equalities(Ps,Ps).
1007
1008 :- use_module(debug,[debug_println/2,formatsilent/2]).
1009 % find and apply obvious equalities so that they do not interfere with partitioning into components
1010 % example: c = 1 & f: 1..c --> A & g: 1..c --> B
1011 % TO DO: preprocess and do one pass to detect potential equalities
1012 find_and_remove_equalities([],[]).
1013 find_and_remove_equalities(List,[pred(P,PIds,Sel)|FT]) :-
1014 ? select(pred(P,PIds,Sel),List,Rest),
1015 %PIds = [Id],
1016 ? identifier_equality(P,Id,Value),
1017 %(value_which_can_be_replaced(Value) -> true ; nl,print('Not replaced: '),translate:print_bexpr(Value),nl,fail),
1018 ? (get_texpr_id(Value,Id2)
1019 -> Id2 \= Id %,print(inline_id(Id,Id2)),nl
1020 % Note: this inlining does *not* help with partitioning; but does help ProB detect common predicates/expressions
1021 ; PIds=[Id],value_which_can_be_replaced(Value)),
1022 ? debug_println(9,replace_simple_equality(Id,Value,PIds)),
1023 ? maplist(apply_to_pred(Id,Value),Rest,RT),
1024 ? !,
1025 ? find_and_remove_equalities(RT,FT).
1026 % TO DO: detect equalityes x = EXPR, where EXPR does not contain x and where x occurs in no other predicate
1027 % we can then annotate x as not to enumerate
1028 find_and_remove_equalities(R,R).
1029
1030 identifier_equality(b(equal(LHS,RHS),_,_),Id,EqTerm) :-
1031 (get_texpr_id(LHS,Id) -> EqTerm = RHS
1032 ; get_texpr_id(RHS,Id) -> EqTerm = LHS).
1033
1034 value_which_can_be_replaced(b(E,T,_)) :- value_which_can_be_replaced2(E,T).
1035 %(value_which_can_be_replaced2(E,T) -> true ; print(not_val(E)),nl,fail).
1036 value_which_can_be_replaced2(value(_),_).
1037 value_which_can_be_replaced2(integer(_),_).
1038 %value_which_can_be_replaced2(identifier(I),global(G)) :- b_global_constant(G), id_not_used_anywhere(I).
1039 value_which_can_be_replaced2(integer_set(_),_).
1040 value_which_can_be_replaced2(unary_minus(A),_) :- value_which_can_be_replaced(A).
1041 value_which_can_be_replaced2(add(A,B),_) :- value_which_can_be_replaced(A), value_which_can_be_replaced(B).
1042 % we could compute the value
1043 value_which_can_be_replaced2(minus(A,B),_) :- value_which_can_be_replaced(A), value_which_can_be_replaced(B).
1044 value_which_can_be_replaced2(multiplication(A,B),_) :- value_which_can_be_replaced(A), value_which_can_be_replaced(B).
1045 value_which_can_be_replaced2(div(A,B),_) :-
1046 integer_value(B,IB), number(IB), IB \= 0,
1047 value_which_can_be_replaced(A).
1048 value_which_can_be_replaced2(floored_div(A,B),T) :- value_which_can_be_replaced2(div(A,B),T).
1049 % should we add: with WD check: division, modulo, .... ? see also simple2 in b_ast_cleanup
1050 value_which_can_be_replaced2(max_int,_).
1051 value_which_can_be_replaced2(min_int,_).
1052 value_which_can_be_replaced2(string(_),_).
1053 value_which_can_be_replaced2(string_set,_).
1054 value_which_can_be_replaced2(boolean_true,_).
1055 value_which_can_be_replaced2(boolean_false,_).
1056 value_which_can_be_replaced2(bool_set,_).
1057 value_which_can_be_replaced2(empty_set,_).
1058 value_which_can_be_replaced2(empty_sequence,_).
1059 value_which_can_be_replaced2(couple(A,B),_) :- value_which_can_be_replaced(A), value_which_can_be_replaced(B).
1060 value_which_can_be_replaced2(interval(A,B),_) :- value_which_can_be_replaced(A), value_which_can_be_replaced(B).
1061 value_which_can_be_replaced2(set_extension(L),_) :- maplist(value_which_can_be_replaced,L).
1062 value_which_can_be_replaced2(sequence_extension(L),_) :- maplist(value_which_can_be_replaced,L).
1063 value_which_can_be_replaced2(cartesian_product(A,B),_) :- % typing equations, like t_float = INTEGER*NATURAL1
1064 simple_value_set(A), simple_value_set(B).
1065 value_which_can_be_replaced2(pow_subset(A),_) :- simple_value_set(A).
1066 %value_which_can_be_replaced2(identifier(_),_). % TO DO: check that this is not the LHS identifier which we replace !!
1067 % identifiers can also be replaced: we check above that the only identifier in the predicate is the equality identifier
1068 % 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
1069
1070 % TO DO: also allow inlining of prj1/prj2 of simple_value_set:
1071 % 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])))
1072 % 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])))
1073
1074 % TO DO: maybe check if it is an infinite type which cannot be evaluated anyway
1075 simple_value_set(b(E,_,_)) :- simple_value_set2(E).
1076 %simple_value_set2(bool_set). % Warning: we could have a finite construct which gets evaluated multiple times
1077 simple_value_set2(string_set).
1078 simple_value_set2(integer_set(_)).
1079 simple_value_set2(cartesian_product(A,B)) :- simple_value_set(A), simple_value_set(B).
1080 simple_value_set2(pow_subset(A)) :- simple_value_set(A).
1081 % POW, records struct(_) set ?
1082
1083 % apply a substiution of ID/Expr on a pred(EXPR,VarList,X) term
1084 % Expr must either be a variable or contain no variables at all
1085 apply_to_pred(ID,Expr,pred(E1,PIds1,X),pred(E2,PIds3,X)) :-
1086 ? (select(ID,PIds1,PIds2)
1087 -> replace_id_by_expr(E1,ID,Expr,E2), %,print(applied(ID)),nl,translate:print_bexpr(E2),nl
1088 % 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
1089 (get_texpr_id(Expr,NewID)
1090 -> ord_add_element(PIds2,NewID,PIds3)
1091 ; PIds3 = PIds2)
1092 %, format('Apply ~w -> ~w : ',[ID,NewID]),translate:print_bexpr(E2),nl
1093 ; E1=E2,PIds1=PIds3).
1094
1095
1096 % project a predicate : keep only those Predicates that are directly or
1097 % indirectly relevant for Ids; FullIds are all identifiers used by ProjectedPredicate
1098 project_predicate_on_identifiers(Pred,Ids,ProjectedPredicate,FullIds, RestList) :-
1099 (debug:debug_mode(on)
1100 -> print('project: '),print_bexpr(Pred),nl, print(' on : '), print(Ids),nl
1101 ; true),
1102 conjunction_to_list(Pred,Preds),
1103 l_predicate_identifiers(Preds,[],PredIds), % TO DO: allow LocalVariables to be passed
1104 % print(predids(PredIds)),nl,
1105 try_find_and_remove_equalities(PredIds,PredIds2),
1106 extract_all_predicates(Ids,all,Ids,PredIds2,ProjectedPredicates, RestList,FullIds),
1107 conjunct_predicates(ProjectedPredicates,ProjectedPredicate),
1108 (debug:debug_mode(on)
1109 -> print('*result: '),print_bexpr(ProjectedPredicate),nl,
1110 print(' on : '), print(FullIds),nl
1111 ; true).
1112
1113 %print_preds([]).
1114 %print_preds([pred(P,_IDs,_)|T]) :- translate:print_bexpr(P), nl, print(' '), print_preds(T).
1115
1116 :- use_module(b_global_sets,[b_get_global_constants/1, b_get_global_sets/1]).
1117 predicate_identifiers(Pred,Ids) :- predicate_identifiers_in_scope(Pred,[],Ids).
1118 predicate_identifiers_in_scope(Pred,LocalVariables,Ids) :-
1119 get_global_identifiers(IS),
1120 list_to_ord_set(LocalVariables,LV),
1121 ord_subtract(IS,LV,Ignore2), % Do not ignore any local variable; it will be used instead of enumerate set element
1122 find_identifier_uses(Pred,Ignore2,Ids1), % Ignore enumerated set names
1123 list_to_ord_set(Ids1,Ids).
1124
1125 % get global set and constant identifiers which you usually want to exclude for find_identifier_uses
1126 get_global_identifiers(IDs) :-
1127 b_get_global_constants(EnumeratedSetCsts),
1128 % b_global_sets:b_get_global_enumerated_sets(GSets), % is there a reason to exclude deferred sets ??; cardinality inference,... are all done before partitioning ?
1129 b_get_global_sets(GSets),
1130 append(GSets,EnumeratedSetCsts,GE),
1131 list_to_ord_set(GE,IDs).
1132
1133 % find_components(ListOf_pred, Restrict, Out:ListOfComponents)
1134 % role of Restrict: all if we do normal partition or List of VariableIDs on which we restrict our attention to (for Existential quantifier construction)
1135 find_components([],_,[]).
1136 find_components([pred(P,PIds,true)|PRest],Restrict,[component(Pred,Ids)|CRest]) :-
1137 % find all predicates which are using identifiers occuring in PIds
1138 % (and additionally those which use common identifiers )
1139 ord_restrict(Restrict,PIds,InterIDs),
1140 ( InterIDs =[] ->
1141 % we simply copy this predicate into a single component; not with the scope of Restricted IDs
1142 % print(skip(PIds,P)),nl, %
1143 Pred=P, Ids=PIds, PRest=Rest
1144 ; otherwise ->
1145 extract_all_predicates(PIds,Restrict,PIds,PRest,Preds,Rest,Ids),
1146 conjunct_predicates([P|Preds],Pred)
1147 ),
1148 find_components(Rest,Restrict,CRest).
1149 extract_all_predicates([],_,_,Preds,Found,Rest,[]) :- !, % selecting done at end: keep same order of conjuncts
1150 select_predicates(Preds,Found,Rest).
1151 extract_all_predicates(Ids,Restrict,OldIds,Preds,Found,Rest,ResultIds) :-
1152 % search for all predicates that directly use one of the
1153 % identifiers in "Ids"
1154 select_all_using_preds(Preds,Ids,FoundIds),
1155 ord_subtract(FoundIds,OldIds,NewIds),
1156 ord_restrict(Restrict,NewIds,NewIdsToExtract),
1157 ord_union(OldIds,FoundIds,OldIds2),
1158 % now recursively do this which the new identifiers that we have found
1159 extract_all_predicates(NewIdsToExtract,Restrict,OldIds2,Preds,Found,Rest,RestIds),
1160 ord_union([Ids,NewIds,RestIds],ResultIds).
1161
1162 % mark all predicates which intersect with ComponentIds and compute new ids to be added to the component
1163 select_all_using_preds([],_,[]).
1164 select_all_using_preds([pred(_P,PIds,Selected)|PRest],ComponentIds,NewFoundIds) :-
1165 ? ( (Selected==true ; ord_disjoint(PIds,ComponentIds)) ->
1166 NewFoundIds1 = []
1167 ; otherwise -> % we select the predicate for the component
1168 ord_subtract(PIds,ComponentIds,NewFoundIds1),
1169 Selected=true
1170 ),
1171 select_all_using_preds(PRest,ComponentIds,NewFoundIds2),
1172 ord_union(NewFoundIds1,NewFoundIds2,NewFoundIds).
1173
1174 % ord_intersection with special case for all term
1175 ord_restrict(all,Ids,Res) :- !, Res=Ids.
1176 ord_restrict(Restrict,Ids,Res) :- ord_intersection(Ids,Restrict,Res).
1177
1178 select_predicates(Predicates,FoundPreds,OtherPreds) :-
1179 split_list(is_selected_predicate,Predicates,FoundPredIds,OtherPreds),
1180 maplist(extract_found_predicate,FoundPredIds,FoundPreds).
1181 is_selected_predicate(pred(_P,_PIds,Selected)) :- ground(Selected).
1182 extract_found_predicate(pred(P,_PIds,_Selected),P).
1183
1184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1185 % replace (simultaneously) multiple identifiers by expressions
1186 % this could be used to replace the predicate replace_id_by_expr by mapping everything in a
1187 % singleton list. however, that would involve list operations instead of unifications
1188 parse_pred(Codes,TExpr) :- bmachine:b_parse_machine_predicate_from_codes_open(no_quantifier,Codes,[],[],TExpr).
1189 parse_expr(Codes,TExpr) :- bmachine:b_parse_machine_expression_from_codes(Codes,[],TExpr,_Type,true,_Error).
1190 test_result(1,b(equal(b(comprehension_set([b(identifier(__FRESH____),integer,_)],
1191 b(greater(b(identifier(__FRESH____2),integer,_),b(identifier(x),integer,_)),pred,_)),set(integer),_),
1192 b(empty_set,set(integer),_)),pred,_)).
1193
1194 :- assert_must_succeed((bsyntaxtree:parse_pred("{x|x>y}={}",T1), replace_ids_by_exprs(T1,[],[],T1))).
1195 :- assert_must_succeed((bsyntaxtree:parse_pred("{x|x>y}={}",T1), bsyntaxtree:parse_expr("100",T2),
1196 replace_ids_by_exprs(T1,[y],[T2],R),bsyntaxtree:parse_pred("{x|x>100}={}",T3),same_texpr(R,T3) )).
1197 :- assert_must_succeed((bsyntaxtree:parse_pred("{x|x>y}={}",T1),
1198 replace_ids_by_exprs(T1,[y],[b(identifier(x),integer,[])],R),
1199 bsyntaxtree:test_result(1,R),bsyntaxtree:parse_pred("{x|x>x}={}",T3),\+ same_texpr(R,T3) )).
1200 :- assert_must_succeed((bsyntaxtree:parse_pred("{x,y|x>v & y>w}={}",T1),
1201 replace_ids_by_exprs(T1,[v,w],[b(identifier(w),integer,[]),b(identifier(v),integer,[])],R),
1202 bsyntaxtree:parse_pred("{x,y|x>w & y>v}={}",T3), same_texpr(R,T3) )).
1203 :- assert_must_succeed((gensym:reset_gensym, bsyntaxtree:parse_pred("{x,y|x>v & y>w}={}",T1),
1204 replace_ids_by_exprs(T1,[v,w],[b(identifier(w),integer,[]),b(identifier(x),integer,[])],R),
1205 translate:translate_bexpression(R,TR),
1206 TR = '{__FRESH____1,y|__FRESH____1 > w & y > x} = {}')). %'{__FRESH____1,y|(__FRESH____1 : INTEGER & y : INTEGER) & (__FRESH____1 > w & y > x)} = {}' )).
1207
1208 replace_ids_by_exprs(TExpr,[TId],[Inserted],Replaced) :- !, % better, more robust and efficient version
1209 check_ids([TId],[Id]),
1210 replace_id_by_expr(TExpr,Id,Inserted,Replaced).
1211 replace_ids_by_exprs(TExpr,[],[],Replaced) :- !, Replaced=TExpr. % Nothing to do
1212 replace_ids_by_exprs(TExpr,Ids,Exprs,Replaced) :-
1213 check_ids(Ids,Ids2), % convert to atomic identifiers
1214 find_identifier_uses_l(Exprs,[],ExprsUsedIds),
1215 sort(ExprsUsedIds,SExprsUsedIds),
1216 findall(rename(I,E),(nth0(N,Ids2,I),nth0(N,Exprs,E)),RenameList),
1217 %print(replace(RenameList,SExprsUsedIds)),nl,
1218 replace_ids_by_exprs2(RenameList,SExprsUsedIds,TExpr,Replaced,_). %, nl,print(done),nl.
1219 % a version of replace_ids_by_exprs2 for maplist:
1220 %replace_ids_by_exprs1(RenameList,SExprsUsedIds,TExpr,Replaced) :-
1221 % replace_ids_by_exprs2(RenameList,SExprsUsedIds,TExpr,Replaced,_). %, print('Rep: '), translate:print_bexpr(Replaced),nl.
1222 check_ids([],[]).
1223 check_ids([H|T],[ID|IT]) :- (atomic(H) -> ID=H ; def_get_texpr_id(H,ID)), check_ids(T,IT).
1224 replace_ids_by_exprs2(RenameList,ExprsUsedIds,TExpr,Replaced,WDC) :-
1225 remove_bt(TExpr,Expr,NewExpr,TNewExpr),
1226 ( Expr = identifier(Id), member(rename(Id,Inserted),RenameList) ->
1227 Replaced = Inserted,
1228 get_texpr_info(Inserted,Infos),
1229 (memberchk(contains_wd_condition,Infos)
1230 -> WDC = true ; WDC = false) % WDC = true means we have added a wd-condition where previously there was none
1231 ; otherwise ->
1232 syntaxtransformation_fixed(Expr,QSubs,Subs1,Names,NQSubs,NSubs,NewExpr),
1233 find_variable_clashes(Names,ExprsUsedIds,RenameNames), % check for variable caputure
1234 (RenameNames = []
1235 -> Subs = Subs1 % no variable capture occured
1236 ; %format('*** VARIABLE CAPTURE : ~w~n~n',[RenameNames]),
1237 %maplist(replace_ids_by_exprs1(RenameNames,[]),Subs1,Subs) % replace affected names by fresh ids in sub arguments
1238 rename_bt_l(Subs1,RenameNames,Subs) % replace affected names by fresh ids in sub arguments (will also change list of quantified variables itself)
1239 ),
1240 %print(e(SNameIds,QSubs,Subs)),nl,
1241 l_replace_ids_by_exprs2(QSubs,RenameList,ExprsUsedIds,NQSubs,WDC1), % QSubs are like RHS of let expression, where Names are not in scope
1242 remove_hidden_names(Names,RenameList,UpdatedRenameList),
1243 %print(rem_hidden(Names,UpdatedRenameList)),nl,
1244 ( UpdatedRenameList = [] -> % all Ids are now hidden for the inner expressions
1245 NSubs=Subs, WDC=WDC1
1246 ; otherwise -> %print(recur(Subs)),nl,
1247 l_replace_ids_by_exprs2(Subs,UpdatedRenameList,ExprsUsedIds,NSubs,WDC2),
1248 and_wdc(WDC1,WDC2,WDC)
1249 ),
1250 TNewExpr = b(E1,T1,Info1),
1251 rename_update_used_ids_info(RenameList,Info1,Info2),
1252 %(E1 = exists(P,_) -> print(exists(P,Id,Info1,Info2)),nl ; true),
1253 add_wd_if_needed(WDC,b(E1,T1,Info2),Replaced)
1254 ).
1255
1256 % check if we have to rename any quantified variable to avoid variable capture of RHS of renamings
1257 % 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}
1258 find_variable_clashes([],_,[]).
1259 find_variable_clashes([Name|Names],ExprsUsedIds,[rename(ID,FRESHID)|Renaming] ) :-
1260 def_get_texpr_id(Name,ID),
1261 ord_member(ID,ExprsUsedIds), % the quantified name is also introduced by the renaming
1262 !,
1263 gensym('__FRESH__',FRESHID),
1264 find_variable_clashes(Names,ExprsUsedIds,Renaming).
1265 find_variable_clashes([_|Names],ExprsUsedIds,Renaming) :-
1266 find_variable_clashes(Names,ExprsUsedIds,Renaming).
1267
1268
1269 l_replace_ids_by_exprs2([],_,_,[],false).
1270 l_replace_ids_by_exprs2([H|T],UpdatedRenameList,ExprsUsedIds,[IH|IT],WDC) :-
1271 replace_ids_by_exprs2(UpdatedRenameList,ExprsUsedIds,H,IH,WDC1),
1272 l_replace_ids_by_exprs2(T,UpdatedRenameList,ExprsUsedIds,IT,WDC2),
1273 and_wdc(WDC1,WDC2,WDC).
1274
1275 % remove any identifiers that are now "invisible" because they are masked by quantified names
1276 % e.g., when we enter #x.(P) then a renaming of x will be "hidden" inside P
1277 remove_hidden_names([],RenameList,RenameList).
1278 remove_hidden_names([Name|Names],RenameList,NewRenameList) :-
1279 def_get_texpr_id(Name,ID),
1280 delete(RenameList,rename(ID,_),RenameList1),
1281 !, % only one rename should exist
1282 %print(del(ID,RenameList1)),nl,
1283 remove_hidden_names(Names,RenameList1,NewRenameList).
1284
1285 find_rhs_ids(rename(Id,TExpr),rename_ids(Id,InsUsedIds)) :- find_identifier_uses(TExpr,[],InsUsedIds).
1286
1287 % apply a rename list to the used_ids,... information fields
1288 % this is more tricky than applying a single identifier, as we first have to deleted all ids
1289 % and remember which ones were deleted, and only then insert the corresponding ids
1290 % e.g., we could have a RenameList = [rename(p,q),rename(q,p)] ; see test 1776 M1_Internal_v3.mch
1291 rename_update_used_ids_info(RenameList,IIn,IOut) :-
1292 maplist(find_rhs_ids,RenameList,RenameList2),
1293 maplist(apply_rename_list(RenameList2),IIn,IOut).
1294
1295 apply_rename_list(RenameList,I,NI) :-
1296 apply_rename_list2(I,RenameList,NI).
1297 apply_rename_list2(used_ids(IDS),RenameList,used_ids(NewIDS)) :- !, apply_rename_list_to_ids(RenameList,IDS,[],NewIDS).
1298 apply_rename_list2(reads(IDS),RenameList,reads(NewIDS)) :- !, apply_rename_list_to_ids(RenameList,IDS,[],NewIDS).
1299 apply_rename_list2(modifies(IDS),RenameList,modifies(NewIDS)) :- !, apply_rename_list_to_ids(RenameList,IDS,[],NewIDS).
1300 apply_rename_list2(Info,_,Info).
1301
1302 % apply a rename list to a sorted list of ids
1303 apply_rename_list_to_ids([],Acc,ToInsert,Res) :- ord_union(Acc,ToInsert,Res).
1304 apply_rename_list_to_ids([rename_ids(Id,NewIds)|T],Acc,ToInsert,Res) :-
1305 (ord_del_element(Acc,Id,Acc2) % the Id occurs and is deleted
1306 -> ord_union(NewIds,ToInsert,ToInsert2),
1307 apply_rename_list_to_ids(T,Acc2,ToInsert2,Res)
1308 ; apply_rename_list_to_ids(T,Acc,ToInsert,Res)).
1309
1310 % -----------------------
1311 % remove an Identifier from used_ids Info field if it exists
1312 remove_used_id_from_info(I,ID_to_remove,NI) :-
1313 update_used_ids_info(I,ID_to_remove,[],NI).
1314
1315 remove_used_ids_from_info([],I,I).
1316 remove_used_ids_from_info([ID_to_remove|T],I,NI) :- remove_used_id_from_info(I,ID_to_remove,I2),
1317 remove_used_ids_from_info(T,I2,NI).
1318
1319 % remove an Identifier from used_ids Info field if it exists and insert sorted list of ids instead
1320 update_used_ids_info([],_,_,[]).
1321 update_used_ids_info([InfoField|T],ID_to_remove,IDsInserted,[NewInfoField|NT]) :-
1322 ? (update_id_from_info_field(ID_to_remove,IDsInserted,InfoField,R) -> NewInfoField=R
1323 ; NewInfoField=InfoField),
1324 update_used_ids_info(T,ID_to_remove,IDsInserted,NT).
1325
1326 update_id_from_info_field(ID_to_remove,IDsInserted,I,NI) :-
1327 ? update_id_from_info_field2(I,ID_to_remove,IDsInserted,NI).
1328 ?update_id_from_info_field2(used_ids(IDS),ID,IDsInserted,used_ids(NewIDS)) :- update_id(IDS,ID,IDsInserted,NewIDS).
1329 update_id_from_info_field2(reads(IDS),ID,IDsInserted,reads(NewIDS)) :- update_id(IDS,ID,IDsInserted,NewIDS).
1330 update_id_from_info_field2(modifies(IDS),ID,IDsInserted,modifies(NewIDS)) :- update_id(IDS,ID,IDsInserted,NewIDS).
1331
1332 ?update_id(IDS,ID_to_remove,IDsInserted,NewIDS) :- select(ID_to_remove,IDS,IDS2),
1333 (IDsInserted=[] -> NewIDS = IDS2
1334 ; sort(IDS2,SIDS2), ord_union(IDsInserted,SIDS2,NewIDS)).
1335 %if select fails we do not add IDsInserted: we assume the used_ids info is correct and ID_to_remove does not occur !
1336 % We could use this info to avoid traversing subtree !
1337 % print(projecting_away_unknown_id(ID_to_remove,IDS)),nl,
1338
1339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1340
1341 :- 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),
1342 TR = 'r = {__FRESH____1|__FRESH____1 : 1 .. x & __FRESH____1 mod 2 = 1}' )).
1343 :- assert_must_succeed((bsyntaxtree:parse_pred("{x|x>y}={}",T1),
1344 replace_id_by_expr(T1,y,b(identifier(x),integer,[]),R),
1345 bsyntaxtree:test_result(1,R),bsyntaxtree:parse_pred("{x|x>x}={}",T3),\+ same_texpr(R,T3) )).
1346 :- assert_must_succeed((bsyntaxtree:parse_pred("{x|x>y}={}",T1), bsyntaxtree:parse_expr("100",T2),
1347 replace_id_by_expr(T1,y,T2,R),bsyntaxtree:parse_pred("{x|x>100}={}",T3),same_texpr(R,T3) )).
1348
1349 % replace an identifier by an expression
1350 replace_id_by_expr(TExpr,Id,Inserted,Replaced) :- \+ atomic(Id),!,
1351 add_internal_error('Id not atomic: ',replace_id_by_expr(TExpr,Id,Inserted,Replaced)),
1352 Replaced = TExpr.
1353 replace_id_by_expr(TExpr,Id,Inserted,Replaced) :-
1354 %find_all_relevant_quantified_vars(Id,TExpr,QVars),
1355 find_identifier_uses(Inserted,[],InsUsedIds),
1356 sort(InsUsedIds,SInsUsedIds),
1357 replace_id_by_expr2(Id,Inserted,SInsUsedIds,TExpr,Replaced,_).
1358 replace_id_by_expr2(Id,Inserted,InsUsedIds,TExpr,Replaced,WDC) :-
1359 remove_bt(TExpr,Expr,NewExpr,TNewExpr),
1360 ( Expr = identifier(Id) ->
1361 Replaced = Inserted,
1362 get_texpr_info(Inserted,Infos),
1363 (memberchk(contains_wd_condition,Infos)
1364 -> WDC = true ; WDC = false) % WDC = true means we have added a wd-condition where previously there was none
1365 ; otherwise ->
1366 syntaxtransformation_fixed(Expr,QSubs,Subs,Names,NQSubs,NSubs,NewExpr),
1367 %maplist(replace_id_by_expr2(Id,Inserted),QSubs,NQSubs),
1368 l_replace_id_by_expr2(QSubs,Id,Inserted,InsUsedIds,NQSubs,WDC1),
1369 get_texpr_id(TId,Id),
1370 ( memberchk(TId,Names) -> % the Id is now hidden for the inner expressions
1371 NSubs=Subs, WDC=WDC1
1372 ; (InsUsedIds \= [],
1373 get_texpr_ids(Names,Ns),sort(Ns,SNs),
1374 ord_intersection(SNs,InsUsedIds,Captured),
1375 Captured \= [] %, print(inter(SNs,InsUsedIds,Captured)),nl
1376 )
1377 % The Names introduced clash with variables used in the Inserted expression
1378 -> findall(rename(X,FRESHID),(member(X,Captured),gensym:gensym('__FRESH__',FRESHID)),RenameList),
1379 %print(rename(RenameList)),nl,
1380 rename_bt_l(Subs,RenameList,RenSubs),
1381 l_replace_id_by_expr2(RenSubs,Id,Inserted,InsUsedIds,NSubs,WDC2),
1382 and_wdc(WDC1,WDC2,WDC)
1383 ; otherwise ->
1384 l_replace_id_by_expr2(Subs,Id,Inserted,InsUsedIds,NSubs,WDC2),
1385 and_wdc(WDC1,WDC2,WDC)
1386 ),
1387 TNewExpr = b(E1,T1,Info1),
1388 update_used_ids_info(Info1,Id,InsUsedIds,Info2),
1389 %(E1 = exists(P,_) -> print(exists(P,Id,Info1,Info2)),nl ; true),
1390 add_wd_if_needed(WDC,b(E1,T1,Info2),Replaced)
1391 ).
1392
1393 l_replace_id_by_expr2([],_,_,_,[],false).
1394 l_replace_id_by_expr2([H|T],Id,Inserted,InsUsedIds,[IH|IT],WDC) :-
1395 replace_id_by_expr2(Id,Inserted,InsUsedIds,H,IH,WDC1),
1396 l_replace_id_by_expr2(T,Id,Inserted,InsUsedIds,IT,WDC2),
1397 and_wdc(WDC1,WDC2,WDC).
1398
1399 and_wdc(true,_,R) :- !,R=true.
1400 and_wdc(_,true,R) :- !, R=true.
1401 and_wdc(_,_,false).
1402
1403 % add contains_wd_condition if a change occured during replacement of id by expression
1404 add_wd_if_needed(true,b(E,T,Infos),Replaced) :-
1405 nonmember(contains_wd_condition,Infos),
1406 !,
1407 Replaced = b(E,T,[contains_wd_condition|Infos]).
1408 add_wd_if_needed(_,T,T).
1409
1410
1411
1412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1413
1414
1415 % syntaxtransformation_fixed/7 is the same as syntaxtransformation/5 with the exception
1416 % that we distinguish between subexpressions that have the newly introduced identifiers (Names)
1417 % in scope (OSubs) and those who don't (OExprs). The only expressions where the latter case is relevant
1418 % are let_expression and let_predicate.
1419 % TODO: This is a quick'n dirty fix for only some cases.
1420 % NO LONGER REQUIRED: let_expression and let_predicate now obey another semantic, not the Z semantics anymore
1421 %syntaxtransformation_fixed(OExpr,OExprs,OSubs,Names,NExprs,NSubs,NExpr) :-
1422 % is_let_pred_or_expr(OExpr,OTIds,OExprs,OExprPred,LetType),
1423 % !,
1424 % Names=OTIds,
1425 % is_let_pred_or_expr(NExpr,NTIds,NExprs,NExprPred,LetType),
1426 % same_length(OExprs,NExprs),same_length(OTIds,NTIds),
1427 % last(OTIds,OExprPred,OSubs),last(NTIds,NExprPred,NSubs),
1428 % !.
1429 syntaxtransformation_fixed(Expr,[],Subs,Names,[],NSubs,NExpr) :-
1430 syntaxtransformation(Expr,Subs,Names,NSubs,NExpr).
1431
1432 % note : LET substitution is dealt with differently as there we currently allow to use previously introduced IDs in RHS
1433 %is_let_pred_or_expr(let_expression(TIds,Exprs,Expr),TIds,Exprs,Expr,let_expression).
1434 %is_let_pred_or_expr(let_predicate(TIds,Exprs,Expr), TIds,Exprs,Expr,let_predicate).
1435 %is_let_pred_or_expr(lazy_let_pred(ID,SharedExpr,Expr), [ID],[SharedExpr],Expr, lazy_let_pred).
1436 %is_let_pred_or_expr(lazy_let_expr(ID,SharedExpr,Expr), [ID],[SharedExpr],Expr, lazy_let_expr).
1437 %is_let_pred_or_expr(lazy_let_subst(ID,SharedExpr,Expr), [ID],[SharedExpr],Expr, lazy_let_subst).
1438
1439
1440
1441
1442 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1443 % rename identifier
1444
1445 % r = {x|x : 1..y & x mod 2 = 1}
1446 exists_ast(AST) :- AST =
1447 b(equal(b(identifier(r),set(integer),[nodeid(none)]),
1448 b(comprehension_set([b(identifier(x),integer,[nodeid(none)])],
1449 b(conjunct(b(member(b(identifier(x),integer,[nodeid(none)]),
1450 b(interval(b(integer(1),integer,[nodeid(none)]),b(identifier(y),integer,[nodeid(none)])),
1451 set(integer),[nodeid(none)])),pred,[nodeid(none)]),
1452 b(equal(b(modulo(b(identifier(x),integer,[nodeid(none)]),
1453 b(integer(2),integer,[nodeid(none)])),integer,[contains_wd_condition,nodeid(none)]),
1454 b(integer(1),integer,[nodeid(none)])),pred,
1455 [contains_wd_condition,nodeid(none)])),pred,[contains_wd_condition,nodeid(none)])),
1456 set(integer),[contains_wd_condition,nodeid(none)])),
1457 pred,[contains_wd_condition,nodeid(none)]).
1458
1459 :- assert_must_succeed((bsyntaxtree:exists_ast(A), rename_bt(A,[rename(x,xx)],RA), RA==A )).
1460 :- assert_must_succeed((bsyntaxtree:exists_ast(A), rename_bt(A,[rename(r,v)],RA),
1461 translate:translate_bexpression(RA,TR), TR='v = {x|x : 1 .. y & x mod 2 = 1}' )).
1462 :- assert_must_succeed((gensym:reset_gensym, bsyntaxtree:exists_ast(A), rename_bt(A,[rename(y,x)],RA), RA \= A,
1463 translate:translate_bexpression(RA,TR),
1464 TR = 'r = {__FRESH____1|__FRESH____1 : 1 .. x & __FRESH____1 mod 2 = 1}' )).
1465
1466 % a simplified version of replace_ids_by_exprs, which assumes target of renamings are variables
1467 rename_bt(Expr,[],Res) :- !,Res=Expr.
1468 rename_bt(OExpr,Renamings,NExpr) :-
1469 create_texpr(Old,Type,OInfo,OExpr),
1470 create_texpr(New,Type,NInfo,NExpr),
1471 rename_in_infos(OInfo,Renamings,NInfo),
1472 rename_bt2(Old,Renamings,New).
1473 rename_bt2(identifier(Old),Renamings,identifier(New)) :-
1474 !, rename_id(Old,Renamings,New).
1475 rename_bt2(lazy_lookup_expr(Old),Renamings,lazy_lookup_expr(New)) :-
1476 !, rename_id(Old,Renamings,New).
1477 rename_bt2(lazy_lookup_pred(Old),Renamings,lazy_lookup_pred(New)) :-
1478 !, rename_id(Old,Renamings,New).
1479 rename_bt2(OExpr,Renamings,NExpr) :-
1480 syntaxtransformation(OExpr,Subs,TNames,NSubs,NExpr),
1481 get_texpr_exprs(TNames,Names),
1482 remove_renamings(Names,Renamings,NRenamings),
1483 rename_bt_l(Subs,NRenamings,NSubs).
1484 rename_bt_l([],_,[]).
1485 rename_bt_l([Old|ORest],Renamings,[New|NRest]) :-
1486 rename_bt(Old,Renamings,New),
1487 rename_bt_l(ORest,Renamings,NRest).
1488
1489 remove_renamings([],Renamings,Renamings).
1490 remove_renamings([identifier(Name)|Rest],Old,New) :-
1491 ? ( select(rename(Name,_),Old,Inter1) -> true % Name no longer visible to renaming
1492 ; Old = Inter1),
1493 (member(rename(_OldName,Name),Inter1) ->
1494 gensym('__FRESH__',FRESHID),
1495 %print(variable_capture_in_rename(Name,from(OldName),FRESHID)),nl,
1496 Inter2 = [rename(Name,FRESHID)|Inter1]
1497 ; Inter2 = Inter1),
1498 remove_renamings(Rest,Inter2,New).
1499
1500 rename_in_infos(Old,Renamings,New) :-
1501 ( has_info_to_rename(Old) ->
1502 maplist(rename_in_infos2(Renamings),Old,New)
1503 ; otherwise ->
1504 Old = New).
1505 rename_in_infos2(Renamings,OInfo,NInfo) :-
1506 ( infos_to_rename(OInfo,OIds,SortedNIds,NInfo) ->
1507 rename_ids(OIds,Renamings,NIds),
1508 sort(NIds,SortedNIds)
1509 ; otherwise ->
1510 OInfo = NInfo).
1511
1512 rename_ids([],_,[]).
1513 rename_ids([OId|Orest],Renamings,[NId|Nrest]) :-
1514 rename_id(OId,Renamings,NId),
1515 rename_ids(Orest,Renamings,Nrest).
1516 rename_id(Old,Renamings,New) :-
1517 ( memberchk(rename(Old,New),Renamings) -> true % we could use ord_member if we sort !
1518 ; otherwise -> Old=New).
1519
1520 has_info_to_rename(Infos) :-
1521 ? member(I,Infos),infos_to_rename(I,_,_,_),!.
1522
1523 infos_to_rename(modifies(O),O,N,modifies(N)).
1524 infos_to_rename(reads(O),O,N,reads(N)).
1525 infos_to_rename(non_det_modifies(O),O,N,non_det_modifies(N)).
1526 infos_to_rename(modifies_locals(O),O,N,modifies_locals(N)).
1527 infos_to_rename(reads_locals(O),O,N,reads_locals(N)).
1528 infos_to_rename(used_ids(O),O,N,used_ids(N)).
1529
1530
1531 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1532 % remove type information for transformations
1533
1534 remove_bt(b(Expr,Type,Infos),Expr,NExpr,b(NExpr,Type,Infos)).
1535
1536 %remove_bt_l([],[],[],[]).
1537 %remove_bt_l([OT|OTRest],[O|ORest],[N|NRest],[NT|NTRest]) :-
1538 % remove_bt(OT,O,N,NT),
1539 % remove_bt_l(OTRest,ORest,NRest,NTRest).
1540
1541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1542 % traversations
1543 % Takes a predicate or expression or substitution and extracts:
1544 % the expression itself Expr, its type Type, the syntaxnode information Infos
1545 % + the subexpressions as a list Subs and the local identifiers declared
1546 syntaxtraversion(b(Expr,Type,Infos),Expr,Type,Infos,Subs,Names) :- !,
1547 safe_syntaxelement(Expr,Subs,Names,_,_).
1548 syntaxtraversion(IExpr,Expr,Type,Infos,Subs,Names) :-
1549 add_internal_error('Not properly wrapped', syntaxtraversion(IExpr,Expr,Type,Infos,Subs,Names)),
1550 fail.
1551
1552
1553 map_over_full_bexpr_no_fail(P,BExpr) :-
1554 syntaxtraversion(BExpr,Expr,_,_,Subs,_TNames),
1555 call(P,Expr), % the predicate should not fail
1556 (Subs=[] -> true ; maplist(map_over_full_bexpr_no_fail(P),Subs)).
1557
1558 map_over_bexpr(P,BExpr) :-
1559 syntaxtraversion(BExpr,Expr,_,_,Subs,_TNames),
1560 (call(P,Expr) % should probably fail so that by backtrack we recurse
1561 ;
1562 member(Sub,Subs), map_over_bexpr(P,Sub)
1563 ).
1564 % same as above but gets typed expressions:
1565 map_over_typed_bexpr(P,BExpr) :-
1566 ? syntaxtraversion(BExpr,_Expr,_,_,Subs,_TNames),
1567 ? (call(P,BExpr)
1568 ;
1569 ? member(Sub,Subs), map_over_typed_bexpr(P,Sub)
1570 ).
1571 % same as above but returns value:
1572 map_over_typed_bexpr(P,BExpr,Result) :-
1573 syntaxtraversion(BExpr,_Expr,_,_,Subs,_TNames),
1574 (call(P,BExpr,Result)
1575 ;
1576 member(Sub,Subs), map_over_typed_bexpr(P,Sub,Result)
1577 ).
1578
1579 % same as map_over_expr but provides an accumulator passed top-down to children; needs to be used by failure driven loop
1580
1581 map_over_bexpr_top_down_acc(P,BExpr,TDAcc) :-
1582 syntaxtraversion(BExpr,Expr,_,_,Subs,_TNames),
1583 (call(P,Expr,TDAcc,NewAcc)
1584 -> member(Sub,Subs), map_over_bexpr_top_down_acc(P,Sub,NewAcc)
1585 ; member(Sub,Subs), map_over_bexpr_top_down_acc(P,Sub,TDAcc)
1586 ).
1587 % now a version which gets the typed predicate as argument
1588
1589 map_over_type_bexpr_top_down_acc(P,BExpr,TDAcc) :-
1590 syntaxtraversion(BExpr,_Expr,_,_,Subs,_TNames),
1591 (call(P,BExpr,TDAcc,NewAcc)
1592 -> member(Sub,Subs), map_over_type_bexpr_top_down_acc(P,Sub,NewAcc)
1593 ; member(Sub,Subs), map_over_type_bexpr_top_down_acc(P,Sub,TDAcc)
1594 ).
1595
1596
1597 reduce_over_bexpr(P,BExpr,InitialValue,ResultValue) :-
1598 ? syntaxtraversion(BExpr,Expr,_,_,Subs,_TNames),
1599 ? call(P,Expr,InitialValue,I1), % print(reduce(P,Expr,InitialValue,I1)),nl,
1600 ? scanlist(reduce_over_bexpr(P),Subs,I1,ResultValue).
1601
1602 % apply a predicate over a syntax tree (bottom-up)
1603
1604 transform_bexpr(Pred,b(Expr,Type,Info),NewBExpr) :-
1605 syntaxtransformation(Expr,Subs,_Names,NSubs,NewExpr1),
1606 l_transform_bexpr(Subs,Pred,NSubs),
1607 ? (call(Pred,b(NewExpr1,Type,Info),NewBExpr) -> true ; NewBExpr = b(NewExpr1,Type,Info)).
1608
1609 l_transform_bexpr([],_,[]).
1610 l_transform_bexpr([SubH|T],Pred,[TSubH|TT]) :-
1611 transform_bexpr(Pred,SubH,TSubH),
1612 l_transform_bexpr(T,Pred,TT).
1613
1614 % apply a predicate over a syntax tree (bottom-up) with Accumulator result
1615 % Accumulator is constructed bottom up; Pred receives *all* accumulators of sub expressions
1616
1617 transform_bexpr_with_bup_accs(Pred,b(Expr,Type,Info),NewBExpr,EmptyAcc,Acc) :-
1618 syntaxtransformation(Expr,Subs,_Names,NSubs,NewExpr1),
1619 l_transform_bexpr_with_bup_accs(Subs,Pred,NSubs,EmptyAcc,SubAccs),
1620 (call(Pred,b(NewExpr1,Type,Info),NewBExpr,SubAccs,Acc) -> true
1621 ; NewBExpr = b(NewExpr1,Type,Info), Acc = EmptyAcc).
1622
1623 l_transform_bexpr_with_bup_accs([],_,[],_,[]).
1624 l_transform_bexpr_with_bup_accs([SubH|T],Pred,[TSubH|TT],EmptyAcc,[Acc1|RestAcc]) :-
1625 transform_bexpr_with_bup_accs(Pred,SubH,TSubH,EmptyAcc,Acc1),
1626 l_transform_bexpr_with_bup_accs(T,Pred,TT,EmptyAcc,RestAcc).
1627
1628 % apply a predicate over a syntax tree (bottom-up) with Accumulator result
1629 % a single Accumulator is passed along
1630
1631 transform_bexpr_with_acc(_Pred,E,NewBExpr,InAcc,Acc) :- var(E),!,
1632 NewBExpr=E, Acc=InAcc.
1633 transform_bexpr_with_acc(Pred,b(Expr,Type,Info),NewBExpr,InAcc,Acc) :-
1634 syntaxtransformation(Expr,Subs,_Names,NSubs,NewExpr1),
1635 l_transform_bexpr_with_acc(Subs,Pred,NSubs,InAcc,SubAcc),
1636 (call(Pred,b(NewExpr1,Type,Info),NewBExpr,SubAcc,Acc) -> true
1637 ; NewBExpr = b(NewExpr1,Type,Info), Acc = SubAcc).
1638
1639 l_transform_bexpr_with_acc([],_,[],Acc,Acc).
1640 l_transform_bexpr_with_acc([SubH|T],Pred,[TSubH|TT],InAcc,ResAcc) :-
1641 transform_bexpr_with_acc(Pred,SubH,TSubH,InAcc,Acc1),
1642 l_transform_bexpr_with_acc(T,Pred,TT,Acc1,ResAcc).
1643
1644 min_max_integer_value_used(BExpr,Min,Max) :-
1645 min_max_integer_value_used(BExpr,none,none,Min,Max).
1646 min_max_integer_value_used(BExpr,IMin,IMax,Min,Max) :-
1647 reduce_over_bexpr(min_max_aux,BExpr,minmax(IMin,IMax),minmax(Min,Max)).
1648
1649 min_max_aux(sequence_extension(L),minmax(Min,Max),minmax(NMin,NMax)) :- !,
1650 length(L,Len), % we use implicitly numbers from 1..Len
1651 ((number(Min),1>Min) -> NMin=Min ; NMin=1),
1652 ((number(Max),Len<Max) -> NMax=Max ; NMax=Len).
1653 min_max_aux(integer(N),minmax(Min,Max),minmax(NMin,NMax)) :- !,
1654 ((number(Min),N>Min) -> NMin=Min ; NMin=N),
1655 ((number(Max),N<Max) -> NMax=Max ; NMax=N).
1656 min_max_aux(_,V,V).
1657
1658 % check if a B expression uses something like NAT,NAT1,INT, MAXINT or MININT.
1659 uses_implementable_integers(BExpr) :-
1660 map_over_bexpr(uses_implementable_integers_aux,BExpr).
1661
1662 uses_implementable_integers_aux(maxint).
1663 uses_implementable_integers_aux(minint).
1664 uses_implementable_integers_aux(integer_set(X)) :-
1665 (X='NAT1' ; X='NAT' ; X='INT').
1666
1667 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1668 % some checks
1669 check_if_typed_predicate(b(Pred,X,_)) :- ground(X), X=pred, % at runtime there can be value(X) with variables inside !
1670 syntaxelement(Pred,_,_,_,_,pred).
1671 check_if_typed_expression(b(Expr,Type,_)) :-
1672 syntaxelement(Expr,_,_,_,_,expr),
1673 Type \== pred, Type \== subst, ground(Type).
1674 check_if_typed_substitution(b(Subst,X,_)) :- ground(X), X=subst,
1675 syntaxelement(Subst,_,_,_,_,subst).
1676
1677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1678 % transformations
1679
1680 syntaxtransformation(Expr,Subs,Names,NSubs,NExpr) :-
1681 functor(Expr,F,Arity),
1682 functor(NExpr,F,Arity),
1683 safe_syntaxelement(Expr,Subs,Names,Lists,Constant),
1684 all_same_length(Lists,NLists),
1685 syntaxelement(NExpr,NSubs,_,NLists,Constant,_).
1686
1687 safe_syntaxelement(Expr,Subs,Names,Lists,Constant) :-
1688 ( syntaxelement(Expr,SubsX,NamesX,Lists,ConstantX,_) ->
1689 Subs=SubsX, Names=NamesX, Constant=ConstantX
1690 ; otherwise ->
1691 functor(Expr,F,Arity),
1692 add_error_fail(bsyntaxtree,'Uncovered syntax element: ', F/Arity)
1693 ).
1694
1695 % syntaxelement(Expr,SubExprs,Identifiers,Lists,Constant,Type):
1696 % Expr: the expression itself
1697 % SubExprs: a list of sub-expressions
1698 % Identifiers: a list of identifiers that are newly introduced (e.g. by a quantifier)
1699 % Lists: A list of lists in the expression, to prevent infinite loops when having variable parts
1700 % Constant: A part of the expression that is not a sub-expression (e.g. the number in integer(...))
1701 % Type: Fundamental type of the element (predicate, expression, etc)
1702
1703 % predicates
1704 syntaxelement(truth, [], [], [], [], pred).
1705 syntaxelement(falsity, [], [], [], [], pred).
1706 syntaxelement(conjunct(A,B), [A,B],[], [], [], pred).
1707 syntaxelement(negation(A), [A], [], [], [], pred).
1708 syntaxelement(disjunct(A,B), [A,B],[], [], [], pred).
1709 syntaxelement(implication(A,B), [A,B],[], [], [], pred).
1710 syntaxelement(equivalence(A,B), [A,B],[], [], [], pred).
1711 syntaxelement(equal(A,B), [A,B],[], [], [], pred).
1712 syntaxelement(not_equal(A,B), [A,B],[], [], [], pred).
1713 syntaxelement(member(A,B), [A,B],[], [], [], pred).
1714 syntaxelement(not_member(A,B), [A,B],[], [], [], pred).
1715 syntaxelement(subset(A,B), [A,B],[], [], [], pred).
1716 syntaxelement(subset_strict(A,B), [A,B],[], [], [], pred).
1717 syntaxelement(not_subset(A,B), [A,B],[], [], [], pred).
1718 syntaxelement(not_subset_strict(A,B),[A,B],[], [], [], pred).
1719 syntaxelement(less_equal(A,B), [A,B],[], [], [], pred).
1720 syntaxelement(less(A,B), [A,B],[], [], [], pred).
1721 syntaxelement(greater_equal(A,B), [A,B],[], [], [], pred).
1722 syntaxelement(greater(A,B), [A,B],[], [], [], pred).
1723 syntaxelement(forall(Ids,D,P), [D,P|Ids],Ids,[Ids], [], pred).
1724 syntaxelement(exists(Ids,P), [P|Ids], Ids,[Ids], [], pred).
1725 syntaxelement(finite(A), [A], [], [], [], pred/only_typecheck).
1726 syntaxelement(partition(S,Es), [S|Es],[],[Es],[],pred).
1727 syntaxelement(kodkod(PId,Ids), Ids,[],[Ids],PId, pred).
1728 syntaxelement(external_pred_call(F,Args),Args,[],[Args],F,pred).
1729
1730 % expressions
1731 syntaxelement(value(V), [], [], [], V, expr).
1732 syntaxelement(operation_call_in_expr(Id,As), [Id|As], [], [As], [], expr).
1733 syntaxelement(boolean_true, [], [], [], [], expr).
1734 syntaxelement(boolean_false, [], [], [], [], expr).
1735 syntaxelement(max_int, [], [], [], [], expr).
1736 syntaxelement(min_int, [], [], [], [], expr).
1737 syntaxelement(empty_set, [], [], [], [], expr).
1738 syntaxelement(bool_set, [], [], [], [], expr).
1739 syntaxelement(string_set, [], [], [], [], expr).
1740 syntaxelement(convert_bool(A), [A], [], [], [], expr).
1741 syntaxelement(add(A,B), [A,B],[], [], [], expr).
1742 syntaxelement(minus(A,B), [A,B],[], [], [], expr).
1743 syntaxelement(minus_or_set_subtract(A,B),[A,B],[], [], [], expr/only_typecheck).
1744 syntaxelement(unary_minus(A), [A], [], [], [], expr).
1745 syntaxelement(multiplication(A,B), [A,B],[], [], [], expr).
1746 syntaxelement(mult_or_cart(A,B), [A,B],[], [], [], expr/only_typecheck).
1747 syntaxelement(cartesian_product(A,B), [A,B],[], [], [], expr).
1748 syntaxelement(div(A,B), [A,B],[], [], [], expr).
1749 syntaxelement(floored_div(A,B), [A,B],[], [], [], expr).
1750 syntaxelement(modulo(A,B), [A,B],[], [], [], expr).
1751 syntaxelement(power_of(A,B), [A,B],[], [], [], expr).
1752 syntaxelement(successor, [], [], [], [], expr).
1753 syntaxelement(predecessor, [], [], [], [], expr).
1754 syntaxelement(max(A), [A], [], [], [], expr).
1755 syntaxelement(min(A), [A], [], [], [], expr).
1756 syntaxelement(card(A), [A], [], [], [], expr).
1757 syntaxelement(couple(A,B), [A,B],[], [], [], expr).
1758 syntaxelement(pow_subset(A), [A], [], [], [], expr).
1759 syntaxelement(pow1_subset(A), [A], [], [], [], expr).
1760 syntaxelement(fin_subset(A), [A], [], [], [], expr).
1761 syntaxelement(fin1_subset(A), [A], [], [], [], expr).
1762 syntaxelement(interval(A,B), [A,B],[], [], [], expr).
1763 syntaxelement(union(A,B), [A,B],[], [], [], expr).
1764 syntaxelement(intersection(A,B), [A,B],[], [], [], expr).
1765 syntaxelement(set_subtraction(A,B), [A,B],[], [], [], expr).
1766 syntaxelement(general_union(A), [A], [], [], [], expr).
1767 syntaxelement(general_intersection(A), [A] , [], [], [], expr).
1768 syntaxelement(relations(A,B), [A,B],[], [], [], expr).
1769 syntaxelement(identity(A), [A], [], [], [], expr).
1770 syntaxelement(event_b_identity, [], [], [], [], expr). % for Rodin 1.0, TO DO: Daniel please check
1771 syntaxelement(reverse(A), [A], [], [], [], expr).
1772 syntaxelement(first_projection(A,B), [A,B],[], [], [], expr/only_typecheck).
1773 syntaxelement(first_of_pair(A), [A], [], [], [], expr).
1774 syntaxelement(event_b_first_projection(A),[A], [], [], [], expr/only_typecheck).
1775 syntaxelement(event_b_first_projection_v2,[], [], [], [], expr/only_typecheck). % for Rodin 1.0, TO DO: Daniel please check
1776 syntaxelement(second_projection(A,B), [A,B],[], [], [], expr/only_typecheck).
1777 syntaxelement(event_b_second_projection_v2,[], [], [], [], expr/only_typecheck). % for Rodin 1.0, TO DO: Daniel please check
1778 syntaxelement(second_of_pair(A), [A], [], [], [], expr).
1779 syntaxelement(event_b_second_projection(A),[A], [], [], [], expr/only_typecheck).
1780 syntaxelement(composition(A,B), [A,B],[], [], [], expr).
1781 syntaxelement(ring(A,B), [A,B],[], [], [], expr/only_typecheck).
1782 syntaxelement(direct_product(A,B), [A,B],[], [], [], expr).
1783 syntaxelement(parallel_product(A,B), [A,B],[], [], [], expr).
1784 syntaxelement(trans_function(A), [A], [], [], [], expr).
1785 syntaxelement(trans_relation(A), [A], [], [], [], expr).
1786 syntaxelement(iteration(A,B), [A,B],[], [], [], expr).
1787 syntaxelement(reflexive_closure(A), [A], [], [], [], expr).
1788 syntaxelement(closure(A), [A], [], [], [], expr).
1789 syntaxelement(domain(A), [A], [], [], [], expr).
1790 syntaxelement(range(A), [A], [], [], [], expr).
1791 syntaxelement(image(A,B), [A,B],[], [], [], expr).
1792 syntaxelement(domain_restriction(A,B), [A,B],[], [], [], expr).
1793 syntaxelement(domain_subtraction(A,B), [A,B],[], [], [], expr).
1794 syntaxelement(range_restriction(A,B), [A,B],[], [], [], expr).
1795 syntaxelement(range_subtraction(A,B), [A,B],[], [], [], expr).
1796 syntaxelement(overwrite(A,B), [A,B],[], [], [], expr).
1797 syntaxelement(partial_function(A,B), [A,B],[], [], [], expr).
1798 syntaxelement(total_function(A,B), [A,B],[], [], [], expr).
1799 syntaxelement(partial_injection(A,B), [A,B],[], [], [], expr).
1800 syntaxelement(total_injection(A,B), [A,B],[], [], [], expr).
1801 syntaxelement(partial_surjection(A,B), [A,B],[], [], [], expr).
1802 syntaxelement(total_surjection(A,B), [A,B],[], [], [], expr).
1803 syntaxelement(total_bijection(A,B), [A,B],[], [], [], expr).
1804 syntaxelement(partial_bijection(A,B), [A,B],[], [], [], expr).
1805 syntaxelement(total_relation(A,B), [A,B],[], [], [], expr).
1806 syntaxelement(surjection_relation(A,B),[A,B],[], [], [], expr).
1807 syntaxelement(total_surjection_relation(A,B),[A,B],[], [], [], expr).
1808 syntaxelement(seq(A), [A], [], [], [], expr).
1809 syntaxelement(seq1(A), [A], [], [], [], expr).
1810 syntaxelement(iseq(A), [A], [], [], [], expr).
1811 syntaxelement(iseq1(A), [A], [], [], [], expr).
1812 syntaxelement(perm(A), [A], [], [], [], expr).
1813 syntaxelement(empty_sequence, [], [], [], [], expr).
1814 syntaxelement(size(A), [A], [], [], [], expr).
1815 syntaxelement(first(A), [A], [], [], [], expr).
1816 syntaxelement(last(A), [A], [], [], [], expr).
1817 syntaxelement(front(A), [A], [], [], [], expr).
1818 syntaxelement(tail(A), [A], [], [], [], expr).
1819 syntaxelement(rev(A), [A], [], [], [], expr).
1820 syntaxelement(concat(A,B), [A,B],[], [], [], expr).
1821 syntaxelement(insert_front(A,B), [A,B],[], [], [], expr).
1822 syntaxelement(insert_tail(A,B), [A,B],[], [], [], expr).
1823 syntaxelement(restrict_front(A,B), [A,B],[], [], [], expr).
1824 syntaxelement(restrict_tail(A,B), [A,B],[], [], [], expr).
1825 syntaxelement(general_concat(A), [A], [], [], [], expr).
1826 syntaxelement(function(A,B), [A,B],[], [], [], expr).
1827 syntaxelement(external_function_call(F,Args),Args,[],[Args],F,expr).
1828 syntaxelement(identifier(I), [], [], [], I, expr).
1829 syntaxelement(lazy_lookup_expr(I), [], [], [], I, expr).
1830 syntaxelement(lazy_lookup_pred(I), [], [], [], I, pred).
1831 syntaxelement(integer(I), [], [], [], I, expr).
1832 syntaxelement(integer_set(T), [], [], [], T, expr).
1833 syntaxelement(string(S), [], [], [], S, expr).
1834 syntaxelement(set_extension(L), L, [], [L], [], expr).
1835 syntaxelement(sequence_extension(L), L, [], [L], [], expr).
1836 syntaxelement(comprehension_set(Ids,P),[P|Ids], Ids,[Ids], [], expr).
1837 syntaxelement(event_b_comprehension_set(Ids,E,P),[E,P|Ids], Ids,[Ids], [], expr/only_typecheck).
1838 syntaxelement(lambda(Ids,P,E), [P,E|Ids],Ids,[Ids], [], expr).
1839 syntaxelement(general_sum(Ids,P,E), [P,E|Ids],Ids,[Ids], [], expr).
1840 syntaxelement(general_product(Ids,P,E), [P,E|Ids],Ids,[Ids], [], expr).
1841 syntaxelement(quantified_union(Ids,P,E), [P,E|Ids],Ids,[Ids], [], expr).
1842 syntaxelement(quantified_intersection(Ids,P,E), [P,E|Ids],Ids,[Ids], [], expr).
1843 syntaxelement(struct(Rec), [Rec], [], [], [], expr).
1844 syntaxelement(rec(Fields), FContent, [], [FContent], FNames, expr) :- syntaxfields(Fields,FContent, FNames).
1845 syntaxelement(record_field(R,I), [R], [], [], I, expr).
1846 syntaxelement(assertion_expression(Cond,ErrMsg,Expr), [Cond,Expr], [], [], ErrMsg, expr).
1847 syntaxelement(typeset, [], [], [], [], expr/only_typecheck).
1848
1849 syntaxelement(tree(A), [A], [], [], [], expr).
1850 syntaxelement(btree(A), [A], [], [], [], expr).
1851 syntaxelement(const(A,B), [A,B],[], [], [], expr).
1852 syntaxelement(top(A), [A], [], [], [], expr).
1853 syntaxelement(sons(A), [A], [], [], [], expr).
1854 syntaxelement(prefix(A), [A], [], [], [], expr).
1855 syntaxelement(postfix(A), [A], [], [], [], expr).
1856 syntaxelement(sizet(A), [A], [], [], [], expr).
1857 syntaxelement(mirror(A), [A], [], [], [], expr).
1858 syntaxelement(rank(A,B), [A,B],[], [], [], expr).
1859 syntaxelement(father(A,B), [A,B],[], [], [], expr).
1860 syntaxelement(son(A,B,C), [A,B,C],[], [], [], expr).
1861 syntaxelement(subtree(A,B), [A,B],[], [], [], expr).
1862 syntaxelement(arity(A,B), [A,B],[], [], [], expr).
1863 syntaxelement(bin(A), [A],[], [], [], expr).
1864 syntaxelement(bin(A,B,C), [A,B,C],[], [], [], expr).
1865 syntaxelement(infix(A), [A], [], [], [], expr).
1866 syntaxelement(left(A), [A], [], [], [], expr).
1867 syntaxelement(right(A), [A], [], [], [], expr).
1868
1869 % substitutions
1870 syntaxelement(skip, [], [], [], [], subst).
1871 syntaxelement(precondition(A,B), [A,B],[], [], [], subst).
1872 syntaxelement(assertion(A,B), [A,B],[], [], [], subst).
1873 syntaxelement(if_elsif(A,B), [A,B],[], [], [], subst/elsif).
1874 syntaxelement(while(A,B,C,D), [A,B,C,D],[], [], [], subst).
1875 % used only internally in the interpreter, contains last value of variant:
1876 syntaxelement(while1(A,B,C,D,E), [A,B,C,D],[], [], E, subst).
1877 syntaxelement(select_when(A,B), [A,B],[], [], [], subst/when).
1878 syntaxelement(block(S),[S],[],[],[], subst/only_typecheck).
1879 syntaxelement(assign(Lhs,Rhs),Exprs,[],[Lhs,Rhs], [], subst) :- append(Lhs,Rhs,Exprs).
1880 syntaxelement(assign_single_id(Id,Rhs),[Id,Rhs],[],[], [], subst).
1881 syntaxelement(any(Ids,P,S),[P,S|Ids],Ids,[Ids], [], subst).
1882 syntaxelement(var(Ids,S), [S|Ids], Ids,[Ids], [], subst).
1883 syntaxelement(if(Ifs), Ifs, [], [Ifs], [], subst).
1884 syntaxelement(parallel(Ss), Ss, [], [Ss], [], subst).
1885 syntaxelement(sequence(Ss), Ss, [], [Ss], [], subst).
1886 syntaxelement(becomes_element_of(Ids,E), [E|Ids], [], [Ids], [], subst).
1887 syntaxelement(becomes_such(Ids,P), [P|Ids], [], [Ids], [], subst).
1888 syntaxelement(evb2_becomes_such(Ids,P), [P|Ids], [], [Ids], [], subst/only_typecheck).
1889 syntaxelement(let(Ids,P,S), [P,S|Ids], Ids, [Ids], [], subst).
1890 syntaxelement(operation_call(Id,Rs,As), [Id|Exprs], [], [Rs,As], [], subst) :- append(Rs,As,Exprs).
1891 syntaxelement(case(E,Eithers,Else), [E,Else|Eithers], [], [Eithers], [], subst).
1892 syntaxelement(case_or(Es,S), [S|Es], [], [Es], [], subst/caseor).
1893 syntaxelement(choice(Ss), Ss, [], [Ss], [], subst).
1894 syntaxelement(select(Whens), Whens, [], [Whens], [], subst).
1895 syntaxelement(select(Whens,Else), [Else|Whens], [], [Whens], [], subst).
1896 syntaxelement(operation(I,Rs,As,B), [I,B|Ids], Ids, [Rs,As], [], subst) :- append(Rs,As,Ids).
1897 syntaxelement(external_subst_call(F,Args),Args,[],[Args],F,subst).
1898
1899 % elements of a VALUES clause
1900 syntaxelement(values_entry(I,E),[I,E],[],[],[],values_entry).
1901
1902 % syntax for Event-B events
1903 syntaxelement(rlevent(I,Sec,St,Ps,G,Ts,As,VWs,PWs,Ums,Rs), Subs, [], [Ps,Ts,As,VWs,PWs,Ums,Rs], [I,Sec], subst) :-
1904 append([[St],Ps,[G],Ts,As,VWs,PWs,Ums,Rs],Subs).
1905 syntaxelement(witness(I,P), [I,P], [], [], [], witness).
1906
1907 % extended syntax for Z
1908 syntaxelement(let_predicate(Ids,As,Pred), Exprs, Ids, [Ids,As], [], pred) :- append([Ids,As,[Pred]],Exprs).
1909 syntaxelement(let_expression(Ids,As,Expr), Exprs, Ids, [Ids,As], [], expr) :- append([Ids,As,[Expr]],Exprs).
1910 syntaxelement(let_expression_global(Ids,As,Expr), Exprs, Ids, [Ids,As], [], expr) :- % version used by b_compiler
1911 append([Ids,As,[Expr]],Exprs).
1912 syntaxelement(lazy_let_expr(TID,A,Expr), Exprs, [TID], [[TID],[A]], [], expr) :-
1913 append([[TID],[A],[Expr]],Exprs).
1914 syntaxelement(lazy_let_pred(TID,A,Expr), Exprs, [TID], [[TID],[A]], [], pred) :-
1915 append([[TID],[A],[Expr]],Exprs).
1916 syntaxelement(lazy_let_subst(TID,A,Expr), Exprs, [TID], [[TID],[A]], [], subst) :-
1917 append([[TID],[A],[Expr]],Exprs).
1918 syntaxelement(if_then_else(If,Then,Else),[If,Then,Else], [], [], [], expr).
1919 syntaxelement(compaction(A), [A], [], [], [], expr).
1920 syntaxelement(mu(A), [A], [], [], [], expr).
1921 syntaxelement(bag_items(A), [A], [], [], [], expr).
1922
1923 syntaxelement(freetype_set(Id), [], [], [], Id, expr).
1924 syntaxelement(freetype_case(Type,Case,Expr), [Expr], [], [], [Type,Case], pred).
1925 syntaxelement(freetype_constructor(Type,Case,Expr), [Expr], [], [], [Type,Case], expr).
1926 syntaxelement(freetype_destructor(Type,Case,Expr), [Expr], [], [], [Type,Case], expr).
1927
1928 syntaxelement(ordinary, [], [], [], [], status).
1929 syntaxelement(anticipated(Variant), [Variant], [], [], [], status).
1930 syntaxelement(convergent(Variant), [Variant], [], [], [], status).
1931
1932 % Just one ID expected
1933 syntaxelement(recursive_let(Id,C),[Id,C],[Id],[],[], expr).
1934
1935
1936 % fields of records
1937 %syntaxfields(Fields,C,_) :- var(Fields),var(C),var(N),!, add_internal_error('Illegal call: ',syntaxfields(Fields,C,N)),fail.
1938 syntaxfields([],[],[]).
1939 syntaxfields([field(N,C)|Rest],[C|CRest],[N|NRest]) :- syntaxfields(Rest,CRest,NRest).
1940
1941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1942 % helper for declaration of quantified identifiers
1943
1944 % has_declared_identifier/2 returns a list of identifiers which are declared in
1945 % this AST node. The main difference to the Names variable when doing a
1946 % syntaxtraversion/6 or similiar is that the identifiers are described by
1947 % predicates.
1948 has_declared_identifier(TExpr,Ids) :-
1949 get_texpr_expr(TExpr,Expr),
1950 ( default_declaration(Expr,_,Ids,_)
1951 ; non_default_declaration(Expr,Ids)).
1952
1953 add_declaration_for_identifier(TExpr,Decl,NTExpr) :-
1954 remove_bt(TExpr,Expr,NExpr,NTExpr),
1955 ( default_declaration(Expr,Predicate,Ids,Constant) ->
1956 same_functor(Expr,NExpr),
1957 conjunct_predicates([Decl,Predicate],NPredicate),
1958 default_declaration(NExpr,NPredicate,Ids,Constant)
1959 ; non_default_declaration(Expr,_Ids) ->
1960 add_non_default_declaration(Expr,Decl,NExpr)).
1961
1962 :- use_module(probsrc(btypechecker), [prime_identifiers/2]).
1963
1964 default_declaration(forall(Ids,D,P),D,Ids,P).
1965 default_declaration(exists(Ids,P),P,Ids,[]).
1966 default_declaration(comprehension_set(Ids,P),P,Ids,[]).
1967 default_declaration(lambda(Ids,P,E),P,Ids,E).
1968 default_declaration(general_sum(Ids,P,E),P,Ids,E).
1969 default_declaration(general_product(Ids,P,E),P,Ids,E).
1970 default_declaration(quantified_union(Ids,P,E),P,Ids,E).
1971 default_declaration(quantified_intersection(Ids,P,E),P,Ids,E).
1972 default_declaration(any(Ids,P,S),P,Ids,S).
1973 default_declaration(becomes_such(Ids,P),P,Ids,[]).
1974 default_declaration(evb2_becomes_such(Ids,P),P,Primed,[]) :- nl,print(evb2(Ids,Primed)),nl,nl, % no longer used, as it is translated to becomes_such
1975 prime_identifiers(Ids,Primed).
1976 default_declaration(rlevent(I,Sec,St,Ps,G,Ts,As,VWs,PWs,Ums,Rs),G,Ps,
1977 [I,Sec,St,Ps,Ts,As,VWs,PWs,Ums,Rs]).
1978
1979 non_default_declaration(operation(_I,Rs,As,_TBody),Ids) :-
1980 append(Rs,As,Ids).
1981
1982 add_non_default_declaration(operation(I,Rs,As,TBody),Decl,operation(I,Rs,As,NTBody)) :-
1983 ( remove_bt(TBody,precondition(P,S),precondition(NP,S),NTBody) ->
1984 conjunct_predicates([Decl,P],NP)
1985 ; otherwise ->
1986 create_texpr(precondition(Decl,TBody),subst,[],NTBody)).
1987
1988 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1989 % pattern definitions (not yet finished)
1990
1991 bsyntax_pattern(Expr,TExpr) :-
1992 var(Expr),!,Expr=TExpr.
1993 bsyntax_pattern(-Expr,TExpr) :-
1994 !,remove_all_infos(Expr,TExpr).
1995 bsyntax_pattern(Expr,TExpr) :-
1996 functor(Expr,b,3),!,Expr=TExpr.
1997 bsyntax_pattern(Expr:Type/Info,TExpr) :-
1998 !,bsyntax_pattern2(Expr,Type,Info,TExpr).
1999 bsyntax_pattern(Expr:Type,TExpr) :-
2000 !,bsyntax_pattern2(Expr,Type,_Info,TExpr).
2001 bsyntax_pattern(Expr/Info,TExpr) :-
2002 !,bsyntax_pattern2(Expr,_Type,Info,TExpr).
2003 bsyntax_pattern(Expr,TExpr) :-
2004 !,bsyntax_pattern2(Expr,_Type,_Info,TExpr).
2005
2006 bsyntax_pattern2(Pattern,Type,Info,TExpr) :-
2007 functor(Pattern,Functor,Arity),
2008 functor(R,Functor,Arity),
2009 create_texpr(R,Type,Info,TExpr),
2010 syntaxelement(Pattern,PSubs,_,PLists,Const,EType),
2011 syntaxelement(R,RSubs,_,RLists,Const,EType),
2012 ( EType==pred -> Type=pred
2013 ; EType==subst -> Type=subst
2014 ; otherwise -> true),
2015 all_same_length(PLists,RLists),
2016 maplist(bsyntax_pattern,PSubs,RSubs).
2017
2018 all_same_length([],[]).
2019 all_same_length([A|Arest],[B|Brest]) :-
2020 ( var(A),var(B) ->
2021 add_error_fail(bsyntaxtree,'At least one list should be nonvar',[A,B])
2022 ; otherwise ->
2023 same_length(A,B)),
2024 all_same_length(Arest,Brest).
2025
2026 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2027 % strip an AST into a more compact form (without b/3 terms)
2028
2029 strip_and_norm_ast(TExpr,SNExpr) :-
2030 get_texpr_expr(TExpr,Expr),
2031 strip_and_norm_ast_aux(Expr,SNExpr).
2032
2033 :- use_module(tools,[safe_univ_no_cutoff/2]).
2034 strip_and_norm_ast_aux(Expr,Res) :-
2035 comm_assoc_subs(Expr,Op,Subs,[]), !, % associative & commutative operator detected
2036 %print(assoc(Op)),nl,
2037 maplist(strip_and_norm_ast_aux,Subs,NSubs), % Subs are already unwrapped
2038 sort(NSubs,Sorted), % in case there are associative operators that are not commutative: insert is_commutative check
2039 safe_univ_no_cutoff(Res,[Op|Sorted]).
2040 strip_and_norm_ast_aux(Expr,Res) :-
2041 assoc_subs(Expr,Op,Subs,[]), !, % associative operator detected
2042 %print(assoc(Op)),nl,
2043 maplist(strip_and_norm_ast_aux,Subs,NSubs), % Subs are already unwrapped
2044 safe_univ_no_cutoff(Res,[Op|NSubs]).
2045 strip_and_norm_ast_aux(Expr,SNExpr) :-
2046 syntaxtransformation(Expr,Subs,_,NSubs,SExpr),
2047 strip_and_norm_ast_l(Subs,NSubs),
2048 norm_strip(SExpr,SNExpr).
2049
2050 strip_and_norm_ast_l([],[]).
2051 strip_and_norm_ast_l([TExpr|Trest],[NExpr|Nrest]) :-
2052 strip_and_norm_ast(TExpr,NExpr),
2053 strip_and_norm_ast_l(Trest,Nrest).
2054
2055 norm_strip(greater_equal(A,B),less_equal(B,A)) :- !.
2056 norm_strip(greater(A,B),less(B,A)) :- !.
2057 norm_strip(set_extension(NL),set_extension(SNL)) :- !,
2058 sort(NL,SNL).
2059 norm_strip(Old,New) :-
2060 functor(Old,Functor,2),
2061 is_commutative(Functor),!,
2062 arg(1,Old,OA),
2063 arg(2,Old,OB),
2064 ( OA @> OB -> New =.. [Functor,OB,OA]
2065 ; New=Old).
2066 norm_strip(Old,Old).
2067 % TO DO: flatten associative operators into lists !
2068
2069 comm_assoc_subs(conjunct(TA,TB),conjunct) --> !,
2070 {get_texpr_expr(TA,A), get_texpr_expr(TB,B)},
2071 comm_assoc_subs(A,conjunct), comm_assoc_subs(B,conjunct).
2072 comm_assoc_subs(disjunct(TA,TB),disjunct) --> !,
2073 {get_texpr_expr(TA,A), get_texpr_expr(TB,B)},
2074 comm_assoc_subs(A,disjunct), comm_assoc_subs(B,disjunct).
2075 comm_assoc_subs(add(TA,TB),add) --> !,
2076 {get_texpr_expr(TA,A), get_texpr_expr(TB,B)},
2077 comm_assoc_subs(A,add), comm_assoc_subs(B,add).
2078 comm_assoc_subs(multiplication(TA,TB),multiplication) --> !,
2079 {get_texpr_expr(TA,A), get_texpr_expr(TB,B)},
2080 comm_assoc_subs(A,multiplication), comm_assoc_subs(B,multiplication).
2081 comm_assoc_subs(union(TA,TB),union) --> !,
2082 {get_texpr_expr(TA,A), get_texpr_expr(TB,B)},
2083 comm_assoc_subs(A,union), comm_assoc_subs(B,union).
2084 comm_assoc_subs(intersection(TA,TB),intersection) --> !,
2085 {get_texpr_expr(TA,A), get_texpr_expr(TB,B)},
2086 comm_assoc_subs(A,intersection), comm_assoc_subs(B,intersection).
2087 comm_assoc_subs(Expr,Op) --> {nonvar(Op)},[Expr]. % base case for other operators
2088
2089 % detect just associative operators
2090 assoc_subs(concat(TA,TB),concat) --> !,
2091 {get_texpr_expr(TA,A), get_texpr_expr(TB,B)},
2092 assoc_subs(A,concat), assoc_subs(B,concat).
2093 assoc_subs(composition(TA,TB),composition) --> !,
2094 {get_texpr_expr(TA,A), get_texpr_expr(TB,B)},
2095 assoc_subs(A,composition), assoc_subs(B,composition).
2096 assoc_subs(Expr,Op) --> {nonvar(Op)},[Expr]. % base case for other operators
2097
2098 is_commutative(conjunct).
2099 is_commutative(disjunct).
2100 is_commutative(equivalence).
2101 is_commutative(equal).
2102 is_commutative(not_equal).
2103 is_commutative(add).
2104 is_commutative(multiplication).
2105 is_commutative(union).
2106 is_commutative(intersection).
2107
2108 % check if two type expressions are same modulo info fields and reordering of commutative operators
2109 % same_texpr does not reorder wrt commutativity.
2110 same_norm_texpr(TExpr1,TExpr2) :-
2111 strip_and_norm_ast(TExpr1,N1), %print(n1(N1)),nl,
2112 strip_and_norm_ast(TExpr2,N1). %print(n2(N2)),nl, N1=N2.
2113
2114 % -------------------------
2115
2116 % check if a ProB type is a set type:
2117 is_set_type(set(Type),Type).
2118 is_set_type(seq(Type),couple(integer,Type)).
2119 % 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
2120 % is_set_type(any,any).
2121
2122 get_set_type(TypeX,Res) :-
2123 ? (is_set_type(TypeX,SetType) -> Res=SetType ; add_error_fail(get_set_type,'Not a set type: ',TypeX)).
2124
2125 get_texpr_set_type(X,Res) :- get_texpr_type(X,TypeX),
2126 get_set_type(TypeX,Res).
2127
2128
2129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2130 % check if a set contains all elements of a type, i.e., maximal type
2131 is_just_type(Expr) :- is_just_type(Expr,[]).
2132 % is_just_type(+Expr,+RTT):
2133 % like is_just_type/1 but RTT is a list of identifiers (without type information)
2134 % of variables or constants that are known to be types, too.
2135 % E.g. is_just_type(a ** INTEGER) would fail but is_just_type(a ** INTEGER,[a]) would
2136 % succeed.
2137 is_just_type(b(E,T,I),RTT) :- is_just_type3(E,T,I,RTT).
2138
2139
2140 is_just_type3(identifier(G),set(Type),Infos,RefsToTypes) :-
2141 ? ( Type = global(G), memberchk(given_set,Infos)
2142 ; memberchk(G,RefsToTypes)),!.
2143 is_just_type3(freetype_set(_),_,_,_).
2144 is_just_type3(pow_subset(E),_,_,RTT) :- is_just_type(E,RTT).
2145 is_just_type3(fin_subset(E),T,_,RTT) :- \+ is_infinite_type(T),is_just_type(E,RTT).
2146 is_just_type3(integer_set('INTEGER'),set(integer),_,_).
2147 is_just_type3(bool_set,set(boolean),_,_).
2148 is_just_type3(string_set,set(string),_,_).
2149 is_just_type3(cartesian_product(A,B),_,_,RTT) :-
2150 is_just_type(A,RTT),is_just_type(B,RTT).
2151 is_just_type3(mult_or_cart(A,B),_,_,RTT) :- % is_just_type/1 could be called before the cleanup
2152 is_just_type(A,RTT),is_just_type(B,RTT). % of an expression has finished
2153 is_just_type3(relations(A,B),_,_,RTT) :-
2154 is_just_type(A,RTT),is_just_type(B,RTT).
2155 is_just_type3(struct(b(rec(Fields),_,_)),_,_,RTT) :-
2156 maplist(field_is_just_type(RTT),Fields).
2157 is_just_type3(typeset,_,_,_).
2158 is_just_type3(comprehension_set(_,b(truth,_,_)),_,_,_).
2159 is_just_type3(value(Val),ST,_,_) :- is_set_type(ST,Type), is_maximal_value(Val,Type). % also see: quick_is_definitely_maximal_set(Val).
2160
2161 field_is_just_type(RTT,field(_,Set)) :- is_just_type(Set,RTT).
2162
2163 is_maximal_value(V,_) :- var(V),!,fail.
2164 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)
2165
2166 % Generate a custom matching / visitor predicate
2167 % bsyntaxtree:gen_visitor(bexpr_variables_aux,bexpr_variables)
2168 /*
2169 gen_visitor(Pred, BodyPred) :- syntaxelement(Expr,SubsX,_NamesX,_Lists,_ConstantX,_),
2170 print_clause(Pred,BodyPred,Expr,SubsX),
2171 fail.
2172 gen_visitor(Pred, BodyPred) :- nl.
2173
2174 print_clause(Pred,BodyPred,Expr,SubsX) :- E=..[Op|SubsX], format('~w(~w) :- ',[Pred,Expr]).
2175 */
2176
2177 /*
2178 * create_recursive_compset(+Ids,+Cond,+Type,+Infos,-RecId,-TCompSet)
2179 * creates a recursive comprehension set:
2180 * Ids is the list of the introduced typed identifiers
2181 * Cond is the condition (a typed predicate)
2182 * Infos are additional informations for the comprehension set syntax element
2183 * RecId is the identifier (untyped, an atom) that can be used in Cond to refer to the
2184 * comprehension set recursively. Usually RecId is used in Cond as a variable
2185 * TCompSet is the generated recursive comprehension set, the recursion parameter is introduced
2186 * by a recusive(Id,CompSet) syntax element
2187 */
2188 create_recursive_compset(Ids,Cond,Type,Infos,RecId,TCompSet) :-
2189 unique_id("recursive.",RecId),
2190 add_symbolic_annotation(Infos,RInfos),
2191 create_texpr(comprehension_set(Ids,Cond),Type,RInfos,TCompSet1),
2192 create_typed_id(RecId,Type,TRecId),
2193 create_texpr(recursive_let(TRecId,TCompSet1),Type,[],TCompSet).
2194
2195 unique_typed_id(Prefix,Type,TId) :-
2196 unique_id(Prefix,Id),
2197 create_typed_id(Id,Type,TId).
2198
2199
2200 mark_bexpr_as_symbolic(b(E,T,I),b(E2,T,RI)) :-
2201 add_symbolic_annotation(I,RI),
2202 mark_aux(E,E2).
2203 mark_aux(union(A,B),R) :- !, R=union(SA,SB),
2204 mark_bexpr_as_symbolic(A,SA), mark_bexpr_as_symbolic(B,SB).
2205 % union is currently the only operator that is kept symbolically
2206 mark_aux(A,A).
2207
2208 add_symbolic_annotation([H|I],R) :- H == prob_annotation('SYMBOLIC'),!, R=[H|I].
2209 add_symbolic_annotation(I,R) :- !, R=[prob_annotation('SYMBOLIC')|I].
2210
2211 % identifier_sub_ast(+TExpr,+Identifier,-SubPosition):
2212 % Find occurences of an identifier "Identifier" in an expression "TExpr"
2213 % Returns a list of positions (beginning with 0) that describes the position of a sub-expression
2214 % that contains all occurrences of Identifier in TExpr.
2215 % E.g. [1,0,1] means "second sub-expression of TExpr, then the first sub-expression of that,
2216 % then the second sub-expression of that".
2217 % When an identifier has multiple occurences, the position of the sub-expression is returned
2218 % where all occurences of it are located.
2219 % If the identifier is not found, the call fails.
2220 % Sub-expressions are meant like the ones syntaxtraversion or syntaxtransformation return.
2221 identifier_sub_ast(TExpr,Identifier,SubPosition) :-
2222 syntaxtraversion(TExpr,Expr,_Type,_Infos,AllSubs,Names),
2223 identifier_sub_ast_aux(Expr,AllSubs,Names,Identifier,SubPosition).
2224 identifier_sub_ast_aux(identifier(Identifier),[],[],Identifier,[]) :- !.
2225 identifier_sub_ast_aux(_Expr,AllSubs,Names,Identifier,SubPosition) :-
2226 get_texpr_id(TId,Identifier),nonmember(TId,Names),
2227 % For each sub-expression E in the list AllSubs create a term Pos-E
2228 % where Pos is E's position (starting with 0) in AllSubs
2229 foldl(annotate_pos,AllSubs,AllAnnotatedSubs,0,_),
2230 % Introduced identifiers occur alsa as sub-expressions, remove those
2231 foldl(select_sub,Names,AllAnnotatedSubs,RealAnnSubs),
2232 convlist(identifier_sub_ast_aux2(Identifier),RealAnnSubs,SubPositions),
2233 ( SubPositions = [SubPosition] -> true
2234 ; SubPositions = [_,_|_] -> % More then one occurrences - make this the found node
2235 SubPosition = []).
2236 identifier_sub_ast_aux2(Identifier,Pos-TExpr,[Pos|SubPosition]) :-
2237 identifier_sub_ast(TExpr,Identifier,SubPosition).
2238 annotate_pos(TExpr,I-TExpr,I,I2) :- I2 is I+1.
2239 select_sub(Name,AnnotatedSubs,Result) :-
2240 selectchk(_Pos-Name,AnnotatedSubs,Result).
2241
2242 % exchange_ast_position(+SubPosition,+OldTExpr,-OldInner,+NewInner,-NewTExpr):
2243 % exchanges a sub-expression in the expression "OldTExpr".
2244 % SubPosition is a list of positions like identifier_sub_ast/3 returns it.
2245 % OldInner is the sub-expression found in OldTExpr.
2246 % NewInner is the new sub-expression.
2247 % NewTExpr is the new expression that originates from replacing OldInner by NewInner.
2248 exchange_ast_position([],Old,Old,New,New).
2249 exchange_ast_position([Pos|RestPos],OldTExpr,OldInner,NewInner,NewTExpr) :-
2250 remove_bt(OldTExpr,OldExpr,NewExpr,NewTExpr),
2251 syntaxtransformation(OldExpr,Subs,_Names,NSubs,NewExpr),
2252 nth0(Pos,Subs, OldSelected,Rest),
2253 nth0(Pos,NSubs,NewSelected,Rest),
2254 exchange_ast_position(RestPos,OldSelected,OldInner,NewInner,NewSelected).
2255
2256
2257 % -----------------------
2258
2259 % a simple checker to see if an AST is well-formed:
2260 % can be tested e.g. as follows: b_get_invariant_from_machine(I), check_ast(I).
2261
2262 check_ast(TE) :- check_ast(false,TE).
2263 check_ast(AllowVars,TExpr) :- %nl,print('CHECK AST'),nl,
2264 map_over_typed_bexpr(check_ast_texpr(AllowVars),TExpr).
2265 check_ast(_,_).
2266
2267 :- use_module(typing_tools,[valid_ground_type/1]).
2268 %check_ast_texpr(X) :- print(check(X)),nl,fail.
2269 check_ast_texpr(AllowVars,b(E,Type,Infos)) :-
2270 (check_expr(E,Type,Infos) -> true ; add_error(check_ast_texpr,'Invalid Expr: ', b(E,Type,Infos))),
2271 (check_type(Type,AllowVars) -> true ; add_error(check_ast_texpr,'Invalid Type: ',b(E,Type,Infos))),
2272 safe_functor(E,F),
2273 (check_infos(Infos,F) -> true ; add_error(check_ast_texpr,'Invalid Infos: ',b(E,Type,Infos))),
2274 fail. % to force backtracking in map_over_typed_bexpr
2275
2276 safe_functor(V,R) :- var(V),!,R='$VAR'.
2277 safe_functor(E,F/N) :- functor(E,F,N).
2278
2279 check_type(X,AllowVars) :- var(X),!,
2280 (AllowVars==true -> true ; add_error(check_type,'Variable type: ',X),fail).
2281 check_type(pred,_) :- !.
2282 check_type(subst,_) :- !.
2283 check_type(op(Paras,Returns),AllowVars) :- !,
2284 maplist(check_normal_type(AllowVars),Paras),
2285 maplist(check_normal_type(AllowVars),Returns).
2286 check_type(T,AllowVars) :- check_normal_type(AllowVars,T).
2287
2288 check_normal_type(AllowVars,T) :-
2289 (AllowVars \== true -> valid_ground_type(T)
2290 ; ground(T) -> valid_ground_type(T)
2291 ; true). % TO DO: call valid_ground_type but pass AllowVars
2292
2293
2294 check_infos(X,F) :- var(X),!, add_error(check_infos,'Info field list not terminated: ',F:X),fail.
2295 check_infos([],_).
2296 check_infos([H|_],F) :- \+ ground(H),!, add_error(check_infos,'Info field not ground: ',F:H),fail.
2297 check_infos([[H|T]|_],F) :- !, add_error(check_infos,'Info field contains nested list: ',F:[H|T]),fail.
2298 check_infos([cse_used_ids(H)|T],F) :- member(cse_used_ids(H2),T),!,
2299 add_error(check_infos,'Multiple cse_used_ids entry: ',F:[H,H2]),fail.
2300 check_infos([used_ids(H)|T],F) :- member(used_ids(H2),T),!,
2301 add_error(check_infos,'Multiple used_ids entry: ',F:[H,H2]),fail.
2302 check_infos([_|T],F) :- check_infos(T,F).
2303
2304 check_expr(Expr,Type,Infos) :- nonmember(contains_wd_condition,Infos),
2305 sub_expression_contains_wd_condition(Expr,Sub),
2306 TE = b(Expr,Type,Infos),
2307 (Type = subst -> fail % AST cleanup is not called for substitutions; WD-info not available for substitutions at the moment
2308 %translate:translate_substitution(TE,PS)
2309 ; translate_bexpression(TE,PS)),
2310 functor(Expr,Functor,_),
2311 functor(Sub,SubFunctor,_),
2312 tools:ajoin(['Node for AST node ',Functor,' does not contain WD info from Subexpression ',SubFunctor,' :'],Msg),
2313 add_warning(check_expr,Msg,PS,TE).
2314 check_expr(member(LHS,RHS),Type,Infos) :- is_just_type(RHS),
2315 get_preference(optimize_ast,true),
2316 !,
2317 TE = b(member(LHS,RHS),Type,Infos),
2318 translate:translate_bexpression(TE,PS),
2319 add_warning(check_expr,'AST contains redundant typing predicate: ',PS,TE).
2320 check_expr(identifier(ID),_,_) :- illegal_id(ID),!,
2321 add_error(check_infos,'Illegal identifier: ', identifier(ID)).
2322 check_expr(lazy_lookup_expr(ID),_,_) :- illegal_id(ID),!,
2323 add_error(check_infos,'Illegal identifier: ', lazy_lookup_expr(ID)).
2324 check_expr(lazy_lookup_pred(ID),_,_) :- illegal_id(ID),!,
2325 add_error(check_infos,'Illegal identifier: ', lazy_lookup_pred(ID)).
2326 check_expr(exists(Parameters,Condition),pred,Infos) :- !,
2327 b_interpreter:get_exists_used_ids(Parameters,Condition,Infos,_Used). % this will do some checks
2328 check_expr(_,_,_).
2329
2330 illegal_id(ID) :- var(ID),!.
2331 illegal_id(op(ID)) :- !, \+ atom(ID).
2332 illegal_id(ID) :- \+ atom(ID).
2333
2334 % -----------------------
2335
2336
2337 indent_ws(X) :- X<1,!.
2338 indent_ws(X) :- print(' '), X1 is X-1, indent_ws(X1).
2339
2340 print_ast_td(b(E,T,I),Level,L1) :-
2341 indent_ws(Level),
2342 (E=identifier(_)
2343 -> format('~w (~w) -> ~w~n',[E,T,I])
2344 ; functor(E,F,N),
2345 format('~w/~w (~w) -> ~w~n',[F,N,T,I])
2346 ),
2347 L1 is Level+1.
2348 print_ast(TExpr) :-
2349 (map_over_type_bexpr_top_down_acc(print_ast_td,TExpr,0),fail ; true).
2350
2351 % ---------------------
2352
2353 :- dynamic count_id_usage/2.
2354 single_usage_id_count(Expr) :- uses_an_identifier(Expr,Id),
2355 retract(count_id_usage(Id,Count)),
2356 !,
2357 Count=0,
2358 C1 is Count+1,
2359 assert(count_id_usage(Id,C1)).
2360 single_usage_id_count(_).
2361
2362 % check if an identifier is used at most once
2363 single_usage_identifier(ID,ExprOrPredicate,Count) :-
2364 retractall(count_id_usage(_,_)),
2365 assert(count_id_usage(ID,0)),
2366 % TO DO: take care of naming; do not count occurences when we enter scope defining ID
2367 map_over_full_bexpr_no_fail(single_usage_id_count,ExprOrPredicate),
2368 retract(count_id_usage(ID,Count)).
2369