/**************************************************************************** ** ** This file is part of GAP, a system for computational discrete algebra. ** ** Copyright of GAP belongs to its developers, whose names are too numerous ** to list here. Please refer to the COPYRIGHT file for details. ** ** SPDX-License-Identifier: GPL-2.0-or-later ** ** This file contains the functions for the function call mechanism package. ** ** For a description of what the function call mechanism is about see the ** declaration part of this package. ** ** Each function is represented by a function bag (of type 'T_FUNCTION'), ** which has the following format. ** ** +-------+-------+- - - -+-------+ ** |handler|handler| |handler| (for all functions) ** | 0 | 1 | | 7 | ** +-------+-------+- - - -+-------+ ** ** +-------+-------+-------+-------+ ** | name | number| args &| prof- | (for all functions) ** | func. | args | locals| iling | ** +-------+-------+-------+-------+ ** ** +-------+-------+-------+-------+ ** | number| body | envir-| funcs.| (only for interpreted functions) ** | locals| func. | onment| exprs.| ** +-------+-------+-------+-------+ ** ** ...what the handlers are.. ** ...what the other components are...
*/
Obj NAMI_FUNC(Obj func, Int i)
{ return ELM_LIST(NAMS_FUNC(func),i);
}
/**************************************************************************** ** *F COUNT_PROF( <prof> ) . . . . . . . . number of invocations of a function *F TIME_WITH_PROF( <prof> ) . . . . . . time with children in a function *F TIME_WOUT_PROF( <prof> ) . . . . . . time without children in a function *F STOR_WITH_PROF( <prof> ) . . . . storage with children in a function *F STOR_WOUT_PROF( <prof> ) . . . . storage without children in a function *V LEN_PROF . . . . . . . . . . . length of a profiling bag for a function ** ** With each function we associate two time measurements. First the *time ** spent by this function without its children*, i.e., the amount of time ** during which this function was active. Second the *time spent by this ** function with its children*, i.e., the amount of time during which this ** function was either active or suspended. ** ** Likewise with each function we associate the two storage measurements, ** the storage spent by this function without its children and the storage ** spent by this function with its children. ** ** These macros make it possible to access the various components of a ** profiling information bag <prof> for a function <func>. ** ** 'COUNT_PROF(<prof>)' is the number of calls to the function <func>. ** 'TIME_WITH_PROF(<prof>) is the time spent while the function <func> was ** either active or suspended. 'TIME_WOUT_PROF(<prof>)' is the time spent ** while the function <func> was active. 'STOR_WITH_PROF(<prof>)' is the ** amount of storage allocated while the function <func> was active or ** suspended. 'STOR_WOUT_PROF(<prof>)' is the amount of storage allocated ** while the function <func> was active. 'LEN_PROF' is the length of a ** profiling information bag.
*/ #define COUNT_PROF(prof) (INT_INTOBJ(ELM_PLIST(prof,1))) #define TIME_WITH_PROF(prof) (INT_INTOBJ(ELM_PLIST(prof,2))) #define TIME_WOUT_PROF(prof) (INT_INTOBJ(ELM_PLIST(prof,3))) #define STOR_WITH_PROF(prof) (UInt8_ObjInt(ELM_PLIST(prof,4))) #define STOR_WOUT_PROF(prof) (UInt8_ObjInt(ELM_PLIST(prof,5)))
/**************************************************************************** ** *F * * * * wrapper for functions with variable number of arguments * * * * *
*/
/**************************************************************************** ** *F DoWrap0args( <self> ) . . . . . . . . . . . wrap up 0 arguments in a list ** ** 'DoWrap<i>args' accepts the <i> arguments <arg1>, <arg2>, and so on, ** wraps them up in a list, and then calls <self> again via 'CALL_XARGS', ** passing this list. 'DoWrap<i>args' are the handlers for callees that ** accept a variable number of arguments. Note that there is no ** 'DoWrapXargs' handler, since in this case the function call mechanism ** already requires that the passed arguments are collected in a list.
*/ static Obj DoWrap0args(Obj self)
{
Obj result; // value of function call, result
Obj args; // arguments list
// make the arguments list
args = NEW_PLIST( T_PLIST, 0 );
// call the variable number of arguments function
result = CALL_XARGS( self, args ); return result;
}
/**************************************************************************** ** *F DoWrap1args( <self>, <arg1> ) . . . . . . . wrap up 1 argument in a list
*/ static Obj DoWrap1args(Obj self, Obj arg1)
{
Obj result; // value of function call, result
Obj args; // arguments list
// make the arguments list
args = NEW_PLIST( T_PLIST, 1 );
SET_LEN_PLIST( args, 1 );
SET_ELM_PLIST( args, 1, arg1 );
// call the variable number of arguments function
result = CALL_XARGS( self, args ); return result;
}
/**************************************************************************** ** *F DoWrap2args( <self>, <arg1>, ... ) . . . . wrap up 2 arguments in a list
*/ static Obj DoWrap2args(Obj self, Obj arg1, Obj arg2)
{
Obj result; // value of function call, result
Obj args; // arguments list
// make the arguments list
args = NEW_PLIST( T_PLIST, 2 );
SET_LEN_PLIST( args, 2 );
SET_ELM_PLIST( args, 1, arg1 );
SET_ELM_PLIST( args, 2, arg2 );
// call the variable number of arguments function
result = CALL_XARGS( self, args ); return result;
}
/**************************************************************************** ** *F DoWrap3args( <self>, <arg1>, ... ) . . . . wrap up 3 arguments in a list
*/ static Obj DoWrap3args(Obj self, Obj arg1, Obj arg2, Obj arg3)
{
Obj result; // value of function call, result
Obj args; // arguments list
// make the arguments list
args = NEW_PLIST( T_PLIST, 3 );
SET_LEN_PLIST( args, 3 );
SET_ELM_PLIST( args, 1, arg1 );
SET_ELM_PLIST( args, 2, arg2 );
SET_ELM_PLIST( args, 3, arg3 );
// call the variable number of arguments function
result = CALL_XARGS( self, args ); return result;
}
/**************************************************************************** ** *F DoWrap4args( <self>, <arg1>, ... ) . . . . wrap up 4 arguments in a list
*/ static Obj DoWrap4args(Obj self, Obj arg1, Obj arg2, Obj arg3, Obj arg4)
{
Obj result; // value of function call, result
Obj args; // arguments list
// call the variable number of arguments function
result = CALL_XARGS( self, args ); return result;
}
/**************************************************************************** ** *F * * wrapper for functions with do not support the number of arguments * *
*/
/**************************************************************************** ** *F DoFail0args( <self> ) . . . . . . fail a function call with 0 arguments ** ** 'DoFail<i>args' accepts the <i> arguments <arg1>, <arg2>, and so on, and ** signals an error, because the function for which they are installed ** expects another number of arguments. 'DoFail<i>args' are the handlers in ** the other slots of a function.
*/
// Pull this out to avoid repetition, since it gets a little more complex in // the presence of partially variadic functions
NORETURN staticvoid NargError(Obj func, Int actual)
{ Int narg = NARG_FUNC(func);
/**************************************************************************** ** *V TimeDone . . . . . . amount of time spent for completed function calls ** ** 'TimeDone' is the amount of time spent for all function calls that have ** already been completed.
*/ static UInt TimeDone;
/**************************************************************************** ** *V StorDone . . . . . amount of storage spent for completed function calls ** ** 'StorDone' is the amount of storage spent for all function call that have ** already been completed.
*/ static UInt8 StorDone;
/**************************************************************************** ** *F DoProf0args( <self> ) . . . . . . . . profile a function with 0 arguments ** ** 'DoProf<i>args' accepts the <i> arguments <arg1>, <arg2>, and so on, and ** calls the function through the secondary handler. It also updates the ** profiling information in the profiling information bag of the called ** function. 'DoProf<i>args' are the primary handlers for all functions ** when profiling is requested.
*/ static ALWAYS_INLINE Obj DoProfNNNargs (
Obj self, Int n,
Obj arg1,
Obj arg2,
Obj arg3,
Obj arg4,
Obj arg5,
Obj arg6 )
{
Obj result; // value of function call, result
Obj prof; // profiling bag
UInt timeElse; // time spent elsewhere
UInt timeCurr; // time spent in current funcs.
UInt8 storElse; // storage spent elsewhere
UInt8 storCurr; // storage spent in current funcs.
// get the profiling bag
prof = PROF_FUNC( PROF_FUNC( self ) );
// time and storage spent so far while this function what not active
timeElse = SyTime() - TIME_WITH_PROF(prof);
storElse = SizeAllBags - STOR_WITH_PROF(prof);
// time and storage spent so far by all currently suspended functions
timeCurr = SyTime() - TimeDone;
storCurr = SizeAllBags - StorDone;
// call the real function switch (n) { case 0: result = CALL_0ARGS_PROF( self ); break; case 1: result = CALL_1ARGS_PROF( self, arg1 ); break; case 2: result = CALL_2ARGS_PROF( self, arg1, arg2 ); break; case 3: result = CALL_3ARGS_PROF( self, arg1, arg2, arg3 ); break; case 4: result = CALL_4ARGS_PROF( self, arg1, arg2, arg3, arg4 ); break; case 5: result = CALL_5ARGS_PROF( self, arg1, arg2, arg3, arg4, arg5 ); break; case 6: result = CALL_6ARGS_PROF( self, arg1, arg2, arg3, arg4, arg5, arg6 ); break; case -1: result = CALL_XARGS_PROF( self, arg1 ); break; default: result = 0; GAP_ASSERT(0);
}
// number of invocation of this function
SET_COUNT_PROF( prof, COUNT_PROF(prof) + 1 );
// time and storage spent in this function and its children
SET_TIME_WITH_PROF( prof, SyTime() - timeElse );
SET_STOR_WITH_PROF( prof, SizeAllBags - storElse );
// time and storage spent by this invocation of this function
timeCurr = SyTime() - TimeDone - timeCurr;
SET_TIME_WOUT_PROF( prof, TIME_WOUT_PROF(prof) + timeCurr );
TimeDone += timeCurr;
storCurr = SizeAllBags - StorDone - storCurr;
SET_STOR_WOUT_PROF( prof, STOR_WOUT_PROF(prof) + storCurr );
StorDone += storCurr;
/**************************************************************************** ** *F InitHandlerFunc( <handler>, <cookie> ) . . . . . . . . register a handler ** ** Every handler should be registered (once) before it is installed in any ** function bag. This is needed so that it can be identified when loading a ** saved workspace. <cookie> should be a unique C string, identifying the ** handler
*/ #ifndef MAX_HANDLERS #define MAX_HANDLERS 20000 #endif
// zero handlers are used in a few odd places if ( hdlr != 0 ) { for ( i = 0; i < NHandlerFuncs; i++ ) { if ( hdlr == HandlerFuncs[i].hdlr ) break;
} if ( i == NHandlerFuncs ) {
Pr("Unregistered Handler %d args ", j, 0);
PrintObj(NAME_FUNC(bag));
Pr("\n", 0, 0);
}
}
}
}
}
staticint IsLessHandlerInfo (
TypeHandlerInfo * h1,
TypeHandlerInfo * h2,
UInt byWhat )
{ switch (byWhat) { case 1: // cast to please Irix CC and HPUX CC return (UInt)(h1->hdlr) < (UInt)(h2->hdlr); case 2: return strcmp(h1->cookie, h2->cookie) < 0; default:
ErrorQuit("Invalid sort mode %u", (Int)byWhat, 0);
}
}
void SortHandlers( UInt byWhat )
{
TypeHandlerInfo tmp;
UInt len, h, i, k; if (HandlerSortingStatus == byWhat) return;
len = NHandlerFuncs;
h = 1; while ( 9*h + 4 < len )
{ h = 3*h + 1; } while ( 0 < h ) { for ( i = h; i < len; i++ ) {
tmp = HandlerFuncs[i];
k = i; while ( h <= k && IsLessHandlerInfo(&tmp, HandlerFuncs+(k-h), byWhat))
{
HandlerFuncs[k] = HandlerFuncs[k-h];
k -= h;
}
HandlerFuncs[k] = tmp;
}
h = h / 3;
}
HandlerSortingStatus = byWhat;
}
if ( HandlerSortingStatus != 1 ) { for ( i = 0; i < NHandlerFuncs; i++ ) { if ( hdlr == HandlerFuncs[i].hdlr ) return HandlerFuncs[i].cookie;
} return (Char *)0;
} else {
top = NHandlerFuncs;
bottom = 0; while ( top >= bottom ) {
middle = (top + bottom)/2; if ( (UInt)(hdlr) < (UInt)(HandlerFuncs[middle].hdlr) )
top = middle-1; elseif ( (UInt)(hdlr) > (UInt)(HandlerFuncs[middle].hdlr) )
bottom = middle+1; else return HandlerFuncs[middle].cookie;
} return (Char *)0;
}
}
ObjFunc HandlerOfCookie( constChar * cookie )
{ Int i,top,bottom,middle; Int res; if (HandlerSortingStatus != 2)
{ for (i = 0; i < NHandlerFuncs; i++)
{ if (streq(cookie, HandlerFuncs[i].cookie)) return HandlerFuncs[i].hdlr;
} return (ObjFunc)0;
} else
{
top = NHandlerFuncs;
bottom = 0; while (top >= bottom) {
middle = (top + bottom)/2;
res = strcmp(cookie,HandlerFuncs[middle].cookie); if (res < 0)
top = middle-1; elseif (res > 0)
bottom = middle+1; else return HandlerFuncs[middle].hdlr;
} return (ObjFunc)0;
}
}
#endif
/**************************************************************************** ** *F NewFunction( <name>, <narg>, <nams>, <hdlr> ) . . . . make a new function ** ** 'NewFunction' creates and returns a new function. <name> must be a GAP ** string containing the name of the function. <narg> must be the number of ** arguments, where -1 means a variable number of arguments. <nams> must be ** a GAP list containing the names of the arguments. <hdlr> must be the ** C function (accepting <self> and the <narg> arguments) that will be ** called to execute the function.
*/
Obj NewFunction (
Obj name, Int narg,
Obj nams,
ObjFunc hdlr )
{ return NewFunctionT( T_FUNCTION, sizeof(FuncBag), name, narg, nams, hdlr );
}
/**************************************************************************** ** *F NewFunctionC( <name>, <narg>, <nams>, <hdlr> ) . . . make a new function ** ** 'NewFunctionC' does the same as 'NewFunction', but expects <name> and ** <nams> as C strings.
*/
Obj NewFunctionC ( constChar * name, Int narg, constChar * nams,
ObjFunc hdlr )
{ return NewFunction(MakeImmString(name), narg, ArgStringToList(nams), hdlr);
}
/**************************************************************************** ** *F NewFunctionT( <type>, <size>, <name>, <narg>, <nams>, <hdlr> ) ** ** 'NewFunctionT' does the same as 'NewFunction', but allows to specify the ** <type> and <size> of the newly created bag.
*/
Obj NewFunctionT (
UInt type,
UInt size,
Obj name, Int narg,
Obj nams,
ObjFunc hdlr )
{
Obj func; // function, result
Obj prof; // profiling bag
// make the function object
func = NewBag( type, size );
// create a function with a fixed number of arguments if ( narg >= 0 ) {
SET_HDLR_FUNC(func, 0, DoFail0args);
SET_HDLR_FUNC(func, 1, DoFail1args);
SET_HDLR_FUNC(func, 2, DoFail2args);
SET_HDLR_FUNC(func, 3, DoFail3args);
SET_HDLR_FUNC(func, 4, DoFail4args);
SET_HDLR_FUNC(func, 5, DoFail5args);
SET_HDLR_FUNC(func, 6, DoFail6args);
SET_HDLR_FUNC(func, 7, DoFailXargs);
SET_HDLR_FUNC(func, (narg <= 6 ? narg : 7), hdlr );
}
// enter the arguments and the names
SET_NAME_FUNC(func, name ? ImmutableString(name) : 0);
SET_NARG_FUNC(func, narg);
SET_NAMS_FUNC(func, nams);
SET_NLOC_FUNC(func, 0); #ifdef HPCGAP if (nams) MakeBagPublic(nams); #endif
CHANGED_BAG(func);
/**************************************************************************** ** *F ArgStringToList( <nams_c> ) ** ** 'ArgStringToList' takes a C string <nams_c> containing a list of comma ** separated argument names, and turns it into a plist of strings, ready ** to be passed to 'NewFunction' as <nams>.
*/
Obj ArgStringToList(constChar *nams_c) {
Obj tmp; // argument name as an object
Obj nams_o; // nams as an object
UInt len; // length
UInt i, k, l; // loop variables
// convert the arguments list to an object
len = 0; for ( k = 0; nams_c[k] != '\0'; k++ ) { if ( (0 == k || nams_c[k-1] == ' ' || nams_c[k-1] == ',')
&& ( nams_c[k ] != ' ' && nams_c[k ] != ',') ) {
len++;
}
}
nams_o = NEW_PLIST( T_PLIST, len );
SET_LEN_PLIST( nams_o, len );
k = 0; for ( i = 1; i <= len; i++ ) { while ( nams_c[k] == ' ' || nams_c[k] == ',' ) {
k++;
}
l = k; while ( nams_c[l] != ' ' && nams_c[l] != ',' && nams_c[l] != '\0' ) {
l++;
}
tmp = MakeImmStringWithLen(nams_c + k, l - k);
SET_ELM_PLIST( nams_o, i, tmp );
CHANGED_BAG( nams_o );
k = l;
}
/**************************************************************************** ** *F TypeFunction( <func> ) . . . . . . . . . . . . . . . type of a function ** ** 'TypeFunction' returns the type of the function <func>. ** ** 'TypeFunction' is the function in 'TypeObjFuncs' for functions.
*/ static Obj TYPE_FUNCTION; static Obj TYPE_OPERATION; static Obj TYPE_FUNCTION_WITH_NAME; static Obj TYPE_OPERATION_WITH_NAME;
staticvoid PrintFunction(Obj func)
{ Int narg; // number of arguments Int nloc; // number of locals
UInt i; // loop variable BOOL isvarg; // does function have varargs?
/**************************************************************************** ** *F FuncCALL_FUNC_LIST( <self>, <func>, <list> ) . . . . . . call a function ** ** 'FuncCALL_FUNC_LIST' implements the internal function 'CallFuncList'. ** ** 'CallFuncList( <func>, <list> )' ** ** 'CallFuncList' calls the function <func> with the arguments list <list>, ** i.e., it is equivalent to '<func>( <list>[1], <list>[2]... )'.
*/
Obj CallFuncListOper; static Obj CallFuncListWrapOper;
Obj CallFuncList ( Obj func, Obj list )
{
Obj result; // result
Obj list2; // list of arguments
Obj arg; // one argument
UInt i; // loop variable
/**************************************************************************** ** *F FuncNARG_FUNC( <self>, <func> ) . . . . number of arguments of a function
*/ static Obj NARG_FUNC_Oper;
/**************************************************************************** ** *F FuncNAMS_FUNC( <self>, <func> ) . . . . names of local vars of a function
*/ static Obj NAMS_FUNC_Oper;
// Returns a measure of the size of a GAP function static Obj FuncFUNC_BODY_SIZE(Obj self, Obj func)
{
RequireFunction(SELF_NAME, func);
Obj body = BODY_FUNC(func); if (body == 0) return INTOBJ_INT(0); return ObjInt_UInt(SIZE_BAG(body));
}
#ifdef GAP_ENABLE_SAVELOAD
staticvoid SaveHandler(ObjFunc hdlr)
{ constChar * cookie; if (hdlr == (ObjFunc)0)
SaveCStr(""); else {
cookie = CookieOfHandler(hdlr); if (!cookie) {
Pr("No cookie for Handler -- workspace will be corrupt\n", 0, 0);
SaveCStr("");
} else
SaveCStr(cookie);
}
}
/**************************************************************************** ** *F MarkFunctionSubBags( <bag> ) . . . . . . . marking function for functions ** ** 'MarkFunctionSubBags' is the marking function for bags of type 'T_FUNCTION'.
*/ staticvoid MarkFunctionSubBags(Obj func, void * ref)
{ // the first eight slots are pointers to C functions, so we need // to skip those for marking
UInt size = SIZE_BAG(func) / sizeof(Obj) - 8; const Bag * data = CONST_PTR_BAG(func) + 8;
MarkArrayOfBags(data, size, ref);
}
// initialise all 'Do<Something><N>args' handlers, give the most // common ones short cookies to save space in the saved workspace
InitHandlerFunc( DoFail0args, "f0" );
InitHandlerFunc( DoFail1args, "f1" );
InitHandlerFunc( DoFail2args, "f2" );
InitHandlerFunc( DoFail3args, "f3" );
InitHandlerFunc( DoFail4args, "f4" );
InitHandlerFunc( DoFail5args, "f5" );
InitHandlerFunc( DoFail6args, "f6" );
InitHandlerFunc( DoFailXargs, "f7" );
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.24Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.