📄 engine.c
字号:
/*======================================================*/ /* If rule execution was halted because the rule firing */ /* limit was reached, then print a message. */ /*======================================================*/ if (runLimit == rulesFired) { EnvPrintRouter(theEnv,WDIALOG,"rule firing limit reached\n"); } /*==============================*/ /* Restore execution variables. */ /*==============================*/ EngineData(theEnv)->ExecutingRule = NULL; EngineData(theEnv)->HaltRules = FALSE; /*=================================================*/ /* Print out statistics if they are being watched. */ /*=================================================*/#if DEBUGGING_FUNCTIONS if (EngineData(theEnv)->WatchStatistics) { char printSpace[60]; endTime = gentime(); PrintLongInteger(theEnv,WDIALOG,rulesFired); EnvPrintRouter(theEnv,WDIALOG," rules fired");#if (! GENERIC) if (startTime != endTime) { EnvPrintRouter(theEnv,WDIALOG," Run time is "); PrintFloat(theEnv,WDIALOG,endTime - startTime); EnvPrintRouter(theEnv,WDIALOG," seconds.\n"); PrintFloat(theEnv,WDIALOG,(double) rulesFired / (endTime - startTime)); EnvPrintRouter(theEnv,WDIALOG," rules per second.\n"); } else { EnvPrintRouter(theEnv,WDIALOG,"\n"); }#endif#if DEFTEMPLATE_CONSTRUCT gensprintf(printSpace,"%ld mean number of facts (%ld maximum).\n", (long) (((double) sumFacts / (rulesFired + 1)) + 0.5), maxFacts); EnvPrintRouter(theEnv,WDIALOG,printSpace);#endif#if OBJECT_SYSTEM gensprintf(printSpace,"%ld mean number of instances (%ld maximum).\n", (long) (((double) sumInstances / (rulesFired + 1)) + 0.5), maxInstances); EnvPrintRouter(theEnv,WDIALOG,printSpace);#endif gensprintf(printSpace,"%ld mean number of activations (%ld maximum).\n", (long) (((double) sumActivations / (rulesFired + 1)) + 0.5), maxActivations); EnvPrintRouter(theEnv,WDIALOG,printSpace); #if DEVELOPER gensprintf(printSpace,"%9ld left to right comparisons.\n", EngineData(theEnv)->leftToRightComparisons); EnvPrintRouter(theEnv,WDIALOG,printSpace); gensprintf(printSpace,"%9ld left to right succeeds.\n", EngineData(theEnv)->leftToRightSucceeds); EnvPrintRouter(theEnv,WDIALOG,printSpace); gensprintf(printSpace,"%9ld left to right loops.\n", EngineData(theEnv)->leftToRightLoops); EnvPrintRouter(theEnv,WDIALOG,printSpace); gensprintf(printSpace,"%9ld right to left comparisons.\n", EngineData(theEnv)->rightToLeftComparisons); EnvPrintRouter(theEnv,WDIALOG,printSpace); gensprintf(printSpace,"%9ld right to left succeeds.\n", EngineData(theEnv)->rightToLeftSucceeds); EnvPrintRouter(theEnv,WDIALOG,printSpace); gensprintf(printSpace,"%9ld right to left loops.\n", EngineData(theEnv)->rightToLeftLoops); EnvPrintRouter(theEnv,WDIALOG,printSpace); gensprintf(printSpace,"%9ld find next conflicting comparisons.\n", EngineData(theEnv)->findNextConflictingComparisons); EnvPrintRouter(theEnv,WDIALOG,printSpace); gensprintf(printSpace,"%9ld beta hash list skips.\n", EngineData(theEnv)->betaHashListSkips); EnvPrintRouter(theEnv,WDIALOG,printSpace); gensprintf(printSpace,"%9ld beta hash hash table skips.\n", EngineData(theEnv)->betaHashHTSkips); EnvPrintRouter(theEnv,WDIALOG,printSpace); gensprintf(printSpace,"%9ld unneeded marker compare.\n", EngineData(theEnv)->unneededMarkerCompare); EnvPrintRouter(theEnv,WDIALOG,printSpace);#endif }#endif /*==========================================*/ /* The current module should be the current */ /* focus when the run finishes. */ /*==========================================*/ if (EngineData(theEnv)->CurrentFocus != NULL) { if (EngineData(theEnv)->CurrentFocus->theModule != ((struct defmodule *) EnvGetCurrentModule(theEnv))) { EnvSetCurrentModule(theEnv,(void *) EngineData(theEnv)->CurrentFocus->theModule); } } /*===================================*/ /* Return the number of rules fired. */ /*===================================*/ EngineData(theEnv)->AlreadyRunning = FALSE; return(rulesFired); }/***********************************************************//* NextActivationToFire: Returns the next activation which *//* should be executed based on the current focus. *//***********************************************************/static struct activation *NextActivationToFire( void *theEnv) { struct activation *theActivation; struct defmodule *theModule; /*====================================*/ /* If there is no current focus, then */ /* focus on the MAIN module. */ /*====================================*/ if (EngineData(theEnv)->CurrentFocus == NULL) { theModule = (struct defmodule *) EnvFindDefmodule(theEnv,"MAIN"); EnvFocus(theEnv,theModule); } /*===========================================================*/ /* Determine the top activation on the agenda of the current */ /* focus. If the current focus has no activations on its */ /* agenda, then pop the focus off the focus stack until */ /* a focus that has an activation on its agenda is found. */ /*===========================================================*/ theActivation = EngineData(theEnv)->CurrentFocus->theDefruleModule->agenda; while ((theActivation == NULL) && (EngineData(theEnv)->CurrentFocus != NULL)) { if (EngineData(theEnv)->CurrentFocus != NULL) EnvPopFocus(theEnv); if (EngineData(theEnv)->CurrentFocus != NULL) theActivation = EngineData(theEnv)->CurrentFocus->theDefruleModule->agenda; } /*=========================================*/ /* Return the next activation to be fired. */ /*=========================================*/ return(theActivation); }/***************************************************//* RemoveFocus: Removes the first occurence of the *//* specified module from the focus stack. *//***************************************************/static struct defmodule *RemoveFocus( void *theEnv, struct defmodule *theModule) { struct focus *tempFocus,*prevFocus, *nextFocus; int found = FALSE; int currentFocusRemoved = FALSE; /*====================================*/ /* Return NULL if there is nothing on */ /* the focus stack to remove. */ /*====================================*/ if (EngineData(theEnv)->CurrentFocus == NULL) return(NULL); /*=============================================*/ /* Remove the first occurence of the specified */ /* module from the focus stack. */ /*=============================================*/ prevFocus = NULL; tempFocus = EngineData(theEnv)->CurrentFocus; while ((tempFocus != NULL) && (! found)) { if (tempFocus->theModule == theModule) { found = TRUE; nextFocus = tempFocus->next; rtn_struct(theEnv,focus,tempFocus); tempFocus = nextFocus; if (prevFocus == NULL) { currentFocusRemoved = TRUE; EngineData(theEnv)->CurrentFocus = tempFocus; } else { prevFocus->next = tempFocus; } } else { prevFocus = tempFocus; tempFocus = tempFocus->next; } } /*=========================================*/ /* If the given module is not in the focus */ /* stack, simply return the current focus */ /*=========================================*/ if (! found) return(EngineData(theEnv)->CurrentFocus->theModule); /*========================================*/ /* If the current focus is being watched, */ /* then print an informational message. */ /*========================================*/#if DEBUGGING_FUNCTIONS if (EngineData(theEnv)->WatchFocus) { EnvPrintRouter(theEnv,WTRACE,"<== Focus "); EnvPrintRouter(theEnv,WTRACE,ValueToString(theModule->name)); if ((EngineData(theEnv)->CurrentFocus != NULL) && currentFocusRemoved) { EnvPrintRouter(theEnv,WTRACE," to "); EnvPrintRouter(theEnv,WTRACE,ValueToString(EngineData(theEnv)->CurrentFocus->theModule->name)); } EnvPrintRouter(theEnv,WTRACE,"\n"); }#endif /*======================================================*/ /* Set the current module to the module associated with */ /* the current focus (if it changed) and set a boolean */ /* flag indicating that the focus has changed. */ /*======================================================*/ if ((EngineData(theEnv)->CurrentFocus != NULL) && currentFocusRemoved) { EnvSetCurrentModule(theEnv,(void *) EngineData(theEnv)->CurrentFocus->theModule); } EngineData(theEnv)->FocusChanged = TRUE; /*====================================*/ /* Return the module that was removed */ /* from the focus stack. */ /*====================================*/ return(theModule); }/*************************************************************//* EnvPopFocus: C access routine for the pop-focus function. *//*************************************************************/globle void *EnvPopFocus( void *theEnv) { if (EngineData(theEnv)->CurrentFocus == NULL) return(NULL); return((void *) RemoveFocus(theEnv,EngineData(theEnv)->CurrentFocus->theModule)); }/***************************************************************//* EnvGetNextFocus: Returns the next focus on the focus stack. *//***************************************************************/globle void *EnvGetNextFocus( void *theEnv, void *theFocus) { /*==================================================*/ /* If NULL is passed as an argument, return the top */ /* focus on the focus stack (the current focus). */ /*==================================================*/ if (theFocus == NULL) return((void *) EngineData(theEnv)->CurrentFocus); /*=======================================*/ /* Otherwise, return the focus following */ /* the focus passed as an argument. */ /*=======================================*/ return((void *) ((struct focus *) theFocus)->next); }/******************************************************//* EnvFocus: C access routine for the focus function. *//******************************************************/globle void EnvFocus( void *theEnv, void *vTheModule) { struct defmodule *theModule = (struct defmodule *) vTheModule; struct focus *tempFocus; /*==================================================*/ /* Make the specified module be the current module. */ /* If the specified module is the current focus, */ /* then no further action is needed. */ /*==================================================*/ EnvSetCurrentModule(theEnv,(void *) theModule); if (EngineData(theEnv)->CurrentFocus != NULL) { if (EngineData(theEnv)->CurrentFocus->theModule == theModule) return; } /*=====================================*/ /* If the focus is being watched, then */ /* print an information message. */ /*=====================================*/#if DEBUGGING_FUNCTIONS if (EngineData(theEnv)->WatchFocus) { EnvPrintRouter(theEnv,WTRACE,"==> Focus "); EnvPrintRouter(theEnv,WTRACE,ValueToString(theModule->name)); if (EngineData(theEnv)->CurrentFocus != NULL) { EnvPrintRouter(theEnv,WTRACE," from "); EnvPrintRouter(theEnv,WTRACE,ValueToString(EngineData(theEnv)->CurrentFocus->theModule->name)); } EnvPrintRouter(theEnv,WTRACE,"\n"); }#endif /*=======================================*/ /* Add the new focus to the focus stack. */ /*=======================================*/ tempFocus = get_struct(theEnv,focus); tempFocus->theModule = theModule; tempFocus->theDefruleModule = GetDefruleModuleItem(theEnv,theModule); tempFocus->next = EngineData(theEnv)->CurrentFocus; EngineData(theEnv)->CurrentFocus = tempFocus; EngineData(theEnv)->FocusChanged = TRUE; }/************************************************//* ClearFocusStackCommand: H/L access routine *//* for the clear-focus-stack command. *//************************************************/globle void ClearFocusStackCommand( void *theEnv) { if (EnvArgCountCheck(theEnv,"list-focus-stack",EXACTLY,0) == -1) return; EnvClearFocusStack(theEnv); }/****************************************//* EnvClearFocusStack: C access routine *//* for the clear-focus-stack command. *//****************************************/globle void EnvClearFocusStack( void *theEnv) { while (EngineData(theEnv)->CurrentFocus != NULL) EnvPopFocus(theEnv); EngineData(theEnv)->FocusChanged = TRUE; }#if (! ENVIRONMENT_API_ONLY) && ALLOW_ENVIRONMENT_GLOBALS/***********************************//* AddRunFunction: Adds a function *//* to the ListOfRunFunctions. *//***********************************/globle intBool AddRunFunction( char *name, void (*functionPtr)(void), int priority) { void *theEnv; theEnv = GetCurrentEnvironment(); EngineData(theEnv)->ListOfRunFunctions = AddFunctionToCallList(theEnv,name,priority,(void (*)(void *)) functionPtr, EngineData(theEnv)->ListOfRunFunctions,TRUE); return(1); }#endif/**************************************//* EnvAddRunFunction: Adds a function *//* to the ListOfRunFunctions. *//**************************************/globle intBool EnvAddRunFunction( void *theEnv, char *name, void (*functionPtr)(void *), int priority) { EngineData(theEnv)->ListOfRunFunctions = AddFunctionToCallList(theEnv,name,priority, functionPtr, EngineData(theEnv)->ListOfRunFunctions,TRUE); return(1); }/********************************************//* EnvRemoveRunFunction: Removes a function *//* from the ListOfRunFunctions. *//********************************************/globle intBool EnvRemoveRunFunction( void *theEnv, char *name) { int found; EngineData(theEnv)->ListOfRunFunctions = RemoveFunctionFromCallList(theEnv,name,EngineData(theEnv)->ListOfRunFunctions,&found); if (found) return(TRUE); return(FALSE); }/*********************************************************//* RunCommand: H/L access routine for the run command. *//*********************************************************/globle void RunCommand( void *theEnv) { int numArgs; long long runLimit = -1LL; DATA_OBJECT argPtr; if ((numArgs = EnvArgCountCheck(theEnv,"run",NO_MORE_THAN,1)) == -1) return; if (numArgs == 0) { runLimit = -1LL; } else if (numArgs == 1) { if (EnvArgTypeCheck(theEnv,"run",1,INTEGER,&argPtr) == FALSE) return; runLimit = DOToLong(argPtr); } EnvRun(theEnv,runLimit); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -