📄 tmpltfun.c
字号:
{
DATA_OBJECT tempDO;
char *deftemplateName;
/*============================================*/
/* Check for the correct number of arguments. */
/*============================================*/
if (EnvArgCountCheck(theEnv,functionName,EXACTLY,2) == -1)
{ return(NULL); }
/*=======================================*/
/* Get the reference to the deftemplate. */
/*=======================================*/
EnvRtnUnknown(theEnv,1,&tempDO);
if (GetType(tempDO) != SYMBOL)
{
ExpectedTypeError1(theEnv,functionName,1,"deftemplate name");
return(NULL);
}
deftemplateName = DOToString(tempDO);
*theDeftemplate = (struct deftemplate *) EnvFindDeftemplate(theEnv,deftemplateName);
if (*theDeftemplate == NULL)
{
CantFindItemErrorMessage(theEnv,"deftemplate",deftemplateName);
return(NULL);
}
/*===========================*/
/* Get the name of the slot. */
/*===========================*/
if (EnvArgTypeCheck(theEnv,functionName,2,SYMBOL,&tempDO) == FALSE)
{ return(NULL); }
return((SYMBOL_HN *) GetValue(tempDO));
}
#if (! RUN_TIME) && (! BLOAD_ONLY)
/***************************************************************/
/* UpdateModifyDuplicate: Changes the modify/duplicate command */
/* found on the RHS of a rule such that the positions of the */
/* slots for replacement are stored rather than the slot */
/* name which allows quicker replacement of slots. This */
/* substitution can only take place when the deftemplate */
/* type is known (i.e. if a fact-index is used you don't */
/* know which type of deftemplate is going to be replaced */
/* until you actually do the replacement of slots). */
/***************************************************************/
globle intBool UpdateModifyDuplicate(
void *theEnv,
struct expr *top,
char *name,
void *vTheLHS)
{
struct expr *functionArgs, *tempArg;
SYMBOL_HN *templateName;
struct deftemplate *theDeftemplate;
struct templateSlot *slotPtr;
short position;
/*========================================*/
/* Determine the fact-address or index to */
/* be retracted by the modify command. */
/*========================================*/
functionArgs = top->argList;
if (functionArgs->type == SF_VARIABLE)
{
templateName = FindTemplateForFactAddress((SYMBOL_HN *) functionArgs->value,
(struct lhsParseNode *) vTheLHS);
if (templateName == NULL) return(TRUE);
}
else
{ return(TRUE); }
/*========================================*/
/* Make sure that the fact being modified */
/* has a corresponding deftemplate. */
/*========================================*/
theDeftemplate = (struct deftemplate *)
LookupConstruct(theEnv,DeftemplateData(theEnv)->DeftemplateConstruct,
ValueToString(templateName),
FALSE);
if (theDeftemplate == NULL) return(TRUE);
if (theDeftemplate->implied) return(TRUE);
/*=============================================================*/
/* Make sure all the slot names are valid for the deftemplate. */
/*=============================================================*/
tempArg = functionArgs->nextArg;
while (tempArg != NULL)
{
/*======================*/
/* Does the slot exist? */
/*======================*/
if ((slotPtr = FindSlot(theDeftemplate,(SYMBOL_HN *) tempArg->value,&position)) == NULL)
{
InvalidDeftemplateSlotMessage(theEnv,ValueToString(tempArg->value),
ValueToString(theDeftemplate->header.name),TRUE);
return(FALSE);
}
/*=========================================================*/
/* Is a multifield value being put in a single field slot? */
/*=========================================================*/
if (slotPtr->multislot == FALSE)
{
if (tempArg->argList == NULL)
{
SingleFieldSlotCardinalityError(theEnv,slotPtr->slotName->contents);
return(FALSE);
}
else if (tempArg->argList->nextArg != NULL)
{
SingleFieldSlotCardinalityError(theEnv,slotPtr->slotName->contents);
return(FALSE);
}
else if ((tempArg->argList->type == MF_VARIABLE) ||
((tempArg->argList->type == FCALL) ?
(((struct FunctionDefinition *) tempArg->argList->value)->returnValueType == 'm') :
FALSE))
{
SingleFieldSlotCardinalityError(theEnv,slotPtr->slotName->contents);
return(FALSE);
}
}
/*======================================*/
/* Are the slot restrictions satisfied? */
/*======================================*/
if (CheckRHSSlotTypes(theEnv,tempArg->argList,slotPtr,name) == 0)
return(FALSE);
/*=============================================*/
/* Replace the slot with the integer position. */
/*=============================================*/
tempArg->type = INTEGER;
tempArg->value = (void *) EnvAddLong(theEnv,(long) (FindSlotPosition(theDeftemplate,(SYMBOL_HN *) tempArg->value) - 1));
tempArg = tempArg->nextArg;
}
return(TRUE);
}
/**************************************************/
/* FindTemplateForFactAddress: Searches for the */
/* deftemplate name associated with the pattern */
/* to which a fact address has been bound. */
/**************************************************/
static SYMBOL_HN *FindTemplateForFactAddress(
SYMBOL_HN *factAddress,
struct lhsParseNode *theLHS)
{
struct lhsParseNode *thePattern = NULL;
/*===============================================*/
/* Look through the LHS patterns for the pattern */
/* which is bound to the fact address used by */
/* the modify/duplicate function. */
/*===============================================*/
while (theLHS != NULL)
{
if (theLHS->value == (void *) factAddress)
{
thePattern = theLHS;
theLHS = NULL;
}
else
{ theLHS = theLHS->bottom; }
}
if (thePattern == NULL) return(NULL);
/*=====================================*/
/* Verify that just a symbol is stored */
/* as the first field of the pattern. */
/*=====================================*/
thePattern = thePattern->right;
if ((thePattern->type != SF_WILDCARD) || (thePattern->bottom == NULL))
{ return(NULL); }
thePattern = thePattern->bottom;
if ((thePattern->type != SYMBOL) ||
(thePattern->right != NULL) ||
(thePattern->bottom != NULL))
{ return(NULL); }
/*==============================*/
/* Return the deftemplate name. */
/*==============================*/
return((SYMBOL_HN *) thePattern->value);
}
/*******************************************/
/* ModifyParse: Parses the modify command. */
/*******************************************/
globle struct expr *ModifyParse(
void *theEnv,
struct expr *top,
char *logicalName)
{
return(ModAndDupParse(theEnv,top,logicalName,"modify"));
}
/*************************************************/
/* DuplicateParse: Parses the duplicate command. */
/*************************************************/
globle struct expr *DuplicateParse(
void *theEnv,
struct expr *top,
char *logicalName)
{
return(ModAndDupParse(theEnv,top,logicalName,"duplicate"));
}
/*************************************************************/
/* ModAndDupParse: Parses the modify and duplicate commands. */
/*************************************************************/
static struct expr *ModAndDupParse(
void *theEnv,
struct expr *top,
char *logicalName,
char *name)
{
int error = FALSE;
struct token theToken;
struct expr *nextOne, *tempSlot;
struct expr *newField, *firstField, *lastField;
int printError;
short done;
/*==================================================================*/
/* Parse the fact-address or index to the modify/duplicate command. */
/*==================================================================*/
SavePPBuffer(theEnv," ");
GetToken(theEnv,logicalName,&theToken);
if ((theToken.type == SF_VARIABLE) || (theToken.type == GBL_VARIABLE))
{ nextOne = GenConstant(theEnv,theToken.type,theToken.value); }
else if (theToken.type == INTEGER)
{
if (! TopLevelCommand(theEnv))
{
PrintErrorID(theEnv,"TMPLTFUN",1,TRUE);
EnvPrintRouter(theEnv,WERROR,"Fact-indexes can only be used by ");
EnvPrintRouter(theEnv,WERROR,name);
EnvPrintRouter(theEnv,WERROR," as a top level command.\n");
ReturnExpression(theEnv,top);
return(NULL);
}
nextOne = GenConstant(theEnv,INTEGER,theToken.value);
}
else
{
ExpectedTypeError2(theEnv,name,1);
ReturnExpression(theEnv,top);
return(NULL);
}
nextOne->nextArg = NULL;
nextOne->argList = NULL;
top->argList = nextOne;
nextOne = top->argList;
/*=======================================================*/
/* Parse the remaining modify/duplicate slot specifiers. */
/*=======================================================*/
GetToken(theEnv,logicalName,&theToken);
while (theToken.type != RPAREN)
{
PPBackup(theEnv);
SavePPBuffer(theEnv," ");
SavePPBuffer(theEnv,theToken.printForm);
/*=================================================*/
/* Slot definition begins with a left parenthesis. */
/*=================================================*/
if (theToken.type != LPAREN)
{
SyntaxErrorMessage(theEnv,"duplicate/modify function");
ReturnExpression(theEnv,top);
return(NULL);
}
/*=================================*/
/* The slot name must be a symbol. */
/*=================================*/
GetToken(theEnv,logicalName,&theToken);
if (theToken.type != SYMBOL)
{
SyntaxErrorMessage(theEnv,"duplicate/modify function");
ReturnExpression(theEnv,top);
return(NULL);
}
/*=================================*/
/* Check for duplicate slot names. */
/*=================================*/
for (tempSlot = top->argList->nextArg;
tempSlot != NULL;
tempSlot = tempSlot->nextArg)
{
if (tempSlot->value == theToken.value)
{
AlreadyParsedErrorMessage(theEnv,"slot ",ValueToString(theToken.value));
ReturnExpression(theEnv,top);
return(NULL);
}
}
/*=========================================*/
/* Add the slot name to the list of slots. */
/*=========================================*/
nextOne->nextArg = GenConstant(theEnv,SYMBOL,theToken.value);
nextOne = nextOne->nextArg;
/*====================================================*/
/* Get the values to be stored in the specified slot. */
/*====================================================*/
firstField = NULL;
lastField = NULL;
done = FALSE;
while (! done)
{
SavePPBuffer(theEnv," ");
newField = GetAssertArgument(theEnv,logicalName,&theToken,&error,
RPAREN,FALSE,&printError);
if (error)
{
if (printError) SyntaxErrorMessage(theEnv,"deftemplate pattern");
ReturnExpression(theEnv,top);
return(NULL);
}
if (newField == NULL)
{ do
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -