]> andersk Git - splint.git/blame - src/constraintResolve.c
pre addition of functino level annotations.
[splint.git] / src / constraintResolve.c
CommitLineData
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 19constraintList reflectChanges (constraintList pre2, constraintList post1);
20constraint substitute (constraint c, constraintList p);
21constraint constraint_searchandreplace (constraint c, constraintExpr old, constraintExpr new);
22bool rangeCheck (arithType ar1, constraintExpr expr1, arithType ar2, constraintExpr expr2);
23bool satifies (constraint pre, constraint post);
24bool resolve (constraint c, constraintList p);
25constraintList reflectChangesEnsures (constraintList pre2, constraintList post1);
26constraint constraint_simplify (constraint c);
361091cc 27
754746a0 28constraintList constraintList_fixConflicts (constraintList list1, constraintList list2);
29
30constraintList constraintList_subsumeEnsures (constraintList list1, constraintList list2);
31
32constraintList constraintList_mergeEnsures (constraintList list1, constraintList list2);
33
34
35/*********************************************/
36
37
38constraintList 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 56void 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
116constraintList 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 138constraintList 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 159constraintList 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
184bool 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 203void 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 216bool 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.
235constraintList 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
252bool 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 */
269bool 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 284bool 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
310bool 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 346constraint 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 355bool 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 366constraint 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 398constraint 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 426constraint 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 436constraint 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
454bool 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
This page took 0.130099 seconds and 5 git commands to generate.