#include <stdio.h>
#include "setup.h"
#if DEFRULE_CONSTRUCT
#include "drive.h"
#include "engine.h"
#include "envrnmnt.h"
#include "incrrset.h"
#include "match.h"
#include "memalloc.h"
#include "moduldef.h"
#include "pattern.h"
#include "prntutil.h"
#include "retract.h"
#include "router.h"
#include "rulecom.h"
#include "reteutil.h"
static void TraceErrorToRuleDriver(Environment *,struct joinNode *,const char *,int,bool);
static struct alphaMemoryHash *FindAlphaMemory(Environment *,struct patternNodeHeader *,unsigned long);
static unsigned long AlphaMemoryHashValue(struct patternNodeHeader *,unsigned long);
static void UnlinkAlphaMemory(Environment *,struct patternNodeHeader *,struct alphaMemoryHash *);
static void UnlinkAlphaMemoryBucketSiblings(Environment *,struct alphaMemoryHash *);
static void InitializePMLinks(struct partialMatch *);
static void UnlinkBetaPartialMatchfromAlphaAndBetaLineage(struct partialMatch *);
static int CountPriorPatterns(struct joinNode *);
static void ResizeBetaMemory(Environment *,struct betaMemory *);
static void ResetBetaMemory(Environment *,struct betaMemory *);
#if (CONSTRUCT_COMPILER || BLOAD_AND_BSAVE) && (! RUN_TIME)
static void TagNetworkTraverseJoins(Environment *,unsigned long *,unsigned long *,struct joinNode *);
#endif
void PrintPartialMatch(
Environment *theEnv,
const char *logicalName,
struct partialMatch *list)
{
struct patternEntity *matchingItem;
unsigned short i;
for (i = 0; i < list->bcount;)
{
if ((get_nth_pm_match(list,i) != NULL) &&
(get_nth_pm_match(list,i)->matchingItem != NULL))
{
matchingItem = get_nth_pm_match(list,i)->matchingItem;
(*matchingItem->theInfo->base.shortPrintFunction)(theEnv,logicalName,matchingItem);
}
else
{ WriteString(theEnv,logicalName,"*"); }
i++;
if (i < list->bcount) WriteString(theEnv,logicalName,",");
}
}
struct partialMatch *CopyPartialMatch(
Environment *theEnv,
struct partialMatch *list)
{
struct partialMatch *linker;
unsigned short i;
linker = get_var_struct(theEnv,partialMatch,sizeof(struct genericMatch) *
(list->bcount - 1));
InitializePMLinks(linker);
linker->betaMemory = true;
linker->busy = false;
linker->rhsMemory = false;
linker->deleting = false;
linker->bcount = list->bcount;
linker->hashValue = 0;
for (i = 0; i < linker->bcount; i++) linker->binds[i] = list->binds[i];
return(linker);
}
struct partialMatch *CreateEmptyPartialMatch(
Environment *theEnv)
{
struct partialMatch *linker;
linker = get_struct(theEnv,partialMatch);
InitializePMLinks(linker);
linker->betaMemory = true;
linker->busy = false;
linker->rhsMemory = false;
linker->deleting = false;
linker->bcount = 1;
linker->hashValue = 0;
linker->binds[0].gm.theValue = NULL;
return(linker);
}
static void InitializePMLinks(
struct partialMatch *theMatch)
{
theMatch->nextInMemory = NULL;
theMatch->prevInMemory = NULL;
theMatch->nextRightChild = NULL;
theMatch->prevRightChild = NULL;
theMatch->nextLeftChild = NULL;
theMatch->prevLeftChild = NULL;
theMatch->children = NULL;
theMatch->rightParent = NULL;
theMatch->leftParent = NULL;
theMatch->blockList = NULL;
theMatch->nextBlocked = NULL;
theMatch->prevBlocked = NULL;
theMatch->marker = NULL;
theMatch->dependents = NULL;
}
void UpdateBetaPMLinks(
Environment *theEnv,
struct partialMatch *thePM,
struct partialMatch *lhsBinds,
struct partialMatch *rhsBinds,
struct joinNode *join,
unsigned long hashValue,
int side)
{
unsigned long betaLocation;
struct betaMemory *theMemory;
if (side == LHS)
{
theMemory = join->leftMemory;
thePM->rhsMemory = false;
}
else
{
theMemory = join->rightMemory;
thePM->rhsMemory = true;
}
thePM->hashValue = hashValue;
betaLocation = hashValue % theMemory->size;
if (side == LHS)
{
thePM->nextInMemory = theMemory->beta[betaLocation];
if (theMemory->beta[betaLocation] != NULL)
{ theMemory->beta[betaLocation]->prevInMemory = thePM; }
theMemory->beta[betaLocation] = thePM;
}
else
{
if (theMemory->last[betaLocation] != NULL)
{
theMemory->last[betaLocation]->nextInMemory = thePM;
thePM->prevInMemory = theMemory->last[betaLocation];
}
else
{ theMemory->beta[betaLocation] = thePM; }
theMemory->last[betaLocation] = thePM;
}
theMemory->count++;
if (side == LHS)
{ join->memoryLeftAdds++; }
else
{ join->memoryRightAdds++; }
thePM->owner = join;
if (rhsBinds != NULL)
{
thePM->nextRightChild = rhsBinds->children;
if (rhsBinds->children != NULL)
{ rhsBinds->children->prevRightChild = thePM; }
rhsBinds->children = thePM;
thePM->rightParent = rhsBinds;
}
if (lhsBinds != NULL)
{
thePM->nextLeftChild = lhsBinds->children;
if (lhsBinds->children != NULL)
{ lhsBinds->children->prevLeftChild = thePM; }
lhsBinds->children = thePM;
thePM->leftParent = lhsBinds;
}
if (! DefruleData(theEnv)->BetaMemoryResizingFlag)
{ return; }
if ((theMemory->size > 1) &&
(theMemory->count > (theMemory->size * 11)))
{ ResizeBetaMemory(theEnv,theMemory); }
}
void AddBlockedLink(
struct partialMatch *thePM,
struct partialMatch *rhsBinds)
{
thePM->marker = rhsBinds;
thePM->nextBlocked = rhsBinds->blockList;
if (rhsBinds->blockList != NULL)
{ rhsBinds->blockList->prevBlocked = thePM; }
rhsBinds->blockList = thePM;
}
void RemoveBlockedLink(
struct partialMatch *thePM)
{
struct partialMatch *blocker;
if (thePM->prevBlocked == NULL)
{
blocker = (struct partialMatch *) thePM->marker;
blocker->blockList = thePM->nextBlocked;
}
else
{ thePM->prevBlocked->nextBlocked = thePM->nextBlocked; }
if (thePM->nextBlocked != NULL)
{ thePM->nextBlocked->prevBlocked = thePM->prevBlocked; }
thePM->nextBlocked = NULL;
thePM->prevBlocked = NULL;
thePM->marker = NULL;
}
void UnlinkBetaPMFromNodeAndLineage(
Environment *theEnv,
struct joinNode *join,
struct partialMatch *thePM,
int side)
{
unsigned long betaLocation;
struct betaMemory *theMemory;
if (side == LHS)
{ theMemory = join->leftMemory; }
else
{ theMemory = join->rightMemory; }
theMemory->count--;
if (side == LHS)
{ join->memoryLeftDeletes++; }
else
{ join->memoryRightDeletes++; }
betaLocation = thePM->hashValue % theMemory->size;
if ((side == RHS) &&
(theMemory->last[betaLocation] == thePM))
{ theMemory->last[betaLocation] = thePM->prevInMemory; }
if (thePM->prevInMemory == NULL)
{
betaLocation = thePM->hashValue % theMemory->size;
theMemory->beta[betaLocation] = thePM->nextInMemory;
}
else
{ thePM->prevInMemory->nextInMemory = thePM->nextInMemory; }
if (thePM->nextInMemory != NULL)
{ thePM->nextInMemory->prevInMemory = thePM->prevInMemory; }
thePM->nextInMemory = NULL;
thePM->prevInMemory = NULL;
UnlinkBetaPartialMatchfromAlphaAndBetaLineage(thePM);
if (! DefruleData(theEnv)->BetaMemoryResizingFlag)
{ return; }
if ((theMemory->count == 0) && (theMemory->size > 1))
{ ResetBetaMemory(theEnv,theMemory); }
}
void UnlinkNonLeftLineage(
Environment *theEnv,
struct joinNode *join,
struct partialMatch *thePM,
int side)
{
unsigned long betaLocation;
struct betaMemory *theMemory;
struct partialMatch *tempPM;
if (side == LHS)
{ theMemory = join->leftMemory; }
else
{ theMemory = join->rightMemory; }
theMemory->count--;
if (side == LHS)
{ join->memoryLeftDeletes++; }
else
{ join->memoryRightDeletes++; }
betaLocation = thePM->hashValue % theMemory->size;
if ((side == RHS) &&
(theMemory->last[betaLocation] == thePM))
{ theMemory->last[betaLocation] = thePM->prevInMemory; }
if (thePM->prevInMemory == NULL)
{
betaLocation = thePM->hashValue % theMemory->size;
theMemory->beta[betaLocation] = thePM->nextInMemory;
}
else
{ thePM->prevInMemory->nextInMemory = thePM->nextInMemory; }
if (thePM->nextInMemory != NULL)
{ thePM->nextInMemory->prevInMemory = thePM->prevInMemory; }
if (thePM->prevRightChild == NULL)
{
if (thePM->rightParent != NULL)
{
thePM->rightParent->children = thePM->nextRightChild;
if (thePM->nextRightChild != NULL)
{
thePM->rightParent->children = thePM->nextRightChild;
thePM->nextRightChild->rightParent = thePM->rightParent;
}
}
}
else
{ thePM->prevRightChild->nextRightChild = thePM->nextRightChild; }
if (thePM->nextRightChild != NULL)
{ thePM->nextRightChild->prevRightChild = thePM->prevRightChild; }
if (thePM->prevBlocked == NULL)
{
tempPM = (struct partialMatch *) thePM->marker;
if (tempPM != NULL)
{ tempPM->blockList = thePM->nextBlocked; }
}
else
{ thePM->prevBlocked->nextBlocked = thePM->nextBlocked; }
if (thePM->nextBlocked != NULL)
{ thePM->nextBlocked->prevBlocked = thePM->prevBlocked; }
if (! DefruleData(theEnv)->BetaMemoryResizingFlag)
{ return; }
if ((theMemory->count == 0) && (theMemory->size > 1))
{ ResetBetaMemory(theEnv,theMemory); }
}
static void UnlinkBetaPartialMatchfromAlphaAndBetaLineage(
struct partialMatch *thePM)
{
struct partialMatch *tempPM;
if (thePM->prevRightChild == NULL)
{
if (thePM->rightParent != NULL)
{ thePM->rightParent->children = thePM->nextRightChild; }
}
else
{ thePM->prevRightChild->nextRightChild = thePM->nextRightChild; }
if (thePM->nextRightChild != NULL)
{ thePM->nextRightChild->prevRightChild = thePM->prevRightChild; }
thePM->rightParent = NULL;
thePM->nextRightChild = NULL;
thePM->prevRightChild = NULL;
if (thePM->prevLeftChild == NULL)
{
if (thePM->leftParent != NULL)
{ thePM->leftParent->children = thePM->nextLeftChild; }
}
else
{ thePM->prevLeftChild->nextLeftChild = thePM->nextLeftChild; }
if (thePM->nextLeftChild != NULL)
{ thePM->nextLeftChild->prevLeftChild = thePM->prevLeftChild; }
thePM->leftParent = NULL;
thePM->nextLeftChild = NULL;
thePM->prevLeftChild = NULL;
if (thePM->prevBlocked == NULL)
{
tempPM = (struct partialMatch *) thePM->marker;
if (tempPM != NULL)
{ tempPM->blockList = thePM->nextBlocked; }
}
else
{ thePM->prevBlocked->nextBlocked = thePM->nextBlocked; }
if (thePM->nextBlocked != NULL)
{ thePM->nextBlocked->prevBlocked = thePM->prevBlocked; }
thePM->marker = NULL;
thePM->nextBlocked = NULL;
thePM->prevBlocked = NULL;
if (thePM->children != NULL)
{
if (thePM->rhsMemory)
{
for (tempPM = thePM->children; tempPM != NULL; tempPM = tempPM->nextRightChild)
{ tempPM->rightParent = NULL; }
}
else
{
for (tempPM = thePM->children; tempPM != NULL; tempPM = tempPM->nextLeftChild)
{ tempPM->leftParent = NULL; }
}
thePM->children = NULL;
}
}
struct partialMatch *MergePartialMatches(
Environment *theEnv,
struct partialMatch *lhsBind,
struct partialMatch *rhsBind)
{
struct partialMatch *linker;
static struct partialMatch mergeTemplate = { 1 };
linker = get_var_struct(theEnv,partialMatch,sizeof(struct genericMatch) * lhsBind->bcount);
memcpy(linker,&mergeTemplate,sizeof(struct partialMatch) - sizeof(struct genericMatch));
linker->deleting = false;
linker->bcount = lhsBind->bcount + 1;
memcpy(linker->binds,lhsBind->binds,sizeof(struct genericMatch) * lhsBind->bcount);
if (rhsBind == NULL)
{ linker->binds[lhsBind->bcount].gm.theValue = NULL; }
else
{ linker->binds[lhsBind->bcount].gm.theValue = rhsBind->binds[0].gm.theValue; }
return linker;
}
void InitializePatternHeader(
Environment *theEnv,
struct patternNodeHeader *theHeader)
{
#if MAC_XCD
#pragma unused(theEnv)
#endif
theHeader->firstHash = NULL;
theHeader->lastHash = NULL;
theHeader->entryJoin = NULL;
theHeader->rightHash = NULL;
theHeader->singlefieldNode = false;
theHeader->multifieldNode = false;
theHeader->stopNode = false;
#if (! RUN_TIME)
theHeader->initialize = true;
#else
theHeader->initialize = false;
#endif
theHeader->marked = false;
theHeader->beginSlot = false;
theHeader->endSlot = false;
theHeader->selector = false;
}
struct partialMatch *CreateAlphaMatch(
Environment *theEnv,
void *theEntity,
struct multifieldMarker *markers,
struct patternNodeHeader *theHeader,
unsigned long hashOffset)
{
struct partialMatch *theMatch;
struct alphaMatch *afbtemp;
unsigned long hashValue;
struct alphaMemoryHash *theAlphaMemory;
theMatch = get_struct(theEnv,partialMatch);
InitializePMLinks(theMatch);
theMatch->betaMemory = false;
theMatch->busy = false;
theMatch->deleting = false;
theMatch->bcount = 1;
theMatch->hashValue = hashOffset;
afbtemp = get_struct(theEnv,alphaMatch);
afbtemp->next = NULL;
afbtemp->matchingItem = (struct patternEntity *) theEntity;
if (markers != NULL)
{ afbtemp->markers = CopyMultifieldMarkers(theEnv,markers); }
else
{ afbtemp->markers = NULL; }
theMatch->binds[0].gm.theMatch = afbtemp;
hashValue = AlphaMemoryHashValue(theHeader,hashOffset);
theAlphaMemory = FindAlphaMemory(theEnv,theHeader,hashValue);
afbtemp->bucket = hashValue;
if (theAlphaMemory == NULL)
{
theAlphaMemory = get_struct(theEnv,alphaMemoryHash);
theAlphaMemory->bucket = hashValue;
theAlphaMemory->owner = theHeader;
theAlphaMemory->alphaMemory = NULL;
theAlphaMemory->endOfQueue = NULL;
theAlphaMemory->nextHash = NULL;
theAlphaMemory->next = DefruleData(theEnv)->AlphaMemoryTable[hashValue];
if (theAlphaMemory->next != NULL)
{ theAlphaMemory->next->prev = theAlphaMemory; }
theAlphaMemory->prev = NULL;
DefruleData(theEnv)->AlphaMemoryTable[hashValue] = theAlphaMemory;
if (theHeader->firstHash == NULL)
{
theHeader->firstHash = theAlphaMemory;
theHeader->lastHash = theAlphaMemory;
theAlphaMemory->prevHash = NULL;
}
else
{
theHeader->lastHash->nextHash = theAlphaMemory;
theAlphaMemory->prevHash = theHeader->lastHash;
theHeader->lastHash = theAlphaMemory;
}
}
theMatch->prevInMemory = theAlphaMemory->endOfQueue;
if (theAlphaMemory->endOfQueue == NULL)
{
theAlphaMemory->alphaMemory = theMatch;
theAlphaMemory->endOfQueue = theMatch;
}
else
{
theAlphaMemory->endOfQueue->nextInMemory = theMatch;
theAlphaMemory->endOfQueue = theMatch;
}
return(theMatch);
}
struct multifieldMarker *CopyMultifieldMarkers(
Environment *theEnv,
struct multifieldMarker *theMarkers)
{
struct multifieldMarker *head = NULL, *lastMark = NULL, *newMark;
while (theMarkers != NULL)
{
newMark = get_struct(theEnv,multifieldMarker);
newMark->next = NULL;
newMark->whichField = theMarkers->whichField;
newMark->where = theMarkers->where;
newMark->startPosition = theMarkers->startPosition;
newMark->range = theMarkers->range;
if (lastMark == NULL)
{ head = newMark; }
else
{ lastMark->next = newMark; }
lastMark = newMark;
theMarkers = theMarkers->next;
}
return(head);
}
void FlushAlphaBetaMemory(
Environment *theEnv,
struct partialMatch *pfl)
{
struct partialMatch *pfltemp;
while (pfl != NULL)
{
pfltemp = pfl->nextInMemory;
UnlinkBetaPartialMatchfromAlphaAndBetaLineage(pfl);
ReturnPartialMatch(theEnv,pfl);
pfl = pfltemp;
}
}
void DestroyAlphaBetaMemory(
Environment *theEnv,
struct partialMatch *pfl)
{
struct partialMatch *pfltemp;
while (pfl != NULL)
{
pfltemp = pfl->nextInMemory;
DestroyPartialMatch(theEnv,pfl);
pfl = pfltemp;
}
}
bool FindEntityInPartialMatch(
struct patternEntity *theEntity,
struct partialMatch *thePartialMatch)
{
unsigned short i;
for (i = 0 ; i < thePartialMatch->bcount; i++)
{
if (thePartialMatch->binds[i].gm.theMatch == NULL) continue;
if (thePartialMatch->binds[i].gm.theMatch->matchingItem == theEntity)
{ return true; }
}
return false;
}
int GetPatternNumberFromJoin(
struct joinNode *joinPtr)
{
int whichOne = 0;
while (joinPtr != NULL)
{
if (joinPtr->joinFromTheRight)
{ joinPtr = (struct joinNode *) joinPtr->rightSideEntryStructure; }
else
{
whichOne++;
joinPtr = joinPtr->lastLevel;
}
}
return(whichOne);
}
void TraceErrorToRule(
Environment *theEnv,
struct joinNode *joinPtr,
const char *indentSpaces)
{
int patternCount;
MarkRuleNetwork(theEnv,0);
patternCount = CountPriorPatterns(joinPtr->lastLevel) + 1;
TraceErrorToRuleDriver(theEnv,joinPtr,indentSpaces,patternCount,false);
MarkRuleNetwork(theEnv,0);
}
static void TraceErrorToRuleDriver(
Environment *theEnv,
struct joinNode *joinPtr,
const char *indentSpaces,
int priorRightJoinPatterns,
bool enteredJoinFromRight)
{
const char *name;
int priorPatternCount;
struct joinLink *theLinks;
if ((joinPtr->joinFromTheRight) && enteredJoinFromRight)
{ priorPatternCount = CountPriorPatterns(joinPtr->lastLevel); }
else
{ priorPatternCount = 0; }
if (joinPtr->marked)
{ }
else if (joinPtr->ruleToActivate != NULL)
{
joinPtr->marked = 1;
name = DefruleName(joinPtr->ruleToActivate);
WriteString(theEnv,STDERR,indentSpaces);
WriteString(theEnv,STDERR,"Of pattern #");
WriteInteger(theEnv,STDERR,priorRightJoinPatterns+priorPatternCount);
WriteString(theEnv,STDERR," in rule ");
WriteString(theEnv,STDERR,name);
WriteString(theEnv,STDERR,"\n");
}
else
{
joinPtr->marked = 1;
theLinks = joinPtr->nextLinks;
while (theLinks != NULL)
{
TraceErrorToRuleDriver(theEnv,theLinks->join,indentSpaces,
priorRightJoinPatterns+priorPatternCount,
(theLinks->enterDirection == RHS));
theLinks = theLinks->next;
}
}
}
static int CountPriorPatterns(
struct joinNode *joinPtr)
{
int count = 0;
while (joinPtr != NULL)
{
if (joinPtr->joinFromTheRight)
{ count += CountPriorPatterns((struct joinNode *) joinPtr->rightSideEntryStructure); }
else
{ count++; }
joinPtr = joinPtr->lastLevel;
}
return(count);
}
void MarkRuleNetwork(
Environment *theEnv,
bool value)
{
Defrule *rulePtr, *disjunctPtr;
struct joinNode *joinPtr;
Defmodule *modulePtr;
SaveCurrentModule(theEnv);
for (modulePtr = GetNextDefmodule(theEnv,NULL);
modulePtr != NULL;
modulePtr = GetNextDefmodule(theEnv,modulePtr))
{
SetCurrentModule(theEnv,modulePtr);
rulePtr = GetNextDefrule(theEnv,NULL);
while (rulePtr != NULL)
{
for (disjunctPtr = rulePtr; disjunctPtr != NULL; disjunctPtr = disjunctPtr->disjunct)
{
joinPtr = disjunctPtr->lastJoin;
MarkRuleJoins(joinPtr,value);
}
rulePtr = GetNextDefrule(theEnv,rulePtr);
}
}
RestoreCurrentModule(theEnv);
}
void MarkRuleJoins(
struct joinNode *joinPtr,
bool value)
{
while (joinPtr != NULL)
{
if (joinPtr->joinFromTheRight)
{ MarkRuleJoins((struct joinNode *) joinPtr->rightSideEntryStructure,value); }
joinPtr->marked = value;
joinPtr = joinPtr->lastLevel;
}
}
struct partialMatch *GetAlphaMemory(
Environment *theEnv,
struct patternNodeHeader *theHeader,
unsigned long hashOffset)
{
struct alphaMemoryHash *theAlphaMemory;
unsigned long hashValue;
hashValue = AlphaMemoryHashValue(theHeader,hashOffset);
theAlphaMemory = FindAlphaMemory(theEnv,theHeader,hashValue);
if (theAlphaMemory == NULL)
{ return NULL; }
return theAlphaMemory->alphaMemory;
}
struct partialMatch *GetLeftBetaMemory(
struct joinNode *theJoin,
unsigned long hashValue)
{
unsigned long betaLocation;
betaLocation = hashValue % theJoin->leftMemory->size;
return theJoin->leftMemory->beta[betaLocation];
}
struct partialMatch *GetRightBetaMemory(
struct joinNode *theJoin,
unsigned long hashValue)
{
unsigned long betaLocation;
betaLocation = hashValue % theJoin->rightMemory->size;
return theJoin->rightMemory->beta[betaLocation];
}
void ReturnLeftMemory(
Environment *theEnv,
struct joinNode *theJoin)
{
if (theJoin->leftMemory == NULL) return;
genfree(theEnv,theJoin->leftMemory->beta,sizeof(struct partialMatch *) * theJoin->leftMemory->size);
rtn_struct(theEnv,betaMemory,theJoin->leftMemory);
theJoin->leftMemory = NULL;
}
void ReturnRightMemory(
Environment *theEnv,
struct joinNode *theJoin)
{
if (theJoin->rightMemory == NULL) return;
genfree(theEnv,theJoin->rightMemory->beta,sizeof(struct partialMatch *) * theJoin->rightMemory->size);
genfree(theEnv,theJoin->rightMemory->last,sizeof(struct partialMatch *) * theJoin->rightMemory->size);
rtn_struct(theEnv,betaMemory,theJoin->rightMemory);
theJoin->rightMemory = NULL;
}
void DestroyBetaMemory(
Environment *theEnv,
struct joinNode *theJoin,
int side)
{
unsigned long i;
if (side == LHS)
{
if (theJoin->leftMemory == NULL) return;
for (i = 0; i < theJoin->leftMemory->size; i++)
{ DestroyAlphaBetaMemory(theEnv,theJoin->leftMemory->beta[i]); }
}
else
{
if (theJoin->rightMemory == NULL) return;
for (i = 0; i < theJoin->rightMemory->size; i++)
{ DestroyAlphaBetaMemory(theEnv,theJoin->rightMemory->beta[i]); }
}
}
void FlushBetaMemory(
Environment *theEnv,
struct joinNode *theJoin,
int side)
{
unsigned long i;
if (side == LHS)
{
if (theJoin->leftMemory == NULL) return;
for (i = 0; i < theJoin->leftMemory->size; i++)
{ FlushAlphaBetaMemory(theEnv,theJoin->leftMemory->beta[i]); }
}
else
{
if (theJoin->rightMemory == NULL) return;
for (i = 0; i < theJoin->rightMemory->size; i++)
{ FlushAlphaBetaMemory(theEnv,theJoin->rightMemory->beta[i]); }
}
}
bool BetaMemoryNotEmpty(
struct joinNode *theJoin)
{
if (theJoin->leftMemory != NULL)
{
if (theJoin->leftMemory->count > 0)
{ return true; }
}
if (theJoin->rightMemory != NULL)
{
if (theJoin->rightMemory->count > 0)
{ return true; }
}
return false;
}
void RemoveAlphaMemoryMatches(
Environment *theEnv,
struct patternNodeHeader *theHeader,
struct partialMatch *theMatch,
struct alphaMatch *theAlphaMatch)
{
struct alphaMemoryHash *theAlphaMemory = NULL;
unsigned long hashValue;
if ((theMatch->prevInMemory == NULL) || (theMatch->nextInMemory == NULL))
{
hashValue = theAlphaMatch->bucket;
theAlphaMemory = FindAlphaMemory(theEnv,theHeader,hashValue);
}
if (theMatch->prevInMemory != NULL)
{ theMatch->prevInMemory->nextInMemory = theMatch->nextInMemory; }
else
{ theAlphaMemory->alphaMemory = theMatch->nextInMemory; }
if (theMatch->nextInMemory != NULL)
{ theMatch->nextInMemory->prevInMemory = theMatch->prevInMemory; }
else
{ theAlphaMemory->endOfQueue = theMatch->prevInMemory; }
theMatch->nextInMemory = EngineData(theEnv)->GarbagePartialMatches;
EngineData(theEnv)->GarbagePartialMatches = theMatch;
if ((theAlphaMemory != NULL) && (theAlphaMemory->alphaMemory == NULL))
{ UnlinkAlphaMemory(theEnv,theHeader,theAlphaMemory); }
}
void DestroyAlphaMemory(
Environment *theEnv,
struct patternNodeHeader *theHeader,
bool unlink)
{
struct alphaMemoryHash *theAlphaMemory, *tempMemory;
theAlphaMemory = theHeader->firstHash;
while (theAlphaMemory != NULL)
{
tempMemory = theAlphaMemory->nextHash;
DestroyAlphaBetaMemory(theEnv,theAlphaMemory->alphaMemory);
if (unlink)
{ UnlinkAlphaMemoryBucketSiblings(theEnv,theAlphaMemory); }
rtn_struct(theEnv,alphaMemoryHash,theAlphaMemory);
theAlphaMemory = tempMemory;
}
theHeader->firstHash = NULL;
theHeader->lastHash = NULL;
}
void FlushAlphaMemory(
Environment *theEnv,
struct patternNodeHeader *theHeader)
{
struct alphaMemoryHash *theAlphaMemory, *tempMemory;
theAlphaMemory = theHeader->firstHash;
while (theAlphaMemory != NULL)
{
tempMemory = theAlphaMemory->nextHash;
FlushAlphaBetaMemory(theEnv,theAlphaMemory->alphaMemory);
UnlinkAlphaMemoryBucketSiblings(theEnv,theAlphaMemory);
rtn_struct(theEnv,alphaMemoryHash,theAlphaMemory);
theAlphaMemory = tempMemory;
}
theHeader->firstHash = NULL;
theHeader->lastHash = NULL;
}
static struct alphaMemoryHash *FindAlphaMemory(
Environment *theEnv,
struct patternNodeHeader *theHeader,
unsigned long hashValue)
{
struct alphaMemoryHash *theAlphaMemory;
theAlphaMemory = DefruleData(theEnv)->AlphaMemoryTable[hashValue];
if (theAlphaMemory != NULL)
{
while ((theAlphaMemory != NULL) && (theAlphaMemory->owner != theHeader))
{ theAlphaMemory = theAlphaMemory->next; }
}
return theAlphaMemory;
}
static unsigned long AlphaMemoryHashValue(
struct patternNodeHeader *theHeader,
unsigned long hashOffset)
{
unsigned long hashValue;
union
{
void *vv;
unsigned uv;
} fis;
fis.uv = 0;
fis.vv = theHeader;
hashValue = fis.uv + hashOffset;
hashValue = hashValue % ALPHA_MEMORY_HASH_SIZE;
return hashValue;
}
static void UnlinkAlphaMemory(
Environment *theEnv,
struct patternNodeHeader *theHeader,
struct alphaMemoryHash *theAlphaMemory)
{
UnlinkAlphaMemoryBucketSiblings(theEnv,theAlphaMemory);
if (theAlphaMemory == theHeader->firstHash)
{ theHeader->firstHash = theAlphaMemory->nextHash; }
if (theAlphaMemory == theHeader->lastHash)
{ theHeader->lastHash = theAlphaMemory->prevHash; }
if (theAlphaMemory->prevHash != NULL)
{ theAlphaMemory->prevHash->nextHash = theAlphaMemory->nextHash; }
if (theAlphaMemory->nextHash != NULL)
{ theAlphaMemory->nextHash->prevHash = theAlphaMemory->prevHash; }
rtn_struct(theEnv,alphaMemoryHash,theAlphaMemory);
}
static void UnlinkAlphaMemoryBucketSiblings(
Environment *theEnv,
struct alphaMemoryHash *theAlphaMemory)
{
if (theAlphaMemory->prev == NULL)
{ DefruleData(theEnv)->AlphaMemoryTable[theAlphaMemory->bucket] = theAlphaMemory->next; }
else
{ theAlphaMemory->prev->next = theAlphaMemory->next; }
if (theAlphaMemory->next != NULL)
{ theAlphaMemory->next->prev = theAlphaMemory->prev; }
}
unsigned long ComputeRightHashValue(
Environment *theEnv,
struct patternNodeHeader *theHeader)
{
struct expr *tempExpr;
unsigned long hashValue = 0;
unsigned long multiplier = 1;
union
{
void *vv;
unsigned long liv;
} fis;
if (theHeader->rightHash == NULL)
{ return hashValue; }
for (tempExpr = theHeader->rightHash;
tempExpr != NULL;
tempExpr = tempExpr->nextArg, multiplier = multiplier * 509)
{
UDFValue theResult;
struct expr *oldArgument;
oldArgument = EvaluationData(theEnv)->CurrentExpression;
EvaluationData(theEnv)->CurrentExpression = tempExpr;
(*EvaluationData(theEnv)->PrimitivesArray[tempExpr->type]->evaluateFunction)(theEnv,tempExpr->value,&theResult);
EvaluationData(theEnv)->CurrentExpression = oldArgument;
switch (theResult.header->type)
{
case STRING_TYPE:
case SYMBOL_TYPE:
case INSTANCE_NAME_TYPE:
hashValue += (theResult.lexemeValue->bucket * multiplier);
break;
case INTEGER_TYPE:
hashValue += (theResult.integerValue->bucket * multiplier);
break;
case FLOAT_TYPE:
hashValue += (theResult.floatValue->bucket * multiplier);
break;
case FACT_ADDRESS_TYPE:
#if OBJECT_SYSTEM
case INSTANCE_ADDRESS_TYPE:
#endif
fis.liv = 0;
fis.vv = theResult.value;
hashValue += fis.liv * multiplier;
break;
case EXTERNAL_ADDRESS_TYPE:
fis.liv = 0;
fis.vv = theResult.externalAddressValue->contents;
hashValue += fis.liv * multiplier;
break;
}
}
return hashValue;
}
void ResizeBetaMemory(
Environment *theEnv,
struct betaMemory *theMemory)
{
struct partialMatch **oldArray, **lastAdd, *thePM, *nextPM;
unsigned long i, oldSize, betaLocation;
oldSize = theMemory->size;
oldArray = theMemory->beta;
theMemory->size = oldSize * 11;
theMemory->beta = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *) * theMemory->size);
lastAdd = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *) * theMemory->size);
memset(theMemory->beta,0,sizeof(struct partialMatch *) * theMemory->size);
memset(lastAdd,0,sizeof(struct partialMatch *) * theMemory->size);
for (i = 0; i < oldSize; i++)
{
thePM = oldArray[i];
while (thePM != NULL)
{
nextPM = thePM->nextInMemory;
thePM->nextInMemory = NULL;
betaLocation = thePM->hashValue % theMemory->size;
thePM->prevInMemory = lastAdd[betaLocation];
if (lastAdd[betaLocation] != NULL)
{ lastAdd[betaLocation]->nextInMemory = thePM; }
else
{ theMemory->beta[betaLocation] = thePM; }
lastAdd[betaLocation] = thePM;
thePM = nextPM;
}
}
if (theMemory->last != NULL)
{
genfree(theEnv,theMemory->last,sizeof(struct partialMatch *) * oldSize);
theMemory->last = lastAdd;
}
else
{ genfree(theEnv,lastAdd,sizeof(struct partialMatch *) * theMemory->size); }
genfree(theEnv,oldArray,sizeof(struct partialMatch *) * oldSize);
}
static void ResetBetaMemory(
Environment *theEnv,
struct betaMemory *theMemory)
{
struct partialMatch **oldArray, **lastAdd;
unsigned long oldSize;
if ((theMemory->size == 1) ||
(theMemory->size == INITIAL_BETA_HASH_SIZE))
{ return; }
oldSize = theMemory->size;
oldArray = theMemory->beta;
theMemory->size = INITIAL_BETA_HASH_SIZE;
theMemory->beta = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *) * theMemory->size);
memset(theMemory->beta,0,sizeof(struct partialMatch *) * theMemory->size);
genfree(theEnv,oldArray,sizeof(struct partialMatch *) * oldSize);
if (theMemory->last != NULL)
{
lastAdd = (struct partialMatch **) genalloc(theEnv,sizeof(struct partialMatch *) * theMemory->size);
memset(lastAdd,0,sizeof(struct partialMatch *) * theMemory->size);
genfree(theEnv,theMemory->last,sizeof(struct partialMatch *) * oldSize);
theMemory->last = lastAdd;
}
}
unsigned long PrintBetaMemory(
Environment *theEnv,
const char *logName,
struct betaMemory *theMemory,
bool indentFirst,
const char *indentString,
Verbosity output)
{
struct partialMatch *listOfMatches;
unsigned long b, count = 0;
if (GetHaltExecution(theEnv) == true)
{ return count; }
for (b = 0; b < theMemory->size; b++)
{
listOfMatches = theMemory->beta[b];
while (listOfMatches != NULL)
{
if (GetHaltExecution(theEnv) == true)
{ return count; }
if (output == VERBOSE)
{
if (indentFirst)
{ WriteString(theEnv,logName,indentString); }
else
{ indentFirst = true; }
}
if (output == VERBOSE)
{
PrintPartialMatch(theEnv,logName,listOfMatches);
WriteString(theEnv,logName,"\n");
}
count++;
listOfMatches = listOfMatches->nextInMemory;
}
}
return count;
}
#if (CONSTRUCT_COMPILER || BLOAD_AND_BSAVE) && (! RUN_TIME)
void TagRuleNetwork(
Environment *theEnv,
unsigned long *moduleCount,
unsigned long *ruleCount,
unsigned long *joinCount,
unsigned long *linkCount)
{
Defmodule *modulePtr;
Defrule *rulePtr, *disjunctPtr;
struct joinLink *theLink;
*moduleCount = 0;
*ruleCount = 0;
*joinCount = 0;
*linkCount = 0;
MarkRuleNetwork(theEnv,0);
for (theLink = DefruleData(theEnv)->LeftPrimeJoins;
theLink != NULL;
theLink = theLink->next)
{
theLink->bsaveID = *linkCount;
(*linkCount)++;
}
for (theLink = DefruleData(theEnv)->RightPrimeJoins;
theLink != NULL;
theLink = theLink->next)
{
theLink->bsaveID = *linkCount;
(*linkCount)++;
}
for (modulePtr = GetNextDefmodule(theEnv,NULL);
modulePtr != NULL;
modulePtr = GetNextDefmodule(theEnv,modulePtr))
{
(*moduleCount)++;
SetCurrentModule(theEnv,modulePtr);
rulePtr = GetNextDefrule(theEnv,NULL);
while (rulePtr != NULL)
{
for (disjunctPtr = rulePtr; disjunctPtr != NULL; disjunctPtr = disjunctPtr->disjunct)
{
disjunctPtr->header.bsaveID = *ruleCount;
(*ruleCount)++;
TagNetworkTraverseJoins(theEnv,joinCount,linkCount,disjunctPtr->lastJoin);
}
rulePtr = GetNextDefrule(theEnv,rulePtr);
}
}
}
static void TagNetworkTraverseJoins(
Environment *theEnv,
unsigned long *joinCount,
unsigned long *linkCount,
struct joinNode *joinPtr)
{
struct joinLink *theLink;
for (;
joinPtr != NULL;
joinPtr = joinPtr->lastLevel)
{
if (joinPtr->marked == 0)
{
joinPtr->marked = 1;
joinPtr->bsaveID = *joinCount;
(*joinCount)++;
for (theLink = joinPtr->nextLinks;
theLink != NULL;
theLink = theLink->next)
{
theLink->bsaveID = *linkCount;
(*linkCount)++;
}
}
if (joinPtr->joinFromTheRight)
{ TagNetworkTraverseJoins(theEnv,joinCount,linkCount,(struct joinNode *) joinPtr->rightSideEntryStructure); }
}
}
#endif
#endif