📄 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)
{
register unsigned 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 int FindMethodByIndex(
DEFGENERIC *gfunc,
unsigned theIndex)
{
register unsigned i;
for (i = 0 ; i < gfunc->mcnt ; i++)
if (gfunc->methods[i].index == theIndex)
return((int) 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
#endif
globle void PrintMethod(
void *theEnv,
char *buf,
int buflen,
DEFMETHOD *meth)
{
#if MAC_MCW || IBM_MCW || MAC_XCD
#pragma unused(theEnv)
#endif
register unsigned j,k;
register RESTRICTION *rptr;
char numbuf[15];
buf[0] = '\0';
if (meth->system)
strncpy(buf,"SYS",(STD_SIZE) buflen);
sprintf(numbuf,"%-2d ",meth->index);
strncat(buf,numbuf,(STD_SIZE) buflen-3);
for (j = 0 ; j < (unsigned) meth->restrictionCount ; j++)
{
rptr = &meth->restrictions[j];
if ((((int) j) == meth->restrictionCount-1) && (meth->maxRestrictions == -1))
{
if ((rptr->tcnt == 0) && (rptr->query == NULL))
{
strncat(buf,"$?",buflen-strlen(buf));
break;
}
strncat(buf,"($? ",buflen-strlen(buf));
}
else
strncat(buf,"(",buflen-strlen(buf));
for (k = 0 ; k < rptr->tcnt ; k++)
{
#if OBJECT_SYSTEM
strncat(buf,EnvGetDefclassName(theEnv,rptr->types[k]),buflen-strlen(buf));
#else
strncat(buf,TypeName(theEnv,ValueToInteger(rptr->types[k])),buflen-strlen(buf));
#endif
if (((int) k) < (((int) rptr->tcnt) - 1))
strncat(buf," ",buflen-strlen(buf));
}
if (rptr->query != NULL)
{
if (rptr->tcnt != 0)
strncat(buf," ",buflen-strlen(buf));
strncat(buf,"<qry>",buflen-strlen(buf));
}
strncat(buf,")",buflen-strlen(buf));
if (((int) j) != (((int) meth->restrictionCount)-1))
strncat(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 int CheckMethodExists(
void *theEnv,
char *fname,
DEFGENERIC *gfunc,
int mi)
{
int fi;
fi = FindMethodByIndex(gfunc,(unsigned) 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,(long) 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)
{
register unsigned 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 + -