📄 factmngr.c
字号:
/* MatchFactFunction: Filters a fact through *//* 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) { unsigned long hashValue; unsigned long length, i; struct field *theField; struct fact *theFact = (struct fact *) vTheFact; intBool duplicate; /*==========================================*/ /* 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,&duplicate); if (duplicate) 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 + -