forked from gap-system/gap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
calls.h
492 lines (421 loc) · 16.8 KB
/
calls.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
/****************************************************************************
**
*W calls.h GAP source Martin Schönert
**
**
*Y Copyright (C) 1996, Lehrstuhl D für Mathematik, RWTH Aachen, Germany
*Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland
*Y Copyright (C) 2002 The GAP Group
**
** 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 unneccessary 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 <src/gap.h>
#include <src/gaputils.h>
#include <src/lists.h>
#include <src/integer.h>
/****************************************************************************
**
*T ObjFunc . . . . . . . . . . . . . . . . type of function returning object
**
** 'ObjFunc' is the type of a function returning an object.
*/
typedef Obj (* ObjFunc) (/*arguments*/);
typedef Obj (* ObjFunc_0ARGS) (Obj self);
typedef Obj (* ObjFunc_1ARGS) (Obj self, Obj a1);
typedef Obj (* ObjFunc_2ARGS) (Obj self, Obj a1, Obj a2);
typedef Obj (* ObjFunc_3ARGS) (Obj self, Obj a1, Obj a2, Obj a3);
typedef Obj (* ObjFunc_4ARGS) (Obj self, Obj a1, Obj a2, Obj a3, Obj a4);
typedef Obj (* ObjFunc_5ARGS) (Obj self, Obj a1, Obj a2, Obj a3, Obj a4, Obj a5);
typedef Obj (* ObjFunc_6ARGS) (Obj self, Obj a1, Obj a2, Obj a3, Obj a4, Obj a5, Obj a6);
/****************************************************************************
**
*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
*F FEXS_FUNC(<func>) . . . . . . . . . . . . func. expr. list of a function
**
** These macros 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).
**
** 'FEXS_FUNC(<func>)' is the function expressions list (i.e., the list of
** the function expressions of the functions defined inside of <func>).
**
** '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;
Int nargs;
Obj namesOfLocals;
Obj prof;
UInt nloc;
Obj body;
Obj envi;
Obj fexs;
#ifdef HPCGAP
Obj locks;
#endif
// additional data follows for operations
} FunctionHeader;
static inline FunctionHeader * FUNC_HEADER(Obj func)
{
GAP_ASSERT(TNUM_OBJ(func) == T_FUNCTION);
return (FunctionHeader *)ADDR_OBJ(func);
}
static inline ObjFunc HDLR_FUNC(Obj func, Int i)
{
return FUNC_HEADER(func)->handlers[i];
}
static inline Obj NAME_FUNC(Obj func)
{
return FUNC_HEADER(func)->name;
}
static inline Int NARG_FUNC(Obj func)
{
return FUNC_HEADER(func)->nargs;
}
static inline Obj NAMS_FUNC(Obj func)
{
return FUNC_HEADER(func)->namesOfLocals;
}
extern Char * NAMI_FUNC(Obj func, Int i);
static inline Obj PROF_FUNC(Obj func)
{
return FUNC_HEADER(func)->prof;
}
static inline UInt NLOC_FUNC(Obj func)
{
return FUNC_HEADER(func)->nloc;
}
static inline Obj BODY_FUNC(Obj func)
{
return FUNC_HEADER(func)->body;
}
static inline Obj ENVI_FUNC(Obj func)
{
return FUNC_HEADER(func)->envi;
}
static inline Obj FEXS_FUNC(Obj func)
{
return FUNC_HEADER(func)->fexs;
}
#ifdef HPCGAP
static inline Obj LCKS_FUNC(Obj func)
{
return FUNC_HEADER(func)->locks;
}
#endif
static inline void SET_HDLR_FUNC(Obj func, Int i, ObjFunc hdlr)
{
FunctionHeader *header = FUNC_HEADER(func);
GAP_ASSERT(0 <= i && i < ARRAY_SIZE(header->handlers));
header->handlers[i] = hdlr;
}
extern void SET_NAME_FUNC(Obj func, Obj name);
static inline void SET_NARG_FUNC(Obj func, Int nargs)
{
FUNC_HEADER(func)->nargs = nargs;
}
static inline void SET_NAMS_FUNC(Obj func, Obj namesOfLocals)
{
FUNC_HEADER(func)->namesOfLocals = namesOfLocals;
}
static inline void SET_PROF_FUNC(Obj func, Obj prof)
{
FUNC_HEADER(func)->prof = prof;
}
static inline void SET_NLOC_FUNC(Obj func, UInt nloc)
{
FUNC_HEADER(func)->nloc = nloc;
}
static inline void SET_BODY_FUNC(Obj func, Obj body)
{
GAP_ASSERT(TNUM_OBJ(body) == T_BODY);
FUNC_HEADER(func)->body = body;
}
static inline void SET_ENVI_FUNC(Obj func, Obj envi)
{
FUNC_HEADER(func)->envi = envi;
}
static inline void SET_FEXS_FUNC(Obj func, Obj fexs)
{
FUNC_HEADER(func)->fexs = fexs;
}
#ifdef HPCGAP
static inline void SET_LCKS_FUNC(Obj func, Obj locks)
{
FUNC_HEADER(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.
*/
extern Int IsKernelFunction(Obj func);
#define HDLR_0ARGS(func) ((ObjFunc_0ARGS)HDLR_FUNC(func,0))
#define HDLR_1ARGS(func) ((ObjFunc_1ARGS)HDLR_FUNC(func,1))
#define HDLR_2ARGS(func) ((ObjFunc_2ARGS)HDLR_FUNC(func,2))
#define HDLR_3ARGS(func) ((ObjFunc_3ARGS)HDLR_FUNC(func,3))
#define HDLR_4ARGS(func) ((ObjFunc_4ARGS)HDLR_FUNC(func,4))
#define HDLR_5ARGS(func) ((ObjFunc_5ARGS)HDLR_FUNC(func,5))
#define HDLR_6ARGS(func) ((ObjFunc_6ARGS)HDLR_FUNC(func,6))
#define HDLR_XARGS(func) ((ObjFunc_1ARGS)HDLR_FUNC(func,7))
extern Obj NargError(Obj func, Int actual);
/****************************************************************************
**
*F IS_FUNC( <obj> ) . . . . . . . . . . . . . check if object is a function
*/
#define IS_FUNC(obj) (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.
*/
#define CALL_0ARGS(f) HDLR_0ARGS(f)(f)
#define CALL_1ARGS(f,a1) HDLR_1ARGS(f)(f,a1)
#define CALL_2ARGS(f,a1,a2) HDLR_2ARGS(f)(f,a1,a2)
#define CALL_3ARGS(f,a1,a2,a3) HDLR_3ARGS(f)(f,a1,a2,a3)
#define CALL_4ARGS(f,a1,a2,a3,a4) HDLR_4ARGS(f)(f,a1,a2,a3,a4)
#define CALL_5ARGS(f,a1,a2,a3,a4,a5) HDLR_5ARGS(f)(f,a1,a2,a3,a4,a5)
#define CALL_6ARGS(f,a1,a2,a3,a4,a5,a6) HDLR_6ARGS(f)(f,a1,a2,a3,a4,a5,a6)
#define CALL_XARGS(f,as) 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 args
*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.
*/
#define CALL_0ARGS_PROF(f) \
HDLR_0ARGS(PROF_FUNC(f))(f)
#define CALL_1ARGS_PROF(f,a1) \
HDLR_1ARGS(PROF_FUNC(f))(f,a1)
#define CALL_2ARGS_PROF(f,a1,a2) \
HDLR_2ARGS(PROF_FUNC(f))(f,a1,a2)
#define CALL_3ARGS_PROF(f,a1,a2,a3) \
HDLR_3ARGS(PROF_FUNC(f))(f,a1,a2,a3)
#define CALL_4ARGS_PROF(f,a1,a2,a3,a4) \
HDLR_4ARGS(PROF_FUNC(f))(f,a1,a2,a3,a4)
#define CALL_5ARGS_PROF(f,a1,a2,a3,a4,a5) \
HDLR_5ARGS(PROF_FUNC(f))(f,a1,a2,a3,a4,a5)
#define CALL_6ARGS_PROF(f,a1,a2,a3,a4,a5,a6) \
HDLR_6ARGS(PROF_FUNC(f))(f,a1,a2,a3,a4,a5,a6)
#define CALL_XARGS_PROF(f,as) \
HDLR_XARGS(PROF_FUNC(f))(f,as)
/****************************************************************************
**
*F FuncFILENAME_FUNC(Obj self, Obj func) . . . . . . . filename of function
*F FuncSTARTLINE_FUNC(Obj self, Obj func) . . . . . start line of function
*F FuncENDLINE_FUNC(Obj self, Obj func) . . . . . . . end line of function
**
** These functions, usually exported to GAP, get information about GAP
** functions */
Obj FuncFILENAME_FUNC(Obj self, Obj func);
Obj FuncSTARTLINE_FUNC(Obj self, Obj func);
Obj FuncENDLINE_FUNC(Obj self, Obj func);
/****************************************************************************
**
*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
*/
extern void InitHandlerFunc (
ObjFunc hdlr,
const Char * cookie );
extern const Char * CookieOfHandler(
ObjFunc hdlr );
extern ObjFunc HandlerOfCookie (
const Char * cookie );
extern void SortHandlers( UInt byWhat );
/****************************************************************************
**
*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> )
*F NewFunctionCT( <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 containg 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.
**
** 'NewFunctionCT' does the same as 'NewFunction', but expects <name> and
** <nams> as C strings, and allows to specify the <type> and <size> of the
** newly created bag.
*/
extern Obj NewFunction (
Obj name,
Int narg,
Obj nams,
ObjFunc hdlr );
extern Obj NewFunctionC (
const Char * name,
Int narg,
const Char * nams,
ObjFunc hdlr );
extern Obj NewFunctionT (
UInt type,
UInt size,
Obj name,
Int narg,
Obj nams,
ObjFunc hdlr );
extern Obj NewFunctionCT (
UInt type,
UInt size,
const Char * name,
Int narg,
const Char * 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>.
*/
extern Obj ArgStringToList(const Char *nams_c);
/****************************************************************************
**
*F * * * * * * * * * * * * * type and print function * * * * * * * * * * * *
*/
/****************************************************************************
**
*F PrintFunction( <func> ) . . . . . . . . . . . . . . . print a function
**
** 'PrintFunction' prints the function <func> .
*/
extern void PrintFunction (
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]... )'.
*/
extern Obj CallFuncList(
Obj func,
Obj list);
extern Obj CallFuncListOper;
/****************************************************************************
**
*F * * * * * * * * * * * * * initialize package * * * * * * * * * * * * * * *
*/
/****************************************************************************
**
*F InitInfoCalls() . . . . . . . . . . . . . . . . . table of init functions
*/
StructInitInfo * InitInfoCalls ( void );
#endif // GAP_CALLS_H