📄 genrcexe.c
字号:
DESCRIPTION : Determines if a shadowed generic
function method is available for
execution
INPUTS : None
RETURNS : TRUE if there is a method available,
FALSE otherwise
SIDE EFFECTS : None
NOTES : H/L Syntax: (next-methodp)
***************************************************/
globle int NextMethodP(
void *theEnv)
{
register DEFMETHOD *meth;
if (DefgenericData(theEnv)->CurrentMethod == NULL)
return(FALSE);
meth = FindApplicableMethod(theEnv,DefgenericData(theEnv)->CurrentGeneric,DefgenericData(theEnv)->CurrentMethod);
if (meth != NULL)
{
meth->busy--;
return(TRUE);
}
return(FALSE);
}
/****************************************************
NAME : CallNextMethod
DESCRIPTION : Executes the next available method
in the core for a generic function
INPUTS : Caller's buffer for the result
RETURNS : Nothing useful
SIDE EFFECTS : Side effects of execution of shadow
EvaluationError set if no method
is available to execute.
NOTES : H/L Syntax: (call-next-method)
****************************************************/
globle void CallNextMethod(
void *theEnv,
DATA_OBJECT *result)
{
DEFMETHOD *oldMethod;
#if PROFILING_FUNCTIONS
struct profileFrameInfo profileFrame;
#endif
result->type = SYMBOL;
result->value = EnvFalseSymbol(theEnv);
if (EvaluationData(theEnv)->HaltExecution)
return;
oldMethod = DefgenericData(theEnv)->CurrentMethod;
if (DefgenericData(theEnv)->CurrentMethod != NULL)
DefgenericData(theEnv)->CurrentMethod = FindApplicableMethod(theEnv,DefgenericData(theEnv)->CurrentGeneric,DefgenericData(theEnv)->CurrentMethod);
if (DefgenericData(theEnv)->CurrentMethod == NULL)
{
DefgenericData(theEnv)->CurrentMethod = oldMethod;
PrintErrorID(theEnv,"GENRCEXE",2,FALSE);
EnvPrintRouter(theEnv,WERROR,"Shadowed methods not applicable in current context.\n");
SetEvaluationError(theEnv,TRUE);
return;
}
#if DEBUGGING_FUNCTIONS
if (DefgenericData(theEnv)->CurrentMethod->trace)
WatchMethod(theEnv,BEGIN_TRACE);
#endif
if (DefgenericData(theEnv)->CurrentMethod->system)
{
EXPRESSION fcall;
fcall.type = FCALL;
fcall.value = DefgenericData(theEnv)->CurrentMethod->actions->value;
fcall.nextArg = NULL;
fcall.argList = GetProcParamExpressions(theEnv);
EvaluateExpression(theEnv,&fcall,result);
}
else
{
#if PROFILING_FUNCTIONS
StartProfile(theEnv,&profileFrame,
&DefgenericData(theEnv)->CurrentGeneric->header.usrData,
ProfileFunctionData(theEnv)->ProfileConstructs);
#endif
EvaluateProcActions(theEnv,DefgenericData(theEnv)->CurrentGeneric->header.whichModule->theModule,
DefgenericData(theEnv)->CurrentMethod->actions,DefgenericData(theEnv)->CurrentMethod->localVarCount,
result,UnboundMethodErr);
#if PROFILING_FUNCTIONS
EndProfile(theEnv,&profileFrame);
#endif
}
DefgenericData(theEnv)->CurrentMethod->busy--;
#if DEBUGGING_FUNCTIONS
if (DefgenericData(theEnv)->CurrentMethod->trace)
WatchMethod(theEnv,END_TRACE);
#endif
DefgenericData(theEnv)->CurrentMethod = oldMethod;
ProcedureFunctionData(theEnv)->ReturnFlag = FALSE;
}
/**************************************************************************
NAME : CallSpecificMethod
DESCRIPTION : Allows a specific method to be called without regards to
higher precedence methods which might also be applicable
However, shadowed methods can still be called.
INPUTS : A data object buffer to hold the method evaluation result
RETURNS : Nothing useful
SIDE EFFECTS : Side-effects of method applicability tests and the
evaluation of methods
NOTES : H/L Syntax: (call-specific-method
<generic-function> <method-index> <args>)
**************************************************************************/
globle void CallSpecificMethod(
void *theEnv,
DATA_OBJECT *result)
{
DATA_OBJECT temp;
DEFGENERIC *gfunc;
int mi;
result->type = SYMBOL;
result->value = EnvFalseSymbol(theEnv);
if (EnvArgTypeCheck(theEnv,"call-specific-method",1,SYMBOL,&temp) == FALSE)
return;
gfunc = CheckGenericExists(theEnv,"call-specific-method",DOToString(temp));
if (gfunc == NULL)
return;
if (EnvArgTypeCheck(theEnv,"call-specific-method",2,INTEGER,&temp) == FALSE)
return;
mi = CheckMethodExists(theEnv,"call-specific-method",gfunc,DOToInteger(temp));
if (mi == -1)
return;
gfunc->methods[mi].busy++;
GenericDispatch(theEnv,gfunc,NULL,&gfunc->methods[mi],
GetFirstArgument()->nextArg->nextArg,result);
gfunc->methods[mi].busy--;
}
/***********************************************************************
NAME : OverrideNextMethod
DESCRIPTION : Changes the arguments to shadowed methods, thus the set
of applicable methods to this call may change
INPUTS : A buffer to hold the result of the call
RETURNS : Nothing useful
SIDE EFFECTS : Any of evaluating method restrictions and bodies
NOTES : H/L Syntax: (override-next-method <args>)
***********************************************************************/
globle void OverrideNextMethod(
void *theEnv,
DATA_OBJECT *result)
{
result->type = SYMBOL;
result->value = EnvFalseSymbol(theEnv);
if (EvaluationData(theEnv)->HaltExecution)
return;
if (DefgenericData(theEnv)->CurrentMethod == NULL)
{
PrintErrorID(theEnv,"GENRCEXE",2,FALSE);
EnvPrintRouter(theEnv,WERROR,"Shadowed methods not applicable in current context.\n");
SetEvaluationError(theEnv,TRUE);
return;
}
GenericDispatch(theEnv,DefgenericData(theEnv)->CurrentGeneric,DefgenericData(theEnv)->CurrentMethod,NULL,
GetFirstArgument(),result);
}
/***********************************************************
NAME : GetGenericCurrentArgument
DESCRIPTION : Returns the value of the generic function
argument being tested in the method
applicability determination process
INPUTS : A data-object buffer
RETURNS : Nothing useful
SIDE EFFECTS : Data-object set
NOTES : Useful for queries in wildcard restrictions
***********************************************************/
globle void GetGenericCurrentArgument(
void *theEnv,
DATA_OBJECT *result)
{
result->type = DefgenericData(theEnv)->GenericCurrentArgument->type;
result->value = DefgenericData(theEnv)->GenericCurrentArgument->value;
result->begin = DefgenericData(theEnv)->GenericCurrentArgument->begin;
result->end = DefgenericData(theEnv)->GenericCurrentArgument->end;
}
/* =========================================
*****************************************
INTERNALLY VISIBLE FUNCTIONS
=========================================
***************************************** */
/************************************************************
NAME : FindApplicableMethod
DESCRIPTION : Finds the first/next applicable
method for a generic function call
INPUTS : 1) The generic function pointer
2) The address of the current method
(NULL to find the first)
RETURNS : The address of the first/next
applicable method (NULL on errors)
SIDE EFFECTS : Any from evaluating query restrictions
Methoid busy count incremented if applicable
NOTES : None
************************************************************/
static DEFMETHOD *FindApplicableMethod(
void *theEnv,
DEFGENERIC *gfunc,
DEFMETHOD *meth)
{
if (meth != NULL)
meth++;
else
meth = gfunc->methods;
for ( ; meth < &gfunc->methods[gfunc->mcnt] ; meth++)
{
meth->busy++;
if (IsMethodApplicable(theEnv,meth))
return(meth);
meth->busy--;
}
return(NULL);
}
#if DEBUGGING_FUNCTIONS
/**********************************************************************
NAME : WatchGeneric
DESCRIPTION : Prints out a trace of the beginning or end
of the execution of a generic function
INPUTS : A string to indicate beginning or end of execution
RETURNS : Nothing useful
SIDE EFFECTS : None
NOTES : Uses the globals CurrentGeneric, ProcParamArraySize and
ProcParamArray for other trace info
**********************************************************************/
static void WatchGeneric(
void *theEnv,
char *tstring)
{
EnvPrintRouter(theEnv,WTRACE,"GNC ");
EnvPrintRouter(theEnv,WTRACE,tstring);
EnvPrintRouter(theEnv,WTRACE," ");
if (DefgenericData(theEnv)->CurrentGeneric->header.whichModule->theModule != ((struct defmodule *) EnvGetCurrentModule(theEnv)))
{
EnvPrintRouter(theEnv,WTRACE,EnvGetDefmoduleName(theEnv,(void *)
DefgenericData(theEnv)->CurrentGeneric->header.whichModule->theModule));
EnvPrintRouter(theEnv,WTRACE,"::");
}
EnvPrintRouter(theEnv,WTRACE,ValueToString((void *) DefgenericData(theEnv)->CurrentGeneric->header.name));
EnvPrintRouter(theEnv,WTRACE," ");
EnvPrintRouter(theEnv,WTRACE," ED:");
PrintLongInteger(theEnv,WTRACE,(long) EvaluationData(theEnv)->CurrentEvaluationDepth);
PrintProcParamArray(theEnv,WTRACE);
}
/**********************************************************************
NAME : WatchMethod
DESCRIPTION : Prints out a trace of the beginning or end
of the execution of a generic function
method
INPUTS : A string to indicate beginning or end of execution
RETURNS : Nothing useful
SIDE EFFECTS : None
NOTES : Uses the globals CurrentGeneric, CurrentMethod,
ProcParamArraySize and ProcParamArray for
other trace info
**********************************************************************/
static void WatchMethod(
void *theEnv,
char *tstring)
{
EnvPrintRouter(theEnv,WTRACE,"MTH ");
EnvPrintRouter(theEnv,WTRACE,tstring);
EnvPrintRouter(theEnv,WTRACE," ");
if (DefgenericData(theEnv)->CurrentGeneric->header.whichModule->theModule != ((struct defmodule *) EnvGetCurrentModule(theEnv)))
{
EnvPrintRouter(theEnv,WTRACE,EnvGetDefmoduleName(theEnv,(void *)
DefgenericData(theEnv)->CurrentGeneric->header.whichModule->theModule));
EnvPrintRouter(theEnv,WTRACE,"::");
}
EnvPrintRouter(theEnv,WTRACE,ValueToString((void *) DefgenericData(theEnv)->CurrentGeneric->header.name));
EnvPrintRouter(theEnv,WTRACE,":#");
if (DefgenericData(theEnv)->CurrentMethod->system)
EnvPrintRouter(theEnv,WTRACE,"SYS");
PrintLongInteger(theEnv,WTRACE,(long) DefgenericData(theEnv)->CurrentMethod->index);
EnvPrintRouter(theEnv,WTRACE," ");
EnvPrintRouter(theEnv,WTRACE," ED:");
PrintLongInteger(theEnv,WTRACE,(long) EvaluationData(theEnv)->CurrentEvaluationDepth);
PrintProcParamArray(theEnv,WTRACE);
}
#endif
#if OBJECT_SYSTEM
/***************************************************
NAME : DetermineRestrictionClass
DESCRIPTION : Finds the class of an argument in
the ProcParamArray
INPUTS : The argument data object
RETURNS : The class address, NULL if error
SIDE EFFECTS : EvaluationError set on errors
NOTES : None
***************************************************/
static DEFCLASS *DetermineRestrictionClass(
void *theEnv,
DATA_OBJECT *dobj)
{
INSTANCE_TYPE *ins;
DEFCLASS *cls;
if (dobj->type == INSTANCE_NAME)
{
ins = FindInstanceBySymbol(theEnv,(SYMBOL_HN *) dobj->value);
cls = (ins != NULL) ? ins->cls : NULL;
}
else if (dobj->type == INSTANCE_ADDRESS)
{
ins = (INSTANCE_TYPE *) dobj->value;
cls = (ins->garbage == 0) ? ins->cls : NULL;
}
else
return(DefclassData(theEnv)->PrimitiveClassMap[dobj->type]);
if (cls == NULL)
{
SetEvaluationError(theEnv,TRUE);
PrintErrorID(theEnv,"GENRCEXE",3,FALSE);
EnvPrintRouter(theEnv,WERROR,"Unable to determine class of ");
PrintDataObject(theEnv,WERROR,dobj);
EnvPrintRouter(theEnv,WERROR," in generic function ");
EnvPrintRouter(theEnv,WERROR,EnvGetDefgenericName(theEnv,(void *) DefgenericData(theEnv)->CurrentGeneric));
EnvPrintRouter(theEnv,WERROR,".\n");
}
return(cls);
}
#endif
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -