#include <stdio.h>
#include <string.h>
#include "setup.h"
#if DEFRULE_CONSTRUCT
#include "argacces.h"
#include "constant.h"
#include "constrct.h"
#include "crstrtgy.h"
#include "engine.h"
#include "envrnmnt.h"
#include "evaluatn.h"
#include "extnfunc.h"
#include "incrrset.h"
#include "lgcldpnd.h"
#include "memalloc.h"
#include "multifld.h"
#include "pattern.h"
#include "prntutil.h"
#include "reteutil.h"
#include "router.h"
#include "ruledlt.h"
#include "sysdep.h"
#include "utility.h"
#include "watch.h"
#if BLOAD || BLOAD_AND_BSAVE || BLOAD_ONLY
#include "rulebin.h"
#endif
#include "rulecom.h"
#if DEVELOPER
static void ShowJoins(Environment *,Defrule *);
#endif
#if DEBUGGING_FUNCTIONS
static long long ListAlphaMatches(Environment *,struct joinInformation *,Verbosity);
static long long ListBetaMatches(Environment *,struct joinInformation *,long,unsigned short,Verbosity);
static void ListBetaJoinActivity(Environment *,struct joinInformation *,long,long,int,UDFValue *);
static unsigned short AlphaJoinCountDriver(Environment *,struct joinNode *);
static unsigned short BetaJoinCountDriver(Environment *,struct joinNode *);
static void AlphaJoinsDriver(Environment *,struct joinNode *,unsigned short,struct joinInformation *);
static void BetaJoinsDriver(Environment *,struct joinNode *,unsigned short,struct joinInformation *,struct betaMemory *,struct joinNode *);
static int CountPatterns(Environment *,struct joinNode *,bool);
static const char *BetaHeaderString(Environment *,struct joinInformation *,long,long);
static const char *ActivityHeaderString(Environment *,struct joinInformation *,long,long);
static void JoinActivityReset(Environment *,ConstructHeader *,void *);
#endif
void DefruleCommands(
Environment *theEnv)
{
#if ! RUN_TIME
AddUDF(theEnv,"run","v",0,1,"l",RunCommand,"RunCommand",NULL);
AddUDF(theEnv,"halt","v",0,0,NULL,HaltCommand,"HaltCommand",NULL);
AddUDF(theEnv,"focus","b",1,UNBOUNDED,"y",FocusCommand,"FocusCommand",NULL);
AddUDF(theEnv,"clear-focus-stack","v",0,0,NULL,ClearFocusStackCommand,"ClearFocusStackCommand",NULL);
AddUDF(theEnv,"get-focus-stack","m",0,0,NULL,GetFocusStackFunction,"GetFocusStackFunction",NULL);
AddUDF(theEnv,"pop-focus","y",0,0,NULL,PopFocusFunction,"PopFocusFunction",NULL);
AddUDF(theEnv,"get-focus","y",0,0,NULL,GetFocusFunction,"GetFocusFunction",NULL);
#if DEBUGGING_FUNCTIONS
AddUDF(theEnv,"set-break","v",1,1,"y",SetBreakCommand,"SetBreakCommand",NULL);
AddUDF(theEnv,"remove-break","v",0,1,"y",RemoveBreakCommand,"RemoveBreakCommand",NULL);
AddUDF(theEnv,"show-breaks","v",0,1,"y",ShowBreaksCommand,"ShowBreaksCommand",NULL);
AddUDF(theEnv,"matches","bm",1,2,"y",MatchesCommand,"MatchesCommand",NULL);
AddUDF(theEnv,"join-activity","bm",1,2,"y",JoinActivityCommand,"JoinActivityCommand",NULL);
AddUDF(theEnv,"join-activity-reset","v",0,0,NULL,JoinActivityResetCommand,"JoinActivityResetCommand",NULL);
AddUDF(theEnv,"list-focus-stack","v",0,0,NULL,ListFocusStackCommand,"ListFocusStackCommand",NULL);
AddUDF(theEnv,"dependencies","v",1,1,"infly",DependenciesCommand,"DependenciesCommand",NULL);
AddUDF(theEnv,"dependents","v",1,1,"infly",DependentsCommand,"DependentsCommand",NULL);
AddUDF(theEnv,"timetag","l",1,1,"infly" ,TimetagFunction,"TimetagFunction",NULL);
#endif
AddUDF(theEnv,"get-beta-memory-resizing","b",0,0,NULL,GetBetaMemoryResizingCommand,"GetBetaMemoryResizingCommand",NULL);
AddUDF(theEnv,"set-beta-memory-resizing","b",1,1,NULL,SetBetaMemoryResizingCommand,"SetBetaMemoryResizingCommand",NULL);
AddUDF(theEnv,"get-strategy","y",0,0,NULL,GetStrategyCommand,"GetStrategyCommand",NULL);
AddUDF(theEnv,"set-strategy","y",1,1,"y",SetStrategyCommand,"SetStrategyCommand",NULL);
#if DEVELOPER && (! BLOAD_ONLY)
AddUDF(theEnv,"rule-complexity","l",1,1,"y",RuleComplexityCommand,"RuleComplexityCommand",NULL);
AddUDF(theEnv,"show-joins","v",1,1,"y",ShowJoinsCommand,"ShowJoinsCommand",NULL);
AddUDF(theEnv,"show-aht","v",0,0,NULL,ShowAlphaHashTable,"ShowAlphaHashTable",NULL);
#if DEBUGGING_FUNCTIONS
AddWatchItem(theEnv,"rule-analysis",0,&DefruleData(theEnv)->WatchRuleAnalysis,0,NULL,NULL);
#endif
#endif
#else
#if MAC_XCD
#pragma unused(theEnv)
#endif
#endif
}
bool GetBetaMemoryResizing(
Environment *theEnv)
{
return DefruleData(theEnv)->BetaMemoryResizingFlag;
}
bool SetBetaMemoryResizing(
Environment *theEnv,
bool value)
{
bool ov;
ov = DefruleData(theEnv)->BetaMemoryResizingFlag;
DefruleData(theEnv)->BetaMemoryResizingFlag = value;
return(ov);
}
void SetBetaMemoryResizingCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
UDFValue theArg;
returnValue->lexemeValue = CreateBoolean(theEnv,GetBetaMemoryResizing(theEnv));
if (! UDFFirstArgument(context,ANY_TYPE_BITS,&theArg))
{ return; }
if (theArg.value == FalseSymbol(theEnv))
{ SetBetaMemoryResizing(theEnv,false); }
else
{ SetBetaMemoryResizing(theEnv,true); }
}
void GetBetaMemoryResizingCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
returnValue->lexemeValue = CreateBoolean(theEnv,GetBetaMemoryResizing(theEnv));
}
void GetFocusFunction(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
Defmodule *rv;
rv = GetFocus(theEnv);
if (rv == NULL)
{
returnValue->lexemeValue = FalseSymbol(theEnv);
return;
}
returnValue->value = rv->header.name;
}
Defmodule *GetFocus(
Environment *theEnv)
{
if (EngineData(theEnv)->CurrentFocus == NULL) return NULL;
return EngineData(theEnv)->CurrentFocus->theModule;
}
#if DEBUGGING_FUNCTIONS
void MatchesCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
const char *ruleName, *argument;
Defrule *rulePtr;
UDFValue theArg;
Verbosity output;
CLIPSValue result;
if (! UDFFirstArgument(context,SYMBOL_BIT,&theArg))
{ return; }
ruleName = theArg.lexemeValue->contents;
rulePtr = FindDefrule(theEnv,ruleName);
if (rulePtr == NULL)
{
CantFindItemErrorMessage(theEnv,"defrule",ruleName,true);
returnValue->lexemeValue = FalseSymbol(theEnv);
return;
}
if (UDFHasNextArgument(context))
{
if (! UDFNextArgument(context,SYMBOL_BIT,&theArg))
{ return; }
argument = theArg.lexemeValue->contents;
if (strcmp(argument,"verbose") == 0)
{ output = VERBOSE; }
else if (strcmp(argument,"succinct") == 0)
{ output = SUCCINCT; }
else if (strcmp(argument,"terse") == 0)
{ output = TERSE; }
else
{
UDFInvalidArgumentMessage(context,"symbol with value verbose, succinct, or terse");
returnValue->lexemeValue = FalseSymbol(theEnv);
return;
}
}
else
{ output = VERBOSE; }
Matches(rulePtr,output,&result);
CLIPSToUDFValue(&result,returnValue);
}
void Matches(
Defrule *theDefrule,
Verbosity output,
CLIPSValue *returnValue)
{
Defrule *rulePtr;
Defrule *topDisjunct = theDefrule;
long joinIndex;
unsigned short arraySize;
struct joinInformation *theInfo;
long long alphaMatchCount = 0;
long long betaMatchCount = 0;
long long activations = 0;
Activation *agendaPtr;
Environment *theEnv = theDefrule->header.env;
returnValue->value = CreateMultifield(theEnv,3L);
returnValue->multifieldValue->contents[0].integerValue = SymbolData(theEnv)->Zero;
returnValue->multifieldValue->contents[1].integerValue = SymbolData(theEnv)->Zero;
returnValue->multifieldValue->contents[2].integerValue = SymbolData(theEnv)->Zero;
for (rulePtr = topDisjunct; rulePtr != NULL; rulePtr = rulePtr->disjunct)
{
arraySize = AlphaJoinCount(theEnv,rulePtr);
theInfo = CreateJoinArray(theEnv,arraySize);
AlphaJoins(theEnv,rulePtr,arraySize,theInfo);
for (joinIndex = 0; joinIndex < arraySize; joinIndex++)
{
alphaMatchCount += ListAlphaMatches(theEnv,&theInfo[joinIndex],output);
returnValue->multifieldValue->contents[0].integerValue = CreateInteger(theEnv,alphaMatchCount);
}
FreeJoinArray(theEnv,theInfo,arraySize);
arraySize = BetaJoinCount(theEnv,rulePtr);
theInfo = CreateJoinArray(theEnv,arraySize);
BetaJoins(theEnv,rulePtr,arraySize,theInfo);
for (joinIndex = 1; joinIndex < arraySize; joinIndex++)
{
betaMatchCount += ListBetaMatches(theEnv,theInfo,joinIndex,arraySize,output);
returnValue->multifieldValue->contents[1].integerValue = CreateInteger(theEnv,betaMatchCount);
}
FreeJoinArray(theEnv,theInfo,arraySize);
}
if (output == VERBOSE)
{ WriteString(theEnv,STDOUT,"Activations\n"); }
for (agendaPtr = ((struct defruleModule *) topDisjunct->header.whichModule)->agenda;
agendaPtr != NULL;
agendaPtr = (struct activation *) GetNextActivation(theEnv,agendaPtr))
{
if (GetHaltExecution(theEnv) == true) return;
if (((struct activation *) agendaPtr)->theRule->header.name == topDisjunct->header.name)
{
activations++;
if (output == VERBOSE)
{
PrintPartialMatch(theEnv,STDOUT,GetActivationBasis(theEnv,agendaPtr));
WriteString(theEnv,STDOUT,"\n");
}
}
}
if (output == SUCCINCT)
{
WriteString(theEnv,STDOUT,"Activations: ");
WriteInteger(theEnv,STDOUT,activations);
WriteString(theEnv,STDOUT,"\n");
}
if ((activations == 0) && (output == VERBOSE)) WriteString(theEnv,STDOUT," None\n");
returnValue->multifieldValue->contents[2].integerValue = CreateInteger(theEnv,activations);
}
static unsigned short AlphaJoinCountDriver(
Environment *theEnv,
struct joinNode *theJoin)
{
unsigned short alphaCount = 0;
if (theJoin == NULL)
{ return alphaCount; }
if (theJoin->joinFromTheRight)
{ return AlphaJoinCountDriver(theEnv,(struct joinNode *) theJoin->rightSideEntryStructure); }
else if (theJoin->lastLevel != NULL)
{ alphaCount += AlphaJoinCountDriver(theEnv,theJoin->lastLevel); }
alphaCount++;
return alphaCount;
}
unsigned short AlphaJoinCount(
Environment *theEnv,
Defrule *theDefrule)
{
return AlphaJoinCountDriver(theEnv,theDefrule->lastJoin->lastLevel);
}
static void AlphaJoinsDriver(
Environment *theEnv,
struct joinNode *theJoin,
unsigned short alphaIndex,
struct joinInformation *theInfo)
{
if (theJoin == NULL)
{ return; }
if (theJoin->joinFromTheRight)
{
AlphaJoinsDriver(theEnv,(struct joinNode *) theJoin->rightSideEntryStructure,alphaIndex,theInfo);
return;
}
else if (theJoin->lastLevel != NULL)
{ AlphaJoinsDriver(theEnv,theJoin->lastLevel,alphaIndex-1,theInfo); }
theInfo[alphaIndex-1].whichCE = alphaIndex;
theInfo[alphaIndex-1].theJoin = theJoin;
return;
}
void AlphaJoins(
Environment *theEnv,
Defrule *theDefrule,
unsigned short alphaCount,
struct joinInformation *theInfo)
{
AlphaJoinsDriver(theEnv,theDefrule->lastJoin->lastLevel,alphaCount,theInfo);
}
static unsigned short BetaJoinCountDriver(
Environment *theEnv,
struct joinNode *theJoin)
{
unsigned short betaCount = 0;
if (theJoin == NULL)
{ return betaCount; }
betaCount++;
if (theJoin->joinFromTheRight)
{ betaCount += BetaJoinCountDriver(theEnv,(struct joinNode *) theJoin->rightSideEntryStructure); }
else if (theJoin->lastLevel != NULL)
{ betaCount += BetaJoinCountDriver(theEnv,theJoin->lastLevel); }
return betaCount;
}
unsigned short BetaJoinCount(
Environment *theEnv,
Defrule *theDefrule)
{
return BetaJoinCountDriver(theEnv,theDefrule->lastJoin->lastLevel);
}
static void BetaJoinsDriver(
Environment *theEnv,
struct joinNode *theJoin,
unsigned short betaIndex,
struct joinInformation *theJoinInfoArray,
struct betaMemory *lastMemory,
struct joinNode *nextJoin)
{
unsigned short theCE = 0;
int theCount;
struct joinNode *tmpPtr;
if (theJoin == NULL)
{ return; }
theJoinInfoArray[betaIndex-1].theJoin = theJoin;
theJoinInfoArray[betaIndex-1].theMemory = lastMemory;
theJoinInfoArray[betaIndex-1].nextJoin = nextJoin;
for (tmpPtr = theJoin; tmpPtr != NULL; tmpPtr = tmpPtr->lastLevel)
{ theCE++; }
theJoinInfoArray[betaIndex-1].whichCE = theCE;
theCount = CountPatterns(theEnv,theJoin,true);
theJoinInfoArray[betaIndex-1].patternEnd = theCount;
theCount = CountPatterns(theEnv,theJoin,false);
theJoinInfoArray[betaIndex-1].patternBegin = theCount;
if (theJoin->joinFromTheRight)
{ BetaJoinsDriver(theEnv,(struct joinNode *) theJoin->rightSideEntryStructure,betaIndex-1,theJoinInfoArray,theJoin->rightMemory,theJoin); }
else if (theJoin->lastLevel != NULL)
{ BetaJoinsDriver(theEnv,theJoin->lastLevel,betaIndex-1,theJoinInfoArray,theJoin->leftMemory,theJoin); }
return;
}
void BetaJoins(
Environment *theEnv,
Defrule *theDefrule,
unsigned short betaArraySize,
struct joinInformation *theInfo)
{
BetaJoinsDriver(theEnv,theDefrule->lastJoin->lastLevel,betaArraySize,theInfo,theDefrule->lastJoin->leftMemory,theDefrule->lastJoin);
}
struct joinInformation *CreateJoinArray(
Environment *theEnv,
unsigned short size)
{
if (size == 0) return NULL;
return (struct joinInformation *) genalloc(theEnv,sizeof(struct joinInformation) * size);
}
void FreeJoinArray(
Environment *theEnv,
struct joinInformation *theArray,
unsigned short size)
{
if (size == 0) return;
genfree(theEnv,theArray,sizeof(struct joinInformation) * size);
}
static long long ListAlphaMatches(
Environment *theEnv,
struct joinInformation *theInfo,
Verbosity output)
{
struct alphaMemoryHash *listOfHashNodes;
struct partialMatch *listOfMatches;
long long count;
struct joinNode *theJoin;
long long alphaCount = 0;
if (GetHaltExecution(theEnv) == true)
{ return(alphaCount); }
theJoin = theInfo->theJoin;
if (output == VERBOSE)
{
WriteString(theEnv,STDOUT,"Matches for Pattern ");
WriteInteger(theEnv,STDOUT,theInfo->whichCE);
WriteString(theEnv,STDOUT,"\n");
}
if (theJoin->rightSideEntryStructure == NULL)
{
if (theJoin->rightMemory->beta[0]->children != NULL)
{ alphaCount += 1; }
if (output == VERBOSE)
{
if (theJoin->rightMemory->beta[0]->children != NULL)
{ WriteString(theEnv,STDOUT,"*\n"); }
else
{ WriteString(theEnv,STDOUT," None\n"); }
}
else if (output == SUCCINCT)
{
WriteString(theEnv,STDOUT,"Pattern ");
WriteInteger(theEnv,STDOUT,theInfo->whichCE);
WriteString(theEnv,STDOUT,": ");
if (theJoin->rightMemory->beta[0]->children != NULL)
{ WriteString(theEnv,STDOUT,"1"); }
else
{ WriteString(theEnv,STDOUT,"0"); }
WriteString(theEnv,STDOUT,"\n");
}
return(alphaCount);
}
listOfHashNodes = ((struct patternNodeHeader *) theJoin->rightSideEntryStructure)->firstHash;
for (count = 0;
listOfHashNodes != NULL;
listOfHashNodes = listOfHashNodes->nextHash)
{
listOfMatches = listOfHashNodes->alphaMemory;
while (listOfMatches != NULL)
{
if (GetHaltExecution(theEnv) == true)
{ return(alphaCount); }
count++;
if (output == VERBOSE)
{
PrintPartialMatch(theEnv,STDOUT,listOfMatches);
WriteString(theEnv,STDOUT,"\n");
}
listOfMatches = listOfMatches->nextInMemory;
}
}
alphaCount += count;
if ((count == 0) && (output == VERBOSE)) WriteString(theEnv,STDOUT," None\n");
if (output == SUCCINCT)
{
WriteString(theEnv,STDOUT,"Pattern ");
WriteInteger(theEnv,STDOUT,theInfo->whichCE);
WriteString(theEnv,STDOUT,": ");
WriteInteger(theEnv,STDOUT,count);
WriteString(theEnv,STDOUT,"\n");
}
return(alphaCount);
}
static const char *BetaHeaderString(
Environment *theEnv,
struct joinInformation *infoArray,
long joinIndex,
long arraySize)
{
struct joinNode *theJoin;
struct joinInformation *theInfo;
long i, j, startPosition, endPosition, positionsToPrint = 0;
bool nestedCEs = false;
const char *returnString = "";
long lastIndex;
char buffer[32];
for (i = 0; i < arraySize; i++)
{ infoArray[i].marked = false; }
theInfo = &infoArray[joinIndex];
theJoin = theInfo->theJoin;
lastIndex = joinIndex;
while (theJoin != NULL)
{
for (i = lastIndex; i >= 0; i--)
{
if (infoArray[i].theJoin == theJoin)
{
positionsToPrint++;
infoArray[i].marked = true;
if (infoArray[i].patternBegin != infoArray[i].patternEnd)
{ nestedCEs = true; }
lastIndex = i - 1;
break;
}
}
theJoin = theJoin->lastLevel;
}
for (i = 0; i <= joinIndex; i++)
{
if (infoArray[i].marked == false) continue;
positionsToPrint--;
startPosition = i;
endPosition = i;
if (infoArray[i].patternBegin == infoArray[i].patternEnd)
{
for (j = i + 1; j <= joinIndex; j++)
{
if (infoArray[j].marked == false) continue;
if (infoArray[j].patternBegin != infoArray[j].patternEnd) break;
positionsToPrint--;
i = j;
endPosition = j;
}
}
theInfo = &infoArray[startPosition];
gensprintf(buffer,"%d",theInfo->whichCE);
returnString = AppendStrings(theEnv,returnString,buffer);
if (nestedCEs)
{
if (theInfo->patternBegin == theInfo->patternEnd)
{
returnString = AppendStrings(theEnv,returnString," (P");
gensprintf(buffer,"%d",theInfo->patternBegin);
returnString = AppendStrings(theEnv,returnString,buffer);
returnString = AppendStrings(theEnv,returnString,")");
}
else
{
returnString = AppendStrings(theEnv,returnString," (P");
gensprintf(buffer,"%d",theInfo->patternBegin);
returnString = AppendStrings(theEnv,returnString,buffer);
returnString = AppendStrings(theEnv,returnString," - P");
gensprintf(buffer,"%d",theInfo->patternEnd);
returnString = AppendStrings(theEnv,returnString,buffer);
returnString = AppendStrings(theEnv,returnString,")");
}
}
if (startPosition != endPosition)
{
theInfo = &infoArray[endPosition];
returnString = AppendStrings(theEnv,returnString," - ");
gensprintf(buffer,"%d",theInfo->whichCE);
returnString = AppendStrings(theEnv,returnString,buffer);
if (nestedCEs)
{
if (theInfo->patternBegin == theInfo->patternEnd)
{
returnString = AppendStrings(theEnv,returnString," (P");
gensprintf(buffer,"%d",theInfo->patternBegin);
returnString = AppendStrings(theEnv,returnString,buffer);
returnString = AppendStrings(theEnv,returnString,")");
}
else
{
returnString = AppendStrings(theEnv,returnString," (P");
gensprintf(buffer,"%d",theInfo->patternBegin);
returnString = AppendStrings(theEnv,returnString,buffer);
returnString = AppendStrings(theEnv,returnString," - P");
gensprintf(buffer,"%d",theInfo->patternEnd);
returnString = AppendStrings(theEnv,returnString,buffer);
returnString = AppendStrings(theEnv,returnString,")");
}
}
}
if (positionsToPrint > 0)
{ returnString = AppendStrings(theEnv,returnString," , "); }
}
return returnString;
}
static long long ListBetaMatches(
Environment *theEnv,
struct joinInformation *infoArray,
long joinIndex,
unsigned short arraySize,
Verbosity output)
{
long betaCount = 0;
struct joinInformation *theInfo;
unsigned long count;
if (GetHaltExecution(theEnv) == true)
{ return(betaCount); }
theInfo = &infoArray[joinIndex];
if (output == VERBOSE)
{
WriteString(theEnv,STDOUT,"Partial matches for CEs ");
WriteString(theEnv,STDOUT,
BetaHeaderString(theEnv,infoArray,joinIndex,arraySize));
WriteString(theEnv,STDOUT,"\n");
}
count = PrintBetaMemory(theEnv,STDOUT,theInfo->theMemory,true,"",output);
betaCount += count;
if ((output == VERBOSE) && (count == 0))
{ WriteString(theEnv,STDOUT," None\n"); }
else if (output == SUCCINCT)
{
WriteString(theEnv,STDOUT,"CEs ");
WriteString(theEnv,STDOUT,
BetaHeaderString(theEnv,infoArray,joinIndex,arraySize));
WriteString(theEnv,STDOUT,": ");
WriteInteger(theEnv,STDOUT,betaCount);
WriteString(theEnv,STDOUT,"\n");
}
return betaCount;
}
static int CountPatterns(
Environment *theEnv,
struct joinNode *theJoin,
bool followRight)
{
int theCount = 0;
if (theJoin == NULL) return theCount;
if (theJoin->joinFromTheRight && (followRight == false))
{ theCount++; }
while (theJoin != NULL)
{
if (theJoin->joinFromTheRight)
{
if (followRight)
{ theJoin = (struct joinNode *) theJoin->rightSideEntryStructure; }
else
{ theJoin = theJoin->lastLevel; }
}
else
{
theCount++;
theJoin = theJoin->lastLevel;
}
followRight = true;
}
return theCount;
}
void JoinActivityCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
const char *ruleName, *argument;
Defrule *rulePtr;
UDFValue theArg;
int output;
if (! UDFFirstArgument(context,SYMBOL_BIT,&theArg))
{ return; }
ruleName = theArg.lexemeValue->contents;
rulePtr = FindDefrule(theEnv,ruleName);
if (rulePtr == NULL)
{
CantFindItemErrorMessage(theEnv,"defrule",ruleName,true);
returnValue->lexemeValue = FalseSymbol(theEnv);
return;
}
if (UDFHasNextArgument(context))
{
if (! UDFNextArgument(context,SYMBOL_BIT,&theArg))
{ return; }
argument = theArg.lexemeValue->contents;
if (strcmp(argument,"verbose") == 0)
{ output = VERBOSE; }
else if (strcmp(argument,"succinct") == 0)
{ output = SUCCINCT; }
else if (strcmp(argument,"terse") == 0)
{ output = TERSE; }
else
{
UDFInvalidArgumentMessage(context,"symbol with value verbose, succinct, or terse");
returnValue->lexemeValue = FalseSymbol(theEnv);
return;
}
}
else
{ output = VERBOSE; }
JoinActivity(theEnv,rulePtr,output,returnValue);
}
void JoinActivity(
Environment *theEnv,
Defrule *theRule,
int output,
UDFValue *returnValue)
{
Defrule *rulePtr;
long disjunctCount, disjunctIndex, joinIndex;
unsigned short arraySize;
struct joinInformation *theInfo;
returnValue->begin = 0;
returnValue->range = 3;
returnValue->value = CreateMultifield(theEnv,3L);
returnValue->multifieldValue->contents[0].integerValue = SymbolData(theEnv)->Zero;
returnValue->multifieldValue->contents[1].integerValue = SymbolData(theEnv)->Zero;
returnValue->multifieldValue->contents[2].integerValue = SymbolData(theEnv)->Zero;
disjunctCount = GetDisjunctCount(theEnv,theRule);
for (disjunctIndex = 1; disjunctIndex <= disjunctCount; disjunctIndex++)
{
rulePtr = GetNthDisjunct(theEnv,theRule,disjunctIndex);
arraySize = BetaJoinCount(theEnv,rulePtr);
theInfo = CreateJoinArray(theEnv,arraySize);
BetaJoins(theEnv,rulePtr,arraySize,theInfo);
for (joinIndex = 0; joinIndex < arraySize; joinIndex++)
{ ListBetaJoinActivity(theEnv,theInfo,joinIndex,arraySize,output,returnValue); }
FreeJoinArray(theEnv,theInfo,arraySize);
}
}
static const char *ActivityHeaderString(
Environment *theEnv,
struct joinInformation *infoArray,
long joinIndex,
long arraySize)
{
struct joinNode *theJoin;
struct joinInformation *theInfo;
long i;
bool nestedCEs = false;
const char *returnString = "";
long lastIndex;
char buffer[32];
for (i = 0; i < arraySize; i++)
{ infoArray[i].marked = false; }
theInfo = &infoArray[joinIndex];
theJoin = theInfo->theJoin;
lastIndex = joinIndex;
while (theJoin != NULL)
{
for (i = lastIndex; i >= 0; i--)
{
if (infoArray[i].theJoin == theJoin)
{
if (infoArray[i].patternBegin != infoArray[i].patternEnd)
{ nestedCEs = true; }
lastIndex = i - 1;
break;
}
}
theJoin = theJoin->lastLevel;
}
gensprintf(buffer,"%d",theInfo->whichCE);
returnString = AppendStrings(theEnv,returnString,buffer);
if (nestedCEs == false)
{ return returnString; }
if (theInfo->patternBegin == theInfo->patternEnd)
{
returnString = AppendStrings(theEnv,returnString," (P");
gensprintf(buffer,"%d",theInfo->patternBegin);
returnString = AppendStrings(theEnv,returnString,buffer);
returnString = AppendStrings(theEnv,returnString,")");
}
else
{
returnString = AppendStrings(theEnv,returnString," (P");
gensprintf(buffer,"%d",theInfo->patternBegin);
returnString = AppendStrings(theEnv,returnString,buffer);
returnString = AppendStrings(theEnv,returnString," - P");
gensprintf(buffer,"%d",theInfo->patternEnd);
returnString = AppendStrings(theEnv,returnString,buffer);
returnString = AppendStrings(theEnv,returnString,")");
}
return returnString;
}
static void ListBetaJoinActivity(
Environment *theEnv,
struct joinInformation *infoArray,
long joinIndex,
long arraySize,
int output,
UDFValue *returnValue)
{
long long activity = 0;
long long compares, adds, deletes;
struct joinNode *theJoin, *nextJoin;
struct joinInformation *theInfo;
if (GetHaltExecution(theEnv) == true)
{ return; }
theInfo = &infoArray[joinIndex];
theJoin = theInfo->theJoin;
nextJoin = theInfo->nextJoin;
compares = theJoin->memoryCompares;
if (theInfo->nextJoin->joinFromTheRight)
{
adds = nextJoin->memoryRightAdds;
deletes = nextJoin->memoryRightDeletes;
}
else
{
adds = nextJoin->memoryLeftAdds;
deletes = nextJoin->memoryLeftDeletes;
}
activity = compares + adds + deletes;
if (output == VERBOSE)
{
char buffer[100];
WriteString(theEnv,STDOUT,"Activity for CE ");
WriteString(theEnv,STDOUT,
ActivityHeaderString(theEnv,infoArray,joinIndex,arraySize));
WriteString(theEnv,STDOUT,"\n");
sprintf(buffer," Compares: %10lld\n",compares);
WriteString(theEnv,STDOUT,buffer);
sprintf(buffer," Adds: %10lld\n",adds);
WriteString(theEnv,STDOUT,buffer);
sprintf(buffer," Deletes: %10lld\n",deletes);
WriteString(theEnv,STDOUT,buffer);
}
else if (output == SUCCINCT)
{
WriteString(theEnv,STDOUT,"CE ");
WriteString(theEnv,STDOUT,
ActivityHeaderString(theEnv,infoArray,joinIndex,arraySize));
WriteString(theEnv,STDOUT,": ");
WriteInteger(theEnv,STDOUT,activity);
WriteString(theEnv,STDOUT,"\n");
}
compares += returnValue->multifieldValue->contents[0].integerValue->contents;
adds += returnValue->multifieldValue->contents[1].integerValue->contents;
deletes += returnValue->multifieldValue->contents[2].integerValue->contents;
returnValue->multifieldValue->contents[0].integerValue = CreateInteger(theEnv,compares);
returnValue->multifieldValue->contents[1].integerValue = CreateInteger(theEnv,adds);
returnValue->multifieldValue->contents[2].integerValue = CreateInteger(theEnv,deletes);
}
static void JoinActivityReset(
Environment *theEnv,
ConstructHeader *theConstruct,
void *buffer)
{
#if MAC_XCD
#pragma unused(buffer)
#endif
Defrule *theDefrule = (Defrule *) theConstruct;
struct joinNode *theJoin = theDefrule->lastJoin;
while (theJoin != NULL)
{
theJoin->memoryCompares = 0;
theJoin->memoryLeftAdds = 0;
theJoin->memoryRightAdds = 0;
theJoin->memoryLeftDeletes = 0;
theJoin->memoryRightDeletes = 0;
if (theJoin->joinFromTheRight)
{ theJoin = (struct joinNode *) theJoin->rightSideEntryStructure; }
else
{ theJoin = theJoin->lastLevel; }
}
}
void JoinActivityResetCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
DoForAllConstructs(theEnv,
JoinActivityReset,
DefruleData(theEnv)->DefruleModuleIndex,true,NULL);
}
void TimetagFunction(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
UDFValue theArg;
void *ptr;
ptr = GetFactOrInstanceArgument(context,1,&theArg);
if (ptr == NULL)
{
returnValue->integerValue = CreateInteger(theEnv,-1LL);
return;
}
returnValue->integerValue = CreateInteger(theEnv,(long long) ((struct patternEntity *) ptr)->timeTag);
}
#endif
#if DEVELOPER
void RuleComplexityCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
const char *ruleName;
Defrule *rulePtr;
ruleName = GetConstructName(context,"rule-complexity","rule name");
if (ruleName == NULL)
{
returnValue->integerValue = CreateInteger(theEnv,-1);
return;
}
rulePtr = FindDefrule(theEnv,ruleName);
if (rulePtr == NULL)
{
CantFindItemErrorMessage(theEnv,"defrule",ruleName,true);
returnValue->integerValue = CreateInteger(theEnv,-1);
return;
}
returnValue->integerValue = CreateInteger(theEnv,rulePtr->complexity);
}
void ShowJoinsCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
const char *ruleName;
Defrule *rulePtr;
ruleName = GetConstructName(context,"show-joins","rule name");
if (ruleName == NULL) return;
rulePtr = FindDefrule(theEnv,ruleName);
if (rulePtr == NULL)
{
CantFindItemErrorMessage(theEnv,"defrule",ruleName,true);
return;
}
ShowJoins(theEnv,rulePtr);
return;
}
static void ShowJoins(
Environment *theEnv,
Defrule *theRule)
{
Defrule *rulePtr;
struct joinNode *theJoin;
struct joinNode *joinList[MAXIMUM_NUMBER_OF_PATTERNS];
int numberOfJoins;
char rhsType;
unsigned int disjunct = 0;
unsigned long count = 0;
rulePtr = theRule;
if ((rulePtr != NULL) && (rulePtr->disjunct != NULL))
{ disjunct = 1; }
while (rulePtr != NULL)
{
if (disjunct > 0)
{
WriteString(theEnv,STDOUT,"Disjunct #");
PrintUnsignedInteger(theEnv,STDOUT,disjunct++);
WriteString(theEnv,STDOUT,"\n");
}
numberOfJoins = -1;
theJoin = rulePtr->lastJoin;
while (theJoin != NULL)
{
if (theJoin->joinFromTheRight)
{
numberOfJoins++;
joinList[numberOfJoins] = theJoin;
theJoin = (struct joinNode *) theJoin->rightSideEntryStructure;
}
else
{
numberOfJoins++;
joinList[numberOfJoins] = theJoin;
theJoin = theJoin->lastLevel;
}
}
while (numberOfJoins >= 0)
{
char buffer[20];
if (joinList[numberOfJoins]->patternIsNegated)
{ rhsType = 'n'; }
else if (joinList[numberOfJoins]->patternIsExists)
{ rhsType = 'x'; }
else
{ rhsType = ' '; }
gensprintf(buffer,"%2hu%c%c%c%c : ",joinList[numberOfJoins]->depth,
(joinList[numberOfJoins]->firstJoin) ? 'f' : ' ',
rhsType,
(joinList[numberOfJoins]->joinFromTheRight) ? 'j' : ' ',
(joinList[numberOfJoins]->logicalJoin) ? 'l' : ' ');
WriteString(theEnv,STDOUT,buffer);
PrintExpression(theEnv,STDOUT,joinList[numberOfJoins]->networkTest);
WriteString(theEnv,STDOUT,"\n");
if (joinList[numberOfJoins]->ruleToActivate != NULL)
{
WriteString(theEnv,STDOUT," RA : ");
WriteString(theEnv,STDOUT,DefruleName(joinList[numberOfJoins]->ruleToActivate));
WriteString(theEnv,STDOUT,"\n");
}
if (joinList[numberOfJoins]->secondaryNetworkTest != NULL)
{
WriteString(theEnv,STDOUT," SNT : ");
PrintExpression(theEnv,STDOUT,joinList[numberOfJoins]->secondaryNetworkTest);
WriteString(theEnv,STDOUT,"\n");
}
if (joinList[numberOfJoins]->leftHash != NULL)
{
WriteString(theEnv,STDOUT," LH : ");
PrintExpression(theEnv,STDOUT,joinList[numberOfJoins]->leftHash);
WriteString(theEnv,STDOUT,"\n");
}
if (joinList[numberOfJoins]->rightHash != NULL)
{
WriteString(theEnv,STDOUT," RH : ");
PrintExpression(theEnv,STDOUT,joinList[numberOfJoins]->rightHash);
WriteString(theEnv,STDOUT,"\n");
}
if (! joinList[numberOfJoins]->firstJoin)
{
WriteString(theEnv,STDOUT," LM : ");
count = PrintBetaMemory(theEnv,STDOUT,joinList[numberOfJoins]->leftMemory,false,"",SUCCINCT);
if (count == 0)
{ WriteString(theEnv,STDOUT,"None\n"); }
else
{
sprintf(buffer,"%lu\n",count);
WriteString(theEnv,STDOUT,buffer);
}
}
if (joinList[numberOfJoins]->joinFromTheRight)
{
WriteString(theEnv,STDOUT," RM : ");
count = PrintBetaMemory(theEnv,STDOUT,joinList[numberOfJoins]->rightMemory,false,"",SUCCINCT);
if (count == 0)
{ WriteString(theEnv,STDOUT,"None\n"); }
else
{
sprintf(buffer,"%lu\n",count);
WriteString(theEnv,STDOUT,buffer);
}
}
numberOfJoins--;
};
rulePtr = rulePtr->disjunct;
if (rulePtr != NULL) WriteString(theEnv,STDOUT,"\n");
}
}
void ShowAlphaHashTable(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
int i, count;
long totalCount = 0;
struct alphaMemoryHash *theEntry;
struct partialMatch *theMatch;
char buffer[40];
for (i = 0; i < ALPHA_MEMORY_HASH_SIZE; i++)
{
for (theEntry = DefruleData(theEnv)->AlphaMemoryTable[i], count = 0;
theEntry != NULL;
theEntry = theEntry->next)
{ count++; }
if (count != 0)
{
totalCount += count;
gensprintf(buffer,"%4d: %4d ->",i,count);
WriteString(theEnv,STDOUT,buffer);
for (theEntry = DefruleData(theEnv)->AlphaMemoryTable[i], count = 0;
theEntry != NULL;
theEntry = theEntry->next)
{
for (theMatch = theEntry->alphaMemory;
theMatch != NULL;
theMatch = theMatch->nextInMemory)
{ count++; }
gensprintf(buffer," %4d",count);
WriteString(theEnv,STDOUT,buffer);
if (theEntry->owner->rightHash == NULL)
{ WriteString(theEnv,STDOUT,"*"); }
}
WriteString(theEnv,STDOUT,"\n");
}
}
gensprintf(buffer,"Total Count: %ld\n",totalCount);
WriteString(theEnv,STDOUT,buffer);
}
#endif
#endif