📄 rulebld.c
字号:
trackNode = tempNode; } /*================================================*/ /* If none of the previous conditions have been */ /* met, then there is an internal error in CLIPS. */ /*================================================*/ else { CLIPSSystemError("BUILD",1); ExitCLIPS(4); } } /*====================================*/ /* Check the next pattern in the LHS. */ /*====================================*/ theLHS = theLHS->bottom; } } /********************************************************************//* FindShareableJoin: Determines whether a join exists that can be *//* reused for the join currently being added to the join network. *//* Returns a pointer to the join to be shared if one if found, *//* otherwise returns a NULL pointer. *//********************************************************************/static struct joinNode *FindShareableJoin(listOfJoins,rhsStruct,firstJoin,negatedRHS, isLogical,joinTest, endDepth,currentDepth,lastIteration, nandReconnect) struct joinNode *listOfJoins; VOID *rhsStruct; int firstJoin; int negatedRHS; int isLogical; struct expr *joinTest; int endDepth, currentDepth, lastIteration; struct joinNode **nandReconnect; { /*========================================*/ /* Loop through all of the joins in the */ /* list of potential candiates for reuse. */ /*========================================*/ while (listOfJoins != NULL) { /*=========================================================*/ /* If the join being tested for reuse is connected on the */ /* RHS to the end node of the pattern node associated with */ /* the join to be added, then determine if the join can */ /* be reused. If so, return the join. */ /*=========================================================*/ if (listOfJoins->rightSideEntryStructure == rhsStruct) { if (TestJoinForReuse(listOfJoins,firstJoin,negatedRHS,isLogical, joinTest,endDepth,currentDepth, lastIteration,nandReconnect)) { return(listOfJoins); } } /*====================================================*/ /* Move on to the next potential candidate. Note that */ /* the rightMatchNode link is used for traversing */ /* through the candidates for the first join of a */ /* rule and that rightDriveNode link is used for */ /* traversing through the candidates for subsequent */ /* joins of a rule. */ /*====================================================*/ if (firstJoin) { listOfJoins = listOfJoins->rightMatchNode; } else { listOfJoins = listOfJoins->rightDriveNode; } } /*================================*/ /* Return a NULL pointer, since a */ /* reusable join was not found. */ /*================================*/ return(NULL); } /**************************************************************//* TestJoinForReuse: Determines if the specified join can be *//* shared with a join being added for a rule being defined. *//* Returns TRUE if the join can be shared, otherwise FALSE. *//**************************************************************/static int TestJoinForReuse(testJoin,firstJoin,negatedRHS,isLogical,joinTest, endDepth,currentDepth,lastIteration,nandReconnect) struct joinNode *testJoin; int firstJoin; int negatedRHS; int isLogical; struct expr *joinTest; int endDepth, currentDepth, lastIteration; struct joinNode **nandReconnect; { /*==================================================*/ /* The first join of a rule may only be shared with */ /* a join that has its firstJoin field set to TRUE. */ /*==================================================*/ if (testJoin->firstJoin != firstJoin) return(CLIPS_FALSE); /*========================================================*/ /* A join connected to a not CE may only be shared with a */ /* join that has its patternIsNegated field set to TRUE. */ /*========================================================*/ if (testJoin->patternIsNegated != negatedRHS) return(CLIPS_FALSE); /*==========================================================*/ /* If the join added is associated with a logical CE, then */ /* either the join to be shared must be associated with a */ /* logical CE or the beta memory must be empty (since */ /* joins associate an extra field with each partial match). */ /*==========================================================*/ if ((isLogical == CLIPS_TRUE) && (testJoin->logicalJoin == CLIPS_FALSE) && (testJoin->beta != NULL)) { return(CLIPS_FALSE); } /*===============================================================*/ /* The expression associated with the join must be identical to */ /* the networkTest expression stored with the join to be shared. */ /*===============================================================*/ if (IdenticalExpression(testJoin->networkTest,joinTest) != CLIPS_TRUE) { return(CLIPS_FALSE); } /*==============================================================*/ /* If the join being added enters another join from the right, */ /* then the series of "joins from the right" for the join being */ /* added must match the series of "joins from the right" for */ /* the join being tested for reuse (i.e. the LHS connections */ /* from other joins must be identical for each of the joins in */ /* the series of "joins from the right." */ /*==============================================================*/ for (; endDepth < currentDepth; currentDepth--) { testJoin = testJoin->nextLevel; if (testJoin == NULL) return(CLIPS_FALSE); if (testJoin->joinFromTheRight == CLIPS_FALSE) { return(CLIPS_FALSE); } else if (nandReconnect[currentDepth-2] != testJoin->lastLevel) { return(CLIPS_FALSE); } } /*=============================================================*/ /* The last join of a rule cannot be shared with the last join */ /* of another rule. A join cannot be used as the last join of */ /* a rule if it already has partial matches in its beta memory */ /* (because of the extra slot used to point at activations). */ /*=============================================================*/ if (lastIteration) { if (testJoin->ruleToActivate != NULL) return(CLIPS_FALSE); if (testJoin->beta != NULL) return(CLIPS_FALSE); } /*===========================================================================*/ /* A join cannot be shared if it is not the last join for a rule and shares */ /* part, but not all, of a series of joins connected to other joins from the */ /* right. This is because the data structure for joins can only point to */ /* either a single join that is entered from the right or a series of joins */ /* that are entered from the left, but not both. (The last join of a rule */ /* does not require any links to other joins so it can be shared). */ /*===========================================================================*/ if ((! lastIteration) && (testJoin->nextLevel != NULL)) { if (testJoin->nextLevel->joinFromTheRight == CLIPS_TRUE) { if (((struct joinNode *) testJoin->nextLevel->rightSideEntryStructure) == testJoin) { return(CLIPS_FALSE); } } } /*=============================================*/ /* The join can be shared since all conditions */ /* for sharing have been satisfied. */ /*=============================================*/ return(CLIPS_TRUE); } /*************************************************************************//* CreateNewJoin: Creates a new join and links it into the join network. *//*************************************************************************/static struct joinNode *CreateNewJoin(joinTest,lhsEntryStruct,rhsEntryStruct, joinFromTheRight,negatedRHSPattern) struct expr *joinTest; struct joinNode *lhsEntryStruct; VOID *rhsEntryStruct; int joinFromTheRight; int negatedRHSPattern; { struct joinNode *newJoin; /*===============================================*/ /* If compilations are being watch, print +j to */ /* indicate that a new join has been created for */ /* this pattern of the rule (i.e. a join could */ /* not be shared with another rule. */ /*===============================================*/ #if DEBUGGING_FUNCTIONS if ((GetWatchItem("compilations") == CLIPS_TRUE) && GetPrintWhileLoading()) { PrintCLIPS(WDIALOG,"+j"); }#endif /*========================================================*/ /* Create the new join and initialize some of its values. */ /*========================================================*/ newJoin = get_struct(joinNode); newJoin->beta = NULL; newJoin->nextLevel = NULL; newJoin->joinFromTheRight = joinFromTheRight; newJoin->patternIsNegated = negatedRHSPattern;#if INCREMENTAL_RESET newJoin->initialize = GetIncrementalReset();#else newJoin->initialize = CLIPS_FALSE;#endif newJoin->logicalJoin = CLIPS_FALSE; newJoin->ruleToActivate = NULL; /*==============================================*/ /* Install the expressions used to determine */ /* if a partial match satisfies the constraints */ /* associated with this join. */ /*==============================================*/ newJoin->networkTest = AddHashedExpression(joinTest); /*============================================================*/ /* Initialize the values associated with the LHS of the join. */ /*============================================================*/ newJoin->lastLevel = lhsEntryStruct; if (lhsEntryStruct == NULL) { newJoin->firstJoin = CLIPS_TRUE; newJoin->depth = 1; newJoin->rightDriveNode = NULL; } else { newJoin->firstJoin = CLIPS_FALSE; newJoin->depth = lhsEntryStruct->depth; newJoin->depth++; /* To work around Sparcworks C compiler bug */ newJoin->rightDriveNode = lhsEntryStruct->nextLevel; lhsEntryStruct->nextLevel = newJoin; } /*=======================================================*/ /* Initialize the pointer values associated with the RHS */ /* of the join (both for the new join and the join or */ /* pattern which enters this join from the right. */ /*=======================================================*/ newJoin->rightSideEntryStructure = rhsEntryStruct; if (joinFromTheRight) { newJoin->rightMatchNode = NULL; ((struct joinNode *) rhsEntryStruct)->nextLevel = newJoin; } else { newJoin->rightMatchNode = ((struct patternNodeHeader *) rhsEntryStruct)->entryJoin; ((struct patternNodeHeader *) rhsEntryStruct)->entryJoin = newJoin; } /*================================*/ /* Return the newly created join. */ /*================================*/ return(newJoin); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -