📄 rulebld.c
字号:
lastNode->bottom = tempNode;
lastNode->endNandDepth = trackNode->endNandDepth;
ReturnLHSParseNodes(theEnv,trackNode);
trackNode = tempNode;
}
/*================================================*/
/* If none of the previous conditions have been */
/* met, then there is an internal error. */
/*================================================*/
else
{
SystemError(theEnv,"BUILD",1);
EnvExitRouter(theEnv,EXIT_FAILURE);
}
}
/*====================================*/
/* 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(
struct joinNode *listOfJoins,
void *rhsStruct,
unsigned int firstJoin,
unsigned int negatedRHS,
int isLogical,
struct expr *joinTest,
int endDepth,
int currentDepth,
int 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(
struct joinNode *testJoin,
unsigned firstJoin,
unsigned negatedRHS,
int isLogical,
struct expr *joinTest,
int endDepth,
int currentDepth,
int 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(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(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 == TRUE) &&
(testJoin->logicalJoin == FALSE) &&
(testJoin->beta != NULL))
{ return(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) != TRUE)
{ return(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(FALSE);
if (testJoin->joinFromTheRight == FALSE)
{ return(FALSE); }
else if (nandReconnect[currentDepth-2] != testJoin->lastLevel)
{ return(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(FALSE);
if (testJoin->beta != NULL) return(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 == TRUE)
{
if (((struct joinNode *) testJoin->nextLevel->rightSideEntryStructure) == testJoin)
{ return(FALSE); }
}
}
/*=============================================*/
/* The join can be shared since all conditions */
/* for sharing have been satisfied. */
/*=============================================*/
return(TRUE);
}
/*************************************************************************/
/* CreateNewJoin: Creates a new join and links it into the join network. */
/*************************************************************************/
static struct joinNode *CreateNewJoin(
void *theEnv,
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 ((EnvGetWatchItem(theEnv,"compilations") == TRUE) && GetPrintWhileLoading(theEnv))
{ EnvPrintRouter(theEnv,WDIALOG,"+j"); }
#endif
/*========================================================*/
/* Create the new join and initialize some of its values. */
/*========================================================*/
newJoin = get_struct(theEnv,joinNode);
newJoin->beta = NULL;
newJoin->nextLevel = NULL;
newJoin->joinFromTheRight = joinFromTheRight;
newJoin->patternIsNegated = negatedRHSPattern;
newJoin->initialize = EnvGetIncrementalReset(theEnv);
newJoin->logicalJoin = FALSE;
newJoin->ruleToActivate = NULL;
/*==============================================*/
/* Install the expressions used to determine */
/* if a partial match satisfies the constraints */
/* associated with this join. */
/*==============================================*/
newJoin->networkTest = AddHashedExpression(theEnv,joinTest);
/*============================================================*/
/* Initialize the values associated with the LHS of the join. */
/*============================================================*/
newJoin->lastLevel = lhsEntryStruct;
if (lhsEntryStruct == NULL)
{
newJoin->firstJoin = TRUE;
newJoin->depth = 1;
newJoin->rightDriveNode = NULL;
}
else
{
newJoin->firstJoin = 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 + -