globle void PNLDrive( void *theEnv, struct joinNode *join, struct partialMatch *binds) { struct joinNode *listOfJoins; struct alphaMatch *tempAlpha; /*=======================================================*/ /* Create a pseudo-fact representing the facts which did */ /* not match the not CE associated with this join. */ /*=======================================================*/ tempAlpha = get_struct(theEnv,alphaMatch); tempAlpha->next = NULL; tempAlpha->matchingItem = NULL; tempAlpha->markers = NULL; /*===============================================*/ /* Store the pointer to the pseudo-fact directly */ /* in the beta memory partial match. */ /*===============================================*/ binds->counterf = FALSE; binds->binds[binds->bcount - 1].gm.theMatch = tempAlpha; /*====================================================*/ /* Activate the rule satisfied by this partial match. */ /*====================================================*/ if (join->ruleToActivate != NULL) AddActivation(theEnv,join->ruleToActivate,binds); /*========================================================*/ /* Send the merged partial match to all descendent joins. */ /*========================================================*/ listOfJoins = join->nextLevel; if (listOfJoins != NULL) { if (((struct joinNode *) (listOfJoins->rightSideEntryStructure)) == join) { NetworkAssert(theEnv,binds,listOfJoins,RHS); } else while (listOfJoins != NULL) { NetworkAssert(theEnv,binds,listOfJoins,LHS); listOfJoins = listOfJoins->rightDriveNode; } } }
static void PPDrive( void *theEnv, struct partialMatch *lhsBinds, struct partialMatch *rhsBinds, struct joinNode *join) { struct partialMatch *linker; struct joinNode *listOfJoins; /*==================================================*/ /* Merge the alpha and beta memory partial matches. */ /*==================================================*/ linker = MergePartialMatches(theEnv,lhsBinds,rhsBinds, (join->ruleToActivate == NULL) ? 0 : 1, (int) join->logicalJoin); /*=======================================================*/ /* Add the partial match to the beta memory of the join. */ /*=======================================================*/ linker->next = join->beta; join->beta = linker; /*====================================================*/ /* Activate the rule satisfied by this partial match. */ /*====================================================*/ if (join->ruleToActivate != NULL) AddActivation(theEnv,join->ruleToActivate,linker); /*================================================*/ /* Send the new partial match to all child joins. */ /*================================================*/ listOfJoins = join->nextLevel; if (listOfJoins != NULL) { if (((struct joinNode *) (listOfJoins->rightSideEntryStructure)) == join) { NetworkAssert(theEnv,linker,listOfJoins,RHS); } else while (listOfJoins != NULL) { NetworkAssert(theEnv,linker,listOfJoins,LHS); listOfJoins = listOfJoins->rightDriveNode; } } return; }
static void ResetDefrulesPrime( void *theEnv) { struct joinLink *theLink; struct partialMatch *notParent; for (theLink = DefruleData(theEnv)->RightPrimeJoins; theLink != NULL; theLink = theLink->next) { NetworkAssert(theEnv,theLink->join->rightMemory->beta[0],theLink->join); } for (theLink = DefruleData(theEnv)->LeftPrimeJoins; theLink != NULL; theLink = theLink->next) { if ((theLink->join->patternIsNegated || theLink->join->joinFromTheRight) && (! theLink->join->patternIsExists)) { notParent = theLink->join->leftMemory->beta[0]; if (theLink->join->secondaryNetworkTest != NULL) { if (EvaluateSecondaryNetworkTest(theEnv,notParent,theLink->join) == FALSE) { continue; } } notParent->marker = NULL; EPMDrive(theEnv,notParent,theLink->join); } } }
static void ProcessFactAlphaMatch( void *theEnv, struct fact *theFact, struct multifieldMarker *theMarks, struct factPatternNode *thePattern) { struct partialMatch *theMatch; struct patternMatch *listOfMatches; struct joinNode *listOfJoins; /*===========================================*/ /* Create the partial match for the pattern. */ /*===========================================*/ theMatch = CreateAlphaMatch(theEnv,theFact,theMarks,(struct patternNodeHeader *) &thePattern->header); /*=======================================================*/ /* Add the pattern to the list of matches for this fact. */ /*=======================================================*/ listOfMatches = (struct patternMatch *) theFact->list; theFact->list = (void *) get_struct(theEnv,patternMatch); ((struct patternMatch *) theFact->list)->next = listOfMatches; ((struct patternMatch *) theFact->list)->matchingPattern = (struct patternNodeHeader *) thePattern; ((struct patternMatch *) theFact->list)->theMatch = theMatch; /*================================================================*/ /* Send the partial match to the joins connected to this pattern. */ /*================================================================*/ for (listOfJoins = thePattern->header.entryJoin; listOfJoins != NULL; listOfJoins = listOfJoins->rightMatchNode) { NetworkAssert(theEnv,theMatch,listOfJoins,RHS); } }
static void PrimeJoin( void *theEnv, struct joinNode *joinPtr) { struct partialMatch *theList; /*===========================================================*/ /* If the join is the first join of a rule, then send all of */ /* the partial matches from the alpha memory of the pattern */ /* associated with this join to the join for processing and */ /* the priming process is then complete. */ /*===========================================================*/ if (joinPtr->firstJoin == TRUE) { for (theList = ((struct patternNodeHeader *) joinPtr->rightSideEntryStructure)->alphaMemory; theList != NULL; theList = theList->next) { NetworkAssert(theEnv,theList,joinPtr,RHS); } return; } /*======================================================*/ /* If the join already has partial matches in its beta */ /* memory, then don't bother priming it. I don't recall */ /* if this situation is possible. */ /*======================================================*/ if (joinPtr->beta != NULL) return; /*================================================================*/ /* Send all partial matches from the preceding join to this join. */ /*================================================================*/ for (theList = joinPtr->lastLevel->beta; theList != NULL; theList = theList->next) { if (! theList->counterf) /* 6.05 incremental reset bug fix */ { NetworkAssert(theEnv,theList,joinPtr,LHS); } } }
static void DriveRetractions() { struct rdriveinfo *tempDR; struct joinNode *joinPtr; while (DriveRetractionList != NULL) { for (joinPtr = DriveRetractionList->jlist; joinPtr != NULL; joinPtr = joinPtr->rightDriveNode) { NetworkAssert(DriveRetractionList->link,joinPtr,LHS); } tempDR = DriveRetractionList->next; rtn_struct(rdriveinfo,DriveRetractionList); DriveRetractionList = tempDR; } }
static void DriveRetractions( void *theEnv) { struct rdriveinfo *tempDR; struct joinNode *joinPtr; while (EngineData(theEnv)->DriveRetractionList != NULL) { for (joinPtr = EngineData(theEnv)->DriveRetractionList->jlist; joinPtr != NULL; joinPtr = joinPtr->rightDriveNode) { NetworkAssert(theEnv,EngineData(theEnv)->DriveRetractionList->link,joinPtr,LHS); } tempDR = EngineData(theEnv)->DriveRetractionList->next; rtn_struct(theEnv,rdriveinfo,EngineData(theEnv)->DriveRetractionList); EngineData(theEnv)->DriveRetractionList = tempDR; } }
void NegEntryRetract( struct joinNode *theJoin, struct partialMatch *theMatch, int duringRetract) { struct partialMatch *theLHS; int result; struct rdriveinfo *tempDR; struct alphaMatch *tempAlpha; struct joinNode *listOfJoins; /*===============================================*/ /* Loop through all LHS partial matches checking */ /* for sets that satisfied the join expression. */ /*===============================================*/ for (theLHS = theJoin->beta; theLHS != NULL; theLHS = theLHS->next) { /*===========================================================*/ /* Don't bother checking partial matches that are satisfied. */ /* We're looking for joins from which the removal of a */ /* partial match would satisfy the join. */ /*===========================================================*/ if (theLHS->counterf == FALSE) continue; /*==================================================*/ /* If the partial match being removed isn't the one */ /* preventing the LHS partial match from being */ /* satisifed, then don't bother processing it. */ /*==================================================*/ if (theLHS->binds[theLHS->bcount - 1].gm.theValue != (void *) theMatch) continue; /*======================================================*/ /* Try to find another RHS partial match which prevents */ /* the LHS partial match from being satisifed. */ /*======================================================*/ theLHS->binds[theLHS->bcount - 1].gm.theValue = NULL; result = FindNextConflictingAlphaMatch(theLHS,theMatch->next,theJoin); /*=========================================================*/ /* If the LHS partial match now has no RHS partial matches */ /* that conflict with it, then it satisfies the conditions */ /* of the RHS not CE. Create a partial match and send it */ /* to the joins below. */ /*=========================================================*/ if (result == FALSE) { /*===============================*/ /* Create the new partial match. */ /*===============================*/ theLHS->counterf = FALSE; tempAlpha = get_struct(alphaMatch); tempAlpha->next = NULL; tempAlpha->matchingItem = NULL; tempAlpha->markers = NULL; theLHS->binds[theLHS->bcount - 1].gm.theMatch = tempAlpha; /*==============================================*/ /* If partial matches from this join correspond */ /* to a rule activation, then add an activation */ /* to the agenda. */ /*==============================================*/ if (theJoin->ruleToActivate != NULL) { AddActivation(theJoin->ruleToActivate,theLHS); } /*=======================================================*/ /* Send the partial match to the list of joins following */ /* this join. If we're in the middle of a retract, add */ /* the partial match to the list of join activities that */ /* need to be processed later. If we're doing an assert, */ /* then the join activity can be processed immediately. */ /*=======================================================*/ listOfJoins = theJoin->nextLevel; if (listOfJoins != NULL) { if (((struct joinNode *) (listOfJoins->rightSideEntryStructure)) == theJoin) { NetworkAssert(theLHS,listOfJoins,RHS); } else { if (duringRetract) { tempDR = get_struct(rdriveinfo); tempDR->link = theLHS; tempDR->jlist = theJoin->nextLevel; tempDR->next = DriveRetractionList; DriveRetractionList = tempDR; } else while (listOfJoins != NULL) { NetworkAssert(theLHS,listOfJoins,LHS); listOfJoins = listOfJoins->rightDriveNode; } } } } } }
static void PrimeJoinFromRightMemory( void *theEnv, struct joinNode *joinPtr) { struct partialMatch *theList, *linker; unsigned long b; struct betaMemory *theMemory; unsigned long hashValue; struct joinLink *tempLink; struct partialMatch *notParent; /*=======================================*/ /* This should be a join from the right. */ /*=======================================*/ if (joinPtr->joinFromTheRight == FALSE) { return; } /*========================================*/ /* Find another beta memory from which we */ /* can retrieve the partial matches. */ /*========================================*/ tempLink = ((struct joinNode *) joinPtr->rightSideEntryStructure)->nextLinks; while (tempLink != NULL) { if ((tempLink->join != joinPtr) && (tempLink->join->initialize == FALSE)) { break; } tempLink = tempLink->next; } if (tempLink == NULL) { if (joinPtr->firstJoin && (joinPtr->rightMemory->beta[0] == NULL) && (! joinPtr->patternIsExists)) { notParent = joinPtr->leftMemory->beta[0]; if (joinPtr->secondaryNetworkTest != NULL) { if (EvaluateSecondaryNetworkTest(theEnv,notParent,joinPtr) == FALSE) { return; } } EPMDrive(theEnv,notParent,joinPtr); } return; } if (tempLink->enterDirection == LHS) { theMemory = tempLink->join->leftMemory; } else { theMemory = tempLink->join->rightMemory; } /*============================================*/ /* Send all partial matches from the selected */ /* beta memory to the new join. */ /*============================================*/ for (b = 0; b < theMemory->size; b++) { for (theList = theMemory->beta[b]; theList != NULL; theList = theList->nextInMemory) { linker = CopyPartialMatch(theEnv,theList); if (joinPtr->rightHash != NULL) { hashValue = BetaMemoryHashValue(theEnv,joinPtr->rightHash,linker,NULL,joinPtr); } else { hashValue = 0; } UpdateBetaPMLinks(theEnv,linker,theList->leftParent,theList->rightParent,joinPtr,hashValue,RHS); NetworkAssert(theEnv,linker,joinPtr); } } if (joinPtr->firstJoin && (joinPtr->rightMemory->beta[0] == NULL) && (! joinPtr->patternIsExists)) { notParent = joinPtr->leftMemory->beta[0]; if (joinPtr->secondaryNetworkTest != NULL) { if (EvaluateSecondaryNetworkTest(theEnv,notParent,joinPtr) == FALSE) { return; } } EPMDrive(theEnv,notParent,joinPtr); } }
static void PrimeJoinFromLeftMemory( void *theEnv, struct joinNode *joinPtr) { struct partialMatch *theList, *linker; struct alphaMemoryHash *listOfHashNodes; unsigned long b; unsigned long hashValue; struct betaMemory *theMemory; struct partialMatch *notParent; struct joinLink *tempLink; /*===========================================================*/ /* If the join is the first join of a rule, then send all of */ /* the partial matches from the alpha memory of the pattern */ /* associated with this join to the join for processing and */ /* the priming process is then complete. */ /*===========================================================*/ if (joinPtr->firstJoin == TRUE) { if (joinPtr->rightSideEntryStructure == NULL) { NetworkAssert(theEnv,joinPtr->rightMemory->beta[0],joinPtr); } else if (joinPtr->patternIsNegated) { notParent = joinPtr->leftMemory->beta[0]; if (joinPtr->secondaryNetworkTest != NULL) { if (EvaluateSecondaryNetworkTest(theEnv,notParent,joinPtr) == FALSE) { return; } } for (listOfHashNodes = ((struct patternNodeHeader *) joinPtr->rightSideEntryStructure)->firstHash; listOfHashNodes != NULL; listOfHashNodes = listOfHashNodes->nextHash) { if (listOfHashNodes->alphaMemory != NULL) { AddBlockedLink(notParent,listOfHashNodes->alphaMemory); return; } } EPMDrive(theEnv,notParent,joinPtr); } else { for (listOfHashNodes = ((struct patternNodeHeader *) joinPtr->rightSideEntryStructure)->firstHash; listOfHashNodes != NULL; listOfHashNodes = listOfHashNodes->nextHash) { for (theList = listOfHashNodes->alphaMemory; theList != NULL; theList = theList->nextInMemory) { NetworkAssert(theEnv,theList,joinPtr); } } } return; } /*========================================*/ /* Find another beta memory from which we */ /* can retrieve the partial matches. */ /*========================================*/ tempLink = joinPtr->lastLevel->nextLinks; while (tempLink != NULL) { if ((tempLink->join != joinPtr) && (tempLink->join->initialize == FALSE)) { break; } tempLink = tempLink->next; } if (tempLink == NULL) return; if (tempLink->enterDirection == LHS) { theMemory = tempLink->join->leftMemory; } else { theMemory = tempLink->join->rightMemory; } /*============================================*/ /* Send all partial matches from the selected */ /* beta memory to the new join. */ /*============================================*/ for (b = 0; b < theMemory->size; b++) { for (theList = theMemory->beta[b]; theList != NULL; theList = theList->nextInMemory) { linker = CopyPartialMatch(theEnv,theList); if (joinPtr->leftHash != NULL) { hashValue = BetaMemoryHashValue(theEnv,joinPtr->leftHash,linker,NULL,joinPtr); } else { hashValue = 0; } UpdateBetaPMLinks(theEnv,linker,theList->leftParent,theList->rightParent,joinPtr,hashValue,LHS); NetworkAssertLeft(theEnv,linker,joinPtr); } } }
static void EmptyDrive( struct joinNode *join, struct partialMatch *rhsBinds) { struct partialMatch *linker; struct joinNode *listOfJoins; int joinExpr; /*======================================================*/ /* Determine if the alpha memory partial match satifies */ /* the join expression. If it doesn't then no further */ /* action is taken. */ /*======================================================*/ if (join->networkTest != NULL) { joinExpr = EvaluateJoinExpression(join->networkTest,NULL,rhsBinds,join); EvaluationError = FALSE; if (joinExpr == FALSE) return; } /*===========================================================*/ /* The first join of a rule cannot be connected to a NOT CE. */ /*===========================================================*/ if (join->patternIsNegated == TRUE) { SystemError("DRIVE",2); ExitRouter(EXIT_FAILURE); } /*=========================================================*/ /* If the join's RHS entry is associated with a pattern CE */ /* (positive entry), then copy the alpha memory partial */ /* match and send it to all child joins. */ /*=========================================================*/ linker = CopyPartialMatch(rhsBinds, (join->ruleToActivate == NULL) ? 0 : 1, (int) join->logicalJoin); /*=======================================================*/ /* Add the partial match to the beta memory of the join. */ /*=======================================================*/ linker->next = join->beta; join->beta = linker; /*====================================================*/ /* Activate the rule satisfied by this partial match. */ /*====================================================*/ if (join->ruleToActivate != NULL) AddActivation(join->ruleToActivate,linker); /*============================================*/ /* Send the partial match to all child joins. */ /*============================================*/ listOfJoins = join->nextLevel; while (listOfJoins != NULL) { NetworkAssert(linker,listOfJoins,LHS); listOfJoins = listOfJoins->rightDriveNode; } }