📄 factqpsr.c
字号:
DESCRIPTION : In parsing an fact-set query,
this function replaces a constant
template name with an actual pointer
to the template
INPUTS : The expression
RETURNS : TRUE if all OK, FALSE
if template cannot be found
SIDE EFFECTS : The expression type and value are
modified if template is found
NOTES : Searches current and imported
modules for reference
***************************************************/
static intBool ReplaceTemplateNameWithReference(
void *theEnv,
EXPRESSION *theExp)
{
char *theTemplateName;
void *theDeftemplate;
int count;
if (theExp->type == SYMBOL)
{
theTemplateName = ValueToString(theExp->value);
theDeftemplate = (struct deftemplate *)
FindImportedConstruct(theEnv,"deftemplate",NULL,theTemplateName,
&count,TRUE,NULL);
if (theDeftemplate == NULL)
{ /* TBD */
CantFindItemErrorMessage(theEnv,"deftemplate",theTemplateName);
return(FALSE);
}
if (count > 1)
{
AmbiguousReferenceErrorMessage(theEnv,"deftemplate",theTemplateName);
return(FALSE);
}
theExp->type = DEFTEMPLATE_PTR;
theExp->value = theDeftemplate;
}
return(TRUE);
}
/*************************************************************
NAME : ParseQueryTestExpression
DESCRIPTION : Parses the test-expression for a query
INPUTS : 1) The top node of the query expression
2) The logical name of the input
RETURNS : TRUE if all OK, FALSE otherwise
SIDE EFFECTS : Entire query-expression deleted on errors
Nodes allocated for new expression
Test shoved in front of class-restrictions on
query argument list
NOTES : Expects top != NULL
*************************************************************/
static int ParseQueryTestExpression(
void *theEnv,
EXPRESSION *top,
char *readSource)
{
EXPRESSION *qtest;
int error;
struct BindInfo *oldBindList;
error = FALSE;
oldBindList = GetParsedBindNames(theEnv);
SetParsedBindNames(theEnv,NULL);
qtest = ArgumentParse(theEnv,readSource,&error);
if (error == TRUE)
{
SetParsedBindNames(theEnv,oldBindList);
ReturnExpression(theEnv,top);
return(FALSE);
}
if (qtest == NULL)
{
SetParsedBindNames(theEnv,oldBindList);
SyntaxErrorMessage(theEnv,"fact-set query function");
ReturnExpression(theEnv,top);
return(FALSE);
}
qtest->nextArg = top->argList;
top->argList = qtest;
if (ParsedBindNamesEmpty(theEnv) == FALSE)
{
ClearParsedBindNames(theEnv);
SetParsedBindNames(theEnv,oldBindList);
PrintErrorID(theEnv,"FACTQPSR",2,FALSE);
EnvPrintRouter(theEnv,WERROR,"Binds are not allowed in fact-set query in function ");
EnvPrintRouter(theEnv,WERROR,ValueToString(ExpressionFunctionCallName(top)));
EnvPrintRouter(theEnv,WERROR,".\n");
ReturnExpression(theEnv,top);
return(FALSE);
}
SetParsedBindNames(theEnv,oldBindList);
return(TRUE);
}
/*************************************************************
NAME : ParseQueryActionExpression
DESCRIPTION : Parses the action-expression for a query
INPUTS : 1) The top node of the query expression
2) The logical name of the input
3) List of query parameters
RETURNS : TRUE if all OK, FALSE otherwise
SIDE EFFECTS : Entire query-expression deleted on errors
Nodes allocated for new expression
Action shoved in front of template-restrictions
and in back of test-expression on query
argument list
NOTES : Expects top != NULL && top->argList != NULL
*************************************************************/
static int ParseQueryActionExpression(
void *theEnv,
EXPRESSION *top,
char *readSource,
EXPRESSION *factQuerySetVars,
struct token *queryInputToken)
{
EXPRESSION *qaction,*tmpFactSetVars;
int error;
struct BindInfo *oldBindList,*newBindList,*prev;
error = FALSE;
oldBindList = GetParsedBindNames(theEnv);
SetParsedBindNames(theEnv,NULL);
ExpressionData(theEnv)->BreakContext = TRUE;
ExpressionData(theEnv)->ReturnContext = ExpressionData(theEnv)->svContexts->rtn;
qaction = GroupActions(theEnv,readSource,queryInputToken,TRUE,NULL,FALSE);
PPBackup(theEnv);
PPBackup(theEnv);
SavePPBuffer(theEnv,queryInputToken->printForm);
ExpressionData(theEnv)->BreakContext = FALSE;
if (error == TRUE)
{
SetParsedBindNames(theEnv,oldBindList);
ReturnExpression(theEnv,top);
return(FALSE);
}
if (qaction == NULL)
{
SetParsedBindNames(theEnv,oldBindList);
SyntaxErrorMessage(theEnv,"fact-set query function");
ReturnExpression(theEnv,top);
return(FALSE);
}
qaction->nextArg = top->argList->nextArg;
top->argList->nextArg = qaction;
newBindList = GetParsedBindNames(theEnv);
prev = NULL;
while (newBindList != NULL)
{
tmpFactSetVars = factQuerySetVars;
while (tmpFactSetVars != NULL)
{
if (tmpFactSetVars->value == (void *) newBindList->name)
{
ClearParsedBindNames(theEnv);
SetParsedBindNames(theEnv,oldBindList);
PrintErrorID(theEnv,"FACTQPSR",3,FALSE);
EnvPrintRouter(theEnv,WERROR,"Cannot rebind fact-set member variable ");
EnvPrintRouter(theEnv,WERROR,ValueToString(tmpFactSetVars->value));
EnvPrintRouter(theEnv,WERROR," in function ");
EnvPrintRouter(theEnv,WERROR,ValueToString(ExpressionFunctionCallName(top)));
EnvPrintRouter(theEnv,WERROR,".\n");
ReturnExpression(theEnv,top);
return(FALSE);
}
tmpFactSetVars = tmpFactSetVars->nextArg;
}
prev = newBindList;
newBindList = newBindList->next;
}
if (prev == NULL)
{ SetParsedBindNames(theEnv,oldBindList); }
else
{ prev->next = oldBindList; }
return(TRUE);
}
/***********************************************************************************
NAME : ReplaceFactVariables
DESCRIPTION : Replaces all references to fact-variables within an
fact query-function with function calls to query-fact
(which references the fact array at run-time)
INPUTS : 1) The fact-variable list
2) A boolean expression containing variable references
3) A flag indicating whether to allow slot references of the type
<fact-query-variable>:<slot-name> for direct slot access
or not
4) Nesting depth of query functions
RETURNS : Nothing useful
SIDE EFFECTS : If a SF_VARIABLE node is found and is on the list of fact
variables, it is replaced with a query-fact function call.
NOTES : Other SF_VARIABLE(S) are left alone for replacement by other
parsers. This implies that a user may use defgeneric,
defrule, and defmessage-handler variables within a query-function
where they do not conflict with fact-variable names.
***********************************************************************************/
static void ReplaceFactVariables(
void *theEnv,
EXPRESSION *vlist,
EXPRESSION *bexp,
int sdirect,
int ndepth)
{
EXPRESSION *eptr;
struct FunctionDefinition *rindx_func,*rslot_func;
int posn;
rindx_func = FindFunction(theEnv,"(query-fact)");
rslot_func = FindFunction(theEnv,"(query-fact-slot)");
while (bexp != NULL)
{
if (bexp->type == SF_VARIABLE)
{
eptr = vlist;
posn = 0;
while ((eptr != NULL) ? (eptr->value != bexp->value) : FALSE)
{
eptr = eptr->nextArg;
posn++;
}
if (eptr != NULL)
{
bexp->type = FCALL;
bexp->value = (void *) rindx_func;
eptr = GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) ndepth));
eptr->nextArg = GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) posn));
bexp->argList = eptr;
}
else if (sdirect == TRUE)
{ ReplaceSlotReference(theEnv,vlist,bexp,rslot_func,ndepth); }
}
if (bexp->argList != NULL)
{
if (IsQueryFunction(bexp))
{ ReplaceFactVariables(theEnv,vlist,bexp->argList,sdirect,ndepth+1); }
else
{ ReplaceFactVariables(theEnv,vlist,bexp->argList,sdirect,ndepth); }
}
bexp = bexp->nextArg;
}
}
/*************************************************************************
NAME : ReplaceSlotReference
DESCRIPTION : Replaces fact-set query function variable
references of the form: <fact-variable>:<slot-name>
with function calls to get these fact-slots at run
time
INPUTS : 1) The fact-set variable list
2) The expression containing the variable
3) The address of the fact slot access function
4) Nesting depth of query functions
RETURNS : Nothing useful
SIDE EFFECTS : If the variable is a slot reference, then it is replaced
with the appropriate function-call.
NOTES : None
*************************************************************************/
static void ReplaceSlotReference(
void *theEnv,
EXPRESSION *vlist,
EXPRESSION *theExp,
struct FunctionDefinition *func,
int ndepth)
{
unsigned len;
int posn,oldpp;
register unsigned i;
register char *str;
EXPRESSION *eptr;
struct token itkn;
str = ValueToString(theExp->value);
len = strlen(str);
if (len < 3)
return;
for (i = len-2 ; i >= 1 ; i--)
{
if ((str[i] == FACT_SLOT_REF) ? (i >= 1) : FALSE)
{
eptr = vlist;
posn = 0;
while (eptr && ((i != strlen(ValueToString(eptr->value))) ||
strncmp(ValueToString(eptr->value),str,
(STD_SIZE) i)))
{
eptr = eptr->nextArg;
posn++;
}
if (eptr != NULL)
{
OpenStringSource(theEnv,"query-var",str+i+1,0);
oldpp = GetPPBufferStatus(theEnv);
SetPPBufferStatus(theEnv,OFF);
GetToken(theEnv,"query-var",&itkn);
SetPPBufferStatus(theEnv,oldpp);
CloseStringSource(theEnv,"query-var");
theExp->type = FCALL;
theExp->value = (void *) func;
theExp->argList = GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) ndepth));
theExp->argList->nextArg =
GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) posn));
theExp->argList->nextArg->nextArg = GenConstant(theEnv,itkn.type,itkn.value);
break;
}
}
}
}
/********************************************************************
NAME : IsQueryFunction
DESCRIPTION : Determines if an expression is a query function call
INPUTS : The expression
RETURNS : TRUE if query function call, FALSE otherwise
SIDE EFFECTS : None
NOTES : None
********************************************************************/
static int IsQueryFunction(
EXPRESSION *theExp)
{
int (*fptr)(void);
if (theExp->type != FCALL)
return(FALSE);
fptr = (int (*)(void)) ExpressionFunctionPointer(theExp);
if (fptr == (int (*)(void)) AnyFacts)
return(TRUE);
if (fptr == (int (*)(void)) QueryFindFact)
return(TRUE);
if (fptr == (int (*)(void)) QueryFindAllFacts)
return(TRUE);
if (fptr == (int (*)(void)) QueryDoForFact)
return(TRUE);
if (fptr == (int (*)(void)) QueryDoForAllFacts)
return(TRUE);
if (fptr == (int (*)(void)) DelayedQueryDoForAllFacts)
return(TRUE);
return(FALSE);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -