]>
Commit | Line | Data |
---|---|---|
361091cc | 1 | /* |
754746a0 | 2 | * |
361091cc | 3 | ** constraintResolve.c |
4 | */ | |
5 | ||
6 | # include <ctype.h> /* for isdigit */ | |
7 | # include "lclintMacros.nf" | |
8 | # include "basic.h" | |
9 | # include "cgrammar.h" | |
10 | # include "cgrammar_tokens.h" | |
11 | ||
12 | # include "exprChecks.h" | |
13 | # include "aliasChecks.h" | |
14 | # include "exprNodeSList.h" | |
15 | # include "exprData.i" | |
16 | ||
92c4a786 | 17 | #include "constraintExpr.h" |
361091cc | 18 | |
92c4a786 | 19 | constraintList reflectChanges (constraintList pre2, constraintList post1); |
20 | constraint substitute (constraint c, constraintList p); | |
21 | constraint constraint_searchandreplace (constraint c, constraintExpr old, constraintExpr new); | |
22 | bool rangeCheck (arithType ar1, constraintExpr expr1, arithType ar2, constraintExpr expr2); | |
23 | bool satifies (constraint pre, constraint post); | |
24 | bool resolve (constraint c, constraintList p); | |
25 | constraintList reflectChangesEnsures (constraintList pre2, constraintList post1); | |
26 | constraint constraint_simplify (constraint c); | |
361091cc | 27 | |
754746a0 | 28 | constraintList constraintList_fixConflicts (constraintList list1, constraintList list2); |
29 | ||
30 | constraintList constraintList_subsumeEnsures (constraintList list1, constraintList list2); | |
31 | ||
32 | constraintList constraintList_mergeEnsures (constraintList list1, constraintList list2); | |
33 | ||
34 | ||
35 | /*********************************************/ | |
36 | ||
37 | ||
38 | constraintList constraintList_mergeEnsures (constraintList list1, constraintList list2) | |
39 | { | |
40 | constraintList ret; | |
41 | constraintList temp; | |
42 | ret = constraintList_new(); | |
43 | ||
44 | ret = reflectChangesEnsures (list1, list2); | |
45 | ret = constraintList_fixConflicts (ret, list2); | |
46 | ret = constraintList_subsumeEnsures (ret, list2); | |
47 | list2 = constraintList_subsumeEnsures (list2, ret); | |
48 | temp = constraintList_copy(list2); | |
49 | ||
50 | temp = constraintList_addList (temp, ret); | |
51 | return temp; | |
52 | //ret = constraintList_addList (ret, list2); | |
53 | //return ret; | |
54 | } | |
55 | ||
92c4a786 | 56 | void mergeResolve (exprNode parent, exprNode child1, exprNode child2) |
361091cc | 57 | { |
92c4a786 | 58 | constraintList temp; |
754746a0 | 59 | |
60 | TPRINTF( (message ("magically merging constraint into parent:%s for", exprNode_unparse (parent) ))); | |
61 | ||
62 | TPRINTF( (message (" children: %s and %s", exprNode_unparse (child1), exprNode_unparse(child2) ) ) ); | |
63 | ||
64 | if (exprNode_isError (child1) || exprNode_isError(child2) ) | |
92c4a786 | 65 | { |
66 | if (exprNode_isError (child1) && !exprNode_isError(child2) ) | |
67 | { | |
68 | parent->requiresConstraints = constraintList_copy (child2->requiresConstraints); | |
69 | parent->ensuresConstraints = constraintList_copy (child2->ensuresConstraints); | |
70 | TPRINTF((message ("Copied child constraints: pre: %s and post: %s", | |
71 | constraintList_print( child2->requiresConstraints), | |
72 | constraintList_print (child2->ensuresConstraints) | |
73 | ) | |
74 | )); | |
75 | return; | |
76 | } | |
77 | else | |
78 | { | |
79 | llassert(exprNode_isError(child2) ); | |
80 | parent->requiresConstraints = constraintList_new(); | |
81 | parent->ensuresConstraints = constraintList_new(); | |
82 | return; | |
83 | } | |
84 | } | |
361091cc | 85 | |
92c4a786 | 86 | llassert(!exprNode_isError (child1) && ! exprNode_isError(child2) ); |
87 | ||
88 | TPRINTF( (message ("Child constraints are %s %s and %s %s", | |
89 | constraintList_print (child1->requiresConstraints), | |
90 | constraintList_print (child1->ensuresConstraints), | |
91 | constraintList_print (child2->requiresConstraints), | |
92 | constraintList_print (child2->ensuresConstraints) | |
93 | ) ) ); | |
94 | ||
95 | parent->requiresConstraints = constraintList_new(); | |
96 | parent->ensuresConstraints = constraintList_new(); | |
361091cc | 97 | |
92c4a786 | 98 | parent->requiresConstraints = constraintList_copy (child1->requiresConstraints); |
99 | ||
100 | temp = reflectChanges (child2->requiresConstraints, child1->ensuresConstraints); | |
101 | parent->requiresConstraints = constraintList_addList (parent->requiresConstraints, temp); | |
361091cc | 102 | |
754746a0 | 103 | parent->ensuresConstraints = constraintList_mergeEnsures(child1->ensuresConstraints, |
104 | child2->ensuresConstraints); | |
92c4a786 | 105 | |
106 | TPRINTF( (message ("Parent constraints are %s and %s ", | |
107 | constraintList_print (parent->requiresConstraints), | |
108 | constraintList_print (parent->ensuresConstraints) | |
109 | ) ) ); | |
110 | ||
361091cc | 111 | } |
112 | ||
361091cc | 113 | |
92c4a786 | 114 | |
754746a0 | 115 | |
116 | constraintList constraintList_subsumeEnsures (constraintList list1, constraintList list2) | |
117 | { | |
118 | constraintList ret; | |
119 | ret = constraintList_new(); | |
120 | constraintList_elements (list1, el) | |
121 | { | |
122 | ||
123 | TPRINTF ((message ("Examining %s", constraint_print (el) ) ) ); | |
124 | if (!resolve (el, list2) ) | |
125 | { | |
126 | ret = constraintList_add (ret, el); | |
127 | } | |
128 | else | |
129 | { | |
130 | TPRINTF ( (message ("Subsuming %s", constraint_print (el) ) ) ); | |
131 | } | |
132 | } end_constraintList_elements; | |
133 | ||
134 | return ret; | |
135 | } | |
136 | ||
137 | ||
92c4a786 | 138 | constraintList reflectChanges (constraintList pre2, constraintList post1) |
139 | { | |
140 | ||
141 | constraintList ret; | |
142 | constraint temp; | |
143 | ret = constraintList_new(); | |
144 | constraintList_elements (pre2, el) | |
361091cc | 145 | { |
92c4a786 | 146 | if (!resolve (el, post1) ) |
147 | { | |
148 | temp = substitute (el, post1); | |
754746a0 | 149 | if (!resolve (temp, post1) ) |
150 | ret = constraintList_add (ret, temp); | |
92c4a786 | 151 | } |
152 | } end_constraintList_elements; | |
361091cc | 153 | |
92c4a786 | 154 | return ret; |
361091cc | 155 | } |
156 | ||
361091cc | 157 | |
361091cc | 158 | |
92c4a786 | 159 | constraintList reflectChangesEnsures (constraintList pre2, constraintList post1) |
160 | { | |
161 | constraintList ret; | |
162 | constraint temp; | |
163 | ret = constraintList_new(); | |
164 | constraintList_elements (pre2, el) | |
361091cc | 165 | { |
92c4a786 | 166 | if (!resolve (el, post1) ) |
167 | { | |
168 | temp = substitute (el, post1); | |
754746a0 | 169 | llassert (temp != NULL); |
170 | ||
171 | if (!resolve (temp, post1) ) | |
92c4a786 | 172 | ret = constraintList_add (ret, temp); |
173 | } | |
754746a0 | 174 | else |
175 | { | |
176 | TPRINTF ( (message ("Resolved away %s ", constraint_print(el) ) ) ); | |
177 | } | |
92c4a786 | 178 | } end_constraintList_elements; |
bf92e32c | 179 | |
92c4a786 | 180 | return ret; |
361091cc | 181 | } |
182 | ||
92c4a786 | 183 | |
184 | bool constraint_conflict (constraint c1, constraint c2) | |
361091cc | 185 | { |
186 | ||
92c4a786 | 187 | if (constraintExpr_similar(c1->lexpr, c2->lexpr) ) |
bf92e32c | 188 | { |
754746a0 | 189 | if (c1->ar == EQ) |
190 | if (c1->ar == c2->ar) | |
191 | { | |
192 | TPRINTF ( (message ("%s conflicts with %s ", constraint_print (c1), constraint_print(c2) ) ) ); | |
193 | return TRUE; | |
194 | } | |
92c4a786 | 195 | } |
bf92e32c | 196 | |
754746a0 | 197 | DPRINTF ( (message ("%s doesn't conflict with %s ", constraint_print (c1), constraint_print(c2) ) ) ); |
361091cc | 198 | |
92c4a786 | 199 | return FALSE; |
361091cc | 200 | |
361091cc | 201 | } |
202 | ||
92c4a786 | 203 | void constraint_fixConflict (constraint good, constraint conflicting) |
361091cc | 204 | { |
92c4a786 | 205 | constraint temp; |
206 | if (conflicting->ar ==EQ ) | |
361091cc | 207 | { |
92c4a786 | 208 | good->expr = constraintExpr_searchandreplace (good->expr, conflicting->lexpr, conflicting->expr); |
209 | temp = constraint_simplify (good); | |
210 | constraint_overWrite (good, temp); | |
361091cc | 211 | } |
212 | ||
361091cc | 213 | |
361091cc | 214 | } |
215 | ||
92c4a786 | 216 | bool conflict (constraint c, constraintList list) |
361091cc | 217 | { |
361091cc | 218 | |
92c4a786 | 219 | constraintList_elements (list, el) |
220 | { | |
221 | if ( constraint_conflict(el, c) ) | |
222 | { | |
223 | constraint_fixConflict (el, c); | |
224 | return TRUE; | |
225 | } | |
226 | } end_constraintList_elements; | |
361091cc | 227 | |
92c4a786 | 228 | return FALSE; |
229 | ||
361091cc | 230 | |
361091cc | 231 | } |
232 | ||
92c4a786 | 233 | //check if constraint in list1 and conflict with constraints in List2. If so we |
234 | //remove form list1 and (optionally) change list2. | |
235 | constraintList constraintList_fixConflicts (constraintList list1, constraintList list2) | |
6364363c | 236 | { |
92c4a786 | 237 | constraintList ret; |
238 | ret = constraintList_new(); | |
239 | constraintList_elements (list1, el) | |
240 | { | |
241 | if (! conflict (el, list2) ) | |
242 | { | |
243 | ret = constraintList_add (ret, el); | |
244 | } | |
245 | } end_constraintList_elements; | |
6364363c | 246 | |
92c4a786 | 247 | return ret; |
248 | ||
249 | ||
361091cc | 250 | } |
251 | ||
252 | bool resolve (constraint c, constraintList p) | |
253 | { | |
254 | constraintList_elements (p, el) | |
255 | { | |
256 | if ( satifies (c, el) ) | |
257 | { | |
92c4a786 | 258 | TPRINTF ( (message ("\n%s Satifies %s\n ", constraint_print(el), constraint_print(c) ) ) ); |
361091cc | 259 | return TRUE; |
260 | } | |
261 | } | |
262 | end_constraintList_elements; | |
754746a0 | 263 | DPRINTF ( (message ("no constraints satify %s", constraint_print(c) ) )); |
361091cc | 264 | return FALSE; |
265 | } | |
266 | ||
bf92e32c | 267 | |
92c4a786 | 268 | /*returns true if cosntraint post satifies cosntriant pre */ |
269 | bool satifies (constraint pre, constraint post) | |
bf92e32c | 270 | { |
92c4a786 | 271 | if (!constraintExpr_similar (pre->lexpr, post->lexpr) ) |
bf92e32c | 272 | { |
92c4a786 | 273 | return FALSE; |
274 | } | |
275 | if (post->expr == NULL) | |
276 | { | |
277 | llassert(FALSE); | |
278 | return FALSE; | |
bf92e32c | 279 | } |
92c4a786 | 280 | |
281 | return rangeCheck (pre->ar, pre->expr, post->ar, post->expr); | |
bf92e32c | 282 | } |
283 | ||
754746a0 | 284 | bool arithType_canResolve (arithType ar1, arithType ar2) |
285 | { | |
286 | switch (ar1) | |
287 | { | |
288 | case GTE: | |
289 | case GT: | |
290 | if ( (ar2 == GT) || (ar2 == GTE) || (ar2 == EQ) ) | |
291 | { | |
292 | return TRUE; | |
293 | } | |
294 | break; | |
295 | ||
296 | case EQ: | |
297 | if (ar2 == EQ) | |
298 | return TRUE; | |
299 | break; | |
300 | ||
301 | case LT: | |
302 | case LTE: | |
303 | llassert(FALSE); | |
304 | if ( (ar2 == LT) || (ar2 == LTE) || (ar2 == EQ) ) | |
305 | return TRUE; | |
306 | } | |
307 | return FALSE; | |
308 | } | |
92c4a786 | 309 | |
310 | bool rangeCheck (arithType ar1, constraintExpr expr1, arithType ar2, constraintExpr expr2) | |
311 | ||
bf92e32c | 312 | { |
754746a0 | 313 | DPRINTF ((message ("Doing Range CHECK %s and %s", constraintExpr_unparse(expr1), constraintExpr_unparse(expr2) ) )); |
314 | ||
315 | if (! arithType_canResolve (ar1, ar2) ) | |
316 | return FALSE; | |
317 | ||
92c4a786 | 318 | switch (ar1) |
319 | { | |
320 | case GTE: | |
321 | case GT: | |
754746a0 | 322 | if (! (constraintExpr_canGetValue (expr1) && |
323 | constraintExpr_canGetValue (expr2) ) ) | |
324 | { | |
325 | DPRINTF( ("Can't Get value")); | |
326 | return FALSE; | |
327 | } | |
328 | ||
329 | if (constraintExpr_compare (expr2, expr1) >= 0) | |
330 | return TRUE; | |
331 | ||
332 | return FALSE; | |
333 | case EQ: | |
334 | if (constraintExpr_similar (expr1, expr2) ) | |
335 | return TRUE; | |
336 | ||
337 | return FALSE; | |
338 | ||
92c4a786 | 339 | default: |
754746a0 | 340 | DPRINTF(("case not handled")); |
92c4a786 | 341 | } |
342 | return FALSE; | |
343 | } | |
bf92e32c | 344 | |
754746a0 | 345 | |
92c4a786 | 346 | constraint constraint_searchandreplace (constraint c, constraintExpr old, constraintExpr new) |
347 | { | |
754746a0 | 348 | DPRINTF (("Doing replace for lexpr") ); |
92c4a786 | 349 | c->lexpr = constraintExpr_searchandreplace (c->lexpr, old, new); |
754746a0 | 350 | DPRINTF (("Doing replace for expr") ); |
92c4a786 | 351 | c->expr = constraintExpr_searchandreplace (c->expr, old, new); |
352 | return c; | |
bf92e32c | 353 | } |
6364363c | 354 | |
754746a0 | 355 | bool constraint_search (constraint c, constraintExpr old) |
356 | { | |
357 | bool ret; | |
358 | ret = FALSE; | |
359 | ||
360 | ret = constraintExpr_search (c->lexpr, old); | |
361 | ret = ret || constraintExpr_search (c->expr, old); | |
362 | return ret; | |
363 | } | |
364 | ||
6364363c | 365 | |
92c4a786 | 366 | constraint constraint_adjust (constraint substitute, constraint old) |
bf92e32c | 367 | { |
92c4a786 | 368 | fileloc loc1, loc2, loc3; |
6364363c | 369 | |
754746a0 | 370 | DPRINTF ( (message("Start adjust on %s and %s", constraint_print(substitute), |
371 | constraint_print(old)) | |
372 | )); | |
373 | ||
92c4a786 | 374 | loc1 = constraint_getFileloc (old); |
6364363c | 375 | |
92c4a786 | 376 | loc2 = constraintExpr_getFileloc (substitute->lexpr); |
6364363c | 377 | |
92c4a786 | 378 | loc3 = constraintExpr_getFileloc (substitute->expr); |
6364363c | 379 | |
754746a0 | 380 | |
381 | // special case of an equality that "contains itself" | |
382 | if (constraintExpr_search (substitute->expr, substitute->lexpr) ) | |
383 | if (fileloc_closer (loc1, loc3, loc2)) | |
6364363c | 384 | { |
92c4a786 | 385 | constraintExpr temp; |
754746a0 | 386 | DPRINTF ( (message("Doing adjust on %s", constraint_print(substitute) ) |
387 | )); | |
92c4a786 | 388 | temp = substitute->lexpr; |
389 | substitute->lexpr = substitute->expr; | |
390 | substitute->expr = temp; | |
391 | substitute = constraint_simplify(substitute); | |
6364363c | 392 | } |
393 | ||
92c4a786 | 394 | return substitute; |
395 | ||
bf92e32c | 396 | } |
397 | ||
361091cc | 398 | constraint substitute (constraint c, constraintList p) |
399 | { | |
400 | constraintList_elements (p, el) | |
401 | { | |
92c4a786 | 402 | if ( el->ar == EQ) |
403 | if (!constraint_conflict (c, el) ) | |
404 | ||
405 | { | |
92c4a786 | 406 | constraint temp; |
407 | temp = constraint_copy(el); | |
408 | ||
409 | temp = constraint_adjust(temp, c); | |
754746a0 | 410 | |
411 | DPRINTF((message ("Substituting %s for %s", | |
412 | constraint_print (temp), constraint_print (c) | |
413 | ) ) ); | |
414 | ||
92c4a786 | 415 | |
754746a0 | 416 | c = constraint_searchandreplace (c, temp->lexpr, temp->expr); |
92c4a786 | 417 | } |
361091cc | 418 | } |
419 | end_constraintList_elements; | |
420 | ||
421 | c = constraint_simplify(c); | |
422 | return c; | |
423 | } | |
424 | ||
361091cc | 425 | |
92c4a786 | 426 | constraint constraint_solve (constraint c) |
6364363c | 427 | { |
754746a0 | 428 | DPRINTF( (message ("Solving %s\n", constraint_print(c) ) ) ); |
92c4a786 | 429 | c->expr = constraintExpr_solveBinaryExpr (c->lexpr, c->expr); |
754746a0 | 430 | DPRINTF( (message ("Solved and got %s\n", constraint_print(c) ) ) ); |
361091cc | 431 | |
92c4a786 | 432 | return c; |
361091cc | 433 | } |
434 | ||
361091cc | 435 | |
92c4a786 | 436 | constraint constraint_simplify (constraint c) |
361091cc | 437 | { |
92c4a786 | 438 | c->lexpr = constraintExpr_simplify (c->lexpr); |
439 | c->expr = constraintExpr_simplify (c->expr); | |
361091cc | 440 | |
92c4a786 | 441 | c = constraint_solve (c); |
754746a0 | 442 | |
92c4a786 | 443 | c->lexpr = constraintExpr_simplify (c->lexpr); |
444 | c->expr = constraintExpr_simplify (c->expr); | |
754746a0 | 445 | |
361091cc | 446 | return c; |
447 | } | |
448 | ||
449 | ||
361091cc | 450 | |
361091cc | 451 | |
92c4a786 | 452 | /* returns true if fileloc for term1 is closer to file for term2 than term3*/ |
453 | ||
454 | bool fileloc_closer (fileloc loc1, fileloc loc2, fileloc loc3) | |
361091cc | 455 | { |
92c4a786 | 456 | if ( fileloc_lessthan (loc1, loc2) ) |
6364363c | 457 | { |
92c4a786 | 458 | if (fileloc_lessthan (loc2, loc3) ) |
6364363c | 459 | { |
92c4a786 | 460 | llassert (fileloc_lessthan (loc1, loc3) ); |
461 | return TRUE; | |
6364363c | 462 | } |
463 | else | |
464 | { | |
92c4a786 | 465 | return FALSE; |
6364363c | 466 | } |
467 | } | |
468 | ||
92c4a786 | 469 | if ( !fileloc_lessthan (loc1, loc2) ) |
470 | { | |
471 | if (!fileloc_lessthan (loc2, loc3) ) | |
472 | { | |
473 | llassert (!fileloc_lessthan (loc1, loc3) ); | |
474 | return TRUE; | |
475 | } | |
476 | else | |
477 | { | |
478 | return FALSE; | |
479 | } | |
480 | } | |
361091cc | 481 | |
92c4a786 | 482 | llassert(FALSE); |
483 | return FALSE; | |
361091cc | 484 | } |
485 | ||
754746a0 | 486 |