#include "setup.h"
#if DEFRULE_CONSTRUCT && OBJECT_SYSTEM
#include "classfun.h"
#include "memalloc.h"
#include "drive.h"
#include "engine.h"
#include "envrnmnt.h"
#if (! RUN_TIME) && (! BLOAD_ONLY)
#include "incrrset.h"
#endif
#include "lgcldpnd.h"
#include "multifld.h"
#include "objrtfnx.h"
#include "objrtmch.h"
#include "prntutil.h"
#include "reteutil.h"
#include "ruledlt.h"
#include "reorder.h"
#include "retract.h"
#include "router.h"
#include "insmngr.h"
static void QueueObjectMatchAction(Environment *,int,Instance *,int);
static SLOT_BITMAP *QueueModifySlotMap(Environment *,SLOT_BITMAP *,int);
static void ReturnObjectMatchAction(Environment *,OBJECT_MATCH_ACTION *);
static void ProcessObjectMatchQueue(Environment *);
static void MarkObjectPatternNetwork(Environment *,SLOT_BITMAP *);
static bool CompareSlotBitMaps(SLOT_BITMAP *,SLOT_BITMAP *);
static void ObjectPatternMatch(Environment *,size_t,size_t,OBJECT_PATTERN_NODE *,struct multifieldMarker *);
static void ProcessPatternNode(Environment *,size_t,size_t,OBJECT_PATTERN_NODE *,struct multifieldMarker *);
static void CreateObjectAlphaMatch(Environment *,OBJECT_ALPHA_NODE *);
static bool EvaluateObjectPatternTest(Environment *,size_t,struct multifieldMarker *,
Expression *,OBJECT_PATTERN_NODE *);
static void ObjectAssertAction(Environment *,Instance *);
static void ObjectModifyAction(Environment *,Instance *,SLOT_BITMAP *);
static void ObjectRetractAction(Environment *,Instance *,SLOT_BITMAP *);
static void ObjectPatternNetErrorMessage(Environment *,OBJECT_PATTERN_NODE *);
static void TraceErrorToObjectPattern(Environment *,bool,OBJECT_PATTERN_NODE *);
void ObjectMatchDelay(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
bool ov;
ov = SetDelayObjectPatternMatching(theEnv,true);
if (! UDFFirstArgument(context,ANY_TYPE_BITS,returnValue))
{ return; }
if (EvaluationData(theEnv)->EvaluationError)
{
SetHaltExecution(theEnv,false);
SetEvaluationError(theEnv,false);
SetDelayObjectPatternMatching(theEnv,ov);
SetEvaluationError(theEnv,true);
}
else
SetDelayObjectPatternMatching(theEnv,ov);
}
bool SetDelayObjectPatternMatching(
Environment *theEnv,
bool value)
{
bool oldval;
oldval = ObjectReteData(theEnv)->DelayObjectPatternMatching;
if (value)
ObjectReteData(theEnv)->DelayObjectPatternMatching = true;
else
{
ObjectReteData(theEnv)->DelayObjectPatternMatching = false;
ObjectNetworkAction(theEnv,0,NULL,-1);
}
return(oldval);
}
bool GetDelayObjectPatternMatching(
Environment *theEnv)
{
return(ObjectReteData(theEnv)->DelayObjectPatternMatching);
}
OBJECT_PATTERN_NODE *ObjectNetworkPointer(
Environment *theEnv)
{
return(ObjectReteData(theEnv)->ObjectPatternNetworkPointer);
}
OBJECT_ALPHA_NODE *ObjectNetworkTerminalPointer(
Environment *theEnv)
{
return(ObjectReteData(theEnv)->ObjectPatternNetworkTerminalPointer);
}
void SetObjectNetworkPointer(
Environment *theEnv,
OBJECT_PATTERN_NODE *value)
{
ObjectReteData(theEnv)->ObjectPatternNetworkPointer = value;
}
void SetObjectNetworkTerminalPointer(
Environment *theEnv,
OBJECT_ALPHA_NODE *value)
{
ObjectReteData(theEnv)->ObjectPatternNetworkTerminalPointer = value;
}
void ObjectNetworkAction(
Environment *theEnv,
int type,
Instance *ins,
int slotNameID)
{
SLOT_BITMAP *tmpMap;
if (EngineData(theEnv)->JoinOperationInProgress)
return;
EngineData(theEnv)->JoinOperationInProgress = true;
ObjectReteData(theEnv)->UseEntityTimeTag = DefruleData(theEnv)->CurrentEntityTimeTag++;
if (ins != NULL)
{
ins->reteSynchronized = false;
if (ObjectReteData(theEnv)->DelayObjectPatternMatching == false)
switch (type)
{
case OBJECT_ASSERT :
ObjectAssertAction(theEnv,ins);
break;
case OBJECT_RETRACT :
ObjectRetractAction(theEnv,ins,NULL);
break;
default :
tmpMap = QueueModifySlotMap(theEnv,NULL,slotNameID);
ObjectModifyAction(theEnv,ins,tmpMap);
rm(theEnv,tmpMap,SlotBitMapSize(tmpMap));
}
else
QueueObjectMatchAction(theEnv,type,ins,slotNameID);
}
ProcessObjectMatchQueue(theEnv);
EngineData(theEnv)->JoinOperationInProgress = false;
ForceLogicalRetractions(theEnv);
if (EngineData(theEnv)->ExecutingRule == NULL) FlushGarbagePartialMatches(theEnv);
}
void ResetObjectMatchTimeTags(
Environment *theEnv)
{
OBJECT_ALPHA_NODE *alphaPtr;
OBJECT_PATTERN_NODE *lastLevel;
if ((ObjectReteData(theEnv)->CurrentObjectMatchTimeTag + 1L) > ObjectReteData(theEnv)->CurrentObjectMatchTimeTag)
return;
ObjectReteData(theEnv)->CurrentObjectMatchTimeTag = 0L;
alphaPtr = ObjectNetworkTerminalPointer(theEnv);
while (alphaPtr != NULL)
{
alphaPtr->matchTimeTag = 0L;
lastLevel = alphaPtr->patternNode;
while (lastLevel != NULL)
{
if (lastLevel->matchTimeTag == 0L)
break;
lastLevel->matchTimeTag = 0L;
lastLevel = lastLevel->lastLevel;
}
alphaPtr = alphaPtr->nxtTerminal;
}
}
static void QueueObjectMatchAction(
Environment *theEnv,
int type,
Instance *ins,
int slotNameID)
{
OBJECT_MATCH_ACTION *prv,*cur,*newMatch;
OBJECT_MATCH_ACTION *prvRetract = NULL;
prv = NULL;
cur = ObjectReteData(theEnv)->ObjectMatchActionQueue;
while (cur != NULL)
{
if (cur->ins == ins)
{
if (cur->type == OBJECT_ASSERT)
{
if (type == OBJECT_RETRACT)
{
if (prv == NULL)
ObjectReteData(theEnv)->ObjectMatchActionQueue = cur->nxt;
else
prv->nxt = cur->nxt;
cur->ins->busy--;
ReturnObjectMatchAction(theEnv,cur);
}
}
else if (type == OBJECT_RETRACT)
{
cur->type = OBJECT_RETRACT;
if (cur->slotNameIDs != NULL)
{
rm(theEnv,cur->slotNameIDs,SlotBitMapSize(cur->slotNameIDs));
cur->slotNameIDs = NULL;
}
}
else
cur->slotNameIDs = QueueModifySlotMap(theEnv,cur->slotNameIDs,slotNameID);
return;
}
if (cur->type == OBJECT_RETRACT)
{ prvRetract = cur; }
prv = cur;
cur = cur->nxt;
}
newMatch = get_struct(theEnv,objectMatchAction);
newMatch->type = type;
newMatch->nxt = NULL;
newMatch->slotNameIDs = (type != OBJECT_MODIFY) ? NULL :
QueueModifySlotMap(theEnv,NULL,slotNameID);
newMatch->ins = ins;
newMatch->ins->busy++;
if (type == OBJECT_RETRACT)
{
if (prvRetract == NULL)
{
newMatch->nxt = ObjectReteData(theEnv)->ObjectMatchActionQueue;
ObjectReteData(theEnv)->ObjectMatchActionQueue = newMatch;
}
else
{
newMatch->nxt = prvRetract->nxt;
prvRetract->nxt = newMatch;
}
}
else
if (prv == NULL)
ObjectReteData(theEnv)->ObjectMatchActionQueue = newMatch;
else
prv->nxt = newMatch;
}
static SLOT_BITMAP *QueueModifySlotMap(
Environment *theEnv,
SLOT_BITMAP *oldMap,
int slotNameID)
{
SLOT_BITMAP *newMap;
unsigned short newmaxid;
unsigned oldsz,newsz;
if ((oldMap == NULL) ? true : (slotNameID > oldMap->maxid))
{
newmaxid = (unsigned short) (slotNameID * 2);
newsz = sizeof(SLOT_BITMAP) +
(sizeof(char) * (newmaxid / BITS_PER_BYTE));
newMap = (SLOT_BITMAP *) gm2(theEnv,newsz);
ClearBitString(newMap,newsz);
if (oldMap != NULL)
{
oldsz = SlotBitMapSize(oldMap);
GenCopyMemory(char,oldsz,newMap,oldMap);
rm(theEnv,oldMap,oldsz);
}
newMap->maxid = newmaxid;
}
else
newMap = oldMap;
SetBitMap(newMap->map,slotNameID);
return(newMap);
}
static void ReturnObjectMatchAction(
Environment *theEnv,
OBJECT_MATCH_ACTION *omaPtr)
{
if (omaPtr->slotNameIDs != NULL)
rm(theEnv,omaPtr->slotNameIDs,SlotBitMapSize(omaPtr->slotNameIDs));
rtn_struct(theEnv,objectMatchAction,omaPtr);
}
static void ProcessObjectMatchQueue(
Environment *theEnv)
{
OBJECT_MATCH_ACTION *cur;
while ((ObjectReteData(theEnv)->ObjectMatchActionQueue != NULL) &&
(ObjectReteData(theEnv)->DelayObjectPatternMatching == false))
{
cur = ObjectReteData(theEnv)->ObjectMatchActionQueue;
ObjectReteData(theEnv)->ObjectMatchActionQueue = cur->nxt;
switch(cur->type)
{
case OBJECT_ASSERT :
ObjectAssertAction(theEnv,cur->ins);
break;
case OBJECT_RETRACT :
ObjectRetractAction(theEnv,cur->ins,cur->slotNameIDs);
break;
default :
ObjectModifyAction(theEnv,cur->ins,cur->slotNameIDs);
}
cur->ins->busy--;
ReturnObjectMatchAction(theEnv,cur);
}
}
static void MarkObjectPatternNetwork(
Environment *theEnv,
SLOT_BITMAP *slotNameIDs)
{
OBJECT_ALPHA_NODE *alphaPtr;
OBJECT_PATTERN_NODE *upper;
Defclass *cls;
CLASS_ALPHA_LINK *current_alpha_link;
cls = ObjectReteData(theEnv)->CurrentPatternObject->cls;
current_alpha_link = cls->relevant_terminal_alpha_nodes;
ResetObjectMatchTimeTags(theEnv);
ObjectReteData(theEnv)->CurrentObjectMatchTimeTag++;
while (current_alpha_link != NULL)
{
alphaPtr = current_alpha_link->alphaNode;
#if (! RUN_TIME) && (! BLOAD_ONLY)
if (EngineData(theEnv)->IncrementalResetInProgress &&
(alphaPtr->header.initialize == false))
{
current_alpha_link = current_alpha_link->next;
continue;
}
#endif
if (slotNameIDs == NULL)
{
alphaPtr->matchTimeTag = ObjectReteData(theEnv)->CurrentObjectMatchTimeTag;
for (upper = alphaPtr->patternNode;
upper != NULL;
upper = upper->lastLevel)
{
if (upper->matchTimeTag == ObjectReteData(theEnv)->CurrentObjectMatchTimeTag)
{ break; }
else
{ upper->matchTimeTag = ObjectReteData(theEnv)->CurrentObjectMatchTimeTag; }
}
}
else if (alphaPtr->slotbmp != NULL)
{
if (CompareSlotBitMaps(slotNameIDs,
(SLOT_BITMAP *) alphaPtr->slotbmp->contents))
{
alphaPtr->matchTimeTag = ObjectReteData(theEnv)->CurrentObjectMatchTimeTag;
for (upper = alphaPtr->patternNode;
upper != NULL;
upper = upper->lastLevel)
{
if (upper->matchTimeTag == ObjectReteData(theEnv)->CurrentObjectMatchTimeTag)
{ break; }
else
{ upper->matchTimeTag = ObjectReteData(theEnv)->CurrentObjectMatchTimeTag; }
}
}
}
current_alpha_link = current_alpha_link->next;
}
}
static bool CompareSlotBitMaps(
SLOT_BITMAP *smap1,
SLOT_BITMAP *smap2)
{
unsigned short i, maxByte;
maxByte = (unsigned short)
(((smap1->maxid < smap2->maxid) ?
smap1->maxid : smap2->maxid) / BITS_PER_BYTE);
for (i = 0 ; i <= maxByte ; i++)
if (smap1->map[i] & smap2->map[i])
return true;
return false;
}
static void ObjectPatternMatch(
Environment *theEnv,
size_t offset,
size_t multifieldsProcessed,
OBJECT_PATTERN_NODE *patternTop,
struct multifieldMarker *endMark)
{
size_t saveSlotLength;
InstanceSlot *saveSlot;
OBJECT_PATTERN_NODE *blockedNode;
while (patternTop != NULL)
{
if (patternTop->matchTimeTag == ObjectReteData(theEnv)->CurrentObjectMatchTimeTag)
{
if ((patternTop->slotNameID == ISA_ID) ||
(patternTop->slotNameID == NAME_ID))
{
ObjectReteData(theEnv)->CurrentPatternObjectSlot = NULL;
ObjectReteData(theEnv)->CurrentObjectSlotLength = 1;
offset = 0;
}
else if ((ObjectReteData(theEnv)->CurrentPatternObjectSlot == NULL) ? true :
(ObjectReteData(theEnv)->CurrentPatternObjectSlot->desc->slotName->id != patternTop->slotNameID))
{
ObjectReteData(theEnv)->CurrentPatternObjectSlot =
ObjectReteData(theEnv)->CurrentPatternObject->slotAddresses[ObjectReteData(theEnv)->CurrentPatternObject->cls->slotNameMap
[patternTop->slotNameID] - 1];
offset = 0;
if (ObjectReteData(theEnv)->CurrentPatternObjectSlot->desc->multiple)
ObjectReteData(theEnv)->CurrentObjectSlotLength =
ObjectReteData(theEnv)->CurrentPatternObjectSlot->multifieldValue->length;
else
ObjectReteData(theEnv)->CurrentObjectSlotLength = 1;
}
saveSlotLength = ObjectReteData(theEnv)->CurrentObjectSlotLength;
saveSlot = ObjectReteData(theEnv)->CurrentPatternObjectSlot;
ProcessPatternNode(theEnv,offset,multifieldsProcessed,patternTop,endMark);
ObjectReteData(theEnv)->CurrentObjectSlotLength = saveSlotLength;
ObjectReteData(theEnv)->CurrentPatternObjectSlot = saveSlot;
}
if (patternTop->blocked == true)
{
patternTop->blocked = false;
blockedNode = patternTop;
patternTop = patternTop->rightNode;
while (patternTop != NULL)
{
if ((patternTop->slotNameID != blockedNode->slotNameID) ||
(patternTop->whichField != blockedNode->whichField))
break;
patternTop = patternTop->rightNode;
}
}
else
patternTop = patternTop->rightNode;
}
}
static void ProcessPatternNode(
Environment *theEnv,
size_t offset,
size_t multifieldsProcessed,
OBJECT_PATTERN_NODE *patternNode,
struct multifieldMarker *endMark)
{
unsigned short patternSlotField;
size_t objectSlotField;
size_t objectSlotLength;
size_t repeatCount;
InstanceSlot *objectSlot;
struct multifieldMarker *newMark;
UDFValue theResult;
OBJECT_PATTERN_NODE *tempPtr;
patternSlotField = patternNode->whichField;
objectSlotField = patternSlotField + offset - multifieldsProcessed;
if (ObjectReteData(theEnv)->CurrentPatternObjectSlot == NULL)
{
if (patternNode->selector)
{
if (EvaluateObjectPatternTest(theEnv,objectSlotField,NULL,patternNode->networkTest->nextArg,patternNode))
{
EvaluateExpression(theEnv,patternNode->networkTest,&theResult);
tempPtr = (OBJECT_PATTERN_NODE *) FindHashedPatternNode(theEnv,patternNode,theResult.header->type,theResult.value);
if (tempPtr != NULL)
{
if (tempPtr->alphaNode != NULL)
{ CreateObjectAlphaMatch(theEnv,tempPtr->alphaNode); }
ObjectPatternMatch(theEnv,offset,multifieldsProcessed,tempPtr->nextLevel,endMark);
}
}
}
else if ((patternNode->networkTest == NULL) ? true :
(EvaluateObjectPatternTest(theEnv,objectSlotField,NULL,
(Expression *) patternNode->networkTest,patternNode)))
{
if (patternNode->alphaNode != NULL)
CreateObjectAlphaMatch(theEnv,patternNode->alphaNode);
ObjectPatternMatch(theEnv,offset,multifieldsProcessed,patternNode->nextLevel,endMark);
}
return;
}
if (patternNode->multifieldNode == 0)
{
if (patternNode->selector)
{
if (EvaluateObjectPatternTest(theEnv,objectSlotField,NULL,patternNode->networkTest->nextArg,patternNode))
{
EvaluateExpression(theEnv,patternNode->networkTest,&theResult);
tempPtr = (OBJECT_PATTERN_NODE *) FindHashedPatternNode(theEnv,patternNode,theResult.header->type,theResult.value);
if (tempPtr != NULL)
{
if (tempPtr->alphaNode != NULL)
{ CreateObjectAlphaMatch(theEnv,tempPtr->alphaNode); }
ObjectPatternMatch(theEnv,offset,multifieldsProcessed,tempPtr->nextLevel,endMark);
}
}
}
else if ((patternNode->networkTest == NULL) ? true :
EvaluateObjectPatternTest(theEnv,objectSlotField,NULL,
(Expression *) patternNode->networkTest,patternNode))
{
if (patternNode->alphaNode != NULL)
CreateObjectAlphaMatch(theEnv,patternNode->alphaNode);
ObjectPatternMatch(theEnv,offset,multifieldsProcessed,patternNode->nextLevel,endMark);
}
return;
}
newMark = get_struct(theEnv,multifieldMarker);
newMark->whichField = patternSlotField;
newMark->where.whichSlot = (void *) ObjectReteData(theEnv)->CurrentPatternObjectSlot->desc->slotName->name;
newMark->startPosition = objectSlotField;
newMark->next = NULL;
if (ObjectReteData(theEnv)->CurrentPatternObjectMarks == NULL)
ObjectReteData(theEnv)->CurrentPatternObjectMarks = newMark;
else
endMark->next = newMark;
if (patternNode->endSlot == false)
{
objectSlotLength = ObjectReteData(theEnv)->CurrentObjectSlotLength;
objectSlot = ObjectReteData(theEnv)->CurrentPatternObjectSlot;
newMark->range = 0;
if ((objectSlotLength + 2) < (newMark->startPosition + patternNode->leaveFields))
{ repeatCount = 0; }
else
{ repeatCount = objectSlotLength + 2 - newMark->startPosition - patternNode->leaveFields; }
while (repeatCount > 0)
{
if (patternNode->selector)
{
if (EvaluateObjectPatternTest(theEnv,objectSlotField,newMark,patternNode->networkTest->nextArg,patternNode))
{
EvaluateExpression(theEnv,patternNode->networkTest,&theResult);
tempPtr = (OBJECT_PATTERN_NODE *) FindHashedPatternNode(theEnv,patternNode,theResult.header->type,theResult.value);
if (tempPtr != NULL)
{
if (tempPtr->alphaNode != NULL)
{ CreateObjectAlphaMatch(theEnv,tempPtr->alphaNode); }
ObjectPatternMatch(theEnv,offset + newMark->startPosition + newMark->range - objectSlotField,
multifieldsProcessed+1,tempPtr->nextLevel,newMark);
ObjectReteData(theEnv)->CurrentObjectSlotLength = objectSlotLength;
ObjectReteData(theEnv)->CurrentPatternObjectSlot = objectSlot;
}
}
}
else if ((patternNode->networkTest == NULL) ? true :
EvaluateObjectPatternTest(theEnv,objectSlotField,newMark,
(Expression *) patternNode->networkTest,patternNode))
{
if (patternNode->alphaNode != NULL)
CreateObjectAlphaMatch(theEnv,patternNode->alphaNode);
ObjectPatternMatch(theEnv,offset + newMark->startPosition + newMark->range - objectSlotField,
multifieldsProcessed+1,patternNode->nextLevel,newMark);
ObjectReteData(theEnv)->CurrentObjectSlotLength = objectSlotLength;
ObjectReteData(theEnv)->CurrentPatternObjectSlot = objectSlot;
}
newMark->range++;
repeatCount--;
}
}
else
{
newMark->range = ObjectReteData(theEnv)->CurrentObjectSlotLength + 1 - newMark->startPosition - patternNode->leaveFields;
if (patternNode->selector)
{
if (EvaluateObjectPatternTest(theEnv,objectSlotField,newMark,patternNode->networkTest->nextArg,patternNode))
{
EvaluateExpression(theEnv,patternNode->networkTest,&theResult);
tempPtr = (OBJECT_PATTERN_NODE *) FindHashedPatternNode(theEnv,patternNode,theResult.header->type,theResult.value);
if (tempPtr != NULL)
{
if (tempPtr->alphaNode != NULL)
CreateObjectAlphaMatch(theEnv,tempPtr->alphaNode);
ObjectPatternMatch(theEnv,0,0,tempPtr->nextLevel,newMark);
}
}
}
else if ((patternNode->networkTest == NULL) ? true :
EvaluateObjectPatternTest(theEnv,objectSlotField,newMark,
(Expression *) patternNode->networkTest,patternNode))
{
if (patternNode->alphaNode != NULL)
CreateObjectAlphaMatch(theEnv,patternNode->alphaNode);
ObjectPatternMatch(theEnv,0,0,patternNode->nextLevel,newMark);
}
}
if (ObjectReteData(theEnv)->CurrentPatternObjectMarks == newMark)
ObjectReteData(theEnv)->CurrentPatternObjectMarks = NULL;
else
endMark->next = NULL;
rtn_struct(theEnv,multifieldMarker,newMark);
}
static void CreateObjectAlphaMatch(
Environment *theEnv,
OBJECT_ALPHA_NODE *alphaPtr)
{
struct joinNode *listOfJoins;
struct partialMatch *theMatch;
struct patternMatch *newMatch;
unsigned long hashValue;
while (alphaPtr != NULL)
{
if (alphaPtr->matchTimeTag == ObjectReteData(theEnv)->CurrentObjectMatchTimeTag)
{
hashValue = ComputeRightHashValue(theEnv,&alphaPtr->header);
ObjectReteData(theEnv)->CurrentPatternObject->busy++;
theMatch = CreateAlphaMatch(theEnv,ObjectReteData(theEnv)->CurrentPatternObject,
ObjectReteData(theEnv)->CurrentPatternObjectMarks,
(struct patternNodeHeader *) alphaPtr,hashValue);
theMatch->owner = alphaPtr;
newMatch = get_struct(theEnv,patternMatch);
newMatch->next = (struct patternMatch *) ObjectReteData(theEnv)->CurrentPatternObject->partialMatchList;
newMatch->matchingPattern = (struct patternNodeHeader *) alphaPtr;
newMatch->theMatch = theMatch;
ObjectReteData(theEnv)->CurrentPatternObject->partialMatchList = (void *) newMatch;
listOfJoins = alphaPtr->header.entryJoin;
while (listOfJoins != NULL)
{
NetworkAssert(theEnv,theMatch,listOfJoins);
listOfJoins = listOfJoins->rightMatchNode;
}
}
alphaPtr = alphaPtr->nxtInGroup;
}
}
static bool EvaluateObjectPatternTest(
Environment *theEnv,
size_t objectSlotField,
struct multifieldMarker *selfSlotMarker,
Expression *networkTest,
OBJECT_PATTERN_NODE *patternNode)
{
UDFValue vresult;
int rv;
if (networkTest == NULL) return true;
if (networkTest->type == OBJ_PN_CONSTANT)
{
struct expr *oldArgument;
oldArgument = EvaluationData(theEnv)->CurrentExpression;
EvaluationData(theEnv)->CurrentExpression = networkTest;
rv = ObjectCmpConstantFunction(theEnv,networkTest->value,&vresult);
EvaluationData(theEnv)->CurrentExpression = oldArgument;
if (rv)
{
if (((struct ObjectCmpPNConstant *)
networkTest->bitMapValue->contents)->pass)
patternNode->blocked = true;
return true;
}
return false;
}
if (networkTest->value == ExpressionData(theEnv)->PTR_OR)
{
networkTest = networkTest->argList;
while (networkTest != NULL)
{
if (EvaluateObjectPatternTest(theEnv,objectSlotField,selfSlotMarker,networkTest,patternNode))
{
patternNode->blocked = false;
return true;
}
patternNode->blocked = false;
networkTest = networkTest->nextArg;
}
return false;
}
else if (networkTest->value == ExpressionData(theEnv)->PTR_AND)
{
networkTest = networkTest->argList;
while (networkTest != NULL)
{
if (EvaluateObjectPatternTest(theEnv,objectSlotField,selfSlotMarker,networkTest,patternNode)
== false)
{
patternNode->blocked = false;
return false;
}
patternNode->blocked = false;
networkTest = networkTest->nextArg;
}
return true;
}
else
{
EvaluationData(theEnv)->HaltExecution = false;
if (EvaluateExpression(theEnv,networkTest,&vresult))
{
ObjectPatternNetErrorMessage(theEnv,patternNode);
EvaluationData(theEnv)->EvaluationError = false;
EvaluationData(theEnv)->HaltExecution = false;
return false;
}
if (vresult.value != FalseSymbol(theEnv))
return true;
}
return false;
}
static void ObjectAssertAction(
Environment *theEnv,
Instance *ins)
{
ins->patternHeader.timeTag = ObjectReteData(theEnv)->UseEntityTimeTag;
ObjectReteData(theEnv)->CurrentPatternObject = ins;
ObjectReteData(theEnv)->CurrentPatternObjectSlot = NULL;
MarkObjectPatternNetwork(theEnv,NULL);
ObjectPatternMatch(theEnv,0,0,ObjectNetworkPointer(theEnv),NULL);
ins->reteSynchronized = true;
}
static void ObjectModifyAction(
Environment *theEnv,
Instance *ins,
SLOT_BITMAP *slotNameIDs)
{
ins->patternHeader.timeTag = ObjectReteData(theEnv)->UseEntityTimeTag;
ObjectRetractAction(theEnv,ins,slotNameIDs);
ObjectReteData(theEnv)->CurrentPatternObject = ins;
ObjectReteData(theEnv)->CurrentPatternObjectSlot = NULL;
MarkObjectPatternNetwork(theEnv,slotNameIDs);
ObjectPatternMatch(theEnv,0,0,ObjectNetworkPointer(theEnv),NULL);
ins->reteSynchronized = true;
}
static void ObjectRetractAction(
Environment *theEnv,
Instance *ins,
SLOT_BITMAP *slotNameIDs)
{
struct patternMatch *prvMatch,*tmpMatch,
*deleteMatch,*lastDeleteMatch;
OBJECT_ALPHA_NODE *alphaPtr;
void *saveDependents;
if (slotNameIDs == NULL)
{
if (ins->partialMatchList != NULL)
{
tmpMatch = (struct patternMatch *) ins->partialMatchList;
while (tmpMatch != NULL)
{
ins->busy--;
tmpMatch = tmpMatch->next;
}
NetworkRetract(theEnv,(struct patternMatch *) ins->partialMatchList);
ins->partialMatchList = NULL;
}
}
else
{
deleteMatch = NULL;
lastDeleteMatch = NULL;
prvMatch = NULL;
tmpMatch = (struct patternMatch *) ins->partialMatchList;
while (tmpMatch != NULL)
{
alphaPtr = (OBJECT_ALPHA_NODE *) tmpMatch->matchingPattern;
if (alphaPtr->slotbmp != NULL)
{
if (CompareSlotBitMaps(slotNameIDs,
(SLOT_BITMAP *) alphaPtr->slotbmp->contents))
{
ins->busy--;
if (prvMatch == NULL)
ins->partialMatchList = (void *) tmpMatch->next;
else
prvMatch->next = tmpMatch->next;
if (!deleteMatch)
deleteMatch = tmpMatch;
else
lastDeleteMatch->next = tmpMatch;
lastDeleteMatch = tmpMatch;
tmpMatch = tmpMatch->next;
lastDeleteMatch->next = NULL;
}
else
{
prvMatch = tmpMatch;
tmpMatch = tmpMatch->next;
}
}
else
{
prvMatch = tmpMatch;
tmpMatch = tmpMatch->next;
}
}
if (deleteMatch != NULL)
{
saveDependents = ins->patternHeader.dependents;
ins->patternHeader.dependents = NULL;
NetworkRetract(theEnv,deleteMatch);
ins->patternHeader.dependents = saveDependents;
}
}
ins->reteSynchronized = true;
}
static void ObjectPatternNetErrorMessage(
Environment *theEnv,
OBJECT_PATTERN_NODE *patternPtr)
{
PrintErrorID(theEnv,"OBJRTMCH",1,true);
WriteString(theEnv,STDERR,"This error occurred in the object pattern network\n");
WriteString(theEnv,STDERR," Currently active instance: [");
WriteString(theEnv,STDERR,ObjectReteData(theEnv)->CurrentPatternObject->name->contents);
WriteString(theEnv,STDERR,"]\n");
WriteString(theEnv,STDERR," Problem resides in slot '");
WriteString(theEnv,STDERR,FindIDSlotName(theEnv,patternPtr->slotNameID)->contents);
WriteString(theEnv,STDERR,"' field #");
PrintUnsignedInteger(theEnv,STDERR,patternPtr->whichField);
WriteString(theEnv,STDERR,"\n");
TraceErrorToObjectPattern(theEnv,true,patternPtr);
WriteString(theEnv,STDERR,"\n");
}
static void TraceErrorToObjectPattern(
Environment *theEnv,
bool errorNode,
OBJECT_PATTERN_NODE *patternPtr)
{
struct joinNode *joinPtr;
while (patternPtr != NULL)
{
if (patternPtr->alphaNode != NULL)
{
joinPtr = patternPtr->alphaNode->header.entryJoin;
while (joinPtr != NULL)
{
TraceErrorToRule(theEnv,joinPtr," ");
joinPtr = joinPtr->rightMatchNode;
}
}
TraceErrorToObjectPattern(theEnv,false,patternPtr->nextLevel);
if (errorNode)
break;
patternPtr = patternPtr->rightNode;
}
}
#endif