📄 reorder.c
字号:
/* an and CE can be combined. */
/*==============================*/
else if ((theLHS->type == AND_CE) && (argPtr->type == TEST_CE) &&
((argPtr->bottom != NULL) ? argPtr->bottom->type == TEST_CE :
FALSE) &&
(argPtr->beginNandDepth == argPtr->endNandDepth) &&
(argPtr->endNandDepth == argPtr->bottom->beginNandDepth))
{
change = TRUE;
*newChange = TRUE;
e1 = LHSParseNodesToExpression(theEnv,argPtr->expression);
e2 = LHSParseNodesToExpression(theEnv,argPtr->bottom->expression);
e1 = CombineExpressions(theEnv,e1,e2);
ReturnLHSParseNodes(theEnv,argPtr->expression);
argPtr->expression = ExpressionToLHSParseNodes(theEnv,e1);
ReturnExpression(theEnv,e1);
tempArg = argPtr->bottom;
argPtr->bottom = tempArg->bottom;
tempArg->bottom = NULL;
ReturnLHSParseNodes(theEnv,tempArg);
}
/*=====================================*/
/* Replace and CEs containing a single */
/* test CE with just a test CE. */
/*=====================================*/
else if ((theLHS->type == AND_CE) && (argPtr->type == TEST_CE) &&
(theLHS->right == argPtr) && (argPtr->bottom == NULL))
{
change = TRUE;
*newChange = TRUE;
CopyLHSParseNode(theEnv,theLHS,argPtr,TRUE);
theLHS->right = NULL;
ReturnLHSParseNodes(theEnv,argPtr);
break;
}
/*===================================================*/
/* If no changes are needed, move on to the next CE. */
/*===================================================*/
else
{
lastArg = argPtr;
argPtr = argPtr->bottom;
}
}
}
/*===========================*/
/* Return the reordered LHS. */
/*===========================*/
return(theLHS);
}
/*********************************************************************/
/* CopyLHSParseNodes: Copies a linked group of conditional elements. */
/*********************************************************************/
globle struct lhsParseNode *CopyLHSParseNodes(
void *theEnv,
struct lhsParseNode *listOfCEs)
{
struct lhsParseNode *newList;
if (listOfCEs == NULL)
{ return(NULL); }
newList = get_struct(theEnv,lhsParseNode);
CopyLHSParseNode(theEnv,newList,listOfCEs,TRUE);
newList->right = CopyLHSParseNodes(theEnv,listOfCEs->right);
newList->bottom = CopyLHSParseNodes(theEnv,listOfCEs->bottom);
return(newList);
}
/**********************************************************/
/* CopyLHSParseNode: Copies a single conditional element. */
/**********************************************************/
globle void CopyLHSParseNode(
void *theEnv,
struct lhsParseNode *dest,
struct lhsParseNode *src,
int duplicate)
{
dest->type = src->type;
dest->value = src->value;
dest->negated = src->negated;
dest->bindingVariable = src->bindingVariable;
dest->withinMultifieldSlot = src->withinMultifieldSlot;
dest->multifieldSlot = src->multifieldSlot;
dest->multiFieldsBefore = src->multiFieldsBefore;
dest->multiFieldsAfter = src->multiFieldsAfter;
dest->singleFieldsBefore = src->singleFieldsBefore;
dest->singleFieldsAfter = src->singleFieldsAfter;
dest->logical = src->logical;
dest->userCE = src->userCE;
dest->referringNode = src->referringNode;
dest->patternType = src->patternType;
dest->pattern = src->pattern;
dest->index = src->index;
dest->slot = src->slot;
dest->slotNumber = src->slotNumber;
dest->beginNandDepth = src->beginNandDepth;
dest->endNandDepth = src->endNandDepth;
/*==========================================================*/
/* The duplicate flag controls whether pointers to existing */
/* data structures are used when copying some slots or if */
/* new copies of the data structures are made. */
/*==========================================================*/
if (duplicate)
{
dest->networkTest = CopyExpression(theEnv,src->networkTest);
if (src->userData == NULL)
{ dest->userData = NULL; }
else if (src->patternType->copyUserDataFunction == NULL)
{ dest->userData = src->userData; }
else
{ dest->userData = (*src->patternType->copyUserDataFunction)(theEnv,src->userData); }
dest->expression = CopyLHSParseNodes(theEnv,src->expression);
dest->constraints = CopyConstraintRecord(theEnv,src->constraints);
if (dest->constraints != NULL) dest->derivedConstraints = TRUE;
else dest->derivedConstraints = FALSE;
}
else
{
dest->networkTest = src->networkTest;
dest->userData = src->userData;
dest->expression = src->expression;
dest->derivedConstraints = FALSE;
dest->constraints = src->constraints;
}
}
/****************************************************/
/* GetLHSParseNode: Creates an empty node structure */
/* used for building conditional elements. */
/****************************************************/
globle struct lhsParseNode *GetLHSParseNode(
void *theEnv)
{
struct lhsParseNode *newNode;
newNode = get_struct(theEnv,lhsParseNode);
newNode->type = UNKNOWN_VALUE;
newNode->value = NULL;
newNode->negated = FALSE;
newNode->bindingVariable = FALSE;
newNode->withinMultifieldSlot = FALSE;
newNode->multifieldSlot = FALSE;
newNode->multiFieldsBefore = 0;
newNode->multiFieldsAfter = 0;
newNode->singleFieldsBefore = 0;
newNode->singleFieldsAfter = 0;
newNode->logical = FALSE;
newNode->derivedConstraints = FALSE;
newNode->userCE = TRUE;
newNode->constraints = NULL;
newNode->referringNode = NULL;
newNode->patternType = NULL;
newNode->pattern = -1;
newNode->index = -1;
newNode->slot = NULL;
newNode->slotNumber = -1;
newNode->beginNandDepth = 1;
newNode->endNandDepth = 1;
newNode->userData = NULL;
newNode->networkTest = NULL;
newNode->expression = NULL;
newNode->right = NULL;
newNode->bottom = NULL;
return(newNode);
}
/********************************************************/
/* ReturnLHSParseNodes: Returns a multiply linked list */
/* of lhsParseNode structures to the memory manager. */
/********************************************************/
globle void ReturnLHSParseNodes(
void *theEnv,
struct lhsParseNode *waste)
{
if (waste != NULL)
{
ReturnExpression(theEnv,waste->networkTest);
ReturnLHSParseNodes(theEnv,waste->right);
ReturnLHSParseNodes(theEnv,waste->bottom);
ReturnLHSParseNodes(theEnv,waste->expression);
if (waste->derivedConstraints) RemoveConstraint(theEnv,waste->constraints);
if ((waste->userData != NULL) &&
(waste->patternType->returnUserDataFunction != NULL))
{ (*waste->patternType->returnUserDataFunction)(theEnv,waste->userData); }
rtn_struct(theEnv,lhsParseNode,waste);
}
}
/********************************************************/
/* ExpressionToLHSParseNodes: Copies an expression into */
/* the equivalent lhsParseNode data structures. */
/********************************************************/
globle struct lhsParseNode *ExpressionToLHSParseNodes(
void *theEnv,
struct expr *expressionList)
{
struct lhsParseNode *newList, *theList;
struct FunctionDefinition *theFunction;
int i, theRestriction;
/*===========================================*/
/* A NULL expression requires no conversion. */
/*===========================================*/
if (expressionList == NULL) return(NULL);
/*====================================*/
/* Recursively convert the expression */
/* to lhsParseNode data structures. */
/*====================================*/
newList = GetLHSParseNode(theEnv);
newList->type = expressionList->type;
newList->value = expressionList->value;
newList->right = ExpressionToLHSParseNodes(theEnv,expressionList->nextArg);
newList->bottom = ExpressionToLHSParseNodes(theEnv,expressionList->argList);
/*==================================================*/
/* If the expression is a function call, then store */
/* the constraint information for the functions */
/* arguments in the lshParseNode data structures. */
/*==================================================*/
if (newList->type != FCALL) return(newList);
theFunction = (struct FunctionDefinition *) newList->value;
for (theList = newList->bottom, i = 1;
theList != NULL;
theList = theList->right, i++)
{
if (theList->type == SF_VARIABLE)
{
theRestriction = GetNthRestriction(theFunction,i);
theList->constraints = ArgumentTypeToConstraintRecord(theEnv,theRestriction);
theList->derivedConstraints = TRUE;
}
}
/*==================================*/
/* Return the converted expression. */
/*==================================*/
return(newList);
}
/******************************************************************/
/* LHSParseNodesToExpression: Copies lhsParseNode data structures */
/* into the equivalent expression data structures. */
/******************************************************************/
globle struct expr *LHSParseNodesToExpression(
void *theEnv,
struct lhsParseNode *nodeList)
{
struct expr *newList;
if (nodeList == NULL)
{ return(NULL); }
newList = get_struct(theEnv,expr);
newList->type = nodeList->type;
newList->value = nodeList->value;
newList->nextArg = LHSParseNodesToExpression(theEnv,nodeList->right);
newList->argList = LHSParseNodesToExpression(theEnv,nodeList->bottom);
return(newList);
}
/************************************************************/
/* IncrementNandDepth: Increments the nand depth of a group */
/* of CEs. The nand depth is used to indicate the nesting */
/* of not/and or not/not CEs which are implemented using */
/* joins from the right. A single pattern within a "not" */
/* CE does not require a join from the right and its nand */
/* depth is normally not increased (except when it's */
/* within a not/and or not/not CE. The begin nand depth */
/* indicates the current nesting for a CE. The end nand */
/* depth indicates the nand depth in the following CE */
/* (assuming that the next CE is not the beginning of a */
/* new group of nand CEs). All but the last CE in a nand */
/* group should have the same begin and end nand depths. */
/* Since a single CE can be the last CE of several nand */
/* groups, it is possible to have an end nand depth that */
/* is more than 1 less than the begin nand depth of the */
/* CE. */
/************************************************************/
static void IncrementNandDepth(
void *theEnv,
struct lhsParseNode *theLHS,
int lastCE)
{
/*======================================*/
/* Loop through each CE in the group of */
/* CEs having its nand depth increased. */
/*======================================*/
for (;
theLHS != NULL;
theLHS = theLHS->bottom)
{
/*=========================================================*/
/* Increment the begin nand depth of pattern and test CEs. */
/* The last CE in the original list doesn't have its end */
/* nand depth incremented. All other last CEs in other CEs */
/* entered recursively do have their end depth incremented */
/* (unless the last CE in the recursively entered CE is */
/* the same last CE as contained in the original group */
/* when this function was first entered). */
/*=========================================================*/
if ((theLHS->type == PATTERN_CE) || (theLHS->type == TEST_CE))
{
theLHS->beginNandDepth++;
if (lastCE == FALSE) theLHS->endNandDepth++;
else if (theLHS->bottom != NULL) theLHS->endNandDepth++;
}
/*==============================================*/
/* Recursively increase the nand depth of other */
/* CEs contained within the CE having its nand */
/* depth increased. */
/*==============================================*/
else if ((theLHS->type == AND_CE) || (theLHS->type == NOT_CE))
{
IncrementNandDepth(theEnv,theLHS->right,
(lastCE ? (theLHS->bottom == NULL) : FALSE));
}
/*=====================================*/
/* All or CEs should have been removed */
/* from the LHS at this point. */
/*=====================================*/
else if (theLHS->type == OR_CE)
{ SystemError(theEnv,"REORDER",1); }
}
}
/***********************************************************/
/* CreateInitialPattern: Creates a default pattern used in */
/* the LHS of a rule under certain cirmustances (such as */
/* when a "not" or "test" CE is the first CE in an "and" */
/* CE or when no CEs are specified in the LHS of a rule. */
/***********************************************************/
static struct lhsParseNode *CreateInitialPattern(
void *theEnv,
struct patternParser *theParser)
{
struct lhsParseNode *topNode;
/*==========================================*/
/* Create the top most node of the pattern. */
/*==========================================*/
topNode = GetLHSParseNode(theEnv);
topNode->type = PATTERN_CE;
topNode->userCE = FALSE;
topNode->bottom = NULL;
/*==============================================*/
/* If a pattern type was not supplied, then try */
/* to use the (initial-fact) fact pattern. */
/*==============================================*/
if (theParser == NULL)
{ theParser = FindPatternParser(theEnv,"facts"); }
/*====================================================*/
/* If a pattern type was supplied or the initial fact */
/* pattern is available, create the initial pattern */
/* with one of those in the given order. */
/*====================================================*/
if (theParser != NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -