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 #define _FACTMCH_SOURCE_
00032
00033 #include <stdio.h>
00034 #define _STDIO_INCLUDED_
00035
00036 #include "setup.h"
00037
00038 #if DEFTEMPLATE_CONSTRUCT && DEFRULE_CONSTRUCT
00039
00040 #include "drive.h"
00041 #include "engine.h"
00042 #include "envrnmnt.h"
00043 #include "extnfunc.h"
00044 #include "factgen.h"
00045 #include "factrete.h"
00046 #include "incrrset.h"
00047 #include "memalloc.h"
00048 #include "reteutil.h"
00049 #include "router.h"
00050 #include "sysdep.h"
00051 #include "tmpltdef.h"
00052
00053 #include "factmch.h"
00054
00055
00056
00057
00058
00059 static intBool EvaluatePatternExpression(void *,struct factPatternNode *,struct expr *);
00060 static void TraceErrorToJoin(void *,struct factPatternNode *,int);
00061 static void ProcessFactAlphaMatch(void *,struct fact *,struct multifieldMarker *,struct factPatternNode *);
00062 static struct factPatternNode *GetNextFactPatternNode(void *,int,struct factPatternNode *);
00063 static int SkipFactPatternNode(void *,struct factPatternNode *);
00064 static void ProcessMultifieldNode(void *,
00065 struct factPatternNode *,
00066 struct multifieldMarker *,
00067 struct multifieldMarker *,int);
00068 static void PatternNetErrorMessage(void *,struct factPatternNode *);
00069
00070
00071
00072
00073 globle void FactPatternMatch(
00074 void *theEnv,
00075 struct fact *theFact,
00076 struct factPatternNode *patternPtr,
00077 int offset,
00078 struct multifieldMarker *markers,
00079 struct multifieldMarker *endMark)
00080 {
00081 int theSlotField;
00082 int offsetSlot;
00083 DATA_OBJECT theResult;
00084 struct factPatternNode *tempPtr;
00085
00086
00087
00088
00089
00090
00091
00092 if (patternPtr == NULL) return;
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 offsetSlot = patternPtr->whichSlot;
00104
00105
00106
00107
00108
00109
00110 FactData(theEnv)->CurrentPatternFact = theFact;
00111 FactData(theEnv)->CurrentPatternMarks = markers;
00112
00113
00114
00115
00116
00117 while (patternPtr != NULL)
00118 {
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 theSlotField = patternPtr->whichField;
00129 if (offsetSlot == patternPtr->whichSlot)
00130 { theSlotField += offset; }
00131
00132
00133
00134
00135
00136
00137 if (SkipFactPatternNode(theEnv,patternPtr))
00138 { patternPtr = GetNextFactPatternNode(theEnv,TRUE,patternPtr); }
00139
00140
00141
00142
00143
00144
00145
00146 else if (patternPtr->header.singlefieldNode)
00147 {
00148
00149
00150
00151
00152
00153
00154
00155 int skipit = FALSE;
00156 if (patternPtr->header.endSlot &&
00157 ((FactData(theEnv)->CurrentPatternMarks == NULL) ?
00158 FALSE :
00159 (FactData(theEnv)->CurrentPatternMarks->where.whichSlotNumber == patternPtr->whichSlot)) &&
00160 (FactData(theEnv)->CurrentPatternFact->theProposition.theFields
00161 [patternPtr->whichSlot].type == MULTIFIELD))
00162 {
00163 if ((patternPtr->leaveFields + theSlotField) != (int)
00164 ((struct multifield *) FactData(theEnv)->CurrentPatternFact->theProposition.theFields
00165 [patternPtr->whichSlot].value)->multifieldLength)
00166 { skipit = TRUE; }
00167 }
00168
00169 if (skipit)
00170 { patternPtr = GetNextFactPatternNode(theEnv,TRUE,patternPtr); }
00171 else
00172
00173 if (patternPtr->header.selector)
00174 {
00175 if (EvaluatePatternExpression(theEnv,patternPtr,patternPtr->networkTest->nextArg))
00176 {
00177 EvaluateExpression(theEnv,patternPtr->networkTest,&theResult);
00178
00179 tempPtr = (struct factPatternNode *) FindHashedPatternNode(theEnv,patternPtr,theResult.type,theResult.value);
00180 }
00181 else
00182 { tempPtr = NULL; }
00183
00184 if (tempPtr != NULL)
00185 {
00186 if (tempPtr->header.stopNode)
00187 { ProcessFactAlphaMatch(theEnv,theFact,markers,tempPtr); }
00188
00189 patternPtr = GetNextFactPatternNode(theEnv,FALSE,tempPtr);
00190 }
00191 else
00192 { patternPtr = GetNextFactPatternNode(theEnv,TRUE,patternPtr); }
00193 }
00194
00195
00196
00197
00198
00199 else if (EvaluatePatternExpression(theEnv,patternPtr,patternPtr->networkTest))
00200 {
00201
00202
00203
00204
00205
00206
00207 if (patternPtr->header.stopNode)
00208 { ProcessFactAlphaMatch(theEnv,theFact,markers,patternPtr); }
00209
00210
00211
00212
00213
00214 patternPtr = GetNextFactPatternNode(theEnv,FALSE,patternPtr);
00215 }
00216
00217
00218
00219
00220
00221 else
00222 { patternPtr = GetNextFactPatternNode(theEnv,TRUE,patternPtr); }
00223 }
00224
00225
00226
00227
00228
00229
00230
00231 else if (patternPtr->header.multifieldNode)
00232 {
00233
00234
00235
00236
00237
00238
00239
00240 if (offsetSlot == patternPtr->whichSlot)
00241 { ProcessMultifieldNode(theEnv,patternPtr,markers,endMark,offset); }
00242 else
00243 { ProcessMultifieldNode(theEnv,patternPtr,markers,endMark,0); }
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 patternPtr = GetNextFactPatternNode(theEnv,TRUE,patternPtr);
00255 }
00256 }
00257 }
00258
00259
00260
00261
00262
00263
00264
00265
00266 static void ProcessMultifieldNode(
00267 void *theEnv,
00268 struct factPatternNode *thePattern,
00269 struct multifieldMarker *markers,
00270 struct multifieldMarker *endMark,
00271 int offset)
00272 {
00273 struct multifieldMarker *newMark, *oldMark;
00274 int repeatCount;
00275 struct multifield *theSlotValue;
00276 DATA_OBJECT theResult;
00277 struct factPatternNode *tempPtr;
00278 intBool success;
00279
00280
00281
00282
00283
00284
00285 theSlotValue = (struct multifield *)
00286 FactData(theEnv)->CurrentPatternFact->theProposition.theFields[thePattern->whichSlot].value;
00287
00288
00289
00290
00291
00292 oldMark = markers;
00293
00294
00295
00296
00297
00298
00299 newMark = get_struct(theEnv,multifieldMarker);
00300 newMark->whichField = thePattern->whichField - 1;
00301 newMark->where.whichSlotNumber = (short) thePattern->whichSlot;
00302 newMark->startPosition = (thePattern->whichField - 1) + offset;
00303 newMark->next = NULL;
00304
00305 if (endMark == NULL)
00306 {
00307 markers = newMark;
00308 FactData(theEnv)->CurrentPatternMarks = markers;
00309 }
00310 else
00311 { endMark->next = newMark; }
00312
00313
00314
00315
00316
00317
00318 if (thePattern->header.endSlot)
00319 {
00320 newMark->endPosition = (long) theSlotValue->multifieldLength -
00321 (thePattern->leaveFields + 1);
00322
00323
00324
00325
00326
00327
00328
00329 if (newMark->endPosition < newMark->startPosition)
00330 { newMark->endPosition = newMark->startPosition - 1; }
00331
00332
00333
00334
00335
00336 if (thePattern->header.selector)
00337 {
00338 if (EvaluatePatternExpression(theEnv,thePattern,thePattern->networkTest->nextArg))
00339 {
00340 EvaluateExpression(theEnv,thePattern->networkTest,&theResult);
00341
00342 thePattern = (struct factPatternNode *) FindHashedPatternNode(theEnv,thePattern,theResult.type,theResult.value);
00343 if (thePattern != NULL)
00344 { success = TRUE; }
00345 else
00346 { success = FALSE; }
00347 }
00348 else
00349 { success = FALSE; }
00350 }
00351 else if ((thePattern->networkTest == NULL) ?
00352 TRUE :
00353 (EvaluatePatternExpression(theEnv,thePattern,thePattern->networkTest)))
00354 { success = TRUE; }
00355 else
00356 { success = FALSE; }
00357
00358 if (success)
00359 {
00360
00361
00362
00363
00364
00365
00366 if (thePattern->header.stopNode)
00367 { ProcessFactAlphaMatch(theEnv,FactData(theEnv)->CurrentPatternFact,FactData(theEnv)->CurrentPatternMarks,thePattern); }
00368
00369
00370
00371
00372
00373
00374 FactPatternMatch(theEnv,FactData(theEnv)->CurrentPatternFact,
00375 thePattern->nextLevel,0,FactData(theEnv)->CurrentPatternMarks,newMark);
00376 }
00377
00378
00379
00380
00381
00382
00383
00384 rtn_struct(theEnv,multifieldMarker,newMark);
00385 if (endMark != NULL) endMark->next = NULL;
00386 FactData(theEnv)->CurrentPatternMarks = oldMark;
00387 return;
00388 }
00389
00390
00391
00392
00393
00394 for (repeatCount = (long) (theSlotValue->multifieldLength -
00395 (newMark->startPosition + thePattern->leaveFields));
00396 repeatCount >= 0;
00397 repeatCount--)
00398 {
00399 newMark->endPosition = newMark->startPosition + (repeatCount - 1);
00400
00401 if (thePattern->header.selector)
00402 {
00403 if (EvaluatePatternExpression(theEnv,thePattern,thePattern->networkTest->nextArg))
00404 {
00405 EvaluateExpression(theEnv,thePattern->networkTest,&theResult);
00406
00407 tempPtr = (struct factPatternNode *) FindHashedPatternNode(theEnv,thePattern,theResult.type,theResult.value);
00408 if (tempPtr != NULL)
00409 {
00410 FactPatternMatch(theEnv,FactData(theEnv)->CurrentPatternFact,
00411 tempPtr->nextLevel,offset + repeatCount - 1,
00412 FactData(theEnv)->CurrentPatternMarks,newMark);
00413 }
00414 }
00415 }
00416 else if ((thePattern->networkTest == NULL) ?
00417 TRUE :
00418 (EvaluatePatternExpression(theEnv,thePattern,thePattern->networkTest)))
00419 {
00420 FactPatternMatch(theEnv,FactData(theEnv)->CurrentPatternFact,
00421 thePattern->nextLevel,offset + repeatCount - 1,
00422 FactData(theEnv)->CurrentPatternMarks,newMark);
00423 }
00424 }
00425
00426
00427
00428
00429
00430 rtn_struct(theEnv,multifieldMarker,newMark);
00431 if (endMark != NULL) endMark->next = NULL;
00432 FactData(theEnv)->CurrentPatternMarks = oldMark;
00433 }
00434
00435
00436
00437
00438
00439
00440 static struct factPatternNode *GetNextFactPatternNode(
00441 void *theEnv,
00442 int finishedMatching,
00443 struct factPatternNode *thePattern)
00444 {
00445 EvaluationData(theEnv)->EvaluationError = FALSE;
00446
00447
00448
00449
00450
00451
00452
00453 if (finishedMatching == FALSE)
00454 { if (thePattern->nextLevel != NULL) return(thePattern->nextLevel); }
00455
00456
00457
00458
00459
00460
00461 while ((thePattern->rightNode == NULL) ||
00462 ((thePattern->lastLevel != NULL) &&
00463 (thePattern->lastLevel->header.selector)))
00464 {
00465
00466
00467
00468
00469 thePattern = thePattern->lastLevel;
00470
00471
00472
00473
00474
00475
00476 if (thePattern == NULL) return(NULL);
00477
00478
00479
00480
00481
00482
00483 if ((thePattern->lastLevel != NULL) &&
00484 (thePattern->lastLevel->header.selector))
00485 { thePattern = thePattern->lastLevel; }
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 if (thePattern->header.multifieldNode) return(NULL);
00496 }
00497
00498
00499
00500
00501
00502 return(thePattern->rightNode);
00503 }
00504
00505
00506
00507
00508
00509
00510
00511 static void ProcessFactAlphaMatch(
00512 void *theEnv,
00513 struct fact *theFact,
00514 struct multifieldMarker *theMarks,
00515 struct factPatternNode *thePattern)
00516 {
00517 struct partialMatch *theMatch;
00518 struct patternMatch *listOfMatches;
00519 struct joinNode *listOfJoins;
00520 unsigned long hashValue;
00521
00522
00523
00524
00525
00526 hashValue = ComputeRightHashValue(theEnv,&thePattern->header);
00527
00528
00529
00530
00531
00532 theMatch = CreateAlphaMatch(theEnv,theFact,theMarks,(struct patternNodeHeader *) &thePattern->header,hashValue);
00533 theMatch->owner = &thePattern->header;
00534
00535
00536
00537
00538
00539 listOfMatches = (struct patternMatch *) theFact->list;
00540 theFact->list = (void *) get_struct(theEnv,patternMatch);
00541 ((struct patternMatch *) theFact->list)->next = listOfMatches;
00542 ((struct patternMatch *) theFact->list)->matchingPattern = (struct patternNodeHeader *) thePattern;
00543 ((struct patternMatch *) theFact->list)->theMatch = theMatch;
00544
00545
00546
00547
00548
00549 for (listOfJoins = thePattern->header.entryJoin;
00550 listOfJoins != NULL;
00551 listOfJoins = listOfJoins->rightMatchNode)
00552 { NetworkAssert(theEnv,theMatch,listOfJoins); }
00553 }
00554
00555
00556
00557
00558
00559
00560 static int EvaluatePatternExpression(
00561 void *theEnv,
00562 struct factPatternNode *patternPtr,
00563 struct expr *theTest)
00564 {
00565 DATA_OBJECT theResult;
00566 struct expr *oldArgument;
00567 int rv;
00568
00569
00570
00571
00572
00573
00574 if (theTest == NULL) return(TRUE);
00575
00576
00577
00578
00579
00580 switch(theTest->type)
00581 {
00582
00583
00584
00585
00586
00587
00588 case FACT_PN_CONSTANT1:
00589 oldArgument = EvaluationData(theEnv)->CurrentExpression;
00590 EvaluationData(theEnv)->CurrentExpression = theTest;
00591 rv = FactPNConstant1(theEnv,theTest->value,&theResult);
00592 EvaluationData(theEnv)->CurrentExpression = oldArgument;
00593 return(rv);
00594
00595
00596
00597
00598
00599
00600
00601 case FACT_PN_CONSTANT2:
00602 oldArgument = EvaluationData(theEnv)->CurrentExpression;
00603 EvaluationData(theEnv)->CurrentExpression = theTest;
00604 rv = FactPNConstant2(theEnv,theTest->value,&theResult);
00605 EvaluationData(theEnv)->CurrentExpression = oldArgument;
00606 return(rv);
00607
00608
00609
00610
00611
00612
00613 case FACT_SLOT_LENGTH:
00614 oldArgument = EvaluationData(theEnv)->CurrentExpression;
00615 EvaluationData(theEnv)->CurrentExpression = theTest;
00616 rv = FactSlotLength(theEnv,theTest->value,&theResult);
00617 EvaluationData(theEnv)->CurrentExpression = oldArgument;
00618 return(rv);
00619 }
00620
00621
00622
00623
00624
00625
00626
00627 if (theTest->value == ExpressionData(theEnv)->PTR_OR)
00628 {
00629 for (theTest = theTest->argList;
00630 theTest != NULL;
00631 theTest = theTest->nextArg)
00632 {
00633 if (EvaluatePatternExpression(theEnv,patternPtr,theTest) == TRUE)
00634 {
00635 if (EvaluationData(theEnv)->EvaluationError) return(FALSE);
00636 return(TRUE);
00637 }
00638 if (EvaluationData(theEnv)->EvaluationError) return(FALSE);
00639 }
00640
00641 return(FALSE);
00642 }
00643
00644
00645
00646
00647
00648
00649
00650 else if (theTest->value == ExpressionData(theEnv)->PTR_AND)
00651 {
00652 for (theTest = theTest->argList;
00653 theTest != NULL;
00654 theTest = theTest->nextArg)
00655 {
00656 if (EvaluatePatternExpression(theEnv,patternPtr,theTest) == FALSE)
00657 { return(FALSE); }
00658 if (EvaluationData(theEnv)->EvaluationError) return(FALSE);
00659 }
00660
00661 return(TRUE);
00662 }
00663
00664
00665
00666
00667
00668 if (EvaluateExpression(theEnv,theTest,&theResult))
00669 {
00670 PatternNetErrorMessage(theEnv,patternPtr);
00671 return(FALSE);
00672 }
00673
00674 if ((theResult.value == EnvFalseSymbol(theEnv)) && (theResult.type == SYMBOL))
00675 { return(FALSE); }
00676
00677 return(TRUE);
00678 }
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 static void PatternNetErrorMessage(
00691 void *theEnv,
00692 struct factPatternNode *patternPtr)
00693 {
00694 char buffer[60];
00695 struct templateSlot *theSlots;
00696 int i;
00697
00698
00699
00700
00701
00702 PrintErrorID(theEnv,"FACTMCH",1,TRUE);
00703 EnvPrintRouter(theEnv,WERROR,"This error occurred in the fact pattern network\n");
00704 EnvPrintRouter(theEnv,WERROR," Currently active fact: ");
00705 PrintFact(theEnv,WERROR,FactData(theEnv)->CurrentPatternFact,FALSE,FALSE);
00706 EnvPrintRouter(theEnv,WERROR,"\n");
00707
00708
00709
00710
00711
00712
00713 if (FactData(theEnv)->CurrentPatternFact->whichDeftemplate->implied)
00714 { gensprintf(buffer," Problem resides in field #%d\n",patternPtr->whichField); }
00715 else
00716 {
00717 theSlots = FactData(theEnv)->CurrentPatternFact->whichDeftemplate->slotList;
00718 for (i = 0; i < (int) patternPtr->whichSlot; i++) theSlots = theSlots->next;
00719 gensprintf(buffer," Problem resides in slot %s\n",ValueToString(theSlots->slotName));
00720 }
00721
00722 EnvPrintRouter(theEnv,WERROR,buffer);
00723
00724
00725
00726
00727
00728
00729
00730
00731 TraceErrorToJoin(theEnv,patternPtr,FALSE);
00732 EnvPrintRouter(theEnv,WERROR,"\n");
00733 }
00734
00735
00736
00737
00738
00739
00740
00741
00742 static void TraceErrorToJoin(
00743 void *theEnv,
00744 struct factPatternNode *patternPtr,
00745 int traceRight)
00746 {
00747 struct joinNode *joinPtr;
00748
00749 while (patternPtr != NULL)
00750 {
00751 if (patternPtr->header.stopNode)
00752 {
00753 for (joinPtr = patternPtr->header.entryJoin;
00754 joinPtr != NULL;
00755 joinPtr = joinPtr->rightMatchNode)
00756 { TraceErrorToRule(theEnv,joinPtr," "); }
00757 }
00758 else
00759 { TraceErrorToJoin(theEnv,patternPtr->nextLevel,TRUE); }
00760
00761 if (traceRight) patternPtr = patternPtr->rightNode;
00762 else patternPtr = NULL;
00763 }
00764 }
00765
00766
00767
00768
00769
00770
00771
00772
00773 static int SkipFactPatternNode(
00774 void *theEnv,
00775 struct factPatternNode *thePattern)
00776 {
00777 #if (MAC_MCW || WIN_MCW) && (RUN_TIME || BLOAD_ONLY)
00778 #pragma unused(theEnv,thePattern)
00779 #endif
00780
00781 #if (! RUN_TIME) && (! BLOAD_ONLY)
00782 if (EngineData(theEnv)->IncrementalResetInProgress &&
00783 (thePattern->header.initialize == FALSE))
00784 { return(TRUE); }
00785 #endif
00786
00787 return(FALSE);
00788 }
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 #if WIN_BTC
00800 #pragma argsused
00801 #endif
00802 globle void MarkFactPatternForIncrementalReset(
00803 void *theEnv,
00804 struct patternNodeHeader *thePattern,
00805 int value)
00806 {
00807 struct factPatternNode *patternPtr = (struct factPatternNode *) thePattern;
00808 struct joinNode *theJoin;
00809 #if MAC_MCW || WIN_MCW || MAC_XCD
00810 #pragma unused(theEnv)
00811 #endif
00812
00813
00814
00815
00816
00817
00818 Bogus(patternPtr == NULL);
00819
00820
00821
00822
00823
00824
00825
00826
00827 if (patternPtr->header.initialize == FALSE)
00828 {
00829 for (theJoin = patternPtr->header.entryJoin;
00830 theJoin != NULL;
00831 theJoin = theJoin->rightMatchNode)
00832 {
00833 if (theJoin->initialize == FALSE)
00834 { return; }
00835 }
00836 }
00837
00838
00839
00840
00841
00842
00843 while (patternPtr != NULL)
00844 {
00845 patternPtr->header.initialize = value;
00846 patternPtr = patternPtr->lastLevel;
00847 }
00848 }
00849
00850
00851
00852
00853
00854
00855
00856
00857 globle void FactsIncrementalReset(
00858 void *theEnv)
00859 {
00860 struct fact *factPtr;
00861
00862 for (factPtr = (struct fact *) EnvGetNextFact(theEnv,NULL);
00863 factPtr != NULL;
00864 factPtr = (struct fact *) EnvGetNextFact(theEnv,factPtr))
00865 {
00866 EngineData(theEnv)->JoinOperationInProgress = TRUE;
00867 FactPatternMatch(theEnv,factPtr,
00868 factPtr->whichDeftemplate->patternNetwork,
00869 0,NULL,NULL);
00870 EngineData(theEnv)->JoinOperationInProgress = FALSE;
00871 }
00872 }
00873
00874 #endif
00875