📄 retract.c
字号:
/*==================================================*/ /* 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 == CLIPS_FALSE) { /*===============================*/ /* Create the new partial match. */ /*===============================*/ theLHS->counterf = CLIPS_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; } } } } } }/**************************************************************//* FindNextConflictingAlphaMatch: Finds the next conflicting *//* partial match in the alpha memory of a join (or the beta *//* memory of a join from the right) that prevents a partial *//* match in the beta memory of the join from being *//* satisfied. *//**************************************************************/static BOOLEAN FindNextConflictingAlphaMatch(theBind,possibleConflicts,theJoin) struct partialMatch *theBind; struct partialMatch *possibleConflicts; struct joinNode *theJoin; { int i, result; /*=====================================================*/ /* If we're dealing with a join from the right, then */ /* we need to check the entire beta memory of the join */ /* from the right (a join doesn't have an end of queue */ /* pointer like a pattern data structure has). */ /*=====================================================*/ if (theJoin->joinFromTheRight) { possibleConflicts = ((struct joinNode *) theJoin->rightSideEntryStructure)->beta; } /*====================================*/ /* Check each of the possible partial */ /* matches which could conflict. */ /*====================================*/ for (; possibleConflicts != NULL; possibleConflicts = possibleConflicts->next) { /*=====================================*/ /* Initially indicate that the partial */ /* match doesn't conflict. */ /*=====================================*/ result = CLIPS_FALSE; /*====================================================*/ /* A partial match with the counterf flag set is not */ /* yet a "real" partial match, so ignore it. When the */ /* counterf flag is set that means that the partial */ /* match is associated with a not CE that has a data */ /* entity preventing it from being satsified. */ /*====================================================*/ if (possibleConflicts->counterf) { /* Do Nothing */ } /* ===================================================== 6.05 Bug Fix It is possible that a pattern entity (e.g., instance) in a partial match is 'out of date' with respect to the lazy evaluation scheme use by negated patterns. In other words, the object may have changed since it was last pushed through the network, and thus the partial match may be invalid. If so, the partial match must be ignored here. ===================================================== */ else if (PartialMatchDefunct(possibleConflicts)) { /* Do Nothing */ } /*==================================================*/ /* If the join doesn't have a network expression to */ /* be evaluated, then partial match conflicts. If */ /* the partial match is retrieved from a join from */ /* the right, the RHS partial match must correspond */ /* to the partial match in the beta memory of the */ /* join being examined (in a join associated with a */ /* not CE, each partial match in the beta memory of */ /* the join corresponds uniquely to a partial match */ /* in either the alpha memory from the RHS or in */ /* the beta memory of a join from the right). */ /*==================================================*/ else if (theJoin->networkTest == NULL) { result = CLIPS_TRUE; if (theJoin->joinFromTheRight) { for (i = 0; i < (int) (theBind->bcount - 1); i++) { if (possibleConflicts->binds[i].gm.theMatch != theBind->binds[i].gm.theMatch) { result = CLIPS_FALSE; break; } } } } /*=================================================*/ /* Otherwise, if the join has a network expression */ /* to evaluate, then evaluate it. */ /*=================================================*/ else { result = EvaluateJoinExpression(theJoin->networkTest,theBind, possibleConflicts,theJoin); if (EvaluationError) { result = CLIPS_TRUE; EvaluationError = CLIPS_FALSE; } } /*==============================================*/ /* If the network expression evaluated to TRUE, */ /* then partial match being examined conflicts. */ /* Point the beta memory partial match to the */ /* conflicting partial match and return TRUE to */ /* indicate a conflict was found. */ /*==============================================*/ if (result != CLIPS_FALSE) { theBind->binds[theBind->bcount - 1].gm.theValue = (VOID *) possibleConflicts; return(CLIPS_TRUE); } } /*========================*/ /* No conflict was found. */ /*========================*/ return(CLIPS_FALSE); } /*************************************************************//* PartialMatchDefunct: Determines if any pattern entities *//* contained within the partial match have changed since *//* this partial match was generated. *//*************************************************************/static BOOLEAN PartialMatchDefunct(thePM) struct partialMatch * thePM; { register int i; register struct patternEntity * thePE; /* Assumes counterf is false */ for (i = 0 ; i < thePM->bcount ; i++) { thePE = thePM->binds[i].gm.theMatch->matchingItem; if (thePE && thePE->theInfo->synchronized && !(*thePE->theInfo->synchronized)(thePE)) return(CLIPS_TRUE); } return(CLIPS_FALSE); }/*************************************************************//* RemovePartialMatches: Searches through a list of partial *//* matches and removes any partial match that contains the *//* specified data entity. *//*************************************************************/static struct partialMatch *RemovePartialMatches(theAlphaNode,listOfPMs,deleteHead, position,returnLast) struct alphaMatch *theAlphaNode; struct partialMatch *listOfPMs; struct partialMatch **deleteHead; int position; struct partialMatch **returnLast; { struct partialMatch *head, *lastPM, *nextPM; struct partialMatch *lastDelete = NULL; /*====================================================*/ /* Initialize pointers used for creating the new list */ /* of partial matches and the list of partial matches */ /* to be deleted. */ /*====================================================*/ head = listOfPMs; lastPM = listOfPMs; *deleteHead = NULL; /*==========================================*/ /* Loop through each of the partial matches */ /* and determine if it needs to be deleted. */ /*==========================================*/ while (listOfPMs != NULL) { if ((listOfPMs->counterf == TRUE) && (position == (listOfPMs->bcount - 1))) { lastPM = listOfPMs; listOfPMs = listOfPMs->next; } /*=====================================================*/ /* Otherwise, if the specified position in the partial */ /* match contains the specified data entity, then */ /* remove the partial match from the list and add it */ /* to a deletion list. */ /*=====================================================*/ else if (listOfPMs->binds[position].gm.theMatch == theAlphaNode) { /*===================================================*/ /* If the partial match has an activation associated */ /* with it, then return the activation. */ /*===================================================*/ if ((listOfPMs->activationf) ? (listOfPMs->binds[listOfPMs->bcount].gm.theValue != NULL) : FALSE) { RemoveActivation((struct activation *) listOfPMs->binds[listOfPMs->bcount].gm.theValue,CLIPS_TRUE,CLIPS_TRUE); } /*==================================================*/ /* If the partial match is at the head of the list */ /* of matches, then use the following deletion code */ /* for the head of the list. */ /*==================================================*/ if (listOfPMs == head) { /*===================================*/ /* Remember the new beginning of the */ /* new list of partial matches. */ /*===================================*/ nextPM = listOfPMs->next;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -