📄 tmpltfun.c
字号:
SetpDOBegin(returnValue,1); SetpDOEnd(returnValue,theFact->theProposition.multifieldLength); SetpType(returnValue,FACT_ADDRESS); SetpValue(returnValue,(VOID *) theFact); } return; } #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 BOOLEAN UpdateModifyDuplicate(top,name,vTheLHS) struct expr *top; char *name; VOID *vTheLHS; { struct expr *functionArgs, *tempArg; SYMBOL_HN *templateName; struct deftemplate *theDeftemplate; struct templateSlot *slotPtr; int 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,vTheLHS); if (templateName == NULL) return(CLIPS_TRUE); } else { return(CLIPS_TRUE); } /*========================================*/ /* Make sure that the fact being modified */ /* has a corresponding deftemplate. */ /*========================================*/ theDeftemplate = (struct deftemplate *) LookupConstruct(DeftemplateConstruct, ValueToString(templateName), CLIPS_FALSE); if (theDeftemplate == NULL) return(CLIPS_TRUE); if (theDeftemplate->implied) return(CLIPS_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,tempArg->value,&position)) == NULL) { InvalidDeftemplateSlotMessage(ValueToString(tempArg->value), ValueToString(theDeftemplate->header.name)); return(CLIPS_FALSE); } /*=========================================================*/ /* Is a multifield value being put in a single field slot? */ /*=========================================================*/ if (slotPtr->multislot == CLIPS_FALSE) { if (tempArg->argList == NULL) { SingleFieldSlotCardinalityError(slotPtr->slotName->contents); return(CLIPS_FALSE); } else if (tempArg->argList->nextArg != NULL) { SingleFieldSlotCardinalityError(slotPtr->slotName->contents); return(CLIPS_FALSE); } else if ((tempArg->argList->type == MF_VARIABLE) || ((tempArg->argList->type == FCALL) ? (((struct FunctionDefinition *) tempArg->argList->value)->returnValueType == 'm') : CLIPS_FALSE)) { SingleFieldSlotCardinalityError(slotPtr->slotName->contents); return(CLIPS_FALSE); } } /*======================================*/ /* Are the slot restrictions satisfied? */ /*======================================*/ if (CheckRHSSlotTypes(tempArg->argList,slotPtr,name) == 0) return(CLIPS_FALSE); /*=============================================*/ /* Replace the slot with the integer position. */ /*=============================================*/ tempArg->type = INTEGER; tempArg->value = (VOID *) AddLong((long) (FindSlotPosition(theDeftemplate,tempArg->value) - 1)); tempArg = tempArg->nextArg; } return(CLIPS_TRUE); } /**************************************************//* FindTemplateForFactAddress: Searches for the *//* deftemplate name associated with the pattern *//* to which a fact address has been bound. *//**************************************************/static SYMBOL_HN *FindTemplateForFactAddress(factAddress,theLHS) 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(top,logicalName) struct expr *top; char *logicalName; { return(ModAndDupParse(top,logicalName,"modify")); }/*************************************************//* DuplicateParse: Parses the duplicate command. *//*************************************************/globle struct expr *DuplicateParse(top,logicalName) struct expr *top; char *logicalName; { return(ModAndDupParse(top,logicalName,"duplicate")); }/*************************************************************//* ModAndDupParse: Parses the modify and duplicate commands. *//*************************************************************/static struct expr *ModAndDupParse(top,logicalName,name) struct expr *top; char *logicalName; char *name; { int error = CLIPS_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(" "); GetToken(logicalName,&theToken); if ((theToken.type == SF_VARIABLE) || (theToken.type == GBL_VARIABLE)) { nextOne = GenConstant(theToken.type,theToken.value); } else if (theToken.type == INTEGER) { if (! TopLevelCommand()) { PrintErrorID("TMPLTFUN",1,CLIPS_TRUE); PrintCLIPS(WERROR,"Fact-indexes can only be used by "); PrintCLIPS(WERROR,name); PrintCLIPS(WERROR," as a top level command.\n"); ReturnExpression(top); return(NULL); } nextOne = GenConstant(INTEGER,theToken.value); } else { ExpectedTypeError2(name,1); ReturnExpression(top); return(NULL); } nextOne->nextArg = NULL; nextOne->argList = NULL; top->argList = nextOne; nextOne = top->argList; /*=======================================================*/ /* Parse the remaining modify/duplicate slot specifiers. */ /*=======================================================*/ GetToken(logicalName,&theToken); while (theToken.type != RPAREN) { PPBackup(); SavePPBuffer(" "); SavePPBuffer(theToken.printForm); /*=================================================*/ /* Slot definition begins with a left parenthesis. */ /*=================================================*/ if (theToken.type != LPAREN) { SyntaxErrorMessage("duplicate/modify function"); ReturnExpression(top); return(NULL); } /*=================================*/ /* The slot name must be a symbol. */ /*=================================*/ GetToken(logicalName,&theToken); if (theToken.type != SYMBOL) { SyntaxErrorMessage("duplicate/modify function"); ReturnExpression(top); return(NULL); } /*=================================*/ /* Check for duplicate slot names. */ /*=================================*/ for (tempSlot = top->argList->nextArg; tempSlot != NULL; tempSlot = tempSlot->nextArg) { if (tempSlot->value == theToken.value) { AlreadyParsedErrorMessage("slot ",ValueToString(theToken.value)); ReturnExpression(top); return(NULL); } } /*=========================================*/ /* Add the slot name to the list of slots. */ /*=========================================*/ nextOne->nextArg = GenConstant(SYMBOL,theToken.value); nextOne = nextOne->nextArg; /*====================================================*/ /* Get the values to be stored in the specified slot. */ /*====================================================*/ firstField = NULL; lastField = NULL; done = CLIPS_FALSE; while (! done) { SavePPBuffer(" "); newField = GetAssertArgument(logicalName,&theToken,&error, RPAREN,CLIPS_FALSE,&printError); if (error) { if (printError) SyntaxErrorMessage("deftemplate pattern"); ReturnExpression(top); return(NULL); } if (newField == NULL) { done = CLIPS_TRUE; } if (lastField == NULL) { firstField = newField; } else { lastField->nextArg = newField; } lastField = newField; } /*================================================*/ /* Slot definition ends with a right parenthesis. */ /*================================================*/ if (theToken.type != RPAREN) { SyntaxErrorMessage("duplicate/modify function"); ReturnExpression(top); ReturnExpression(firstField); return(NULL); } else { PPBackup(); PPBackup(); SavePPBuffer(")"); } nextOne->argList = firstField; GetToken(logicalName,&theToken); } /*================================================*/ /* Return the parsed modify/duplicate expression. */ /*================================================*/ return(top); }#endif /* (! RUN_TIME) && (! BLOAD_ONLY) */#endif /* DEFTEMPLATE_CONSTRUCT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -