summaryrefslogtreecommitdiff
path: root/src/incrrset.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/incrrset.c')
-rw-r--r--src/incrrset.c432
1 files changed, 347 insertions, 85 deletions
diff --git a/src/incrrset.c b/src/incrrset.c
index 2c6b1ad..6eee578 100644
--- a/src/incrrset.c
+++ b/src/incrrset.c
@@ -1,7 +1,7 @@
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
- /* CLIPS Version 6.24 05/17/06 */
+ /* CLIPS Version 6.30 08/16/14 */
/* */
/* INCREMENTAL RESET MODULE */
/*******************************************************/
@@ -17,12 +17,25 @@
/* Contributing Programmer(s): */
/* */
/* Revision History: */
+/* */
/* 6.23: Correction for FalseSymbol/TrueSymbol. DR0859 */
/* */
/* 6.24: Removed INCREMENTAL_RESET compilation flag. */
/* */
/* Renamed BOOLEAN macro type to intBool. */
/* */
+/* 6.30: Added support for hashed alpha memories and */
+/* other join network changes. */
+/* */
+/* Removed conditional code for unsupported */
+/* compilers/operating systems (IBM_MCW and */
+/* MAC_MCW). */
+/* */
+/* Modified EnvSetIncrementalReset to check for */
+/* the existance of rules. */
+/* */
+/* Converted API macros to function calls. */
+/* */
/*************************************************************/
#define _INCRRSET_SOURCE_
@@ -43,6 +56,7 @@
#include "evaluatn.h"
#include "pattern.h"
#include "router.h"
+#include "reteutil.h"
#include "incrrset.h"
@@ -52,8 +66,10 @@
#if (! RUN_TIME) && (! BLOAD_ONLY)
static void MarkNetworkForIncrementalReset(void *,struct defrule *,int);
- static void CheckForPrimableJoins(void *,struct defrule *);
- static void PrimeJoin(void *,struct joinNode *);
+ static void MarkJoinsForIncrementalReset(void *,struct joinNode *,int);
+ static void CheckForPrimableJoins(void *,struct defrule *,struct joinNode *);
+ static void PrimeJoinFromLeftMemory(void *,struct joinNode *);
+ static void PrimeJoinFromRightMemory(void *,struct joinNode *);
static void MarkPatternForIncrementalReset(void *,int,struct patternNodeHeader *,int);
#endif
@@ -64,10 +80,6 @@ globle void IncrementalReset(
void *theEnv,
struct defrule *tempRule)
{
-#if (MAC_MCW || IBM_MCW) && (RUN_TIME || BLOAD_ONLY)
-#pragma unused(theEnv,tempRule)
-#endif
-
#if (! RUN_TIME) && (! BLOAD_ONLY)
struct defrule *tempPtr;
struct patternParser *theParser;
@@ -100,7 +112,7 @@ globle void IncrementalReset(
for (tempPtr = tempRule;
tempPtr != NULL;
tempPtr = tempPtr->disjunct)
- { CheckForPrimableJoins(theEnv,tempPtr); }
+ { CheckForPrimableJoins(theEnv,tempPtr,tempPtr->lastJoin); }
/*===============================================*/
/* Filter existing data entities through the new */
@@ -141,9 +153,6 @@ static void MarkNetworkForIncrementalReset(
struct defrule *tempRule,
int value)
{
- struct joinNode *joinPtr;
- struct patternNodeHeader *patternPtr;
-
/*============================================*/
/* Loop through each of the rule's disjuncts. */
/*============================================*/
@@ -151,25 +160,49 @@ static void MarkNetworkForIncrementalReset(
for (;
tempRule != NULL;
tempRule = tempRule->disjunct)
- {
- /*============================================*/
- /* Loop through each of the disjunct's joins. */
- /*============================================*/
+ { MarkJoinsForIncrementalReset(theEnv,tempRule->lastJoin,value); }
+ }
- for (joinPtr = tempRule->lastJoin;
- joinPtr != NULL;
- joinPtr = GetPreviousJoin(joinPtr))
+/**********************************************************************/
+/* MarkJoinsForIncrementalReset: Coordinates marking the initialize */
+/* flags in the pattern and join networks both before and after an */
+/* incremental reset. */
+/**********************************************************************/
+static void MarkJoinsForIncrementalReset(
+ void *theEnv,
+ struct joinNode *joinPtr,
+ int value)
+ {
+ struct patternNodeHeader *patternPtr;
+
+ for (;
+ joinPtr != NULL;
+ joinPtr = joinPtr->lastLevel)
+ {
+ if (joinPtr->ruleToActivate != NULL)
{
- /*================*/
- /* Mark the join. */
- /*================*/
+ joinPtr->marked = FALSE;
+ joinPtr->initialize = value;
+ continue;
+ }
- joinPtr->marked = FALSE; /* GDR 6.05 */
- if ((joinPtr->initialize) && (joinPtr->joinFromTheRight == FALSE))
+ if (joinPtr->joinFromTheRight)
+ { MarkJoinsForIncrementalReset(theEnv,(struct joinNode *) joinPtr->rightSideEntryStructure,value); }
+
+ /*================*/
+ /* Mark the join. */
+ /*================*/
+
+ joinPtr->marked = FALSE; /* GDR 6.05 */
+
+ if (joinPtr->initialize)
+ {
+ joinPtr->initialize = value;
+ if (joinPtr->joinFromTheRight == FALSE)
{
- joinPtr->initialize = value;
patternPtr = (struct patternNodeHeader *) GetPatternForJoin(joinPtr);
- MarkPatternForIncrementalReset(theEnv,(int) joinPtr->rhsType,patternPtr,value);
+ if (patternPtr != NULL)
+ { MarkPatternForIncrementalReset(theEnv,(int) joinPtr->rhsType,patternPtr,value); }
}
}
}
@@ -185,71 +218,79 @@ static void MarkNetworkForIncrementalReset(
/*******************************************************************************/
static void CheckForPrimableJoins(
void *theEnv,
- struct defrule *tempRule)
+ struct defrule *tempRule,
+ struct joinNode *joinPtr)
{
- struct joinNode *joinPtr;
- struct partialMatch *theList;
-
/*========================================*/
/* Loop through each of the rule's joins. */
/*========================================*/
- for (joinPtr = tempRule->lastJoin;
+ for (;
joinPtr != NULL;
- joinPtr = GetPreviousJoin(joinPtr))
+ joinPtr = joinPtr->lastLevel)
{
/*===============================*/
/* Update the join if necessary. */
/*===============================*/
- if ((joinPtr->initialize) && (! joinPtr->marked)) /* GDR 6.05 */
+ if ((joinPtr->initialize) && (! joinPtr->marked))
{
if (joinPtr->firstJoin == TRUE)
{
- if (((struct patternNodeHeader *) GetPatternForJoin(joinPtr))->initialize == FALSE)
+ if (joinPtr->joinFromTheRight == FALSE)
{
- PrimeJoin(theEnv,joinPtr);
- joinPtr->marked = TRUE; /* GDR 6.05 */
+ if ((joinPtr->rightSideEntryStructure == NULL) ||
+ (joinPtr->patternIsNegated) ||
+ (((struct patternNodeHeader *) joinPtr->rightSideEntryStructure)->initialize == FALSE))
+ {
+ PrimeJoinFromLeftMemory(theEnv,joinPtr);
+ joinPtr->marked = TRUE;
+ }
+ }
+ else
+ {
+ PrimeJoinFromRightMemory(theEnv,joinPtr);
+ joinPtr->marked = TRUE;
}
}
else if (joinPtr->lastLevel->initialize == FALSE)
{
- PrimeJoin(theEnv,joinPtr);
- joinPtr->marked = TRUE; /* GDR 6.05 */
+ PrimeJoinFromLeftMemory(theEnv,joinPtr);
+ joinPtr->marked = TRUE;
+ }
+ else if ((joinPtr->joinFromTheRight) &&
+ (((struct joinNode *) joinPtr->rightSideEntryStructure)->initialize == FALSE))
+ {
+ PrimeJoinFromRightMemory(theEnv,joinPtr);
+ joinPtr->marked = TRUE;
}
}
- /*================================================================*/
- /* If the join is associated with a rule activation (i.e. partial */
- /* matches that reach this join cause an activation to be placed */
- /* on the agenda), then add activations to the agenda for the */
- /* rule being incrementally reset. */
- /*================================================================*/
-
- else if (joinPtr->ruleToActivate == tempRule)
- {
- for (theList = joinPtr->beta;
- theList != NULL;
- theList = theList->next)
- { AddActivation(theEnv,tempRule,theList); }
- }
+ if (joinPtr->joinFromTheRight)
+ { CheckForPrimableJoins(theEnv,tempRule,(struct joinNode *) joinPtr->rightSideEntryStructure); }
}
}
/****************************************************************************/
-/* PrimeJoin: Updates a join in a rule for an incremental reset. Joins are */
-/* updated by "priming" them only if the join (or its associated pattern) */
-/* is shared with other rules that have already been incrementally reset. */
-/* A join for a new rule will be updated if it is marked for */
-/* initialization and either its parent join or its associated entry */
-/* pattern node has not been marked for initialization. */
+/* PrimeJoinFromLeftMemory: Updates a join in a rule for an incremental */
+/* reset. Joins are updated by "priming" them only if the join (or its */
+/* associated pattern) is shared with other rules that have already been */
+/* incrementally reset. A join for a new rule will be updated if it is */
+/* marked for initialization and either its parent join or its associated */
+/* entry pattern node has not been marked for initialization. */
/****************************************************************************/
-static void PrimeJoin(
+static void PrimeJoinFromLeftMemory(
void *theEnv,
struct joinNode *joinPtr)
{
- struct partialMatch *theList;
-
+ struct partialMatch *theList, *linker;
+ struct alphaMemoryHash *listOfHashNodes;
+ unsigned long b;
+ unsigned long hashValue;
+ struct betaMemory *theMemory;
+ struct partialMatch *notParent;
+ struct joinLink *tempLink;
+
/*===========================================================*/
/* If the join is the first join of a rule, then send all of */
/* the partial matches from the alpha memory of the pattern */
@@ -259,31 +300,196 @@ static void PrimeJoin(
if (joinPtr->firstJoin == TRUE)
{
- for (theList = ((struct patternNodeHeader *) joinPtr->rightSideEntryStructure)->alphaMemory;
+ if (joinPtr->rightSideEntryStructure == NULL)
+ { NetworkAssert(theEnv,joinPtr->rightMemory->beta[0],joinPtr); }
+ else if (joinPtr->patternIsNegated)
+ {
+ notParent = joinPtr->leftMemory->beta[0];
+
+ if (joinPtr->secondaryNetworkTest != NULL)
+ {
+ if (EvaluateSecondaryNetworkTest(theEnv,notParent,joinPtr) == FALSE)
+ { return; }
+ }
+
+ for (listOfHashNodes = ((struct patternNodeHeader *) joinPtr->rightSideEntryStructure)->firstHash;
+ listOfHashNodes != NULL;
+ listOfHashNodes = listOfHashNodes->nextHash)
+ {
+ if (listOfHashNodes->alphaMemory != NULL)
+ {
+ AddBlockedLink(notParent,listOfHashNodes->alphaMemory);
+ return;
+ }
+ }
+
+ EPMDrive(theEnv,notParent,joinPtr,NETWORK_ASSERT);
+ }
+ else
+ {
+ for (listOfHashNodes = ((struct patternNodeHeader *) joinPtr->rightSideEntryStructure)->firstHash;
+ listOfHashNodes != NULL;
+ listOfHashNodes = listOfHashNodes->nextHash)
+ {
+ for (theList = listOfHashNodes->alphaMemory;
+ theList != NULL;
+ theList = theList->nextInMemory)
+ { NetworkAssert(theEnv,theList,joinPtr); }
+ }
+ }
+ return;
+ }
+
+ /*========================================*/
+ /* Find another beta memory from which we */
+ /* can retrieve the partial matches. */
+ /*========================================*/
+
+ tempLink = joinPtr->lastLevel->nextLinks;
+
+ while (tempLink != NULL)
+ {
+ if ((tempLink->join != joinPtr) &&
+ (tempLink->join->initialize == FALSE))
+ { break; }
+
+ tempLink = tempLink->next;
+ }
+
+ if (tempLink == NULL) return;
+
+ if (tempLink->enterDirection == LHS)
+ { theMemory = tempLink->join->leftMemory; }
+ else
+ { theMemory = tempLink->join->rightMemory; }
+
+ /*============================================*/
+ /* Send all partial matches from the selected */
+ /* beta memory to the new join. */
+ /*============================================*/
+
+ for (b = 0; b < theMemory->size; b++)
+ {
+ for (theList = theMemory->beta[b];
theList != NULL;
- theList = theList->next)
- { NetworkAssert(theEnv,theList,joinPtr,RHS); }
+ theList = theList->nextInMemory)
+ {
+ linker = CopyPartialMatch(theEnv,theList);
+
+ if (joinPtr->leftHash != NULL)
+ { hashValue = BetaMemoryHashValue(theEnv,joinPtr->leftHash,linker,NULL,joinPtr); }
+ else
+ { hashValue = 0; }
+
+ UpdateBetaPMLinks(theEnv,linker,theList->leftParent,theList->rightParent,joinPtr,hashValue,LHS);
+
+ NetworkAssertLeft(theEnv,linker,joinPtr,NETWORK_ASSERT);
+ }
+ }
+ }
+
+/****************************************************************************/
+/* PrimeJoinFromRightMemory: Updates a join in a rule for an incremental */
+/* reset. Joins are updated by "priming" them only if the join (or its */
+/* associated pattern) is shared with other rules that have already been */
+/* incrementally reset. A join for a new rule will be updated if it is */
+/* marked for initialization and either its parent join or its associated */
+/* entry pattern node has not been marked for initialization. */
+/****************************************************************************/
+static void PrimeJoinFromRightMemory(
+ void *theEnv,
+ struct joinNode *joinPtr)
+ {
+ struct partialMatch *theList, *linker;
+ unsigned long b;
+ struct betaMemory *theMemory;
+ unsigned long hashValue;
+ struct joinLink *tempLink;
+ struct partialMatch *notParent;
+
+ /*=======================================*/
+ /* This should be a join from the right. */
+ /*=======================================*/
+
+ if (joinPtr->joinFromTheRight == FALSE)
+ { return; }
+
+ /*========================================*/
+ /* Find another beta memory from which we */
+ /* can retrieve the partial matches. */
+ /*========================================*/
+
+ tempLink = ((struct joinNode *) joinPtr->rightSideEntryStructure)->nextLinks;
+ while (tempLink != NULL)
+ {
+ if ((tempLink->join != joinPtr) &&
+ (tempLink->join->initialize == FALSE))
+ { break; }
+
+ tempLink = tempLink->next;
+ }
+
+ if (tempLink == NULL)
+ {
+ if (joinPtr->firstJoin &&
+ (joinPtr->rightMemory->beta[0] == NULL) &&
+ (! joinPtr->patternIsExists))
+ {
+ notParent = joinPtr->leftMemory->beta[0];
+
+ if (joinPtr->secondaryNetworkTest != NULL)
+ {
+ if (EvaluateSecondaryNetworkTest(theEnv,notParent,joinPtr) == FALSE)
+ { return; }
+ }
+
+ EPMDrive(theEnv,notParent,joinPtr,NETWORK_ASSERT);
+ }
+
return;
}
- /*======================================================*/
- /* If the join already has partial matches in its beta */
- /* memory, then don't bother priming it. I don't recall */
- /* if this situation is possible. */
- /*======================================================*/
+ if (tempLink->enterDirection == LHS)
+ { theMemory = tempLink->join->leftMemory; }
+ else
+ { theMemory = tempLink->join->rightMemory; }
+
+ /*============================================*/
+ /* Send all partial matches from the selected */
+ /* beta memory to the new join. */
+ /*============================================*/
+
+ for (b = 0; b < theMemory->size; b++)
+ {
+ for (theList = theMemory->beta[b];
+ theList != NULL;
+ theList = theList->nextInMemory)
+ {
+ linker = CopyPartialMatch(theEnv,theList);
- if (joinPtr->beta != NULL) return;
+ if (joinPtr->rightHash != NULL)
+ { hashValue = BetaMemoryHashValue(theEnv,joinPtr->rightHash,linker,NULL,joinPtr); }
+ else
+ { hashValue = 0; }
- /*================================================================*/
- /* Send all partial matches from the preceding join to this join. */
- /*================================================================*/
+ UpdateBetaPMLinks(theEnv,linker,theList->leftParent,theList->rightParent,joinPtr,hashValue,RHS);
+ NetworkAssert(theEnv,linker,joinPtr);
+ }
+ }
- for (theList = joinPtr->lastLevel->beta;
- theList != NULL;
- theList = theList->next)
+ if (joinPtr->firstJoin &&
+ (joinPtr->rightMemory->beta[0] == NULL) &&
+ (! joinPtr->patternIsExists))
{
- if (! theList->counterf) /* 6.05 incremental reset bug fix */
- { NetworkAssert(theEnv,theList,joinPtr,LHS); }
+ notParent = joinPtr->leftMemory->beta[0];
+
+ if (joinPtr->secondaryNetworkTest != NULL)
+ {
+ if (EvaluateSecondaryNetworkTest(theEnv,notParent,joinPtr) == FALSE)
+ { return; }
+ }
+
+ EPMDrive(theEnv,notParent,joinPtr,NETWORK_ASSERT);
}
}
@@ -300,7 +506,7 @@ static void MarkPatternForIncrementalReset(
int value)
{
struct patternParser *tempParser;
-
+
tempParser = GetPatternParser(theEnv,rhsType);
if (tempParser != NULL)
@@ -318,7 +524,7 @@ static void MarkPatternForIncrementalReset(
/********************************************/
globle intBool EnvGetIncrementalReset(
void *theEnv)
- {
+ {
return(EngineData(theEnv)->IncrementalResetFlag);
}
@@ -331,9 +537,34 @@ globle intBool EnvSetIncrementalReset(
int value)
{
int ov;
+ struct defmodule *theModule;
+
+ /*============================================*/
+ /* The incremental reset behavior can only be */
+ /* changed if there are no existing rules. */
+ /*============================================*/
+
+ SaveCurrentModule(theEnv);
+
+ for (theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,NULL);
+ theModule != NULL;
+ theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,theModule))
+ {
+ EnvSetCurrentModule(theEnv,(void *) theModule);
+ if (EnvGetNextDefrule(theEnv,NULL) != NULL)
+ {
+ RestoreCurrentModule(theEnv);
+ return(-1);
+ }
+ }
+
+ RestoreCurrentModule(theEnv);
+
+ /*====================================*/
+ /* Change the incremental reset flag. */
+ /*====================================*/
ov = EngineData(theEnv)->IncrementalResetFlag;
- if (EnvGetNextDefrule(theEnv,NULL) != NULL) return(-1);
EngineData(theEnv)->IncrementalResetFlag = value;
return(ov);
}
@@ -347,6 +578,7 @@ globle int SetIncrementalResetCommand(
{
int oldValue;
DATA_OBJECT argPtr;
+ struct defmodule *theModule;
oldValue = EnvGetIncrementalReset(theEnv);
@@ -362,14 +594,25 @@ globle int SetIncrementalResetCommand(
/* changed when rules are loaded. */
/*=========================================*/
- if (EnvGetNextDefrule(theEnv,NULL) != NULL)
+ SaveCurrentModule(theEnv);
+
+ for (theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,NULL);
+ theModule != NULL;
+ theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,theModule))
{
- PrintErrorID(theEnv,"INCRRSET",1,FALSE);
- EnvPrintRouter(theEnv,WERROR,"The incremental reset behavior cannot be changed with rules loaded.\n");
- SetEvaluationError(theEnv,TRUE);
- return(oldValue);
+ EnvSetCurrentModule(theEnv,(void *) theModule);
+ if (EnvGetNextDefrule(theEnv,NULL) != NULL)
+ {
+ RestoreCurrentModule(theEnv);
+ PrintErrorID(theEnv,"INCRRSET",1,FALSE);
+ EnvPrintRouter(theEnv,WERROR,"The incremental reset behavior cannot be changed with rules loaded.\n");
+ SetEvaluationError(theEnv,TRUE);
+ return(oldValue);
+ }
}
+ RestoreCurrentModule(theEnv);
+
/*==================================================*/
/* The symbol FALSE disables incremental reset. Any */
/* other value enables incremental reset. */
@@ -406,4 +649,23 @@ globle int GetIncrementalResetCommand(
return(oldValue);
}
+/*#####################################*/
+/* ALLOW_ENVIRONMENT_GLOBALS Functions */
+/*#####################################*/
+
+#if ALLOW_ENVIRONMENT_GLOBALS
+
+globle intBool GetIncrementalReset()
+ {
+ return EnvGetIncrementalReset(GetCurrentEnvironment());
+ }
+
+globle intBool SetIncrementalReset(
+ int value)
+ {
+ return EnvSetIncrementalReset(GetCurrentEnvironment(),value);
+ }
+
+#endif /* ALLOW_ENVIRONMENT_GLOBALS */
+
#endif /* DEFRULE_CONSTRUCT */