/****************************************************************************
* *
* * 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 declares the functions of the generic function call mechanism
* * package .
* *
* * This package defines the * call mechanism * through which one GAP function ,
* * named the * caller * , can temporarily transfer control to another function ,
* * named the * callee * .
* *
* * There are * compiled functions * and * interpreted functions * . Thus there
* * are four possible pairings of caller and callee .
* *
* * If the caller is compiled , then the call comes directly from the caller .
* * If it is interpreted , then the call comes from one of the functions
* * ' EvalFunccall < i > args ' that implement evaluation of function calls .
* *
* * If the callee is compiled , then the call goes directly to the callee .
* * If it is interpreted , then the call goes to one of the handlers
* * ' DoExecFunc < i > args ' that implement execution of function bodies .
* *
* * The call mechanism makes it in any case unnecessary for the calling code
* * to know whether the callee is a compiled or an interpreted function .
* * Likewise the called code need not know , actually cannot know , whether the
* * caller is a compiled or an interpreted function .
* *
* * Also the call mechanism checks that the number of arguments passed by the
* * caller is the same as the number of arguments expected by the callee , or
* * it collects the arguments in a list if the callee allows a variable
* * number of arguments .
* *
* * Finally the call mechanism profiles all functions if requested .
* *
* * All this has very little overhead . In the case of one compiled function
* * calling another compiled function , which expects fewer than 4 arguments ,
* * with no profiling , the overhead is only a couple of instructions .
*/
#ifndef GAP_CALLS_H
#define GAP_CALLS_H
#include "gaputils.h"
#include "objects.h"
/****************************************************************************
* *
* F HDLR_FUNC ( < func > , < i > ) . . . . . . . . . < i > - th call handler of a function
* F NAME_FUNC ( < func > ) . . . . . . . . . . . . . . . . . . name of a function
* F NARG_FUNC ( < func > ) . . . . . . . . . . . number of arguments of a function
* F NAMS_FUNC ( < func > ) . . . . . . . . names of local variables of a function
* F NAMI_FUNC ( < func > ) . . . . . . name of < i > - th local variable of a function
* F PROF_FUNC ( < func > ) . . . . . . . . profiling information bag of a function
* F NLOC_FUNC ( < func > ) . . . . . . . . . . . . number of locals of a function
* F BODY_FUNC ( < func > ) . . . . . . . . . . . . . . . . . . body of a function
* F ENVI_FUNC ( < func > ) . . . . . . . . . . . . . . . environment of a function
* *
* * These functions make it possible to access the various components of a
* * function .
* *
* * ' HDLR_FUNC ( < func > , < i > ) ' is the < i > - th handler of the function < func > .
* *
* * ' NAME_FUNC ( < func > ) ' is the name of the function .
* *
* * ' NARG_FUNC ( < func > ) ' is the number of arguments ( - 1 if < func > accepts a
* * variable number of arguments ) .
* *
* * ' NAMS_FUNC ( < func > ) ' is the list of the names of the local variables ,
* *
* * ' NAMI_FUNC ( < func > , < i > ) ' is the name of the < i > - th local variable .
* *
* * ' PROF_FUNC ( < func > ) ' is the profiling information bag .
* *
* * ' NLOC_FUNC ( < func > ) ' is the number of local variables of the interpreted
* * function < func > .
* *
* * ' BODY_FUNC ( < func > ) ' is the body .
* *
* * ' ENVI_FUNC ( < func > ) ' is the environment ( i . e . , the local variables bag )
* * that was current when < func > was created .
* *
* * ' LCKS_FUNC ( < func > ) ' is a string that contains the lock mode for the
* * arguments of < func > . Each byte corresponds to the mode for an argument :
* * 0 means no lock , 1 means a read - only lock , 2 means a read - write lock .
* * The value of the bag can be null , in which case no argument requires a
* * lock . Only used in HPC - GAP .
*/
typedef struct {
ObjFunc handlers[8 ];
Obj name;
Obj nargs;
Obj namesOfArgsAndLocals;
Obj prof;
Obj nloc;
Obj body;
Obj envi;
#ifdef HPCGAP
Obj locks;
#endif
// additional data follows for operations
} FuncBag;
EXPORT_INLINE FuncBag * FUNC(Obj func)
{
GAP_ASSERT(TNUM_OBJ(func) == T_FUNCTION);
return (FuncBag *)ADDR_OBJ(func);
}
EXPORT_INLINE const FuncBag * CONST_FUNC(Obj func)
{
GAP_ASSERT(TNUM_OBJ(func) == T_FUNCTION);
return (const FuncBag *)CONST_ADDR_OBJ(func);
}
EXPORT_INLINE ObjFunc HDLR_FUNC(Obj func, Int i)
{
GAP_ASSERT(0 <= i && i < 8 );
return CONST_FUNC(func)->handlers[i];
}
EXPORT_INLINE Obj NAME_FUNC(Obj func)
{
return CONST_FUNC(func)->name;
}
EXPORT_INLINE Int NARG_FUNC(Obj func)
{
return INT_INTOBJ(CONST_FUNC(func)->nargs);
}
EXPORT_INLINE Obj NAMS_FUNC(Obj func)
{
return CONST_FUNC(func)->namesOfArgsAndLocals;
}
Obj NAMI_FUNC(Obj func, Int i);
EXPORT_INLINE Obj PROF_FUNC(Obj func)
{
return CONST_FUNC(func)->prof;
}
EXPORT_INLINE UInt NLOC_FUNC(Obj func)
{
return INT_INTOBJ(CONST_FUNC(func)->nloc);
}
EXPORT_INLINE Obj BODY_FUNC(Obj func)
{
return CONST_FUNC(func)->body;
}
EXPORT_INLINE Obj ENVI_FUNC(Obj func)
{
return CONST_FUNC(func)->envi;
}
#ifdef HPCGAP
EXPORT_INLINE Obj LCKS_FUNC(Obj func)
{
return CONST_FUNC(func)->locks;
}
#endif
EXPORT_INLINE void SET_HDLR_FUNC(Obj func, Int i, ObjFunc hdlr)
{
GAP_ASSERT(0 <= i && i < 8 );
FUNC(func)->handlers[i] = hdlr;
}
void SET_NAME_FUNC(Obj func, Obj name);
EXPORT_INLINE void SET_NARG_FUNC(Obj func, Int nargs)
{
FUNC(func)->nargs = INTOBJ_INT(nargs);
}
EXPORT_INLINE void SET_NAMS_FUNC(Obj func, Obj namesOfArgsAndLocals)
{
FUNC(func)->namesOfArgsAndLocals = namesOfArgsAndLocals;
}
EXPORT_INLINE void SET_PROF_FUNC(Obj func, Obj prof)
{
FUNC(func)->prof = prof;
}
EXPORT_INLINE void SET_NLOC_FUNC(Obj func, UInt nloc)
{
FUNC(func)->nloc = INTOBJ_INT(nloc);
}
EXPORT_INLINE void SET_BODY_FUNC(Obj func, Obj body)
{
GAP_ASSERT(TNUM_OBJ(body) == T_BODY);
FUNC(func)->body = body;
}
EXPORT_INLINE void SET_ENVI_FUNC(Obj func, Obj envi)
{
FUNC(func)->envi = envi;
}
#ifdef HPCGAP
EXPORT_INLINE void SET_LCKS_FUNC(Obj func, Obj locks)
{
FUNC(func)->locks = locks;
}
#endif
/****************************************************************************
*
* F IsKernelFunction ( < func > )
* *
* * ' IsKernelFunction ' returns 1 if < func > is a kernel function ( i . e .
* * compiled from C code ) , and 0 otherwise .
*/
BOOL IsKernelFunction(Obj func);
EXPORT_INLINE ObjFunc_0ARGS HDLR_0ARGS(Obj func)
{
return (ObjFunc_0ARGS)(void *)HDLR_FUNC(func, 0 );
}
EXPORT_INLINE ObjFunc_1ARGS HDLR_1ARGS(Obj func)
{
return (ObjFunc_1ARGS)(void *)HDLR_FUNC(func, 1 );
}
EXPORT_INLINE ObjFunc_2ARGS HDLR_2ARGS(Obj func)
{
return (ObjFunc_2ARGS)(void *)HDLR_FUNC(func, 2 );
}
EXPORT_INLINE ObjFunc_3ARGS HDLR_3ARGS(Obj func)
{
return (ObjFunc_3ARGS)(void *)HDLR_FUNC(func, 3 );
}
EXPORT_INLINE ObjFunc_4ARGS HDLR_4ARGS(Obj func)
{
return (ObjFunc_4ARGS)(void *)HDLR_FUNC(func, 4 );
}
EXPORT_INLINE ObjFunc_5ARGS HDLR_5ARGS(Obj func)
{
return (ObjFunc_5ARGS)(void *)HDLR_FUNC(func, 5 );
}
EXPORT_INLINE ObjFunc_6ARGS HDLR_6ARGS(Obj func)
{
return (ObjFunc_6ARGS)(void *)HDLR_FUNC(func, 6 );
}
EXPORT_INLINE ObjFunc_1ARGS HDLR_XARGS(Obj func)
{
return (ObjFunc_1ARGS)(void *)HDLR_FUNC(func, 7 );
}
/****************************************************************************
* *
* F IS_FUNC ( < obj > ) . . . . . . . . . . . . . check if object is a function
*/
EXPORT_INLINE BOOL IS_FUNC(Obj obj)
{
return TNUM_OBJ(obj) == T_FUNCTION;
}
/****************************************************************************
* *
* F CALL_0ARGS ( < func > ) . . . . . . . . . call a function with 0 arguments
* F CALL_1ARGS ( < func > , < arg1 > ) . . . . . . call a function with 1 arguments
* F CALL_2ARGS ( < func > , < arg1 > . . . ) . . . . call a function with 2 arguments
* F CALL_3ARGS ( < func > , < arg1 > . . . ) . . . . call a function with 3 arguments
* F CALL_4ARGS ( < func > , < arg1 > . . . ) . . . . call a function with 4 arguments
* F CALL_5ARGS ( < func > , < arg1 > . . . ) . . . . call a function with 5 arguments
* F CALL_6ARGS ( < func > , < arg1 > . . . ) . . . . call a function with 6 arguments
* F CALL_XARGS ( < func > , < args > ) . . . . . . call a function with more arguments
* *
* * ' CALL_ < i > ARGS ' passes control to the function < func > , which must be a
* * function object ( ' T_FUNCTION ' ) . It returns the return value of < func > .
* * ' CALL_0ARGS ' is for calls passing no arguments , ' CALL_1ARGS ' for calls
* * passing one argument , and so on . ' CALL_XARGS ' is for calls passing more
* * than 5 arguments , where the arguments must be collected in a plain list ,
* * and this plain list must then be passed .
* *
* * ' CALL_ < i > ARGS ' can be used independently of whether the called function
* * is a compiled or interpreted function . It checks that the number of
* * passed arguments is the same as the number of arguments expected by the
* * callee , or it collects the arguments in a list if the callee allows a
* * variable number of arguments .
*/
EXPORT_INLINE Obj CALL_0ARGS(Obj f)
{
return HDLR_0ARGS(f)(f);
}
EXPORT_INLINE Obj CALL_1ARGS(Obj f, Obj a1)
{
return HDLR_1ARGS(f)(f, a1);
}
EXPORT_INLINE Obj CALL_2ARGS(Obj f, Obj a1, Obj a2)
{
return HDLR_2ARGS(f)(f, a1, a2);
}
EXPORT_INLINE Obj CALL_3ARGS(Obj f, Obj a1, Obj a2, Obj a3)
{
return HDLR_3ARGS(f)(f, a1, a2, a3);
}
EXPORT_INLINE Obj CALL_4ARGS(Obj f, Obj a1, Obj a2, Obj a3, Obj a4)
{
return HDLR_4ARGS(f)(f, a1, a2, a3, a4);
}
EXPORT_INLINE Obj CALL_5ARGS(Obj f, Obj a1, Obj a2, Obj a3, Obj a4, Obj a5)
{
return HDLR_5ARGS(f)(f, a1, a2, a3, a4, a5);
}
EXPORT_INLINE Obj CALL_6ARGS(Obj f, Obj a1, Obj a2, Obj a3, Obj a4, Obj a5, Obj a6)
{
return HDLR_6ARGS(f)(f, a1, a2, a3, a4, a5, a6);
}
EXPORT_INLINE Obj CALL_XARGS(Obj f, Obj as)
{
return HDLR_XARGS(f)(f, as);
}
/****************************************************************************
* *
* F CALL_0ARGS_PROF ( < func > , < arg1 > ) . . . . . call a prof func with 0 args
* F CALL_1ARGS_PROF ( < func > , < arg1 > , . . . ) . . call a prof func with 1 arg
* F CALL_2ARGS_PROF ( < func > , < arg1 > , . . . ) . . call a prof func with 2 args
* F CALL_3ARGS_PROF ( < func > , < arg1 > , . . . ) . . call a prof func with 3 args
* F CALL_4ARGS_PROF ( < func > , < arg1 > , . . . ) . . call a prof func with 4 args
* F CALL_5ARGS_PROF ( < func > , < arg1 > , . . . ) . . call a prof func with 5 args
* F CALL_6ARGS_PROF ( < func > , < arg1 > , . . . ) . . call a prof func with 6 args
* F CALL_XARGS_PROF ( < func > , < arg1 > , . . . ) . . call a prof func with X args
* *
* * ' CALL_ < i > ARGS_PROF ' is used in the profile handler ' DoProf < i > args ' to
* * call the real handler stored in the profiling information of the
* * function .
*/
EXPORT_INLINE Obj CALL_0ARGS_PROF(Obj f)
{
return HDLR_0ARGS(PROF_FUNC(f))(f);
}
EXPORT_INLINE Obj CALL_1ARGS_PROF(Obj f, Obj a1)
{
return HDLR_1ARGS(PROF_FUNC(f))(f, a1);
}
EXPORT_INLINE Obj CALL_2ARGS_PROF(Obj f, Obj a1, Obj a2)
{
return HDLR_2ARGS(PROF_FUNC(f))(f, a1, a2);
}
EXPORT_INLINE Obj CALL_3ARGS_PROF(Obj f, Obj a1, Obj a2, Obj a3)
{
return HDLR_3ARGS(PROF_FUNC(f))(f, a1, a2, a3);
}
EXPORT_INLINE Obj CALL_4ARGS_PROF(Obj f, Obj a1, Obj a2, Obj a3, Obj a4)
{
return HDLR_4ARGS(PROF_FUNC(f))(f, a1, a2, a3, a4);
}
EXPORT_INLINE Obj CALL_5ARGS_PROF(Obj f, Obj a1, Obj a2, Obj a3, Obj a4, Obj a5)
{
return HDLR_5ARGS(PROF_FUNC(f))(f, a1, a2, a3, a4, a5);
}
EXPORT_INLINE Obj CALL_6ARGS_PROF(Obj f, Obj a1, Obj a2, Obj a3, Obj a4, Obj a5, Obj a6)
{
return HDLR_6ARGS(PROF_FUNC(f))(f, a1, a2, a3, a4, a5, a6);
}
EXPORT_INLINE Obj CALL_XARGS_PROF(Obj f, Obj as)
{
return HDLR_XARGS(PROF_FUNC(f))(f, as);
}
/****************************************************************************
* *
* F * * * * * * * * * * * * * create a new function * * * * * * * * * * * * *
*/
/****************************************************************************
* *
* 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
*/
void InitHandlerFunc(ObjFunc hdlr, const Char * cookie);
#ifdef USE_GASMAN
const Char * CookieOfHandler(ObjFunc hdlr);
ObjFunc HandlerOfCookie(const Char * cookie);
void SortHandlers(UInt byWhat);
void CheckAllHandlers(void );
#endif
/****************************************************************************
* *
* F NewFunction ( < name > , < narg > , < nams > , < hdlr > ) . . . make a new function
* F NewFunctionC ( < name > , < narg > , < nams > , < hdlr > ) . . . make a new function
* F NewFunctionT ( < type > , < size > , < name > , < narg > , < nams > , < hdlr > )
* *
* * ' 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 .
* *
* * ' NewFunctionC ' does the same as ' NewFunction ' , but expects < name > and
* * < nams > as C strings .
* *
* * ' NewFunctionT ' does the same as ' NewFunction ' , but allows to specify the
* * < type > and < size > of the newly created bag .
*/
Obj NewFunction(Obj name, Int narg, Obj nams, ObjFunc hdlr);
Obj NewFunctionC(const Char * name,
Int narg,
const Char * nams,
ObjFunc hdlr);
Obj NewFunctionT(
UInt type, UInt size, Obj name, Int narg, Obj nams, ObjFunc hdlr);
/****************************************************************************
* *
* 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(const Char * nams_c);
/****************************************************************************
* *
* F * * * * * * * * * * * * * type and print function * * * * * * * * * * * *
*/
void PrintKernelFunction(Obj func);
/****************************************************************************
* *
* * ' 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 CallFuncList(Obj func, Obj list);
extern Obj CallFuncListOper;
/****************************************************************************
* *
* F * * * * * * * * * * * * * initialize module * * * * * * * * * * * * * * *
*/
/****************************************************************************
* *
* F InitInfoCalls ( ) . . . . . . . . . . . . . . . . . table of init functions
*/
StructInitInfo * InitInfoCalls ( void );
#endif // GAP_CALLS_H
Messung V0.5 in Prozent C=97 H=100 G=98
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet am 2026-09-27)
¤
*© Formatika GbR, Deutschland