📄 factmch.c
字号:
oldMark = markers; /*===========================================*/ /* Create a new multifield marker and append */ /* it to the end of the current list. */ /*===========================================*/ newMark = get_struct(theEnv,multifieldMarker); newMark->whichField = thePattern->whichField - 1; newMark->where.whichSlotNumber = (short) thePattern->whichSlot; newMark->startPosition = (thePattern->whichField - 1) + offset; newMark->next = NULL; if (endMark == NULL) { markers = newMark; FactData(theEnv)->CurrentPatternMarks = markers; } else { endMark->next = newMark; } /*============================================*/ /* Handle a multifield constraint as the last */ /* constraint of a slot as a special case. */ /*============================================*/ if (thePattern->header.endSlot) { newMark->endPosition = (long) theSlotValue->multifieldLength - (thePattern->leaveFields + 1); /*=======================================================*/ /* Make sure the endPosition is never more than less one */ /* less of the startPosition (a multifield containing no */ /* values. */ /*=======================================================*/ if (newMark->endPosition < newMark->startPosition) { newMark->endPosition = newMark->startPosition - 1; } /*===========================================*/ /* Determine if the constraint is satisfied. */ /*===========================================*/ if (thePattern->header.selector) { if (EvaluatePatternExpression(theEnv,thePattern,thePattern->networkTest->nextArg)) { EvaluateExpression(theEnv,thePattern->networkTest,&theResult); thePattern = FindHashedPatternNode(theEnv,thePattern,theResult.type,theResult.value); if (thePattern != NULL) { success = TRUE; } else { success = FALSE; } } else { success = FALSE; } } else if ((thePattern->networkTest == NULL) ? TRUE : (EvaluatePatternExpression(theEnv,thePattern,thePattern->networkTest))) { success = TRUE; } else { success = FALSE; } if (success) { /*=======================================================*/ /* If a leaf pattern node has been successfully reached, */ /* then the pattern has been satisified. Generate an */ /* alpha match to store in the pattern node. */ /*=======================================================*/ if (thePattern->header.stopNode) { ProcessFactAlphaMatch(theEnv,FactData(theEnv)->CurrentPatternFact,FactData(theEnv)->CurrentPatternMarks,thePattern); } /*=============================================*/ /* Recursively continue pattern matching based */ /* on the multifield binding just generated. */ /*=============================================*/ FactPatternMatch(theEnv,FactData(theEnv)->CurrentPatternFact, thePattern->nextLevel,0,FactData(theEnv)->CurrentPatternMarks,newMark); } /*================================================*/ /* Discard the multifield marker since we've done */ /* all the pattern matching for this binding of */ /* the multifield slot constraint. */ /*================================================*/ rtn_struct(theEnv,multifieldMarker,newMark); if (endMark != NULL) endMark->next = NULL; FactData(theEnv)->CurrentPatternMarks = oldMark; return; } /*==============================================*/ /* Perform matching for nodes beneath this one. */ /*==============================================*/ for (repeatCount = (long) (theSlotValue->multifieldLength - (newMark->startPosition + thePattern->leaveFields)); repeatCount >= 0; repeatCount--) { newMark->endPosition = newMark->startPosition + (repeatCount - 1); if (thePattern->header.selector) { if (EvaluatePatternExpression(theEnv,thePattern,thePattern->networkTest->nextArg)) { EvaluateExpression(theEnv,thePattern->networkTest,&theResult); tempPtr = FindHashedPatternNode(theEnv,thePattern,theResult.type,theResult.value); if (tempPtr != NULL) { FactPatternMatch(theEnv,FactData(theEnv)->CurrentPatternFact, tempPtr->nextLevel,offset + repeatCount - 1, FactData(theEnv)->CurrentPatternMarks,newMark); } } } else if ((thePattern->networkTest == NULL) ? TRUE : (EvaluatePatternExpression(theEnv,thePattern,thePattern->networkTest))) { FactPatternMatch(theEnv,FactData(theEnv)->CurrentPatternFact, thePattern->nextLevel,offset + repeatCount - 1, FactData(theEnv)->CurrentPatternMarks,newMark); } } /*======================================================*/ /* Get rid of the marker created for a multifield node. */ /*======================================================*/ rtn_struct(theEnv,multifieldMarker,newMark); if (endMark != NULL) endMark->next = NULL; FactData(theEnv)->CurrentPatternMarks = oldMark; }/******************************************************//* GetNextFactPatternNode: Returns the next node in a *//* pattern network tree to be traversed. The next *//* node is computed using a depth first traversal. *//******************************************************/static struct factPatternNode *GetNextFactPatternNode( void *theEnv, int finishedMatching, struct factPatternNode *thePattern) { EvaluationData(theEnv)->EvaluationError = FALSE; /*===================================================*/ /* If pattern matching was successful at the current */ /* node in the tree and it's possible to go deeper */ /* into the tree, then move down to the next level. */ /*===================================================*/ if (finishedMatching == FALSE) { if (thePattern->nextLevel != NULL) return(thePattern->nextLevel); } /*================================================*/ /* Keep backing up toward the root of the pattern */ /* network until a side branch can be taken. */ /*================================================*/ while ((thePattern->rightNode == NULL) || ((thePattern->lastLevel != NULL) && (thePattern->lastLevel->header.selector))) { /*========================================*/ /* Back up to check the next side branch. */ /*========================================*/ thePattern = thePattern->lastLevel; /*======================================*/ /* If we branched up from the root, the */ /* entire tree has been traversed. */ /*======================================*/ if (thePattern == NULL) return(NULL); /*======================================*/ /* Skip selector constants and pop back */ /* back to the selector node. */ /*======================================*/ if ((thePattern->lastLevel != NULL) && (thePattern->lastLevel->header.selector)) { thePattern = thePattern->lastLevel; } /*===================================================*/ /* If we branched up to a multifield node, then stop */ /* since these nodes are handled recursively. The */ /* previous call to the pattern matching algorithm */ /* on the stack will handle backing up to the nodes */ /* above the multifield node in the pattern network. */ /*===================================================*/ if (thePattern->header.multifieldNode) return(NULL); } /*==================================*/ /* Move on to the next side branch. */ /*==================================*/ return(thePattern->rightNode); }/*******************************************************//* ProcessFactAlphaMatch: When a fact pattern has been *//* satisfied, this routine creates an alpha match to *//* store in the pattern network and then sends the *//* new alpha match through the join network. *//*******************************************************/static void ProcessFactAlphaMatch( void *theEnv, struct fact *theFact, struct multifieldMarker *theMarks, struct factPatternNode *thePattern) { struct partialMatch *theMatch; struct patternMatch *listOfMatches; struct joinNode *listOfJoins; unsigned long hashValue = 0; /*============================================*/ /* Create the hash value for the alpha match. */ /*============================================*/ hashValue = ComputeRightHashValue(theEnv,&thePattern->header); /*===========================================*/ /* Create the partial match for the pattern. */ /*===========================================*/ theMatch = CreateAlphaMatch(theEnv,theFact,theMarks,(struct patternNodeHeader *) &thePattern->header,hashValue); theMatch->owner = &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); } }/*****************************************************************//* EvaluatePatternExpression: Performs a faster evaluation for *//* fact pattern network expressions than if EvaluateExpression *//* were used directly. *//*****************************************************************/static int EvaluatePatternExpression( void *theEnv, struct factPatternNode *patternPtr, struct expr *theTest) { DATA_OBJECT theResult; struct expr *oldArgument; int rv; /*=====================================*/ /* A pattern node without a constraint */ /* is always satisfied. */ /*=====================================*/ if (theTest == NULL) return(TRUE); /*======================================*/ /* Evaluate pattern network primitives. */ /*======================================*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -