Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

Path: gap4r8 / src / funcs.c
Views: 415065
1
/****************************************************************************
2
**
3
*W funcs.c GAP source Martin Schönert
4
**
5
**
6
*Y Copyright (C) 1996, Lehrstuhl D für Mathematik, RWTH Aachen, Germany
7
*Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland
8
*Y Copyright (C) 2002 The GAP Group
9
**
10
** This file contains the functions of the function interpreter package.
11
**
12
** The function interpreter package contains the executors for procedure
13
** calls, the evaluators for function calls, the evaluator for function
14
** expressions, and the handlers for the execution of function bodies.
15
**
16
** It uses the function call mechanism defined by the calls package.
17
*/
18
#include <stdio.h> /* on SunOS, assert.h uses stderr
19
but does not include stdio.h */
20
#include <assert.h> /* assert */
21
#include "system.h" /* Ints, UInts */
22
#include "bool.h"
23
24
25
#include "gasman.h" /* garbage collector */
26
#include "objects.h" /* objects */
27
#include "scanner.h" /* scanner */
28
29
#include "gap.h" /* error handling, initialisation */
30
31
#include "string.h" /* strings */
32
#include "calls.h" /* generic call mechanism */
33
34
#include "code.h" /* coder */
35
#include "exprs.h" /* expressions */
36
#include "stats.h" /* statements */
37
38
#include "funcs.h" /* functions */
39
40
#include "read.h" /* read expressions */
41
#include "records.h" /* generic records */
42
#include "precord.h" /* plain records */
43
44
#include "lists.h" /* generic lists */
45
#include "plist.h" /* plain lists */
46
47
48
#include "saveload.h" /* saving and loading */
49
50
#include "opers.h" /* generic operations */
51
#include "gvars.h"
52
#include "thread.h" /* threads */
53
#include "tls.h" /* thread-local storage */
54
55
#include "vars.h" /* variables */
56
57
58
#include "profile.h" /* installing methods */
59
/****************************************************************************
60
**
61
*F ExecProccallOpts( <call> ). . execute a procedure call with options
62
**
63
** Calls with options are wrapped in an outer statement, which is
64
** handled here
65
*/
66
67
static Obj PushOptions;
68
static Obj PopOptions;
69
70
UInt ExecProccallOpts(
71
Stat call )
72
{
73
Obj opts;
74
75
SET_BRK_CURR_STAT( call );
76
opts = EVAL_EXPR( ADDR_STAT(call)[0] );
77
CALL_1ARGS(PushOptions, opts);
78
79
EXEC_STAT( ADDR_STAT( call )[1]);
80
81
CALL_0ARGS(PopOptions);
82
83
return 0;
84
}
85
86
87
/****************************************************************************
88
**
89
*F ExecProccall0args(<call>) . execute a procedure call with 0 arguments
90
*F ExecProccall1args(<call>) . execute a procedure call with 1 arguments
91
*F ExecProccall2args(<call>) . execute a procedure call with 2 arguments
92
*F ExecProccall3args(<call>) . execute a procedure call with 3 arguments
93
*F ExecProccall4args(<call>) . execute a procedure call with 4 arguments
94
*F ExecProccall5args(<call>) . execute a procedure call with 5 arguments
95
*F ExecProccall6args(<call>) . execute a procedure call with 6 arguments
96
*F ExecProccallXargs(<call>) . execute a procedure call with more arguments
97
**
98
** 'ExecProccall<i>args' executes a procedure call to the function
99
** 'FUNC_CALL(<call>)' with the arguments 'ARGI_CALL(<call>,1)' to
100
** 'ARGI_CALL(<call>,<i>)'. It returns the value returned by the function.
101
*/
102
103
static Obj DispatchFuncCall( Obj func, Int nargs, Obj arg1, Obj arg2, Obj arg3, Obj arg4, Obj arg5, Obj arg6)
104
{
105
Obj arglist;
106
if (nargs != -1) {
107
arglist = NEW_PLIST(T_PLIST_DENSE, nargs);
108
SET_LEN_PLIST(arglist, nargs);
109
switch(nargs) {
110
case 6:
111
SET_ELM_PLIST(arglist,6, arg6);
112
case 5:
113
SET_ELM_PLIST(arglist,5, arg5);
114
case 4:
115
SET_ELM_PLIST(arglist,4, arg4);
116
case 3:
117
SET_ELM_PLIST(arglist,3, arg3);
118
case 2:
119
SET_ELM_PLIST(arglist,2, arg2);
120
case 1:
121
SET_ELM_PLIST(arglist,1, arg1);
122
case 0:
123
CHANGED_BAG(arglist);
124
}
125
} else {
126
arglist = arg1;
127
}
128
return DoOperation2Args(CallFuncListOper, func, arglist);
129
}
130
131
132
UInt ExecProccall0args (
133
Stat call )
134
{
135
Obj func; /* function */
136
137
/* evaluate the function */
138
SET_BRK_CURR_STAT( call );
139
func = EVAL_EXPR( FUNC_CALL( call ) );
140
141
/* call the function */
142
SET_BRK_CALL_TO( call );
143
if (TNUM_OBJ(func) != T_FUNCTION)
144
DispatchFuncCall(func, 0, (Obj) 0L, (Obj) 0L, (Obj) 0L, (Obj) 0L, (Obj) 0L, (Obj) 0L);
145
else {
146
CALL_0ARGS( func );
147
}
148
if (TLS(UserHasQuit) || TLS(UserHasQUIT)) /* the procedure must have called
149
READ() and the user quit from a break
150
loop inside it */
151
ReadEvalError();
152
/* return 0 (to indicate that no leave-statement was executed) */
153
return 0;
154
}
155
156
UInt ExecProccall1args (
157
Stat call )
158
{
159
Obj func; /* function */
160
Obj arg1; /* first argument */
161
162
/* evaluate the function */
163
SET_BRK_CURR_STAT( call );
164
func = EVAL_EXPR( FUNC_CALL( call ) );
165
166
/* evaluate the arguments */
167
arg1 = EVAL_EXPR( ARGI_CALL( call, 1 ) );
168
169
/* call the function */
170
if (TNUM_OBJ(func) != T_FUNCTION)
171
DispatchFuncCall(func, 1, (Obj) arg1, (Obj) 0L, (Obj) 0L, (Obj) 0L, (Obj) 0L, (Obj) 0L);
172
else {
173
SET_BRK_CALL_TO( call );
174
CALL_1ARGS( func, arg1 );
175
}
176
if (TLS(UserHasQuit) || TLS(UserHasQUIT)) /* the procedure must have called
177
READ() and the user quit from a break
178
loop inside it */
179
ReadEvalError();
180
/* return 0 (to indicate that no leave-statement was executed) */
181
return 0;
182
}
183
184
UInt ExecProccall2args (
185
Stat call )
186
{
187
Obj func; /* function */
188
Obj arg1; /* first argument */
189
Obj arg2; /* second argument */
190
191
/* evaluate the function */
192
SET_BRK_CURR_STAT( call );
193
func = EVAL_EXPR( FUNC_CALL( call ) );
194
195
/* evaluate the arguments */
196
arg1 = EVAL_EXPR( ARGI_CALL( call, 1 ) );
197
arg2 = EVAL_EXPR( ARGI_CALL( call, 2 ) );
198
199
/* call the function */
200
if (TNUM_OBJ(func) != T_FUNCTION)
201
DispatchFuncCall(func, 2, (Obj) arg1, (Obj) arg2, (Obj) 0L, (Obj) 0L, (Obj) 0L, (Obj) 0L);
202
else {
203
SET_BRK_CALL_TO( call );
204
CALL_2ARGS( func, arg1, arg2 );
205
}
206
if (TLS(UserHasQuit) || TLS(UserHasQUIT)) /* the procedure must have called
207
READ() and the user quit from a break
208
loop inside it */
209
ReadEvalError();
210
/* return 0 (to indicate that no leave-statement was executed) */
211
return 0;
212
}
213
214
UInt ExecProccall3args (
215
Stat call )
216
{
217
Obj func; /* function */
218
Obj arg1; /* first argument */
219
Obj arg2; /* second argument */
220
Obj arg3; /* third argument */
221
222
/* evaluate the function */
223
SET_BRK_CURR_STAT( call );
224
func = EVAL_EXPR( FUNC_CALL( call ) );
225
226
/* evaluate the arguments */
227
arg1 = EVAL_EXPR( ARGI_CALL( call, 1 ) );
228
arg2 = EVAL_EXPR( ARGI_CALL( call, 2 ) );
229
arg3 = EVAL_EXPR( ARGI_CALL( call, 3 ) );
230
231
/* call the function */
232
if (TNUM_OBJ(func) != T_FUNCTION)
233
DispatchFuncCall(func, 3, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) 0L, (Obj) 0L, (Obj) 0L);
234
else {
235
SET_BRK_CALL_TO( call );
236
CALL_3ARGS( func, arg1, arg2, arg3 );
237
}
238
if (TLS(UserHasQuit) || TLS(UserHasQUIT)) /* the procedure must have called
239
READ() and the user quit from a break
240
loop inside it */
241
ReadEvalError();
242
/* return 0 (to indicate that no leave-statement was executed) */
243
return 0;
244
}
245
246
UInt ExecProccall4args (
247
Stat call )
248
{
249
Obj func; /* function */
250
Obj arg1; /* first argument */
251
Obj arg2; /* second argument */
252
Obj arg3; /* third argument */
253
Obj arg4; /* fourth argument */
254
255
/* evaluate the function */
256
SET_BRK_CURR_STAT( call );
257
func = EVAL_EXPR( FUNC_CALL( call ) );
258
259
/* evaluate the arguments */
260
arg1 = EVAL_EXPR( ARGI_CALL( call, 1 ) );
261
arg2 = EVAL_EXPR( ARGI_CALL( call, 2 ) );
262
arg3 = EVAL_EXPR( ARGI_CALL( call, 3 ) );
263
arg4 = EVAL_EXPR( ARGI_CALL( call, 4 ) );
264
265
/* call the function */
266
if (TNUM_OBJ(func) != T_FUNCTION)
267
DispatchFuncCall(func, 4, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) arg4, (Obj) 0, (Obj) 0);
268
else {
269
SET_BRK_CALL_TO( call );
270
CALL_4ARGS( func, arg1, arg2, arg3, arg4 );
271
}
272
if (TLS(UserHasQuit) || TLS(UserHasQUIT)) /* the procedure must have called
273
READ() and the user quit from a break
274
loop inside it */
275
ReadEvalError();
276
/* return 0 (to indicate that no leave-statement was executed) */
277
return 0;
278
}
279
280
UInt ExecProccall5args (
281
Stat call )
282
{
283
Obj func; /* function */
284
Obj arg1; /* first argument */
285
Obj arg2; /* second argument */
286
Obj arg3; /* third argument */
287
Obj arg4; /* fourth argument */
288
Obj arg5; /* fifth argument */
289
290
/* evaluate the function */
291
SET_BRK_CURR_STAT( call );
292
func = EVAL_EXPR( FUNC_CALL( call ) );
293
while ( TNUM_OBJ( func ) != T_FUNCTION ) {
294
func = ErrorReturnObj(
295
"Function Calls: <func> must be a function (not a %s)",
296
(Int)TNAM_OBJ(func), 0L,
297
"you can replace <func> via 'return <func>;'" );
298
}
299
300
/* evaluate the arguments */
301
arg1 = EVAL_EXPR( ARGI_CALL( call, 1 ) );
302
arg2 = EVAL_EXPR( ARGI_CALL( call, 2 ) );
303
arg3 = EVAL_EXPR( ARGI_CALL( call, 3 ) );
304
arg4 = EVAL_EXPR( ARGI_CALL( call, 4 ) );
305
arg5 = EVAL_EXPR( ARGI_CALL( call, 5 ) );
306
307
/* call the function */
308
if (TNUM_OBJ(func) != T_FUNCTION)
309
DispatchFuncCall(func, 5, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) arg4, (Obj) arg5, (Obj) 0L);
310
else {
311
SET_BRK_CALL_TO( call );
312
CALL_5ARGS( func, arg1, arg2, arg3, arg4, arg5 );
313
}
314
if (TLS(UserHasQuit) || TLS(UserHasQUIT)) /* the procedure must have called
315
READ() and the user quit from a break
316
loop inside it */
317
ReadEvalError();
318
/* return 0 (to indicate that no leave-statement was executed) */
319
return 0;
320
}
321
322
UInt ExecProccall6args (
323
Stat call )
324
{
325
Obj func; /* function */
326
Obj arg1; /* first argument */
327
Obj arg2; /* second argument */
328
Obj arg3; /* third argument */
329
Obj arg4; /* fourth argument */
330
Obj arg5; /* fifth argument */
331
Obj arg6; /* sixth argument */
332
333
/* evaluate the function */
334
SET_BRK_CURR_STAT( call );
335
func = EVAL_EXPR( FUNC_CALL( call ) );
336
337
/* evaluate the arguments */
338
arg1 = EVAL_EXPR( ARGI_CALL( call, 1 ) );
339
arg2 = EVAL_EXPR( ARGI_CALL( call, 2 ) );
340
arg3 = EVAL_EXPR( ARGI_CALL( call, 3 ) );
341
arg4 = EVAL_EXPR( ARGI_CALL( call, 4 ) );
342
arg5 = EVAL_EXPR( ARGI_CALL( call, 5 ) );
343
arg6 = EVAL_EXPR( ARGI_CALL( call, 6 ) );
344
345
/* call the function */
346
if (TNUM_OBJ(func) != T_FUNCTION)
347
DispatchFuncCall(func, 6, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) arg4, (Obj) arg5, (Obj) arg6);
348
else {
349
SET_BRK_CALL_TO( call );
350
CALL_6ARGS( func, arg1, arg2, arg3, arg4, arg5, arg6 );
351
}
352
if (TLS(UserHasQuit) || TLS(UserHasQUIT)) /* the procedure must have called
353
READ() and the user quit from a break
354
loop inside it */
355
ReadEvalError();
356
/* return 0 (to indicate that no leave-statement was executed) */
357
return 0;
358
}
359
360
UInt ExecProccallXargs (
361
Stat call )
362
{
363
Obj func; /* function */
364
Obj args; /* argument list */
365
Obj argi; /* <i>-th argument */
366
UInt i; /* loop variable */
367
368
/* evaluate the function */
369
SET_BRK_CURR_STAT( call );
370
func = EVAL_EXPR( FUNC_CALL( call ) );
371
372
373
/* evaluate the arguments */
374
args = NEW_PLIST( T_PLIST, NARG_SIZE_CALL(SIZE_STAT(call)) );
375
SET_LEN_PLIST( args, NARG_SIZE_CALL(SIZE_STAT(call)) );
376
for ( i = 1; i <= NARG_SIZE_CALL(SIZE_STAT(call)); i++ ) {
377
argi = EVAL_EXPR( ARGI_CALL( call, i ) );
378
SET_ELM_PLIST( args, i, argi );
379
CHANGED_BAG( args );
380
}
381
382
/* call the function */
383
if (TNUM_OBJ(func) != T_FUNCTION) {
384
DoOperation2Args(CallFuncListOper, func, args);
385
} else {
386
SET_BRK_CALL_TO( call );
387
CALL_XARGS( func, args );
388
}
389
390
if (TLS(UserHasQuit) || TLS(UserHasQUIT)) /* the procedure must have called
391
READ() and the user quit from a break
392
loop inside it */
393
ReadEvalError();
394
/* return 0 (to indicate that no leave-statement was executed) */
395
return 0;
396
}
397
398
/****************************************************************************
399
**
400
*F EvalFunccallOpts( <call> ). . evaluate a function call with options
401
**
402
** Calls with options are wrapped in an outer statement, which is
403
** handled here
404
*/
405
406
Obj EvalFunccallOpts(
407
Expr call )
408
{
409
Obj opts;
410
Obj res;
411
412
413
opts = EVAL_EXPR( ADDR_STAT(call)[0] );
414
CALL_1ARGS(PushOptions, opts);
415
416
res = EVAL_EXPR( ADDR_STAT( call )[1]);
417
418
CALL_0ARGS(PopOptions);
419
420
return res;
421
}
422
423
424
/****************************************************************************
425
**
426
*F EvalFunccall0args(<call>) . . execute a function call with 0 arguments
427
*F EvalFunccall1args(<call>) . . execute a function call with 1 arguments
428
*F EvalFunccall2args(<call>) . . execute a function call with 2 arguments
429
*F EvalFunccall3args(<call>) . . execute a function call with 3 arguments
430
*F EvalFunccall4args(<call>) . . execute a function call with 4 arguments
431
*F EvalFunccall5args(<call>) . . execute a function call with 5 arguments
432
*F EvalFunccall6args(<call>) . . execute a function call with 6 arguments
433
*F EvalFunccallXargs(<call>) . . execute a function call with more arguments
434
**
435
** 'EvalFunccall<i>args' executes a function call to the function
436
** 'FUNC_CALL(<call>)' with the arguments 'ARGI_CALL(<call>,1)' to
437
** 'ARGI_CALL(<call>,<i>)'. It returns the value returned by the function.
438
*/
439
440
Obj EvalFunccall0args (
441
Expr call )
442
{
443
Obj result; /* value of function call, result */
444
Obj func; /* function */
445
446
/* evaluate the function */
447
func = EVAL_EXPR( FUNC_CALL( call ) );
448
449
if (TNUM_OBJ(func) != T_FUNCTION) {
450
return DispatchFuncCall(func, 0, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0 );
451
}
452
453
/* call the function and return the result */
454
SET_BRK_CALL_TO( call );
455
result = CALL_0ARGS( func );
456
if (TLS(UserHasQuit) || TLS(UserHasQUIT)) /* the procedure must have called
457
READ() and the user quit from a break
458
loop inside it */
459
ReadEvalError();
460
while ( result == 0 ) {
461
result = ErrorReturnObj(
462
"Function Calls: <func> must return a value",
463
0L, 0L,
464
"you can supply one by 'return <value>;'" );
465
}
466
return result;
467
}
468
469
Obj EvalFunccall1args (
470
Expr call )
471
{
472
Obj result; /* value of function call, result */
473
Obj func; /* function */
474
Obj arg1; /* first argument */
475
476
/* evaluate the function */
477
func = EVAL_EXPR( FUNC_CALL( call ) );
478
/* evaluate the arguments */
479
arg1 = EVAL_EXPR( ARGI_CALL( call, 1 ) );
480
481
if (TNUM_OBJ(func) != T_FUNCTION) {
482
return DispatchFuncCall(func, 1, (Obj) arg1, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0 );
483
}
484
485
/* call the function and return the result */
486
SET_BRK_CALL_TO( call );
487
result = CALL_1ARGS( func, arg1 );
488
if (TLS(UserHasQuit) || TLS(UserHasQUIT)) /* the procedure must have called
489
READ() and the user quit from a break
490
loop inside it */
491
ReadEvalError();
492
while ( result == 0 ) {
493
result = ErrorReturnObj(
494
"Function Calls: <func> must return a value",
495
0L, 0L,
496
"you can supply one by 'return <value>;'" );
497
}
498
return result;
499
}
500
501
Obj EvalFunccall2args (
502
Expr call )
503
{
504
Obj result; /* value of function call, result */
505
Obj func; /* function */
506
Obj arg1; /* first argument */
507
Obj arg2; /* second argument */
508
509
/* evaluate the function */
510
func = EVAL_EXPR( FUNC_CALL( call ) );
511
512
/* evaluate the arguments */
513
arg1 = EVAL_EXPR( ARGI_CALL( call, 1 ) );
514
arg2 = EVAL_EXPR( ARGI_CALL( call, 2 ) );
515
516
if (TNUM_OBJ(func) != T_FUNCTION) {
517
return DispatchFuncCall(func, 2, (Obj) arg1, (Obj) arg2, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0 );
518
}
519
520
/* call the function and return the result */
521
SET_BRK_CALL_TO( call );
522
result = CALL_2ARGS( func, arg1, arg2 );
523
if (TLS(UserHasQuit) || TLS(UserHasQUIT)) /* the procedure must have called
524
READ() and the user quit from a break
525
loop inside it */
526
ReadEvalError();
527
while ( result == 0 ) {
528
result = ErrorReturnObj(
529
"Function Calls: <func> must return a value",
530
0L, 0L,
531
"you can supply one by 'return <value>;'" );
532
}
533
return result;
534
}
535
536
Obj EvalFunccall3args (
537
Expr call )
538
{
539
Obj result; /* value of function call, result */
540
Obj func; /* function */
541
Obj arg1; /* first argument */
542
Obj arg2; /* second argument */
543
Obj arg3; /* third argument */
544
545
/* evaluate the function */
546
func = EVAL_EXPR( FUNC_CALL( call ) );
547
548
/* evaluate the arguments */
549
arg1 = EVAL_EXPR( ARGI_CALL( call, 1 ) );
550
arg2 = EVAL_EXPR( ARGI_CALL( call, 2 ) );
551
arg3 = EVAL_EXPR( ARGI_CALL( call, 3 ) );
552
553
if (TNUM_OBJ(func) != T_FUNCTION) {
554
return DispatchFuncCall(func, 1, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) 0, (Obj) 0, (Obj) 0 );
555
}
556
557
/* call the function and return the result */
558
SET_BRK_CALL_TO( call );
559
result = CALL_3ARGS( func, arg1, arg2, arg3 );
560
if (TLS(UserHasQuit) || TLS(UserHasQUIT)) /* the procedure must have called
561
READ() and the user quit from a break
562
loop inside it */
563
ReadEvalError();
564
while ( result == 0 ) {
565
result = ErrorReturnObj(
566
"Function Calls: <func> must return a value",
567
0L, 0L,
568
"you can supply one by 'return <value>;'" );
569
}
570
return result;
571
}
572
573
Obj EvalFunccall4args (
574
Expr call )
575
{
576
Obj result; /* value of function call, result */
577
Obj func; /* function */
578
Obj arg1; /* first argument */
579
Obj arg2; /* second argument */
580
Obj arg3; /* third argument */
581
Obj arg4; /* fourth argument */
582
583
/* evaluate the function */
584
func = EVAL_EXPR( FUNC_CALL( call ) );
585
/* evaluate the arguments */
586
arg1 = EVAL_EXPR( ARGI_CALL( call, 1 ) );
587
arg2 = EVAL_EXPR( ARGI_CALL( call, 2 ) );
588
arg3 = EVAL_EXPR( ARGI_CALL( call, 3 ) );
589
arg4 = EVAL_EXPR( ARGI_CALL( call, 4 ) );
590
591
if (TNUM_OBJ(func) != T_FUNCTION) {
592
return DispatchFuncCall(func, 4, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) arg4, (Obj) 0, (Obj) 0 );
593
}
594
595
/* call the function and return the result */
596
SET_BRK_CALL_TO( call );
597
result = CALL_4ARGS( func, arg1, arg2, arg3, arg4 );
598
if (TLS(UserHasQuit) || TLS(UserHasQUIT)) /* the procedure must have called
599
READ() and the user quit from a break
600
loop inside it */
601
ReadEvalError();
602
while ( result == 0 ) {
603
result = ErrorReturnObj(
604
"Function Calls: <func> must return a value",
605
0L, 0L,
606
"you can supply one by 'return <value>;'" );
607
}
608
return result;
609
}
610
611
Obj EvalFunccall5args (
612
Expr call )
613
{
614
Obj result; /* value of function call, result */
615
Obj func; /* function */
616
Obj arg1; /* first argument */
617
Obj arg2; /* second argument */
618
Obj arg3; /* third argument */
619
Obj arg4; /* fourth argument */
620
Obj arg5; /* fifth argument */
621
622
/* evaluate the function */
623
func = EVAL_EXPR( FUNC_CALL( call ) );
624
625
/* evaluate the arguments */
626
arg1 = EVAL_EXPR( ARGI_CALL( call, 1 ) );
627
arg2 = EVAL_EXPR( ARGI_CALL( call, 2 ) );
628
arg3 = EVAL_EXPR( ARGI_CALL( call, 3 ) );
629
arg4 = EVAL_EXPR( ARGI_CALL( call, 4 ) );
630
arg5 = EVAL_EXPR( ARGI_CALL( call, 5 ) );
631
632
if (TNUM_OBJ(func) != T_FUNCTION) {
633
return DispatchFuncCall(func, 5, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) arg4, (Obj) arg5, (Obj) 0 );
634
}
635
636
/* call the function and return the result */
637
SET_BRK_CALL_TO( call );
638
result = CALL_5ARGS( func, arg1, arg2, arg3, arg4, arg5 );
639
if (TLS(UserHasQuit) || TLS(UserHasQUIT)) /* the procedure must have called
640
READ() and the user quit from a break
641
loop inside it */
642
ReadEvalError();
643
while ( result == 0 ) {
644
result = ErrorReturnObj(
645
"Function Calls: <func> must return a value",
646
0L, 0L,
647
"you can supply one by 'return <value>;'" );
648
}
649
return result;
650
}
651
652
Obj EvalFunccall6args (
653
Expr call )
654
{
655
Obj result; /* value of function call, result */
656
Obj func; /* function */
657
Obj arg1; /* first argument */
658
Obj arg2; /* second argument */
659
Obj arg3; /* third argument */
660
Obj arg4; /* fourth argument */
661
Obj arg5; /* fifth argument */
662
Obj arg6; /* sixth argument */
663
664
/* evaluate the function */
665
func = EVAL_EXPR( FUNC_CALL( call ) );
666
667
/* evaluate the arguments */
668
arg1 = EVAL_EXPR( ARGI_CALL( call, 1 ) );
669
arg2 = EVAL_EXPR( ARGI_CALL( call, 2 ) );
670
arg3 = EVAL_EXPR( ARGI_CALL( call, 3 ) );
671
arg4 = EVAL_EXPR( ARGI_CALL( call, 4 ) );
672
arg5 = EVAL_EXPR( ARGI_CALL( call, 5 ) );
673
arg6 = EVAL_EXPR( ARGI_CALL( call, 6 ) );
674
675
if (TNUM_OBJ(func) != T_FUNCTION) {
676
return DispatchFuncCall(func, 6, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) arg4, (Obj) arg5, (Obj) arg6 );
677
}
678
679
/* call the function and return the result */
680
SET_BRK_CALL_TO( call );
681
result = CALL_6ARGS( func, arg1, arg2, arg3, arg4, arg5, arg6 );
682
if (TLS(UserHasQuit) || TLS(UserHasQUIT)) /* the procedure must have called
683
READ() and the user quit from a break
684
loop inside it */
685
ReadEvalError();
686
while ( result == 0 ) {
687
result = ErrorReturnObj(
688
"Function Calls: <func> must return a value",
689
0L, 0L,
690
"you can supply one by 'return <value>;'" );
691
}
692
return result;
693
}
694
695
Obj EvalFunccallXargs (
696
Expr call )
697
{
698
Obj result; /* value of function call, result */
699
Obj func; /* function */
700
Obj args; /* argument list */
701
Obj argi; /* <i>-th argument */
702
UInt i; /* loop variable */
703
704
/* evaluate the function */
705
func = EVAL_EXPR( FUNC_CALL( call ) );
706
707
/* evaluate the arguments */
708
args = NEW_PLIST( T_PLIST, NARG_SIZE_CALL(SIZE_EXPR(call)) );
709
SET_LEN_PLIST( args, NARG_SIZE_CALL(SIZE_EXPR(call)) );
710
for ( i = 1; i <= NARG_SIZE_CALL(SIZE_EXPR(call)); i++ ) {
711
argi = EVAL_EXPR( ARGI_CALL( call, i ) );
712
SET_ELM_PLIST( args, i, argi );
713
CHANGED_BAG( args );
714
}
715
716
if (TNUM_OBJ(func) != T_FUNCTION) {
717
return DispatchFuncCall(func, -1, (Obj) args, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0 );
718
}
719
720
/* call the function and return the result */
721
SET_BRK_CALL_TO( call );
722
result = CALL_XARGS( func, args );
723
if (TLS(UserHasQuit) || TLS(UserHasQUIT)) /* the procedure must have called
724
READ() and the user quit from a break
725
loop inside it */
726
ReadEvalError();
727
while ( result == 0 ) {
728
result = ErrorReturnObj(
729
"Function Calls: <func> must return a value",
730
0L, 0L,
731
"you can supply one by 'return <value>;'" );
732
}
733
return result;
734
}
735
736
737
/****************************************************************************
738
**
739
*F DoExecFunc0args(<func>) . . . . interpret a function with 0 arguments
740
*F DoExecFunc1args(<func>,<arg1>) . interpret a function with 1 arguments
741
*F DoExecFunc2args(<func>,<arg1>...) interpret a function with 2 arguments
742
*F DoExecFunc3args(<func>,<arg1>...) interpret a function with 3 arguments
743
*F DoExecFunc4args(<func>,<arg1>...) interpret a function with 4 arguments
744
*F DoExecFunc5args(<func>,<arg1>...) interpret a function with 5 arguments
745
*F DoExecFunc6args(<func>,<arg1>...) interpret a function with 6 arguments
746
*F DoExecFuncXargs(<func>,<args>) . interpret a function with more arguments
747
**
748
** 'DoExecFunc<i>args' interprets the function <func> that expects <i>
749
** arguments with the <i> actual argument <arg1>, <arg2>, and so on. If the
750
** function expects more than 4 arguments the actual arguments are passed in
751
** the plain list <args>.
752
**
753
** 'DoExecFunc<i>args' is the handler for interpreted functions expecting
754
** <i> arguments.
755
**
756
** 'DoExecFunc<i>args' first switches to a new values bag. Then it enters
757
** the arguments <arg1>, <arg2>, and so on in this new values bag. Then it
758
** executes the function body. After that it switches back to the old
759
** values bag. Finally it returns the result from 'TLS(ReturnObjStat)'.
760
**
761
** Note that these functions are never called directly, they are only called
762
** through the function call mechanism.
763
**
764
** The following functions implement the recursion depth control.
765
**
766
*/
767
768
Int RecursionDepth;
769
static UInt RecursionTrapInterval;
770
771
static void RecursionDepthTrap( void )
772
{
773
Int recursionDepth;
774
/* in interactive work the RecursionDepth could become slightly negative
775
* when quit-ting a higher level brk-loop to a lower level one.
776
* Therefore we don't do anything if RecursionDepth <= 0
777
*/
778
if (TLS(RecursionDepth) > 0) {
779
recursionDepth = TLS(RecursionDepth);
780
TLS(RecursionDepth) = 0;
781
ErrorReturnVoid( "recursion depth trap (%d)\n",
782
(Int)recursionDepth, 0L,
783
"you may 'return;'" );
784
TLS(RecursionDepth) = recursionDepth;
785
}
786
}
787
788
static inline void CheckRecursionBefore( void )
789
{
790
TLS(RecursionDepth)++;
791
if ( RecursionTrapInterval &&
792
0 == (TLS(RecursionDepth) % RecursionTrapInterval) )
793
RecursionDepthTrap();
794
}
795
796
797
Obj STEVES_TRACING;
798
799
#define CHECK_RECURSION_BEFORE \
800
CheckRecursionBefore(); \
801
ProfileLineByLineIntoFunction(func);
802
803
#define CHECK_RECURSION_AFTER \
804
TLS(RecursionDepth)--; \
805
ProfileLineByLineOutFunction(func);
806
807
#define REMEMBER_LOCKSTACK() \
808
do { } while (0)
809
810
#define CLEAR_LOCK_STACK() \
811
do { } while (0)
812
813
814
Obj DoExecFunc0args (
815
Obj func )
816
{
817
Bag oldLvars; /* old values bag */
818
REMEMBER_LOCKSTACK();
819
820
OLD_BRK_CURR_STAT /* old executing statement */
821
822
CHECK_RECURSION_BEFORE
823
824
825
/* switch to a new values bag */
826
SWITCH_TO_NEW_LVARS( func, 0, NLOC_FUNC(func), oldLvars );
827
828
/* execute the statement sequence */
829
REM_BRK_CURR_STAT();
830
EXEC_STAT( FIRST_STAT_CURR_FUNC );
831
RES_BRK_CURR_STAT();
832
CLEAR_LOCK_STACK();
833
834
/* remove the link to the calling function, in case this values bag
835
stays alive due to higher variable reference */
836
SET_BRK_CALL_FROM( ((Obj) 0));
837
838
/* Switch back to the old values bag */
839
SWITCH_TO_OLD_LVARS_AND_FREE( oldLvars );
840
841
CHECK_RECURSION_AFTER
842
843
/* return the result */
844
{
845
Obj returnObjStat;
846
returnObjStat = TLS(ReturnObjStat);
847
TLS(ReturnObjStat) = (Obj)0;
848
return returnObjStat;
849
}
850
}
851
852
Obj DoExecFunc1args (
853
Obj func,
854
Obj arg1 )
855
{
856
Bag oldLvars; /* old values bag */
857
REMEMBER_LOCKSTACK();
858
OLD_BRK_CURR_STAT /* old executing statement */
859
860
CHECK_RECURSION_BEFORE
861
862
/* switch to a new values bag */
863
SWITCH_TO_NEW_LVARS( func, 1, NLOC_FUNC(func), oldLvars );
864
865
/* enter the arguments */
866
ASS_LVAR( 1, arg1 );
867
868
/* execute the statement sequence */
869
REM_BRK_CURR_STAT();
870
EXEC_STAT( FIRST_STAT_CURR_FUNC );
871
RES_BRK_CURR_STAT();
872
CLEAR_LOCK_STACK();
873
874
/* remove the link to the calling function, in case this values bag
875
stays alive due to higher variable reference */
876
SET_BRK_CALL_FROM( ((Obj) 0));
877
878
/* switch back to the old values bag */
879
SWITCH_TO_OLD_LVARS_AND_FREE( oldLvars );
880
881
CHECK_RECURSION_AFTER
882
883
/* return the result */
884
{
885
Obj returnObjStat;
886
returnObjStat = TLS(ReturnObjStat);
887
TLS(ReturnObjStat) = (Obj)0;
888
return returnObjStat;
889
}
890
}
891
892
Obj DoExecFunc2args (
893
Obj func,
894
Obj arg1,
895
Obj arg2 )
896
{
897
Bag oldLvars; /* old values bag */
898
REMEMBER_LOCKSTACK();
899
OLD_BRK_CURR_STAT /* old executing statement */
900
901
CHECK_RECURSION_BEFORE
902
903
/* switch to a new values bag */
904
SWITCH_TO_NEW_LVARS( func, 2, NLOC_FUNC(func), oldLvars );
905
906
/* enter the arguments */
907
ASS_LVAR( 1, arg1 );
908
ASS_LVAR( 2, arg2 );
909
910
/* execute the statement sequence */
911
REM_BRK_CURR_STAT();
912
EXEC_STAT( FIRST_STAT_CURR_FUNC );
913
RES_BRK_CURR_STAT();
914
CLEAR_LOCK_STACK();
915
916
/* remove the link to the calling function, in case this values bag
917
stays alive due to higher variable reference */
918
SET_BRK_CALL_FROM( ((Obj) 0));
919
920
/* switch back to the old values bag */
921
SWITCH_TO_OLD_LVARS_AND_FREE( oldLvars );
922
923
CHECK_RECURSION_AFTER
924
925
/* return the result */
926
{
927
Obj returnObjStat;
928
returnObjStat = TLS(ReturnObjStat);
929
TLS(ReturnObjStat) = (Obj)0;
930
return returnObjStat;
931
}
932
}
933
934
Obj DoExecFunc3args (
935
Obj func,
936
Obj arg1,
937
Obj arg2,
938
Obj arg3 )
939
{
940
Bag oldLvars; /* old values bag */
941
REMEMBER_LOCKSTACK();
942
OLD_BRK_CURR_STAT /* old executing statement */
943
944
CHECK_RECURSION_BEFORE
945
946
/* switch to a new values bag */
947
SWITCH_TO_NEW_LVARS( func, 3, NLOC_FUNC(func), oldLvars );
948
949
/* enter the arguments */
950
ASS_LVAR( 1, arg1 );
951
ASS_LVAR( 2, arg2 );
952
ASS_LVAR( 3, arg3 );
953
954
/* execute the statement sequence */
955
REM_BRK_CURR_STAT();
956
EXEC_STAT( FIRST_STAT_CURR_FUNC );
957
RES_BRK_CURR_STAT();
958
CLEAR_LOCK_STACK();
959
960
/* remove the link to the calling function, in case this values bag
961
stays alive due to higher variable reference */
962
SET_BRK_CALL_FROM( ((Obj) 0));
963
964
/* switch back to the old values bag */
965
SWITCH_TO_OLD_LVARS_AND_FREE( oldLvars );
966
967
CHECK_RECURSION_AFTER
968
969
/* return the result */
970
{
971
Obj returnObjStat;
972
returnObjStat = TLS(ReturnObjStat);
973
TLS(ReturnObjStat) = (Obj)0;
974
return returnObjStat;
975
}
976
}
977
978
Obj DoExecFunc4args (
979
Obj func,
980
Obj arg1,
981
Obj arg2,
982
Obj arg3,
983
Obj arg4 )
984
{
985
Bag oldLvars; /* old values bag */
986
REMEMBER_LOCKSTACK();
987
OLD_BRK_CURR_STAT /* old executing statement */
988
989
CHECK_RECURSION_BEFORE
990
991
/* switch to a new values bag */
992
SWITCH_TO_NEW_LVARS( func, 4, NLOC_FUNC(func), oldLvars );
993
994
/* enter the arguments */
995
ASS_LVAR( 1, arg1 );
996
ASS_LVAR( 2, arg2 );
997
ASS_LVAR( 3, arg3 );
998
ASS_LVAR( 4, arg4 );
999
1000
/* execute the statement sequence */
1001
REM_BRK_CURR_STAT();
1002
EXEC_STAT( FIRST_STAT_CURR_FUNC );
1003
RES_BRK_CURR_STAT();
1004
CLEAR_LOCK_STACK();
1005
1006
/* remove the link to the calling function, in case this values bag
1007
stays alive due to higher variable reference */
1008
SET_BRK_CALL_FROM( ((Obj) 0));
1009
1010
/* switch back to the old values bag */
1011
SWITCH_TO_OLD_LVARS_AND_FREE( oldLvars );
1012
1013
CHECK_RECURSION_AFTER
1014
1015
/* return the result */
1016
{
1017
Obj returnObjStat;
1018
returnObjStat = TLS(ReturnObjStat);
1019
TLS(ReturnObjStat) = (Obj)0;
1020
return returnObjStat;
1021
}
1022
}
1023
1024
Obj DoExecFunc5args (
1025
Obj func,
1026
Obj arg1,
1027
Obj arg2,
1028
Obj arg3,
1029
Obj arg4,
1030
Obj arg5 )
1031
{
1032
Bag oldLvars; /* old values bag */
1033
REMEMBER_LOCKSTACK();
1034
OLD_BRK_CURR_STAT /* old executing statement */
1035
1036
CHECK_RECURSION_BEFORE
1037
1038
/* switch to a new values bag */
1039
SWITCH_TO_NEW_LVARS( func, 5, NLOC_FUNC(func), oldLvars );
1040
1041
/* enter the arguments */
1042
ASS_LVAR( 1, arg1 );
1043
ASS_LVAR( 2, arg2 );
1044
ASS_LVAR( 3, arg3 );
1045
ASS_LVAR( 4, arg4 );
1046
ASS_LVAR( 5, arg5 );
1047
1048
/* execute the statement sequence */
1049
REM_BRK_CURR_STAT();
1050
EXEC_STAT( FIRST_STAT_CURR_FUNC );
1051
RES_BRK_CURR_STAT();
1052
CLEAR_LOCK_STACK();
1053
1054
/* remove the link to the calling function, in case this values bag
1055
stays alive due to higher variable reference */
1056
SET_BRK_CALL_FROM( ((Obj) 0));
1057
1058
/* switch back to the old values bag */
1059
SWITCH_TO_OLD_LVARS_AND_FREE( oldLvars );
1060
1061
CHECK_RECURSION_AFTER
1062
1063
/* return the result */
1064
{
1065
Obj returnObjStat;
1066
returnObjStat = TLS(ReturnObjStat);
1067
TLS(ReturnObjStat) = (Obj)0;
1068
return returnObjStat;
1069
}
1070
}
1071
1072
Obj DoExecFunc6args (
1073
Obj func,
1074
Obj arg1,
1075
Obj arg2,
1076
Obj arg3,
1077
Obj arg4,
1078
Obj arg5,
1079
Obj arg6 )
1080
{
1081
Bag oldLvars; /* old values bag */
1082
REMEMBER_LOCKSTACK();
1083
OLD_BRK_CURR_STAT /* old executing statement */
1084
1085
CHECK_RECURSION_BEFORE
1086
1087
/* switch to a new values bag */
1088
SWITCH_TO_NEW_LVARS( func, 6, NLOC_FUNC(func), oldLvars );
1089
1090
/* enter the arguments */
1091
ASS_LVAR( 1, arg1 );
1092
ASS_LVAR( 2, arg2 );
1093
ASS_LVAR( 3, arg3 );
1094
ASS_LVAR( 4, arg4 );
1095
ASS_LVAR( 5, arg5 );
1096
ASS_LVAR( 6, arg6 );
1097
1098
/* execute the statement sequence */
1099
REM_BRK_CURR_STAT();
1100
EXEC_STAT( FIRST_STAT_CURR_FUNC );
1101
RES_BRK_CURR_STAT();
1102
CLEAR_LOCK_STACK();
1103
1104
/* remove the link to the calling function, in case this values bag
1105
stays alive due to higher variable reference */
1106
SET_BRK_CALL_FROM( ((Obj) 0));
1107
1108
/* switch back to the old values bag */
1109
SWITCH_TO_OLD_LVARS_AND_FREE( oldLvars );
1110
1111
CHECK_RECURSION_AFTER
1112
1113
/* return the result */
1114
{
1115
Obj returnObjStat;
1116
returnObjStat = TLS(ReturnObjStat);
1117
TLS(ReturnObjStat) = (Obj)0;
1118
return returnObjStat;
1119
}
1120
}
1121
1122
Obj DoExecFuncXargs (
1123
Obj func,
1124
Obj args )
1125
{
1126
Bag oldLvars; /* old values bag */
1127
REMEMBER_LOCKSTACK();
1128
OLD_BRK_CURR_STAT /* old executing statement */
1129
UInt len; /* number of arguments */
1130
UInt i; /* loop variable */
1131
1132
CHECK_RECURSION_BEFORE
1133
1134
/* check the number of arguments */
1135
len = NARG_FUNC( func );
1136
while ( len != LEN_PLIST( args ) ) {
1137
args = ErrorReturnObj(
1138
"Function Calls: number of arguments must be %d (not %d)",
1139
len, LEN_PLIST( args ),
1140
"you can replace the <list> of arguments via 'return <list>;'" );
1141
PLAIN_LIST( args );
1142
}
1143
1144
/* switch to a new values bag */
1145
SWITCH_TO_NEW_LVARS( func, len, NLOC_FUNC(func), oldLvars );
1146
1147
/* enter the arguments */
1148
for ( i = 1; i <= len; i++ ) {
1149
ASS_LVAR( i, ELM_PLIST( args, i ) );
1150
}
1151
1152
/* execute the statement sequence */
1153
REM_BRK_CURR_STAT();
1154
EXEC_STAT( FIRST_STAT_CURR_FUNC );
1155
RES_BRK_CURR_STAT();
1156
CLEAR_LOCK_STACK();
1157
1158
/* remove the link to the calling function, in case this values bag
1159
stays alive due to higher variable reference */
1160
SET_BRK_CALL_FROM( ((Obj) 0));
1161
1162
/* switch back to the old values bag */
1163
SWITCH_TO_OLD_LVARS_AND_FREE( oldLvars );
1164
1165
CHECK_RECURSION_AFTER
1166
1167
/* return the result */
1168
{
1169
Obj returnObjStat;
1170
returnObjStat = TLS(ReturnObjStat);
1171
TLS(ReturnObjStat) = (Obj)0;
1172
return returnObjStat;
1173
}
1174
}
1175
1176
1177
1178
Obj DoPartialUnWrapFunc(Obj func, Obj args) {
1179
1180
Bag oldLvars; /* old values bag */
1181
OLD_BRK_CURR_STAT /* old executing statement */
1182
UInt named; /* number of arguments */
1183
UInt i; /* loop variable */
1184
UInt len;
1185
Obj argx;
1186
1187
1188
named = ((UInt)-NARG_FUNC(func))-1;
1189
len = LEN_PLIST(args);
1190
1191
if (named > len) { /* Can happen for > 6 arguments */
1192
argx = NargError(func, len);
1193
return DoOperation2Args(CallFuncListOper, func, argx);
1194
}
1195
1196
CHECK_RECURSION_BEFORE
1197
SWITCH_TO_NEW_LVARS( func, named+1, NLOC_FUNC(func), oldLvars );
1198
1199
for (i = 1; i <= named; i++) {
1200
ASS_LVAR(i, ELM_PLIST(args,i));
1201
}
1202
for (i = named+1; i <= len; i++) {
1203
SET_ELM_PLIST(args, i-named, ELM_PLIST(args,i));
1204
}
1205
SET_LEN_PLIST(args, len-named);
1206
ASS_LVAR(named+1, args);
1207
/* execute the statement sequence */
1208
REM_BRK_CURR_STAT();
1209
EXEC_STAT( FIRST_STAT_CURR_FUNC );
1210
RES_BRK_CURR_STAT();
1211
1212
/* remove the link to the calling function, in case this values bag
1213
stays alive due to higher variable reference */
1214
SET_BRK_CALL_FROM( ((Obj) 0));
1215
1216
/* switch back to the old values bag */
1217
SWITCH_TO_OLD_LVARS( oldLvars );
1218
1219
CHECK_RECURSION_AFTER
1220
1221
/* return the result */
1222
{
1223
Obj returnObjStat;
1224
returnObjStat = TLS(ReturnObjStat);
1225
TLS(ReturnObjStat) = (Obj)0;
1226
return returnObjStat;
1227
}
1228
}
1229
1230
/****************************************************************************
1231
**
1232
*F MakeFunction(<fexp>) . . . . . . . . . . . . . . . . . . make a function
1233
**
1234
** 'MakeFunction' makes a function from the function expression bag <fexp>.
1235
*/
1236
Obj MakeFunction (
1237
Obj fexp )
1238
{
1239
Obj func; /* function, result */
1240
ObjFunc hdlr; /* handler */
1241
1242
/* select the right handler */
1243
if ( NARG_FUNC(fexp) == 0 ) hdlr = DoExecFunc0args;
1244
else if ( NARG_FUNC(fexp) == 1 ) hdlr = DoExecFunc1args;
1245
else if ( NARG_FUNC(fexp) == 2 ) hdlr = DoExecFunc2args;
1246
else if ( NARG_FUNC(fexp) == 3 ) hdlr = DoExecFunc3args;
1247
else if ( NARG_FUNC(fexp) == 4 ) hdlr = DoExecFunc4args;
1248
else if ( NARG_FUNC(fexp) == 5 ) hdlr = DoExecFunc5args;
1249
else if ( NARG_FUNC(fexp) == 6 ) hdlr = DoExecFunc6args;
1250
else if ( NARG_FUNC(fexp) >= 7 ) hdlr = DoExecFuncXargs;
1251
else if ( NARG_FUNC(fexp) == -1 ) hdlr = DoExecFunc1args;
1252
else /* NARG_FUNC(fexp) < -1 */ hdlr = DoPartialUnWrapFunc;
1253
1254
/* make the function */
1255
func = NewFunctionT( T_FUNCTION, SIZE_FUNC,
1256
NAME_FUNC( fexp ),
1257
NARG_FUNC( fexp ), NAMS_FUNC( fexp ),
1258
hdlr );
1259
1260
/* install the things an interpreted function needs */
1261
NLOC_FUNC( func ) = NLOC_FUNC( fexp );
1262
BODY_FUNC( func ) = BODY_FUNC( fexp );
1263
ENVI_FUNC( func ) = TLS(CurrLVars);
1264
/* the 'CHANGED_BAG(TLS(CurrLVars))' is needed because it is delayed */
1265
CHANGED_BAG( TLS(CurrLVars) );
1266
FEXS_FUNC( func ) = FEXS_FUNC( fexp );
1267
1268
/* return the function */
1269
return func;
1270
}
1271
1272
1273
/****************************************************************************
1274
**
1275
*F EvalFuncExpr(<expr>) . . . evaluate a function expression to a function
1276
**
1277
** 'EvalFuncExpr' evaluates the function expression <expr> to a function.
1278
*/
1279
Obj EvalFuncExpr (
1280
Expr expr )
1281
{
1282
Obj fexs; /* func. expr. list of curr. func. */
1283
Obj fexp; /* function expression bag */
1284
1285
/* get the function expression bag */
1286
fexs = FEXS_FUNC( CURR_FUNC );
1287
fexp = ELM_PLIST( fexs, (Int)(ADDR_EXPR(expr)[0]) );
1288
1289
/* and make the function */
1290
return MakeFunction( fexp );
1291
}
1292
1293
1294
/****************************************************************************
1295
**
1296
*F PrintFuncExpr(<expr>) . . . . . . . . . . . . print a function expression
1297
**
1298
** 'PrintFuncExpr' prints a function expression.
1299
*/
1300
void PrintFuncExpr (
1301
Expr expr )
1302
{
1303
Obj fexs; /* func. expr. list of curr. func. */
1304
Obj fexp; /* function expression bag */
1305
1306
/* get the function expression bag */
1307
fexs = FEXS_FUNC( CURR_FUNC );
1308
fexp = ELM_PLIST( fexs, (Int)(ADDR_EXPR(expr)[0]) );
1309
PrintFunction( fexp );
1310
/* Pr("function ... end",0L,0L); */
1311
}
1312
1313
1314
/****************************************************************************
1315
**
1316
*F PrintProccall(<call>) . . . . . . . . . . . . . . print a procedure call
1317
**
1318
** 'PrintProccall' prints a procedure call.
1319
*/
1320
extern void PrintFunccall (
1321
Expr call );
1322
1323
extern void PrintFunccallOpts (
1324
Expr call );
1325
1326
void PrintProccall (
1327
Stat call )
1328
{
1329
PrintFunccall( call );
1330
Pr( ";", 0L, 0L );
1331
}
1332
1333
void PrintProccallOpts (
1334
Stat call )
1335
{
1336
PrintFunccallOpts( call );
1337
Pr( ";", 0L, 0L );
1338
}
1339
1340
1341
/****************************************************************************
1342
**
1343
*F PrintFunccall(<call>) . . . . . . . . . . . . . . . print a function call
1344
**
1345
** 'PrintFunccall' prints a function call.
1346
*/
1347
static void PrintFunccall1 (
1348
Expr call )
1349
{
1350
UInt i; /* loop variable */
1351
1352
/* print the expression that should evaluate to a function */
1353
Pr("%2>",0L,0L);
1354
PrintExpr( FUNC_CALL(call) );
1355
1356
/* print the opening parenthesis */
1357
Pr("%<( %>",0L,0L);
1358
1359
/* print the expressions that evaluate to the actual arguments */
1360
for ( i = 1; i <= NARG_SIZE_CALL( SIZE_EXPR(call) ); i++ ) {
1361
PrintExpr( ARGI_CALL(call,i) );
1362
if ( i != NARG_SIZE_CALL( SIZE_EXPR(call) ) ) {
1363
Pr("%<, %>",0L,0L);
1364
}
1365
}
1366
1367
return;
1368
1369
}
1370
1371
void PrintFunccall (
1372
Expr call )
1373
{
1374
PrintFunccall1( call );
1375
1376
/* print the closing parenthesis */
1377
Pr(" %2<)",0L,0L);
1378
}
1379
1380
1381
void PrintFunccallOpts (
1382
Expr call )
1383
{
1384
PrintFunccall1( ADDR_STAT( call )[1]);
1385
Pr(" :%2> ", 0L, 0L);
1386
PrintRecExpr1 ( ADDR_STAT( call )[0]);
1387
Pr(" %4<)",0L,0L);
1388
}
1389
1390
1391
1392
/****************************************************************************
1393
**
1394
*F ExecBegin() . . . . . . . . . . . . . . . . . . . . . begin an execution
1395
*F ExecEnd(<error>) . . . . . . . . . . . . . . . . . . . end an execution
1396
*/
1397
Obj ExecState;
1398
1399
void ExecBegin ( Obj frame )
1400
{
1401
Obj execState; /* old execution state */
1402
1403
/* remember the old execution state */
1404
execState = NewBag( T_PLIST, 4*sizeof(Obj) );
1405
ADDR_OBJ(execState)[0] = (Obj)3;
1406
ADDR_OBJ(execState)[1] = TLS(ExecState);
1407
ADDR_OBJ(execState)[2] = TLS(CurrLVars);
1408
/* the 'CHANGED_BAG(TLS(CurrLVars))' is needed because it is delayed */
1409
CHANGED_BAG( TLS(CurrLVars) );
1410
ADDR_OBJ(execState)[3] = INTOBJ_INT((Int)TLS(CurrStat));
1411
TLS(ExecState) = execState;
1412
1413
/* set up new state */
1414
SWITCH_TO_OLD_LVARS( frame );
1415
SET_BRK_CURR_STAT( 0 );
1416
}
1417
1418
void ExecEnd (
1419
UInt error )
1420
{
1421
/* if everything went fine */
1422
if ( ! error ) {
1423
1424
/* the state must be primal again */
1425
assert( TLS(CurrStat) == 0 );
1426
1427
/* switch back to the old state */
1428
SET_BRK_CURR_STAT( (Stat)INT_INTOBJ((ADDR_OBJ(TLS(ExecState))[3]) ));
1429
SWITCH_TO_OLD_LVARS( ADDR_OBJ(TLS(ExecState))[2] );
1430
TLS(ExecState) = ADDR_OBJ(TLS(ExecState))[1];
1431
1432
}
1433
1434
/* otherwise clean up the mess */
1435
else {
1436
1437
/* switch back to the old state */
1438
SET_BRK_CURR_STAT( (Stat)INT_INTOBJ((ADDR_OBJ(TLS(ExecState))[3]) ));
1439
SWITCH_TO_OLD_LVARS( ADDR_OBJ(TLS(ExecState))[2] );
1440
TLS(ExecState) = ADDR_OBJ(TLS(ExecState))[1];
1441
1442
}
1443
}
1444
1445
/****************************************************************************
1446
**
1447
*F FuncSetRecursionTrapInterval( <self>, <interval> )
1448
**
1449
*/
1450
1451
Obj FuncSetRecursionTrapInterval( Obj self, Obj interval )
1452
{
1453
while (!IS_INTOBJ(interval) || INT_INTOBJ(interval) < 0)
1454
interval = ErrorReturnObj( "SetRecursionTrapInterval( <interval> ): "
1455
"<interval> must be a non-negative small integer",
1456
0L, 0L,
1457
"you can replace <interval> via 'return <interval>;'");
1458
RecursionTrapInterval = INT_INTOBJ( interval);
1459
return 0;
1460
}
1461
1462
1463
/****************************************************************************
1464
**
1465
*F * * * * * * * * * * * * * initialize package * * * * * * * * * * * * * * *
1466
*/
1467
1468
/****************************************************************************
1469
**
1470
*V GVarFuncs . . . . . . . . . . . . . . . . . . list of functions to export
1471
*/
1472
static StructGVarFunc GVarFuncs [] = {
1473
1474
{ "SetRecursionTrapInterval", 1, "interval",
1475
FuncSetRecursionTrapInterval, "src/funcs.c:SetRecursionTrapInterval" },
1476
1477
{ 0 }
1478
1479
};
1480
1481
/****************************************************************************
1482
**
1483
*F InitLibrary( <module> ) . . . . . . . initialise library data structures
1484
*/
1485
static Int InitLibrary (
1486
StructInitInfo * module )
1487
{
1488
/* init filters and functions */
1489
InitGVarFuncsFromTable( GVarFuncs );
1490
1491
1492
/* return success */
1493
return 0;
1494
}
1495
1496
1497
/****************************************************************************
1498
**
1499
1500
*F InitKernel( <module> ) . . . . . . . . initialise kernel data structures
1501
*/
1502
static Int InitKernel (
1503
StructInitInfo * module )
1504
{
1505
RecursionTrapInterval = 5000;
1506
InitCopyGVar("STEVES_TRACING", &STEVES_TRACING);
1507
1508
/* make the global variable known to Gasman */
1509
InitGlobalBag( &ExecState, "src/funcs.c:ExecState" );
1510
1511
/* Register the handler for our exported function */
1512
InitHdlrFuncsFromTable( GVarFuncs );
1513
1514
/* Import some functions from the library */
1515
ImportFuncFromLibrary( "PushOptions", &PushOptions );
1516
ImportFuncFromLibrary( "PopOptions", &PopOptions );
1517
1518
/* use short cookies to save space in saved workspace */
1519
InitHandlerFunc( DoExecFunc0args, "i0");
1520
InitHandlerFunc( DoExecFunc1args, "i1");
1521
InitHandlerFunc( DoExecFunc2args, "i2");
1522
InitHandlerFunc( DoExecFunc3args, "i3");
1523
InitHandlerFunc( DoExecFunc4args, "i4");
1524
InitHandlerFunc( DoExecFunc5args, "i5");
1525
InitHandlerFunc( DoExecFunc6args, "i6");
1526
InitHandlerFunc( DoExecFuncXargs, "iX");
1527
InitHandlerFunc( DoPartialUnWrapFunc, "pUW");
1528
1529
/* install the evaluators and executors */
1530
InstallExecStatFunc( T_PROCCALL_0ARGS , ExecProccall0args);
1531
InstallExecStatFunc( T_PROCCALL_1ARGS , ExecProccall1args);
1532
InstallExecStatFunc( T_PROCCALL_2ARGS , ExecProccall2args);
1533
InstallExecStatFunc( T_PROCCALL_3ARGS , ExecProccall3args);
1534
InstallExecStatFunc( T_PROCCALL_4ARGS , ExecProccall4args);
1535
InstallExecStatFunc( T_PROCCALL_5ARGS , ExecProccall5args);
1536
InstallExecStatFunc( T_PROCCALL_6ARGS , ExecProccall6args);
1537
InstallExecStatFunc( T_PROCCALL_XARGS , ExecProccallXargs);
1538
InstallExecStatFunc( T_PROCCALL_OPTS , ExecProccallOpts);
1539
1540
InstallEvalExprFunc( T_FUNCCALL_0ARGS , EvalFunccall0args);
1541
InstallEvalExprFunc( T_FUNCCALL_1ARGS , EvalFunccall1args);
1542
InstallEvalExprFunc( T_FUNCCALL_2ARGS , EvalFunccall2args);
1543
InstallEvalExprFunc( T_FUNCCALL_3ARGS , EvalFunccall3args);
1544
InstallEvalExprFunc( T_FUNCCALL_4ARGS , EvalFunccall4args);
1545
InstallEvalExprFunc( T_FUNCCALL_5ARGS , EvalFunccall5args);
1546
InstallEvalExprFunc( T_FUNCCALL_6ARGS , EvalFunccall6args);
1547
InstallEvalExprFunc( T_FUNCCALL_XARGS , EvalFunccallXargs);
1548
InstallEvalExprFunc( T_FUNCCALL_OPTS , EvalFunccallOpts);
1549
InstallEvalExprFunc( T_FUNC_EXPR , EvalFuncExpr);
1550
1551
/* install the printers */
1552
InstallPrintStatFunc( T_PROCCALL_0ARGS , PrintProccall);
1553
InstallPrintStatFunc( T_PROCCALL_1ARGS , PrintProccall);
1554
InstallPrintStatFunc( T_PROCCALL_2ARGS , PrintProccall);
1555
InstallPrintStatFunc( T_PROCCALL_3ARGS , PrintProccall);
1556
InstallPrintStatFunc( T_PROCCALL_4ARGS , PrintProccall);
1557
InstallPrintStatFunc( T_PROCCALL_5ARGS , PrintProccall);
1558
InstallPrintStatFunc( T_PROCCALL_6ARGS , PrintProccall);
1559
InstallPrintStatFunc( T_PROCCALL_XARGS , PrintProccall);
1560
InstallPrintStatFunc( T_PROCCALL_OPTS , PrintProccallOpts);
1561
InstallPrintExprFunc( T_FUNCCALL_0ARGS , PrintFunccall);
1562
InstallPrintExprFunc( T_FUNCCALL_1ARGS , PrintFunccall);
1563
InstallPrintExprFunc( T_FUNCCALL_2ARGS , PrintFunccall);
1564
InstallPrintExprFunc( T_FUNCCALL_3ARGS , PrintFunccall);
1565
InstallPrintExprFunc( T_FUNCCALL_4ARGS , PrintFunccall);
1566
InstallPrintExprFunc( T_FUNCCALL_5ARGS , PrintFunccall);
1567
InstallPrintExprFunc( T_FUNCCALL_6ARGS , PrintFunccall);
1568
InstallPrintExprFunc( T_FUNCCALL_XARGS , PrintFunccall);
1569
InstallPrintExprFunc( T_FUNCCALL_OPTS , PrintFunccallOpts);
1570
InstallPrintExprFunc( T_FUNC_EXPR , PrintFuncExpr);
1571
1572
/* return success */
1573
return 0;
1574
}
1575
1576
1577
/****************************************************************************
1578
**
1579
*F InitInfoFuncs() . . . . . . . . . . . . . . . . . table of init functions
1580
*/
1581
static StructInitInfo module = {
1582
MODULE_BUILTIN, /* type */
1583
"funcs", /* name */
1584
0, /* revision entry of c file */
1585
0, /* revision entry of h file */
1586
0, /* version */
1587
0, /* crc */
1588
InitKernel, /* initKernel */
1589
InitLibrary, /* initLibrary */
1590
0, /* checkInit */
1591
0, /* preSave */
1592
0, /* postSave */
1593
0 /* postRestore */
1594
};
1595
1596
StructInitInfo * InitInfoFuncs ( void )
1597
{
1598
return &module;
1599
}
1600
1601
1602
/****************************************************************************
1603
**
1604
1605
*E funcs.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here
1606
*/
1607
1608