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
00035
00036
00037 #define _RETRACT_SOURCE_
00038
00039 #include <stdio.h>
00040 #define _STDIO_INCLUDED_
00041 #include <stdlib.h>
00042
00043 #include "setup.h"
00044
00045 #if DEFRULE_CONSTRUCT
00046
00047 #include "agenda.h"
00048 #include "argacces.h"
00049 #include "constant.h"
00050 #include "drive.h"
00051 #include "engine.h"
00052 #include "envrnmnt.h"
00053 #include "lgcldpnd.h"
00054 #include "match.h"
00055 #include "memalloc.h"
00056 #include "network.h"
00057 #include "reteutil.h"
00058 #include "router.h"
00059 #include "symbol.h"
00060
00061 #include "retract.h"
00062
00063
00064
00065
00066
00067 static void ReturnMarkers(void *,struct multifieldMarker *);
00068 static intBool FindNextConflictingMatch(void *,struct partialMatch *,
00069 struct partialMatch *,
00070 struct joinNode *,struct partialMatch *);
00071 static intBool PartialMatchDefunct(void *,struct partialMatch *);
00072 static void NegEntryRetractAlpha(void *,struct partialMatch *);
00073 static void NegEntryRetractBeta(void *,struct joinNode *,struct partialMatch *,
00074 struct partialMatch *);
00075
00076
00077
00078
00079
00080
00081
00082 globle void NetworkRetract(
00083 void *theEnv,
00084 struct patternMatch *listOfMatchedPatterns)
00085 {
00086 struct patternMatch *tempMatch, *nextMatch;
00087
00088 tempMatch = listOfMatchedPatterns;
00089 while (tempMatch != NULL)
00090 {
00091 nextMatch = tempMatch->next;
00092
00093 if (tempMatch->theMatch->children != NULL)
00094 { PosEntryRetractAlpha(theEnv,tempMatch->theMatch); }
00095
00096 if (tempMatch->theMatch->blockList != NULL)
00097 { NegEntryRetractAlpha(theEnv,tempMatch->theMatch); }
00098
00099
00100
00101
00102
00103 RemoveAlphaMemoryMatches(theEnv,tempMatch->matchingPattern,
00104 tempMatch->theMatch,
00105 tempMatch->theMatch->binds[0].gm.theMatch);
00106
00107 rtn_struct(theEnv,patternMatch,tempMatch);
00108
00109 tempMatch = nextMatch;
00110 }
00111 }
00112
00113
00114
00115
00116 globle void PosEntryRetractAlpha(
00117 void *theEnv,
00118 struct partialMatch *alphaMatch)
00119 {
00120 struct partialMatch *betaMatch, *tempMatch;
00121 struct joinNode *joinPtr;
00122
00123 betaMatch = alphaMatch->children;
00124 while (betaMatch != NULL)
00125 {
00126 joinPtr = (struct joinNode *) betaMatch->owner;
00127
00128 if (betaMatch->children != NULL)
00129 { PosEntryRetractBeta(theEnv,betaMatch,betaMatch->children); }
00130
00131 if (betaMatch->rhsMemory)
00132 { NegEntryRetractAlpha(theEnv,betaMatch); }
00133
00134
00135
00136 if ((joinPtr->ruleToActivate != NULL) ?
00137 (betaMatch->marker != NULL) : FALSE)
00138 { RemoveActivation(theEnv,(struct activation *) betaMatch->marker,TRUE,TRUE); }
00139
00140 tempMatch = betaMatch->nextRightChild;
00141
00142 if (betaMatch->rhsMemory)
00143 { UnlinkBetaPMFromNodeAndLineage(theEnv,joinPtr,betaMatch,RHS); }
00144 else
00145 { UnlinkBetaPMFromNodeAndLineage(theEnv,joinPtr,betaMatch,LHS); }
00146
00147 DeletePartialMatches(theEnv,betaMatch);
00148
00149 betaMatch = tempMatch;
00150 }
00151 }
00152
00153
00154
00155
00156 static void NegEntryRetractAlpha(
00157 void *theEnv,
00158 struct partialMatch *alphaMatch)
00159 {
00160 struct partialMatch *betaMatch;
00161 struct joinNode *joinPtr;
00162
00163 betaMatch = alphaMatch->blockList;
00164 while (betaMatch != NULL)
00165 {
00166 joinPtr = (struct joinNode *) betaMatch->owner;
00167
00168 if ((! joinPtr->patternIsNegated) &&
00169 (! joinPtr->patternIsExists) &&
00170 (! joinPtr->joinFromTheRight))
00171 {
00172 SystemError(theEnv,"RETRACT",117);
00173 betaMatch = betaMatch->nextBlocked;
00174 continue;
00175 }
00176
00177 NegEntryRetractBeta(theEnv,joinPtr,alphaMatch,betaMatch);
00178 betaMatch = alphaMatch->blockList;
00179 }
00180 }
00181
00182
00183
00184
00185 static void NegEntryRetractBeta(
00186 void *theEnv,
00187 struct joinNode *joinPtr,
00188 struct partialMatch *alphaMatch,
00189 struct partialMatch *betaMatch)
00190 {
00191
00192
00193
00194
00195
00196 RemoveBlockedLink(betaMatch);
00197
00198 if (FindNextConflictingMatch(theEnv,betaMatch,alphaMatch->nextInMemory,joinPtr,alphaMatch))
00199 { return; }
00200 else if (joinPtr->patternIsExists)
00201 {
00202 if (betaMatch->children != NULL)
00203 { PosEntryRetractBeta(theEnv,betaMatch,betaMatch->children); }
00204 return;
00205 }
00206 else if (joinPtr->firstJoin && (joinPtr->patternIsNegated || joinPtr->joinFromTheRight) && (! joinPtr->patternIsExists))
00207 {
00208 if (joinPtr->secondaryNetworkTest != NULL)
00209 {
00210 if (EvaluateSecondaryNetworkTest(theEnv,betaMatch,joinPtr) == FALSE)
00211 { return; }
00212 }
00213
00214 EPMDrive(theEnv,betaMatch,joinPtr);
00215
00216 return;
00217 }
00218
00219 if (joinPtr->secondaryNetworkTest != NULL)
00220 {
00221 if (EvaluateSecondaryNetworkTest(theEnv,betaMatch,joinPtr) == FALSE)
00222 { return; }
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 PPDrive(theEnv,betaMatch,NULL,joinPtr);
00237 }
00238
00239
00240
00241
00242 globle void PosEntryRetractBeta(
00243 void *theEnv,
00244 struct partialMatch *parentMatch,
00245 struct partialMatch *betaMatch)
00246 {
00247 struct partialMatch *tempMatch;
00248
00249 while (betaMatch != NULL)
00250 {
00251 if (betaMatch->children != NULL)
00252 {
00253 betaMatch = betaMatch->children;
00254 continue;
00255 }
00256
00257 if (betaMatch->nextLeftChild != NULL)
00258 { tempMatch = betaMatch->nextLeftChild; }
00259 else
00260 {
00261 tempMatch = betaMatch->leftParent;
00262 betaMatch->leftParent->children = NULL;
00263 }
00264
00265 if (betaMatch->blockList != NULL)
00266 { NegEntryRetractAlpha(theEnv,betaMatch); }
00267 else if ((((struct joinNode *) betaMatch->owner)->ruleToActivate != NULL) ?
00268 (betaMatch->marker != NULL) : FALSE)
00269 { RemoveActivation(theEnv,(struct activation *) betaMatch->marker,TRUE,TRUE); }
00270
00271 if (betaMatch->rhsMemory)
00272 { UnlinkNonLeftLineage(theEnv,(struct joinNode *) betaMatch->owner,betaMatch,RHS); }
00273 else
00274 { UnlinkNonLeftLineage(theEnv,(struct joinNode *) betaMatch->owner,betaMatch,LHS); }
00275
00276 if (betaMatch->dependents != NULL) RemoveLogicalSupport(theEnv,betaMatch);
00277 ReturnPartialMatch(theEnv,betaMatch);
00278
00279 if (tempMatch == parentMatch) return;
00280 betaMatch = tempMatch;
00281 }
00282 }
00283
00284
00285
00286
00287
00288
00289 static intBool FindNextConflictingMatch(
00290 void *theEnv,
00291 struct partialMatch *theBind,
00292 struct partialMatch *possibleConflicts,
00293 struct joinNode *theJoin,
00294 struct partialMatch *skipMatch)
00295 {
00296 int result, restore = FALSE;
00297 struct partialMatch *oldLHSBinds = NULL;
00298 struct partialMatch *oldRHSBinds = NULL;
00299 struct joinNode *oldJoin = NULL;
00300
00301
00302
00303
00304
00305
00306 #if DEVELOPER
00307 if (possibleConflicts != NULL)
00308 { EngineData(theEnv)->leftToRightLoops++; }
00309 #endif
00310
00311
00312
00313
00314 if (possibleConflicts != NULL)
00315 {
00316 oldLHSBinds = EngineData(theEnv)->GlobalLHSBinds;
00317 oldRHSBinds = EngineData(theEnv)->GlobalRHSBinds;
00318 oldJoin = EngineData(theEnv)->GlobalJoin;
00319 EngineData(theEnv)->GlobalLHSBinds = theBind;
00320 EngineData(theEnv)->GlobalJoin = theJoin;
00321 restore = TRUE;
00322 }
00323
00324 for (;
00325 possibleConflicts != NULL;
00326 possibleConflicts = possibleConflicts->nextInMemory)
00327 {
00328 theJoin->memoryCompares++;
00329
00330
00331
00332
00333
00334
00335 result = FALSE;
00336
00337 if (skipMatch == possibleConflicts)
00338 { }
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 else if (PartialMatchDefunct(theEnv,possibleConflicts))
00351 { }
00352
00353
00354
00355
00356
00357
00358 else if (theJoin->networkTest == NULL)
00359 { result = TRUE; }
00360
00361
00362
00363
00364
00365
00366 else
00367 {
00368 #if DEVELOPER
00369 if (theJoin->networkTest)
00370 {
00371 EngineData(theEnv)->leftToRightComparisons++;
00372 EngineData(theEnv)->findNextConflictingComparisons++;
00373 }
00374 #endif
00375 EngineData(theEnv)->GlobalRHSBinds = possibleConflicts;
00376
00377 result = EvaluateJoinExpression(theEnv,theJoin->networkTest,theJoin);
00378 if (EvaluationData(theEnv)->EvaluationError)
00379 {
00380 result = TRUE;
00381 EvaluationData(theEnv)->EvaluationError = FALSE;
00382 }
00383
00384 #if DEVELOPER
00385 if (result != FALSE)
00386 { EngineData(theEnv)->leftToRightSucceeds++; }
00387 #endif
00388 }
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398 if (result != FALSE)
00399 {
00400 AddBlockedLink(theBind,possibleConflicts);
00401 EngineData(theEnv)->GlobalLHSBinds = oldLHSBinds;
00402 EngineData(theEnv)->GlobalRHSBinds = oldRHSBinds;
00403 EngineData(theEnv)->GlobalJoin = oldJoin;
00404 return(TRUE);
00405 }
00406 }
00407
00408 if (restore)
00409 {
00410 EngineData(theEnv)->GlobalLHSBinds = oldLHSBinds;
00411 EngineData(theEnv)->GlobalRHSBinds = oldRHSBinds;
00412 EngineData(theEnv)->GlobalJoin = oldJoin;
00413 }
00414
00415
00416
00417
00418
00419 return(FALSE);
00420 }
00421
00422
00423
00424
00425
00426
00427
00428 static intBool PartialMatchDefunct(
00429 void *theEnv,
00430 struct partialMatch *thePM)
00431 {
00432 register unsigned short i;
00433 register struct patternEntity * thePE;
00434
00435 for (i = 0 ; i < thePM->bcount ; i++)
00436 {
00437 if (thePM->binds[i].gm.theMatch == NULL) continue;
00438 thePE = thePM->binds[i].gm.theMatch->matchingItem;
00439 if (thePE && thePE->theInfo->synchronized &&
00440 !(*thePE->theInfo->synchronized)(theEnv,thePE))
00441 return(TRUE);
00442 }
00443 return(FALSE);
00444 }
00445
00446
00447
00448
00449
00450 void DeletePartialMatches(
00451 void *theEnv,
00452 struct partialMatch *listOfPMs)
00453 {
00454 struct partialMatch *nextPM;
00455
00456 while (listOfPMs != NULL)
00457 {
00458
00459
00460
00461
00462 nextPM = listOfPMs->nextInMemory;
00463
00464
00465
00466
00467
00468
00469
00470 if (listOfPMs->dependents != NULL) RemoveLogicalSupport(theEnv,listOfPMs);
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485 ReturnPartialMatch(theEnv,listOfPMs);
00486
00487
00488
00489
00490
00491 listOfPMs = nextPM;
00492 }
00493 }
00494
00495
00496
00497
00498
00499 globle void ReturnPartialMatch(
00500 void *theEnv,
00501 struct partialMatch *waste)
00502 {
00503
00504
00505
00506
00507
00508
00509 if (waste->busy)
00510 {
00511 waste->nextInMemory = EngineData(theEnv)->GarbagePartialMatches;
00512 EngineData(theEnv)->GarbagePartialMatches = waste;
00513 return;
00514 }
00515
00516
00517
00518
00519
00520
00521
00522
00523 if (waste->betaMemory == FALSE)
00524 {
00525 if (waste->binds[0].gm.theMatch->markers != NULL)
00526 { ReturnMarkers(theEnv,waste->binds[0].gm.theMatch->markers); }
00527 rm(theEnv,waste->binds[0].gm.theMatch,(int) sizeof(struct alphaMatch));
00528 }
00529
00530
00531
00532
00533
00534
00535
00536 if (waste->dependents != NULL) RemovePMDependencies(theEnv,waste);
00537
00538
00539
00540
00541
00542 rtn_var_struct(theEnv,partialMatch,(int) sizeof(struct genericMatch *) *
00543 (waste->bcount - 1),
00544 waste);
00545 }
00546
00547
00548
00549
00550
00551 globle void DestroyPartialMatch(
00552 void *theEnv,
00553 struct partialMatch *waste)
00554 {
00555
00556
00557
00558
00559
00560
00561
00562 if (waste->betaMemory == FALSE)
00563 {
00564 if (waste->binds[0].gm.theMatch->markers != NULL)
00565 { ReturnMarkers(theEnv,waste->binds[0].gm.theMatch->markers); }
00566 rm(theEnv,waste->binds[0].gm.theMatch,(int) sizeof(struct alphaMatch));
00567 }
00568
00569
00570
00571
00572
00573
00574
00575 if (waste->dependents != NULL) DestroyPMDependencies(theEnv,waste);
00576
00577
00578
00579
00580
00581 rtn_var_struct(theEnv,partialMatch,(int) sizeof(struct genericMatch *) *
00582 (waste->bcount - 1),
00583 waste);
00584 }
00585
00586
00587
00588
00589
00590
00591 static void ReturnMarkers(
00592 void *theEnv,
00593 struct multifieldMarker *waste)
00594 {
00595 struct multifieldMarker *temp;
00596
00597 while (waste != NULL)
00598 {
00599 temp = waste->next;
00600 rtn_struct(theEnv,multifieldMarker,waste);
00601 waste = temp;
00602 }
00603 }
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613 globle void FlushGarbagePartialMatches(
00614 void *theEnv)
00615 {
00616 struct partialMatch *pmPtr;
00617 struct alphaMatch *amPtr;
00618
00619
00620
00621
00622
00623
00624 while (EngineData(theEnv)->GarbageAlphaMatches != NULL)
00625 {
00626 amPtr = EngineData(theEnv)->GarbageAlphaMatches->next;
00627 rtn_struct(theEnv,alphaMatch,EngineData(theEnv)->GarbageAlphaMatches);
00628 EngineData(theEnv)->GarbageAlphaMatches = amPtr;
00629 }
00630
00631
00632
00633
00634
00635
00636 while (EngineData(theEnv)->GarbagePartialMatches != NULL)
00637 {
00638
00639
00640
00641
00642 pmPtr = EngineData(theEnv)->GarbagePartialMatches->nextInMemory;
00643
00644
00645
00646
00647
00648
00649 EngineData(theEnv)->GarbagePartialMatches->busy = FALSE;
00650 ReturnPartialMatch(theEnv,EngineData(theEnv)->GarbagePartialMatches);
00651 EngineData(theEnv)->GarbagePartialMatches = pmPtr;
00652 }
00653 }
00654
00655 #endif
00656