00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 # include "lclintMacros.nf"
00035 # include "llbasic.h"
00036 # include "llgrammar.h"
00037 # include "checking.h"
00038 # include "lclscan.h"
00039
00040
00041
00042 static cstring printBadArgs (sortSetList p_args);
00043 static sortSet
00044 standardOperators ( nameNode p_n, sortSetList p_argSorts, sort p_qual);
00045 static bool isStandardOperator ( nameNode p_n);
00046 static void assignSorts (termNode p_t, sort p_s);
00047
00048 termNode
00049 computePossibleSorts ( termNode t)
00050 {
00051 ltoken errtok;
00052
00053 if (t != (termNode) 0)
00054 {
00055 switch (t->kind)
00056 {
00057 case TRM_LITERAL:
00058 case TRM_CONST:
00059 case TRM_VAR:
00060 case TRM_ZEROARY:
00061 case TRM_SIZEOF:
00062 case TRM_UNCHANGEDALL:
00063 case TRM_UNCHANGEDOTHERS:
00064 case TRM_QUANTIFIER:
00065 break;
00066 case TRM_APPLICATION:
00067 {
00068 bool fail = FALSE;
00069 sortSetList argSorts = sortSetList_new ();
00070 lslOpSet ops;
00071 sortSet standards;
00072
00073 if (termNodeList_size (t->args) != 0)
00074 {
00075 termNodeList_elements (t->args, arg)
00076 {
00077 (void) computePossibleSorts (arg);
00078
00079 if (sortSet_size (arg->possibleSorts) == 0)
00080 {
00081 fail = TRUE;
00082 }
00083 else
00084 {
00085 sortSetList_addh (argSorts, arg->possibleSorts);
00086 }
00087 } end_termNodeList_elements;
00088
00089 if (fail)
00090 {
00091 lslOpSet_free (t->possibleOps);
00092 sortSetList_free (argSorts);
00093 t->possibleOps = lslOpSet_new ();
00094 return t;
00095 }
00096 }
00097
00098 ops = symtable_opsWithLegalDomain (g_symtab, t->name, argSorts, t->given);
00099 lslOpSet_free (t->possibleOps);
00100 t->possibleOps = ops;
00101
00102 lslOpSet_elements (t->possibleOps, op)
00103 {
00104 sort sort;
00105 sort = sigNode_rangeSort (op->signature);
00106 (void) sortSet_insert (t->possibleSorts, sort);
00107 } end_lslOpSet_elements;
00108
00109 standards = standardOperators (t->name, argSorts, t->given);
00110
00111 sortSet_elements (standards, el)
00112 {
00113 (void) sortSet_insert (t->possibleSorts, el);
00114 } end_sortSet_elements;
00115
00116 sortSet_free (standards);
00117
00118 if (!(t->error_reported) && sortSet_size (t->possibleSorts) == 0)
00119 {
00120 unsigned int arity = termNodeList_size (t->args);
00121 errtok = nameNode_errorToken (t->name);
00122
00123
00124
00125 if (isStandardOperator (t->name))
00126 {
00127 lclerror (errtok,
00128 message ("Type error: %q not declared for %q",
00129 nameNode_unparse (t->name), printBadArgs (argSorts)));
00130 }
00131 else if (t->name != NULL
00132 && symtable_opExistsWithArity (g_symtab, t->name, arity))
00133 {
00134 sigNodeSet possibleOps = symtable_possibleOps (g_symtab, t->name);
00135 cstring opName = nameNode_unparse (t->name);
00136
00137
00138
00139
00140
00141 if (cstring_equalLit (opName, "__ [__]"))
00142 {
00143 lclerror (errtok,
00144 message ("Type error: %q not declared for %q",
00145 opName, printBadArgs (argSorts)));
00146 }
00147 else
00148 {
00149 lclerror (errtok,
00150 message ("Type error: %q declared: %q\ngiven: %q",
00151 opName,
00152 sigNodeSet_unparseSomeSigs (possibleOps),
00153 printBadArgs (argSorts)));
00154 }
00155 }
00156 else
00157 {
00158 sigNodeSet possibleOps;
00159 int npossibleOps;
00160
00161 llassert (t->name != NULL);
00162
00163 possibleOps = symtable_possibleOps (g_symtab, t->name);
00164 npossibleOps = sigNodeSet_size (possibleOps);
00165
00166
00167
00168
00169
00170 if (npossibleOps == 0)
00171 {
00172 lclerror
00173 (errtok,
00174 message ("Undeclared operator: %q", nameNode_unparse (t->name)));
00175 }
00176 else
00177 {
00178 lclerror
00179 (errtok,
00180 message ("Operator %q declared for %q arguments, given %d",
00181 nameNode_unparse (t->name),
00182 sigNodeSet_unparsePossibleAritys (possibleOps),
00183 arity));
00184 }
00185 }
00186 t->error_reported = TRUE;
00187 }
00188 sortSetList_free (argSorts);
00189 break;
00190 }
00191 }
00192 }
00193
00194 return t;
00195 }
00196
00197 static cstring
00198 printBadArgs (sortSetList args)
00199 {
00200 if (sortSetList_size (args) == 1)
00201 {
00202 return (sortSet_unparseOr (sortSetList_head (args)));
00203 }
00204 else
00205 {
00206 cstring s = cstring_undefined;
00207 int argno = 1;
00208
00209 sortSetList_elements (args, ss)
00210 {
00211 if (argno == 1)
00212 s = message ("arg %d: %q", argno, sortSet_unparseOr (ss));
00213 else
00214 s = message ("%q; arg %d: %q", s, argno, sortSet_unparseOr (ss));
00215 argno++;
00216 } end_sortSetList_elements;
00217
00218 return s;
00219 }
00220 }
00221
00222 termNode
00223 checkSort ( termNode t)
00224 {
00225 sortSet sorts;
00226 sort theSort;
00227 int size;
00228 ltoken errtok;
00229
00230 (void) computePossibleSorts (t);
00231 sorts = t->possibleSorts;
00232
00233 llassert (sortSet_isDefined (sorts));
00234
00235 size = sortSet_size (sorts);
00236 switch (size)
00237 {
00238 case 0:
00239 break;
00240 case 1:
00241 theSort = sortSet_choose (sorts);
00242 assignSorts (t, theSort);
00243 break;
00244 default:
00245
00246 if (t->kind != TRM_LITERAL)
00247 {
00248 errtok = termNode_errorToken (t);
00249 t->error_reported = TRUE;
00250
00251 lclerror (errtok,
00252 message ("Term %q: can have more than one possible type. Possible types: %q",
00253 termNode_unparse (t), sortSet_unparseClean (sorts)));
00254 }
00255 }
00256 return t;
00257 }
00258
00259 static void
00260 assignSorts (termNode t, sort s)
00261 {
00262
00263 ltoken errtok;
00264
00265 switch (t->kind)
00266 {
00267 case TRM_ZEROARY:
00268 case TRM_LITERAL:
00269 sortSet_elements (t->possibleSorts, s2)
00270 {
00271 if (sort_equal (&s2, &s))
00272 {
00273 sortSet_free (t->possibleSorts);
00274 t->possibleSorts = sortSet_new ();
00275 (void) sortSet_insert (t->possibleSorts, s);
00276 t->sort = s;
00277 }
00278 return;
00279 } end_sortSet_elements;
00280 break;
00281 case TRM_APPLICATION:
00282 {
00283 lslOpSet sigs = t->possibleOps;
00284 lslOpSet oldops = lslOpSet_undefined;
00285 sigNode op = (sigNode) 0;
00286 nameNode name = t->name;
00287 termNodeList args = t->args;
00288 bool found = FALSE;
00289
00290 errtok = nameNode_errorToken (name);
00291
00292
00293 lslOpSet_elements (sigs, sig)
00294 {
00295 sort rsort = sigNode_rangeSort (sig->signature);
00296
00297 if (sort_equal (&s, &rsort))
00298 {
00299 lslOp iop;
00300
00301 if (found)
00302 {
00303 t->error_reported = TRUE;
00304
00305 lclerror (errtok,
00306 message ("Ambiguous operator %q: %q or %q",
00307 nameNode_unparse (name),
00308 sigNode_unparse (op),
00309 sigNode_unparse (sig->signature)));
00310 return;
00311 }
00312
00313 iop = (lslOp) dmalloc (sizeof (*iop));
00314 found = TRUE;
00315 op = sig->signature;
00316
00317 oldops = t->possibleOps;
00318 t->possibleOps = lslOpSet_new ();
00319 iop->name = nameNode_copy (name);
00320 iop->signature = op;
00321 (void) lslOpSet_insert (t->possibleOps, iop);
00322 t->sort = s;
00323
00324 }
00325
00326 } end_lslOpSet_elements;
00327
00328 lslOpSet_free (oldops);
00329
00330 if (!found)
00331 {
00332 if (sortSet_size (t->possibleSorts) == 1)
00333 {
00334 t->sort = sortSet_choose (t->possibleSorts);
00335 }
00336 else
00337 {
00338
00339 t->error_reported = TRUE;
00340
00341 lclerror (errtok, message ("Operator not found: %q",
00342 nameNode_unparse (name)));
00343
00344 }
00345 return;
00346 }
00347
00348 if (termNodeList_empty (args))
00349 {
00350 if (op != (sigNode) 0)
00351 {
00352
00353
00354 sortList dom = sigNode_domain (op);
00355
00356 sortList_reset (dom);
00357 termNodeList_elements (args, arg)
00358 {
00359 assignSorts (arg, sortList_current (dom));
00360 sortList_advance (dom);
00361 } end_termNodeList_elements;
00362
00363 sortList_free (dom);
00364 }
00365 else
00366 {
00367 errtok = nameNode_errorToken (name);
00368
00369 t->error_reported = TRUE;
00370
00371 lclerror (errtok, message ("No matching operator: %q",
00372 nameNode_unparse (name)));
00373 }
00374 return;
00375 }
00376 break;
00377 }
00378 default:
00379 break;
00380 }
00381 }
00382
00383 void
00384 checkLclPredicate (ltoken t, lclPredicateNode n)
00385 {
00386 sort theSort;
00387
00388 if ((n == NULL) || (n->predicate == NULL))
00389 {
00390 llcontbuglit ("checkLclPredicate expects valid lclPredicate. "
00391 "Skipping current check");
00392 return;
00393 }
00394
00395
00396
00397 if (!n->predicate->error_reported)
00398 {
00399
00400 theSort = n->predicate->sort;
00401 if (!sort_compatible (theSort, sort_capBool))
00402 {
00403 if (sort_isNoSort (theSort))
00404 {
00405 ;
00406 }
00407 else
00408 {
00409 cstring clauset = ltoken_getRawString (t);
00410
00411 if (cstring_firstChar (clauset) == '(')
00412 {
00413 clauset = cstring_makeLiteral ("Equality");
00414 }
00415 else
00416 {
00417
00418 clauset = cstring_copy (clauset);
00419 cstring_setChar (clauset, 1,
00420 (char) toupper (cstring_firstChar (clauset)));
00421 }
00422
00423 lclerror (t, message ("%q expects a boolean term, given %q.",
00424 clauset, sort_unparse (theSort)));
00425
00426 }
00427 }
00428 }
00429 }
00430
00431
00432
00433
00434
00435 static bool isDeRefOperator (cstring s)
00436 {
00437 return (cstring_equalLit (s, "*"));
00438 }
00439
00440 static bool isStateOperator (cstring s)
00441 {
00442 return (cstring_equalLit (s, "^") ||
00443 cstring_equalLit (s, "'") ||
00444 cstring_equalLit (s, "\\any") ||
00445 cstring_equalLit (s, "\\pre") ||
00446 cstring_equalLit (s, "\\post"));
00447 }
00448
00449 static bool isCompareOperator (cstring s)
00450 {
00451 return (cstring_equalLit (s, "\\eq") ||
00452 cstring_equalLit (s, "\\neq") ||
00453 cstring_equalLit (s, "=") ||
00454 cstring_equalLit (s, "!=") ||
00455 cstring_equalLit (s, "~=") ||
00456 cstring_equalLit (s, "=="));
00457 }
00458
00459 static bool isStandardOperator ( nameNode n)
00460 {
00461 if (n != (nameNode) 0)
00462 {
00463 if (!n->isOpId)
00464 {
00465 opFormNode opf = n->content.opform;
00466
00467 llassert (opf != NULL);
00468
00469 switch (opf->kind)
00470 {
00471 case OPF_IF: return TRUE;
00472 case OPF_ANYOP:
00473 break;
00474 case OPF_MANYOP:
00475 {
00476 cstring s = ltoken_getRawString (opf->content.anyop);
00477
00478 if (isStateOperator (s)) return TRUE;
00479 return FALSE;
00480 }
00481 case OPF_ANYOPM:
00482
00483 {
00484 cstring s = ltoken_getRawString (opf->content.anyop);
00485
00486 return (isDeRefOperator (s));
00487 }
00488 case OPF_MANYOPM:
00489 {
00490 cstring s = ltoken_getRawString (opf->content.anyop);
00491
00492 return (isCompareOperator (s));
00493 }
00494 case OPF_MIDDLE:
00495 break;
00496 case OPF_MMIDDLE:
00497 break;
00498 case OPF_MIDDLEM:
00499 break;
00500 case OPF_MMIDDLEM:
00501 break;
00502 case OPF_BMIDDLE:
00503 break;
00504 case OPF_BMMIDDLE:
00505 break;
00506 case OPF_BMIDDLEM:
00507 break;
00508 case OPF_BMMIDDLEM:
00509 break;
00510 case OPF_SELECT:
00511 break;
00512 case OPF_MAP:
00513 break;
00514 case OPF_MSELECT:
00515 break;
00516 case OPF_MMAP:
00517 break;
00518 default:
00519 break;
00520 }
00521 }
00522 else
00523 {
00524 int code = ltoken_getCode (n->content.opid);
00525
00526 if (code == simpleId)
00527 {
00528 cstring text = nameNode_unparse (n);
00529 bool ret = (cstring_equalLit (text, "trashed")
00530 || cstring_equalLit (text, "maxIndex")
00531 || cstring_equalLit (text, "minIndex")
00532 || cstring_equalLit (text, "isSub"));
00533
00534 cstring_free (text);
00535 return ret;
00536 }
00537
00538 return (code == LLT_MODIFIES || code == LLT_FRESH
00539 || code == LLT_UNCHANGED || code == LLT_SIZEOF);
00540 }
00541 }
00542 return FALSE;
00543 }
00544
00545 static sortSet
00546 standardOperators ( nameNode n, sortSetList argSorts, sort qual)
00547 {
00548 sortSet argSet;
00549 sortSet ret = sortSet_new ();
00550
00551 if (n == (nameNode) 0) return ret;
00552
00553 if (n->isOpId)
00554 {
00555 int code = ltoken_getCode (n->content.opid);
00556
00557 if (sortSetList_size (argSorts) == 1)
00558 {
00559 sortSetList_reset (argSorts);
00560
00561 argSet = sortSetList_current (argSorts);
00562
00563 sortSet_elements (argSet, current)
00564 {
00565 sortNode sn;
00566
00567 sn = sort_quietLookup (current);
00568
00569 while (sn.kind == SRT_SYN)
00570 {
00571 sn = sort_quietLookup (sn.baseSort);
00572 }
00573
00574
00575 switch (code)
00576 {
00577 case simpleId:
00578 {
00579 cstring text = ltoken_getRawString (n->content.opid);
00580
00581 if (cstring_equalLit (text, "trashed"))
00582 {
00583 if (sn.kind == SRT_OBJ ||
00584 sn.kind == SRT_ARRAY)
00585 (void) sortSet_insert (ret, sort_bool);
00586 }
00587
00588 if (cstring_equalLit (text, "maxIndex") ||
00589 cstring_equalLit (text, "minIndex"))
00590 {
00591 if (sn.kind == SRT_ARRAY || sn.kind == SRT_PTR)
00592 (void) sortSet_insert (ret, sort_int);
00593
00594
00595 }
00596 }
00597 break;
00598 case LLT_MODIFIES:
00599 case LLT_FRESH:
00600 case LLT_UNCHANGED:
00601 if (sn.kind == SRT_OBJ ||
00602 sn.kind == SRT_ARRAY)
00603 {
00604 (void) sortSet_insert (ret, sort_bool);
00605 }
00606 break;
00607 case LLT_SIZEOF:
00608 if (sn.kind == SRT_OBJ ||
00609 sn.kind == SRT_ARRAY ||
00610 sn.kind == SRT_VECTOR)
00611 (void) sortSet_insert (ret, sort_int);
00612 break;
00613 default:
00614 break;
00615 }
00616 } end_sortSet_elements;
00617 }
00618 }
00619 else
00620 {
00621 opFormNode opf = n->content.opform;
00622
00623 llassert (opf != NULL);
00624
00625 switch (opf->kind)
00626 {
00627 case OPF_IF:
00628
00629
00630
00631
00632
00633 if (sortSetList_size (argSorts) == 3)
00634 {
00635 argSet = sortSetList_head (argSorts);
00636
00637 if (sortSet_member (argSet, sort_bool))
00638 {
00639 sortSetList_reset (argSorts);
00640 sortSetList_advance (argSorts);
00641
00642 argSet = sortSetList_current (argSorts);
00643
00644 if (sortSet_size (argSet) == 1)
00645 {
00646 sort clause = sortSet_choose (argSet);
00647 sort clause2;
00648
00649 sortSetList_advance (argSorts);
00650 argSet = sortSetList_current (argSorts);
00651
00652 clause2 = sortSet_choose (argSet);
00653
00654 if (sortSet_size (argSet) == 1 &&
00655 sort_equal (&clause, &clause2))
00656 {
00657 (void) sortSet_insert (ret, clause);
00658 }
00659 }
00660 }
00661 }
00662 break;
00663 case OPF_MANYOP:
00664 {
00665 cstring s = ltoken_getRawString (opf->content.anyop);
00666
00667 if (isStateOperator (s))
00668 {
00669 if (sortSetList_size (argSorts) == 1)
00670 {
00671 sortSetList_reset (argSorts);
00672
00673 argSet = sortSetList_current (argSorts);
00674
00675 sortSet_elements (argSet, current)
00676 {
00677 sortNode sn;
00678
00679 sn = sort_quietLookup (current);
00680
00681 while (sn.kind == SRT_SYN)
00682 {
00683 sn = sort_quietLookup (sn.baseSort);
00684 }
00685
00686 switch (sn.kind)
00687 {
00688 case SRT_OBJ:
00689 (void) sortSet_insert (ret, sn.baseSort);
00690 break;
00691 case SRT_ARRAY:
00692 (void) sortSet_insert (ret,
00693 sort_makeVec (ltoken_undefined, current));
00694 break;
00695 case SRT_STRUCT:
00696 (void) sortSet_insert (ret,
00697 sort_makeTuple (ltoken_undefined, current));
00698 break;
00699 case SRT_UNION:
00700 (void) sortSet_insert (ret,
00701 sort_makeUnionVal (ltoken_undefined, current));
00702 break;
00703 case SRT_TUPLE:
00704 case SRT_UNIONVAL:
00705 case SRT_ENUM:
00706 case SRT_LAST:
00707 case SRT_FIRST:
00708 case SRT_NONE:
00709 case SRT_HOF:
00710 case SRT_PRIM:
00711 case SRT_PTR:
00712 case SRT_VECTOR:
00713 break;
00714 case SRT_SYN:
00715 llbuglit ("standardOperators: Synonym in switch");
00716 }
00717 } end_sortSet_elements ;
00718 }
00719 }
00720 }
00721 break;
00722 case OPF_ANYOPM:
00723
00724 {
00725 cstring s = ltoken_getRawString (opf->content.anyop);
00726
00727 if (isDeRefOperator (s))
00728 {
00729 if (sortSetList_size (argSorts) == 1)
00730 {
00731 sortSetList_reset (argSorts);
00732
00733 argSet = sortSetList_current (argSorts);
00734
00735 sortSet_elements (argSet, current)
00736 {
00737 sortNode sn;
00738
00739 sn = sort_quietLookup (current);
00740
00741 while (sn.kind == SRT_SYN)
00742 {
00743 sn = sort_quietLookup (sn.baseSort);
00744 }
00745
00746 if (sn.kind == SRT_PTR)
00747 {
00748 (void) sortSet_insert (ret, sn.baseSort);
00749 }
00750 } end_sortSet_elements;
00751 }
00752 }
00753 }
00754 break;
00755 case OPF_ANYOP:
00756 break;
00757 case OPF_MANYOPM:
00758 {
00759 cstring s = ltoken_getRawString (opf->content.anyop);
00760
00761 if (isCompareOperator (s))
00762 {
00763 if (sortSetList_size (argSorts) == 2)
00764 {
00765 sortSet argSet2;
00766
00767 sortSetList_reset (argSorts);
00768
00769 argSet = sortSetList_current (argSorts);
00770 sortSetList_advance (argSorts);
00771 argSet2 = sortSetList_current (argSorts);
00772
00773 if (sortSet_size (argSet) == 1)
00774 {
00775 sortSet_elements (argSet, cl)
00776 {
00777 sortSet_elements (argSet2, cl2)
00778 {
00779 if (sort_equal (&cl, &cl2))
00780 {
00781 (void) sortSet_insert (ret, sort_bool);
00782 }
00783 } end_sortSet_elements;
00784 } end_sortSet_elements;
00785 }
00786 }
00787 }
00788 }
00789 break;
00790 case OPF_MIDDLE:
00791 break;
00792 case OPF_MMIDDLE:
00793 break;
00794 case OPF_MIDDLEM:
00795 break;
00796 case OPF_MMIDDLEM:
00797 break;
00798 case OPF_BMIDDLE:
00799 break;
00800 case OPF_BMMIDDLE:
00801 break;
00802 case OPF_BMIDDLEM:
00803 break;
00804 case OPF_BMMIDDLEM:
00805 break;
00806 case OPF_SELECT:
00807 break;
00808 case OPF_MAP:
00809 break;
00810 case OPF_MSELECT:
00811 break;
00812 case OPF_MMAP:
00813 break;
00814 default:
00815 break;
00816 }
00817
00818 }
00819 return ret;
00820 }