📄 drive.c
字号:
/* Initialize some of the global variables */ /* used when evaluating expressions. */ /*=========================================*/ oldLHSBinds = EngineData(theEnv)->GlobalLHSBinds; oldRHSBinds = EngineData(theEnv)->GlobalRHSBinds; oldJoin = EngineData(theEnv)->GlobalJoin; EngineData(theEnv)->GlobalLHSBinds = lbinds; EngineData(theEnv)->GlobalRHSBinds = rbinds; EngineData(theEnv)->GlobalJoin = joinPtr; /*=========================================*/ /* Evaluate each of the expressions linked */ /* together in the join expression. */ /*=========================================*/ while (hashExpr != NULL) { /*================================*/ /* Evaluate a primitive function. */ /*================================*/ if ((EvaluationData(theEnv)->PrimitivesArray[hashExpr->type] == NULL) ? FALSE : EvaluationData(theEnv)->PrimitivesArray[hashExpr->type]->evaluateFunction != NULL) { struct expr *oldArgument; oldArgument = EvaluationData(theEnv)->CurrentExpression; EvaluationData(theEnv)->CurrentExpression = hashExpr; (*EvaluationData(theEnv)->PrimitivesArray[hashExpr->type]->evaluateFunction)(theEnv,hashExpr->value,&theResult); EvaluationData(theEnv)->CurrentExpression = oldArgument; } /*==========================================================*/ /* Evaluate all other expressions using EvaluateExpression. */ /*==========================================================*/ else { EvaluateExpression(theEnv,hashExpr,&theResult); } switch (theResult.type) { case STRING: case SYMBOL: case INSTANCE_NAME: hashValue += (((SYMBOL_HN *) theResult.value)->bucket * multiplier); break; case INTEGER: hashValue += (((INTEGER_HN *) theResult.value)->bucket * multiplier); break; case FLOAT: hashValue += (((FLOAT_HN *) theResult.value)->bucket * multiplier); break; } /*==============================================*/ /* Move to the next expression to be evaluated. */ /*==============================================*/ hashExpr = hashExpr->nextArg; multiplier = multiplier * 509; i++; } /*=======================================*/ /* Restore some of the global variables. */ /*=======================================*/ EngineData(theEnv)->GlobalLHSBinds = oldLHSBinds; EngineData(theEnv)->GlobalRHSBinds = oldRHSBinds; EngineData(theEnv)->GlobalJoin = oldJoin; /*=================================================*/ /* Return the result of evaluating the expression. */ /*=================================================*/ return(hashValue); }/*******************************************************************//* PPDrive: Handles the merging of an alpha memory partial match *//* with a beta memory partial match for a join that has positive *//* LHS entry and positive RHS entry. The partial matches being *//* merged have previously been checked to determine that they *//* satisify the constraints for the join. Once merged, the new *//* partial match is sent to each child join of the join from *//* which the merge took place. *//*******************************************************************/globle void PPDrive( void *theEnv, struct partialMatch *lhsBinds, struct partialMatch *rhsBinds, struct joinNode *join) { struct partialMatch *linker; struct joinLink *listOfJoins; unsigned long hashValue; /*================================================*/ /* Send the new partial match to all child joins. */ /*================================================*/ listOfJoins = join->nextLinks; if (listOfJoins == NULL) return; /*===============================================================*/ /* In the current implementation, all children of this join must */ /* be entered from the same side (either all left or all right). */ /*===============================================================*/ while (listOfJoins != NULL) { /*==================================================*/ /* Merge the alpha and beta memory partial matches. */ /*==================================================*/ linker = MergePartialMatches(theEnv,lhsBinds,rhsBinds); /*================================================*/ /* Determine the hash value of the partial match. */ /*================================================*/ if (listOfJoins->enterDirection == LHS) { if (listOfJoins->join->leftHash != NULL) { hashValue = BetaMemoryHashValue(theEnv,listOfJoins->join->leftHash,linker,NULL,listOfJoins->join,NULL); } else { hashValue = 0; } } else { if (listOfJoins->join->rightHash != NULL) { hashValue = BetaMemoryHashValue(theEnv,listOfJoins->join->rightHash,linker,NULL,listOfJoins->join,NULL); } else { hashValue = 0; } } /*=======================================================*/ /* Add the partial match to the beta memory of the join. */ /*=======================================================*/ UpdateBetaPMLinks(theEnv,linker,lhsBinds,rhsBinds,listOfJoins->join,hashValue,listOfJoins->enterDirection); if (listOfJoins->enterDirection == LHS) { NetworkAssertLeft(theEnv,linker,listOfJoins->join); } else { NetworkAssertRight(theEnv,linker,listOfJoins->join); } listOfJoins = listOfJoins->next; } return; }/***********************************************************************//* EPMDrive: Drives an empty partial match to the next level of joins. *//* An empty partial match is usually associated with a negated CE *//* that is the first CE of a rule. *//***********************************************************************/globle void EPMDrive( void *theEnv, struct partialMatch *parent, struct joinNode *join) { struct partialMatch *linker; struct joinLink *listOfJoins; listOfJoins = join->nextLinks; if (listOfJoins == NULL) return; while (listOfJoins != NULL) { linker = CreateEmptyPartialMatch(theEnv); UpdateBetaPMLinks(theEnv,linker,parent,NULL,listOfJoins->join,0,listOfJoins->enterDirection); if (listOfJoins->enterDirection == LHS) { NetworkAssertLeft(theEnv,linker,listOfJoins->join); } else { NetworkAssertRight(theEnv,linker,listOfJoins->join); } listOfJoins = listOfJoins->next; } }/***************************************************************//* EmptyDrive: Handles the entry of a alpha memory partial *//* match from the RHS of a join that is the first join of *//* a rule (i.e. a join that cannot be entered from the LHS). *//***************************************************************/static void EmptyDrive( void *theEnv, struct joinNode *join, struct partialMatch *rhsBinds) { struct partialMatch *linker, *existsParent = NULL, *notParent = NULL; struct joinLink *listOfJoins; int joinExpr; unsigned long hashValue; struct partialMatch *oldLHSBinds; struct partialMatch *oldRHSBinds; struct joinNode *oldJoin; /*======================================================*/ /* Determine if the alpha memory partial match satifies */ /* the join expression. If it doesn't then no further */ /* action is taken. */ /*======================================================*/ join->memoryCompares++; if (join->networkTest != NULL) {#if DEVELOPER if (join->networkTest) { EngineData(theEnv)->rightToLeftComparisons++; }#endif oldLHSBinds = EngineData(theEnv)->GlobalLHSBinds; oldRHSBinds = EngineData(theEnv)->GlobalRHSBinds; oldJoin = EngineData(theEnv)->GlobalJoin; EngineData(theEnv)->GlobalLHSBinds = NULL; EngineData(theEnv)->GlobalRHSBinds = rhsBinds; EngineData(theEnv)->GlobalJoin = join; joinExpr = EvaluateJoinExpression(theEnv,join->networkTest,join); EvaluationData(theEnv)->EvaluationError = FALSE; EngineData(theEnv)->GlobalLHSBinds = oldLHSBinds; EngineData(theEnv)->GlobalRHSBinds = oldRHSBinds; EngineData(theEnv)->GlobalJoin = oldJoin; if (joinExpr == FALSE) return; } /*========================================================*/ /* Handle a negated first pattern or join from the right. */ /*========================================================*/ if (join->patternIsNegated || (join->joinFromTheRight && (! join->patternIsExists))) /* reorder to remove patternIsExists test */ { notParent = join->leftMemory->beta[0]; if (notParent->marker != NULL) { return; } AddBlockedLink(notParent,rhsBinds); if (notParent->children != NULL) { PosEntryRetractBeta(theEnv,notParent,notParent->children); } if (notParent->dependents != NULL) { RemoveLogicalSupport(theEnv,notParent); } return; } /*=====================================================*/ /* For exists CEs used as the first pattern of a rule, */ /* a special partial match in the left memory of the */ /* join is used to track the RHS partial match */ /* satisfying the CE. */ /*=====================================================*/ /* TBD reorder */ if (join->patternIsExists) { existsParent = join->leftMemory->beta[0]; if (existsParent->marker != NULL) { return; } AddBlockedLink(existsParent,rhsBinds); } /*============================================*/ /* Send the partial match to all child joins. */ /*============================================*/ listOfJoins = join->nextLinks; if (listOfJoins == NULL) return; while (listOfJoins != NULL) { /*===================================================================*/ /* An exists CE as the first pattern of a rule can generate at most */ /* one partial match, so if there's already a partial match in the */ /* beta memory nothing further needs to be done. Since there are no */ /* variable bindings which child joins can use for indexing, the */ /* partial matches will always be stored in the bucket with index 0. */ /* Although an exists is associated with a specific fact/instance */ /* (through its rightParent link) that allows it to be satisfied, */ /* the bindings in the partial match will be empty for this CE. */ /*===================================================================*/ if (join->patternIsExists) { linker = CreateEmptyPartialMatch(theEnv); } /*=============================================================*/ /* Othewise just copy the partial match from the alpha memory. */ /*=============================================================*/ else { linker = CopyPartialMatch(theEnv,rhsBinds); } /*================================================*/ /* Determine the hash value of the partial match. */ /*================================================*/ if (listOfJoins->enterDirection == LHS) { if (listOfJoins->join->leftHash != NULL) { hashValue = BetaMemoryHashValue(theEnv,listOfJoins->join->leftHash,linker,NULL,listOfJoins->join,NULL); } else { hashValue = 0; } } else { if (listOfJoins->join->rightHash != NULL) { hashValue = BetaMemoryHashValue(theEnv,listOfJoins->join->rightHash,linker,NULL,listOfJoins->join,NULL); } else { hashValue = 0; } } /*=======================================================*/ /* Add the partial match to the beta memory of the join. */ /*=======================================================*/ if (join->patternIsExists) { UpdateBetaPMLinks(theEnv,linker,existsParent,NULL,listOfJoins->join,hashValue,listOfJoins->enterDirection); } else { UpdateBetaPMLinks(theEnv,linker,NULL,rhsBinds,listOfJoins->join,hashValue,listOfJoins->enterDirection); } if (listOfJoins->enterDirection == LHS) { NetworkAssertLeft(theEnv,linker,listOfJoins->join); } else { NetworkAssertRight(theEnv,linker,listOfJoins->join); } listOfJoins = listOfJoins->next; } } /********************************************************************//* JoinNetErrorMessage: Prints an informational message indicating *//* which join of a rule generated an error when a join expression *//* was being evaluated. *//********************************************************************/static void JoinNetErrorMessage( void *theEnv, struct joinNode *joinPtr) { PrintErrorID(theEnv,"DRIVE",1,TRUE); EnvPrintRouter(theEnv,WERROR,"This error occurred in the join network\n"); EnvPrintRouter(theEnv,WERROR," Problem resides in associated join\n"); /* TBD generate test case for join with JFTR *//* sprintf(buffer," Problem resides in join #%d in rule(s):\n",joinPtr->depth); EnvPrintRouter(theEnv,WERROR,buffer);*/ TraceErrorToRule(theEnv,joinPtr," "); EnvPrintRouter(theEnv,WERROR,"\n"); }#endif /* DEFRULE_CONSTRUCT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -