📄 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,(long) DOToLong(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 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 long) DefgenericData(theEnv)->CurrentMethod->index); EnvPrintRouter(theEnv,WTRACE," "); EnvPrintRouter(theEnv,WTRACE," ED:"); PrintLongInteger(theEnv,WTRACE,(long 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 + -