📄 drive.c
字号:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.05 04/09/97 */ /* */ /* DRIVE MODULE */ /*******************************************************//*************************************************************//* Purpose: Handles join network activity associated with *//* with the addition of a data entity such as a fact or *//* instance. *//* *//* Principal Programmer(s): *//* Gary D. Riley *//* *//* Contributing Programmer(s): *//* *//* Revision History: *//* *//*************************************************************/#define _DRIVE_SOURCE_#include <stdio.h>#define _CLIPS_STDIO_#include "setup.h"#if DEFRULE_CONSTRUCT#include "constant.h"#include "clipsmem.h"#include "reteutil.h"#include "prntutil.h"#include "router.h"#include "agenda.h"#include "retract.h"#if LOGICAL_DEPENDENCIES#include "lgcldpnd.h"#endif#if INCREMENTAL_RESET#include "incrrset.h"#endif#include "drive.h"/***************************************//* LOCAL INTERNAL FUNCTION DEFINITIONS *//***************************************/#if ANSI_COMPILER static VOID PPDrive(struct partialMatch *,struct partialMatch *,struct joinNode *); static VOID PNRDrive(struct joinNode *,struct partialMatch *, struct partialMatch *); static VOID EmptyDrive(struct joinNode *,struct partialMatch *); static VOID JoinNetErrorMessage(struct joinNode *);#else static VOID PPDrive(); static VOID PNRDrive(); static VOID EmptyDrive(); static VOID JoinNetErrorMessage();#endif/****************************************//* GLOBAL INTERNAL VARIABLE DEFINITIONS *//****************************************/ globle BOOLEAN JoinOperationInProgress = CLIPS_FALSE; /************************************************//* NetworkAssert: Primary routine for filtering *//* a partial match through the join network. *//************************************************/globle VOID NetworkAssert(binds,join,enterDirection) struct partialMatch *binds; struct joinNode *join; int enterDirection; { struct partialMatch *lhsBinds = NULL, *rhsBinds = NULL; struct partialMatch *comparePMs = NULL, *newBinds; int exprResult; /*=========================================================*/ /* If an incremental reset is being performed and the join */ /* is not part of the network to be reset, then return. */ /*=========================================================*/#if INCREMENTAL_RESET && (! BLOAD_ONLY) && (! RUN_TIME) if (IncrementalResetInProgress && (join->initialize == CLIPS_FALSE)) return;#endif /*=========================================================*/ /* If the associated LHS pattern is a not CE or the join */ /* is a nand join, then we need an additional field in the */ /* partial match to keep track of the pseudo fact if one */ /* is created. The partial match is automatically stored */ /* in the beta memory and the counterf slot is used to */ /* determine if it is an actual partial match. If counterf */ /* is TRUE, there are one or more fact or instances */ /* keeping the not or nand join from being satisfied. */ /*=========================================================*/ if ((enterDirection == LHS) && ((join->patternIsNegated) || (join->joinFromTheRight))) { newBinds = AddSingleMatch(binds,NULL, (join->ruleToActivate == NULL) ? 0 : 1, (int) join->logicalJoin); newBinds->notOriginf = CLIPS_TRUE; newBinds->counterf = CLIPS_TRUE; binds = newBinds; binds->next = join->beta; join->beta = binds; } /*==================================================*/ /* Use a special routine if this is the first join. */ /*==================================================*/ if (join->firstJoin) { EmptyDrive(join,binds); return; } /*==================================================*/ /* Initialize some variables used to indicate which */ /* side is being compared to the new partial match. */ /*==================================================*/ if (enterDirection == LHS) { if (join->joinFromTheRight) { comparePMs = ((struct joinNode *) join->rightSideEntryStructure)->beta;} else { comparePMs = ((struct patternNodeHeader *) join->rightSideEntryStructure)->alphaMemory; } lhsBinds = binds; } else if (enterDirection == RHS) { if (join->patternIsNegated || join->joinFromTheRight) { comparePMs = join->beta; } else { comparePMs = join->lastLevel->beta; } rhsBinds = binds; } else { CLIPSSystemError("DRIVE",1); ExitCLIPS(5); } /*===================================================*/ /* Compare each set of binds on the opposite side of */ /* the join with the set of binds that entered this */ /* join. If the binds don't mismatch, then perform */ /* the appropriate action for the logic of the join. */ /*===================================================*/ while (comparePMs != NULL) { /*===========================================================*/ /* Initialize some variables pointing to the partial matches */ /* in the LHS and RHS of the join. In addition, check for */ /* certain conditions under which the partial match can be */ /* skipped since it's not a "real" partial match. */ /*===========================================================*/ if (enterDirection == RHS) { lhsBinds = comparePMs; /*=====================================================*/ /* The partial matches entering from the LHS of a join */ /* are stored in the beta memory of the previous join */ /* (unless the current join is a join from the right */ /* or is attached to a not CE). If the previous join */ /* is a join from the right or associated with a not */ /* CE, then some of its partial matches in its beta */ /* memory will not be "real" partial matches. That is, */ /* there may be a partial match in the alpha memory */ /* that prevents the partial match from satisfying the */ /* join's conditions. If this is the case, then the */ /* counterf flag in the partial match will be set to */ /* TRUE and in this case, we move on to the next */ /* partial match to be checked. */ /*=====================================================*/ if (lhsBinds->counterf && (join->patternIsNegated == CLIPS_FALSE) && (join->joinFromTheRight == CLIPS_FALSE)) { comparePMs = comparePMs->next; continue; } /*==================================================*/ /* If the join is associated with a not CE or has a */ /* join from the right, then the LHS partial match */ /* currently being checked may already have a */ /* partial match from the alpha memory preventing */ /* it from being satisfied. If this is the case, */ /* then move on to the next partial match in the */ /* beta memory of the join. */ /*==================================================*/ if ((join->patternIsNegated || join->joinFromTheRight) && (lhsBinds->counterf)) { comparePMs = comparePMs->next; continue; } } else { rhsBinds = comparePMs; } /*========================================================*/ /* If the join has no expression associated with it, then */ /* the new partial match derived from the LHS and RHS */ /* partial matches is valid. In the event that the join */ /* is a join from the right, it must also be checked that */ /* the RHS partial match is the same partial match that */ /* the LHS partial match was generated from. Each LHS */ /* partial match in a join from the right corresponds */ /* uniquely to a partial match from the RHS of the join. */ /* To determine whether the LHS partial match is the one */ /* associated with the RHS partial match, we compare the */ /* the entity addresses found in the partial matches to */ /* make sure they're equal. */ /*========================================================*/ if (join->networkTest == NULL) { exprResult = CLIPS_TRUE; if (join->joinFromTheRight) { int i; for (i = 0; i < (int) (lhsBinds->bcount - 1); i++) { if (lhsBinds->binds[i].gm.theMatch != rhsBinds->binds[i].gm.theMatch) { exprResult = CLIPS_FALSE; break; } } } } /*=========================================================*/ /* If the join has an expression associated with it, then */ /* evaluate the expression to determine if the new partial */ /* match derived from the LHS and RHS partial matches is */ /* valid (i.e. variable bindings are consistent and */ /* predicate expressions evaluate to TRUE). */ /*=========================================================*/ else { exprResult = EvaluateJoinExpression(join->networkTest,lhsBinds,rhsBinds,join); if (EvaluationError) { if (join->patternIsNegated) exprResult = CLIPS_TRUE; SetEvaluationError(CLIPS_FALSE); } } /*====================================================*/ /* If the join expression evaluated to true (i.e. */ /* there were no conflicts between variable bindings, */ /* all tests were satisfied, etc.), then perform the */ /* appropriate action given the logic of this join. */ /*====================================================*/ if (exprResult != CLIPS_FALSE) { /*==============================================*/ /* Use the PPDrive routine when the join isn't */ /* associated with a not CE and it doesn't have */ /* a join from the right. */ /*==============================================*/ if ((join->patternIsNegated == CLIPS_FALSE) && (join->joinFromTheRight == CLIPS_FALSE))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -