📄 engine.c
字号:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.05 04/09/97 */ /* */ /* ENGINE MODULE */ /*******************************************************//*************************************************************//* Purpose: Provides functionality primarily associated with *//* the run and focus commands. *//* *//* Principal Programmer(s): *//* Gary D. Riley *//* *//* Contributing Programmer(s): *//* Bebe Ly *//* Brian L. Donnell *//* *//* Revision History: *//* *//*************************************************************/#define _ENGINE_SOURCE_#include <stdio.h>#define _CLIPS_STDIO_#include <string.h>#include "setup.h"#if DEFRULE_CONSTRUCT#include "constant.h"#include "clipsmem.h"#include "watch.h"#include "router.h"#include "argacces.h"#include "reteutil.h"#include "utility.h"#include "retract.h"#include "ruledlt.h"#include "prccode.h"#include "prcdrfun.h"#include "inscom.h"#include "factmngr.h" #include "sysdep.h"#include "agenda.h"#include "modulutl.h"#include "engine.h" /***************************************//* LOCAL INTERNAL FUNCTION DEFINITIONS *//***************************************/#if ANSI_COMPILER static struct activation *NextActivationToFire(void); static struct defmodule *RemoveFocus(struct defmodule *);#else static struct activation *NextActivationToFire(); static struct defmodule *RemoveFocus();#endif/****************************************//* GLOBAL INTERNAL VARIABLE DEFINITIONS *//****************************************/ globle struct defrule *ExecutingRule = NULL; globle BOOLEAN HaltRules = CLIPS_FALSE;#if LOGICAL_DEPENDENCIES globle struct joinNode *TheLogicalJoin = NULL;#endif/***************************************//* LOCAL INTERNAL VARIABLE DEFINITIONS *//***************************************/ static struct callFunctionItem *ListOfRunFunctions = NULL; static struct focus *CurrentFocus = NULL; static int FocusChanged = CLIPS_FALSE;#if DEBUGGING_FUNCTIONS static int WatchStatistics = OFF; static int WatchFocus = OFF;#endif /**********************************************//* Run: C access routine for the run command. *//**********************************************/globle long int Run(runLimit) long int runLimit; { long int rulesFired = 0; DATA_OBJECT result; struct callFunctionItem *theRunFunction;#if DEBUGGING_FUNCTIONS long int maxActivations = 0, sumActivations = 0;#if DEFTEMPLATE_CONSTRUCT long int maxFacts = 0, sumFacts = 0;#endif#if OBJECT_SYSTEM long int maxInstances = 0, sumInstances = 0;#endif double endTime, startTime = 0.0; long int tempValue;#endif unsigned int i; static int alreadyRunning = CLIPS_FALSE; struct patternEntity *theMatchingItem; struct partialMatch *theBasis; ACTIVATION *theActivation; char *ruleFiring; /*=====================================================*/ /* Make sure the run command is not already executing. */ /*=====================================================*/ if (alreadyRunning) return(0); alreadyRunning = CLIPS_TRUE; /*================================*/ /* Set up statistics information. */ /*================================*/#if DEBUGGING_FUNCTIONS if (WatchStatistics) {#if DEFTEMPLATE_CONSTRUCT maxFacts = GetNumberOfFacts(); sumFacts = maxFacts;#endif#if OBJECT_SYSTEM maxInstances = GetGlobalNumberOfInstances(); sumInstances = maxInstances;#endif maxActivations = GetNumberOfActivations(); sumActivations = maxActivations; startTime = gentime(); }#endif /*=============================*/ /* Set up execution variables. */ /*=============================*/ if (CurrentEvaluationDepth == 0) SetHaltExecution(CLIPS_FALSE); HaltRules = CLIPS_FALSE; /*=====================================================*/ /* Fire rules until the agenda is empty, the run limit */ /* has been reached, or a rule execution error occurs. */ /*=====================================================*/ theActivation = NextActivationToFire(); while ((theActivation != NULL) && (runLimit != 0) && (HaltExecution == CLIPS_FALSE) && (HaltRules == CLIPS_FALSE)) { /*===========================================*/ /* Detach the activation from the agenda and */ /* determine which rule is firing. */ /*===========================================*/ DetachActivation(theActivation); ruleFiring = GetActivationName(theActivation); theBasis = (struct partialMatch *) GetActivationBasis(theActivation); ExecutingRule = (struct defrule *) GetActivationRule(theActivation); /*=============================================*/ /* Update the number of rules that have fired. */ /*=============================================*/ rulesFired++; if (runLimit > 0) { runLimit--; } /*==================================*/ /* If rules are being watched, then */ /* print an information message. */ /*==================================*/ #if DEBUGGING_FUNCTIONS if (ExecutingRule->watchFiring) { char printSpace[60]; sprintf(printSpace,"FIRE %4ld ",rulesFired); PrintCLIPS(WTRACE,printSpace); PrintCLIPS(WTRACE,ruleFiring); PrintCLIPS(WTRACE,": "); PrintPartialMatch(WTRACE,theBasis); PrintCLIPS(WTRACE,"\n"); }#endif /*=================================================*/ /* Remove the link between the activation and the */ /* completed match for the rule. Set the busy flag */ /* for the completed match to TRUE (so the match */ /* upon which our RHS variables are dependent is */ /* not deleted while our rule is firing). Set up */ /* the global pointers to the completed match for */ /* routines which do variable extractions. */ /*=================================================*/ theBasis->binds[theBasis->bcount].gm.theValue = NULL; theBasis->busy = CLIPS_TRUE; GlobalLHSBinds = theBasis; GlobalRHSBinds = NULL; /*===================================================================*/ /* Increment the count for each of the facts/objects associated with */ /* the rule activation so that the facts/objects cannot be deleted */ /* by garbage collection while the rule is executing. */ /*===================================================================*/ for (i = 0; i < theBasis->bcount; i++) { theMatchingItem = theBasis->binds[i].gm.theMatch->matchingItem; if (theMatchingItem != NULL) { (*theMatchingItem->theInfo->incrementBasisCount)(theMatchingItem); } } /*====================================================*/ /* Execute the rule's right hand side actions. If the */ /* rule has logical CEs, set up the pointer to the */ /* rules logical join so the assert command will */ /* attach the appropriate dependencies to the facts. */ /*====================================================*/#if LOGICAL_DEPENDENCIES TheLogicalJoin = ExecutingRule->logicalJoin;#endif CurrentEvaluationDepth++; SetEvaluationError(CLIPS_FALSE); ExecutingRule->executing = CLIPS_TRUE; EvaluateProcActions(ExecutingRule->header.whichModule->theModule, ExecutingRule->actions,ExecutingRule->localVarCnt, &result,NULL); ExecutingRule->executing = CLIPS_FALSE; SetEvaluationError(CLIPS_FALSE); CurrentEvaluationDepth--;#if LOGICAL_DEPENDENCIES TheLogicalJoin = NULL;#endif /*=====================================================*/ /* If rule execution was halted, then print a message. */ /*=====================================================*/ #if DEBUGGING_FUNCTIONS if ((HaltExecution) || (HaltRules && ExecutingRule->watchFiring))#else if ((HaltExecution) || (HaltRules))#endif { PrintErrorID("PRCCODE",4,CLIPS_FALSE); PrintCLIPS(WERROR,"Execution halted during the actions of defrule "); PrintCLIPS(WERROR,ruleFiring); PrintCLIPS(WERROR,".\n"); } /*===================================================================*/ /* Decrement the count for each of the facts/objects associated with */ /* the rule activation. If the last match for the activation */ /* is from a not CE, then we need to make sure that the last */ /* match is an actual match for the CE and not a counter. */ /*===================================================================*/ theBasis->busy = CLIPS_FALSE; for (i = 0; i < (theBasis->bcount - 1); i++) { theMatchingItem = theBasis->binds[i].gm.theMatch->matchingItem; if (theMatchingItem != NULL) { (*theMatchingItem->theInfo->decrementBasisCount)(theMatchingItem); } } i = theBasis->bcount - 1; if (theBasis->counterf == CLIPS_FALSE) { theMatchingItem = theBasis->binds[i].gm.theMatch->matchingItem; if (theMatchingItem != NULL) { (*theMatchingItem->theInfo->decrementBasisCount)(theMatchingItem); } } /*========================================*/ /* Return the agenda node to free memory. */ /*========================================*/ RemoveActivation(theActivation,CLIPS_FALSE,CLIPS_FALSE); /*======================================*/ /* Get rid of partial matches discarded */ /* while executing the rule's RHS. */ /*======================================*/ FlushGarbagePartialMatches(); /*==================================*/ /* Get rid of other garbage created */ /* while executing the rule's RHS. */ /*==================================*/ PeriodicCleanup(CLIPS_FALSE,CLIPS_TRUE); /*==========================*/ /* Keep up with statistics. */ /*==========================*/ #if DEBUGGING_FUNCTIONS if (WatchStatistics) {#if DEFTEMPLATE_CONSTRUCT tempValue = GetNumberOfFacts(); if (tempValue > maxFacts) maxFacts = tempValue; sumFacts += tempValue;#endif#if OBJECT_SYSTEM tempValue = GetGlobalNumberOfInstances(); if (tempValue > maxInstances) maxInstances = tempValue; sumInstances += tempValue;#endif tempValue = GetNumberOfActivations(); if (tempValue > maxActivations) maxActivations = tempValue; sumActivations += tempValue; }#endif /*==================================*/ /* Update saliences if appropriate. */ /*==================================*/#if DYNAMIC_SALIENCE if (GetSalienceEvaluation() == EVERY_CYCLE) RefreshAgenda(NULL);#endif /*========================================*/ /* Execute the list of functions that are */ /* to be called after each rule firing. */ /*========================================*/ for (theRunFunction = ListOfRunFunctions; theRunFunction != NULL; theRunFunction = theRunFunction->next) { (*theRunFunction->func)(); } /*========================================*/ /* If a return was issued on the RHS of a */ /* rule, then remove *that* rule's module */ /* from the focus stack */ /*========================================*/ if (ReturnFlag == CLIPS_TRUE) { RemoveFocus(ExecutingRule->header.whichModule->theModule); } ReturnFlag = CLIPS_FALSE; /*========================================*/ /* Determine the next activation to fire. */ /*========================================*/ theActivation = (struct activation *) NextActivationToFire(); /*==============================*/ /* Check for a rule breakpoint. */ /*==============================*/ if (theActivation != NULL) { if (((struct defrule *) GetActivationRule(theActivation))->afterBreakpoint) { HaltRules = CLIPS_TRUE; PrintCLIPS(WDIALOG,"Breaking on rule "); PrintCLIPS(WDIALOG,GetActivationName(theActivation)); PrintCLIPS(WDIALOG,".\n"); } } } /*======================================================*/ /* If rule execution was halted because the rule firing */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -