1 | | % (c) 2020-2024 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(well_def_tools, [rename_norm_term/3, member_in_norm_conjunction/2, not_occurs/2, occurs/2]). |
6 | | |
7 | | :- use_module(probsrc(module_information),[module_info/2]). |
8 | | :- module_info(group,well_def_prover). |
9 | | :- module_info(description,'This module provides utilities for the WD prover.'). |
10 | | |
11 | | |
12 | | :- use_module(probsrc(debug)). |
13 | | % -------------------- |
14 | | % tools for normalized expressions: |
15 | | |
16 | | % check if a known/bound ID occurs in a normalized expression |
17 | ? | not_occurs(Expr,ID) :- (occurs(Expr,ID) -> debug_println(19,occurs_in(ID,Expr)),fail ; true). |
18 | | occurs('$'(ID1),ID2) :- !, ID1 = ID2. |
19 | | occurs(conjunct(A,B),ID) :- !, (occurs(A,ID) ; occurs(B,ID)). |
20 | | occurs(couple(A,B),ID) :- !, (occurs(A,ID) ; occurs(B,ID)). |
21 | | occurs(equal(A,B),ID) :- !, (occurs(A,ID) ; occurs(B,ID)). |
22 | | occurs(field(_,A),ID) :- !, occurs(A,ID). |
23 | | occurs(function(A,B),ID) :- !, (occurs(A,ID) ; occurs(B,ID)). |
24 | | occurs(interval(A,B),ID) :- !, (occurs(A,ID) ; occurs(B,ID)). |
25 | | occurs(member(A,B),ID) :- !, (occurs(A,ID) ; occurs(B,ID)). |
26 | | occurs(record_field(A,B),ID) :- !, (occurs(A,ID) ; occurs(B,ID)). |
27 | | occurs(value(_),_ID) :- !, fail. |
28 | | occurs(string(_),_ID) :- !, fail. |
29 | | occurs(reverse(A),ID) :- !, occurs(A,ID). |
30 | | occurs(domain(A),ID) :- !, occurs(A,ID). |
31 | | occurs(range(A),ID) :- !, occurs(A,ID). |
32 | | occurs(comprehension_set(Paras,Body),ID) :- !, |
33 | | (member('$'(ID),Paras) -> fail % ID becomes invisible |
34 | ? | ; occurs(Body,ID)). |
35 | | % TO DO: treat other bound IDs exists,... [but not crucial, as we err on the safe side here] |
36 | ? | occurs([H|T],ID) :- !, (occurs(H,ID) -> true ; occurs(T,ID)). |
37 | | occurs(boolean_true,_) :- !,fail. |
38 | | occurs(boolean_false,_) :- !,fail. |
39 | | occurs(empty_set,_) :- !,fail. |
40 | ? | occurs(Expr,ID) :- Expr =.. [_|Args], member(A,Args), occurs(A,ID). |
41 | | |
42 | | member_in_norm_conjunction(Pred,Pred). |
43 | | member_in_norm_conjunction(conjunct(A,B),Pred) :- |
44 | ? | member_in_norm_conjunction(A,Pred) ; member_in_norm_conjunction(B,Pred). |
45 | | |
46 | | |
47 | | :- use_module(library(lists),[exclude/3]). |
48 | | |
49 | | % apply a substitution to a normalised term: |
50 | | rename_norm_term('$'(X),Subst,Res) :- !, |
51 | ? | (member(rename(X,NewTerm),Subst) % TODO : use ord_member |
52 | | -> Res=NewTerm |
53 | | ; Res='$'(X)). |
54 | | rename_norm_term(conjunct(A,B),Subst,conjunct(SA,SB)) :- !, |
55 | | rename_norm_term(A,Subst,SA), rename_norm_term(B,Subst,SB). |
56 | | rename_norm_term(if_then_else(A,B,C),Subst,if_then_else(SA,SB,SC)) :- !, |
57 | | rename_norm_term(A,Subst,SA), rename_norm_term(B,Subst,SB), rename_norm_term(C,Subst,SC). |
58 | | rename_norm_term(equal(A,B),Subst,equal(SA,SB)) :- !, |
59 | | rename_norm_term(A,Subst,SA), rename_norm_term(B,Subst,SB). |
60 | | rename_norm_term(function(A,B),Subst,function(SA,SB)) :- !, |
61 | | rename_norm_term(A,Subst,SA), rename_norm_term(B,Subst,SB). |
62 | | rename_norm_term(field(F,B),Subst,field(F,SB)) :- !, |
63 | | rename_norm_term(B,Subst,SB). |
64 | | rename_norm_term(record_field(Rec,FieldName),Subst,record_field(Rec,FieldName)) :- !, |
65 | | rename_norm_term(Rec,Subst,Rec). |
66 | | rename_norm_term(member(A,B),Subst,member(SA,SB)) :- !, |
67 | | rename_norm_term(A,Subst,SA), rename_norm_term(B,Subst,SB). |
68 | | rename_norm_term(rec(F),Subst,rec(SF)) :- !, |
69 | | l_rename_norm_terms(F,Subst,SF). |
70 | ? | rename_norm_term(Nr,_,Res) :- simple_norm_term(Nr),!,Res=Nr. |
71 | | rename_norm_term(QOP,Subst,RQOP) :- |
72 | | quantified_op(QOP,Functor,Ids,Exprs,Bodies),!, |
73 | | l_rename_norm_terms(Exprs,Subst,RExprs), |
74 | | sort(Ids,SIds), |
75 | | % TO DO: also ensure Subst is sorted and use linear algo |
76 | | exclude(clash_with_new(SIds),Subst,NSubst), |
77 | | %print(clashing(SIds,Subst,NSubst,Bodies)),nl, |
78 | | l_rename_norm_terms(Bodies,NSubst,RBodies), |
79 | | quantified_op(RQOP,Functor,Ids,RExprs,RBodies). |
80 | | rename_norm_term(Term,Subst,RenTerm) :- functor(Term,BOP,2), bin_op(BOP),!, |
81 | | functor(RenTerm,BOP,2), |
82 | | arg(1,Term,A), arg(1,RenTerm,RA), rename_norm_term(A,Subst,RA), |
83 | | arg(2,Term,B), arg(2,RenTerm,RB), rename_norm_term(B,Subst,RB). |
84 | | rename_norm_term(Term,Subst,RenTerm) :- functor(Term,UOP,1), un_op(UOP),!, |
85 | | functor(RenTerm,UOP,1), |
86 | ? | arg(1,Term,A), arg(1,RenTerm,RA), rename_norm_term(A,Subst,RA). |
87 | | rename_norm_term(Term,Subst,RenTerm) :- list_op(Term,Kind,List),!, |
88 | ? | list_op(RenTerm,Kind,RList), |
89 | | l_rename_norm_terms(List,Subst,RList). |
90 | | rename_norm_term(A,_,_) :- print(uncovered_renaming(A)),nl,fail. |
91 | | |
92 | | % uncovered_renaming(external_function_call(STRING_CODES,[$(s)])) |
93 | | |
94 | | :- use_module(library(ordsets),[ord_member/2]). |
95 | | clash_with_new(SortedIDs,rename(ID,_)) :- ord_member($(ID),SortedIDs). |
96 | | |
97 | | l_rename_norm_terms([],_,[]). |
98 | | l_rename_norm_terms([H|T],Subst,[RH|RT]) :- |
99 | | rename_norm_term(H,Subst,RH),!, |
100 | | l_rename_norm_terms(T,Subst,RT). |
101 | | |
102 | | |
103 | | list_op(set_extension(L),set_extension,L). |
104 | | list_op(sequence_extension(L),sequence_extension,L). |
105 | | list_op(external_function_call(Name,Args),external_function_call(Name),Args). |
106 | | |
107 | | % quantified_op(Term, ListOfDollarIDs, ListOfExprsOutsideOfScope, ListExpressionInNewScope) |
108 | | quantified_op(comprehension_set(IDS,Body),comprehension_set,IDS,[],[Body]). |
109 | | quantified_op(exists(IDS,Body),exists,IDS,[],[Body]). |
110 | | quantified_op(forall(IDS,LHS,RHS),forall,IDS,[],[LHS,RHS]). |
111 | | quantified_op(let_expression(IDS,Exprs,Body),let_expression,IDS,Exprs,[Body]). |
112 | | quantified_op(let_predicate(IDS,Exprs,Body),let_predicate,IDS,Exprs,[Body]). |
113 | | quantified_op(general_product(IDS,P,E),general_product,IDS,[],[P,E]). |
114 | | quantified_op(general_sum(IDS,P,E),general_sum,IDS,[],[P,E]). |
115 | | % lazy_let_pred, ... |
116 | | |
117 | | |
118 | | % TO DO: add more bin and unary ops; records, quantified operators |
119 | | bin_op(add). |
120 | | bin_op(add_real). |
121 | | bin_op(card). |
122 | | bin_op(cartesian_product). |
123 | | bin_op(composition). |
124 | | bin_op(concat). |
125 | | bin_op(couple). |
126 | | bin_op(div). |
127 | | bin_op(div_real). |
128 | | bin_op(disjunct). |
129 | | bin_op(domain_restriction). |
130 | | bin_op(domain_subtraction). |
131 | | bin_op(equivalence). |
132 | | bin_op(greater). |
133 | | bin_op(greater_equal). |
134 | | bin_op(floored_div). |
135 | | bin_op(function). |
136 | | bin_op(image). |
137 | | bin_op(implication). |
138 | | bin_op(insert_front). |
139 | | bin_op(insert_tail). |
140 | | bin_op(intersection). |
141 | | bin_op(interval). |
142 | | bin_op(iteration). |
143 | | bin_op(less). |
144 | | bin_op(less_equal). |
145 | | bin_op(less_real). |
146 | | bin_op(less_equal_real). |
147 | | bin_op(minus). |
148 | | bin_op(minus_real). |
149 | | bin_op(modulo). |
150 | | bin_op(multiplication). |
151 | | bin_op(multiplication_real). |
152 | | bin_op(overwrite). |
153 | | bin_op(not_equal). |
154 | | bin_op(not_member). |
155 | | bin_op(partial_bijection). |
156 | | bin_op(partial_function). |
157 | | bin_op(partial_injection). |
158 | | bin_op(partial_surjection). |
159 | | bin_op(power_of). |
160 | | bin_op(power_of_real). |
161 | | bin_op(range_restriction). |
162 | | bin_op(range_subtraction). |
163 | | bin_op(relations). |
164 | | bin_op(restrict_front). |
165 | | bin_op(restrict_tail). |
166 | | bin_op(set_subtraction). |
167 | | bin_op(size). |
168 | | bin_op(subset). |
169 | | bin_op(subset_strict). |
170 | | bin_op(surjection_relation). |
171 | | bin_op(total_function). |
172 | | bin_op(total_injection). |
173 | | bin_op(total_surjection). |
174 | | bin_op(total_relation). |
175 | | bin_op(total_surjection_relation). |
176 | | bin_op(union). |
177 | | |
178 | | un_op(bag_items). |
179 | | un_op(card). |
180 | | un_op(closure). % closure1 |
181 | | un_op(compaction). |
182 | | un_op(convert_bool). |
183 | | un_op(convert_real). |
184 | | un_op(convert_int_floor). |
185 | | un_op(convert_int_ceiling). |
186 | | un_op(domain). |
187 | | un_op(finite). |
188 | | un_op(fin_subset). |
189 | | un_op(fin1_subset). |
190 | | un_op(first_of_pair). |
191 | | un_op(front). |
192 | | un_op(identity). |
193 | | un_op(iseq). |
194 | | un_op(iseq1). |
195 | | un_op(last). |
196 | | un_op(negation). |
197 | | un_op(max). |
198 | | un_op(max_real). |
199 | | un_op(min). |
200 | | un_op(min_real). |
201 | | un_op(mu). |
202 | | un_op(perm). |
203 | | un_op(pow_subset). |
204 | | un_op(pow1_subset). |
205 | | un_op(range). |
206 | | un_op(rev). |
207 | | un_op(reverse). |
208 | | un_op(reflexive_closure). |
209 | | un_op(second_of_pair). |
210 | | un_op(seq). |
211 | | un_op(seq1). |
212 | | un_op(size). |
213 | | un_op(tail). |
214 | | un_op(unary_minus). |
215 | | un_op(unary_minus_real). |
216 | | |
217 | | % do not require renaming: |
218 | | simple_norm_term(truth). |
219 | | simple_norm_term(boolean_true). |
220 | | simple_norm_term(boolean_false). |
221 | | simple_norm_term(bool_set). |
222 | | simple_norm_term(float_set). |
223 | | simple_norm_term(real_set). |
224 | | simple_norm_term(string_set). |
225 | | simple_norm_term(typeset). |
226 | | simple_norm_term(value(_)). |
227 | | simple_norm_term(string(_)). |
228 | | simple_norm_term(empty_set). |
229 | | simple_norm_term(empty_sequence). |
230 | | simple_norm_term(max_int). |
231 | | simple_norm_term(min_int). |
232 | | simple_norm_term('NATURAL'). |
233 | | simple_norm_term('NATURAL1'). |
234 | | simple_norm_term(lazy_lookup_pred(_)). |
235 | | simple_norm_term(lazy_lookup_expr(_)). |
236 | | simple_norm_term(Nr) :- number(Nr). |