#include "setup.h"
#if (! RUN_TIME) && (! BLOAD_ONLY) && DEFRULE_CONSTRUCT
#include <stdio.h>
#include "cstrnutl.h"
#include "envrnmnt.h"
#include "extnfunc.h"
#include "memalloc.h"
#include "pattern.h"
#include "prntutil.h"
#include "router.h"
#include "rulelhs.h"
#if DEVELOPER && DEBUGGING_FUNCTIONS
#include "watch.h"
#include "rulepsr.h"
#endif
#include "reorder.h"
struct variableReference
{
CLIPSLexeme *name;
int depth;
struct variableReference *next;
};
struct groupReference
{
struct lhsParseNode *theGroup;
int depth;
struct groupReference *next;
};
static struct lhsParseNode *ReverseAndOr(Environment *,struct lhsParseNode *,struct lhsParseNode *,int);
static struct lhsParseNode *PerformReorder1(Environment *,struct lhsParseNode *,bool *,int);
static struct lhsParseNode *PerformReorder2(Environment *,struct lhsParseNode *,bool *,int);
static struct lhsParseNode *CompressCEs(Environment *,struct lhsParseNode *,bool *,int);
static void IncrementNandDepth(Environment *,struct lhsParseNode *,bool);
static struct lhsParseNode *CreateInitialPattern(Environment *);
static struct lhsParseNode *ReorderDriver(Environment *,struct lhsParseNode *,bool *,int,int);
static struct lhsParseNode *AddRemainingInitialPatterns(Environment *,struct lhsParseNode *);
static struct lhsParseNode *AssignPatternIndices(struct lhsParseNode *,short,int,unsigned short);
static void PropagateIndexSlotPatternValues(struct lhsParseNode *,short,unsigned short,
CLIPSLexeme *,unsigned short);
static void PropagateJoinDepth(struct lhsParseNode *,unsigned short);
static void PropagateNandDepth(struct lhsParseNode *,int,int);
static void MarkExistsNands(struct lhsParseNode *);
static unsigned short PropagateWhichCE(struct lhsParseNode *,unsigned short);
struct lhsParseNode *ReorderPatterns(
Environment *theEnv,
struct lhsParseNode *theLHS,
bool *anyChange)
{
struct lhsParseNode *newLHS, *tempLHS, *lastLHS;
if (theLHS == NULL) return(theLHS);
newLHS = GetLHSParseNode(theEnv);
newLHS->pnType = AND_CE_NODE;
newLHS->right = theLHS;
PropagateWhichCE(newLHS,0);
newLHS = ReorderDriver(theEnv,newLHS,anyChange,1,1);
newLHS = ReorderDriver(theEnv,newLHS,anyChange,2,1);
if (newLHS->pnType == OR_CE_NODE)
{
for (tempLHS = newLHS->right, lastLHS = NULL;
tempLHS != NULL;
lastLHS = tempLHS, tempLHS = tempLHS->bottom)
{
if (tempLHS->pnType != AND_CE_NODE)
{
theLHS = GetLHSParseNode(theEnv);
theLHS->pnType = AND_CE_NODE;
theLHS->right = tempLHS;
theLHS->bottom = tempLHS->bottom;
tempLHS->bottom = NULL;
if (lastLHS == NULL)
{ newLHS->right = theLHS; }
else
{ lastLHS->bottom = theLHS; }
tempLHS = theLHS;
}
}
}
else if (newLHS->pnType != AND_CE_NODE)
{
theLHS = newLHS;
newLHS = GetLHSParseNode(theEnv);
newLHS->pnType = AND_CE_NODE;
newLHS->right = theLHS;
}
if (newLHS->pnType == OR_CE_NODE)
{
for (theLHS = newLHS->right;
theLHS != NULL;
theLHS = theLHS->bottom)
{ MarkExistsNands(theLHS->right); }
}
else
{ MarkExistsNands(newLHS->right); }
AddInitialPatterns(theEnv,newLHS);
if (newLHS->pnType == OR_CE_NODE) theLHS = newLHS->right;
else theLHS = newLHS;
for (;
theLHS != NULL;
theLHS = theLHS->bottom)
{ AssignPatternIndices(theLHS->right,1,1,0); }
return(newLHS);
}
static struct lhsParseNode *ReorderDriver(
Environment *theEnv,
struct lhsParseNode *theLHS,
bool *anyChange,
int pass,
int depth)
{
struct lhsParseNode *argPtr;
struct lhsParseNode *before, *save;
bool change, newChange;
*anyChange = false;
change = true;
while (change)
{
change = false;
if ((theLHS->pnType == AND_CE_NODE) ||
(theLHS->pnType == NOT_CE_NODE) ||
(theLHS->pnType == OR_CE_NODE))
{
if (pass == 1) theLHS = PerformReorder1(theEnv,theLHS,&newChange,depth);
else theLHS = PerformReorder2(theEnv,theLHS,&newChange,depth);
if (newChange)
{
*anyChange = true;
change = true;
}
theLHS = CompressCEs(theEnv,theLHS,&newChange,depth);
if (newChange)
{
*anyChange = true;
change = true;
}
}
before = NULL;
argPtr = theLHS->right;
while (argPtr != NULL)
{
save = argPtr->bottom;
if ((argPtr->pnType == AND_CE_NODE) ||
(argPtr->pnType == NOT_CE_NODE) ||
(argPtr->pnType == OR_CE_NODE))
{
if (before == NULL)
{
argPtr->bottom = NULL;
theLHS->right = ReorderDriver(theEnv,argPtr,&newChange,pass,depth+1);
theLHS->right->bottom = save;
before = theLHS->right;
}
else
{
argPtr->bottom = NULL;
before->bottom = ReorderDriver(theEnv,argPtr,&newChange,pass,depth+1);
before->bottom->bottom = save;
before = before->bottom;
}
if (newChange)
{
*anyChange = true;
change = true;
}
}
else
{ before = argPtr; }
argPtr = save;
}
}
return(theLHS);
}
static void MarkExistsNands(
struct lhsParseNode *theLHS)
{
int currentDepth = 1;
struct lhsParseNode *tmpLHS;
while (theLHS != NULL)
{
if (IsExistsSubjoin(theLHS,currentDepth))
{
theLHS->existsNand = true;
for (tmpLHS = theLHS;
tmpLHS != NULL;
tmpLHS = tmpLHS->bottom)
{
tmpLHS->beginNandDepth--;
if (tmpLHS->endNandDepth <= currentDepth)
{ break; }
else
{ tmpLHS->endNandDepth--; }
}
}
currentDepth = theLHS->endNandDepth;
theLHS = theLHS->bottom;
}
}
void AddInitialPatterns(
Environment *theEnv,
struct lhsParseNode *theLHS)
{
struct lhsParseNode *thePattern;
if (theLHS->pnType == OR_CE_NODE)
{
for (thePattern = theLHS->right;
thePattern != NULL;
thePattern = thePattern->bottom)
{ AddInitialPatterns(theEnv,thePattern); }
return;
}
theLHS->right = AddRemainingInitialPatterns(theEnv,theLHS->right);
}
static struct lhsParseNode *PerformReorder1(
Environment *theEnv,
struct lhsParseNode *theLHS,
bool *newChange,
int depth)
{
struct lhsParseNode *argPtr, *lastArg, *nextArg;
struct lhsParseNode *tempArg, *newNode;
int count;
bool change;
change = true;
*newChange = false;
while (change)
{
change = false;
count = 1;
lastArg = NULL;
for (argPtr = theLHS->right;
argPtr != NULL;)
{
if ((theLHS->pnType == AND_CE_NODE) && (argPtr->pnType == OR_CE_NODE))
{
theLHS = ReverseAndOr(theEnv,theLHS,argPtr->right,count);
change = true;
*newChange = true;
break;
}
else if ((theLHS->pnType == NOT_CE_NODE) && (argPtr->pnType == OR_CE_NODE))
{
change = true;
*newChange = true;
tempArg = argPtr->right;
argPtr->right = NULL;
argPtr->bottom = NULL;
ReturnLHSParseNodes(theEnv,argPtr);
theLHS->pnType = AND_CE_NODE;
theLHS->right = tempArg;
while (tempArg != NULL)
{
newNode = GetLHSParseNode(theEnv);
CopyLHSParseNode(theEnv,newNode,tempArg,false);
newNode->right = tempArg->right;
newNode->bottom = NULL;
tempArg->pnType = NOT_CE_NODE;
tempArg->negated = false;
tempArg->exists = false;
tempArg->existsNand = false;
tempArg->logical = false;
tempArg->value = NULL;
tempArg->expression = NULL;
tempArg->secondaryExpression = NULL;
tempArg->right = newNode;
tempArg = tempArg->bottom;
}
break;
}
else if (((theLHS->pnType == OR_CE_NODE) && (argPtr->pnType == OR_CE_NODE)) ||
((theLHS->pnType == AND_CE_NODE) && (argPtr->pnType == AND_CE_NODE)))
{
if (argPtr->logical) theLHS->logical = true;
change = true;
*newChange = true;
tempArg = argPtr->right;
nextArg = argPtr->bottom;
argPtr->right = NULL;
argPtr->bottom = NULL;
ReturnLHSParseNodes(theEnv,argPtr);
if (lastArg == NULL)
{ theLHS->right = tempArg; }
else
{ lastArg->bottom = tempArg; }
argPtr = tempArg;
while (tempArg->bottom != NULL) tempArg = tempArg->bottom;
tempArg->bottom = nextArg;
}
else
{
count++;
lastArg = argPtr;
argPtr = argPtr->bottom;
}
}
}
return(theLHS);
}
static struct lhsParseNode *PerformReorder2(
Environment *theEnv,
struct lhsParseNode *theLHS,
bool *newChange,
int depth)
{
struct lhsParseNode *argPtr;
bool change;
change = true;
*newChange = false;
while (change)
{
change = false;
for (argPtr = theLHS->right;
argPtr != NULL;)
{
if ((theLHS->pnType == NOT_CE_NODE) &&
(argPtr->pnType == NOT_CE_NODE) &&
(argPtr->right != NULL) &&
(argPtr->right->pnType == NOT_CE_NODE))
{
change = true;
*newChange = true;
theLHS->right = argPtr->right->right;
argPtr->right->right = NULL;
ReturnLHSParseNodes(theEnv,argPtr);
break;
}
else if ((theLHS->pnType == NOT_CE_NODE) &&
(argPtr->pnType == NOT_CE_NODE) &&
(argPtr->right != NULL) &&
(argPtr->right->pnType == PATTERN_CE_NODE))
{
change = true;
*newChange = true;
CopyLHSParseNode(theEnv,theLHS,argPtr->right,false);
theLHS->negated = true;
theLHS->exists = true;
theLHS->existsNand = false;
theLHS->right = argPtr->right->right;
argPtr->right->networkTest = NULL;
argPtr->right->externalNetworkTest = NULL;
argPtr->right->secondaryNetworkTest = NULL;
argPtr->right->externalRightHash = NULL;
argPtr->right->externalLeftHash = NULL;
argPtr->right->leftHash = NULL;
argPtr->right->rightHash = NULL;
argPtr->right->betaHash = NULL;
argPtr->right->expression = NULL;
argPtr->right->secondaryExpression = NULL;
argPtr->right->userData = NULL;
argPtr->right->right = NULL;
argPtr->right->bottom = NULL;
ReturnLHSParseNodes(theEnv,argPtr);
break;
}
else if ((theLHS->pnType == NOT_CE_NODE) && (argPtr->pnType == PATTERN_CE_NODE))
{
change = true;
*newChange = true;
CopyLHSParseNode(theEnv,theLHS,argPtr,false);
theLHS->negated = true;
theLHS->exists = false;
theLHS->existsNand = false;
theLHS->right = argPtr->right;
argPtr->networkTest = NULL;
argPtr->externalNetworkTest = NULL;
argPtr->secondaryNetworkTest = NULL;
argPtr->externalRightHash = NULL;
argPtr->externalLeftHash = NULL;
argPtr->constantSelector = NULL;
argPtr->constantValue = NULL;
argPtr->leftHash = NULL;
argPtr->rightHash = NULL;
argPtr->betaHash = NULL;
argPtr->expression = NULL;
argPtr->secondaryExpression = NULL;
argPtr->userData = NULL;
argPtr->right = NULL;
argPtr->bottom = NULL;
ReturnLHSParseNodes(theEnv,argPtr);
break;
}
else if ((theLHS->pnType == NOT_CE_NODE) &&
((argPtr->pnType == AND_CE_NODE) || (argPtr->pnType == NOT_CE_NODE)))
{
change = true;
*newChange = true;
theLHS->pnType = argPtr->pnType;
theLHS->negated = argPtr->negated;
theLHS->exists = argPtr->exists;
theLHS->existsNand = argPtr->existsNand;
theLHS->value = argPtr->value;
theLHS->logical = argPtr->logical;
theLHS->right = argPtr->right;
argPtr->right = NULL;
argPtr->bottom = NULL;
ReturnLHSParseNodes(theEnv,argPtr);
IncrementNandDepth(theEnv,theLHS->right,true);
break;
}
else
{
argPtr = argPtr->bottom;
}
}
}
return(theLHS);
}
static struct lhsParseNode *ReverseAndOr(
Environment *theEnv,
struct lhsParseNode *listOfCEs,
struct lhsParseNode *orCE,
int orPosition)
{
int count;
struct lhsParseNode *listOfExpandedOrCEs = NULL;
struct lhsParseNode *lastExpandedOrCE = NULL;
struct lhsParseNode *copyOfCEs, *replaceCE;
while (orCE != NULL)
{
copyOfCEs = CopyLHSParseNodes(theEnv,listOfCEs);
for (count = 1, replaceCE = copyOfCEs->right;
count != orPosition;
count++, replaceCE = replaceCE->bottom)
{ }
ReturnLHSParseNodes(theEnv,replaceCE->right);
CopyLHSParseNode(theEnv,replaceCE,orCE,true);
replaceCE->right = CopyLHSParseNodes(theEnv,orCE->right);
if (lastExpandedOrCE == NULL)
{
listOfExpandedOrCEs = copyOfCEs;
copyOfCEs->bottom = NULL;
lastExpandedOrCE = copyOfCEs;
}
else
{
lastExpandedOrCE->bottom = copyOfCEs;
copyOfCEs->bottom = NULL;
lastExpandedOrCE = copyOfCEs;
}
orCE = orCE->bottom;
}
ReturnLHSParseNodes(theEnv,listOfCEs);
copyOfCEs = GetLHSParseNode(theEnv);
copyOfCEs->pnType = OR_CE_NODE;
copyOfCEs->right = listOfExpandedOrCEs;
return(copyOfCEs);
}
static struct lhsParseNode *CompressCEs(
Environment *theEnv,
struct lhsParseNode *theLHS,
bool *newChange,
int depth)
{
struct lhsParseNode *argPtr, *lastArg, *nextArg;
struct lhsParseNode *tempArg;
bool change;
struct expr *e1, *e2;
change = true;
*newChange = false;
while (change)
{
change = false;
lastArg = NULL;
for (argPtr = theLHS->right;
argPtr != NULL;)
{
if (((theLHS->pnType == OR_CE_NODE) && (argPtr->pnType == OR_CE_NODE)) ||
((theLHS->pnType == AND_CE_NODE) && (argPtr->pnType == AND_CE_NODE)))
{
if (argPtr->logical) theLHS->logical = true;
change = true;
*newChange = true;
tempArg = argPtr->right;
nextArg = argPtr->bottom;
argPtr->right = NULL;
argPtr->bottom = NULL;
ReturnLHSParseNodes(theEnv,argPtr);
if (lastArg == NULL)
{ theLHS->right = tempArg; }
else
{ lastArg->bottom = tempArg; }
argPtr = tempArg;
while (tempArg->bottom != NULL) tempArg = tempArg->bottom;
tempArg->bottom = nextArg;
}
else if ((theLHS->pnType == NOT_CE_NODE) && (argPtr->pnType == TEST_CE_NODE))
{
change = true;
*newChange = true;
tempArg = GetLHSParseNode(theEnv);
tempArg->pnType = FCALL_NODE;
tempArg->value = ExpressionData(theEnv)->PTR_NOT;
tempArg->bottom = argPtr->expression;
argPtr->expression = tempArg;
CopyLHSParseNode(theEnv,theLHS,argPtr,true);
ReturnLHSParseNodes(theEnv,argPtr);
theLHS->right = NULL;
break;
}
else if ((theLHS->pnType == AND_CE_NODE) && (argPtr->pnType == TEST_CE_NODE) &&
((argPtr->bottom != NULL) ? argPtr->bottom->pnType == TEST_CE_NODE :
false) &&
(argPtr->beginNandDepth == argPtr->endNandDepth) &&
(argPtr->endNandDepth == argPtr->bottom->beginNandDepth))
{
change = true;
*newChange = true;
argPtr->expression = CombineLHSParseNodes(theEnv,argPtr->expression,argPtr->bottom->expression);
argPtr->bottom->expression = NULL;
tempArg = argPtr->bottom;
argPtr->bottom = tempArg->bottom;
tempArg->bottom = NULL;
ReturnLHSParseNodes(theEnv,tempArg);
}
else if ((theLHS->pnType == AND_CE_NODE) && (argPtr->pnType == PATTERN_CE_NODE) &&
((argPtr->bottom != NULL) ? argPtr->bottom->pnType == TEST_CE_NODE :
false) &&
(argPtr->negated == false) &&
(argPtr->exists == false) &&
(argPtr->beginNandDepth == argPtr->endNandDepth) &&
(argPtr->endNandDepth == argPtr->bottom->beginNandDepth))
{
int endNandDepth;
change = true;
*newChange = true;
endNandDepth = argPtr->bottom->endNandDepth;
if (argPtr->negated || argPtr->exists)
{
e1 = LHSParseNodesToExpression(theEnv,argPtr->secondaryExpression);
e2 = LHSParseNodesToExpression(theEnv,argPtr->bottom->expression);
e1 = CombineExpressions(theEnv,e1,e2);
ReturnLHSParseNodes(theEnv,argPtr->secondaryExpression);
argPtr->secondaryExpression = ExpressionToLHSParseNodes(theEnv,e1);
ReturnExpression(theEnv,e1);
}
else
{
argPtr->expression = CombineLHSParseNodes(theEnv,argPtr->expression,argPtr->bottom->expression);
argPtr->bottom->expression = NULL;
}
if ((theLHS->right == argPtr) && ((argPtr->beginNandDepth - 1) == endNandDepth))
{
if (argPtr->negated)
{
argPtr->negated = false;
argPtr->exists = true;
e1 = LHSParseNodesToExpression(theEnv,argPtr->secondaryExpression);
e1 = NegateExpression(theEnv,e1);
ReturnLHSParseNodes(theEnv,argPtr->secondaryExpression);
argPtr->secondaryExpression = ExpressionToLHSParseNodes(theEnv,e1);
ReturnExpression(theEnv,e1);
}
else if (argPtr->exists)
{
argPtr->negated = true;
argPtr->exists = false;
e1 = LHSParseNodesToExpression(theEnv,argPtr->secondaryExpression);
e1 = NegateExpression(theEnv,e1);
ReturnLHSParseNodes(theEnv,argPtr->secondaryExpression);
argPtr->secondaryExpression = ExpressionToLHSParseNodes(theEnv,e1);
ReturnExpression(theEnv,e1);
}
else
{
argPtr->negated = true;
}
PropagateNandDepth(argPtr,endNandDepth,endNandDepth);
}
tempArg = argPtr->bottom;
argPtr->bottom = tempArg->bottom;
tempArg->bottom = NULL;
ReturnLHSParseNodes(theEnv,tempArg);
}
else if ((theLHS->pnType == AND_CE_NODE) && (argPtr->pnType == TEST_CE_NODE) &&
(theLHS->right == argPtr) && (argPtr->bottom == NULL))
{
change = true;
*newChange = true;
CopyLHSParseNode(theEnv,theLHS,argPtr,true);
theLHS->right = NULL;
ReturnLHSParseNodes(theEnv,argPtr);
break;
}
else if ((theLHS->pnType == AND_CE_NODE) && (argPtr->pnType == PATTERN_CE_NODE) &&
(theLHS->right == argPtr) && (argPtr->bottom == NULL) && (depth > 1))
{
change = true;
*newChange = true;
CopyLHSParseNode(theEnv,theLHS,argPtr,false);
theLHS->right = argPtr->right;
argPtr->networkTest = NULL;
argPtr->externalNetworkTest = NULL;
argPtr->secondaryNetworkTest = NULL;
argPtr->externalRightHash = NULL;
argPtr->externalLeftHash = NULL;
argPtr->constantSelector = NULL;
argPtr->constantValue = NULL;
argPtr->leftHash = NULL;
argPtr->rightHash = NULL;
argPtr->betaHash = NULL;
argPtr->expression = NULL;
argPtr->secondaryExpression = NULL;
argPtr->userData = NULL;
argPtr->right = NULL;
argPtr->bottom = NULL;
ReturnLHSParseNodes(theEnv,argPtr);
break;
}
else
{
lastArg = argPtr;
argPtr = argPtr->bottom;
}
}
}
return(theLHS);
}
struct lhsParseNode *CopyLHSParseNodes(
Environment *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);
}
void CopyLHSParseNode(
Environment *theEnv,
struct lhsParseNode *dest,
struct lhsParseNode *src,
bool duplicate)
{
dest->pnType = src->pnType;
dest->value = src->value;
dest->negated = src->negated;
dest->exists = src->exists;
dest->existsNand = src->existsNand;
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->whichCE = src->whichCE;
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;
dest->joinDepth = src->joinDepth;
if (duplicate)
{
dest->networkTest = CopyExpression(theEnv,src->networkTest);
dest->externalNetworkTest = CopyExpression(theEnv,src->externalNetworkTest);
dest->secondaryNetworkTest = CopyExpression(theEnv,src->secondaryNetworkTest);
dest->externalRightHash = CopyExpression(theEnv,src->externalRightHash);
dest->externalLeftHash = CopyExpression(theEnv,src->externalLeftHash);
dest->constantSelector = CopyExpression(theEnv,src->constantSelector);
dest->constantValue = CopyExpression(theEnv,src->constantValue);
dest->leftHash = CopyExpression(theEnv,src->leftHash);
dest->betaHash = CopyExpression(theEnv,src->betaHash);
dest->rightHash = CopyExpression(theEnv,src->rightHash);
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->secondaryExpression = CopyLHSParseNodes(theEnv,src->secondaryExpression);
dest->constraints = CopyConstraintRecord(theEnv,src->constraints);
if (dest->constraints != NULL) dest->derivedConstraints = true;
else dest->derivedConstraints = false;
}
else
{
dest->networkTest = src->networkTest;
dest->externalNetworkTest = src->externalNetworkTest;
dest->secondaryNetworkTest = src->secondaryNetworkTest;
dest->externalRightHash = src->externalRightHash;
dest->externalLeftHash = src->externalLeftHash;
dest->constantSelector = src->constantSelector;
dest->constantValue = src->constantValue;
dest->leftHash = src->leftHash;
dest->betaHash = src->betaHash;
dest->rightHash = src->rightHash;
dest->userData = src->userData;
dest->expression = src->expression;
dest->secondaryExpression = src->secondaryExpression;
dest->derivedConstraints = false;
dest->constraints = src->constraints;
}
}
struct lhsParseNode *GetLHSParseNode(
Environment *theEnv)
{
struct lhsParseNode *newNode;
newNode = get_struct(theEnv,lhsParseNode);
newNode->pnType = UNKNOWN_NODE;
newNode->value = NULL;
newNode->negated = false;
newNode->exists = false;
newNode->existsNand = 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->whichCE = 0;
newNode->constraints = NULL;
newNode->referringNode = NULL;
newNode->patternType = NULL;
newNode->pattern = -1;
newNode->index = NO_INDEX;
newNode->slot = NULL;
newNode->slotNumber = UNSPECIFIED_SLOT;
newNode->beginNandDepth = 1;
newNode->endNandDepth = 1;
newNode->joinDepth = 0;
newNode->userData = NULL;
newNode->networkTest = NULL;
newNode->externalNetworkTest = NULL;
newNode->secondaryNetworkTest = NULL;
newNode->externalRightHash = NULL;
newNode->externalLeftHash = NULL;
newNode->constantSelector = NULL;
newNode->constantValue = NULL;
newNode->leftHash = NULL;
newNode->betaHash = NULL;
newNode->rightHash = NULL;
newNode->expression = NULL;
newNode->secondaryExpression = NULL;
newNode->right = NULL;
newNode->bottom = NULL;
return(newNode);
}
void ReturnLHSParseNodes(
Environment *theEnv,
struct lhsParseNode *waste)
{
if (waste != NULL)
{
ReturnExpression(theEnv,waste->networkTest);
ReturnExpression(theEnv,waste->externalNetworkTest);
ReturnExpression(theEnv,waste->secondaryNetworkTest);
ReturnExpression(theEnv,waste->externalRightHash);
ReturnExpression(theEnv,waste->externalLeftHash);
ReturnExpression(theEnv,waste->constantSelector);
ReturnExpression(theEnv,waste->constantValue);
ReturnExpression(theEnv,waste->leftHash);
ReturnExpression(theEnv,waste->betaHash);
ReturnExpression(theEnv,waste->rightHash);
ReturnLHSParseNodes(theEnv,waste->right);
ReturnLHSParseNodes(theEnv,waste->bottom);
ReturnLHSParseNodes(theEnv,waste->expression);
ReturnLHSParseNodes(theEnv,waste->secondaryExpression);
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);
}
}
struct lhsParseNode *ExpressionToLHSParseNodes(
Environment *theEnv,
struct expr *expressionList)
{
struct lhsParseNode *newList, *theList;
struct functionDefinition *theFunction;
unsigned int i;
unsigned theRestriction2;
if (expressionList == NULL) return NULL;
newList = GetLHSParseNode(theEnv);
newList->pnType = TypeToNodeType(expressionList->type);
newList->value = expressionList->value;
newList->right = ExpressionToLHSParseNodes(theEnv,expressionList->nextArg);
newList->bottom = ExpressionToLHSParseNodes(theEnv,expressionList->argList);
if (newList->pnType != FCALL_NODE) return(newList);
theFunction = newList->functionValue;
for (theList = newList->bottom, i = 1;
theList != NULL;
theList = theList->right, i++)
{
if (theList->pnType == SF_VARIABLE_NODE)
{
theRestriction2 = GetNthRestriction(theEnv,theFunction,i);
theList->constraints = ArgumentTypeToConstraintRecord(theEnv,theRestriction2);
theList->derivedConstraints = true;
}
}
return(newList);
}
struct expr *LHSParseNodesToExpression(
Environment *theEnv,
struct lhsParseNode *nodeList)
{
struct expr *newList;
if (nodeList == NULL)
{ return NULL; }
newList = get_struct(theEnv,expr);
newList->type = NodeTypeToType(nodeList);
newList->value = nodeList->value;
newList->nextArg = LHSParseNodesToExpression(theEnv,nodeList->right);
newList->argList = LHSParseNodesToExpression(theEnv,nodeList->bottom);
return(newList);
}
bool ConstantNode(
struct lhsParseNode *theNode)
{
switch (theNode->pnType)
{
case SYMBOL_NODE:
case STRING_NODE:
case INTEGER_NODE:
case FLOAT_NODE:
#if OBJECT_SYSTEM
case INSTANCE_NAME_NODE:
#endif
return true;
default:
return false;
}
return false;
}
unsigned short NodeTypeToType(
struct lhsParseNode *theNode)
{
switch (theNode->pnType)
{
case FLOAT_NODE:
return FLOAT_TYPE;
case INTEGER_NODE:
return INTEGER_TYPE;
case SYMBOL_NODE:
return SYMBOL_TYPE;
case STRING_NODE:
return STRING_TYPE;
case INSTANCE_NAME_NODE:
return INSTANCE_NAME_TYPE;
case SF_VARIABLE_NODE:
return SF_VARIABLE;
case MF_VARIABLE_NODE:
return MF_VARIABLE;
case GBL_VARIABLE_NODE:
return GBL_VARIABLE;
case FCALL_NODE:
return FCALL;
case PCALL_NODE:
return PCALL;
case GCALL_NODE:
return GCALL;
case FACT_STORE_MULTIFIELD_NODE:
return FACT_STORE_MULTIFIELD;
case DEFTEMPLATE_PTR_NODE:
return DEFTEMPLATE_PTR;
case DEFCLASS_PTR_NODE:
return DEFCLASS_PTR;
default:
return VOID_TYPE;
}
}
ParseNodeType TypeToNodeType(
unsigned short theType)
{
switch (theType)
{
case FLOAT_TYPE:
return FLOAT_NODE;
case INTEGER_TYPE:
return INTEGER_NODE;
case SYMBOL_TYPE:
return SYMBOL_NODE;
case STRING_TYPE:
return STRING_NODE;
case INSTANCE_NAME_TYPE:
return INSTANCE_NAME_NODE;
case SF_VARIABLE:
return SF_VARIABLE_NODE;
case MF_VARIABLE:
return MF_VARIABLE_NODE;
case GBL_VARIABLE:
return GBL_VARIABLE_NODE;
case FCALL:
return FCALL_NODE;
case PCALL:
return PCALL_NODE;
case GCALL:
return GCALL_NODE;
case FACT_STORE_MULTIFIELD:
return FACT_STORE_MULTIFIELD_NODE;
case DEFTEMPLATE_PTR:
return DEFTEMPLATE_PTR_NODE;
case DEFCLASS_PTR:
return DEFCLASS_PTR_NODE;
default:
return UNKNOWN_NODE;
}
}
static void IncrementNandDepth(
Environment *theEnv,
struct lhsParseNode *theLHS,
bool lastCE)
{
for (;
theLHS != NULL;
theLHS = theLHS->bottom)
{
if ((theLHS->pnType == PATTERN_CE_NODE) || (theLHS->pnType == TEST_CE_NODE))
{
theLHS->beginNandDepth++;
if (lastCE == false) theLHS->endNandDepth++;
else if (theLHS->bottom != NULL) theLHS->endNandDepth++;
}
else if ((theLHS->pnType == AND_CE_NODE) || (theLHS->pnType == NOT_CE_NODE))
{
IncrementNandDepth(theEnv,theLHS->right,
(lastCE ? (theLHS->bottom == NULL) : false));
}
else if (theLHS->pnType == OR_CE_NODE)
{ SystemError(theEnv,"REORDER",1); }
}
}
static struct lhsParseNode *CreateInitialPattern(
Environment *theEnv)
{
struct lhsParseNode *topNode;
topNode = GetLHSParseNode(theEnv);
topNode->pnType = PATTERN_CE_NODE;
topNode->userCE = false;
topNode->bottom = NULL;
return(topNode);
}
static struct lhsParseNode *AddRemainingInitialPatterns(
Environment *theEnv,
struct lhsParseNode *theLHS)
{
struct lhsParseNode *lastNode = NULL, *thePattern, *rv = theLHS;
int currentDepth = 1;
while (theLHS != NULL)
{
if ((theLHS->pnType == TEST_CE_NODE) &&
(theLHS->beginNandDepth > currentDepth))
{
thePattern = CreateInitialPattern(theEnv);
thePattern->beginNandDepth = theLHS->beginNandDepth;
thePattern->endNandDepth = theLHS->beginNandDepth;
thePattern->logical = theLHS->logical;
thePattern->existsNand = theLHS->existsNand;
theLHS->existsNand = false;
thePattern->bottom = theLHS;
if (lastNode == NULL)
{ rv = thePattern; }
else
{ lastNode->bottom = thePattern; }
}
lastNode = theLHS;
currentDepth = theLHS->endNandDepth;
theLHS = theLHS->bottom;
}
return(rv);
}
static struct lhsParseNode *AssignPatternIndices(
struct lhsParseNode *theLHS,
short startIndex,
int nandDepth,
unsigned short joinDepth)
{
struct lhsParseNode *theField;
while (theLHS != NULL)
{
if (theLHS->beginNandDepth > nandDepth)
{
theLHS = AssignPatternIndices(theLHS,startIndex,nandDepth+1,joinDepth);
if (theLHS->endNandDepth < nandDepth) return(theLHS);
startIndex++;
joinDepth++;
}
else if (theLHS->pnType == TEST_CE_NODE)
{
if (joinDepth == 0)
{ joinDepth++; }
theLHS->joinDepth = joinDepth - 1;
PropagateJoinDepth(theLHS->expression,joinDepth - 1);
PropagateNandDepth(theLHS->expression,theLHS->beginNandDepth,theLHS->endNandDepth);
if (theLHS->endNandDepth < nandDepth) return(theLHS);
}
else if (theLHS->pnType == PATTERN_CE_NODE)
{
if (theLHS->expression != NULL)
{
PropagateJoinDepth(theLHS->expression,joinDepth);
PropagateNandDepth(theLHS->expression,theLHS->beginNandDepth,theLHS->endNandDepth);
}
theLHS->pattern = startIndex;
theLHS->joinDepth = joinDepth;
PropagateJoinDepth(theLHS->right,joinDepth);
PropagateNandDepth(theLHS->right,theLHS->beginNandDepth,theLHS->endNandDepth);
for (theField = theLHS->right; theField != NULL; theField = theField->right)
{
theField->pattern = startIndex;
PropagateIndexSlotPatternValues(theField,theField->pattern,
theField->index,theField->slot,
theField->slotNumber);
}
if (theLHS->endNandDepth < nandDepth) return(theLHS);
startIndex++;
joinDepth++;
}
theLHS = theLHS->bottom;
}
return NULL;
}
static void PropagateIndexSlotPatternValues(
struct lhsParseNode *theField,
short thePattern,
unsigned short theIndex,
CLIPSLexeme *theSlot,
unsigned short theSlotNumber)
{
struct lhsParseNode *tmpNode, *andField;
if (theField == NULL) return;
if (theField->multifieldSlot)
{
theField->pattern = thePattern;
if ((theIndex > 0) && (theIndex != NO_INDEX))
{ theField->index = theIndex; }
theField->slot = theSlot;
theField->slotNumber = theSlotNumber;
for (tmpNode = theField->bottom;
tmpNode != NULL;
tmpNode = tmpNode->right)
{
tmpNode->pattern = thePattern;
tmpNode->slot = theSlot;
PropagateIndexSlotPatternValues(tmpNode,thePattern,tmpNode->index,
theSlot,theSlotNumber);
}
return;
}
for (theField = theField->bottom;
theField != NULL;
theField = theField->bottom)
{
for (andField = theField; andField != NULL; andField = andField->right)
{
andField->pattern = thePattern;
if ((theIndex > 0) && (theIndex != NO_INDEX))
{ andField->index = theIndex; }
andField->slot = theSlot;
andField->slotNumber = theSlotNumber;
}
}
}
static void PropagateJoinDepth(
struct lhsParseNode *theField,
unsigned short joinDepth)
{
while (theField != NULL)
{
theField->joinDepth = joinDepth;
if (theField->bottom != NULL)
{ PropagateJoinDepth(theField->bottom,joinDepth); }
if (theField->expression != NULL)
{ PropagateJoinDepth(theField->expression,joinDepth); }
if (theField->secondaryExpression != NULL)
{ PropagateJoinDepth(theField->secondaryExpression,joinDepth); }
theField = theField->right;
}
}
static void PropagateNandDepth(
struct lhsParseNode *theField,
int beginDepth,
int endDepth)
{
if (theField == NULL) return;
for (; theField != NULL; theField = theField->right)
{
theField->beginNandDepth = beginDepth;
theField->endNandDepth = endDepth;
PropagateNandDepth(theField->expression,beginDepth,endDepth);
PropagateNandDepth(theField->secondaryExpression,beginDepth,endDepth);
PropagateNandDepth(theField->bottom,beginDepth,endDepth);
}
}
static unsigned short PropagateWhichCE(
struct lhsParseNode *theField,
unsigned short whichCE)
{
while (theField != NULL)
{
if ((theField->pnType == PATTERN_CE_NODE) || (theField->pnType == TEST_CE_NODE))
{ whichCE++; }
theField->whichCE = whichCE;
whichCE = PropagateWhichCE(theField->right,whichCE);
PropagateWhichCE(theField->expression,whichCE);
theField = theField->bottom;
}
return whichCE;
}
bool IsExistsSubjoin(
struct lhsParseNode *theLHS,
int parentDepth)
{
int startDepth = theLHS->beginNandDepth;
if ((startDepth - parentDepth) != 2)
{ return false; }
while (theLHS->endNandDepth >= startDepth)
{ theLHS = theLHS->bottom; }
if (theLHS->endNandDepth <= parentDepth)
{ return true; }
return false;
}
struct lhsParseNode *CombineLHSParseNodes(
Environment *theEnv,
struct lhsParseNode *expr1,
struct lhsParseNode *expr2)
{
struct lhsParseNode *tempPtr;
if (expr1 == NULL) return(expr2);
if (expr2 == NULL) return(expr1);
if ((expr1->value == ExpressionData(theEnv)->PTR_AND) &&
(expr2->value != ExpressionData(theEnv)->PTR_AND))
{
tempPtr = expr1->bottom;
if (tempPtr == NULL)
{
rtn_struct(theEnv,lhsParseNode,expr1);
return(expr2);
}
while (tempPtr->right != NULL)
{ tempPtr = tempPtr->right; }
tempPtr->right = expr2;
return(expr1);
}
if ((expr1->value != ExpressionData(theEnv)->PTR_AND) &&
(expr2->value == ExpressionData(theEnv)->PTR_AND))
{
tempPtr = expr2->bottom;
if (tempPtr == NULL)
{
rtn_struct(theEnv,lhsParseNode,expr2);
return(expr1);
}
expr2->bottom = expr1;
expr1->right = tempPtr;
return(expr2);
}
if ((expr1->value == ExpressionData(theEnv)->PTR_AND) &&
(expr2->value == ExpressionData(theEnv)->PTR_AND))
{
tempPtr = expr1->bottom;
if (tempPtr == NULL)
{
rtn_struct(theEnv,lhsParseNode,expr1);
return(expr2);
}
while (tempPtr->right != NULL)
{ tempPtr = tempPtr->right; }
tempPtr->right = expr2->bottom;
rtn_struct(theEnv,lhsParseNode,expr2);
return(expr1);
}
tempPtr = GetLHSParseNode(theEnv);
tempPtr->pnType = FCALL_NODE;
tempPtr->value = ExpressionData(theEnv)->PTR_AND;
tempPtr->bottom = expr1;
expr1->right = expr2;
return(tempPtr);
}
#endif