00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #define _RULECSTR_SOURCE_
00025
00026 #include "setup.h"
00027
00028 #if (! RUN_TIME) && (! BLOAD_ONLY) && DEFRULE_CONSTRUCT
00029
00030 #include <stdio.h>
00031 #define _STDIO_INCLUDED_
00032
00033 #include "analysis.h"
00034 #include "cstrnchk.h"
00035 #include "cstrnops.h"
00036 #include "cstrnutl.h"
00037 #include "envrnmnt.h"
00038 #include "extnfunc.h"
00039 #include "prcdrpsr.h"
00040 #include "reorder.h"
00041 #include "router.h"
00042 #include "rulepsr.h"
00043
00044 #include "rulecstr.h"
00045
00046
00047
00048
00049
00050 static intBool CheckForUnmatchableConstraints(void *,struct lhsParseNode *,int);
00051 static intBool MultifieldCardinalityViolation(void *,struct lhsParseNode *);
00052 static struct lhsParseNode *UnionVariableConstraints(void *,struct lhsParseNode *,
00053 struct lhsParseNode *);
00054 static struct lhsParseNode *AddToVariableConstraints(void *,struct lhsParseNode *,
00055 struct lhsParseNode *);
00056 static void ConstraintConflictMessage(void *,struct symbolHashNode *,
00057 int,int,struct symbolHashNode *);
00058 static intBool CheckArgumentForConstraintError(void *,struct expr *,struct expr*,
00059 int,struct FunctionDefinition *,
00060 struct lhsParseNode *);
00061
00062
00063
00064
00065
00066
00067 static intBool CheckForUnmatchableConstraints(
00068 void *theEnv,
00069 struct lhsParseNode *theNode,
00070 int whichCE)
00071 {
00072 if (EnvGetStaticConstraintChecking(theEnv) == FALSE) return(FALSE);
00073
00074 if (UnmatchableConstraint(theNode->constraints))
00075 {
00076 ConstraintConflictMessage(theEnv,(SYMBOL_HN *) theNode->value,whichCE,
00077 theNode->index,theNode->slot);
00078 return(TRUE);
00079 }
00080
00081 return(FALSE);
00082 }
00083
00084
00085
00086
00087
00088
00089 static void ConstraintConflictMessage(
00090 void *theEnv,
00091 struct symbolHashNode *variableName,
00092 int thePattern,
00093 int theField,
00094 struct symbolHashNode *theSlot)
00095 {
00096
00097
00098
00099
00100 PrintErrorID(theEnv,"RULECSTR",1,TRUE);
00101
00102
00103
00104
00105
00106
00107 if (variableName != NULL)
00108 {
00109 EnvPrintRouter(theEnv,WERROR,"Variable ?");
00110 EnvPrintRouter(theEnv,WERROR,ValueToString(variableName));
00111 EnvPrintRouter(theEnv,WERROR," in CE #");
00112 PrintLongInteger(theEnv,WERROR,(long int) thePattern);
00113 }
00114 else
00115 {
00116 EnvPrintRouter(theEnv,WERROR,"Pattern #");
00117 PrintLongInteger(theEnv,WERROR,(long int) thePattern);
00118 }
00119
00120
00121
00122
00123
00124
00125 if (theSlot == NULL)
00126 {
00127 EnvPrintRouter(theEnv,WERROR," field #");
00128 PrintLongInteger(theEnv,WERROR,(long int) theField);
00129 }
00130 else
00131 {
00132 EnvPrintRouter(theEnv,WERROR," slot ");
00133 EnvPrintRouter(theEnv,WERROR,ValueToString(theSlot));
00134 }
00135
00136
00137
00138
00139
00140 EnvPrintRouter(theEnv,WERROR,"\nhas constraint conflicts which make the pattern unmatchable.\n");
00141 }
00142
00143
00144
00145
00146
00147 static intBool MultifieldCardinalityViolation(
00148 void *theEnv,
00149 struct lhsParseNode *theNode)
00150 {
00151 struct lhsParseNode *tmpNode;
00152 struct expr *tmpMax;
00153 long minFields = 0;
00154 long maxFields = 0;
00155 int posInfinity = FALSE;
00156 CONSTRAINT_RECORD *newConstraint, *tempConstraint;
00157
00158
00159
00160
00161
00162
00163 if (theNode->multifieldSlot == FALSE) return(FALSE);
00164
00165
00166
00167
00168
00169
00170
00171 for (tmpNode = theNode->bottom;
00172 tmpNode != NULL;
00173 tmpNode = tmpNode->right)
00174 {
00175
00176
00177
00178
00179
00180 if ((tmpNode->type == SF_VARIABLE) ||
00181 (tmpNode->type == SF_WILDCARD))
00182 {
00183 minFields++;
00184 maxFields++;
00185 }
00186
00187
00188
00189
00190
00191
00192
00193
00194 else if (tmpNode->constraints != NULL)
00195 {
00196
00197
00198
00199
00200
00201 if (tmpNode->constraints->minFields->value != SymbolData(theEnv)->NegativeInfinity)
00202 { minFields += (long) ValueToLong(tmpNode->constraints->minFields->value); }
00203
00204
00205
00206
00207
00208
00209 tmpMax = tmpNode->constraints->maxFields;
00210 while (tmpMax->nextArg != NULL) tmpMax = tmpMax->nextArg;
00211 if (tmpMax->value == SymbolData(theEnv)->PositiveInfinity)
00212 { posInfinity = TRUE; }
00213 else
00214 { maxFields += (long) ValueToLong(tmpMax->value); }
00215 }
00216
00217
00218
00219
00220
00221
00222
00223 else
00224 { posInfinity = TRUE; }
00225 }
00226
00227
00228
00229
00230
00231
00232 if (theNode->constraints == NULL) tempConstraint = GetConstraintRecord(theEnv);
00233 else tempConstraint = CopyConstraintRecord(theEnv,theNode->constraints);
00234 ReturnExpression(theEnv,tempConstraint->minFields);
00235 ReturnExpression(theEnv,tempConstraint->maxFields);
00236 tempConstraint->minFields = GenConstant(theEnv,INTEGER,EnvAddLong(theEnv,(long long) minFields));
00237 if (posInfinity) tempConstraint->maxFields = GenConstant(theEnv,SYMBOL,SymbolData(theEnv)->PositiveInfinity);
00238 else tempConstraint->maxFields = GenConstant(theEnv,INTEGER,EnvAddLong(theEnv,(long long) maxFields));
00239
00240
00241
00242
00243
00244
00245
00246 newConstraint = IntersectConstraints(theEnv,theNode->constraints,tempConstraint);
00247 if (theNode->derivedConstraints) RemoveConstraint(theEnv,theNode->constraints);
00248 RemoveConstraint(theEnv,tempConstraint);
00249 theNode->constraints = newConstraint;
00250 theNode->derivedConstraints = TRUE;
00251
00252
00253
00254
00255
00256 if (EnvGetStaticConstraintChecking(theEnv) == FALSE) return(FALSE);
00257 if (UnmatchableConstraint(newConstraint)) return(TRUE);
00258
00259 return(FALSE);
00260 }
00261
00262
00263
00264
00265
00266
00267 globle intBool ProcessConnectedConstraints(
00268 void *theEnv,
00269 struct lhsParseNode *theNode,
00270 struct lhsParseNode *multifieldHeader,
00271 struct lhsParseNode *patternHead)
00272 {
00273 struct constraintRecord *orConstraints = NULL, *andConstraints;
00274 struct constraintRecord *tmpConstraints, *rvConstraints;
00275 struct lhsParseNode *orNode, *andNode;
00276 struct expr *tmpExpr;
00277
00278
00279
00280
00281
00282
00283 for (orNode = theNode->bottom; orNode != NULL; orNode = orNode->bottom)
00284 {
00285
00286
00287
00288
00289 andConstraints = NULL;
00290 for (andNode = orNode; andNode != NULL; andNode = andNode->right)
00291 {
00292 if (! andNode->negated)
00293 {
00294 if (andNode->type == RETURN_VALUE_CONSTRAINT)
00295 {
00296 if (andNode->expression->type == FCALL)
00297 {
00298 rvConstraints = FunctionCallToConstraintRecord(theEnv,andNode->expression->value);
00299 tmpConstraints = andConstraints;
00300 andConstraints = IntersectConstraints(theEnv,andConstraints,rvConstraints);
00301 RemoveConstraint(theEnv,tmpConstraints);
00302 RemoveConstraint(theEnv,rvConstraints);
00303 }
00304 }
00305 else if (ConstantType(andNode->type))
00306 {
00307 tmpExpr = GenConstant(theEnv,andNode->type,andNode->value);
00308 rvConstraints = ExpressionToConstraintRecord(theEnv,tmpExpr);
00309 tmpConstraints = andConstraints;
00310 andConstraints = IntersectConstraints(theEnv,andConstraints,rvConstraints);
00311 RemoveConstraint(theEnv,tmpConstraints);
00312 RemoveConstraint(theEnv,rvConstraints);
00313 ReturnExpression(theEnv,tmpExpr);
00314 }
00315 else if (andNode->constraints != NULL)
00316 {
00317 tmpConstraints = andConstraints;
00318 andConstraints = IntersectConstraints(theEnv,andConstraints,andNode->constraints);
00319 RemoveConstraint(theEnv,tmpConstraints);
00320 }
00321 }
00322 }
00323
00324
00325
00326
00327
00328 tmpConstraints = andConstraints;
00329 andConstraints = IntersectConstraints(theEnv,andConstraints,theNode->constraints);
00330 RemoveConstraint(theEnv,tmpConstraints);
00331
00332
00333
00334
00335
00336 for (andNode = orNode; andNode != NULL; andNode = andNode->right)
00337 {
00338 if ((andNode->negated) && ConstantType(andNode->type))
00339 { RemoveConstantFromConstraint(theEnv,andNode->type,andNode->value,andConstraints); }
00340 }
00341
00342
00343
00344
00345
00346 tmpConstraints = orConstraints;
00347 orConstraints = UnionConstraints(theEnv,orConstraints,andConstraints);
00348 RemoveConstraint(theEnv,tmpConstraints);
00349 RemoveConstraint(theEnv,andConstraints);
00350 }
00351
00352
00353
00354
00355
00356
00357
00358 if (orConstraints != NULL)
00359 {
00360 if (theNode->derivedConstraints) RemoveConstraint(theEnv,theNode->constraints);
00361 theNode->constraints = orConstraints;
00362 theNode->derivedConstraints = TRUE;
00363 }
00364
00365
00366
00367
00368
00369 if (CheckForUnmatchableConstraints(theEnv,theNode,(int) patternHead->whichCE))
00370 { return(TRUE); }
00371
00372
00373
00374
00375
00376
00377 if ((multifieldHeader != NULL) && (theNode->right == NULL))
00378 {
00379 if (MultifieldCardinalityViolation(theEnv,multifieldHeader))
00380 {
00381 ConstraintViolationErrorMessage(theEnv,"The group of restrictions",
00382 NULL,FALSE,
00383 (int) patternHead->whichCE,
00384 multifieldHeader->slot,
00385 multifieldHeader->index,
00386 CARDINALITY_VIOLATION,
00387 multifieldHeader->constraints,TRUE);
00388 return(TRUE);
00389 }
00390 }
00391
00392
00393
00394
00395
00396
00397 return(FALSE);
00398 }
00399
00400
00401
00402
00403
00404
00405 globle void ConstraintReferenceErrorMessage(
00406 void *theEnv,
00407 struct symbolHashNode *theVariable,
00408 struct lhsParseNode *theExpression,
00409 int whichArgument,
00410 int whichCE,
00411 struct symbolHashNode *slotName,
00412 int theField)
00413 {
00414 struct expr *temprv;
00415
00416 PrintErrorID(theEnv,"RULECSTR",2,TRUE);
00417
00418
00419
00420
00421
00422 EnvPrintRouter(theEnv,WERROR,"Previous variable bindings of ?");
00423 EnvPrintRouter(theEnv,WERROR,ValueToString(theVariable));
00424 EnvPrintRouter(theEnv,WERROR," caused the type restrictions");
00425
00426
00427
00428
00429
00430 EnvPrintRouter(theEnv,WERROR,"\nfor argument #");
00431 PrintLongInteger(theEnv,WERROR,(long int) whichArgument);
00432
00433
00434
00435
00436
00437 EnvPrintRouter(theEnv,WERROR," of the expression ");
00438 temprv = LHSParseNodesToExpression(theEnv,theExpression);
00439 ReturnExpression(theEnv,temprv->nextArg);
00440 temprv->nextArg = NULL;
00441 PrintExpression(theEnv,WERROR,temprv);
00442 EnvPrintRouter(theEnv,WERROR,"\n");
00443 ReturnExpression(theEnv,temprv);
00444
00445
00446
00447
00448
00449
00450
00451 EnvPrintRouter(theEnv,WERROR,"found in CE #");
00452 PrintLongInteger(theEnv,WERROR,(long int) whichCE);
00453 if (slotName == NULL)
00454 {
00455 if (theField > 0)
00456 {
00457 EnvPrintRouter(theEnv,WERROR," field #");
00458 PrintLongInteger(theEnv,WERROR,(long int) theField);
00459 }
00460 }
00461 else
00462 {
00463 EnvPrintRouter(theEnv,WERROR," slot ");
00464 EnvPrintRouter(theEnv,WERROR,ValueToString(slotName));
00465 }
00466
00467 EnvPrintRouter(theEnv,WERROR," to be violated.\n");
00468 }
00469
00470
00471
00472
00473
00474
00475
00476 static struct lhsParseNode *AddToVariableConstraints(
00477 void *theEnv,
00478 struct lhsParseNode *oldList,
00479 struct lhsParseNode *newItems)
00480 {
00481 CONSTRAINT_RECORD *newConstraints;
00482 struct lhsParseNode *temp, *trace;
00483
00484
00485
00486
00487
00488
00489
00490 while (newItems != NULL)
00491 {
00492
00493
00494
00495
00496
00497 temp = newItems->right;
00498 newItems->right = NULL;
00499
00500
00501
00502
00503
00504 for (trace = oldList; trace != NULL; trace = trace->right)
00505 {
00506
00507
00508
00509
00510
00511
00512 if (trace->value == newItems->value)
00513 {
00514 newConstraints = IntersectConstraints(theEnv,trace->constraints,
00515 newItems->constraints);
00516 RemoveConstraint(theEnv,trace->constraints);
00517 trace->constraints = newConstraints;
00518 ReturnLHSParseNodes(theEnv,newItems);
00519 break;
00520 }
00521 }
00522
00523
00524
00525
00526
00527
00528 if (trace == NULL)
00529 {
00530 newItems->right = oldList;
00531 oldList = newItems;
00532 }
00533
00534
00535
00536
00537
00538 newItems = temp;
00539 }
00540
00541 return(oldList);
00542 }
00543
00544
00545
00546
00547
00548
00549
00550 static struct lhsParseNode *UnionVariableConstraints(
00551 void *theEnv,
00552 struct lhsParseNode *list1,
00553 struct lhsParseNode *list2)
00554 {
00555 struct lhsParseNode *list3 = NULL, *trace, *temp;
00556
00557
00558
00559
00560
00561
00562 while (list1 != NULL)
00563 {
00564
00565
00566
00567
00568 for (trace = list2; trace != NULL; trace = trace->right)
00569 {
00570
00571
00572
00573
00574
00575
00576 if (list1->value == trace->value)
00577 {
00578 temp = GetLHSParseNode(theEnv);
00579 temp->derivedConstraints = TRUE;
00580 temp->value = list1->value;
00581 temp->constraints = UnionConstraints(theEnv,list1->constraints,trace->constraints);
00582 temp->right = list3;
00583 list3 = temp;
00584 break;
00585 }
00586 }
00587
00588
00589
00590
00591
00592
00593 temp = list1->right;
00594 list1->right = NULL;
00595 ReturnLHSParseNodes(theEnv,list1);
00596 list1 = temp;
00597 }
00598
00599
00600
00601
00602
00603 ReturnLHSParseNodes(theEnv,list2);
00604
00605
00606
00607
00608
00609 return(list3);
00610 }
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 globle struct lhsParseNode *GetExpressionVarConstraints(
00621 void *theEnv,
00622 struct lhsParseNode *theExpression)
00623 {
00624 struct lhsParseNode *list1 = NULL, *list2;
00625
00626 for (; theExpression != NULL; theExpression = theExpression->bottom)
00627 {
00628 if (theExpression->right != NULL)
00629 {
00630 list2 = GetExpressionVarConstraints(theEnv,theExpression->right);
00631 list1 = AddToVariableConstraints(theEnv,list2,list1);
00632 }
00633
00634 if (theExpression->type == SF_VARIABLE)
00635 {
00636 list2 = GetLHSParseNode(theEnv);
00637 if (theExpression->referringNode != NULL)
00638 { list2->type = theExpression->referringNode->type; }
00639 else
00640 { list2->type = SF_VARIABLE; }
00641 list2->value = theExpression->value;
00642 list2->derivedConstraints = TRUE;
00643 list2->constraints = CopyConstraintRecord(theEnv,theExpression->constraints);
00644 list1 = AddToVariableConstraints(theEnv,list2,list1);
00645 }
00646 }
00647
00648 return(list1);
00649 }
00650
00651
00652
00653
00654
00655
00656 globle struct lhsParseNode *DeriveVariableConstraints(
00657 void *theEnv,
00658 struct lhsParseNode *theNode)
00659 {
00660 struct lhsParseNode *orNode, *andNode;
00661 struct lhsParseNode *list1, *list2, *list3 = NULL;
00662 int first = TRUE;
00663
00664
00665
00666
00667
00668
00669 for (orNode = theNode->bottom; orNode != NULL; orNode = orNode->bottom)
00670 {
00671
00672
00673
00674
00675 list2 = NULL;
00676 for (andNode = orNode; andNode != NULL; andNode = andNode->right)
00677 {
00678 if ((andNode->type == RETURN_VALUE_CONSTRAINT) ||
00679 (andNode->type == PREDICATE_CONSTRAINT))
00680 {
00681 list1 = GetExpressionVarConstraints(theEnv,andNode->expression);
00682 list2 = AddToVariableConstraints(theEnv,list2,list1);
00683 }
00684 }
00685
00686 if (first)
00687 {
00688 list3 = list2;
00689 first = FALSE;
00690 }
00691 else
00692 { list3 = UnionVariableConstraints(theEnv,list3,list2); }
00693 }
00694
00695 return(list3);
00696 }
00697
00698
00699
00700
00701
00702 globle intBool CheckRHSForConstraintErrors(
00703 void *theEnv,
00704 struct expr *expressionList,
00705 struct lhsParseNode *theLHS)
00706 {
00707 struct FunctionDefinition *theFunction;
00708 int i;
00709 struct expr *lastOne = NULL, *checkList, *tmpPtr;
00710
00711 if (expressionList == NULL) return(FALSE);
00712
00713 for (checkList = expressionList;
00714 checkList != NULL;
00715 checkList = checkList->nextArg)
00716 {
00717 expressionList = checkList->argList;
00718 i = 1;
00719 if (checkList->type == FCALL)
00720 {
00721 lastOne = checkList;
00722 theFunction = (struct FunctionDefinition *) checkList->value;
00723 }
00724 else
00725 { theFunction = NULL; }
00726
00727 while (expressionList != NULL)
00728 {
00729 if (CheckArgumentForConstraintError(theEnv,expressionList,lastOne,i,
00730 theFunction,theLHS))
00731 { return(TRUE); }
00732
00733 i++;
00734 tmpPtr = expressionList->nextArg;
00735 expressionList->nextArg = NULL;
00736 if (CheckRHSForConstraintErrors(theEnv,expressionList,theLHS)) return(TRUE);
00737 expressionList->nextArg = tmpPtr;
00738 expressionList = expressionList->nextArg;
00739 }
00740 }
00741
00742 return(FALSE);
00743 }
00744
00745
00746
00747
00748
00749
00750 static intBool CheckArgumentForConstraintError(
00751 void *theEnv,
00752 struct expr *expressionList,
00753 struct expr *lastOne,
00754 int i,
00755 struct FunctionDefinition *theFunction,
00756 struct lhsParseNode *theLHS)
00757 {
00758 int theRestriction;
00759 CONSTRAINT_RECORD *constraint1, *constraint2, *constraint3, *constraint4;
00760 struct lhsParseNode *theVariable;
00761 struct expr *tmpPtr;
00762 int rv = FALSE;
00763
00764
00765
00766
00767
00768
00769
00770 if ((expressionList->type != SF_VARIABLE) || (theFunction == NULL))
00771 { return (rv); }
00772
00773
00774
00775
00776
00777
00778 theRestriction = GetNthRestriction(theFunction,i);
00779 constraint1 = ArgumentTypeToConstraintRecord(theEnv,theRestriction);
00780
00781
00782
00783
00784
00785
00786 theVariable = FindVariable((SYMBOL_HN *) expressionList->value,theLHS);
00787 if (theVariable != NULL)
00788 {
00789 if (theVariable->type == MF_VARIABLE)
00790 {
00791 constraint2 = GetConstraintRecord(theEnv);
00792 SetConstraintType(MULTIFIELD,constraint2);
00793 }
00794 else if (theVariable->constraints == NULL)
00795 { constraint2 = GetConstraintRecord(theEnv); }
00796 else
00797 { constraint2 = CopyConstraintRecord(theEnv,theVariable->constraints); }
00798 }
00799 else
00800 { constraint2 = NULL; }
00801
00802
00803
00804
00805
00806
00807 constraint3 = FindBindConstraints(theEnv,(SYMBOL_HN *) expressionList->value);
00808
00809
00810
00811
00812
00813
00814 constraint3 = UnionConstraints(theEnv,constraint3,constraint2);
00815
00816
00817
00818
00819
00820
00821
00822 constraint4 = IntersectConstraints(theEnv,constraint3,constraint1);
00823
00824
00825
00826
00827
00828 if (UnmatchableConstraint(constraint4) && EnvGetStaticConstraintChecking(theEnv))
00829 {
00830 PrintErrorID(theEnv,"RULECSTR",3,TRUE);
00831 EnvPrintRouter(theEnv,WERROR,"Previous variable bindings of ?");
00832 EnvPrintRouter(theEnv,WERROR,ValueToString((SYMBOL_HN *) expressionList->value));
00833 EnvPrintRouter(theEnv,WERROR," caused the type restrictions");
00834 EnvPrintRouter(theEnv,WERROR,"\nfor argument #");
00835 PrintLongInteger(theEnv,WERROR,(long int) i);
00836 EnvPrintRouter(theEnv,WERROR," of the expression ");
00837 tmpPtr = lastOne->nextArg;
00838 lastOne->nextArg = NULL;
00839 PrintExpression(theEnv,WERROR,lastOne);
00840 lastOne->nextArg = tmpPtr;
00841 EnvPrintRouter(theEnv,WERROR,"\nfound in the rule's RHS to be violated.\n");
00842
00843 rv = TRUE;
00844 }
00845
00846
00847
00848
00849
00850 RemoveConstraint(theEnv,constraint1);
00851 RemoveConstraint(theEnv,constraint2);
00852 RemoveConstraint(theEnv,constraint3);
00853 RemoveConstraint(theEnv,constraint4);
00854
00855
00856
00857
00858
00859
00860 return(rv);
00861 }
00862
00863 #endif