📄 factmngr.c
字号:
/* the appropriate fact pattern network. */
/*********************************************/
globle void MatchFactFunction(
void *theEnv,
void *vTheFact)
{
struct fact *theFact = (struct fact *) vTheFact;
FactPatternMatch(theEnv,theFact,theFact->whichDeftemplate->patternNetwork,0,NULL,NULL);
}
/*********************************************************/
/* EnvRetract: C access routine for the retract command. */
/*********************************************************/
globle intBool EnvRetract(
void *theEnv,
void *vTheFact)
{
struct fact *theFact = (struct fact *) vTheFact;
struct deftemplate *theTemplate = theFact->whichDeftemplate;
/*===========================================*/
/* A fact can not be retracted while another */
/* fact is being asserted or retracted. */
/*===========================================*/
if (EngineData(theEnv)->JoinOperationInProgress)
{
PrintErrorID(theEnv,"FACTMNGR",1,TRUE);
EnvPrintRouter(theEnv,WERROR,"Facts may not be retracted during pattern-matching\n");
return(FALSE);
}
/*====================================*/
/* A NULL fact pointer indicates that */
/* all facts should be retracted. */
/*====================================*/
if (theFact == NULL)
{
RemoveAllFacts(theEnv);
return(TRUE);
}
/*======================================================*/
/* Check to see if the fact has already been retracted. */
/*======================================================*/
if (theFact->garbage) return(FALSE);
/*============================*/
/* Print retraction output if */
/* facts are being watched. */
/*============================*/
#if DEBUGGING_FUNCTIONS
if (theFact->whichDeftemplate->watch)
{
EnvPrintRouter(theEnv,WTRACE,"<== ");
PrintFactWithIdentifier(theEnv,WTRACE,theFact);
EnvPrintRouter(theEnv,WTRACE,"\n");
}
#endif
/*==================================*/
/* Set the change flag to indicate */
/* the fact-list has been modified. */
/*==================================*/
FactData(theEnv)->ChangeToFactList = TRUE;
/*===============================================*/
/* Remove any links between the fact and partial */
/* matches in the join network. These links are */
/* used to keep track of logical dependencies. */
/*===============================================*/
RemoveEntityDependencies(theEnv,(struct patternEntity *) theFact);
/*===========================================*/
/* Remove the fact from the fact hash table. */
/*===========================================*/
RemoveHashedFact(theEnv,theFact);
/*=========================================*/
/* Remove the fact from its template list. */
/*=========================================*/
if (theFact == theTemplate->lastFact)
{ theTemplate->lastFact = theFact->previousTemplateFact; }
if (theFact->previousTemplateFact == NULL)
{
theTemplate->factList = theTemplate->factList->nextTemplateFact;
if (theTemplate->factList != NULL)
{ theTemplate->factList->previousTemplateFact = NULL; }
}
else
{
theFact->previousTemplateFact->nextTemplateFact = theFact->nextTemplateFact;
if (theFact->nextTemplateFact != NULL)
{ theFact->nextTemplateFact->previousTemplateFact = theFact->previousTemplateFact; }
}
/*=====================================*/
/* Remove the fact from the fact list. */
/*=====================================*/
if (theFact == FactData(theEnv)->LastFact)
{ FactData(theEnv)->LastFact = theFact->previousFact; }
if (theFact->previousFact == NULL)
{
FactData(theEnv)->FactList = FactData(theEnv)->FactList->nextFact;
if (FactData(theEnv)->FactList != NULL)
{ FactData(theEnv)->FactList->previousFact = NULL; }
}
else
{
theFact->previousFact->nextFact = theFact->nextFact;
if (theFact->nextFact != NULL)
{ theFact->nextFact->previousFact = theFact->previousFact; }
}
/*==================================*/
/* Update busy counts and ephemeral */
/* garbage information. */
/*==================================*/
FactDeinstall(theEnv,theFact);
UtilityData(theEnv)->EphemeralItemCount++;
UtilityData(theEnv)->EphemeralItemSize += sizeof(struct fact) + (sizeof(struct field) * theFact->theProposition.multifieldLength);
/*========================================*/
/* Add the fact to the fact garbage list. */
/*========================================*/
theFact->nextFact = FactData(theEnv)->GarbageFacts;
FactData(theEnv)->GarbageFacts = theFact;
theFact->garbage = TRUE;
/*===================================================*/
/* Reset the evaluation error flag since expressions */
/* will be evaluated as part of the retract. */
/*===================================================*/
SetEvaluationError(theEnv,FALSE);
/*===========================================*/
/* Loop through the list of all the patterns */
/* that matched the fact and process the */
/* retract operation for each one. */
/*===========================================*/
EngineData(theEnv)->JoinOperationInProgress = TRUE;
NetworkRetract(theEnv,(struct patternMatch *) theFact->list);
EngineData(theEnv)->JoinOperationInProgress = FALSE;
/*=========================================*/
/* Free partial matches that were released */
/* by the retraction of the fact. */
/*=========================================*/
if (EngineData(theEnv)->ExecutingRule == NULL)
{ FlushGarbagePartialMatches(theEnv); }
/*=========================================*/
/* Retract other facts that were logically */
/* dependent on the fact just retracted. */
/*=========================================*/
ForceLogicalRetractions(theEnv);
/*===========================================*/
/* Force periodic cleanup if the retract was */
/* executed from an embedded application. */
/*===========================================*/
if ((EvaluationData(theEnv)->CurrentEvaluationDepth == 0) && (! CommandLineData(theEnv)->EvaluatingTopLevelCommand) &&
(EvaluationData(theEnv)->CurrentExpression == NULL))
{ PeriodicCleanup(theEnv,TRUE,FALSE); }
/*==================================*/
/* Return TRUE to indicate the fact */
/* was successfully retracted. */
/*==================================*/
return(TRUE);
}
/*******************************************************************/
/* RemoveGarbageFacts: Returns facts that have been retracted to */
/* the pool of available memory. It is necessary to postpone */
/* returning the facts to memory because RHS actions retrieve */
/* their variable bindings directly from the fact data structure */
/* and the facts may be in use in other data structures. */
/*******************************************************************/
static void RemoveGarbageFacts(
void *theEnv)
{
struct fact *factPtr, *nextPtr, *lastPtr = NULL;
factPtr = FactData(theEnv)->GarbageFacts;
while (factPtr != NULL)
{
nextPtr = factPtr->nextFact;
if ((factPtr->factHeader.busyCount == 0) &&
(((int) factPtr->depth) > EvaluationData(theEnv)->CurrentEvaluationDepth))
{
UtilityData(theEnv)->EphemeralItemCount--;
UtilityData(theEnv)->EphemeralItemSize -= sizeof(struct fact) + (sizeof(struct field) * factPtr->theProposition.multifieldLength);
ReturnFact(theEnv,factPtr);
if (lastPtr == NULL) FactData(theEnv)->GarbageFacts = nextPtr;
else lastPtr->nextFact = nextPtr;
}
else
{ lastPtr = factPtr; }
factPtr = nextPtr;
}
}
/********************************************************/
/* EnvAssert: C access routine for the assert function. */
/********************************************************/
globle void *EnvAssert(
void *theEnv,
void *vTheFact)
{
int hashValue;
unsigned long length, i;
struct field *theField;
struct fact *theFact = (struct fact *) vTheFact;
/*==========================================*/
/* A fact can not be asserted while another */
/* fact is being asserted or retracted. */
/*==========================================*/
if (EngineData(theEnv)->JoinOperationInProgress)
{
ReturnFact(theEnv,theFact);
PrintErrorID(theEnv,"FACTMNGR",2,TRUE);
EnvPrintRouter(theEnv,WERROR,"Facts may not be asserted during pattern-matching\n");
return(NULL);
}
/*=============================================================*/
/* Replace invalid data types in the fact with the symbol nil. */
/*=============================================================*/
length = theFact->theProposition.multifieldLength;
theField = theFact->theProposition.theFields;
for (i = 0; i < length; i++)
{
if (theField[i].type == RVOID)
{
theField[i].type = SYMBOL;
theField[i].value = (void *) EnvAddSymbol(theEnv,"nil");
}
}
/*========================================================*/
/* If fact assertions are being checked for duplications, */
/* then search the fact list for a duplicate fact. */
/*========================================================*/
hashValue = HandleFactDuplication(theEnv,theFact);
if (hashValue < 0) return(NULL);
/*==========================================================*/
/* If necessary, add logical dependency links between the */
/* fact and the partial match which is its logical support. */
/*==========================================================*/
if (AddLogicalDependencies(theEnv,(struct patternEntity *) theFact,FALSE) == FALSE)
{
ReturnFact(theEnv,theFact);
return(NULL);
}
/*======================================*/
/* Add the fact to the fact hash table. */
/*======================================*/
AddHashedFact(theEnv,theFact,hashValue);
/*================================*/
/* Add the fact to the fact list. */
/*================================*/
theFact->nextFact = NULL;
theFact->list = NULL;
theFact->previousFact = FactData(theEnv)->LastFact;
if (FactData(theEnv)->LastFact == NULL)
{ FactData(theEnv)->FactList = theFact; }
else
{ FactData(theEnv)->LastFact->nextFact = theFact; }
FactData(theEnv)->LastFact = theFact;
/*====================================*/
/* Add the fact to its template list. */
/*====================================*/
theFact->previousTemplateFact = theFact->whichDeftemplate->lastFact;
theFact->nextTemplateFact = NULL;
if (theFact->whichDeftemplate->lastFact == NULL)
{ theFact->whichDeftemplate->factList = theFact; }
else
{ theFact->whichDeftemplate->lastFact->nextTemplateFact = theFact; }
theFact->whichDeftemplate->lastFact = theFact;
/*==================================*/
/* Set the fact index and time tag. */
/*==================================*/
theFact->factIndex = FactData(theEnv)->NextFactIndex++;
theFact->factHeader.timeTag = DefruleData(theEnv)->CurrentEntityTimeTag++;
/*=====================*/
/* Update busy counts. */
/*=====================*/
FactInstall(theEnv,theFact);
/*==========================*/
/* Print assert output if */
/* facts are being watched. */
/*==========================*/
#if DEBUGGING_FUNCTIONS
if (theFact->whichDeftemplate->watch)
{
EnvPrintRouter(theEnv,WTRACE,"==> ");
PrintFactWithIdentifier(theEnv,WTRACE,theFact);
EnvPrintRouter(theEnv,WTRACE,"\n");
}
#endif
/*==================================*/
/* Set the change flag to indicate */
/* the fact-list has been modified. */
/*==================================*/
FactData(theEnv)->ChangeToFactList = TRUE;
/*==========================================*/
/* Check for constraint errors in the fact. */
/*==========================================*/
CheckTemplateFact(theEnv,theFact);
/*===================================================*/
/* Reset the evaluation error flag since expressions */
/* will be evaluated as part of the assert . */
/*===================================================*/
SetEvaluationError(theEnv,FALSE);
/*=============================================*/
/* Pattern match the fact using the associated */
/* deftemplate's pattern network. */
/*=============================================*/
EngineData(theEnv)->JoinOperationInProgress = TRUE;
FactPatternMatch(theEnv,theFact,theFact->whichDeftemplate->patternNetwork,0,NULL,NULL);
EngineData(theEnv)->JoinOperationInProgress = FALSE;
/*===================================================*/
/* Retract other facts that were logically dependent */
/* on the non-existence of the fact just asserted. */
/*===================================================*/
ForceLogicalRetractions(theEnv);
/*=========================================*/
/* Free partial matches that were released */
/* by the assertion of the fact. */
/*=========================================*/
if (EngineData(theEnv)->ExecutingRule == NULL) FlushGarbagePartialMatches(theEnv);
/*==========================================*/
/* Force periodic cleanup if the assert was */
/* executed from an embedded application. */
/*==========================================*/
if ((EvaluationData(theEnv)->CurrentEvaluationDepth == 0) && (! CommandLineData(theEnv)->EvaluatingTopLevelCommand) &&
(EvaluationData(theEnv)->CurrentExpression == NULL))
{ PeriodicCleanup(theEnv,TRUE,FALSE); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -