📄 factbld.c
字号:
FactData(theEnv)->CurrentDeftemplate->patternNetwork = newNode;
return(newNode);
}
/*************************************************************/
/* DetachFactPattern: Removes a pattern node and all of its */
/* parent nodes from the pattern network. Nodes are only */
/* removed if they are no longer shared (i.e. a pattern */
/* node that has more than one child node is shared). A */
/* pattern from a rule is typically removed by removing */
/* the bottom most pattern node used by the pattern and */
/* then removing any parent nodes which are not shared by */
/* other patterns. */
/* */
/* Example: */
/* Patterns (a b c d) and (a b e f) would be represented */
/* by the pattern net shown on the left. If (a b c d) */
/* was detached, the resultant pattern net would be the */
/* one shown on the right. */
/* */
/* a a */
/* | | */
/* b b */
/* | | */
/* c--e e */
/* | | | */
/* d f f */
/* */
/*************************************************************/
static void DetachFactPattern(
void *theEnv,
struct patternNodeHeader *thePattern)
{
struct factPatternNode *patternPtr;
struct factPatternNode *upperLevel;
/*=====================================================*/
/* Get rid of any matches stored in the alpha memory. */
/*=====================================================*/
patternPtr = (struct factPatternNode *) thePattern;
ClearPatternMatches(theEnv,patternPtr);
/*=====================================================*/
/* If there are no joins entered from this pattern, then */
/* the pattern node is no longer a stop node. Also if */
/* the pattern has a next level pointer, then it can */
/* not be removed since other patterns make use of it. */
/*=====================================================*/
if (patternPtr->header.entryJoin == NULL) patternPtr->header.stopNode = FALSE;
if (patternPtr->nextLevel != NULL) return;
/*==============================================================*/
/* Loop until all appropriate pattern nodes have been detached. */
/*==============================================================*/
upperLevel = patternPtr;
while (upperLevel != NULL)
{
if ((upperLevel->leftNode == NULL) &&
(upperLevel->rightNode == NULL))
{
/*===============================================*/
/* Pattern node is the only node on this level. */
/* Remove it and continue detaching other nodes */
/* above this one, because no other patterns are */
/* dependent upon this node. */
/*===============================================*/
patternPtr = upperLevel;
upperLevel = patternPtr->lastLevel;
if (upperLevel == NULL)
{ FindAndSetDeftemplatePatternNetwork(theEnv,patternPtr,NULL); }
else
{
upperLevel->nextLevel = NULL;
if (upperLevel->header.stopNode) upperLevel = NULL;
}
RemoveHashedExpression(theEnv,patternPtr->networkTest);
rtn_struct(theEnv,factPatternNode,patternPtr);
}
else if (upperLevel->leftNode != NULL)
{
/*====================================================*/
/* Pattern node has another pattern node which must */
/* be checked preceding it. Remove the pattern node, */
/* but do not detach any nodes above this one. */
/*====================================================*/
patternPtr = upperLevel;
upperLevel->leftNode->rightNode = upperLevel->rightNode;
if (upperLevel->rightNode != NULL)
{ upperLevel->rightNode->leftNode = upperLevel->leftNode; }
RemoveHashedExpression(theEnv,patternPtr->networkTest);
rtn_struct(theEnv,factPatternNode,patternPtr);
upperLevel = NULL;
}
else
{
/*====================================================*/
/* Pattern node has no pattern node preceding it, but */
/* does have one succeeding it. Remove the pattern */
/* node, but do not detach any nodes above this one. */
/*====================================================*/
patternPtr = upperLevel;
upperLevel = upperLevel->lastLevel;
if (upperLevel == NULL)
{ FindAndSetDeftemplatePatternNetwork(theEnv,patternPtr,patternPtr->rightNode); }
else
{ upperLevel->nextLevel = patternPtr->rightNode; }
patternPtr->rightNode->leftNode = NULL;
RemoveHashedExpression(theEnv,patternPtr->networkTest);
rtn_struct(theEnv,factPatternNode,patternPtr);
upperLevel = NULL;
}
}
}
#endif
/**************************************************************/
/* DestroyFactPatternNetwork: Deallocates the data structures */
/* associated with a fact pattern network. */
/**************************************************************/
globle void DestroyFactPatternNetwork(
void *theEnv,
struct factPatternNode *thePattern)
{
struct factPatternNode *patternPtr;
if (thePattern == NULL) return;
while (thePattern != NULL)
{
patternPtr = thePattern->rightNode;
DestroyFactPatternNetwork(theEnv,thePattern->nextLevel);
DestroyAlphaBetaMemory(theEnv,thePattern->header.alphaMemory);
#if (! BLOAD_ONLY) && (! RUN_TIME)
rtn_struct(theEnv,factPatternNode,thePattern);
#endif
thePattern = patternPtr;
}
}
#if (! RUN_TIME) && (! BLOAD_ONLY)
/***********************************************************/
/* FindAndSetDeftemplatePatternNetwork: When a deftemplate */
/* pattern is detached from the fact pattern network, it */
/* is not possible to directly detach the link from the */
/* deftemplate to the pattern network (it is a one way */
/* link). Therefore if the top most pointer to a */
/* deftemplates pattern network must be changed, it is */
/* necessary to search the list of deftemplates to find */
/* the appropriate one to modify. */
/***********************************************************/
static void FindAndSetDeftemplatePatternNetwork(
void *theEnv,
struct factPatternNode *rootNode,
struct factPatternNode *newRootNode)
{
struct deftemplate *theDeftemplate;
struct defmodule *theModule;
/*=======================================================*/
/* Save the current module since we will be changing it. */
/*=======================================================*/
SaveCurrentModule(theEnv);
/*=======================================================*/
/* Loop through every module looking for the deftemplate */
/* associated with the specified root node. */
/*=======================================================*/
for (theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,NULL);
theModule != NULL;
theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,theModule))
{
/*======================================================*/
/* Set the current module to the module being examined. */
/*======================================================*/
EnvSetCurrentModule(theEnv,(void *) theModule);
/*======================================================*/
/* Loop through every deftemplate in the current module */
/* searching for the deftemplate associated with the */
/* specified root node. */
/*======================================================*/
for (theDeftemplate = (struct deftemplate *) EnvGetNextDeftemplate(theEnv,NULL);
theDeftemplate != NULL;
theDeftemplate = (struct deftemplate *) EnvGetNextDeftemplate(theEnv,theDeftemplate))
{
/*===========================================================*/
/* When the associated deftemplate is found, change its root */
/* node from the current value to the new value. Restore the */
/* current module before leaving this routine. */
/*===========================================================*/
if (theDeftemplate->patternNetwork == rootNode)
{
RestoreCurrentModule(theEnv);
theDeftemplate->patternNetwork = newRootNode;
return;
}
}
}
/*========================================================*/
/* If the deftemplate wasn't found, then we're presumably */
/* we're in the the middle of a clear and the deftemplate */
/* has already been deleted so there's no need to update */
/* the links to the fact pattern network. */
/*========================================================*/
RestoreCurrentModule(theEnv);
}
/***************************************************************/
/* ClearPatternMatches: Clears the fact list of all pointers */
/* which point to a specific pattern. The pointers are used */
/* to remember which patterns were matched by a fact to */
/* make retraction easier. When a rule is excised, the */
/* pointers need to be removed. */
/***************************************************************/
static void ClearPatternMatches(
void *theEnv,
struct factPatternNode *patternPtr)
{
struct fact *theFact;
struct patternMatch *lastMatch, *theMatch;
/*===========================================*/
/* Loop through every fact in the fact list. */
/*===========================================*/
for (theFact = (struct fact *) EnvGetNextFact(theEnv,NULL);
theFact != NULL;
theFact = (struct fact *) EnvGetNextFact(theEnv,theFact))
{
/*========================================*/
/* Loop through every match for the fact. */
/*========================================*/
lastMatch = NULL;
theMatch = (struct patternMatch *) theFact->list;
while (theMatch != NULL)
{
/*================================================*/
/* If the match is for the pattern being deleted, */
/* then remove the match. */
/*================================================*/
if (theMatch->matchingPattern == (struct patternNodeHeader *) patternPtr)
{
if (lastMatch == NULL)
{
/*=====================================*/
/* Remove the first match of the fact. */
/*=====================================*/
theFact->list = (void *) theMatch->next;
rtn_struct(theEnv,patternMatch,theMatch);
theMatch = (struct patternMatch *) theFact->list;
}
else
{
/*===================================*/
/* Remove a match for the fact which */
/* follows the first match. */
/*===================================*/
lastMatch->next = theMatch->next;
rtn_struct(theEnv,patternMatch,theMatch);
theMatch = lastMatch->next;
}
}
/*====================================================*/
/* If the match is not for the pattern being deleted, */
/* then move on to the next match for the fact. */
/*====================================================*/
else
{
lastMatch = theMatch;
theMatch = theMatch->next;
}
}
}
}
#endif /* (! RUN_TIME) && (! BLOAD_ONLY) */
#endif /* DEFTEMPLATE_CONSTRUCT && DEFRULE_CONSTRUCT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -