📄 factmch.c
字号:
return(rv);
/*================================================*/
/* This primitive determines if a multifield slot */
/* contains at least a certain number of fields. */
/*================================================*/
case FACT_SLOT_LENGTH:
oldArgument = EvaluationData(theEnv)->CurrentExpression;
EvaluationData(theEnv)->CurrentExpression = theTest;
rv = FactSlotLength(theEnv,theTest->value,&theResult);
EvaluationData(theEnv)->CurrentExpression = oldArgument;
return(rv);
}
/*==============================================*/
/* Evaluate "or" expressions by evaluating each */
/* argument and return TRUE if any of them */
/* evaluated to TRUE, otherwise return FALSE. */
/*==============================================*/
if (theTest->value == ExpressionData(theEnv)->PTR_OR)
{
for (theTest = theTest->argList;
theTest != NULL;
theTest = theTest->nextArg)
{
if (EvaluatePatternExpression(theEnv,patternPtr,theTest,thePosition) == TRUE)
{
if (EvaluationData(theEnv)->EvaluationError) return(FALSE);
return(TRUE);
}
if (EvaluationData(theEnv)->EvaluationError) return(FALSE);
}
return(FALSE);
}
/*===============================================*/
/* Evaluate "and" expressions by evaluating each */
/* argument and return FALSE if any of them */
/* evaluated to FALSE, otherwise return TRUE. */
/*===============================================*/
else if (theTest->value == ExpressionData(theEnv)->PTR_AND)
{
for (theTest = theTest->argList;
theTest != NULL;
theTest = theTest->nextArg)
{
if (EvaluatePatternExpression(theEnv,patternPtr,theTest,thePosition) == FALSE)
{ return(FALSE); }
if (EvaluationData(theEnv)->EvaluationError) return(FALSE);
}
return(TRUE);
}
/*==========================================================*/
/* Evaluate all other expressions using EvaluateExpression. */
/*==========================================================*/
if (EvaluateExpression(theEnv,theTest,&theResult))
{
PatternNetErrorMessage(theEnv,patternPtr);
return(FALSE);
}
if ((theResult.value == EnvFalseSymbol(theEnv)) && (theResult.type == SYMBOL))
{ return(FALSE); }
return(TRUE);
}
/************************************************************************/
/* PatternNetErrorMessage: Prints the informational header to the error */
/* message that occurs when a error occurs as the result of */
/* evaluating an expression in the fact pattern network. Prints the */
/* fact currently being pattern matched and the field number or slot */
/* name in the pattern from which the error originated. The error is */
/* then trace to the point where the pattern enters the join network */
/* so that the names of the rule which utilize the pattern can also */
/* be printed. */
/************************************************************************/
static void PatternNetErrorMessage(
void *theEnv,
struct factPatternNode *patternPtr)
{
char buffer[60];
struct templateSlot *theSlots;
int i;
/*=======================================*/
/* Print the fact being pattern matched. */
/*=======================================*/
PrintErrorID(theEnv,"FACTMCH",1,TRUE);
EnvPrintRouter(theEnv,WERROR,"This error occurred in the fact pattern network\n");
EnvPrintRouter(theEnv,WERROR," Currently active fact: ");
PrintFact(theEnv,WERROR,FactData(theEnv)->CurrentPatternFact,FALSE,FALSE);
EnvPrintRouter(theEnv,WERROR,"\n");
/*==============================================*/
/* Print the field position or slot name of the */
/* pattern from which the error originated. */
/*==============================================*/
if (FactData(theEnv)->CurrentPatternFact->whichDeftemplate->implied)
{ sprintf(buffer," Problem resides in field #%d\n",patternPtr->whichField); }
else
{
theSlots = FactData(theEnv)->CurrentPatternFact->whichDeftemplate->slotList;
for (i = 0; i < (int) patternPtr->whichSlot; i++) theSlots = theSlots->next;
sprintf(buffer," Problem resides in slot %s\n",ValueToString(theSlots->slotName));
}
EnvPrintRouter(theEnv,WERROR,buffer);
/*==========================================================*/
/* Trace the pattern to its entry point to the join network */
/* (which then traces to the defrule data structure so that */
/* the name(s) of the rule(s) utilizing the patterns can be */
/* printed). */
/*==========================================================*/
TraceErrorToJoin(theEnv,patternPtr,FALSE);
EnvPrintRouter(theEnv,WERROR,"\n");
}
/***************************************************************************/
/* TraceErrorToJoin: Traces the cause of an evaluation error which occured */
/* in the fact pattern network to the entry join in the join network for */
/* the pattern from which the error originated. Once the entry join is */
/* reached, the error is then traced to the defrule data structures so */
/* that the name of the rule(s) containing the pattern can be printed. */
/***************************************************************************/
static void TraceErrorToJoin(
void *theEnv,
struct factPatternNode *patternPtr,
int traceRight)
{
struct joinNode *joinPtr;
char buffer[60];
while (patternPtr != NULL)
{
if (patternPtr->header.stopNode)
{
for (joinPtr = patternPtr->header.entryJoin;
joinPtr != NULL;
joinPtr = joinPtr->rightMatchNode)
{
sprintf(buffer," Of pattern #%d in rule(s):\n",GetPatternNumberFromJoin(joinPtr));
EnvPrintRouter(theEnv,WERROR,buffer);
TraceErrorToRule(theEnv,joinPtr," ");
}
}
else
{ TraceErrorToJoin(theEnv,patternPtr->nextLevel,TRUE); }
if (traceRight) patternPtr = patternPtr->rightNode;
else patternPtr = NULL;
}
}
/***********************************************************************/
/* SkipFactPatternNode: During an incremental reset, only fact pattern */
/* nodes associated with new patterns are traversed. Given a pattern */
/* node, this routine will return TRUE if the pattern node should be */
/* traversed during incremental reset pattern matching or FALSE if */
/* the node should be skipped. */
/***********************************************************************/
static int SkipFactPatternNode(
void *theEnv,
struct factPatternNode *thePattern)
{
#if (MAC_MCW || IBM_MCW) && (RUN_TIME || BLOAD_ONLY)
#pragma unused(theEnv,thePattern)
#endif
#if (! RUN_TIME) && (! BLOAD_ONLY)
if (EngineData(theEnv)->IncrementalResetInProgress &&
(thePattern->header.initialize == FALSE))
{ return(TRUE); }
#endif
return(FALSE);
}
/***************************************************************/
/* MarkFactPatternForIncrementalReset: Sets the initialization */
/* field of a fact pattern for use with incremental reset. */
/* This is called before an incremental reset for newly added */
/* patterns to indicate that the pattern nodes should be */
/* traversed and then after an incremental reset to indicate */
/* that the nodes were traversed ("initialized") by the */
/* incremental reset. */
/***************************************************************/
#if IBM_TBC
#pragma argsused
#endif
globle void MarkFactPatternForIncrementalReset(
void *theEnv,
struct patternNodeHeader *thePattern,
int value)
{
struct factPatternNode *patternPtr = (struct factPatternNode *) thePattern;
#if MAC_MCW || IBM_MCW || MAC_XCD
#pragma unused(theEnv)
#endif
/*=====================================*/
/* We should be passed a valid pointer */
/* to a fact pattern network node. */
/*=====================================*/
Bogus(patternPtr == NULL);
/*============================================*/
/* If the pattern was previously initialized, */
/* then don't bother with it. */
/*============================================*/
if (patternPtr->header.initialize == FALSE) return;
/*======================================================*/
/* Set the initialization field of this pattern network */
/* node and all pattern network nodes which preceed it. */
/*======================================================*/
while (patternPtr != NULL)
{
patternPtr->header.initialize = value;
patternPtr = patternPtr->lastLevel;
}
}
/**************************************************************/
/* FactsIncrementalReset: Incremental reset function for the */
/* fact pattern network. Asserts all facts in the fact-list */
/* so that they repeat the pattern matching process. During */
/* an incremental reset, newly added patterns should be the */
/* only active patterns in the fact pattern network. */
/**************************************************************/
globle void FactsIncrementalReset(
void *theEnv)
{
struct fact *factPtr;
for (factPtr = (struct fact *) EnvGetNextFact(theEnv,NULL);
factPtr != NULL;
factPtr = (struct fact *) EnvGetNextFact(theEnv,factPtr))
{
FactPatternMatch(theEnv,factPtr,
factPtr->whichDeftemplate->patternNetwork,
0,NULL,NULL);
}
}
#endif /* DEFTEMPLATE_CONSTRUCT && DEFRULE_CONSTRUCT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -