2
* eval.c logo eval/apply module dko
4
* Copyright (C) 1993 by the Regents of the University of California
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33
#define save(register) push(register, stack)
34
#define restore(register) (register = car(stack), pop(stack))
36
#define save2(reg1,reg2) (push(reg1,stack),stack->n_obj=reg2)
37
#define restore2(reg1,reg2) (reg2 = getobject(stack), \
38
reg1 = car(stack), pop(stack))
40
/* saving and restoring FIXNUMs rather than NODEs */
42
#define numsave(register) numpush(register,&numstack)
43
#define numrestore(register) (register=(FIXNUM)car(numstack), numstack=cdr(numstack))
45
#define num2save(reg1,reg2) (numpush(reg1,&numstack),numstack->n_obj=(NODE *)reg2)
46
#define num2restore(reg1,reg2) (reg2=(FIXNUM)getobject(numstack), \
47
reg1=(FIXNUM)car(numstack), numstack=cdr(numstack))
49
/* save and restore a FIXNUM (reg1) and a NODE (reg2) */
51
#define mixsave(reg1,reg2) (numsave(reg1), save(reg2))
52
#define mixrestore(reg1,reg2) (numrestore(reg1), restore(reg2))
54
#define newcont(tag) (numsave(cont), cont = (FIXNUM)tag)
56
/* These variables are all externed in globals.h */
59
*fun = NIL, /* current function name */
60
*ufun = NIL, /* current user-defined function name */
61
*last_ufun = NIL, /* the function that called this one */
62
*this_line = NIL, /* the current instruction line */
63
*last_line = NIL, /* the line that called this one */
64
*var_stack = NIL, /* the stack of variables and their bindings */
65
*var = NIL, /* frame pointer into var_stack */
66
*upvar = NIL, /* for LOCAL, one stack frame up */
67
*last_call = NIL, /* the last proc called */
68
*didnt_output_name = NIL, /* the name of the proc that didn't OP */
69
*didnt_get_output = NIL, /* the name of the proc that wanted the OP */
70
*output_node = NIL; /* the output of the current function */
72
CTRLTYPE stopping_flag = RUN;
73
char *logolib, *helpfiles;
74
FIXNUM tailcall; /* 0 in sequence, 1 for tail, -1 for arg */
75
FIXNUM val_status; /* 0 means no value allowed (body of cmd),
76
1 means value required (arg),
77
2 means OUTPUT ok (body of oper),
78
3 means val or no val ok (fn inside catch),
79
4 means no value in macro (repeat),
80
5 means value maybe ok in macro (catch)
81
6 means value required in macro (show run...)
82
7 means value required *now* (tail call of 6)
84
FIXNUM dont_fix_ift = 0;
85
FIXNUM user_repcount = -1;
87
/* These variables are local to this file. */
88
NODE *qm_list = NIL; /* question mark list */
89
static int trace_level = 0; /* indentation level when tracing */
91
/* These first few functions are externed in globals.h */
93
void numpush(FIXNUM obj, NODE **stack) {
94
NODE *temp = newnode(CONT); /*GC*/
96
temp->n_car = (NODE *)obj;
101
/* forward declaration */
102
NODE *evaluator(NODE *list, enum labels where);
104
/* Evaluate a line of input. */
105
void eval_driver(NODE *line) {
106
evaluator(line, begin_line);
109
/* Evaluate a sequence of expressions until we get a value to return.
110
* (Called from erract.)
112
NODE *err_eval_driver(NODE *seq) {
114
return evaluator(seq, begin_seq);
117
/* The logo word APPLY. */
118
NODE *lapply(NODE *args) {
119
return make_cont(begin_apply, args);
122
/* The logo word ? <question-mark>. */
123
NODE *lqm(NODE *args) {
124
FIXNUM argnum = 1, i;
127
if (args != NIL) argnum = getint(pos_int_arg(args));
128
if (stopping_flag == THROWING) return(UNBOUND);
130
while (--i > 0 && np != NIL) np = cdr(np);
132
return(err_logo(BAD_DATA_UNREC,make_intnode(argnum)));
136
/* The rest of the functions are local to this file. */
138
/* Warn the user if a local variable shadows a global one. */
139
void tell_shadow(NODE *arg) {
140
if (flag__caseobj(arg, VAL_STEPPED))
141
err_logo(SHADOW_WARN, arg);
144
/* Check if a local variable is already in this frame */
145
int not_local(NODE *name, NODE *sp) {
146
for ( ; sp != var; sp = cdr(sp)) {
147
if (compare_node(car(sp),name,TRUE) == 0) {
154
/* reverse a list destructively */
155
NODE *reverse(NODE *list) {
156
NODE *ret = NIL, *temp;
158
while (list != NIL) {
167
/* nondestructive append */
168
NODE *append(NODE *a, NODE *b) {
169
if (a == NIL) return b;
170
return cons(car(a), append(cdr(a), b));
173
/* nondestructive flatten */
174
NODE *flatten(NODE *a) {
175
if (a == NIL) return NIL;
176
return append(car(a), flatten(cdr(a)));
179
/* Reset the var stack to the previous place holder.
181
void reset_args(NODE *old_stack) {
182
for (; var_stack != old_stack; pop(var_stack))
183
setvalnode__caseobj(car(var_stack), getobject(var_stack));
186
NODE *bf3(NODE *name) {
187
NODE *string = cnv_node_to_strnode(name);
188
return make_strnode(getstrptr(string)+3, getstrhead(string),
189
getstrlen(string)-3, nodetype(string), strcpy);
192
NODE *deep_copy(NODE *exp) {
196
if (exp == NIL) return NIL;
197
else if (is_list(exp)) {
198
val = cons(deep_copy(car(exp)), deep_copy(cdr(exp)));
199
val->n_obj = deep_copy(exp->n_obj);
200
settype(val, nodetype(exp));
201
} else if (nodetype(exp) == ARRAY) {
202
val = make_array(getarrdim(exp));
203
setarrorg(val, getarrorg(exp));
204
for (p = getarrptr(exp), q = getarrptr(val), arridx=0;
205
arridx < getarrdim(exp); arridx++, p++)
206
*q++ = deep_copy(*p);
213
/* An explicit control evaluator, taken almost directly from SICP, section
214
* 5.2. list is a flat list of expressions to evaluate. where is a label to
215
* begin at. Return value depends on where.
217
NODE *evaluator(NODE *list, enum labels where) {
220
NODE *exp = NIL, /* the current expression */
221
*val = NIL, /* the value of the last expression */
222
*proc = NIL, /* the procedure definition */
223
*argl = NIL, /* evaluated argument list */
224
*unev = NIL, /* list of unevaluated expressions */
225
*stack = NIL, /* register stack */
226
*numstack = NIL,/* stack whose elements aren't objects */
227
*parm = NIL, /* the current formal */
229
*arg = NIL; /* the current actual */
231
NODE *vsp = 0, /* temp ptr into var_stack */
232
*formals = NIL; /* list of formal parameters */
233
FIXNUM cont = 0; /* where to go next */
236
BOOLEAN tracing = FALSE; /* are we tracing the current procedure? */
237
FIXNUM oldtailcall; /* in case of reentrant use of evaluator */
238
FIXNUM repcount; /* count for repeat */
241
oldtailcall = tailcall;
242
old_ift_iff = ift_iff_flag;
243
save2(var,this_line);
246
cont = (FIXNUM)all_done;
247
numsave((FIXNUM)cont);
256
if (!is_tree(list)) {
260
unev = tree__tree(list);
265
if (val != UNBOUND) {
266
if (NOT_THROWING) err_logo(DK_WHAT, val);
272
/* ----------------- EVAL ---------------------------------- */
277
switch (nodetype(exp)) {
278
case QUOTE: /* quoted literal */
279
val = /* deep_copy */ (node__quote(exp));
281
case COLON: /* variable */
282
val = valnode__colon(exp);
283
while (val == UNBOUND && NOT_THROWING)
284
val = err_logo(NO_VALUE, node__colon(exp));
286
case CONS: /* procedure application */
287
if (tailcall == 1 && is_macro(car(exp)) &&
288
(is_list(procnode__caseobj(car(exp)))
289
|| !compare_node(car(exp), Goto, TRUE))) {
290
/* tail call to user-defined macro must be treated as non-tail
291
* because the expression returned by the macro
292
* remains to be evaluated in the caller's context */
297
if (fun == Not_Enough_Node) {
298
err_logo(TOO_MUCH, NIL);
306
case ARRAY: /* array must be copied */
307
val = deep_copy(exp);
310
val = exp; /* self-evaluating */
315
/* Evaluate an application of a procedure with no arguments. */
317
goto apply_dispatch; /* apply the procedure */
320
/* Evaluate an application of a procedure with arguments. */
323
mixsave(tailcall,var);
324
num2save(val_status,ift_iff_flag);
325
save2(didnt_get_output,didnt_output_name);
327
if (unev == NIL) goto eval_args_done;
329
if (exp == Not_Enough_Node) {
331
err_logo(NOT_ENOUGH, NIL);
336
save2(ufun,last_ufun);
337
save2(this_line,last_line);
341
didnt_get_output = cons_list(0, fun, ufun, this_line, END_OF_LIST);
342
didnt_output_name = NIL;
343
newcont(accumulate_arg);
344
goto eval_dispatch; /* evaluate the current argument */
347
/* Put the evaluated argument into the argl list. */
349
restore2(this_line,last_line);
350
restore2(ufun,last_ufun);
354
while (NOT_THROWING && val == UNBOUND) {
355
val = err_logo(DIDNT_OUTPUT, NIL);
362
restore2(didnt_get_output,didnt_output_name);
363
num2restore(val_status,ift_iff_flag);
364
mixrestore(tailcall,var);
365
if (stopping_flag == THROWING) {
369
argl = reverse(argl);
370
/* --------------------- APPLY ---------------------------- */
372
/* Load in the procedure's definition and decide whether it's a compound
373
* procedure or a primitive procedure.
375
proc = procnode__caseobj(fun);
377
num2save(val_status,tailcall);
379
newcont(macro_return);
381
if (proc == UNDEFINED) { /* 5.0 punctuationless variables */
382
if (compare_node(valnode__caseobj(AllowGetSet),True,TRUE)
383
!= 0) { /* No getter/setter allowed, punt */
384
val = err_logo(DK_HOW, fun);
386
} else if (argl == NIL) { /* possible var getter */
387
val = valnode__caseobj(fun);
388
if (val == UNBOUND && NOT_THROWING)
389
val = err_logo(DK_HOW, fun);
390
else if (val != UNBOUND) {
391
(void)ldefine(cons(fun, cons(
392
cons(NIL,cons(cons(Output,cons(make_colon(fun),NIL)),NIL))
393
,NIL))); /* make real proc so no disk load next time */
394
setflag__caseobj(fun,PROC_BURIED);
397
} else { /* var setter */
398
(void)ldefine(cons(fun, cons(
401
cons(make_quote(bf3(fun)),
402
cons(Dotsvalue,NIL))),
405
setflag__caseobj(fun,PROC_BURIED);
406
argl = cons(bf3(fun), argl);
412
if (is_list(proc)) goto compound_apply;
413
/* primitive_apply */
415
if ((tracing = flag__caseobj(fun, PROC_TRACED))) {
416
for (i = 0; i < trace_level; i++) {
419
ndprintf(stdout, "( %s ", fun);
423
print_node(stdout, maybe_quote(car(arg)));
428
print_char(stdout, ')');
431
val = (*getprimfun(proc))(argl);
432
if (tracing && NOT_THROWING) {
433
for (i = 0; i < trace_level; i++) {
436
print_node(stdout, fun);
438
ndprintf(stdout, " %t\n", message_texts[TRACE_STOPS]);
440
ndprintf(stdout, " %t %s\n", message_texts[TRACE_OUTPUTS],
446
#define do_case(x) case x: goto x;
449
enum labels x = (enum labels)cont;
450
cont = (FIXNUM)car(numstack);
451
numstack=cdr(numstack);
465
if ((tracing = flag__caseobj(fun, PROC_TRACED))) {
466
for (i = 0; i < trace_level; i++) print_space(writestream);
468
ndprintf(writestream, "( %s ", fun);
470
/* Bind the actuals to the formals */
472
vsp = var_stack; /* remember where we came in */
473
for (formals = formals__procnode(proc);
475
formals = cdr(formals)) {
477
if (nodetype(parm) == INT) break; /* default # args */
481
print_node(writestream, maybe_quote(arg));
482
print_space(writestream);
486
if (nodetype(parm) == CASEOBJ) {
487
if (not_local(parm,vsp)) {
488
push(parm, var_stack);
489
var_stack->n_obj = valnode__caseobj(parm);
492
setvalnode__caseobj(parm, arg);
494
err_logo(NOT_ENOUGH, fun);
495
} else if (nodetype(parm) == CONS) {
496
/* parm is optional or rest */
497
if (not_local(car(parm),vsp)) {
498
push(car(parm), var_stack);
499
var_stack->n_obj = valnode__caseobj(car(parm));
501
tell_shadow(car(parm));
502
if (cdr(parm) == NIL) { /* parm is rest */
503
setvalnode__caseobj(car(parm), argl);
505
if (argl != NIL) pop(argl);
506
while (argl != NIL) {
508
print_node(writestream, maybe_quote(arg));
509
print_space(writestream);
515
if (arg == UNBOUND) { /* use default */
518
save2(ufun,last_ufun);
519
save2(this_line,last_line);
520
save2(didnt_output_name,didnt_get_output);
521
num2save(ift_iff_flag,val_status);
532
if (!is_tree(list)) {
534
goto set_args_continue;
536
unev = tree__tree(list);
538
newcont(set_args_continue);
543
restore2(formals,argl);
546
num2restore(ift_iff_flag,val_status);
547
restore2(didnt_output_name,didnt_get_output);
548
restore2(this_line,last_line);
549
restore2(ufun,last_ufun);
554
setvalnode__caseobj(car(parm), arg);
556
if (argl != NIL) pop(argl);
559
err_logo(TOO_MUCH, NIL);
561
if (check_throwing) {
566
if ((tracing = !is_list(fun)) && flag__caseobj(fun, PROC_TRACED)) {
567
if (NOT_THROWING) print_char(writestream, ')');
568
new_line(writestream);
570
newcont(compound_apply_continue);
574
if (!is_list(fun)) ufun = fun;
575
last_line = this_line;
577
proc = (is_list(fun) ? anonymous_function(fun) : procnode__caseobj(fun));
578
list = bodylist__procnode(proc); /* get the body ... */
579
make_tree_from_body(list);
580
if (!is_tree(list)) {
583
unev = tree__tree(list);
584
if (NOT_THROWING) stopping_flag = RUN;
585
output_node = UNBOUND;
586
if (val_status == 1) val_status = 2;
587
else if (val_status == 5) val_status = 3;
590
/* Evaluate each expression in the sequence. Stop as soon as
593
if (!RUNNING || val != UNBOUND) {
596
if (nodetype(unev) == LINE) {
597
if (the_generation != (generation__line(unev))) {
598
/* something redefined while we're running */
600
this_line = tree__tree(bodylist__procnode(proc));
601
while (this_line != unev) {
602
/* If redef isn't end of line, don't try to fix,
603
but don't blow up either. (Maybe not called from here.) */
604
if (this_line == NULL) goto nofix;
605
if (nodetype(this_line) == LINE) linenum++;
606
this_line = cdr(this_line);
608
untreeify_proc(proc);
609
make_tree_from_body(bodylist__procnode(proc));
610
unev = tree__tree(bodylist__procnode(proc));
611
while (--linenum >= 0) {
613
while (unev != NIL && nodetype(unev) != LINE);
616
nofix: this_line = unparsed__line(unev);
617
if (ufun != NIL && flag__caseobj(ufun, PROC_STEPPED)) {
620
while (i++ < trace_level) print_space(stdout);
622
print_node(stdout, this_line);
623
(void)reader(stdin, " >>> ");
629
is_list(exp) && (is_tailform(procnode__caseobj(car(exp))))) {
630
i = (int)getprimpri(procnode__caseobj(car(exp)));
631
if (i == OUTPUT_PRIORITY) {
632
didnt_get_output = cons_list(0,car(exp),ufun,this_line,END_OF_LIST);
633
didnt_output_name = NIL;
634
if (cadr(exp) == Not_Enough_Node) {
635
err_logo(NOT_ENOUGH,car(exp));
639
if (val_status == 2 || val_status == 3) {
642
goto tail_eval_dispatch;
643
} else if (ufun == NIL) {
644
err_logo(AT_TOPLEVEL,car(exp));
647
} else if (val_status < 4) {
651
goto non_tail_eval; /* compute value then give error */
653
} else if (i == STOP_PRIORITY) {
655
err_logo(AT_TOPLEVEL,car(exp));
658
} else if (val_status == 0 || val_status == 3) {
661
} else if (val_status < 4) {
662
didnt_output_name = fun;
666
} else { /* maybeoutput */
669
goto tail_eval_dispatch;
673
if (val_status == 2 || val_status == 4) {
674
didnt_output_name = fun;
678
goto tail_eval_dispatch;
681
if (car(unev) != NIL && is_list(car(unev)) &&
682
(is_tailform(procnode__caseobj(car(car(unev))))) &&
683
getprimpri(procnode__caseobj(car(car(unev)))) == STOP_PRIORITY) {
684
if ((val_status == 0 || val_status == 3) && ufun != NIL) {
685
goto tail_eval_dispatch;
686
} else if (val_status < 4 && ufun != NIL) {
687
didnt_output_name = fun;
688
goto tail_eval_dispatch;
693
num2save(ift_iff_flag,val_status);
694
save2(ufun,last_ufun);
695
save2(this_line,last_line);
701
newcont(eval_sequence_continue);
704
eval_sequence_continue:
708
restore2(this_line,last_line);
709
restore2(ufun,last_ufun);
711
num2restore(dont_fix_ift,val_status);
714
num2restore(ift_iff_flag,val_status);
716
if (stopping_flag == MACRO_RETURN) {
717
if (unev == UNBOUND) unev = NIL;
718
if (val != NIL && is_list(val) && (car(val) == Tag))
719
unev = cdr(val); /* from goto */
721
unev = append(val, unev);
724
if (unev == NIL) goto fetch_cont;
725
} else if (val_status < 4) {
726
if (STOPPING || RUNNING) output_node = UNBOUND;
727
if (stopping_flag == OUTPUT || STOPPING) {
730
if (val != UNBOUND && val_status == 1 && NOT_THROWING) {
731
didnt_output_name = Output;
732
err_logo(DIDNT_OUTPUT,Output);
734
if (val == UNBOUND && val_status == 1 && NOT_THROWING) {
735
didnt_output_name = Stop;
736
err_logo(DIDNT_OUTPUT,Output);
741
if (val != UNBOUND) {
742
err_logo((unev == NIL ? DK_WHAT_UP : DK_WHAT), val);
745
if (NOT_THROWING && (unev == NIL || unev == UNBOUND)) {
746
if (val_status != 4) err_logo(DIDNT_OUTPUT,NIL);
751
compound_apply_continue:
752
/* Only get here if tracing */
756
for (i = 0; i < trace_level; i++) print_space(writestream);
757
print_node(writestream, fun);
759
ndprintf(writestream, " %t\n", message_texts[TRACE_STOPS]);
761
ndprintf(writestream, " %t %s\n", message_texts[TRACE_OUTPUTS],
767
/* --------------------- MACROS ---------------------------- */
770
num2restore(val_status,tailcall);
771
while (!is_list(val) && NOT_THROWING) {
772
val = err_logo(ERR_MACRO,val);
776
newcont(cont__cont(val));
777
val = val__cont(val);
783
stopping_flag = MACRO_RETURN;
784
if (!is_tree(val)) val = NIL;
785
else val = tree__tree(val);
786
} else val = UNBOUND;
800
runresult_continuation:
802
newcont(runresult_followup);
807
if (val == UNBOUND) {
810
val = cons(val, NIL);
816
repcount = getint(car(val));
826
num2save(repcount,user_repcount);
827
num2save(val_status,tailcall);
829
newcont(repeat_followup);
833
if (val != UNBOUND && NOT_THROWING) {
834
err_logo(DK_WHAT, val);
836
num2restore(val_status,tailcall);
837
num2restore(repcount,user_repcount);
839
if (val_status < 4 && tailcall != 0) {
840
if (STOPPING || RUNNING) output_node = UNBOUND;
841
if (stopping_flag == OUTPUT || STOPPING) {
844
if (val != UNBOUND && val_status < 2) {
845
err_logo(DK_WHAT_UP,val);
850
if (repcount > 0) /* negative means forever */
858
if (RUNNING) goto repeat_again;
865
catch_tag = car(val);
866
if (compare_node(catch_tag,Error,TRUE) == 0) {
867
push(Erract, var_stack);
868
var_stack->n_obj = valnode__caseobj(Erract);
869
setvalnode__caseobj(Erract, UNBOUND);
872
save2(didnt_output_name,didnt_get_output);
873
num2save(val_status,tailcall);
874
newcont(catch_followup);
879
num2restore(val_status,tailcall);
880
restore2(didnt_output_name,didnt_get_output);
882
if (val_status < 4 && tailcall != 0) {
883
if (STOPPING || RUNNING) output_node = UNBOUND;
884
if (stopping_flag == OUTPUT || STOPPING) {
887
if (val != UNBOUND && val_status < 2) {
888
err_logo(DK_WHAT_UP,val);
892
if (stopping_flag == THROWING &&
893
compare_node(throw_node, catch_tag, TRUE) == 0) {
894
throw_node = UNBOUND;
903
err_logo(AT_TOPLEVEL, Goto);
907
proc = procnode__caseobj(ufun);
908
list = bodylist__procnode(proc);
909
unev = tree__tree(list);
910
while (unev != NIL && !check_throwing) {
911
if (nodetype(unev) == LINE)
912
this_line = unparsed__line(unev);
916
(object__caseobj(car(exp)) == object__caseobj(Tag)) &&
917
(nodetype(cadr(exp)) == QUOTE) &&
918
compare_node(val, node__quote(cadr(exp)), TRUE) == 0) {
919
val = cons(Tag, unev);
920
stopping_flag = MACRO_RETURN;
924
err_logo(BAD_DATA_UNREC, val);
930
/* This is for lapply. */
932
while (nodetype(fun) == ARRAY && NOT_THROWING)
933
fun = err_logo(APPLY_BAD_DATA, fun);
936
while (!is_list(argl) && NOT_THROWING)
937
argl = err_logo(APPLY_BAD_DATA, argl);
938
if (NOT_THROWING && fun != NIL) {
939
if (is_list(fun)) { /* template */
940
if (is_list(car(fun)) && cdr(fun) != NIL) {
941
if (is_list(cadr(fun))) { /* procedure text form */
942
proc = anonymous_function(fun);
951
llocal(formals); /* bind the formals locally */
952
numrestore(tailcall);
954
formals && argl && NOT_THROWING;
955
formals = cdr(formals),
957
setvalnode__caseobj(car(formals), car(argl));
960
newcont(after_lambda);
962
} else { /* question-mark form */
968
if (list == NIL || !is_tree(list)) {
971
unev = tree__tree(list);
972
save2(didnt_output_name,didnt_get_output);
973
num2save(val_status,tailcall);
974
newcont(qm_continue);
979
num2restore(val_status,tailcall);
980
restore2(didnt_output_name,didnt_get_output);
981
if (val_status < 4 && tailcall != 0) {
982
if (STOPPING || RUNNING) output_node = UNBOUND;
983
if (stopping_flag == OUTPUT || STOPPING) {
986
if (val != UNBOUND && val_status < 2) {
987
err_logo(DK_WHAT_UP,val);
995
} else { /* name of procedure to apply */
999
if (procnode__caseobj(fun) == UNDEFINED && NOT_THROWING &&
1001
silent_load(fun, NULL); /* try ./<fun>.lg */
1002
if (procnode__caseobj(fun) == UNDEFINED && NOT_THROWING &&
1004
silent_load(fun, logolib); /* try <logolib>/<fun> */
1005
proc = procnode__caseobj(fun);
1006
while (proc == UNDEFINED && NOT_THROWING) {
1007
val = err_logo(DK_HOW_UNREC, fun);
1010
if (nodetype(proc) == CONS) {
1011
min = getint(minargs__procnode(proc));
1012
max = getint(maxargs__procnode(proc));
1014
if (getprimdflt(proc) < 0) { /* special form */
1015
err_logo(DK_HOW_UNREC, fun); /* can't apply */
1018
min = getprimmin(proc);
1019
max = getprimmax(proc);
1022
for (n = 0, arg = argl; arg != NIL; n++, arg = cdr(arg));
1024
err_logo(NOT_ENOUGH, NIL);
1025
} else if (n > max && max >= 0) {
1026
err_logo(TOO_MUCH, NIL);
1028
goto apply_dispatch;
1041
tailcall = oldtailcall;
1042
ift_iff_flag = old_ift_iff;
1045
restore2(var,this_line);