/********************************************************* NAME : SlotInfoSlot DESCRIPTION : Runtime support routine for slot-sources, slot-facets, et. al. which looks up a slot INPUTS : 1) Data object buffer 2) Class pointer 3) Name-string of slot to find 4) The name of the calling function RETURNS : Nothing useful SIDE EFFECTS : Support function called and data object buffer initialized NOTES : None *********************************************************/ static SLOT_DESC *SlotInfoSlot( void *theEnv, DATA_OBJECT *result, DEFCLASS *cls, const char *sname, const char *fnxname) { SYMBOL_HN *ssym; int i; if ((ssym = FindSymbolHN(theEnv,sname)) == NULL) { SetEvaluationError(theEnv,TRUE); EnvSetMultifieldErrorValue(theEnv,result); return(NULL); } i = FindInstanceTemplateSlot(theEnv,cls,ssym); if (i == -1) { SlotExistError(theEnv,sname,fnxname); SetEvaluationError(theEnv,TRUE); EnvSetMultifieldErrorValue(theEnv,result); return(NULL); } result->type = MULTIFIELD; result->begin = 0; return(cls->instanceTemplate[i]); }
/*************************************************** NAME : CheckSlotExists DESCRIPTION : Checks first two arguments of a function for a valid class and (inherited) slot INPUTS : 1) The name of the function 2) A buffer to hold the found class 3) A flag indicating whether the non-existence of the slot should be an error 4) A flag indicating if the slot can be inherited or not RETURNS : NULL if slot not found, slot descriptor otherwise SIDE EFFECTS : Class buffer set if no errors, NULL on errors NOTES : None ***************************************************/ static SlotDescriptor *CheckSlotExists( UDFContext *context, const char *func, Defclass **classBuffer, bool existsErrorFlag, bool inheritFlag) { CLIPSLexeme *ssym; int slotIndex; SlotDescriptor *sd; Environment *theEnv = context->environment; ssym = CheckClassAndSlot(context,func,classBuffer); if (ssym == NULL) return NULL; slotIndex = FindInstanceTemplateSlot(theEnv,*classBuffer,ssym); if (slotIndex == -1) { if (existsErrorFlag) { SlotExistError(theEnv,ssym->contents,func); SetEvaluationError(theEnv,true); } return NULL; } sd = (*classBuffer)->instanceTemplate[slotIndex]; if ((sd->cls == *classBuffer) || inheritFlag) { return sd; } PrintErrorID(theEnv,"CLASSEXM",1,false); WriteString(theEnv,STDERR,"Inherited slot '"); WriteString(theEnv,STDERR,ssym->contents); WriteString(theEnv,STDERR,"' from class "); PrintClassName(theEnv,STDERR,sd->cls,true,false); WriteString(theEnv,STDERR," is not valid for function '"); WriteString(theEnv,STDERR,func); WriteString(theEnv,STDERR,"'.\n"); SetEvaluationError(theEnv,true); return NULL; }
/*************************************************** NAME : LookupSlot DESCRIPTION : Finds a slot in a class INPUTS : 1) The class 2) The slot name 3) A flag indicating if inherited slots are OK or not RETURNS : The slot descriptor address, or NULL if not found SIDE EFFECTS : None NOTES : None ***************************************************/ static SLOT_DESC *LookupSlot( void *theEnv, DEFCLASS *theDefclass, char *slotName, intBool inheritFlag) { SYMBOL_HN *slotSymbol; int slotIndex; SLOT_DESC *sd; slotSymbol = FindSymbolHN(theEnv,slotName); if (slotSymbol == NULL) return(NULL); slotIndex = FindInstanceTemplateSlot(theEnv,theDefclass,slotSymbol); if (slotIndex == -1) return(NULL); sd = theDefclass->instanceTemplate[slotIndex]; if ((sd->cls != theDefclass) && (inheritFlag == FALSE)) return(NULL); return(sd); }
/*************************************************** NAME : CheckSlotExists DESCRIPTION : Checks first two arguments of a function for a valid class and (inherited) slot INPUTS : 1) The name of the function 2) A buffer to hold the found class 3) A flag indicating whether the non-existence of the slot should be an error 4) A flag indicating if the slot can be inherited or not RETURNS : NULL if slot not found, slot descriptor otherwise SIDE EFFECTS : Class buffer set if no errors, NULL on errors NOTES : None ***************************************************/ static SLOT_DESC *CheckSlotExists( void *theEnv, char *func, DEFCLASS **classBuffer, intBool existsErrorFlag, intBool inheritFlag) { SYMBOL_HN *ssym; int slotIndex; SLOT_DESC *sd; ssym = CheckClassAndSlot(theEnv,func,classBuffer); if (ssym == NULL) return(NULL); slotIndex = FindInstanceTemplateSlot(theEnv,*classBuffer,ssym); if (slotIndex == -1) { if (existsErrorFlag) { SlotExistError(theEnv,ValueToString(ssym),func); SetEvaluationError(theEnv,TRUE); } return(NULL); } sd = (*classBuffer)->instanceTemplate[slotIndex]; if ((sd->cls == *classBuffer) || inheritFlag) return(sd); PrintErrorID(theEnv,"CLASSEXM",1,FALSE); EnvPrintRouter(theEnv,WERROR,"Inherited slot "); EnvPrintRouter(theEnv,WERROR,ValueToString(ssym)); EnvPrintRouter(theEnv,WERROR," from class "); PrintClassName(theEnv,WERROR,sd->cls,FALSE); EnvPrintRouter(theEnv,WERROR," is not valid for function "); EnvPrintRouter(theEnv,WERROR,func); EnvPrintRouter(theEnv,WERROR,"\n"); SetEvaluationError(theEnv,TRUE); return(NULL); }
/*************************************************** NAME : LookupSlot DESCRIPTION : Finds a slot in a class INPUTS : 1) The class 2) The slot name 3) A flag indicating if inherited slots are OK or not RETURNS : The slot descriptor address, or NULL if not found SIDE EFFECTS : None NOTES : None ***************************************************/ static SlotDescriptor *LookupSlot( Environment *theEnv, Defclass *theDefclass, const char *slotName, bool inheritFlag) { CLIPSLexeme *slotSymbol; int slotIndex; SlotDescriptor *sd; slotSymbol = FindSymbolHN(theEnv,slotName,SYMBOL_BIT); if (slotSymbol == NULL) { return NULL; } slotIndex = FindInstanceTemplateSlot(theEnv,theDefclass,slotSymbol); if (slotIndex == -1) { return NULL; } sd = theDefclass->instanceTemplate[slotIndex]; if ((sd->cls != theDefclass) && (inheritFlag == false)) { return NULL; } return sd; }
/********************************************************* NAME : CheckSlotReference DESCRIPTION : Examines a ?self:<slot-name> reference If the reference is a single-field or global variable, checking and evaluation is delayed until run-time. If the reference is a symbol, this routine verifies that the slot is a legal slot for the reference (i.e., it exists in the class to which the message-handler is being attached, it is visible and it is writable for write reference) INPUTS : 1) A buffer holding the class of the handler being parsed 2) The type of the slot reference 3) The value of the slot reference 4) A flag indicating if this is a read or write access 5) Value expression for write RETURNS : Class slot on success, NULL on errors SIDE EFFECTS : Messages printed on errors. NOTES : For static references, this function insures that the slot is either publicly visible or that the handler is being attached to the same class in which the private slot is defined. *********************************************************/ static SLOT_DESC *CheckSlotReference( void *theEnv, DEFCLASS *theDefclass, int theType, void *theValue, CLIPS_BOOLEAN writeFlag, EXPRESSION *writeExpression) { int slotIndex; SLOT_DESC *sd; int vCode; if (theType != SYMBOL) { PrintErrorID(theEnv,"MSGPSR",7,FALSE); EnvPrintRouter(theEnv,WERROR,"Illegal value for ?self reference.\n"); return(NULL); } slotIndex = FindInstanceTemplateSlot(theEnv,theDefclass,(SYMBOL_HN *) theValue); if (slotIndex == -1) { PrintErrorID(theEnv,"MSGPSR",6,FALSE); EnvPrintRouter(theEnv,WERROR,"No such slot "); EnvPrintRouter(theEnv,WERROR,ValueToString(theValue)); EnvPrintRouter(theEnv,WERROR," in class "); EnvPrintRouter(theEnv,WERROR,EnvGetDefclassName(theEnv,(void *) theDefclass)); EnvPrintRouter(theEnv,WERROR," for ?self reference.\n"); return(NULL); } sd = theDefclass->instanceTemplate[slotIndex]; if ((sd->publicVisibility == 0) && (sd->cls != theDefclass)) { SlotVisibilityViolationError(theEnv,sd,theDefclass); return(NULL); } if (! writeFlag) return(sd); /* ================================================= If a slot is initialize-only, the WithinInit flag still needs to be checked at run-time, for the handler could be called out of the context of an init. ================================================= */ if (sd->noWrite && (sd->initializeOnly == 0)) { SlotAccessViolationError(theEnv,ValueToString(theValue), FALSE,(void *) theDefclass); return(NULL); } if (EnvGetStaticConstraintChecking(theEnv)) { vCode = ConstraintCheckExpressionChain(theEnv,writeExpression,sd->constraint); if (vCode != NO_VIOLATION) { PrintErrorID(theEnv,"CSTRNCHK",1,FALSE); EnvPrintRouter(theEnv,WERROR,"Expression for "); PrintSlot(theEnv,WERROR,sd,NULL,"direct slot write"); ConstraintViolationErrorMessage(theEnv,NULL,NULL,0,0,NULL,0, vCode,sd->constraint,FALSE); return(NULL); } } return(sd); }