📄 rulebld.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.24 05/17/06 */
/* */
/* RULE BUILD MODULE */
/*******************************************************/
/*************************************************************/
/* Purpose: Provides routines to ntegrates a set of pattern */
/* and join tests associated with a rule into the pattern */
/* and join networks. The joins are integrated into the */
/* join network by routines in this module. The pattern */
/* is integrated by calling the external routine */
/* associated with the pattern parser that originally */
/* parsed the pattern. */
/* */
/* Principal Programmer(s): */
/* Gary D. Riley */
/* */
/* Contributing Programmer(s): */
/* */
/* Revision History: */
/* */
/* 6.24: Removed INCREMENTAL_RESET compilation flag. */
/* */
/* Corrected code to remove compiler warnings. */
/* */
/*************************************************************/
#define _RULEBLD_SOURCE_
#include "setup.h"
#if DEFRULE_CONSTRUCT && (! RUN_TIME) && (! BLOAD_ONLY)
#include <stdio.h>
#define _STDIO_INCLUDED_
#include <stdlib.h>
#include "constant.h"
#include "envrnmnt.h"
#include "constrct.h"
#include "drive.h"
#include "incrrset.h"
#include "memalloc.h"
#include "pattern.h"
#include "reteutil.h"
#include "router.h"
#include "rulebld.h"
#include "watch.h"
/***************************************/
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
/***************************************/
static struct joinNode *FindShareableJoin(struct joinNode *,void *,unsigned,unsigned,int,
struct expr *,
int,int,int,struct joinNode **);
static int TestJoinForReuse(struct joinNode *,unsigned,unsigned,int,
struct expr *,
int,int,int,struct joinNode **);
static struct joinNode *CreateNewJoin(void *,struct expr *,
struct joinNode *,void *,int,int);
static void AttachTestCEsToPatternCEs(void *,struct lhsParseNode *);
/****************************************************************/
/* ConstructJoins: Integrates a set of pattern and join tests */
/* associated with a rule into the pattern and join networks. */
/****************************************************************/
globle struct joinNode *ConstructJoins(
void *theEnv,
int logicalJoin,
struct lhsParseNode *theLHS)
{
struct joinNode *lastJoin = NULL;
struct patternNodeHeader *lastPattern;
unsigned firstJoin = TRUE;
int tryToReuse = TRUE;
struct joinNode *listOfJoins;
struct joinNode *oldJoin;
int joinNumber = 1;
int isLogical;
struct joinNode *nandReconnect[32];
int currentDepth = 1;
int lastIteration = FALSE;
int rhsType;
int endDepth;
/*===================================================*/
/* Remove any test CEs from the LHS and attach their */
/* expression to the closest preceeding non-negated */
/* join at the same not/and depth. */
/*===================================================*/
AttachTestCEsToPatternCEs(theEnv,theLHS);
/*=====================================================*/
/* Process each pattern CE in the rule. At this point, */
/* there should be no and/or/not/test CEs in the LHS. */
/*=====================================================*/
while (theLHS != NULL)
{
if (theLHS->bottom == NULL) lastIteration = TRUE;
/*==================================================*/
/* If the pattern is the start of a new not/and CE, */
/* then remember the join to reconnect to after the */
/* join from the right is completed. */
/*==================================================*/
while (theLHS->beginNandDepth > currentDepth)
{
nandReconnect[currentDepth-1] = lastJoin;
currentDepth++;
}
/*============================================================*/
/* Add the next pattern for this rule to the pattern network. */
/*============================================================*/
rhsType = theLHS->patternType->positionInArray;
lastPattern = (*theLHS->patternType->addPatternFunction)(theEnv,theLHS);
/*======================================================*/
/* Determine if the join being added is a logical join. */
/*======================================================*/
if (joinNumber == logicalJoin) isLogical = TRUE;
else isLogical = FALSE;
/*===============================================*/
/* Get the list of joins which could potentially */
/* be reused in place of the join being added. */
/*===============================================*/
if (firstJoin == TRUE)
{ listOfJoins = lastPattern->entryJoin; }
else
{ listOfJoins = lastJoin->nextLevel; }
/*=======================================================*/
/* Determine if the next join to be added can be shared. */
/*=======================================================*/
endDepth = theLHS->endNandDepth;
if ((tryToReuse == TRUE) &&
((oldJoin = FindShareableJoin(listOfJoins,(void *) lastPattern,firstJoin,
theLHS->negated,isLogical,
theLHS->networkTest,
endDepth,currentDepth,
lastIteration,nandReconnect)) != NULL) )
{
#if DEBUGGING_FUNCTIONS
if ((EnvGetWatchItem(theEnv,"compilations") == TRUE) && GetPrintWhileLoading(theEnv))
{ EnvPrintRouter(theEnv,WDIALOG,"=j"); }
#endif
lastJoin = oldJoin;
}
else
{
tryToReuse = FALSE;
lastJoin = CreateNewJoin(theEnv,theLHS->networkTest,
lastJoin,lastPattern,
FALSE,(int) theLHS->negated);
lastJoin->rhsType = rhsType;
}
/*==========================================================*/
/* Create any joins from the right needed to handle not/and */
/* CE combinations and connect them to the join network. */
/*==========================================================*/
while (endDepth < currentDepth)
{
currentDepth--;
if (lastJoin->nextLevel == NULL) tryToReuse = FALSE;
if (tryToReuse)
{
#if DEBUGGING_FUNCTIONS
if ((EnvGetWatchItem(theEnv,"compilations") == TRUE) && GetPrintWhileLoading(theEnv))
{ EnvPrintRouter(theEnv,WDIALOG,"=j"); }
#endif
lastJoin = lastJoin->nextLevel;
}
else
{
lastJoin = CreateNewJoin(theEnv,NULL,nandReconnect[currentDepth-1],
lastJoin,TRUE,FALSE);
}
}
/*=======================================*/
/* Move on to the next join to be added. */
/*=======================================*/
theLHS = theLHS->bottom;
joinNumber++;
firstJoin = FALSE;
}
/*===================================================*/
/* If compilations are being watched, put a carriage */
/* return after all of the =j's and +j's */
/*===================================================*/
#if DEBUGGING_FUNCTIONS
if ((EnvGetWatchItem(theEnv,"compilations") == TRUE) && GetPrintWhileLoading(theEnv))
{ EnvPrintRouter(theEnv,WDIALOG,"\n"); }
#endif
/*=============================*/
/* Return the last join added. */
/*=============================*/
return(lastJoin);
}
/****************************************************************/
/* AttachTestCEsToPatternCEs: Attaches the expressions found in */
/* test CEs to the closest preceeding pattern CE that is not */
/* negated and is at the same not/and depth. */
/****************************************************************/
static void AttachTestCEsToPatternCEs(
void *theEnv,
struct lhsParseNode *theLHS)
{
struct lhsParseNode *lastNode = NULL, *trackNode, *tempNode;
/*===============================================*/
/* Look at each pattern on the rule's LHS to see */
/* if any test CEs should be attached to it. */
/*===============================================*/
while (theLHS != NULL)
{
/*==============================================*/
/* If the pattern is negated, then don't bother */
/* looking for any test CEs to attach to it. */
/*==============================================*/
if (theLHS->negated)
{ trackNode = NULL; }
else
{
lastNode = theLHS;
trackNode = theLHS->bottom;
}
/*=================================================*/
/* Check all of the patterns following the current */
/* pattern to check for test CEs which can be */
/* attached to the current pattern. */
/*=================================================*/
while (trackNode != NULL)
{
/*=======================================================*/
/* Skip over any CEs that have a higher not/and depth or */
/* are negated since any test CEs found within these CEs */
/* would be attached to another pattern with the same */
/* depth, rather than the current pattern. */
/*=======================================================*/
if ((trackNode->beginNandDepth != theLHS->beginNandDepth) ||
(trackNode->negated))
{
lastNode = trackNode;
trackNode = trackNode->bottom;
}
/*======================================================*/
/* Once a non-negated pattern has been encounted at the */
/* same not/and depth as the current pattern, then stop */
/* because any test CEs following this pattern would be */
/* attached to it rather than the current pattern. */
/*======================================================*/
else if (trackNode->type == PATTERN_CE)
{ trackNode = NULL; }
/*==================================================*/
/* A test CE encountered at the same not/and depth */
/* can be added to the network test expressions for */
/* the currentpattern. */
/*==================================================*/
else if (trackNode->type == TEST_CE)
{
theLHS->networkTest = CombineExpressions(theEnv,theLHS->networkTest,
trackNode->networkTest);
trackNode->networkTest = NULL;
tempNode = trackNode->bottom;
trackNode->bottom = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -