📄 genrcfun.c
字号:
/*************************************************** NAME : MethodsExecuting DESCRIPTION : Determines if any of the methods of a generic function are currently executing INPUTS : The generic function address RETURNS : TRUE if any methods are executing, FALSE otherwise SIDE EFFECTS : None NOTES : None ***************************************************/globle int MethodsExecuting( DEFGENERIC *gfunc) { long i; for (i = 0 ; i < gfunc->mcnt ; i++) if (gfunc->methods[i].busy > 0) return(TRUE); return(FALSE); } #endif#if ! OBJECT_SYSTEM/************************************************************** NAME : SubsumeType DESCRIPTION : Determines if the second type subsumes the first type (e.g. INTEGER is subsumed by NUMBER_TYPE_CODE) INPUTS : Two type codes RETURNS : TRUE if type 2 subsumes type 1, FALSE otherwise SIDE EFFECTS : None NOTES : Used only when COOL is not present **************************************************************/globle intBool SubsumeType( int t1, int t2) { if ((t2 == OBJECT_TYPE_CODE) || (t2 == PRIMITIVE_TYPE_CODE)) return(TRUE); if ((t2 == NUMBER_TYPE_CODE) && ((t1 == INTEGER) || (t1 == FLOAT))) return(TRUE); if ((t2 == LEXEME_TYPE_CODE) && ((t1 == STRING) || (t1 == SYMBOL))) return(TRUE); if ((t2 == ADDRESS_TYPE_CODE) && ((t1 == EXTERNAL_ADDRESS) || (t1 == FACT_ADDRESS) || (t1 == INSTANCE_ADDRESS))) return(TRUE); if ((t2 == LEXEME_TYPE_CODE) && ((t1 == INSTANCE_NAME) || (t1 == INSTANCE_ADDRESS))) return(TRUE); return(FALSE); }#endif/***************************************************** NAME : FindMethodByIndex DESCRIPTION : Finds a generic function method of specified index INPUTS : 1) The generic function 2) The index RETURNS : The position of the method in the generic function's method array, -1 if not found SIDE EFFECTS : None NOTES : None *****************************************************/globle long FindMethodByIndex( DEFGENERIC *gfunc, long theIndex) { long i; for (i = 0 ; i < gfunc->mcnt ; i++) if (gfunc->methods[i].index == theIndex) return(i); return(-1); }#if DEBUGGING_FUNCTIONS/************************************************************* NAME : PreviewGeneric DESCRIPTION : Allows the user to see a printout of all the applicable methods for a particular generic function call INPUTS : None RETURNS : Nothing useful SIDE EFFECTS : Any side-effects of evaluating the generic function arguments and evaluating query-functions to determine the set of applicable methods NOTES : H/L Syntax: (preview-generic <func> <args>) *************************************************************/globle void PreviewGeneric( void *theEnv) { DEFGENERIC *gfunc; DEFGENERIC *previousGeneric; int oldce; DATA_OBJECT temp; EvaluationData(theEnv)->EvaluationError = FALSE; if (EnvArgTypeCheck(theEnv,"preview-generic",1,SYMBOL,&temp) == FALSE) return; gfunc = LookupDefgenericByMdlOrScope(theEnv,DOToString(temp)); if (gfunc == NULL) { PrintErrorID(theEnv,"GENRCFUN",3,FALSE); EnvPrintRouter(theEnv,WERROR,"Unable to find generic function "); EnvPrintRouter(theEnv,WERROR,DOToString(temp)); EnvPrintRouter(theEnv,WERROR," in function preview-generic.\n"); return; } oldce = ExecutingConstruct(theEnv); SetExecutingConstruct(theEnv,TRUE); previousGeneric = DefgenericData(theEnv)->CurrentGeneric; DefgenericData(theEnv)->CurrentGeneric = gfunc; EvaluationData(theEnv)->CurrentEvaluationDepth++; PushProcParameters(theEnv,GetFirstArgument()->nextArg, CountArguments(GetFirstArgument()->nextArg), EnvGetDefgenericName(theEnv,(void *) gfunc),"generic function", UnboundMethodErr); if (EvaluationData(theEnv)->EvaluationError) { PopProcParameters(theEnv); DefgenericData(theEnv)->CurrentGeneric = previousGeneric; EvaluationData(theEnv)->CurrentEvaluationDepth--; SetExecutingConstruct(theEnv,oldce); return; } gfunc->busy++; DisplayGenericCore(theEnv,gfunc); gfunc->busy--; PopProcParameters(theEnv); DefgenericData(theEnv)->CurrentGeneric = previousGeneric; EvaluationData(theEnv)->CurrentEvaluationDepth--; SetExecutingConstruct(theEnv,oldce); }/****************************************************************** NAME : PrintMethod DESCRIPTION : Lists a brief description of methods for a method INPUTS : 1) Buffer for method info 2) Size of buffer (not including space for '\0') 3) The method address RETURNS : Nothing useful SIDE EFFECTS : None NOTES : A terminating newline is NOT included ******************************************************************/#if IBM_TBC#pragma argsused#endifgloble void PrintMethod( void *theEnv, char *buf, int buflen, DEFMETHOD *meth) {#if MAC_MCW || IBM_MCW || MAC_XCD#pragma unused(theEnv)#endif long j,k; register RESTRICTION *rptr; char numbuf[15]; buf[0] = '\0'; if (meth->system) genstrncpy(buf,"SYS",(STD_SIZE) buflen); gensprintf(numbuf,"%-2d ",meth->index); genstrncat(buf,numbuf,(STD_SIZE) buflen-3); for (j = 0 ; j < meth->restrictionCount ; j++) { rptr = &meth->restrictions[j]; if ((((int) j) == meth->restrictionCount-1) && (meth->maxRestrictions == -1)) { if ((rptr->tcnt == 0) && (rptr->query == NULL)) { genstrncat(buf,"$?",buflen-strlen(buf)); break; } genstrncat(buf,"($? ",buflen-strlen(buf)); } else genstrncat(buf,"(",buflen-strlen(buf)); for (k = 0 ; k < rptr->tcnt ; k++) {#if OBJECT_SYSTEM genstrncat(buf,EnvGetDefclassName(theEnv,rptr->types[k]),buflen-strlen(buf));#else genstrncat(buf,TypeName(theEnv,ValueToInteger(rptr->types[k])),buflen-strlen(buf));#endif if (((int) k) < (((int) rptr->tcnt) - 1)) genstrncat(buf," ",buflen-strlen(buf)); } if (rptr->query != NULL) { if (rptr->tcnt != 0) genstrncat(buf," ",buflen-strlen(buf)); genstrncat(buf,"<qry>",buflen-strlen(buf)); } genstrncat(buf,")",buflen-strlen(buf)); if (((int) j) != (((int) meth->restrictionCount)-1)) genstrncat(buf," ",buflen-strlen(buf)); } }#endif/*************************************************** NAME : CheckGenericExists DESCRIPTION : Finds the address of named generic function and prints out error message if not found INPUTS : 1) Calling function 2) Name of generic function RETURNS : Generic function address (NULL if not found) SIDE EFFECTS : None NOTES : None ***************************************************/globle DEFGENERIC *CheckGenericExists( void *theEnv, char *fname, char *gname) { DEFGENERIC *gfunc; gfunc = LookupDefgenericByMdlOrScope(theEnv,gname); if (gfunc == NULL) { PrintErrorID(theEnv,"GENRCFUN",3,FALSE); EnvPrintRouter(theEnv,WERROR,"Unable to find generic function "); EnvPrintRouter(theEnv,WERROR,gname); EnvPrintRouter(theEnv,WERROR," in function "); EnvPrintRouter(theEnv,WERROR,fname); EnvPrintRouter(theEnv,WERROR,".\n"); SetEvaluationError(theEnv,TRUE); } return(gfunc); }/*************************************************** NAME : CheckMethodExists DESCRIPTION : Finds the array index of the specified method and prints out error message if not found INPUTS : 1) Calling function 2) Generic function address 3) Index of method RETURNS : Method array index (-1 if not found) SIDE EFFECTS : None NOTES : None ***************************************************/globle long CheckMethodExists( void *theEnv, char *fname, DEFGENERIC *gfunc, long mi) { long fi; fi = FindMethodByIndex(gfunc,mi); if (fi == -1) { PrintErrorID(theEnv,"GENRCFUN",2,FALSE); EnvPrintRouter(theEnv,WERROR,"Unable to find method "); EnvPrintRouter(theEnv,WERROR,EnvGetDefgenericName(theEnv,(void *) gfunc)); EnvPrintRouter(theEnv,WERROR," #"); PrintLongInteger(theEnv,WERROR,mi); EnvPrintRouter(theEnv,WERROR," in function "); EnvPrintRouter(theEnv,WERROR,fname); EnvPrintRouter(theEnv,WERROR,".\n"); SetEvaluationError(theEnv,TRUE); } return(fi); }#if ! OBJECT_SYSTEM/******************************************************* NAME : TypeName DESCRIPTION : Given an integer type code, this function returns the string name of the type INPUTS : The type code RETURNS : The name-string of the type, or "<???UNKNOWN-TYPE???>" for unrecognized types SIDE EFFECTS : EvaluationError set and error message printed for unrecognized types NOTES : Used only when COOL is not present *******************************************************/globle char *TypeName( void *theEnv, int tcode) { switch (tcode) { case INTEGER : return(INTEGER_TYPE_NAME); case FLOAT : return(FLOAT_TYPE_NAME); case SYMBOL : return(SYMBOL_TYPE_NAME); case STRING : return(STRING_TYPE_NAME); case MULTIFIELD : return(MULTIFIELD_TYPE_NAME); case EXTERNAL_ADDRESS : return(EXTERNAL_ADDRESS_TYPE_NAME); case FACT_ADDRESS : return(FACT_ADDRESS_TYPE_NAME); case INSTANCE_ADDRESS : return(INSTANCE_ADDRESS_TYPE_NAME); case INSTANCE_NAME : return(INSTANCE_NAME_TYPE_NAME); case OBJECT_TYPE_CODE : return(OBJECT_TYPE_NAME); case PRIMITIVE_TYPE_CODE : return(PRIMITIVE_TYPE_NAME); case NUMBER_TYPE_CODE : return(NUMBER_TYPE_NAME); case LEXEME_TYPE_CODE : return(LEXEME_TYPE_NAME); case ADDRESS_TYPE_CODE : return(ADDRESS_TYPE_NAME); case INSTANCE_TYPE_CODE : return(INSTANCE_TYPE_NAME); default : PrintErrorID(theEnv,"INSCOM",1,FALSE); EnvPrintRouter(theEnv,WERROR,"Undefined type in function type.\n"); SetEvaluationError(theEnv,TRUE); return("<UNKNOWN-TYPE>"); } }#endif/****************************************************** NAME : PrintGenericName DESCRIPTION : Prints the name of a gneric function (including the module name if the generic is not in the current module) INPUTS : 1) The logical name of the output 2) The generic functions RETURNS : Nothing useful SIDE EFFECTS : Generic name printed NOTES : None ******************************************************/globle void PrintGenericName( void *theEnv, char *logName, DEFGENERIC *gfunc) { if (gfunc->header.whichModule->theModule != ((struct defmodule *) EnvGetCurrentModule(theEnv))) { EnvPrintRouter(theEnv,logName,EnvGetDefmoduleName(theEnv,(void *) gfunc->header.whichModule->theModule)); EnvPrintRouter(theEnv,logName,"::"); } EnvPrintRouter(theEnv,logName,ValueToString((void *) gfunc->header.name)); }/* ========================================= ***************************************** INTERNALLY VISIBLE FUNCTIONS ========================================= ***************************************** */#if DEBUGGING_FUNCTIONS/********************************************************* NAME : DisplayGenericCore DESCRIPTION : Prints out a description of a core frame of applicable methods for a particular call of a generic function INPUTS : The generic function RETURNS : Nothing useful SIDE EFFECTS : None NOTES : None *********************************************************/static void DisplayGenericCore( void *theEnv, DEFGENERIC *gfunc) { long i; char buf[256]; int rtn = FALSE; for (i = 0 ; i < gfunc->mcnt ; i++) { gfunc->methods[i].busy++; if (IsMethodApplicable(theEnv,&gfunc->methods[i])) { rtn = TRUE; EnvPrintRouter(theEnv,WDISPLAY,EnvGetDefgenericName(theEnv,(void *) gfunc)); EnvPrintRouter(theEnv,WDISPLAY," #"); PrintMethod(theEnv,buf,255,&gfunc->methods[i]); EnvPrintRouter(theEnv,WDISPLAY,buf); EnvPrintRouter(theEnv,WDISPLAY,"\n"); } gfunc->methods[i].busy--; } if (rtn == FALSE) { EnvPrintRouter(theEnv,WDISPLAY,"No applicable methods for "); EnvPrintRouter(theEnv,WDISPLAY,EnvGetDefgenericName(theEnv,(void *) gfunc)); EnvPrintRouter(theEnv,WDISPLAY,".\n"); } }#endif#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -