📄 engine.c
字号:
theRunFunction != NULL;
theRunFunction = theRunFunction->next)
{
if (theRunFunction->environmentAware)
{ (*theRunFunction->func)(theEnv); }
else
{ ((void (*)(void))(*theRunFunction->func))(); }
}
}
/*======================================================*/
/* 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
sprintf(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
sprintf(printSpace,"%ld mean number of instances (%ld maximum).\n",
(long) (((double) sumInstances / (rulesFired + 1)) + 0.5),
maxInstances);
EnvPrintRouter(theEnv,WDIALOG,printSpace);
#endif
sprintf(printSpace,"%ld mean number of activations (%ld maximum).\n",
(long) (((double) sumActivations / (rulesFired + 1)) + 0.5),
maxActivations);
EnvPrintRouter(theEnv,WDIALOG,printSpace);
}
#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 int runLimit = -1;
DATA_OBJECT argPtr;
if ((numArgs = EnvArgCountCheck(theEnv,"run",NO_MORE_THAN,1)) == -1) return;
if (numArgs == 0)
{ runLimit = -1; }
else if (numArgs == 1)
{
if (EnvArgTypeCheck(theEnv,"run",1,INTEGER,&argPtr) == FALSE) return;
runLimit = DOToLong(argPtr);
}
EnvRun(theEnv,runLimit);
return;
}
/***********************************************/
/* HaltCommand: Causes rule execution to halt. */
/***********************************************/
globle void HaltCommand(
void *theEnv)
{
EnvArgCountCheck(theEnv,"halt",EXACTLY,0);
EngineData(theEnv)->HaltRules = TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -