* __scm.h (SCM_WTA_DISPATCH_n, SCM_GASSERTn): New macros.
[bpt/guile.git] / libguile / eval.c
CommitLineData
d9c393f5 1/* Copyright (C) 1995,1996,1997,1998, 1999 Free Software Foundation, Inc.
0f2d19dd
JB
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
82892bed
JB
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
0f2d19dd
JB
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
82892bed 40 * If you do not wish that, delete this exception notice. */
0f2d19dd
JB
41\f
42
6dbd0af5
MD
43/* This file is read twice in order to produce debugging versions of
44 * scm_ceval and scm_apply. These functions, scm_deval and
45 * scm_dapply, are produced when we define the preprocessor macro
46 * DEVAL. The file is divided into sections which are treated
47 * differently with respect to DEVAL. The heads of these sections are
48 * marked with the string "SECTION:".
49 */
50
51
52/* SECTION: This code is compiled once.
0f2d19dd
JB
53 */
54
55#ifndef DEVAL
56
d16332b3
JB
57/* We need this to get the definitions for HAVE_ALLOCA_H, etc. */
58#include "scmconfig.h"
59
48b96f4b
JB
60/* AIX requires this to be the first thing in the file. The #pragma
61 directive is indented so pre-ANSI compilers will ignore it, rather
62 than choke on it. */
5862b540 63#ifndef __GNUC__
48b96f4b
JB
64# if HAVE_ALLOCA_H
65# include <alloca.h>
66# else
67# ifdef _AIX
68 #pragma alloca
69# else
70# ifndef alloca /* predefined by HP cc +Olibcalls */
71char *alloca ();
72# endif
73# endif
74# endif
75#endif
76
0f2d19dd
JB
77#include <stdio.h>
78#include "_scm.h"
20e6290e 79#include "debug.h"
20e6290e 80#include "alist.h"
20e6290e
JB
81#include "eq.h"
82#include "continuations.h"
83#include "throw.h"
84#include "smob.h"
6cb702da 85#include "macros.h"
20e6290e
JB
86#include "procprop.h"
87#include "hashtab.h"
ac46ab16 88#include "hash.h"
20e6290e
JB
89#include "srcprop.h"
90#include "stackchk.h"
0c32d76c
MD
91#include "objects.h"
92#include "feature.h"
185905af 93#include "modules.h"
20e6290e
JB
94
95#include "eval.h"
89efbff4 96
61364ba6
MD
97SCM (*scm_memoize_method) (SCM, SCM);
98
0f2d19dd
JB
99\f
100
6dbd0af5
MD
101/* The evaluator contains a plethora of EVAL symbols.
102 * This is an attempt at explanation.
103 *
104 * The following macros should be used in code which is read twice
105 * (where the choice of evaluator is hard soldered):
106 *
107 * SCM_CEVAL is the symbol used within one evaluator to call itself.
108 * Originally, it is defined to scm_ceval, but is redefined to
109 * scm_deval during the second pass.
110 *
111 * SIDEVAL corresponds to SCM_CEVAL, but is used in situations where
112 * only side effects of expressions matter. All immediates are
113 * ignored.
114 *
6cb702da 115 * SCM_EVALIM is used when it is known that the expression is an
6dbd0af5
MD
116 * immediate. (This macro never calls an evaluator.)
117 *
118 * EVALCAR evaluates the car of an expression.
119 *
120 * EVALCELLCAR is like EVALCAR, but is used when it is known that the
121 * car is a lisp cell.
122 *
123 * The following macros should be used in code which is read once
124 * (where the choice of evaluator is dynamic):
125 *
6cb702da 126 * SCM_XEVAL takes care of immediates without calling an evaluator. It
6dbd0af5
MD
127 * then calls scm_ceval *or* scm_deval, depending on the debugging
128 * mode.
129 *
6cb702da 130 * SCM_XEVALCAR corresponds to EVALCAR, but uses scm_ceval *or* scm_deval
6dbd0af5
MD
131 * depending on the debugging mode.
132 *
133 * The main motivation for keeping this plethora is efficiency
134 * together with maintainability (=> locality of code).
135 */
136
6cb702da 137#define SCM_CEVAL scm_ceval
ff467021 138#define SIDEVAL(x, env) if (SCM_NIMP(x)) SCM_CEVAL((x), (env))
6cb702da 139
0f2d19dd 140#define EVALCELLCAR(x, env) (SCM_SYMBOLP (SCM_CAR(x)) \
26d5b9b4 141 ? *scm_lookupcar(x, env, 1) \
0f2d19dd
JB
142 : SCM_CEVAL(SCM_CAR(x), env))
143
0f2d19dd
JB
144#define EVALCAR(x, env) (SCM_NCELLP(SCM_CAR(x))\
145 ? (SCM_IMP(SCM_CAR(x)) \
6cb702da 146 ? SCM_EVALIM(SCM_CAR(x), env) \
0f2d19dd
JB
147 : SCM_GLOC_VAL(SCM_CAR(x))) \
148 : EVALCELLCAR(x, env))
0f2d19dd 149
e2806c10 150#define EXTEND_ENV SCM_EXTEND_ENV
0f2d19dd
JB
151
152#ifdef MEMOIZE_LOCALS
1cc91f1b 153
0f2d19dd
JB
154SCM *
155scm_ilookup (iloc, env)
156 SCM iloc;
157 SCM env;
0f2d19dd
JB
158{
159 register int ir = SCM_IFRAME (iloc);
160 register SCM er = env;
161 for (; 0 != ir; --ir)
162 er = SCM_CDR (er);
163 er = SCM_CAR (er);
164 for (ir = SCM_IDIST (iloc); 0 != ir; --ir)
165 er = SCM_CDR (er);
166 if (SCM_ICDRP (iloc))
a23afe53
MD
167 return SCM_CDRLOC (er);
168 return SCM_CARLOC (SCM_CDR (er));
0f2d19dd
JB
169}
170#endif
171
f8769b1d
MV
172#ifdef USE_THREADS
173
174/* The Lookup Car Race
175 - by Eva Luator
176
177 Memoization of variables and special forms is done while executing
178 the code for the first time. As long as there is only one thread
179 everything is fine, but as soon as two threads execute the same
180 code concurrently `for the first time' they can come into conflict.
181
182 This memoization includes rewriting variable references into more
183 efficient forms and expanding macros. Furthermore, macro expansion
184 includes `compiling' special forms like `let', `cond', etc. into
185 tree-code instructions.
186
187 There shouldn't normally be a problem with memoizing local and
188 global variable references (into ilocs and glocs), because all
189 threads will mutate the code in *exactly* the same way and (if I
190 read the C code correctly) it is not possible to observe a half-way
191 mutated cons cell. The lookup procedure can handle this
192 transparently without any critical sections.
193
194 It is different with macro expansion, because macro expansion
195 happens outside of the lookup procedure and can't be
196 undone. Therefore it can't cope with it. It has to indicate
197 failure when it detects a lost race and hope that the caller can
198 handle it. Luckily, it turns out that this is the case.
199
200 An example to illustrate this: Suppose that the follwing form will
201 be memoized concurrently by two threads
202
203 (let ((x 12)) x)
204
205 Let's first examine the lookup of X in the body. The first thread
206 decides that it has to find the symbol "x" in the environment and
207 starts to scan it. Then the other thread takes over and actually
208 overtakes the first. It looks up "x" and substitutes an
209 appropriate iloc for it. Now the first thread continues and
210 completes its lookup. It comes to exactly the same conclusions as
211 the second one and could - without much ado - just overwrite the
212 iloc with the same iloc.
213
214 But let's see what will happen when the race occurs while looking
215 up the symbol "let" at the start of the form. It could happen that
216 the second thread interrupts the lookup of the first thread and not
217 only substitutes a gloc for it but goes right ahead and replaces it
218 with the compiled form (#@let* (x 12) x). Now, when the first
219 thread completes its lookup, it would replace the #@let* with a
220 gloc pointing to the "let" binding, effectively reverting the form
221 to (let (x 12) x). This is wrong. It has to detect that it has
222 lost the race and the evaluator has to reconsider the changed form
223 completely.
224
225 This race condition could be resolved with some kind of traffic
226 light (like mutexes) around scm_lookupcar, but I think that it is
227 best to avoid them in this case. They would serialize memoization
228 completely and because lookup involves calling arbitrary Scheme
229 code (via the lookup-thunk), threads could be blocked for an
230 arbitrary amount of time or even deadlock. But with the current
231 solution a lot of unnecessary work is potentially done. */
232
233/* SCM_LOOKUPCAR1 is was SCM_LOOKUPCAR used to be but is allowed to
234 return NULL to indicate a failed lookup due to some race conditions
235 between threads. This only happens when VLOC is the first cell of
236 a special form that will eventually be memoized (like `let', etc.)
237 In that case the whole lookup is bogus and the caller has to
238 reconsider the complete special form.
239
240 SCM_LOOKUPCAR is still there, of course. It just calls
241 SCM_LOOKUPCAR1 and aborts on recieving NULL. So SCM_LOOKUPCAR
242 should only be called when it is known that VLOC is not the first
243 pair of a special form. Otherwise, use SCM_LOOKUPCAR1 and check
26d5b9b4
MD
244 for NULL. I think I've found the only places where this
245 applies. */
f8769b1d
MV
246
247#endif /* USE_THREADS */
1cc91f1b 248
26d5b9b4
MD
249/* scm_lookupcar returns a pointer to this when a variable could not
250 be found and it should not throw an error. Never assign to this.
251*/
252static scm_cell undef_cell = { SCM_UNDEFINED, SCM_UNDEFINED };
253
d0b7bad7 254#ifdef USE_THREADS
8ecf1f13 255static SCM *
26d5b9b4 256scm_lookupcar1 (SCM vloc, SCM genv, int check)
d0b7bad7
MD
257#else
258SCM *
26d5b9b4 259scm_lookupcar (SCM vloc, SCM genv, int check)
d0b7bad7 260#endif
0f2d19dd
JB
261{
262 SCM env = genv;
e3173f93
JB
263 register SCM *al, fl, var = SCM_CAR (vloc);
264#ifdef USE_THREADS
265 register SCM var2 = var;
266#endif
0f2d19dd
JB
267#ifdef MEMOIZE_LOCALS
268 register SCM iloc = SCM_ILOC00;
269#endif
270 for (; SCM_NIMP (env); env = SCM_CDR (env))
271 {
272 if (SCM_BOOL_T == scm_procedure_p (SCM_CAR (env)))
273 break;
a23afe53 274 al = SCM_CARLOC (env);
0f2d19dd
JB
275 for (fl = SCM_CAR (*al); SCM_NIMP (fl); fl = SCM_CDR (fl))
276 {
277 if (SCM_NCONSP (fl))
33b97402 278 {
0f2d19dd
JB
279 if (fl == var)
280 {
281#ifdef MEMOIZE_LOCALS
f8769b1d
MV
282#ifdef USE_THREADS
283 if (SCM_CAR (vloc) != var)
284 goto race;
285#endif
a23afe53 286 SCM_SETCAR (vloc, iloc + SCM_ICDR);
0f2d19dd 287#endif
a23afe53 288 return SCM_CDRLOC (*al);
0f2d19dd 289 }
33b97402
MD
290 else
291 break;
292 }
a23afe53 293 al = SCM_CDRLOC (*al);
0f2d19dd
JB
294 if (SCM_CAR (fl) == var)
295 {
296#ifdef MEMOIZE_LOCALS
cf7c17e9 297#ifndef SCM_RECKLESS /* letrec inits to SCM_UNDEFINED */
0f2d19dd
JB
298 if (SCM_UNBNDP (SCM_CAR (*al)))
299 {
300 env = SCM_EOL;
301 goto errout;
302 }
f8769b1d
MV
303#endif
304#ifdef USE_THREADS
305 if (SCM_CAR (vloc) != var)
306 goto race;
0f2d19dd 307#endif
a23afe53 308 SCM_SETCAR (vloc, iloc);
0f2d19dd 309#endif
a23afe53 310 return SCM_CARLOC (*al);
0f2d19dd
JB
311 }
312#ifdef MEMOIZE_LOCALS
313 iloc += SCM_IDINC;
314#endif
315 }
316#ifdef MEMOIZE_LOCALS
317 iloc = (~SCM_IDSTMSK) & (iloc + SCM_IFRINC);
318#endif
319 }
320 {
321 SCM top_thunk, vcell;
322 if (SCM_NIMP(env))
323 {
324 top_thunk = SCM_CAR(env); /* env now refers to a top level env thunk */
325 env = SCM_CDR (env);
326 }
327 else
328 top_thunk = SCM_BOOL_F;
329 vcell = scm_sym2vcell (var, top_thunk, SCM_BOOL_F);
330 if (vcell == SCM_BOOL_F)
331 goto errout;
332 else
333 var = vcell;
334 }
cf7c17e9 335#ifndef SCM_RECKLESS
0f2d19dd
JB
336 if (SCM_NNULLP (env) || SCM_UNBNDP (SCM_CDR (var)))
337 {
338 var = SCM_CAR (var);
339 errout:
f5bf2977 340 /* scm_everr (vloc, genv,...) */
26d5b9b4
MD
341 if (check)
342 scm_misc_error (NULL,
343 SCM_NULLP (env)
344 ? "Unbound variable: %S"
345 : "Damaged environment: %S",
346 scm_listify (var, SCM_UNDEFINED));
347 else
348 return SCM_CDRLOC (&undef_cell);
0f2d19dd
JB
349 }
350#endif
f8769b1d
MV
351#ifdef USE_THREADS
352 if (SCM_CAR (vloc) != var2)
353 {
354 /* Some other thread has changed the very cell we are working
355 on. In effect, it must have done our job or messed it up
356 completely. */
357 race:
358 var = SCM_CAR (vloc);
359 if ((var & 7) == 1)
360 return SCM_GLOC_VAL_LOC (var);
361#ifdef MEMOIZE_LOCALS
362 if ((var & 127) == (127 & SCM_ILOC00))
363 return scm_ilookup (var, genv);
364#endif
365 /* We can't cope with anything else than glocs and ilocs. When
366 a special form has been memoized (i.e. `let' into `#@let') we
367 return NULL and expect the calling function to do the right
368 thing. For the evaluator, this means going back and redoing
369 the dispatch on the car of the form. */
370 return NULL;
371 }
372#endif /* USE_THREADS */
373
a23afe53 374 SCM_SETCAR (vloc, var + 1);
0f2d19dd 375 /* Except wait...what if the var is not a vcell,
f8769b1d 376 * but syntax or something.... */
a23afe53 377 return SCM_CDRLOC (var);
0f2d19dd
JB
378}
379
f8769b1d
MV
380#ifdef USE_THREADS
381SCM *
26d5b9b4 382scm_lookupcar (vloc, genv, check)
f8769b1d
MV
383 SCM vloc;
384 SCM genv;
26d5b9b4 385 int check;
f8769b1d 386{
26d5b9b4 387 SCM *loc = scm_lookupcar1 (vloc, genv, check);
f8769b1d
MV
388 if (loc == NULL)
389 abort ();
390 return loc;
391}
f8769b1d
MV
392#endif
393
0f2d19dd 394#define unmemocar scm_unmemocar
1cc91f1b 395
0f2d19dd
JB
396SCM
397scm_unmemocar (form, env)
398 SCM form;
399 SCM env;
0f2d19dd 400{
6dbd0af5 401#ifdef DEBUG_EXTENSIONS
0f2d19dd 402 register int ir;
6dbd0af5 403#endif
0f2d19dd
JB
404 SCM c;
405
406 if (SCM_IMP (form))
407 return form;
408 c = SCM_CAR (form);
409 if (1 == (c & 7))
a23afe53 410 SCM_SETCAR (form, SCM_CAR (c - 1));
0f2d19dd 411#ifdef MEMOIZE_LOCALS
6dbd0af5 412#ifdef DEBUG_EXTENSIONS
0f2d19dd
JB
413 else if (SCM_ILOCP (c))
414 {
415 for (ir = SCM_IFRAME (c); ir != 0; --ir)
416 env = SCM_CDR (env);
417 env = SCM_CAR (SCM_CAR (env));
418 for (ir = SCM_IDIST (c); ir != 0; --ir)
419 env = SCM_CDR (env);
a23afe53 420 SCM_SETCAR (form, SCM_ICDRP (c) ? env : SCM_CAR (env));
0f2d19dd 421 }
6dbd0af5 422#endif
0f2d19dd
JB
423#endif
424 return form;
425}
426
1cc91f1b 427
0f2d19dd
JB
428SCM
429scm_eval_car (pair, env)
430 SCM pair;
431 SCM env;
0f2d19dd 432{
6cb702da 433 return SCM_XEVALCAR (pair, env);
0f2d19dd
JB
434}
435
436\f
437/*
438 * The following rewrite expressions and
439 * some memoized forms have different syntax
440 */
441
3eeba8d4
JB
442const char scm_s_expression[] = "missing or extra expression";
443const char scm_s_test[] = "bad test";
444const char scm_s_body[] = "bad body";
445const char scm_s_bindings[] = "bad bindings";
446const char scm_s_variable[] = "bad variable";
447const char scm_s_clauses[] = "bad or missing clauses";
448const char scm_s_formals[] = "bad formals";
0f2d19dd 449
81123e6d
MD
450SCM scm_sym_dot, scm_sym_arrow, scm_sym_else;
451SCM scm_sym_unquote, scm_sym_uq_splicing, scm_sym_apply;
452
453SCM scm_f_apply;
b8229a3b 454
6dbd0af5 455#ifdef DEBUG_EXTENSIONS
2f0d1375
MD
456SCM scm_sym_enter_frame, scm_sym_apply_frame, scm_sym_exit_frame;
457SCM scm_sym_trace;
6dbd0af5 458#endif
0f2d19dd
JB
459
460#define ASRTSYNTAX(cond_, msg_) if(!(cond_))scm_wta(xorig, (msg_), what);
461
462
1cc91f1b 463
e4755e5c 464static void bodycheck SCM_P ((SCM xorig, SCM *bodyloc, const char *what));
1cc91f1b 465
0f2d19dd
JB
466static void
467bodycheck (xorig, bodyloc, what)
468 SCM xorig;
469 SCM *bodyloc;
e4755e5c 470 const char *what;
0f2d19dd 471{
6cb702da 472 ASRTSYNTAX (scm_ilength (*bodyloc) >= 1, scm_s_expression);
0f2d19dd
JB
473}
474
26d5b9b4
MD
475/* Check that the body denoted by XORIG is valid and rewrite it into
476 its internal form. The internal form of a body is just the body
477 itself, but prefixed with an ISYM that denotes to what kind of
478 outer construct this body belongs. A lambda body starts with
479 SCM_IM_LAMBDA, for example, a body of a let starts with SCM_IM_LET,
480 etc. The one exception is a body that belongs to a letrec that has
481 been formed by rewriting internal defines: it starts with
482 SCM_IM_DEFINE. */
483
484/* XXX - Besides controlling the rewriting of internal defines, the
485 additional ISYM could be used for improved error messages.
486 This is not done yet. */
487
488static SCM
489scm_m_body (op, xorig, what)
490 SCM op;
491 SCM xorig;
492 char *what;
493{
494 ASRTSYNTAX (scm_ilength (xorig) >= 1, scm_s_expression);
495
496 /* Don't add another ISYM if one is present already. */
497 if (SCM_ISYMP (SCM_CAR (xorig)))
498 return xorig;
499
500 /* Retain possible doc string. */
501 if (SCM_IMP (SCM_CAR(xorig)) || SCM_NCONSP (SCM_CAR (xorig)))
502 {
503 if (SCM_NNULLP (SCM_CDR(xorig)))
504 return scm_cons (SCM_CAR (xorig),
505 scm_m_body (op, SCM_CDR(xorig), what));
506 return xorig;
507 }
508
509 return scm_cons2 (op, SCM_CAR (xorig), SCM_CDR(xorig));
510}
511
b8229a3b 512SCM_SYNTAX(s_quote,"quote", scm_makmmacro, scm_m_quote);
2f0d1375 513SCM_GLOBAL_SYMBOL(scm_sym_quote, s_quote);
1cc91f1b 514
0f2d19dd
JB
515SCM
516scm_m_quote (xorig, env)
517 SCM xorig;
518 SCM env;
0f2d19dd 519{
26d5b9b4
MD
520 SCM x = scm_copy_tree (SCM_CDR (xorig));
521
6cb702da 522 SCM_ASSYNT (scm_ilength (SCM_CDR (xorig)) == 1,
b8229a3b 523 xorig, scm_s_expression, s_quote);
3a3111a8 524 return scm_cons (SCM_IM_QUOTE, x);
0f2d19dd
JB
525}
526
527
1cc91f1b 528
b8229a3b 529SCM_SYNTAX(s_begin, "begin", scm_makmmacro, scm_m_begin);
2f0d1375 530SCM_GLOBAL_SYMBOL(scm_sym_begin, s_begin);
b8229a3b 531
0f2d19dd
JB
532SCM
533scm_m_begin (xorig, env)
534 SCM xorig;
535 SCM env;
0f2d19dd 536{
6cb702da 537 SCM_ASSYNT (scm_ilength (SCM_CDR (xorig)) >= 1,
b8229a3b 538 xorig, scm_s_expression, s_begin);
3a3111a8 539 return scm_cons (SCM_IM_BEGIN, SCM_CDR (xorig));
0f2d19dd
JB
540}
541
b8229a3b 542SCM_SYNTAX(s_if, "if", scm_makmmacro, scm_m_if);
2f0d1375 543SCM_GLOBAL_SYMBOL(scm_sym_if, s_if);
1cc91f1b 544
0f2d19dd
JB
545SCM
546scm_m_if (xorig, env)
547 SCM xorig;
548 SCM env;
0f2d19dd
JB
549{
550 int len = scm_ilength (SCM_CDR (xorig));
6cb702da 551 SCM_ASSYNT (len >= 2 && len <= 3, xorig, scm_s_expression, "if");
3a3111a8 552 return scm_cons (SCM_IM_IF, SCM_CDR (xorig));
0f2d19dd
JB
553}
554
555
89efbff4
MD
556/* Will go into the RnRS module when Guile is factorized.
557SCM_SYNTAX(scm_s_set_x,"set!", scm_makmmacro, scm_m_set_x); */
558const char scm_s_set_x[] = "set!";
559SCM_GLOBAL_SYMBOL(scm_sym_set_x, scm_s_set_x);
1cc91f1b 560
0f2d19dd 561SCM
89efbff4 562scm_m_set_x (xorig, env)
0f2d19dd
JB
563 SCM xorig;
564 SCM env;
0f2d19dd 565{
6dbd0af5 566 SCM x = SCM_CDR (xorig);
89efbff4 567 SCM_ASSYNT (2 == scm_ilength (x), xorig, scm_s_expression, scm_s_set_x);
6cb702da 568 SCM_ASSYNT (SCM_NIMP (SCM_CAR (x)) && SCM_SYMBOLP (SCM_CAR (x)),
89efbff4 569 xorig, scm_s_variable, scm_s_set_x);
3a3111a8 570 return scm_cons (SCM_IM_SET_X, x);
0f2d19dd
JB
571}
572
573
574#if 0
1cc91f1b 575
0f2d19dd
JB
576SCM
577scm_m_vref (xorig, env)
578 SCM xorig;
579 SCM env;
0f2d19dd
JB
580{
581 SCM x = SCM_CDR (xorig);
6cb702da 582 SCM_ASSYNT (1 == scm_ilength (x), xorig, scm_s_expression, s_vref);
0f2d19dd
JB
583 if (SCM_NIMP(x) && UDSCM_VARIABLEP (SCM_CAR (x)))
584 {
f5bf2977 585 /* scm_everr (SCM_UNDEFINED, env,..., "global variable reference") */
523f5266
GH
586 scm_misc_error (NULL,
587 "Bad variable: %S",
588 scm_listify (SCM_CAR (SCM_CDR (x)), SCM_UNDEFINED));
0f2d19dd 589 }
6cb702da
MD
590 SCM_ASSYNT (SCM_NIMP(x) && DEFSCM_VARIABLEP (SCM_CAR (x)),
591 xorig, scm_s_variable, s_vref);
0f2d19dd
JB
592 return scm_cons (IM_VREF, x);
593}
594
595
1cc91f1b 596
0f2d19dd
JB
597SCM
598scm_m_vset (xorig, env)
599 SCM xorig;
600 SCM env;
0f2d19dd
JB
601{
602 SCM x = SCM_CDR (xorig);
6cb702da
MD
603 SCM_ASSYNT (3 == scm_ilength (x), xorig, scm_s_expression, s_vset);
604 SCM_ASSYNT ((DEFSCM_VARIABLEP (SCM_CAR (x))
605 || UDSCM_VARIABLEP (SCM_CAR (x))),
606 xorig, scm_s_variable, s_vset);
0f2d19dd
JB
607 return scm_cons (IM_VSET, x);
608}
609#endif
610
611
b8229a3b 612SCM_SYNTAX(s_and, "and", scm_makmmacro, scm_m_and);
2f0d1375 613SCM_GLOBAL_SYMBOL(scm_sym_and, s_and);
1cc91f1b 614
0f2d19dd
JB
615SCM
616scm_m_and (xorig, env)
617 SCM xorig;
618 SCM env;
0f2d19dd
JB
619{
620 int len = scm_ilength (SCM_CDR (xorig));
b8229a3b 621 SCM_ASSYNT (len >= 0, xorig, scm_s_test, s_and);
0f2d19dd 622 if (len >= 1)
3a3111a8 623 return scm_cons (SCM_IM_AND, SCM_CDR (xorig));
0f2d19dd
JB
624 else
625 return SCM_BOOL_T;
626}
627
b8229a3b 628SCM_SYNTAX(s_or,"or", scm_makmmacro, scm_m_or);
2f0d1375 629SCM_GLOBAL_SYMBOL(scm_sym_or,s_or);
1cc91f1b 630
0f2d19dd
JB
631SCM
632scm_m_or (xorig, env)
633 SCM xorig;
634 SCM env;
0f2d19dd
JB
635{
636 int len = scm_ilength (SCM_CDR (xorig));
b8229a3b 637 SCM_ASSYNT (len >= 0, xorig, scm_s_test, s_or);
0f2d19dd 638 if (len >= 1)
3a3111a8 639 return scm_cons (SCM_IM_OR, SCM_CDR (xorig));
0f2d19dd
JB
640 else
641 return SCM_BOOL_F;
642}
643
644
b8229a3b 645SCM_SYNTAX(s_case, "case", scm_makmmacro, scm_m_case);
2f0d1375 646SCM_GLOBAL_SYMBOL(scm_sym_case, s_case);
1cc91f1b 647
0f2d19dd
JB
648SCM
649scm_m_case (xorig, env)
650 SCM xorig;
651 SCM env;
0f2d19dd 652{
26d5b9b4 653 SCM proc, cdrx = scm_list_copy (SCM_CDR (xorig)), x = cdrx;
b8229a3b 654 SCM_ASSYNT (scm_ilength (x) >= 2, xorig, scm_s_clauses, s_case);
0f2d19dd
JB
655 while (SCM_NIMP (x = SCM_CDR (x)))
656 {
657 proc = SCM_CAR (x);
b8229a3b 658 SCM_ASSYNT (scm_ilength (proc) >= 2, xorig, scm_s_clauses, s_case);
6cb702da 659 SCM_ASSYNT (scm_ilength (SCM_CAR (proc)) >= 0
2f0d1375 660 || scm_sym_else == SCM_CAR (proc),
b8229a3b 661 xorig, scm_s_clauses, s_case);
0f2d19dd 662 }
3a3111a8 663 return scm_cons (SCM_IM_CASE, cdrx);
0f2d19dd
JB
664}
665
666
b8229a3b 667SCM_SYNTAX(s_cond, "cond", scm_makmmacro, scm_m_cond);
2f0d1375 668SCM_GLOBAL_SYMBOL(scm_sym_cond, s_cond);
b8229a3b 669
1cc91f1b 670
0f2d19dd
JB
671SCM
672scm_m_cond (xorig, env)
673 SCM xorig;
674 SCM env;
0f2d19dd 675{
26d5b9b4 676 SCM arg1, cdrx = scm_list_copy (SCM_CDR (xorig)), x = cdrx;
0f2d19dd 677 int len = scm_ilength (x);
b8229a3b 678 SCM_ASSYNT (len >= 1, xorig, scm_s_clauses, s_cond);
0f2d19dd
JB
679 while (SCM_NIMP (x))
680 {
681 arg1 = SCM_CAR (x);
682 len = scm_ilength (arg1);
b8229a3b 683 SCM_ASSYNT (len >= 1, xorig, scm_s_clauses, s_cond);
2f0d1375 684 if (scm_sym_else == SCM_CAR (arg1))
0f2d19dd 685 {
6cb702da 686 SCM_ASSYNT (SCM_NULLP (SCM_CDR (x)) && len >= 2,
b8229a3b 687 xorig, "bad ELSE clause", s_cond);
a23afe53 688 SCM_SETCAR (arg1, SCM_BOOL_T);
0f2d19dd 689 }
2f0d1375 690 if (len >= 2 && scm_sym_arrow == SCM_CAR (SCM_CDR (arg1)))
6cb702da 691 SCM_ASSYNT (3 == len && SCM_NIMP (SCM_CAR (SCM_CDR (SCM_CDR (arg1)))),
b8229a3b 692 xorig, "bad recipient", s_cond);
0f2d19dd
JB
693 x = SCM_CDR (x);
694 }
3a3111a8 695 return scm_cons (SCM_IM_COND, cdrx);
0f2d19dd
JB
696}
697
b8229a3b 698SCM_SYNTAX(s_lambda, "lambda", scm_makmmacro, scm_m_lambda);
2f0d1375 699SCM_GLOBAL_SYMBOL(scm_sym_lambda, s_lambda);
1cc91f1b 700
0f2d19dd
JB
701SCM
702scm_m_lambda (xorig, env)
703 SCM xorig;
704 SCM env;
0f2d19dd
JB
705{
706 SCM proc, x = SCM_CDR (xorig);
26d5b9b4 707 if (scm_ilength (x) < 2)
0f2d19dd
JB
708 goto badforms;
709 proc = SCM_CAR (x);
33b97402
MD
710 if (SCM_NULLP (proc))
711 goto memlambda;
26d5b9b4
MD
712 if (SCM_IM_LET == proc) /* named let */
713 goto memlambda;
33b97402
MD
714 if (SCM_IMP (proc))
715 goto badforms;
716 if (SCM_SYMBOLP (proc))
717 goto memlambda;
718 if (SCM_NCONSP (proc))
719 goto badforms;
720 while (SCM_NIMP (proc))
0f2d19dd 721 {
33b97402
MD
722 if (SCM_NCONSP (proc))
723 {
0f2d19dd 724 if (!SCM_SYMBOLP (proc))
33b97402
MD
725 goto badforms;
726 else
727 goto memlambda;
728 }
0f2d19dd
JB
729 if (!(SCM_NIMP (SCM_CAR (proc)) && SCM_SYMBOLP (SCM_CAR (proc))))
730 goto badforms;
731 proc = SCM_CDR (proc);
732 }
ff467021 733 if (SCM_NNULLP (proc))
26d5b9b4
MD
734 {
735 badforms:
736 scm_wta (xorig, scm_s_formals, s_lambda);
737 }
738
739 memlambda:
3a3111a8
MD
740 return scm_cons2 (SCM_IM_LAMBDA, SCM_CAR (x),
741 scm_m_body (SCM_IM_LAMBDA, SCM_CDR (x), s_lambda));
0f2d19dd
JB
742}
743
b8229a3b 744SCM_SYNTAX(s_letstar,"let*", scm_makmmacro, scm_m_letstar);
2f0d1375 745SCM_GLOBAL_SYMBOL(scm_sym_letstar,s_letstar);
0f2d19dd 746
1cc91f1b 747
0f2d19dd
JB
748SCM
749scm_m_letstar (xorig, env)
750 SCM xorig;
751 SCM env;
0f2d19dd
JB
752{
753 SCM x = SCM_CDR (xorig), arg1, proc, vars = SCM_EOL, *varloc = &vars;
754 int len = scm_ilength (x);
b8229a3b 755 SCM_ASSYNT (len >= 2, xorig, scm_s_body, s_letstar);
0f2d19dd 756 proc = SCM_CAR (x);
b8229a3b 757 SCM_ASSYNT (scm_ilength (proc) >= 0, xorig, scm_s_bindings, s_letstar);
ff467021 758 while (SCM_NIMP (proc))
0f2d19dd
JB
759 {
760 arg1 = SCM_CAR (proc);
b8229a3b 761 SCM_ASSYNT (2 == scm_ilength (arg1), xorig, scm_s_bindings, s_letstar);
6cb702da 762 SCM_ASSYNT (SCM_NIMP (SCM_CAR (arg1)) && SCM_SYMBOLP (SCM_CAR (arg1)),
b8229a3b 763 xorig, scm_s_variable, s_letstar);
0f2d19dd 764 *varloc = scm_cons2 (SCM_CAR (arg1), SCM_CAR (SCM_CDR (arg1)), SCM_EOL);
a23afe53 765 varloc = SCM_CDRLOC (SCM_CDR (*varloc));
0f2d19dd
JB
766 proc = SCM_CDR (proc);
767 }
768 x = scm_cons (vars, SCM_CDR (x));
26d5b9b4 769
3a3111a8
MD
770 return scm_cons2 (SCM_IM_LETSTAR, SCM_CAR (x),
771 scm_m_body (SCM_IM_LETSTAR, SCM_CDR (x), s_letstar));
0f2d19dd
JB
772}
773
774/* DO gets the most radically altered syntax
775 (do ((<var1> <init1> <step1>)
776 (<var2> <init2>)
777 ... )
778 (<test> <return>)
779 <body>)
780 ;; becomes
781 (do_mem (varn ... var2 var1)
782 (<init1> <init2> ... <initn>)
783 (<test> <return>)
784 (<body>)
785 <step1> <step2> ... <stepn>) ;; missing steps replaced by var
786 */
787
b8229a3b 788SCM_SYNTAX(s_do, "do", scm_makmmacro, scm_m_do);
2f0d1375 789SCM_GLOBAL_SYMBOL(scm_sym_do, s_do);
1cc91f1b 790
0f2d19dd
JB
791SCM
792scm_m_do (xorig, env)
793 SCM xorig;
794 SCM env;
0f2d19dd
JB
795{
796 SCM x = SCM_CDR (xorig), arg1, proc;
797 SCM vars = SCM_EOL, inits = SCM_EOL, steps = SCM_EOL;
798 SCM *initloc = &inits, *steploc = &steps;
799 int len = scm_ilength (x);
6cb702da 800 SCM_ASSYNT (len >= 2, xorig, scm_s_test, "do");
0f2d19dd 801 proc = SCM_CAR (x);
6cb702da 802 SCM_ASSYNT (scm_ilength (proc) >= 0, xorig, scm_s_bindings, "do");
ff467021 803 while (SCM_NIMP(proc))
0f2d19dd
JB
804 {
805 arg1 = SCM_CAR (proc);
806 len = scm_ilength (arg1);
6cb702da
MD
807 SCM_ASSYNT (2 == len || 3 == len, xorig, scm_s_bindings, "do");
808 SCM_ASSYNT (SCM_NIMP (SCM_CAR (arg1)) && SCM_SYMBOLP (SCM_CAR (arg1)),
809 xorig, scm_s_variable, "do");
0f2d19dd
JB
810 /* vars reversed here, inits and steps reversed at evaluation */
811 vars = scm_cons (SCM_CAR (arg1), vars); /* variable */
812 arg1 = SCM_CDR (arg1);
813 *initloc = scm_cons (SCM_CAR (arg1), SCM_EOL); /* init */
a23afe53 814 initloc = SCM_CDRLOC (*initloc);
0f2d19dd
JB
815 arg1 = SCM_CDR (arg1);
816 *steploc = scm_cons (SCM_IMP (arg1) ? SCM_CAR (vars) : SCM_CAR (arg1), SCM_EOL); /* step */
a23afe53 817 steploc = SCM_CDRLOC (*steploc);
0f2d19dd
JB
818 proc = SCM_CDR (proc);
819 }
820 x = SCM_CDR (x);
6cb702da 821 SCM_ASSYNT (scm_ilength (SCM_CAR (x)) >= 1, xorig, scm_s_test, "do");
0f2d19dd
JB
822 x = scm_cons2 (SCM_CAR (x), SCM_CDR (x), steps);
823 x = scm_cons2 (vars, inits, x);
a23afe53 824 bodycheck (xorig, SCM_CARLOC (SCM_CDR (SCM_CDR (x))), "do");
3a3111a8 825 return scm_cons (SCM_IM_DO, x);
0f2d19dd
JB
826}
827
6dbd0af5
MD
828/* evalcar is small version of inline EVALCAR when we don't care about
829 * speed
830 */
831#define evalcar scm_eval_car
0f2d19dd 832
1cc91f1b
JB
833
834static SCM iqq SCM_P ((SCM form, SCM env, int depth));
835
b8229a3b 836SCM_SYNTAX(s_quasiquote, "quasiquote", scm_makacro, scm_m_quasiquote);
2f0d1375 837SCM_GLOBAL_SYMBOL(scm_sym_quasiquote, s_quasiquote);
b8229a3b
MS
838
839SCM
840scm_m_quasiquote (xorig, env)
841 SCM xorig;
842 SCM env;
843{
844 SCM x = SCM_CDR (xorig);
845 SCM_ASSYNT (scm_ilength (x) == 1, xorig, scm_s_expression, s_quasiquote);
846 return iqq (SCM_CAR (x), env, 1);
847}
848
849
0f2d19dd
JB
850static SCM
851iqq (form, env, depth)
852 SCM form;
853 SCM env;
854 int depth;
0f2d19dd
JB
855{
856 SCM tmp;
857 int edepth = depth;
ff467021
JB
858 if (SCM_IMP(form))
859 return form;
0f2d19dd
JB
860 if (SCM_VECTORP (form))
861 {
862 long i = SCM_LENGTH (form);
863 SCM *data = SCM_VELTS (form);
864 tmp = SCM_EOL;
865 for (; --i >= 0;)
866 tmp = scm_cons (data[i], tmp);
867 return scm_vector (iqq (tmp, env, depth));
868 }
ff467021
JB
869 if (SCM_NCONSP(form))
870 return form;
0f2d19dd 871 tmp = SCM_CAR (form);
2f0d1375 872 if (scm_sym_quasiquote == tmp)
0f2d19dd
JB
873 {
874 depth++;
875 goto label;
876 }
2f0d1375 877 if (scm_sym_unquote == tmp)
0f2d19dd
JB
878 {
879 --depth;
880 label:
881 form = SCM_CDR (form);
0f2d19dd
JB
882 SCM_ASSERT (SCM_NIMP (form) && SCM_ECONSP (form) && SCM_NULLP (SCM_CDR (form)),
883 form, SCM_ARG1, s_quasiquote);
884 if (0 == depth)
885 return evalcar (form, env);
886 return scm_cons2 (tmp, iqq (SCM_CAR (form), env, depth), SCM_EOL);
887 }
2f0d1375 888 if (SCM_NIMP (tmp) && (scm_sym_uq_splicing == SCM_CAR (tmp)))
0f2d19dd
JB
889 {
890 tmp = SCM_CDR (tmp);
891 if (0 == --edepth)
892 return scm_append (scm_cons2 (evalcar (tmp, env), iqq (SCM_CDR (form), env, depth), SCM_EOL));
893 }
894 return scm_cons (iqq (SCM_CAR (form), env, edepth), iqq (SCM_CDR (form), env, depth));
895}
896
897/* Here are acros which return values rather than code. */
898
b8229a3b 899SCM_SYNTAX(s_delay, "delay", scm_makacro, scm_m_delay);
1cc91f1b 900
0f2d19dd
JB
901SCM
902scm_m_delay (xorig, env)
903 SCM xorig;
904 SCM env;
0f2d19dd 905{
6cb702da 906 SCM_ASSYNT (scm_ilength (xorig) == 2, xorig, scm_s_expression, s_delay);
0f2d19dd 907 xorig = SCM_CDR (xorig);
26d5b9b4
MD
908 return scm_makprom (scm_closure (scm_cons2 (SCM_EOL, SCM_CAR (xorig),
909 SCM_CDR (xorig)),
0f2d19dd
JB
910 env));
911}
912
1cc91f1b 913
b8229a3b 914SCM_SYNTAX(s_define, "define", scm_makmmacro, scm_m_define);
2f0d1375 915SCM_GLOBAL_SYMBOL(scm_sym_define, s_define);
1cc91f1b 916
0f2d19dd
JB
917SCM
918scm_m_define (x, env)
919 SCM x;
920 SCM env;
0f2d19dd
JB
921{
922 SCM proc, arg1 = x;
923 x = SCM_CDR (x);
6cb702da 924 /* SCM_ASSYNT(SCM_NULLP(env), x, "bad placement", s_define);*/
b8229a3b 925 SCM_ASSYNT (scm_ilength (x) >= 2, arg1, scm_s_expression, s_define);
0f2d19dd
JB
926 proc = SCM_CAR (x);
927 x = SCM_CDR (x);
928 while (SCM_NIMP (proc) && SCM_CONSP (proc))
929 { /* nested define syntax */
2f0d1375 930 x = scm_cons (scm_cons2 (scm_sym_lambda, SCM_CDR (proc), x), SCM_EOL);
0f2d19dd
JB
931 proc = SCM_CAR (proc);
932 }
6cb702da 933 SCM_ASSYNT (SCM_NIMP (proc) && SCM_SYMBOLP (proc),
b8229a3b
MS
934 arg1, scm_s_variable, s_define);
935 SCM_ASSYNT (1 == scm_ilength (x), arg1, scm_s_expression, s_define);
0f2d19dd
JB
936 if (SCM_TOP_LEVEL (env))
937 {
938 x = evalcar (x, env);
6dbd0af5 939#ifdef DEBUG_EXTENSIONS
80ea260c
MD
940 if (SCM_REC_PROCNAMES_P && SCM_NIMP (x))
941 {
942 arg1 = x;
943 proc:
944 if (SCM_CLOSUREP (arg1)
945 /* Only the first definition determines the name. */
2f0d1375
MD
946 && scm_procedure_property (arg1, scm_sym_name) == SCM_BOOL_F)
947 scm_set_procedure_property_x (arg1, scm_sym_name, proc);
80ea260c
MD
948 else if (SCM_TYP16 (arg1) == scm_tc16_macro
949 && SCM_CDR (arg1) != arg1)
950 {
951 arg1 = SCM_CDR (arg1);
952 goto proc;
953 }
954 }
6dbd0af5 955#endif
6cb702da 956 arg1 = scm_sym2vcell (proc, scm_env_top_level (env), SCM_BOOL_T);
0f2d19dd 957#if 0
cf7c17e9 958#ifndef SCM_RECKLESS
0f2d19dd
JB
959 if (SCM_NIMP (SCM_CDR (arg1)) && ((SCM) SCM_SNAME (SCM_CDR (arg1)) == proc)
960 && (SCM_CDR (arg1) != x))
961 scm_warn ("redefining built-in ", SCM_CHARS (proc));
962 else
963#endif
964 if (5 <= scm_verbose && SCM_UNDEFINED != SCM_CDR (arg1))
965 scm_warn ("redefining ", SCM_CHARS (proc));
0f2d19dd 966#endif
a23afe53 967 SCM_SETCDR (arg1, x);
0f2d19dd 968#ifdef SICP
2f0d1375 969 return scm_cons2 (scm_sym_quote, SCM_CAR (arg1), SCM_EOL);
0f2d19dd
JB
970#else
971 return SCM_UNSPECIFIED;
972#endif
973 }
974 return scm_cons2 (SCM_IM_DEFINE, proc, x);
975}
6dbd0af5 976
0f2d19dd
JB
977/* end of acros */
978
26d5b9b4
MD
979static SCM
980scm_m_letrec1 (op, imm, xorig, env)
981 SCM op;
982 SCM imm;
0f2d19dd
JB
983 SCM xorig;
984 SCM env;
0f2d19dd
JB
985{
986 SCM cdrx = SCM_CDR (xorig); /* locally mutable version of form */
987 char *what = SCM_CHARS (SCM_CAR (xorig));
988 SCM x = cdrx, proc, arg1; /* structure traversers */
989 SCM vars = SCM_EOL, inits = SCM_EOL, *initloc = &inits;
990
0f2d19dd 991 proc = SCM_CAR (x);
6cb702da 992 ASRTSYNTAX (scm_ilength (proc) >= 1, scm_s_bindings);
0f2d19dd
JB
993 do
994 {
995 /* vars scm_list reversed here, inits reversed at evaluation */
996 arg1 = SCM_CAR (proc);
6cb702da 997 ASRTSYNTAX (2 == scm_ilength (arg1), scm_s_bindings);
26d5b9b4
MD
998 ASRTSYNTAX (SCM_NIMP (SCM_CAR (arg1)) && SCM_SYMBOLP (SCM_CAR (arg1)),
999 scm_s_variable);
0f2d19dd
JB
1000 vars = scm_cons (SCM_CAR (arg1), vars);
1001 *initloc = scm_cons (SCM_CAR (SCM_CDR (arg1)), SCM_EOL);
a23afe53 1002 initloc = SCM_CDRLOC (*initloc);
0f2d19dd 1003 }
ff467021 1004 while (SCM_NIMP (proc = SCM_CDR (proc)));
26d5b9b4 1005
3a3111a8
MD
1006 return scm_cons2 (op, vars,
1007 scm_cons (inits, scm_m_body (imm, SCM_CDR (x), what)));
0f2d19dd
JB
1008}
1009
26d5b9b4 1010SCM_SYNTAX(s_letrec, "letrec", scm_makmmacro, scm_m_letrec);
2f0d1375 1011SCM_GLOBAL_SYMBOL(scm_sym_letrec, s_letrec);
26d5b9b4
MD
1012
1013SCM
1014scm_m_letrec (xorig, env)
1015 SCM xorig;
1016 SCM env;
1017{
1018 SCM x = SCM_CDR (xorig);
1019 SCM_ASSYNT (scm_ilength (x) >= 2, xorig, scm_s_body, s_letrec);
1020
1021 if (SCM_NULLP (SCM_CAR (x))) /* null binding, let* faster */
3a3111a8
MD
1022 return scm_m_letstar (scm_cons2 (SCM_CAR (xorig), SCM_EOL,
1023 scm_m_body (SCM_IM_LETREC,
1024 SCM_CDR (x),
1025 s_letrec)),
26d5b9b4
MD
1026 env);
1027 else
1028 return scm_m_letrec1 (SCM_IM_LETREC, SCM_IM_LETREC, xorig, env);
1029}
1cc91f1b 1030
b8229a3b 1031SCM_SYNTAX(s_let, "let", scm_makmmacro, scm_m_let);
2f0d1375 1032SCM_GLOBAL_SYMBOL(scm_sym_let, s_let);
b8229a3b 1033
0f2d19dd
JB
1034SCM
1035scm_m_let (xorig, env)
1036 SCM xorig;
1037 SCM env;
0f2d19dd
JB
1038{
1039 SCM cdrx = SCM_CDR (xorig); /* locally mutable version of form */
1040 SCM x = cdrx, proc, arg1, name; /* structure traversers */
1041 SCM vars = SCM_EOL, inits = SCM_EOL, *varloc = &vars, *initloc = &inits;
1042
b8229a3b 1043 SCM_ASSYNT (scm_ilength (x) >= 2, xorig, scm_s_body, s_let);
0f2d19dd
JB
1044 proc = SCM_CAR (x);
1045 if (SCM_NULLP (proc)
1046 || (SCM_NIMP (proc) && SCM_CONSP (proc)
26d5b9b4
MD
1047 && SCM_NIMP (SCM_CAR (proc))
1048 && SCM_CONSP (SCM_CAR (proc)) && SCM_NULLP (SCM_CDR (proc))))
1049 {
1050 /* null or single binding, let* is faster */
3a3111a8
MD
1051 return scm_m_letstar (scm_cons2 (SCM_CAR (xorig), proc,
1052 scm_m_body (SCM_IM_LET,
1053 SCM_CDR (x),
1054 s_let)),
26d5b9b4
MD
1055 env);
1056 }
1057
b8229a3b 1058 SCM_ASSYNT (SCM_NIMP (proc), xorig, scm_s_bindings, s_let);
26d5b9b4
MD
1059 if (SCM_CONSP (proc))
1060 {
1061 /* plain let, proc is <bindings> */
1062 return scm_m_letrec1 (SCM_IM_LET, SCM_IM_LET, xorig, env);
1063 }
1064
0f2d19dd 1065 if (!SCM_SYMBOLP (proc))
b8229a3b 1066 scm_wta (xorig, scm_s_bindings, s_let); /* bad let */
0f2d19dd
JB
1067 name = proc; /* named let, build equiv letrec */
1068 x = SCM_CDR (x);
b8229a3b 1069 SCM_ASSYNT (scm_ilength (x) >= 2, xorig, scm_s_body, s_let);
26d5b9b4 1070 proc = SCM_CAR (x); /* bindings list */
b8229a3b 1071 SCM_ASSYNT (scm_ilength (proc) >= 0, xorig, scm_s_bindings, s_let);
ff467021 1072 while (SCM_NIMP (proc))
0f2d19dd
JB
1073 { /* vars and inits both in order */
1074 arg1 = SCM_CAR (proc);
b8229a3b 1075 SCM_ASSYNT (2 == scm_ilength (arg1), xorig, scm_s_bindings, s_let);
6cb702da 1076 SCM_ASSYNT (SCM_NIMP (SCM_CAR (arg1)) && SCM_SYMBOLP (SCM_CAR (arg1)),
b8229a3b 1077 xorig, scm_s_variable, s_let);
0f2d19dd 1078 *varloc = scm_cons (SCM_CAR (arg1), SCM_EOL);
a23afe53 1079 varloc = SCM_CDRLOC (*varloc);
0f2d19dd 1080 *initloc = scm_cons (SCM_CAR (SCM_CDR (arg1)), SCM_EOL);
a23afe53 1081 initloc = SCM_CDRLOC (*initloc);
0f2d19dd
JB
1082 proc = SCM_CDR (proc);
1083 }
26d5b9b4 1084
2f0d1375 1085 proc = scm_cons2 (scm_sym_lambda, vars,
26d5b9b4 1086 scm_m_body (SCM_IM_LET, SCM_CDR (x), "let"));
2f0d1375 1087 proc = scm_cons2 (scm_sym_let, scm_cons (scm_cons2 (name, proc, SCM_EOL),
26d5b9b4
MD
1088 SCM_EOL),
1089 scm_acons (name, inits, SCM_EOL));
1090 return scm_m_letrec1 (SCM_IM_LETREC, SCM_IM_LET, proc, env);
0f2d19dd
JB
1091}
1092
1093
81123e6d
MD
1094SCM_SYNTAX (s_atapply,"@apply", scm_makmmacro, scm_m_apply);
1095SCM_GLOBAL_SYMBOL (scm_sym_atapply, s_atapply);
1096SCM_GLOBAL_SYMBOL (scm_sym_apply, s_atapply + 1);
1cc91f1b 1097
0f2d19dd
JB
1098SCM
1099scm_m_apply (xorig, env)
1100 SCM xorig;
1101 SCM env;
0f2d19dd 1102{
6cb702da 1103 SCM_ASSYNT (scm_ilength (SCM_CDR (xorig)) == 2,
b8229a3b 1104 xorig, scm_s_expression, s_atapply);
0f2d19dd
JB
1105 return scm_cons (SCM_IM_APPLY, SCM_CDR (xorig));
1106}
1107
b8229a3b
MS
1108
1109SCM_SYNTAX(s_atcall_cc,"@call-with-current-continuation", scm_makmmacro, scm_m_cont);
2f0d1375 1110SCM_GLOBAL_SYMBOL(scm_sym_atcall_cc,s_atcall_cc);
0f2d19dd 1111
1cc91f1b 1112
0f2d19dd
JB
1113SCM
1114scm_m_cont (xorig, env)
1115 SCM xorig;
1116 SCM env;
0f2d19dd 1117{
6cb702da 1118 SCM_ASSYNT (scm_ilength (SCM_CDR (xorig)) == 1,
b8229a3b 1119 xorig, scm_s_expression, s_atcall_cc);
3a3111a8 1120 return scm_cons (SCM_IM_CONT, SCM_CDR (xorig));
0f2d19dd
JB
1121}
1122
73b64342
MD
1123/* Multi-language support */
1124
1125SCM scm_nil;
1126SCM scm_t;
1127
1128SCM_SYNTAX (s_nil_cond, "nil-cond", scm_makmmacro, scm_m_nil_cond);
1129
1130SCM
1131scm_m_nil_cond (SCM xorig, SCM env)
1132{
1133 int len = scm_ilength (SCM_CDR (xorig));
1134 SCM_ASSYNT (len >= 1 && (len & 1) == 1, xorig,
1135 scm_s_expression, "nil-cond");
1136 return scm_cons (SCM_IM_NIL_COND, SCM_CDR (xorig));
1137}
1138
1139SCM_SYNTAX (s_nil_ify, "nil-ify", scm_makmmacro, scm_m_nil_ify);
1140
1141SCM
1142scm_m_nil_ify (SCM xorig, SCM env)
1143{
1144 SCM_ASSYNT (scm_ilength (SCM_CDR (xorig)) == 1,
1145 xorig, scm_s_expression, "nil-ify");
1146 return scm_cons (SCM_IM_NIL_IFY, SCM_CDR (xorig));
1147}
1148
1149SCM_SYNTAX (s_t_ify, "t-ify", scm_makmmacro, scm_m_t_ify);
1150
1151SCM
1152scm_m_t_ify (SCM xorig, SCM env)
1153{
1154 SCM_ASSYNT (scm_ilength (SCM_CDR (xorig)) == 1,
1155 xorig, scm_s_expression, "t-ify");
1156 return scm_cons (SCM_IM_T_IFY, SCM_CDR (xorig));
1157}
1158
1159SCM_SYNTAX (s_0_cond, "0-cond", scm_makmmacro, scm_m_0_cond);
1160
1161SCM
1162scm_m_0_cond (SCM xorig, SCM env)
1163{
1164 int len = scm_ilength (SCM_CDR (xorig));
1165 SCM_ASSYNT (len >= 1 && (len & 1) == 1, xorig,
1166 scm_s_expression, "0-cond");
1167 return scm_cons (SCM_IM_0_COND, SCM_CDR (xorig));
1168}
1169
1170SCM_SYNTAX (s_0_ify, "0-ify", scm_makmmacro, scm_m_0_ify);
1171
1172SCM
1173scm_m_0_ify (SCM xorig, SCM env)
1174{
1175 SCM_ASSYNT (scm_ilength (SCM_CDR (xorig)) == 1,
1176 xorig, scm_s_expression, "0-ify");
1177 return scm_cons (SCM_IM_0_IFY, SCM_CDR (xorig));
1178}
1179
1180SCM_SYNTAX (s_1_ify, "1-ify", scm_makmmacro, scm_m_1_ify);
1181
1182SCM
1183scm_m_1_ify (SCM xorig, SCM env)
1184{
1185 SCM_ASSYNT (scm_ilength (SCM_CDR (xorig)) == 1,
1186 xorig, scm_s_expression, "1-ify");
1187 return scm_cons (SCM_IM_1_IFY, SCM_CDR (xorig));
1188}
1189
1190SCM_SYNTAX (s_atfop, "@fop", scm_makmmacro, scm_m_atfop);
1191
1192SCM
1193scm_m_atfop (SCM xorig, SCM env)
1194{
1195 SCM x = SCM_CDR (xorig), vcell;
1196 SCM_ASSYNT (scm_ilength (x) >= 1, xorig, scm_s_expression, "@fop");
1197 vcell = scm_symbol_fref (SCM_CAR (x));
1198 SCM_ASSYNT (SCM_NIMP (vcell) && SCM_CONSP (vcell), x,
1199 "Symbol's function definition is void", NULL);
1200 SCM_SETCAR (x, vcell + 1);
1201 return x;
1202}
1203
1204SCM_SYNTAX (s_atbind, "@bind", scm_makmmacro, scm_m_atbind);
1205
1206SCM
1207scm_m_atbind (SCM xorig, SCM env)
1208{
1209 SCM x = SCM_CDR (xorig);
1210 SCM_ASSYNT (scm_ilength (x) > 1, xorig, scm_s_expression, "@bind");
1211
1212 if (SCM_IMP (env))
1213 env = SCM_BOOL_F;
1214 else
1215 {
1216 while (SCM_NIMP (SCM_CDR (env)))
1217 env = SCM_CDR (env);
1218 env = SCM_CAR (env);
1219 if (SCM_CONSP (env))
1220 env = SCM_BOOL_F;
1221 }
1222
1223 x = SCM_CAR (x);
1224 while (SCM_NIMP (x))
1225 {
1226 SCM_SETCAR (x, scm_sym2vcell (SCM_CAR (x), env, SCM_BOOL_T) + 1);
1227 x = SCM_CDR (x);
1228 }
1229 return scm_cons (SCM_IM_BIND, SCM_CDR (xorig));
1230}
73b64342 1231
26d5b9b4
MD
1232SCM
1233scm_m_expand_body (SCM xorig, SCM env)
1234{
1235 SCM form, x = SCM_CDR (xorig), defs = SCM_EOL;
1236 char *what = SCM_ISYMCHARS (SCM_CAR (xorig)) + 2;
1237
1238 while (SCM_NIMP (x))
1239 {
1240 form = SCM_CAR (x);
1241 if (SCM_IMP (form) || SCM_NCONSP (form))
1242 break;
1243 if (SCM_IMP (SCM_CAR (form)))
1244 break;
1245 if (!SCM_SYMBOLP (SCM_CAR (form)))
1246 break;
1247
3a3111a8
MD
1248 form = scm_macroexp (scm_cons_source (form,
1249 SCM_CAR (form),
1250 SCM_CDR (form)),
1251 env);
26d5b9b4
MD
1252
1253 if (SCM_IM_DEFINE == SCM_CAR (form))
1254 {
1255 defs = scm_cons (SCM_CDR (form), defs);
1256 x = SCM_CDR(x);
1257 }
1258 else if (SCM_NIMP(defs))
1259 {
1260 break;
1261 }
1262 else if (SCM_IM_BEGIN == SCM_CAR (form))
1263 {
1264 x = scm_append (scm_cons2 (SCM_CDR (form), SCM_CDR (x), SCM_EOL));
1265 }
1266 else
1267 {
1268 x = scm_cons (form, SCM_CDR(x));
1269 break;
1270 }
1271 }
1272
1273 SCM_ASSYNT (SCM_NIMP (x), SCM_CDR (xorig), scm_s_body, what);
1274 if (SCM_NIMP (defs))
1275 {
1276 x = scm_cons (scm_m_letrec1 (SCM_IM_LETREC,
1277 SCM_IM_DEFINE,
2f0d1375 1278 scm_cons2 (scm_sym_define, defs, x),
26d5b9b4
MD
1279 env),
1280 SCM_EOL);
1281 }
1282
1283 SCM_DEFER_INTS;
1284 SCM_SETCAR (xorig, SCM_CAR (x));
1285 SCM_SETCDR (xorig, SCM_CDR (x));
1286 SCM_ALLOW_INTS;
1287
1288 return xorig;
1289}
1290
1291SCM
1292scm_macroexp (SCM x, SCM env)
1293{
1294 SCM res, proc;
1295
1296 /* Don't bother to produce error messages here. We get them when we
1297 eventually execute the code for real. */
1298
1299 macro_tail:
1300 if (SCM_IMP (SCM_CAR (x)) || !SCM_SYMBOLP (SCM_CAR (x)))
1301 return x;
1302
1303#ifdef USE_THREADS
1304 {
1305 SCM *proc_ptr = scm_lookupcar1 (x, env, 0);
1306 if (proc_ptr == NULL)
1307 {
1308 /* We have lost the race. */
1309 goto macro_tail;
1310 }
1311 proc = *proc_ptr;
1312 }
1313#else
1314 proc = *scm_lookupcar (x, env, 0);
1315#endif
1316
1317 /* Only handle memoizing macros. `Acros' and `macros' are really
1318 special forms and should not be evaluated here. */
1319
1320 if (SCM_IMP (proc)
1321 || scm_tc16_macro != SCM_TYP16 (proc)
1322 || (int) (SCM_CAR (proc) >> 16) != 2)
1323 return x;
1324
1325 unmemocar (x, env);
1326 res = scm_apply (SCM_CDR (proc), x, scm_cons (env, scm_listofnull));
1327
1328 if (scm_ilength (res) <= 0)
1329 res = scm_cons2 (SCM_IM_BEGIN, res, SCM_EOL);
1330
26d5b9b4
MD
1331 SCM_DEFER_INTS;
1332 SCM_SETCAR (x, SCM_CAR (res));
1333 SCM_SETCDR (x, SCM_CDR (res));
1334 SCM_ALLOW_INTS;
1335
1336 goto macro_tail;
1337}
73b64342 1338
6dbd0af5
MD
1339/* scm_unmemocopy takes a memoized expression together with its
1340 * environment and rewrites it to its original form. Thus, it is the
1341 * inversion of the rewrite rules above. The procedure is not
1342 * optimized for speed. It's used in scm_iprin1 when printing the
220ff1eb
MD
1343 * code of a closure, in scm_procedure_source, in display_frame when
1344 * generating the source for a stackframe in a backtrace, and in
1345 * display_expression.
6dbd0af5
MD
1346 */
1347
26d5b9b4
MD
1348/* We should introduce an anti-macro interface so that it is possible
1349 * to plug in transformers in both directions from other compilation
1350 * units. unmemocopy could then dispatch to anti-macro transformers.
1351 * (Those transformers could perhaps be written in slightly more
1352 * readable style... :)
1353 */
1354
1cc91f1b
JB
1355static SCM unmemocopy SCM_P ((SCM x, SCM env));
1356
6dbd0af5
MD
1357static SCM
1358unmemocopy (x, env)
1359 SCM x;
1360 SCM env;
6dbd0af5
MD
1361{
1362 SCM ls, z;
1363#ifdef DEBUG_EXTENSIONS
1364 SCM p;
1365#endif
1366 if (SCM_NCELLP (x) || SCM_NECONSP (x))
1367 return x;
1368#ifdef DEBUG_EXTENSIONS
1369 p = scm_whash_lookup (scm_source_whash, x);
1370#endif
1371 switch (SCM_TYP7 (x))
1372 {
1373 case (127 & SCM_IM_AND):
2f0d1375 1374 ls = z = scm_cons (scm_sym_and, SCM_UNSPECIFIED);
6dbd0af5
MD
1375 break;
1376 case (127 & SCM_IM_BEGIN):
2f0d1375 1377 ls = z = scm_cons (scm_sym_begin, SCM_UNSPECIFIED);
6dbd0af5
MD
1378 break;
1379 case (127 & SCM_IM_CASE):
2f0d1375 1380 ls = z = scm_cons (scm_sym_case, SCM_UNSPECIFIED);
6dbd0af5
MD
1381 break;
1382 case (127 & SCM_IM_COND):
2f0d1375 1383 ls = z = scm_cons (scm_sym_cond, SCM_UNSPECIFIED);
6dbd0af5
MD
1384 break;
1385 case (127 & SCM_IM_DO):
2f0d1375 1386 ls = scm_cons (scm_sym_do, SCM_UNSPECIFIED);
6dbd0af5
MD
1387 goto transform;
1388 case (127 & SCM_IM_IF):
2f0d1375 1389 ls = z = scm_cons (scm_sym_if, SCM_UNSPECIFIED);
6dbd0af5
MD
1390 break;
1391 case (127 & SCM_IM_LET):
2f0d1375 1392 ls = scm_cons (scm_sym_let, SCM_UNSPECIFIED);
6dbd0af5
MD
1393 goto transform;
1394 case (127 & SCM_IM_LETREC):
1395 {
1396 SCM f, v, e, s;
2f0d1375 1397 ls = scm_cons (scm_sym_letrec, SCM_UNSPECIFIED);
6dbd0af5
MD
1398 transform:
1399 x = SCM_CDR (x);
26d5b9b4 1400 /* binding names */
6dbd0af5
MD
1401 f = v = SCM_CAR (x);
1402 x = SCM_CDR (x);
e2806c10 1403 z = EXTEND_ENV (f, SCM_EOL, env);
26d5b9b4 1404 /* inits */
6dbd0af5 1405 e = scm_reverse (unmemocopy (SCM_CAR (x),
2f0d1375 1406 SCM_CAR (ls) == scm_sym_letrec ? z : env));
6dbd0af5 1407 env = z;
26d5b9b4 1408 /* increments */
2f0d1375 1409 s = SCM_CAR (ls) == scm_sym_do
6dbd0af5
MD
1410 ? scm_reverse (unmemocopy (SCM_CDR (SCM_CDR (SCM_CDR (x))), env))
1411 : f;
26d5b9b4 1412 /* build transformed binding list */
6dbd0af5
MD
1413 z = SCM_EOL;
1414 do
1415 {
1416 z = scm_acons (SCM_CAR (v),
1417 scm_cons (SCM_CAR (e),
1418 SCM_CAR (s) == SCM_CAR (v)
1419 ? SCM_EOL
1420 : scm_cons (SCM_CAR (s), SCM_EOL)),
1421 z);
1422 v = SCM_CDR (v);
1423 e = SCM_CDR (e);
1424 s = SCM_CDR (s);
1425 }
ff467021 1426 while (SCM_NIMP (v));
a23afe53
MD
1427 z = scm_cons (z, SCM_UNSPECIFIED);
1428 SCM_SETCDR (ls, z);
2f0d1375 1429 if (SCM_CAR (ls) == scm_sym_do)
6dbd0af5
MD
1430 {
1431 x = SCM_CDR (x);
26d5b9b4 1432 /* test clause */
a23afe53 1433 SCM_SETCDR (z, scm_cons (unmemocopy (SCM_CAR (x), env),
6dbd0af5 1434 SCM_UNSPECIFIED));
a23afe53
MD
1435 z = SCM_CDR (z);
1436 x = (SCM) (SCM_CARLOC (SCM_CDR (x)) - 1);
26d5b9b4
MD
1437 /* body forms are now to be found in SCM_CDR (x)
1438 (this is how *real* code look like! :) */
6dbd0af5
MD
1439 }
1440 break;
1441 }
1442 case (127 & SCM_IM_LETSTAR):
1443 {
1444 SCM b, y;
1445 x = SCM_CDR (x);
1446 b = SCM_CAR (x);
1447 y = SCM_EOL;
1448 if SCM_IMP (b)
1449 {
e2806c10 1450 env = EXTEND_ENV (SCM_EOL, SCM_EOL, env);
6dbd0af5
MD
1451 goto letstar;
1452 }
1453 y = z = scm_acons (SCM_CAR (b),
1454 unmemocar (
1455 scm_cons (unmemocopy (SCM_CAR (SCM_CDR (b)), env), SCM_EOL), env),
1456 SCM_UNSPECIFIED);
e2806c10 1457 env = EXTEND_ENV (SCM_CAR (b), SCM_BOOL_F, env);
6dbd0af5
MD
1458 b = SCM_CDR (SCM_CDR (b));
1459 if (SCM_IMP (b))
1460 {
1461 SCM_SETCDR (y, SCM_EOL);
2f0d1375 1462 ls = scm_cons (scm_sym_let, z = scm_cons (y, SCM_UNSPECIFIED));
6dbd0af5
MD
1463 break;
1464 }
1465 do
1466 {
a23afe53
MD
1467 SCM_SETCDR (z, scm_acons (SCM_CAR (b),
1468 unmemocar (
6dbd0af5 1469 scm_cons (unmemocopy (SCM_CAR (SCM_CDR (b)), env), SCM_EOL), env),
a23afe53
MD
1470 SCM_UNSPECIFIED));
1471 z = SCM_CDR (z);
e2806c10 1472 env = EXTEND_ENV (SCM_CAR (b), SCM_BOOL_F, env);
6dbd0af5
MD
1473 b = SCM_CDR (SCM_CDR (b));
1474 }
ff467021 1475 while (SCM_NIMP (b));
a23afe53 1476 SCM_SETCDR (z, SCM_EOL);
6dbd0af5 1477 letstar:
2f0d1375 1478 ls = scm_cons (scm_sym_letstar, z = scm_cons (y, SCM_UNSPECIFIED));
6dbd0af5
MD
1479 break;
1480 }
1481 case (127 & SCM_IM_OR):
2f0d1375 1482 ls = z = scm_cons (scm_sym_or, SCM_UNSPECIFIED);
6dbd0af5
MD
1483 break;
1484 case (127 & SCM_IM_LAMBDA):
1485 x = SCM_CDR (x);
2f0d1375 1486 ls = scm_cons (scm_sym_lambda,
6dbd0af5 1487 z = scm_cons (SCM_CAR (x), SCM_UNSPECIFIED));
e2806c10 1488 env = EXTEND_ENV (SCM_CAR (x), SCM_EOL, env);
6dbd0af5
MD
1489 break;
1490 case (127 & SCM_IM_QUOTE):
2f0d1375 1491 ls = z = scm_cons (scm_sym_quote, SCM_UNSPECIFIED);
6dbd0af5 1492 break;
89efbff4
MD
1493 case (127 & SCM_IM_SET_X):
1494 ls = z = scm_cons (scm_sym_set_x, SCM_UNSPECIFIED);
6dbd0af5
MD
1495 break;
1496 case (127 & SCM_IM_DEFINE):
1497 {
1498 SCM n;
1499 x = SCM_CDR (x);
2f0d1375 1500 ls = scm_cons (scm_sym_define,
6dbd0af5
MD
1501 z = scm_cons (n = SCM_CAR (x), SCM_UNSPECIFIED));
1502 if (SCM_NNULLP (env))
a23afe53 1503 SCM_SETCAR (SCM_CAR (env), scm_cons (n, SCM_CAR (SCM_CAR (env))));
6dbd0af5
MD
1504 break;
1505 }
1506 case (127 & SCM_MAKISYM (0)):
1507 z = SCM_CAR (x);
1508 if (!SCM_ISYMP (z))
1509 goto unmemo;
ff467021 1510 switch (SCM_ISYMNUM (z))
6dbd0af5
MD
1511 {
1512 case (SCM_ISYMNUM (SCM_IM_APPLY)):
2f0d1375 1513 ls = z = scm_cons (scm_sym_atapply, SCM_UNSPECIFIED);
6dbd0af5
MD
1514 goto loop;
1515 case (SCM_ISYMNUM (SCM_IM_CONT)):
2f0d1375 1516 ls = z = scm_cons (scm_sym_atcall_cc, SCM_UNSPECIFIED);
6dbd0af5
MD
1517 goto loop;
1518 default:
fa888178 1519 /* appease the Sun compiler god: */ ;
6dbd0af5
MD
1520 }
1521 unmemo:
1522 default:
1523 ls = z = unmemocar (scm_cons (unmemocopy (SCM_CAR (x), env),
1524 SCM_UNSPECIFIED),
1525 env);
1526 }
1527loop:
1528 while (SCM_CELLP (x = SCM_CDR (x)) && SCM_ECONSP (x))
a23afe53 1529 {
26d5b9b4
MD
1530 if (SCM_IMP (SCM_CAR (x)) && SCM_ISYMP (SCM_CAR (x)))
1531 /* skip body markers */
1532 continue;
a23afe53
MD
1533 SCM_SETCDR (z, unmemocar (scm_cons (unmemocopy (SCM_CAR (x), env),
1534 SCM_UNSPECIFIED),
1535 env));
1536 z = SCM_CDR (z);
1537 }
1538 SCM_SETCDR (z, x);
6dbd0af5
MD
1539#ifdef DEBUG_EXTENSIONS
1540 if (SCM_NFALSEP (p))
1541 scm_whash_insert (scm_source_whash, ls, p);
1542#endif
1543 return ls;
1544}
1545
1cc91f1b 1546
6dbd0af5
MD
1547SCM
1548scm_unmemocopy (x, env)
1549 SCM x;
1550 SCM env;
6dbd0af5
MD
1551{
1552 if (SCM_NNULLP (env))
1553 /* Make a copy of the lowest frame to protect it from
1554 modifications by SCM_IM_DEFINE */
1555 return unmemocopy (x, scm_cons (SCM_CAR (env), SCM_CDR (env)));
1556 else
1557 return unmemocopy (x, env);
1558}
1559
cf7c17e9 1560#ifndef SCM_RECKLESS
1cc91f1b 1561
0f2d19dd
JB
1562int
1563scm_badargsp (formals, args)
1564 SCM formals;
1565 SCM args;
0f2d19dd 1566{
ff467021 1567 while (SCM_NIMP (formals))
0f2d19dd 1568 {
ff467021
JB
1569 if (SCM_NCONSP (formals))
1570 return 0;
1571 if (SCM_IMP(args))
1572 return 1;
0f2d19dd
JB
1573 formals = SCM_CDR (formals);
1574 args = SCM_CDR (args);
1575 }
1576 return SCM_NNULLP (args) ? 1 : 0;
1577}
1578#endif
1579
1580
1581\f
6dbd0af5 1582SCM
680ed4a8 1583scm_eval_args (l, env, proc)
6dbd0af5
MD
1584 SCM l;
1585 SCM env;
680ed4a8 1586 SCM proc;
6dbd0af5 1587{
680ed4a8 1588 SCM results = SCM_EOL, *lloc = &results, res;
6dbd0af5
MD
1589 while (SCM_NIMP (l))
1590 {
cf7c17e9 1591#ifdef SCM_CAUTIOUS
680ed4a8
MD
1592 if (SCM_IMP (l))
1593 goto wrongnumargs;
1594 else if (SCM_CONSP (l))
1595 {
1596 if (SCM_IMP (SCM_CAR (l)))
6cb702da 1597 res = SCM_EVALIM (SCM_CAR (l), env);
680ed4a8
MD
1598 else
1599 res = EVALCELLCAR (l, env);
1600 }
1601 else if (SCM_TYP3 (l) == 1)
1602 {
1603 if ((res = SCM_GLOC_VAL (SCM_CAR (l))) == 0)
1604 res = SCM_CAR (l); /* struct planted in code */
1605 }
1606 else
1607 goto wrongnumargs;
1608#else
1609 res = EVALCAR (l, env);
1610#endif
1611 *lloc = scm_cons (res, SCM_EOL);
a23afe53 1612 lloc = SCM_CDRLOC (*lloc);
6dbd0af5
MD
1613 l = SCM_CDR (l);
1614 }
cf7c17e9 1615#ifdef SCM_CAUTIOUS
680ed4a8
MD
1616 if (SCM_NNULLP (l))
1617 {
1618 wrongnumargs:
1619 scm_wrong_num_args (proc);
1620 }
1621#endif
1622 return results;
6dbd0af5 1623}
c4ac4d88 1624
9de33deb
MD
1625SCM
1626scm_eval_body (SCM code, SCM env)
1627{
1628 SCM next;
1629 again:
1630 next = code;
1631 while (SCM_NNULLP (next = SCM_CDR (next)))
1632 {
1633 if (SCM_IMP (SCM_CAR (code)))
1634 {
1635 if (SCM_ISYMP (SCM_CAR (code)))
1636 {
1637 code = scm_m_expand_body (code, env);
1638 goto again;
1639 }
1640 }
1641 else
1642 SCM_XEVAL (SCM_CAR (code), env);
1643 code = next;
1644 }
1645 return SCM_XEVALCAR (code, env);
1646}
1647
c4ac4d88 1648
0f2d19dd
JB
1649#endif /* !DEVAL */
1650
6dbd0af5
MD
1651
1652/* SECTION: This code is specific for the debugging support. One
1653 * branch is read when DEVAL isn't defined, the other when DEVAL is
1654 * defined.
1655 */
1656
1657#ifndef DEVAL
1658
1659#define SCM_APPLY scm_apply
1660#define PREP_APPLY(proc, args)
1661#define ENTER_APPLY
1662#define RETURN(x) return x;
b7ff98dd
MD
1663#ifdef STACK_CHECKING
1664#ifndef NO_CEVAL_STACK_CHECKING
1665#define EVAL_STACK_CHECKING
1666#endif
6dbd0af5
MD
1667#endif
1668
1669#else /* !DEVAL */
1670
0f2d19dd
JB
1671#undef SCM_CEVAL
1672#define SCM_CEVAL scm_deval /* Substitute all uses of scm_ceval */
1673#undef SCM_APPLY
1674#define SCM_APPLY scm_dapply
6dbd0af5
MD
1675#undef PREP_APPLY
1676#define PREP_APPLY(p, l) \
1677{ ++debug.info; debug.info->a.proc = p; debug.info->a.args = l; }
1678#undef ENTER_APPLY
1679#define ENTER_APPLY \
1680{\
b7ff98dd 1681 SCM_SET_ARGSREADY (debug);\
b6d75948 1682 if (CHECK_APPLY && SCM_TRAPS_P)\
b7ff98dd 1683 if (SCM_APPLY_FRAME_P || (SCM_TRACE_P && PROCTRACEP (proc)))\
6dbd0af5 1684 {\
b7ff98dd 1685 SCM tmp, tail = SCM_TRACED_FRAME_P (debug) ? SCM_BOOL_T : SCM_BOOL_F;\
c6a4fbce 1686 SCM_SET_TRACED_FRAME (debug); \
b7ff98dd 1687 if (SCM_CHEAPTRAPS_P)\
6dbd0af5 1688 {\
c0ab1b8d 1689 tmp = scm_make_debugobj (&debug);\
2f0d1375 1690 scm_ithrow (scm_sym_apply_frame, scm_cons2 (tmp, tail, SCM_EOL), 0);\
b6d75948 1691 }\
6dbd0af5
MD
1692 else\
1693 {\
1694 scm_make_cont (&tmp);\
ca6ef71a 1695 if (!setjmp (SCM_JMPBUF (tmp)))\
2f0d1375 1696 scm_ithrow (scm_sym_apply_frame, scm_cons2 (tmp, tail, SCM_EOL), 0);\
6dbd0af5
MD
1697 }\
1698 }\
1699}
0f2d19dd
JB
1700#undef RETURN
1701#define RETURN(e) {proc = (e); goto exit;}
b7ff98dd
MD
1702#ifdef STACK_CHECKING
1703#ifndef EVAL_STACK_CHECKING
1704#define EVAL_STACK_CHECKING
1705#endif
6dbd0af5
MD
1706#endif
1707
1708/* scm_ceval_ptr points to the currently selected evaluator.
1709 * *fixme*: Although efficiency is important here, this state variable
1710 * should probably not be a global. It should be related to the
1711 * current repl.
1712 */
1713
1cc91f1b
JB
1714
1715SCM (*scm_ceval_ptr) SCM_P ((SCM x, SCM env));
0f2d19dd 1716
1646d37b 1717/* scm_last_debug_frame contains a pointer to the last debugging
6dbd0af5
MD
1718 * information stack frame. It is accessed very often from the
1719 * debugging evaluator, so it should probably not be indirectly
1720 * addressed. Better to save and restore it from the current root at
1721 * any stack swaps.
1722 */
1723
1646d37b
MD
1724#ifndef USE_THREADS
1725scm_debug_frame *scm_last_debug_frame;
1726#endif
6dbd0af5
MD
1727
1728/* scm_debug_eframe_size is the number of slots available for pseudo
1729 * stack frames at each real stack frame.
1730 */
1731
1732int scm_debug_eframe_size;
1733
b7ff98dd 1734int scm_debug_mode, scm_check_entry_p, scm_check_apply_p, scm_check_exit_p;
6dbd0af5 1735
a74145b8
MD
1736int scm_eval_stack;
1737
33b97402 1738scm_option scm_eval_opts[] = {
a74145b8 1739 { SCM_OPTION_INTEGER, "stack", 22000, "Size of thread stacks (in machine words)." }
33b97402
MD
1740};
1741
6dbd0af5 1742scm_option scm_debug_opts[] = {
b7ff98dd
MD
1743 { SCM_OPTION_BOOLEAN, "cheap", 1,
1744 "*Flyweight representation of the stack at traps." },
1745 { SCM_OPTION_BOOLEAN, "breakpoints", 0, "*Check for breakpoints." },
1746 { SCM_OPTION_BOOLEAN, "trace", 0, "*Trace mode." },
1747 { SCM_OPTION_BOOLEAN, "procnames", 1,
1748 "Record procedure names at definition." },
1749 { SCM_OPTION_BOOLEAN, "backwards", 0,
1750 "Display backtrace in anti-chronological order." },
4e646a03
MD
1751 { SCM_OPTION_INTEGER, "indent", 10, "Maximal indentation in backtrace." },
1752 { SCM_OPTION_INTEGER, "frames", 3,
b7ff98dd 1753 "Maximum number of tail-recursive frames in backtrace." },
4e646a03
MD
1754 { SCM_OPTION_INTEGER, "maxdepth", 1000,
1755 "Maximal number of stored backtrace frames." },
1756 { SCM_OPTION_INTEGER, "depth", 20, "Maximal length of printed backtrace." },
11f77bfc
MD
1757 { SCM_OPTION_BOOLEAN, "backtrace", 0, "Show backtrace on error." },
1758 { SCM_OPTION_BOOLEAN, "debug", 0, "Use the debugging evaluator." },
a74145b8 1759 { SCM_OPTION_INTEGER, "stack", 20000, "Stack size limit (measured in words; 0 = no check)." }
6dbd0af5
MD
1760};
1761
1762scm_option scm_evaluator_trap_table[] = {
b6d75948 1763 { SCM_OPTION_BOOLEAN, "traps", 0, "Enable evaluator traps." },
b7ff98dd
MD
1764 { SCM_OPTION_BOOLEAN, "enter-frame", 0, "Trap when eval enters new frame." },
1765 { SCM_OPTION_BOOLEAN, "apply-frame", 0, "Trap when entering apply." },
1766 { SCM_OPTION_BOOLEAN, "exit-frame", 0, "Trap when exiting eval or apply." }
6dbd0af5
MD
1767};
1768
33b97402
MD
1769SCM_PROC (s_eval_options_interface, "eval-options-interface", 0, 1, 0, scm_eval_options_interface);
1770
1771SCM
8ecf1f13 1772scm_eval_options_interface (SCM setting)
33b97402
MD
1773{
1774 SCM ans;
1775 SCM_DEFER_INTS;
1776 ans = scm_options (setting,
1777 scm_eval_opts,
1778 SCM_N_EVAL_OPTIONS,
1779 s_eval_options_interface);
a74145b8 1780 scm_eval_stack = SCM_EVAL_STACK * sizeof (void *);
33b97402
MD
1781 SCM_ALLOW_INTS;
1782 return ans;
1783}
1784
1785SCM_PROC (s_evaluator_traps, "evaluator-traps-interface", 0, 1, 0, scm_evaluator_traps);
1786
1787SCM
1788scm_evaluator_traps (setting)
1789 SCM setting;
1790{
1791 SCM ans;
1792 SCM_DEFER_INTS;
1793 ans = scm_options (setting,
1794 scm_evaluator_trap_table,
1795 SCM_N_EVALUATOR_TRAPS,
1796 s_evaluator_traps);
1797 SCM_RESET_DEBUG_MODE;
1798 SCM_ALLOW_INTS
1799 return ans;
1800}
1801
6dbd0af5 1802SCM
680ed4a8
MD
1803scm_deval_args (l, env, proc, lloc)
1804 SCM l, env, proc, *lloc;
0f2d19dd 1805{
680ed4a8 1806 SCM *results = lloc, res;
0f2d19dd
JB
1807 while (SCM_NIMP (l))
1808 {
cf7c17e9 1809#ifdef SCM_CAUTIOUS
680ed4a8
MD
1810 if (SCM_IMP (l))
1811 goto wrongnumargs;
1812 else if (SCM_CONSP (l))
1813 {
1814 if (SCM_IMP (SCM_CAR (l)))
6cb702da 1815 res = SCM_EVALIM (SCM_CAR (l), env);
680ed4a8
MD
1816 else
1817 res = EVALCELLCAR (l, env);
1818 }
1819 else if (SCM_TYP3 (l) == 1)
1820 {
1821 if ((res = SCM_GLOC_VAL (SCM_CAR (l))) == 0)
1822 res = SCM_CAR (l); /* struct planted in code */
1823 }
1824 else
1825 goto wrongnumargs;
1826#else
1827 res = EVALCAR (l, env);
1828#endif
1829 *lloc = scm_cons (res, SCM_EOL);
a23afe53 1830 lloc = SCM_CDRLOC (*lloc);
0f2d19dd
JB
1831 l = SCM_CDR (l);
1832 }
cf7c17e9 1833#ifdef SCM_CAUTIOUS
680ed4a8
MD
1834 if (SCM_NNULLP (l))
1835 {
1836 wrongnumargs:
1837 scm_wrong_num_args (proc);
1838 }
1839#endif
1840 return *results;
0f2d19dd
JB
1841}
1842
6dbd0af5
MD
1843#endif /* !DEVAL */
1844
1845
1846/* SECTION: Some local definitions for the evaluator.
1847 */
1848
1849#ifndef DEVAL
1850#ifdef SCM_FLOATS
1851#define CHECK_EQVISH(A,B) (((A) == (B)) || (SCM_NFALSEP (scm_eqv_p ((A), (B)))))
1852#else
1853#define CHECK_EQVISH(A,B) ((A) == (B))
1854#endif
1855#endif /* DEVAL */
1856
399dedcc 1857#define BUILTIN_RPASUBR /* Handle rpsubrs and asubrs without calling apply */
6dbd0af5
MD
1858
1859/* SECTION: This is the evaluator. Like any real monster, it has
1860 * three heads. This code is compiled twice.
1861 */
1862
0f2d19dd 1863#if 0
1cc91f1b 1864
0f2d19dd
JB
1865SCM
1866scm_ceval (x, env)
1867 SCM x;
1868 SCM env;
0f2d19dd
JB
1869{}
1870#endif
1871#if 0
1cc91f1b 1872
0f2d19dd
JB
1873SCM
1874scm_deval (x, env)
1875 SCM x;
1876 SCM env;
0f2d19dd
JB
1877{}
1878#endif
1879
6dbd0af5 1880SCM
0f2d19dd
JB
1881SCM_CEVAL (x, env)
1882 SCM x;
1883 SCM env;
1884{
1885 union
1886 {
1887 SCM *lloc;
1888 SCM arg1;
f8769b1d 1889 } t;
6dbd0af5
MD
1890 SCM proc, arg2;
1891#ifdef DEVAL
c0ab1b8d
JB
1892 scm_debug_frame debug;
1893 scm_debug_info *debug_info_end;
1646d37b 1894 debug.prev = scm_last_debug_frame;
6dbd0af5 1895 debug.status = scm_debug_eframe_size;
04b6c081
MD
1896 /*
1897 * The debug.vect contains twice as much scm_debug_info frames as the
1898 * user has specified with (debug-set! frames <n>).
1899 *
1900 * Even frames are eval frames, odd frames are apply frames.
1901 */
c0ab1b8d
JB
1902 debug.vect = (scm_debug_info *) alloca (scm_debug_eframe_size
1903 * sizeof (debug.vect[0]));
1904 debug.info = debug.vect;
1905 debug_info_end = debug.vect + scm_debug_eframe_size;
1906 scm_last_debug_frame = &debug;
6dbd0af5 1907#endif
b7ff98dd
MD
1908#ifdef EVAL_STACK_CHECKING
1909 if (SCM_STACK_OVERFLOW_P ((SCM_STACKITEM *) &proc)
1910 && scm_stack_checking_enabled_p)
6dbd0af5 1911 {
b7ff98dd 1912#ifdef DEVAL
6dbd0af5
MD
1913 debug.info->e.exp = x;
1914 debug.info->e.env = env;
b7ff98dd 1915#endif
6dbd0af5
MD
1916 scm_report_stack_overflow ();
1917 }
1918#endif
1919#ifdef DEVAL
1920 goto start;
1921#endif
1922loopnoap:
1923 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
1924loop:
1925#ifdef DEVAL
b7ff98dd
MD
1926 SCM_CLEAR_ARGSREADY (debug);
1927 if (SCM_OVERFLOWP (debug))
6dbd0af5 1928 --debug.info;
04b6c081
MD
1929 /*
1930 * In theory, this should be the only place where it is necessary to
1931 * check for space in debug.vect since both eval frames and
1932 * available space are even.
1933 *
1934 * For this to be the case, however, it is necessary that primitive
1935 * special forms which jump back to `loop', `begin' or some similar
1936 * label call PREP_APPLY. A convenient way to do this is to jump to
1937 * `loopnoap' or `cdrxnoap'.
1938 */
c0ab1b8d 1939 else if (++debug.info >= debug_info_end)
6dbd0af5 1940 {
b7ff98dd 1941 SCM_SET_OVERFLOW (debug);
6dbd0af5
MD
1942 debug.info -= 2;
1943 }
1944start:
1945 debug.info->e.exp = x;
1946 debug.info->e.env = env;
b6d75948 1947 if (CHECK_ENTRY && SCM_TRAPS_P)
b7ff98dd 1948 if (SCM_ENTER_FRAME_P || (SCM_BREAKPOINTS_P && SRCBRKP (x)))
6dbd0af5 1949 {
b7ff98dd
MD
1950 SCM tail = SCM_TAILRECP (debug) ? SCM_BOOL_T : SCM_BOOL_F;
1951 SCM_SET_TAILREC (debug);
b7ff98dd 1952 if (SCM_CHEAPTRAPS_P)
c0ab1b8d 1953 t.arg1 = scm_make_debugobj (&debug);
6dbd0af5
MD
1954 else
1955 {
1956 scm_make_cont (&t.arg1);
ca6ef71a 1957 if (setjmp (SCM_JMPBUF (t.arg1)))
6dbd0af5
MD
1958 {
1959 x = SCM_THROW_VALUE (t.arg1);
1960 if (SCM_IMP (x))
1961 {
1962 RETURN (x);
1963 }
1964 else
1965 /* This gives the possibility for the debugger to
1966 modify the source expression before evaluation. */
1967 goto dispatch;
1968 }
1969 }
2f0d1375 1970 scm_ithrow (scm_sym_enter_frame,
6dbd0af5
MD
1971 scm_cons2 (t.arg1, tail,
1972 scm_cons (scm_unmemocopy (x, env), SCM_EOL)),
1973 0);
1974 }
6dbd0af5 1975#endif
e3173f93 1976#if defined (USE_THREADS) || defined (DEVAL)
f8769b1d 1977dispatch:
e3173f93 1978#endif
9cb5124f 1979 SCM_TICK;
0f2d19dd
JB
1980 switch (SCM_TYP7 (x))
1981 {
1982 case scm_tcs_symbols:
1983 /* Only happens when called at top level.
1984 */
1985 x = scm_cons (x, SCM_UNDEFINED);
1986 goto retval;
1987
1988 case (127 & SCM_IM_AND):
1989 x = SCM_CDR (x);
1990 t.arg1 = x;
1991 while (SCM_NNULLP (t.arg1 = SCM_CDR (t.arg1)))
1992 if (SCM_FALSEP (EVALCAR (x, env)))
1993 {
1994 RETURN (SCM_BOOL_F);
1995 }
1996 else
1997 x = t.arg1;
6dbd0af5 1998 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
0f2d19dd
JB
1999 goto carloop;
2000
2001 case (127 & SCM_IM_BEGIN):
6dbd0af5
MD
2002 cdrxnoap:
2003 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
0f2d19dd
JB
2004 cdrxbegin:
2005 x = SCM_CDR (x);
2006
2007 begin:
2008 t.arg1 = x;
2009 while (SCM_NNULLP (t.arg1 = SCM_CDR (t.arg1)))
2010 {
26d5b9b4
MD
2011 if (SCM_IMP (SCM_CAR (x)))
2012 {
2013 if (SCM_ISYMP (SCM_CAR (x)))
2014 {
2015 x = scm_m_expand_body (x, env);
2016 goto begin;
2017 }
2018 }
2019 else
2020 SCM_CEVAL (SCM_CAR (x), env);
0f2d19dd
JB
2021 x = t.arg1;
2022 }
2023
2024 carloop: /* scm_eval car of last form in list */
2025 if (SCM_NCELLP (SCM_CAR (x)))
2026 {
2027 x = SCM_CAR (x);
6cb702da 2028 RETURN (SCM_IMP (x) ? SCM_EVALIM (x, env) : SCM_GLOC_VAL (x))
0f2d19dd
JB
2029 }
2030
2031 if (SCM_SYMBOLP (SCM_CAR (x)))
2032 {
2033 retval:
26d5b9b4 2034 RETURN (*scm_lookupcar (x, env, 1))
0f2d19dd
JB
2035 }
2036
2037 x = SCM_CAR (x);
2038 goto loop; /* tail recurse */
2039
2040
2041 case (127 & SCM_IM_CASE):
2042 x = SCM_CDR (x);
2043 t.arg1 = EVALCAR (x, env);
2044 while (SCM_NIMP (x = SCM_CDR (x)))
2045 {
2046 proc = SCM_CAR (x);
2f0d1375 2047 if (scm_sym_else == SCM_CAR (proc))
0f2d19dd
JB
2048 {
2049 x = SCM_CDR (proc);
6dbd0af5 2050 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
0f2d19dd
JB
2051 goto begin;
2052 }
2053 proc = SCM_CAR (proc);
2054 while (SCM_NIMP (proc))
2055 {
2056 if (CHECK_EQVISH (SCM_CAR (proc), t.arg1))
2057 {
2058 x = SCM_CDR (SCM_CAR (x));
6dbd0af5 2059 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
0f2d19dd
JB
2060 goto begin;
2061 }
2062 proc = SCM_CDR (proc);
2063 }
2064 }
6dbd0af5 2065 RETURN (SCM_UNSPECIFIED)
0f2d19dd
JB
2066
2067
2068 case (127 & SCM_IM_COND):
2069 while (SCM_NIMP (x = SCM_CDR (x)))
2070 {
2071 proc = SCM_CAR (x);
2072 t.arg1 = EVALCAR (proc, env);
2073 if (SCM_NFALSEP (t.arg1))
2074 {
2075 x = SCM_CDR (proc);
6dbd0af5 2076 if SCM_NULLP (x)
0f2d19dd 2077 {
6dbd0af5 2078 RETURN (t.arg1)
0f2d19dd 2079 }
2f0d1375 2080 if (scm_sym_arrow != SCM_CAR (x))
6dbd0af5
MD
2081 {
2082 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2083 goto begin;
2084 }
0f2d19dd
JB
2085 proc = SCM_CDR (x);
2086 proc = EVALCAR (proc, env);
2087 SCM_ASRTGO (SCM_NIMP (proc), badfun);
6dbd0af5
MD
2088 PREP_APPLY (proc, scm_cons (t.arg1, SCM_EOL));
2089 ENTER_APPLY;
0f2d19dd
JB
2090 goto evap1;
2091 }
2092 }
6dbd0af5 2093 RETURN (SCM_UNSPECIFIED)
0f2d19dd
JB
2094
2095
2096 case (127 & SCM_IM_DO):
2097 x = SCM_CDR (x);
2098 proc = SCM_CAR (SCM_CDR (x)); /* inits */
2099 t.arg1 = SCM_EOL; /* values */
2100 while (SCM_NIMP (proc))
2101 {
2102 t.arg1 = scm_cons (EVALCAR (proc, env), t.arg1);
2103 proc = SCM_CDR (proc);
2104 }
e2806c10 2105 env = EXTEND_ENV (SCM_CAR (x), t.arg1, env);
0f2d19dd
JB
2106 x = SCM_CDR (SCM_CDR (x));
2107 while (proc = SCM_CAR (x), SCM_FALSEP (EVALCAR (proc, env)))
2108 {
f3d2630a 2109 for (proc = SCM_CADR (x); SCM_NIMP (proc); proc = SCM_CDR (proc))
0f2d19dd
JB
2110 {
2111 t.arg1 = SCM_CAR (proc); /* body */
2112 SIDEVAL (t.arg1, env);
2113 }
f3d2630a
MD
2114 for (t.arg1 = SCM_EOL, proc = SCM_CDDR (x);
2115 SCM_NIMP (proc);
2116 proc = SCM_CDR (proc))
0f2d19dd 2117 t.arg1 = scm_cons (EVALCAR (proc, env), t.arg1); /* steps */
e2806c10 2118 env = EXTEND_ENV (SCM_CAR (SCM_CAR (env)), t.arg1, SCM_CDR (env));
0f2d19dd
JB
2119 }
2120 x = SCM_CDR (proc);
2121 if (SCM_NULLP (x))
6dbd0af5
MD
2122 RETURN (SCM_UNSPECIFIED);
2123 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
0f2d19dd
JB
2124 goto begin;
2125
2126
2127 case (127 & SCM_IM_IF):
2128 x = SCM_CDR (x);
2129 if (SCM_NFALSEP (EVALCAR (x, env)))
2130 x = SCM_CDR (x);
2131 else if (SCM_IMP (x = SCM_CDR (SCM_CDR (x))))
2132 {
2133 RETURN (SCM_UNSPECIFIED);
2134 }
6dbd0af5 2135 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
0f2d19dd
JB
2136 goto carloop;
2137
2138
2139 case (127 & SCM_IM_LET):
2140 x = SCM_CDR (x);
2141 proc = SCM_CAR (SCM_CDR (x));
2142 t.arg1 = SCM_EOL;
2143 do
2144 {
2145 t.arg1 = scm_cons (EVALCAR (proc, env), t.arg1);
2146 }
2147 while (SCM_NIMP (proc = SCM_CDR (proc)));
e2806c10 2148 env = EXTEND_ENV (SCM_CAR (x), t.arg1, env);
0f2d19dd 2149 x = SCM_CDR (x);
6dbd0af5 2150 goto cdrxnoap;
0f2d19dd
JB
2151
2152
2153 case (127 & SCM_IM_LETREC):
2154 x = SCM_CDR (x);
e2806c10 2155 env = EXTEND_ENV (SCM_CAR (x), scm_undefineds, env);
0f2d19dd
JB
2156 x = SCM_CDR (x);
2157 proc = SCM_CAR (x);
2158 t.arg1 = SCM_EOL;
2159 do
2160 {
2161 t.arg1 = scm_cons (EVALCAR (proc, env), t.arg1);
2162 }
2163 while (SCM_NIMP (proc = SCM_CDR (proc)));
a23afe53 2164 SCM_SETCDR (SCM_CAR (env), t.arg1);
6dbd0af5 2165 goto cdrxnoap;
0f2d19dd
JB
2166
2167
2168 case (127 & SCM_IM_LETSTAR):
2169 x = SCM_CDR (x);
2170 proc = SCM_CAR (x);
2171 if (SCM_IMP (proc))
2172 {
e2806c10 2173 env = EXTEND_ENV (SCM_EOL, SCM_EOL, env);
6dbd0af5 2174 goto cdrxnoap;
0f2d19dd
JB
2175 }
2176 do
2177 {
2178 t.arg1 = SCM_CAR (proc);
2179 proc = SCM_CDR (proc);
e2806c10 2180 env = EXTEND_ENV (t.arg1, EVALCAR (proc, env), env);
0f2d19dd
JB
2181 }
2182 while (SCM_NIMP (proc = SCM_CDR (proc)));
6dbd0af5 2183 goto cdrxnoap;
0f2d19dd
JB
2184
2185 case (127 & SCM_IM_OR):
2186 x = SCM_CDR (x);
2187 t.arg1 = x;
2188 while (SCM_NNULLP (t.arg1 = SCM_CDR (t.arg1)))
2189 {
2190 x = EVALCAR (x, env);
2191 if (SCM_NFALSEP (x))
2192 {
2193 RETURN (x);
2194 }
2195 x = t.arg1;
2196 }
6dbd0af5 2197 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
0f2d19dd
JB
2198 goto carloop;
2199
2200
2201 case (127 & SCM_IM_LAMBDA):
2202 RETURN (scm_closure (SCM_CDR (x), env));
2203
2204
2205 case (127 & SCM_IM_QUOTE):
2206 RETURN (SCM_CAR (SCM_CDR (x)));
2207
2208
89efbff4 2209 case (127 & SCM_IM_SET_X):
0f2d19dd
JB
2210 x = SCM_CDR (x);
2211 proc = SCM_CAR (x);
6dbd0af5 2212 switch (7 & (int) proc)
0f2d19dd
JB
2213 {
2214 case 0:
26d5b9b4 2215 t.lloc = scm_lookupcar (x, env, 1);
0f2d19dd
JB
2216 break;
2217 case 1:
a23afe53 2218 t.lloc = SCM_GLOC_VAL_LOC (proc);
0f2d19dd
JB
2219 break;
2220#ifdef MEMOIZE_LOCALS
2221 case 4:
2222 t.lloc = scm_ilookup (proc, env);
2223 break;
2224#endif
2225 }
2226 x = SCM_CDR (x);
2227 *t.lloc = EVALCAR (x, env);
0f2d19dd
JB
2228#ifdef SICP
2229 RETURN (*t.lloc);
2230#else
2231 RETURN (SCM_UNSPECIFIED);
2232#endif
2233
2234
2235 case (127 & SCM_IM_DEFINE): /* only for internal defines */
26d5b9b4
MD
2236 scm_misc_error (NULL, "Bad define placement", SCM_EOL);
2237
0f2d19dd
JB
2238 /* new syntactic forms go here. */
2239 case (127 & SCM_MAKISYM (0)):
2240 proc = SCM_CAR (x);
2241 SCM_ASRTGO (SCM_ISYMP (proc), badfun);
2242 switch SCM_ISYMNUM (proc)
2243 {
2244#if 0
2245 case (SCM_ISYMNUM (IM_VREF)):
2246 {
2247 SCM var;
2248 var = SCM_CAR (SCM_CDR (x));
2249 RETURN (SCM_CDR(var));
2250 }
2251 case (SCM_ISYMNUM (IM_VSET)):
2252 SCM_CDR (SCM_CAR ( SCM_CDR (x))) = EVALCAR( SCM_CDR ( SCM_CDR (x)), env);
2253 SCM_CAR (SCM_CAR ( SCM_CDR (x))) = scm_tc16_variable;
6dbd0af5 2254 RETURN (SCM_UNSPECIFIED)
0f2d19dd
JB
2255#endif
2256
2257 case (SCM_ISYMNUM (SCM_IM_APPLY)):
2258 proc = SCM_CDR (x);
2259 proc = EVALCAR (proc, env);
2260 SCM_ASRTGO (SCM_NIMP (proc), badfun);
2261 if (SCM_CLOSUREP (proc))
2262 {
1609038c 2263 SCM argl, tl;
6dbd0af5 2264 PREP_APPLY (proc, SCM_EOL);
0f2d19dd
JB
2265 t.arg1 = SCM_CDR (SCM_CDR (x));
2266 t.arg1 = EVALCAR (t.arg1, env);
6dbd0af5
MD
2267#ifdef DEVAL
2268 debug.info->a.args = t.arg1;
2269#endif
cf7c17e9 2270#ifndef SCM_RECKLESS
0f2d19dd
JB
2271 if (scm_badargsp (SCM_CAR (SCM_CODE (proc)), t.arg1))
2272 goto wrongnumargs;
2273#endif
c79450dd 2274 ENTER_APPLY;
1609038c
MD
2275 /* Copy argument list */
2276 if (SCM_IMP (t.arg1))
2277 argl = t.arg1;
2278 else
2279 {
2280 argl = tl = scm_cons (SCM_CAR (t.arg1), SCM_UNSPECIFIED);
2281 while (SCM_NIMP (t.arg1 = SCM_CDR (t.arg1))
2282 && SCM_CONSP (t.arg1))
2283 {
2284 SCM_SETCDR (tl, scm_cons (SCM_CAR (t.arg1),
2285 SCM_UNSPECIFIED));
2286 tl = SCM_CDR (tl);
2287 }
2288 SCM_SETCDR (tl, t.arg1);
2289 }
2290
2291 env = EXTEND_ENV (SCM_CAR (SCM_CODE (proc)), argl, SCM_ENV (proc));
0f2d19dd
JB
2292 x = SCM_CODE (proc);
2293 goto cdrxbegin;
2294 }
81123e6d 2295 proc = scm_f_apply;
0f2d19dd
JB
2296 goto evapply;
2297
2298 case (SCM_ISYMNUM (SCM_IM_CONT)):
2299 scm_make_cont (&t.arg1);
ca6ef71a 2300 if (setjmp (SCM_JMPBUF (t.arg1)))
0f2d19dd
JB
2301 {
2302 SCM val;
2303 val = SCM_THROW_VALUE (t.arg1);
6dbd0af5 2304 RETURN (val);
0f2d19dd
JB
2305 }
2306 proc = SCM_CDR (x);
2307 proc = evalcar (proc, env);
2308 SCM_ASRTGO (SCM_NIMP (proc), badfun);
6dbd0af5
MD
2309 PREP_APPLY (proc, scm_cons (t.arg1, SCM_EOL));
2310 ENTER_APPLY;
0f2d19dd
JB
2311 goto evap1;
2312
89efbff4 2313 case (SCM_ISYMNUM (SCM_IM_DISPATCH)):
195847fa
MD
2314 proc = SCM_CADR (x); /* unevaluated operands */
2315 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2316 if (SCM_IMP (proc))
2317 arg2 = *scm_ilookup (proc, env);
2318 else if (SCM_NCONSP (proc))
2319 {
2320 if (SCM_NCELLP (proc))
2321 arg2 = SCM_GLOC_VAL (proc);
2322 else
2323 arg2 = *scm_lookupcar (SCM_CDR (x), env, 1);
2324 }
2325 else
2326 {
2327 arg2 = scm_cons (EVALCAR (proc, env), SCM_EOL);
2328 t.lloc = SCM_CDRLOC (arg2);
2329 while (SCM_NIMP (proc = SCM_CDR (proc)))
2330 {
2331 *t.lloc = scm_cons (EVALCAR (proc, env), SCM_EOL);
2332 t.lloc = SCM_CDRLOC (*t.lloc);
2333 }
2334 }
2335
2336 type_dispatch:
61364ba6
MD
2337 /* The type dispatch code is duplicated here
2338 * (c.f. objects.c:scm_mcache_compute_cmethod) since that
2339 * cuts down execution time for type dispatch to 50%.
2340 */
2341 {
2342 int i, n, end, mask;
2343 SCM z = SCM_CDDR (x);
2344 n = SCM_INUM (SCM_CAR (z)); /* maximum number of specializers */
2345 proc = SCM_CADR (z);
2346
2347 if (SCM_NIMP (proc))
2348 {
2349 /* Prepare for linear search */
2350 mask = -1;
2351 i = 0;
2352 end = SCM_LENGTH (proc);
2353 }
2354 else
2355 {
2356 /* Compute a hash value */
2357 int hashset = SCM_INUM (proc);
2358 int j = n;
2359 mask = SCM_INUM (SCM_CAR (z = SCM_CDDR (z)));
2360 proc = SCM_CADR (z);
2361 i = 0;
2362 t.arg1 = arg2;
2363 if (SCM_NIMP (t.arg1))
2364 do
2365 {
2366 i += (SCM_STRUCT_DATA (scm_class_of (SCM_CAR (t.arg1)))
2367 [scm_si_hashsets + hashset]);
2368 t.arg1 = SCM_CDR (t.arg1);
2369 }
2370 while (--j && SCM_NIMP (t.arg1));
2371 i &= mask;
2372 end = i;
2373 }
2374
2375 /* Search for match */
2376 do
2377 {
2378 int j = n;
2379 z = SCM_VELTS (proc)[i];
2380 t.arg1 = arg2; /* list of arguments */
2381 if (SCM_NIMP (t.arg1))
2382 do
2383 {
2384 /* More arguments than specifiers => CLASS != ENV */
2385 if (scm_class_of (SCM_CAR (t.arg1)) != SCM_CAR (z))
2386 goto next_method;
2387 t.arg1 = SCM_CDR (t.arg1);
2388 z = SCM_CDR (z);
2389 }
2390 while (--j && SCM_NIMP (t.arg1));
2391 /* Fewer arguments than specifiers => CAR != ENV */
2392 if (!(SCM_IMP (SCM_CAR (z)) || SCM_CONSP (SCM_CAR (z))))
2393 goto next_method;
2394 apply_cmethod:
2395 env = EXTEND_ENV (SCM_CAR (SCM_CMETHOD_CODE (z)),
2396 arg2,
2397 SCM_CMETHOD_ENV (z));
2398 x = SCM_CMETHOD_CODE (z);
2399 goto cdrxbegin;
2400 next_method:
2401 i = (i + 1) & mask;
2402 } while (i != end);
2403
2404 z = scm_memoize_method (x, arg2);
2405 goto apply_cmethod;
2406 }
73b64342 2407
ca4be6ea
MD
2408 case (SCM_ISYMNUM (SCM_IM_SLOT_REF)):
2409 x = SCM_CDR (x);
2410 t.arg1 = EVALCAR (x, env);
2411 RETURN (SCM_STRUCT_DATA (t.arg1)[SCM_INUM (SCM_CADR (x))]);
2412
2413 case (SCM_ISYMNUM (SCM_IM_SLOT_SET_X)):
2414 x = SCM_CDR (x);
2415 t.arg1 = EVALCAR (x, env);
2416 x = SCM_CDR (x);
2417 proc = SCM_CDR (x);
1f325865
MD
2418 SCM_STRUCT_DATA (t.arg1)[SCM_INUM (SCM_CAR (x))]
2419 = EVALCAR (proc, env);
2420 RETURN (SCM_UNSPECIFIED);
ca4be6ea 2421
73b64342
MD
2422 case (SCM_ISYMNUM (SCM_IM_NIL_COND)):
2423 proc = SCM_CDR (x);
2424 while (SCM_NIMP (x = SCM_CDR (proc)))
2425 {
2426 if (!(SCM_FALSEP (t.arg1 = EVALCAR (proc, env))
2427 || t.arg1 == scm_nil))
2428 {
2429 if (SCM_CAR (x) == SCM_UNSPECIFIED)
2430 RETURN (t.arg1);
2431 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2432 goto carloop;
2433 }
2434 proc = SCM_CDR (x);
2435 }
2436 x = proc;
2437 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2438 goto carloop;
2439
2440 case (SCM_ISYMNUM (SCM_IM_NIL_IFY)):
2441 x = SCM_CDR (x);
2442 RETURN ((SCM_FALSEP (proc = EVALCAR (x, env)) || SCM_NULLP (proc))
2443 ? scm_nil
2444 : proc)
2445
2446 case (SCM_ISYMNUM (SCM_IM_T_IFY)):
2447 x = SCM_CDR (x);
2448 RETURN (SCM_NFALSEP (EVALCAR (x, env)) ? scm_t : scm_nil)
2449
2450 case (SCM_ISYMNUM (SCM_IM_0_COND)):
2451 proc = SCM_CDR (x);
2452 while (SCM_NIMP (x = SCM_CDR (proc)))
2453 {
2454 if (!(SCM_FALSEP (t.arg1 = EVALCAR (proc, env))
2455 || t.arg1 == SCM_INUM0))
2456 {
2457 if (SCM_CAR (x) == SCM_UNSPECIFIED)
2458 RETURN (t.arg1);
2459 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2460 goto carloop;
2461 }
2462 proc = SCM_CDR (x);
2463 }
2464 x = proc;
2465 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2466 goto carloop;
2467
2468 case (SCM_ISYMNUM (SCM_IM_0_IFY)):
2469 x = SCM_CDR (x);
2470 RETURN (SCM_FALSEP (proc = EVALCAR (x, env))
2471 ? SCM_INUM0
2472 : proc)
2473
2474 case (SCM_ISYMNUM (SCM_IM_1_IFY)):
2475 x = SCM_CDR (x);
2476 RETURN (SCM_NFALSEP (EVALCAR (x, env))
2477 ? SCM_MAKINUM (1)
2478 : SCM_INUM0)
2479
2480 case (SCM_ISYMNUM (SCM_IM_BIND)):
2481 x = SCM_CDR (x);
2482
2483 t.arg1 = SCM_CAR (x);
2484 arg2 = SCM_CDAR (env);
2485 while (SCM_NIMP (arg2))
2486 {
2487 proc = SCM_GLOC_VAL (SCM_CAR (t.arg1));
2488 SCM_SETCDR (SCM_CAR (t.arg1) - 1L, SCM_CAR (arg2));
2489 SCM_SETCAR (arg2, proc);
2490 t.arg1 = SCM_CDR (t.arg1);
2491 arg2 = SCM_CDR (arg2);
2492 }
2493 t.arg1 = SCM_CAR (x);
2494 scm_dynwinds = scm_acons (t.arg1, SCM_CDAR (env), scm_dynwinds);
89efbff4 2495
73b64342
MD
2496 arg2 = x = SCM_CDR (x);
2497 while (SCM_NNULLP (arg2 = SCM_CDR (arg2)))
2498 {
2499 SIDEVAL (SCM_CAR (x), env);
2500 x = arg2;
2501 }
2502 proc = EVALCAR (x, env);
2503
2504 scm_dynwinds = SCM_CDR (scm_dynwinds);
2505 arg2 = SCM_CDAR (env);
2506 while (SCM_NIMP (arg2))
2507 {
2508 SCM_SETCDR (SCM_CAR (t.arg1) - 1L, SCM_CAR (arg2));
2509 t.arg1 = SCM_CDR (t.arg1);
2510 arg2 = SCM_CDR (arg2);
2511 }
2512
2513 RETURN (proc)
2514
0f2d19dd
JB
2515 default:
2516 goto badfun;
2517 }
2518
2519 default:
2520 proc = x;
2521 badfun:
f5bf2977 2522 /* scm_everr (x, env,...) */
523f5266
GH
2523 scm_misc_error (NULL,
2524 "Wrong type to apply: %S",
2525 scm_listify (proc, SCM_UNDEFINED));
0f2d19dd
JB
2526 case scm_tc7_vector:
2527 case scm_tc7_wvect:
2528 case scm_tc7_bvect:
2529 case scm_tc7_byvect:
2530 case scm_tc7_svect:
2531 case scm_tc7_ivect:
2532 case scm_tc7_uvect:
2533 case scm_tc7_fvect:
2534 case scm_tc7_dvect:
2535 case scm_tc7_cvect:
2536#ifdef LONGLONGS
2537 case scm_tc7_llvect:
2538#endif
2539 case scm_tc7_string:
0f2d19dd 2540 case scm_tc7_substring:
0f2d19dd
JB
2541 case scm_tc7_smob:
2542 case scm_tcs_closures:
224822be
MD
2543#ifdef CCLO
2544 case scm_tc7_cclo:
2545#endif
89efbff4 2546 case scm_tc7_pws:
0f2d19dd
JB
2547 case scm_tcs_subrs:
2548 RETURN (x);
2549
2550#ifdef MEMOIZE_LOCALS
2551 case (127 & SCM_ILOC00):
2552 proc = *scm_ilookup (SCM_CAR (x), env);
2553 SCM_ASRTGO (SCM_NIMP (proc), badfun);
cf7c17e9
JB
2554#ifndef SCM_RECKLESS
2555#ifdef SCM_CAUTIOUS
0f2d19dd
JB
2556 goto checkargs;
2557#endif
2558#endif
2559 break;
2560#endif /* ifdef MEMOIZE_LOCALS */
2561
2562
2563 case scm_tcs_cons_gloc:
2564 proc = SCM_GLOC_VAL (SCM_CAR (x));
aa00bd1e
MD
2565 if (proc == 0)
2566 /* This is a struct implanted in the code, not a gloc. */
2567 RETURN (x);
0f2d19dd 2568 SCM_ASRTGO (SCM_NIMP (proc), badfun);
cf7c17e9
JB
2569#ifndef SCM_RECKLESS
2570#ifdef SCM_CAUTIOUS
0f2d19dd
JB
2571 goto checkargs;
2572#endif
2573#endif
2574 break;
2575
2576
2577 case scm_tcs_cons_nimcar:
2578 if (SCM_SYMBOLP (SCM_CAR (x)))
2579 {
f8769b1d 2580#ifdef USE_THREADS
26d5b9b4 2581 t.lloc = scm_lookupcar1 (x, env, 1);
f8769b1d
MV
2582 if (t.lloc == NULL)
2583 {
2584 /* we have lost the race, start again. */
2585 goto dispatch;
2586 }
2587 proc = *t.lloc;
2588#else
26d5b9b4 2589 proc = *scm_lookupcar (x, env, 1);
f8769b1d
MV
2590#endif
2591
0f2d19dd
JB
2592 if (SCM_IMP (proc))
2593 {
2594 unmemocar (x, env);
2595 goto badfun;
2596 }
2597 if (scm_tc16_macro == SCM_TYP16 (proc))
2598 {
2599 unmemocar (x, env);
2600
2601 handle_a_macro:
368bf056 2602#ifdef DEVAL
7c354052
MD
2603 /* Set a flag during macro expansion so that macro
2604 application frames can be deleted from the backtrace. */
2605 SCM_SET_MACROEXP (debug);
368bf056 2606#endif
f8769b1d
MV
2607 t.arg1 = SCM_APPLY (SCM_CDR (proc), x,
2608 scm_cons (env, scm_listofnull));
2609
7c354052
MD
2610#ifdef DEVAL
2611 SCM_CLEAR_MACROEXP (debug);
2612#endif
0f2d19dd
JB
2613 switch ((int) (SCM_CAR (proc) >> 16))
2614 {
2615 case 2:
2616 if (scm_ilength (t.arg1) <= 0)
2617 t.arg1 = scm_cons2 (SCM_IM_BEGIN, t.arg1, SCM_EOL);
6dbd0af5
MD
2618#ifdef DEVAL
2619 if (!SCM_CLOSUREP (SCM_CDR (proc)))
2620 {
f8769b1d 2621
6dbd0af5
MD
2622#if 0 /* Top-level defines doesn't very often occur in backtraces */
2623 if (scm_m_define == SCM_SUBRF (SCM_CDR (proc)) && SCM_TOP_LEVEL (env))
2624 /* Prevent memoizing result of define macro */
2625 {
2626 debug.info->e.exp = scm_cons (SCM_CAR (x), SCM_CDR (x));
2627 scm_set_source_properties_x (debug.info->e.exp,
2628 scm_source_properties (x));
2629 }
2630#endif
2631 SCM_DEFER_INTS;
a23afe53
MD
2632 SCM_SETCAR (x, SCM_CAR (t.arg1));
2633 SCM_SETCDR (x, SCM_CDR (t.arg1));
6dbd0af5
MD
2634 SCM_ALLOW_INTS;
2635 goto dispatch;
2636 }
2637 /* Prevent memoizing of debug info expression. */
6203706f
MD
2638 debug.info->e.exp = scm_cons_source (debug.info->e.exp,
2639 SCM_CAR (x),
2640 SCM_CDR (x));
6dbd0af5 2641#endif
0f2d19dd 2642 SCM_DEFER_INTS;
a23afe53
MD
2643 SCM_SETCAR (x, SCM_CAR (t.arg1));
2644 SCM_SETCDR (x, SCM_CDR (t.arg1));
0f2d19dd 2645 SCM_ALLOW_INTS;
6dbd0af5 2646 goto loopnoap;
0f2d19dd
JB
2647 case 1:
2648 if (SCM_NIMP (x = t.arg1))
6dbd0af5 2649 goto loopnoap;
0f2d19dd
JB
2650 case 0:
2651 RETURN (t.arg1);
2652 }
2653 }
2654 }
2655 else
2656 proc = SCM_CEVAL (SCM_CAR (x), env);
2657 SCM_ASRTGO (SCM_NIMP (proc), badfun);
cf7c17e9
JB
2658#ifndef SCM_RECKLESS
2659#ifdef SCM_CAUTIOUS
0f2d19dd
JB
2660 checkargs:
2661#endif
2662 if (SCM_CLOSUREP (proc))
2663 {
2664 arg2 = SCM_CAR (SCM_CODE (proc));
2665 t.arg1 = SCM_CDR (x);
2666 while (SCM_NIMP (arg2))
2667 {
2668 if (SCM_NCONSP (arg2))
2669 goto evapply;
2670 if (SCM_IMP (t.arg1))
2671 goto umwrongnumargs;
2672 arg2 = SCM_CDR (arg2);
2673 t.arg1 = SCM_CDR (t.arg1);
2674 }
2675 if (SCM_NNULLP (t.arg1))
2676 goto umwrongnumargs;
2677 }
2678 else if (scm_tc16_macro == SCM_TYP16 (proc))
2679 goto handle_a_macro;
2680#endif
2681 }
2682
2683
6dbd0af5
MD
2684evapply:
2685 PREP_APPLY (proc, SCM_EOL);
2686 if (SCM_NULLP (SCM_CDR (x))) {
2687 ENTER_APPLY;
89efbff4 2688 evap0:
0f2d19dd
JB
2689 switch (SCM_TYP7 (proc))
2690 { /* no arguments given */
2691 case scm_tc7_subr_0:
2692 RETURN (SCM_SUBRF (proc) ());
2693 case scm_tc7_subr_1o:
2694 RETURN (SCM_SUBRF (proc) (SCM_UNDEFINED));
2695 case scm_tc7_lsubr:
2696 RETURN (SCM_SUBRF (proc) (SCM_EOL));
2697 case scm_tc7_rpsubr:
2698 RETURN (SCM_BOOL_T);
2699 case scm_tc7_asubr:
2700 RETURN (SCM_SUBRF (proc) (SCM_UNDEFINED, SCM_UNDEFINED));
6dbd0af5 2701#ifdef CCLO
0f2d19dd
JB
2702 case scm_tc7_cclo:
2703 t.arg1 = proc;
2704 proc = SCM_CCLO_SUBR (proc);
6dbd0af5
MD
2705#ifdef DEVAL
2706 debug.info->a.proc = proc;
2707 debug.info->a.args = scm_cons (t.arg1, SCM_EOL);
2708#endif
0f2d19dd 2709 goto evap1;
6dbd0af5 2710#endif
89efbff4
MD
2711 case scm_tc7_pws:
2712 proc = SCM_PROCEDURE (proc);
2713#ifdef DEVAL
2714 debug.info->a.proc = proc;
2715#endif
2716 goto evap0;
0f2d19dd
JB
2717 case scm_tcs_closures:
2718 x = SCM_CODE (proc);
e2806c10 2719 env = EXTEND_ENV (SCM_CAR (x), SCM_EOL, SCM_ENV (proc));
0f2d19dd 2720 goto cdrxbegin;
da7f71d7 2721 case scm_tcs_cons_gloc:
195847fa
MD
2722 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
2723 {
2724 x = SCM_ENTITY_PROCEDURE (proc);
2725 arg2 = SCM_EOL;
2726 goto type_dispatch;
2727 }
2728 else if (!SCM_I_OPERATORP (proc))
9b07e212
MD
2729 goto badfun;
2730 else
da7f71d7 2731 {
195847fa
MD
2732 t.arg1 = proc;
2733 proc = (SCM_I_ENTITYP (proc)
2734 ? SCM_ENTITY_PROCEDURE (proc)
2735 : SCM_OPERATOR_PROCEDURE (proc));
da7f71d7 2736#ifdef DEVAL
195847fa
MD
2737 debug.info->a.proc = proc;
2738 debug.info->a.args = scm_cons (t.arg1, SCM_EOL);
da7f71d7 2739#endif
195847fa
MD
2740 if (SCM_NIMP (proc))
2741 goto evap1;
2742 else
2743 goto badfun;
da7f71d7 2744 }
0f2d19dd
JB
2745 case scm_tc7_contin:
2746 case scm_tc7_subr_1:
2747 case scm_tc7_subr_2:
2748 case scm_tc7_subr_2o:
2749 case scm_tc7_cxr:
2750 case scm_tc7_subr_3:
2751 case scm_tc7_lsubr_2:
2752 umwrongnumargs:
2753 unmemocar (x, env);
2754 wrongnumargs:
f5bf2977
GH
2755 /* scm_everr (x, env,...) */
2756 scm_wrong_num_args (proc);
0f2d19dd
JB
2757 default:
2758 /* handle macros here */
2759 goto badfun;
2760 }
6dbd0af5 2761 }
0f2d19dd
JB
2762
2763 /* must handle macros by here */
2764 x = SCM_CDR (x);
cf7c17e9 2765#ifdef SCM_CAUTIOUS
0f2d19dd
JB
2766 if (SCM_IMP (x))
2767 goto wrongnumargs;
680ed4a8
MD
2768 else if (SCM_CONSP (x))
2769 {
2770 if (SCM_IMP (SCM_CAR (x)))
6cb702da 2771 t.arg1 = SCM_EVALIM (SCM_CAR (x), env);
680ed4a8
MD
2772 else
2773 t.arg1 = EVALCELLCAR (x, env);
2774 }
2775 else if (SCM_TYP3 (x) == 1)
2776 {
2777 if ((t.arg1 = SCM_GLOC_VAL (SCM_CAR (x))) == 0)
2778 t.arg1 = SCM_CAR (x); /* struct planted in code */
2779 }
2780 else
2781 goto wrongnumargs;
2782#else
0f2d19dd 2783 t.arg1 = EVALCAR (x, env);
680ed4a8 2784#endif
6dbd0af5
MD
2785#ifdef DEVAL
2786 debug.info->a.args = scm_cons (t.arg1, SCM_EOL);
2787#endif
0f2d19dd
JB
2788 x = SCM_CDR (x);
2789 if (SCM_NULLP (x))
2790 {
6dbd0af5 2791 ENTER_APPLY;
0f2d19dd
JB
2792 evap1:
2793 switch (SCM_TYP7 (proc))
6dbd0af5 2794 { /* have one argument in t.arg1 */
0f2d19dd
JB
2795 case scm_tc7_subr_2o:
2796 RETURN (SCM_SUBRF (proc) (t.arg1, SCM_UNDEFINED));
2797 case scm_tc7_subr_1:
2798 case scm_tc7_subr_1o:
2799 RETURN (SCM_SUBRF (proc) (t.arg1));
2800 case scm_tc7_cxr:
2801#ifdef SCM_FLOATS
2802 if (SCM_SUBRF (proc))
2803 {
2804 if (SCM_INUMP (t.arg1))
2805 {
2806 RETURN (scm_makdbl (SCM_DSUBRF (proc) ((double) SCM_INUM (t.arg1)),
2807 0.0));
2808 }
2809 SCM_ASRTGO (SCM_NIMP (t.arg1), floerr);
2810 if (SCM_REALP (t.arg1))
2811 {
2812 RETURN (scm_makdbl (SCM_DSUBRF (proc) (SCM_REALPART (t.arg1)), 0.0));
2813 }
2814#ifdef SCM_BIGDIG
2815 if (SCM_BIGP (t.arg1))
2816 {
2817 RETURN (scm_makdbl (SCM_DSUBRF (proc) (scm_big2dbl (t.arg1)), 0.0));
2818 }
2819#endif
2820 floerr:
9de33deb
MD
2821 SCM_WTA_DISPATCH_1 (*SCM_SUBR_GENERIC (proc), t.arg1,
2822 SCM_ARG1, SCM_CHARS (SCM_SNAME (proc)));
0f2d19dd
JB
2823 }
2824#endif
2825 proc = (SCM) SCM_SNAME (proc);
2826 {
2827 char *chrs = SCM_CHARS (proc) + SCM_LENGTH (proc) - 1;
2828 while ('c' != *--chrs)
2829 {
2830 SCM_ASSERT (SCM_NIMP (t.arg1) && SCM_CONSP (t.arg1),
2831 t.arg1, SCM_ARG1, SCM_CHARS (proc));
2832 t.arg1 = ('a' == *chrs) ? SCM_CAR (t.arg1) : SCM_CDR (t.arg1);
2833 }
2834 RETURN (t.arg1);
2835 }
2836 case scm_tc7_rpsubr:
2837 RETURN (SCM_BOOL_T);
2838 case scm_tc7_asubr:
2839 RETURN (SCM_SUBRF (proc) (t.arg1, SCM_UNDEFINED));
2840 case scm_tc7_lsubr:
2841#ifdef DEVAL
6dbd0af5 2842 RETURN (SCM_SUBRF (proc) (debug.info->a.args))
0f2d19dd
JB
2843#else
2844 RETURN (SCM_SUBRF (proc) (scm_cons (t.arg1, SCM_EOL)));
2845#endif
6dbd0af5 2846#ifdef CCLO
0f2d19dd
JB
2847 case scm_tc7_cclo:
2848 arg2 = t.arg1;
2849 t.arg1 = proc;
2850 proc = SCM_CCLO_SUBR (proc);
6dbd0af5
MD
2851#ifdef DEVAL
2852 debug.info->a.args = scm_cons (t.arg1, debug.info->a.args);
2853 debug.info->a.proc = proc;
2854#endif
0f2d19dd 2855 goto evap2;
6dbd0af5 2856#endif
89efbff4
MD
2857 case scm_tc7_pws:
2858 proc = SCM_PROCEDURE (proc);
2859#ifdef DEVAL
2860 debug.info->a.proc = proc;
2861#endif
2862 goto evap1;
0f2d19dd 2863 case scm_tcs_closures:
195847fa 2864 /* clos1: */
0f2d19dd
JB
2865 x = SCM_CODE (proc);
2866#ifdef DEVAL
e2806c10 2867 env = EXTEND_ENV (SCM_CAR (x), debug.info->a.args, SCM_ENV (proc));
0f2d19dd 2868#else
e2806c10 2869 env = EXTEND_ENV (SCM_CAR (x), scm_cons (t.arg1, SCM_EOL), SCM_ENV (proc));
0f2d19dd
JB
2870#endif
2871 goto cdrxbegin;
65e41721
MD
2872 case scm_tc7_contin:
2873 scm_call_continuation (proc, t.arg1);
0c32d76c 2874 case scm_tcs_cons_gloc:
f3d2630a
MD
2875 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
2876 {
195847fa 2877 x = SCM_ENTITY_PROCEDURE (proc);
f3d2630a
MD
2878#ifdef DEVAL
2879 arg2 = debug.info->a.args;
2880#else
2881 arg2 = scm_cons (t.arg1, SCM_EOL);
2882#endif
f3d2630a
MD
2883 goto type_dispatch;
2884 }
2885 else if (!SCM_I_OPERATORP (proc))
9b07e212
MD
2886 goto badfun;
2887 else
0c32d76c 2888 {
195847fa
MD
2889 arg2 = t.arg1;
2890 t.arg1 = proc;
2891 proc = (SCM_I_ENTITYP (proc)
2892 ? SCM_ENTITY_PROCEDURE (proc)
2893 : SCM_OPERATOR_PROCEDURE (proc));
0c32d76c 2894#ifdef DEVAL
195847fa
MD
2895 debug.info->a.args = scm_cons (t.arg1, debug.info->a.args);
2896 debug.info->a.proc = proc;
0c32d76c 2897#endif
195847fa
MD
2898 if (SCM_NIMP (proc))
2899 goto evap2;
2900 else
2901 goto badfun;
0c32d76c 2902 }
0f2d19dd
JB
2903 case scm_tc7_subr_2:
2904 case scm_tc7_subr_0:
2905 case scm_tc7_subr_3:
2906 case scm_tc7_lsubr_2:
2907 goto wrongnumargs;
2908 default:
2909 goto badfun;
2910 }
2911 }
cf7c17e9 2912#ifdef SCM_CAUTIOUS
0f2d19dd
JB
2913 if (SCM_IMP (x))
2914 goto wrongnumargs;
680ed4a8
MD
2915 else if (SCM_CONSP (x))
2916 {
2917 if (SCM_IMP (SCM_CAR (x)))
6cb702da 2918 arg2 = SCM_EVALIM (SCM_CAR (x), env);
680ed4a8
MD
2919 else
2920 arg2 = EVALCELLCAR (x, env);
2921 }
2922 else if (SCM_TYP3 (x) == 1)
2923 {
2924 if ((arg2 = SCM_GLOC_VAL (SCM_CAR (x))) == 0)
2925 arg2 = SCM_CAR (x); /* struct planted in code */
2926 }
2927 else
2928 goto wrongnumargs;
2929#else
2930 arg2 = EVALCAR (x, env);
0f2d19dd
JB
2931#endif
2932 { /* have two or more arguments */
6dbd0af5
MD
2933#ifdef DEVAL
2934 debug.info->a.args = scm_cons2 (t.arg1, arg2, SCM_EOL);
2935#endif
0f2d19dd
JB
2936 x = SCM_CDR (x);
2937 if (SCM_NULLP (x)) {
6dbd0af5 2938 ENTER_APPLY;
0f2d19dd
JB
2939#ifdef CCLO
2940 evap2:
2941#endif
6dbd0af5
MD
2942 switch (SCM_TYP7 (proc))
2943 { /* have two arguments */
2944 case scm_tc7_subr_2:
2945 case scm_tc7_subr_2o:
2946 RETURN (SCM_SUBRF (proc) (t.arg1, arg2));
2947 case scm_tc7_lsubr:
0f2d19dd 2948#ifdef DEVAL
6dbd0af5
MD
2949 RETURN (SCM_SUBRF (proc) (debug.info->a.args))
2950#else
2951 RETURN (SCM_SUBRF (proc) (scm_cons2 (t.arg1, arg2, SCM_EOL)));
0f2d19dd 2952#endif
6dbd0af5
MD
2953 case scm_tc7_lsubr_2:
2954 RETURN (SCM_SUBRF (proc) (t.arg1, arg2, SCM_EOL));
2955 case scm_tc7_rpsubr:
2956 case scm_tc7_asubr:
2957 RETURN (SCM_SUBRF (proc) (t.arg1, arg2));
2958#ifdef CCLO
2959 cclon:
2960 case scm_tc7_cclo:
0f2d19dd 2961#ifdef DEVAL
195847fa
MD
2962 RETURN (SCM_APPLY (SCM_CCLO_SUBR (proc),
2963 scm_cons (proc, debug.info->a.args),
2964 SCM_EOL));
0f2d19dd 2965#else
195847fa
MD
2966 RETURN (SCM_APPLY (SCM_CCLO_SUBR (proc),
2967 scm_cons2 (proc, t.arg1,
2968 scm_cons (arg2,
2969 scm_eval_args (x,
2970 env,
2971 proc))),
2972 SCM_EOL));
0f2d19dd 2973#endif
6dbd0af5
MD
2974 /* case scm_tc7_cclo:
2975 x = scm_cons(arg2, scm_eval_args(x, env));
2976 arg2 = t.arg1;
2977 t.arg1 = proc;
2978 proc = SCM_CCLO_SUBR(proc);
2979 goto evap3; */
2980#endif
89efbff4
MD
2981 case scm_tc7_pws:
2982 proc = SCM_PROCEDURE (proc);
2983#ifdef DEVAL
2984 debug.info->a.proc = proc;
2985#endif
2986 goto evap2;
0c32d76c 2987 case scm_tcs_cons_gloc:
f3d2630a
MD
2988 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
2989 {
195847fa 2990 x = SCM_ENTITY_PROCEDURE (proc);
f3d2630a
MD
2991#ifdef DEVAL
2992 arg2 = debug.info->a.args;
2993#else
2994 arg2 = scm_cons2 (t.arg1, arg2, SCM_EOL);
2995#endif
f3d2630a
MD
2996 goto type_dispatch;
2997 }
2998 else if (!SCM_I_OPERATORP (proc))
9b07e212
MD
2999 goto badfun;
3000 else
0c32d76c 3001 {
195847fa 3002 operatorn:
0c32d76c 3003#ifdef DEVAL
195847fa
MD
3004 RETURN (SCM_APPLY (SCM_I_ENTITYP (proc)
3005 ? SCM_ENTITY_PROCEDURE (proc)
3006 : SCM_OPERATOR_PROCEDURE (proc),
3007 scm_cons (proc, debug.info->a.args),
3008 SCM_EOL));
3009#else
3010 RETURN (SCM_APPLY (SCM_I_ENTITYP (proc)
3011 ? SCM_ENTITY_PROCEDURE (proc)
3012 : SCM_OPERATOR_PROCEDURE (proc),
3013 scm_cons2 (proc, t.arg1,
3014 scm_cons (arg2,
3015 scm_eval_args (x,
3016 env,
3017 proc))),
3018 SCM_EOL));
3019#endif
0c32d76c 3020 }
6dbd0af5
MD
3021 case scm_tc7_subr_0:
3022 case scm_tc7_cxr:
3023 case scm_tc7_subr_1o:
3024 case scm_tc7_subr_1:
3025 case scm_tc7_subr_3:
3026 case scm_tc7_contin:
3027 goto wrongnumargs;
3028 default:
3029 goto badfun;
3030 case scm_tcs_closures:
195847fa 3031 /* clos2: */
0f2d19dd 3032#ifdef DEVAL
da7f71d7
MD
3033 env = EXTEND_ENV (SCM_CAR (SCM_CODE (proc)),
3034 debug.info->a.args,
3035 SCM_ENV (proc));
0f2d19dd 3036#else
da7f71d7
MD
3037 env = EXTEND_ENV (SCM_CAR (SCM_CODE (proc)),
3038 scm_cons2 (t.arg1, arg2, SCM_EOL), SCM_ENV (proc));
0f2d19dd 3039#endif
6dbd0af5
MD
3040 x = SCM_CODE (proc);
3041 goto cdrxbegin;
3042 }
0f2d19dd 3043 }
cf7c17e9 3044#ifdef SCM_CAUTIOUS
680ed4a8
MD
3045 if (SCM_IMP (x) || SCM_NECONSP (x))
3046 goto wrongnumargs;
3047#endif
0f2d19dd 3048#ifdef DEVAL
6dbd0af5 3049 debug.info->a.args = scm_cons2 (t.arg1, arg2,
680ed4a8
MD
3050 scm_deval_args (x, env, proc,
3051 SCM_CDRLOC (SCM_CDR (debug.info->a.args))));
0f2d19dd 3052#endif
6dbd0af5 3053 ENTER_APPLY;
89efbff4 3054 evap3:
6dbd0af5
MD
3055 switch (SCM_TYP7 (proc))
3056 { /* have 3 or more arguments */
0f2d19dd 3057#ifdef DEVAL
6dbd0af5
MD
3058 case scm_tc7_subr_3:
3059 SCM_ASRTGO (SCM_NULLP (SCM_CDR (x)), wrongnumargs);
da7f71d7
MD
3060 RETURN (SCM_SUBRF (proc) (t.arg1, arg2,
3061 SCM_CADDR (debug.info->a.args)));
6dbd0af5 3062 case scm_tc7_asubr:
399dedcc
MD
3063#ifdef BUILTIN_RPASUBR
3064 t.arg1 = SCM_SUBRF(proc)(t.arg1, arg2);
3065 arg2 = SCM_CDR (SCM_CDR (debug.info->a.args));
da7f71d7
MD
3066 do
3067 {
3068 t.arg1 = SCM_SUBRF(proc)(t.arg1, SCM_CAR (arg2));
3069 arg2 = SCM_CDR (arg2);
3070 }
3071 while (SCM_NIMP (arg2));
399dedcc
MD
3072 RETURN (t.arg1)
3073#endif /* BUILTIN_RPASUBR */
6dbd0af5 3074 case scm_tc7_rpsubr:
71d3aa6d
MD
3075#ifdef BUILTIN_RPASUBR
3076 if (SCM_FALSEP (SCM_SUBRF (proc) (t.arg1, arg2)))
3077 RETURN (SCM_BOOL_F)
3078 t.arg1 = SCM_CDR (SCM_CDR (debug.info->a.args));
da7f71d7
MD
3079 do
3080 {
3081 if (SCM_FALSEP (SCM_SUBRF (proc) (arg2, SCM_CAR (t.arg1))))
3082 RETURN (SCM_BOOL_F)
3083 arg2 = SCM_CAR (t.arg1);
3084 t.arg1 = SCM_CDR (t.arg1);
3085 }
3086 while (SCM_NIMP (t.arg1));
71d3aa6d
MD
3087 RETURN (SCM_BOOL_T)
3088#else /* BUILTIN_RPASUBR */
da7f71d7
MD
3089 RETURN (SCM_APPLY (proc, t.arg1,
3090 scm_acons (arg2,
3091 SCM_CDR (SCM_CDR (debug.info->a.args)),
3092 SCM_EOL)))
71d3aa6d 3093#endif /* BUILTIN_RPASUBR */
399dedcc 3094 case scm_tc7_lsubr_2:
da7f71d7
MD
3095 RETURN (SCM_SUBRF (proc) (t.arg1, arg2,
3096 SCM_CDR (SCM_CDR (debug.info->a.args))))
399dedcc
MD
3097 case scm_tc7_lsubr:
3098 RETURN (SCM_SUBRF (proc) (debug.info->a.args))
0f2d19dd 3099#ifdef CCLO
6dbd0af5
MD
3100 case scm_tc7_cclo:
3101 goto cclon;
0f2d19dd 3102#endif
89efbff4
MD
3103 case scm_tc7_pws:
3104 proc = SCM_PROCEDURE (proc);
3105 debug.info->a.proc = proc;
3106 goto evap3;
6dbd0af5 3107 case scm_tcs_closures:
b7ff98dd 3108 SCM_SET_ARGSREADY (debug);
e2806c10 3109 env = EXTEND_ENV (SCM_CAR (SCM_CODE (proc)),
6dbd0af5
MD
3110 debug.info->a.args,
3111 SCM_ENV (proc));
3112 x = SCM_CODE (proc);
3113 goto cdrxbegin;
3114#else /* DEVAL */
3115 case scm_tc7_subr_3:
3116 SCM_ASRTGO (SCM_NULLP (SCM_CDR (x)), wrongnumargs);
3117 RETURN (SCM_SUBRF (proc) (t.arg1, arg2, EVALCAR (x, env)));
3118 case scm_tc7_asubr:
399dedcc 3119#ifdef BUILTIN_RPASUBR
da7f71d7
MD
3120 t.arg1 = SCM_SUBRF (proc) (t.arg1, arg2);
3121 do
3122 {
3123 t.arg1 = SCM_SUBRF(proc)(t.arg1, EVALCAR(x, env));
3124 x = SCM_CDR(x);
3125 }
3126 while (SCM_NIMP (x));
399dedcc
MD
3127 RETURN (t.arg1)
3128#endif /* BUILTIN_RPASUBR */
6dbd0af5 3129 case scm_tc7_rpsubr:
71d3aa6d
MD
3130#ifdef BUILTIN_RPASUBR
3131 if (SCM_FALSEP (SCM_SUBRF (proc) (t.arg1, arg2)))
3132 RETURN (SCM_BOOL_F)
da7f71d7
MD
3133 do
3134 {
3135 t.arg1 = EVALCAR (x, env);
3136 if (SCM_FALSEP (SCM_SUBRF (proc) (arg2, t.arg1)))
3137 RETURN (SCM_BOOL_F)
3138 arg2 = t.arg1;
3139 x = SCM_CDR (x);
3140 }
3141 while (SCM_NIMP (x));
71d3aa6d
MD
3142 RETURN (SCM_BOOL_T)
3143#else /* BUILTIN_RPASUBR */
da7f71d7 3144 RETURN (SCM_APPLY (proc, t.arg1,
680ed4a8
MD
3145 scm_acons (arg2,
3146 scm_eval_args (x, env, proc),
3147 SCM_EOL)));
71d3aa6d 3148#endif /* BUILTIN_RPASUBR */
6dbd0af5 3149 case scm_tc7_lsubr_2:
680ed4a8 3150 RETURN (SCM_SUBRF (proc) (t.arg1, arg2, scm_eval_args (x, env, proc)));
6dbd0af5 3151 case scm_tc7_lsubr:
680ed4a8
MD
3152 RETURN (SCM_SUBRF (proc) (scm_cons2 (t.arg1,
3153 arg2,
3154 scm_eval_args (x, env, proc))));
0f2d19dd 3155#ifdef CCLO
6dbd0af5
MD
3156 case scm_tc7_cclo:
3157 goto cclon;
0f2d19dd 3158#endif
89efbff4
MD
3159 case scm_tc7_pws:
3160 proc = SCM_PROCEDURE (proc);
3161 goto evap3;
6dbd0af5
MD
3162 case scm_tcs_closures:
3163#ifdef DEVAL
b7ff98dd 3164 SCM_SET_ARGSREADY (debug);
6dbd0af5 3165#endif
e2806c10 3166 env = EXTEND_ENV (SCM_CAR (SCM_CODE (proc)),
680ed4a8
MD
3167 scm_cons2 (t.arg1,
3168 arg2,
3169 scm_eval_args (x, env, proc)),
6dbd0af5
MD
3170 SCM_ENV (proc));
3171 x = SCM_CODE (proc);
3172 goto cdrxbegin;
0f2d19dd 3173#endif /* DEVAL */
0c32d76c 3174 case scm_tcs_cons_gloc:
f3d2630a
MD
3175 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
3176 {
3177#ifdef DEVAL
3178 arg2 = debug.info->a.args;
3179#else
3180 arg2 = scm_cons2 (t.arg1, arg2, scm_eval_args (x, env, proc));
3181#endif
195847fa 3182 x = SCM_ENTITY_PROCEDURE (proc);
f3d2630a
MD
3183 goto type_dispatch;
3184 }
3185 else if (!SCM_I_OPERATORP (proc))
9b07e212
MD
3186 goto badfun;
3187 else
195847fa 3188 goto operatorn;
6dbd0af5
MD
3189 case scm_tc7_subr_2:
3190 case scm_tc7_subr_1o:
3191 case scm_tc7_subr_2o:
3192 case scm_tc7_subr_0:
3193 case scm_tc7_cxr:
3194 case scm_tc7_subr_1:
3195 case scm_tc7_contin:
3196 goto wrongnumargs;
3197 default:
3198 goto badfun;
3199 }
0f2d19dd
JB
3200 }
3201#ifdef DEVAL
6dbd0af5 3202exit:
b6d75948 3203 if (CHECK_EXIT && SCM_TRAPS_P)
b7ff98dd 3204 if (SCM_EXIT_FRAME_P || (SCM_TRACE_P && SCM_TRACED_FRAME_P (debug)))
6dbd0af5 3205 {
b7ff98dd
MD
3206 SCM_CLEAR_TRACED_FRAME (debug);
3207 if (SCM_CHEAPTRAPS_P)
c0ab1b8d 3208 t.arg1 = scm_make_debugobj (&debug);
6dbd0af5
MD
3209 else
3210 {
3211 scm_make_cont (&t.arg1);
ca6ef71a 3212 if (setjmp (SCM_JMPBUF (t.arg1)))
6dbd0af5
MD
3213 {
3214 proc = SCM_THROW_VALUE (t.arg1);
3215 goto ret;
3216 }
3217 }
2f0d1375 3218 scm_ithrow (scm_sym_exit_frame, scm_cons2 (t.arg1, proc, SCM_EOL), 0);
6dbd0af5
MD
3219 }
3220ret:
1646d37b 3221 scm_last_debug_frame = debug.prev;
0f2d19dd
JB
3222 return proc;
3223#endif
3224}
3225
6dbd0af5
MD
3226
3227/* SECTION: This code is compiled once.
3228 */
3229
0f2d19dd
JB
3230#ifndef DEVAL
3231
82a2622a 3232/* This code processes the arguments to apply:
b145c172
JB
3233
3234 (apply PROC ARG1 ... ARGS)
3235
82a2622a
JB
3236 Given a list (ARG1 ... ARGS), this function conses the ARG1
3237 ... arguments onto the front of ARGS, and returns the resulting
3238 list. Note that ARGS is a list; thus, the argument to this
3239 function is a list whose last element is a list.
3240
3241 Apply calls this function, and applies PROC to the elements of the
b145c172
JB
3242 result. apply:nconc2last takes care of building the list of
3243 arguments, given (ARG1 ... ARGS).
3244
82a2622a
JB
3245 Rather than do new consing, apply:nconc2last destroys its argument.
3246 On that topic, this code came into my care with the following
3247 beautifully cryptic comment on that topic: "This will only screw
3248 you if you do (scm_apply scm_apply '( ... ))" If you know what
3249 they're referring to, send me a patch to this comment. */
b145c172 3250
0f2d19dd 3251SCM_PROC(s_nconc2last, "apply:nconc2last", 1, 0, 0, scm_nconc2last);
1cc91f1b 3252
0f2d19dd
JB
3253SCM
3254scm_nconc2last (lst)
3255 SCM lst;
0f2d19dd
JB
3256{
3257 SCM *lloc;
b145c172 3258 SCM_ASSERT (scm_ilength (lst) > 0, lst, SCM_ARG1, s_nconc2last);
0f2d19dd
JB
3259 lloc = &lst;
3260 while (SCM_NNULLP (SCM_CDR (*lloc)))
a23afe53 3261 lloc = SCM_CDRLOC (*lloc);
b145c172 3262 SCM_ASSERT (scm_ilength (SCM_CAR (*lloc)) >= 0, lst, SCM_ARG1, s_nconc2last);
0f2d19dd
JB
3263 *lloc = SCM_CAR (*lloc);
3264 return lst;
3265}
3266
3267#endif /* !DEVAL */
3268
6dbd0af5
MD
3269
3270/* SECTION: When DEVAL is defined this code yields scm_dapply.
3271 * It is compiled twice.
3272 */
3273
0f2d19dd 3274#if 0
1cc91f1b 3275
0f2d19dd
JB
3276SCM
3277scm_apply (proc, arg1, args)
3278 SCM proc;
3279 SCM arg1;
3280 SCM args;
0f2d19dd
JB
3281{}
3282#endif
3283
3284#if 0
1cc91f1b 3285
0f2d19dd
JB
3286SCM
3287scm_dapply (proc, arg1, args)
3288 SCM proc;
3289 SCM arg1;
3290 SCM args;
0f2d19dd
JB
3291{}
3292#endif
3293
1cc91f1b 3294
82a2622a
JB
3295/* Apply a function to a list of arguments.
3296
3297 This function is exported to the Scheme level as taking two
3298 required arguments and a tail argument, as if it were:
3299 (lambda (proc arg1 . args) ...)
3300 Thus, if you just have a list of arguments to pass to a procedure,
3301 pass the list as ARG1, and '() for ARGS. If you have some fixed
3302 args, pass the first as ARG1, then cons any remaining fixed args
3303 onto the front of your argument list, and pass that as ARGS. */
3304
0f2d19dd
JB
3305SCM
3306SCM_APPLY (proc, arg1, args)
3307 SCM proc;
3308 SCM arg1;
3309 SCM args;
0f2d19dd
JB
3310{
3311#ifdef DEBUG_EXTENSIONS
3312#ifdef DEVAL
6dbd0af5 3313 scm_debug_frame debug;
c0ab1b8d 3314 scm_debug_info debug_vect_body;
1646d37b 3315 debug.prev = scm_last_debug_frame;
b7ff98dd 3316 debug.status = SCM_APPLYFRAME;
c0ab1b8d 3317 debug.vect = &debug_vect_body;
6dbd0af5
MD
3318 debug.vect[0].a.proc = proc;
3319 debug.vect[0].a.args = SCM_EOL;
1646d37b 3320 scm_last_debug_frame = &debug;
0f2d19dd 3321#else
b7ff98dd 3322 if (SCM_DEBUGGINGP)
0f2d19dd
JB
3323 return scm_dapply (proc, arg1, args);
3324#endif
3325#endif
3326
3327 SCM_ASRTGO (SCM_NIMP (proc), badproc);
82a2622a
JB
3328
3329 /* If ARGS is the empty list, then we're calling apply with only two
3330 arguments --- ARG1 is the list of arguments for PROC. Whatever
3331 the case, futz with things so that ARG1 is the first argument to
3332 give to PROC (or SCM_UNDEFINED if no args), and ARGS contains the
30000774
JB
3333 rest.
3334
3335 Setting the debug apply frame args this way is pretty messy.
3336 Perhaps we should store arg1 and args directly in the frame as
3337 received, and let scm_frame_arguments unpack them, because that's
3338 a relatively rare operation. This works for now; if the Guile
3339 developer archives are still around, see Mikael's post of
3340 11-Apr-97. */
0f2d19dd
JB
3341 if (SCM_NULLP (args))
3342 {
3343 if (SCM_NULLP (arg1))
30000774
JB
3344 {
3345 arg1 = SCM_UNDEFINED;
3346#ifdef DEVAL
3347 debug.vect[0].a.args = SCM_EOL;
3348#endif
3349 }
0f2d19dd
JB
3350 else
3351 {
30000774
JB
3352#ifdef DEVAL
3353 debug.vect[0].a.args = arg1;
3354#endif
0f2d19dd
JB
3355 args = SCM_CDR (arg1);
3356 arg1 = SCM_CAR (arg1);
3357 }
3358 }
3359 else
3360 {
82a2622a 3361 /* SCM_ASRTGO(SCM_NIMP(args) && SCM_CONSP(args), wrongnumargs); */
0f2d19dd 3362 args = scm_nconc2last (args);
30000774
JB
3363#ifdef DEVAL
3364 debug.vect[0].a.args = scm_cons (arg1, args);
3365#endif
0f2d19dd 3366 }
0f2d19dd 3367#ifdef DEVAL
b6d75948 3368 if (SCM_ENTER_FRAME_P && SCM_TRAPS_P)
6dbd0af5
MD
3369 {
3370 SCM tmp;
b7ff98dd 3371 if (SCM_CHEAPTRAPS_P)
c0ab1b8d 3372 tmp = scm_make_debugobj (&debug);
6dbd0af5
MD
3373 else
3374 {
3375 scm_make_cont (&tmp);
ca6ef71a 3376 if (setjmp (SCM_JMPBUF (tmp)))
6dbd0af5
MD
3377 goto entap;
3378 }
2f0d1375 3379 scm_ithrow (scm_sym_enter_frame, scm_cons (tmp, SCM_EOL), 0);
6dbd0af5
MD
3380 }
3381entap:
3382 ENTER_APPLY;
3383#endif
3384#ifdef CCLO
3385tail:
0f2d19dd
JB
3386#endif
3387 switch (SCM_TYP7 (proc))
3388 {
3389 case scm_tc7_subr_2o:
3390 args = SCM_NULLP (args) ? SCM_UNDEFINED : SCM_CAR (args);
3391 RETURN (SCM_SUBRF (proc) (arg1, args))
3392 case scm_tc7_subr_2:
269861c7
MD
3393 SCM_ASRTGO (SCM_NNULLP (args) && SCM_NULLP (SCM_CDR (args)),
3394 wrongnumargs);
0f2d19dd
JB
3395 args = SCM_CAR (args);
3396 RETURN (SCM_SUBRF (proc) (arg1, args))
3397 case scm_tc7_subr_0:
3398 SCM_ASRTGO (SCM_UNBNDP (arg1), wrongnumargs);
3399 RETURN (SCM_SUBRF (proc) ())
3400 case scm_tc7_subr_1:
3401 case scm_tc7_subr_1o:
3402 SCM_ASRTGO (SCM_NULLP (args), wrongnumargs);
3403 RETURN (SCM_SUBRF (proc) (arg1))
3404 case scm_tc7_cxr:
3405 SCM_ASRTGO (SCM_NULLP (args), wrongnumargs);
3406#ifdef SCM_FLOATS
3407 if (SCM_SUBRF (proc))
3408 {
6dbd0af5
MD
3409 if (SCM_INUMP (arg1))
3410 {
3411 RETURN (scm_makdbl (SCM_DSUBRF (proc) ((double) SCM_INUM (arg1)), 0.0));
3412 }
0f2d19dd 3413 SCM_ASRTGO (SCM_NIMP (arg1), floerr);
6dbd0af5
MD
3414 if (SCM_REALP (arg1))
3415 {
3416 RETURN (scm_makdbl (SCM_DSUBRF (proc) (SCM_REALPART (arg1)), 0.0));
3417 }
0f2d19dd 3418#ifdef SCM_BIGDIG
26d5b9b4 3419 if (SCM_BIGP (arg1))
0f2d19dd
JB
3420 RETURN (scm_makdbl (SCM_DSUBRF (proc) (scm_big2dbl (arg1)), 0.0))
3421#endif
3422 floerr:
9de33deb
MD
3423 SCM_WTA_DISPATCH_1 (*SCM_SUBR_GENERIC (proc), arg1,
3424 SCM_ARG1, SCM_CHARS (SCM_SNAME (proc)));
0f2d19dd
JB
3425 }
3426#endif
3427 proc = (SCM) SCM_SNAME (proc);
3428 {
3429 char *chrs = SCM_CHARS (proc) + SCM_LENGTH (proc) - 1;
3430 while ('c' != *--chrs)
3431 {
3432 SCM_ASSERT (SCM_NIMP (arg1) && SCM_CONSP (arg1),
3433 arg1, SCM_ARG1, SCM_CHARS (proc));
3434 arg1 = ('a' == *chrs) ? SCM_CAR (arg1) : SCM_CDR (arg1);
3435 }
3436 RETURN (arg1)
3437 }
3438 case scm_tc7_subr_3:
3439 RETURN (SCM_SUBRF (proc) (arg1, SCM_CAR (args), SCM_CAR (SCM_CDR (args))))
3440 case scm_tc7_lsubr:
3441#ifdef DEVAL
6dbd0af5 3442 RETURN (SCM_SUBRF (proc) (SCM_UNBNDP (arg1) ? SCM_EOL : debug.vect[0].a.args))
0f2d19dd
JB
3443#else
3444 RETURN (SCM_SUBRF (proc) (SCM_UNBNDP (arg1) ? SCM_EOL : scm_cons (arg1, args)))
3445#endif
3446 case scm_tc7_lsubr_2:
3447 SCM_ASRTGO (SCM_NIMP (args) && SCM_CONSP (args), wrongnumargs);
3448 RETURN (SCM_SUBRF (proc) (arg1, SCM_CAR (args), SCM_CDR (args)))
3449 case scm_tc7_asubr:
3450 if (SCM_NULLP (args))
3451 RETURN (SCM_SUBRF (proc) (arg1, SCM_UNDEFINED))
3452 while (SCM_NIMP (args))
3453 {
3454 SCM_ASSERT (SCM_CONSP (args), args, SCM_ARG2, "apply");
3455 arg1 = SCM_SUBRF (proc) (arg1, SCM_CAR (args));
3456 args = SCM_CDR (args);
3457 }
3458 RETURN (arg1);
3459 case scm_tc7_rpsubr:
3460 if (SCM_NULLP (args))
3461 RETURN (SCM_BOOL_T);
3462 while (SCM_NIMP (args))
3463 {
3464 SCM_ASSERT (SCM_CONSP (args), args, SCM_ARG2, "apply");
3465 if (SCM_FALSEP (SCM_SUBRF (proc) (arg1, SCM_CAR (args))))
3466 RETURN (SCM_BOOL_F);
3467 arg1 = SCM_CAR (args);
3468 args = SCM_CDR (args);
3469 }
3470 RETURN (SCM_BOOL_T);
3471 case scm_tcs_closures:
3472#ifdef DEVAL
6dbd0af5 3473 arg1 = (SCM_UNBNDP (arg1) ? SCM_EOL : debug.vect[0].a.args);
0f2d19dd
JB
3474#else
3475 arg1 = (SCM_UNBNDP (arg1) ? SCM_EOL : scm_cons (arg1, args));
3476#endif
cf7c17e9 3477#ifndef SCM_RECKLESS
0f2d19dd
JB
3478 if (scm_badargsp (SCM_CAR (SCM_CODE (proc)), arg1))
3479 goto wrongnumargs;
3480#endif
1609038c
MD
3481
3482 /* Copy argument list */
3483 if (SCM_IMP (arg1))
3484 args = arg1;
3485 else
3486 {
3487 SCM tl = args = scm_cons (SCM_CAR (arg1), SCM_UNSPECIFIED);
3488 while (SCM_NIMP (arg1 = SCM_CDR (arg1))
3489 && SCM_CONSP (arg1))
3490 {
3491 SCM_SETCDR (tl, scm_cons (SCM_CAR (arg1),
3492 SCM_UNSPECIFIED));
3493 tl = SCM_CDR (tl);
3494 }
3495 SCM_SETCDR (tl, arg1);
3496 }
3497
3498 args = EXTEND_ENV (SCM_CAR (SCM_CODE (proc)), args, SCM_ENV (proc));
2ddb0920 3499 proc = SCM_CDR (SCM_CODE (proc));
e791c18f
MD
3500 again:
3501 arg1 = proc;
3502 while (SCM_NNULLP (arg1 = SCM_CDR (arg1)))
2ddb0920
MD
3503 {
3504 if (SCM_IMP (SCM_CAR (proc)))
3505 {
3506 if (SCM_ISYMP (SCM_CAR (proc)))
3507 {
3508 proc = scm_m_expand_body (proc, args);
e791c18f 3509 goto again;
2ddb0920 3510 }
2ddb0920
MD
3511 }
3512 else
e791c18f
MD
3513 SCM_CEVAL (SCM_CAR (proc), args);
3514 proc = arg1;
2ddb0920 3515 }
e791c18f 3516 RETURN (EVALCAR (proc, args));
0f2d19dd
JB
3517 case scm_tc7_contin:
3518 SCM_ASRTGO (SCM_NULLP (args), wrongnumargs);
3519 scm_call_continuation (proc, arg1);
3520#ifdef CCLO
3521 case scm_tc7_cclo:
3522#ifdef DEVAL
6dbd0af5
MD
3523 args = (SCM_UNBNDP(arg1) ? SCM_EOL : debug.vect[0].a.args);
3524 arg1 = proc;
3525 proc = SCM_CCLO_SUBR (proc);
3526 debug.vect[0].a.proc = proc;
3527 debug.vect[0].a.args = scm_cons (arg1, args);
0f2d19dd
JB
3528#else
3529 args = (SCM_UNBNDP(arg1) ? SCM_EOL : scm_cons (arg1, args));
0f2d19dd
JB
3530 arg1 = proc;
3531 proc = SCM_CCLO_SUBR (proc);
6dbd0af5 3532#endif
0f2d19dd
JB
3533 goto tail;
3534#endif
89efbff4
MD
3535 case scm_tc7_pws:
3536 proc = SCM_PROCEDURE (proc);
3537#ifdef DEVAL
3538 debug.vect[0].a.proc = proc;
3539#endif
3540 goto tail;
0c32d76c 3541 case scm_tcs_cons_gloc:
f3d2630a
MD
3542 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
3543 {
3544#ifdef DEVAL
3545 args = (SCM_UNBNDP(arg1) ? SCM_EOL : debug.vect[0].a.args);
3546#else
3547 args = (SCM_UNBNDP(arg1) ? SCM_EOL : scm_cons (arg1, args));
3548#endif
195847fa 3549 RETURN (scm_apply_generic (proc, args));
f3d2630a
MD
3550 }
3551 else if (!SCM_I_OPERATORP (proc))
9b07e212
MD
3552 goto badproc;
3553 else
da7f71d7
MD
3554 {
3555#ifdef DEVAL
3556 args = (SCM_UNBNDP(arg1) ? SCM_EOL : debug.vect[0].a.args);
3557#else
3558 args = (SCM_UNBNDP(arg1) ? SCM_EOL : scm_cons (arg1, args));
3559#endif
3560 arg1 = proc;
195847fa
MD
3561 proc = (SCM_I_ENTITYP (proc)
3562 ? SCM_ENTITY_PROCEDURE (proc)
3563 : SCM_OPERATOR_PROCEDURE (proc));
da7f71d7
MD
3564#ifdef DEVAL
3565 debug.vect[0].a.proc = proc;
3566 debug.vect[0].a.args = scm_cons (arg1, args);
3567#endif
195847fa
MD
3568 if (SCM_NIMP (proc))
3569 goto tail;
3570 else
3571 goto badproc;
da7f71d7 3572 }
0f2d19dd 3573 wrongnumargs:
f5bf2977 3574 scm_wrong_num_args (proc);
0f2d19dd
JB
3575 default:
3576 badproc:
3577 scm_wta (proc, (char *) SCM_ARG1, "apply");
3578 RETURN (arg1);
3579 }
3580#ifdef DEVAL
6dbd0af5 3581exit:
b6d75948 3582 if (CHECK_EXIT && SCM_TRAPS_P)
b7ff98dd 3583 if (SCM_EXIT_FRAME_P || (SCM_TRACE_P && SCM_TRACED_FRAME_P (debug)))
6dbd0af5 3584 {
b7ff98dd
MD
3585 SCM_CLEAR_TRACED_FRAME (debug);
3586 if (SCM_CHEAPTRAPS_P)
c0ab1b8d 3587 arg1 = scm_make_debugobj (&debug);
6dbd0af5
MD
3588 else
3589 {
3590 scm_make_cont (&arg1);
ca6ef71a 3591 if (setjmp (SCM_JMPBUF (arg1)))
6dbd0af5
MD
3592 {
3593 proc = SCM_THROW_VALUE (arg1);
3594 goto ret;
3595 }
3596 }
2f0d1375 3597 scm_ithrow (scm_sym_exit_frame, scm_cons2 (arg1, proc, SCM_EOL), 0);
6dbd0af5
MD
3598 }
3599ret:
1646d37b 3600 scm_last_debug_frame = debug.prev;
0f2d19dd
JB
3601 return proc;
3602#endif
3603}
3604
6dbd0af5
MD
3605
3606/* SECTION: The rest of this file is only read once.
3607 */
3608
0f2d19dd
JB
3609#ifndef DEVAL
3610
d9c393f5
JB
3611/* Typechecking for multi-argument MAP and FOR-EACH.
3612
3613 Verify that each element of the vector ARGS, except for the first,
3614 is a proper list whose length is LEN. Attribute errors to WHO,
3615 and claim that the i'th element of ARGS is WHO's i+2'th argument. */
3616static inline void
3617check_map_args (long len, SCM args, const char *who)
3618{
3619 SCM *ve = SCM_VELTS (args);
3620 int i;
3621
3622 for (i = SCM_LENGTH (args) - 1; i >= 1; i--)
3623 {
3624 int elt_len = scm_ilength (ve[i]);
3625
3626 if (elt_len < 0)
3627 scm_wrong_type_arg (who, i + 2, ve[i]);
3628
3629 if (elt_len != len)
3630 scm_out_of_range (who, ve[i]);
3631 }
3632
3633 scm_remember (&args);
3634}
3635
3636
6cb702da 3637SCM_PROC (s_map, "map", 2, 0, 1, scm_map);
1cc91f1b 3638
368bf056
MD
3639/* Note: Currently, scm_map applies PROC to the argument list(s)
3640 sequentially, starting with the first element(s). This is used in
3641 evalext.c where the Scheme procedure `serial-map', which guarantees
3642 sequential behaviour, is implemented using scm_map. If the
3643 behaviour changes, we need to update `serial-map'.
3644*/
3645
0f2d19dd
JB
3646SCM
3647scm_map (proc, arg1, args)
3648 SCM proc;
3649 SCM arg1;
3650 SCM args;
0f2d19dd 3651{
d9c393f5 3652 long i, len;
0f2d19dd
JB
3653 SCM res = SCM_EOL;
3654 SCM *pres = &res;
3655 SCM *ve = &args; /* Keep args from being optimized away. */
3656
3657 if (SCM_NULLP (arg1))
3658 return res;
d9c393f5
JB
3659 len = scm_ilength (arg1);
3660 SCM_ASSERT (len >= 0, arg1, SCM_ARG2, s_map);
0f2d19dd
JB
3661 if (SCM_NULLP (args))
3662 {
3663 while (SCM_NIMP (arg1))
3664 {
3665 SCM_ASSERT (SCM_CONSP (arg1), arg1, SCM_ARG2, s_map);
3666 *pres = scm_cons (scm_apply (proc, SCM_CAR (arg1), scm_listofnull), SCM_EOL);
a23afe53 3667 pres = SCM_CDRLOC (*pres);
0f2d19dd
JB
3668 arg1 = SCM_CDR (arg1);
3669 }
3670 return res;
3671 }
3672 args = scm_vector (scm_cons (arg1, args));
3673 ve = SCM_VELTS (args);
cf7c17e9 3674#ifndef SCM_RECKLESS
d9c393f5 3675 check_map_args (len, args, s_map);
0f2d19dd
JB
3676#endif
3677 while (1)
3678 {
3679 arg1 = SCM_EOL;
3680 for (i = SCM_LENGTH (args) - 1; i >= 0; i--)
3681 {
d9c393f5
JB
3682 if (SCM_IMP (ve[i]))
3683 return res;
0f2d19dd
JB
3684 arg1 = scm_cons (SCM_CAR (ve[i]), arg1);
3685 ve[i] = SCM_CDR (ve[i]);
3686 }
3687 *pres = scm_cons (scm_apply (proc, arg1, SCM_EOL), SCM_EOL);
a23afe53 3688 pres = SCM_CDRLOC (*pres);
0f2d19dd
JB
3689 }
3690}
3691
3692
3693SCM_PROC(s_for_each, "for-each", 2, 0, 1, scm_for_each);
1cc91f1b 3694
0f2d19dd
JB
3695SCM
3696scm_for_each (proc, arg1, args)
3697 SCM proc;
3698 SCM arg1;
3699 SCM args;
0f2d19dd
JB
3700{
3701 SCM *ve = &args; /* Keep args from being optimized away. */
d9c393f5 3702 long i, len;
0f2d19dd
JB
3703 if SCM_NULLP (arg1)
3704 return SCM_UNSPECIFIED;
d9c393f5
JB
3705 len = scm_ilength (arg1);
3706 SCM_ASSERT (len >= 0, arg1, SCM_ARG2, s_for_each);
0f2d19dd
JB
3707 if SCM_NULLP (args)
3708 {
3709 while SCM_NIMP (arg1)
3710 {
3711 SCM_ASSERT (SCM_CONSP (arg1), arg1, SCM_ARG2, s_for_each);
3712 scm_apply (proc, SCM_CAR (arg1), scm_listofnull);
3713 arg1 = SCM_CDR (arg1);
3714 }
3715 return SCM_UNSPECIFIED;
3716 }
3717 args = scm_vector (scm_cons (arg1, args));
3718 ve = SCM_VELTS (args);
cf7c17e9 3719#ifndef SCM_RECKLESS
d9c393f5 3720 check_map_args (len, args, s_for_each);
0f2d19dd
JB
3721#endif
3722 while (1)
3723 {
3724 arg1 = SCM_EOL;
3725 for (i = SCM_LENGTH (args) - 1; i >= 0; i--)
3726 {
3727 if SCM_IMP
3728 (ve[i]) return SCM_UNSPECIFIED;
3729 arg1 = scm_cons (SCM_CAR (ve[i]), arg1);
3730 ve[i] = SCM_CDR (ve[i]);
3731 }
3732 scm_apply (proc, arg1, SCM_EOL);
3733 }
3734}
3735
3736
1cc91f1b 3737
0f2d19dd
JB
3738SCM
3739scm_closure (code, env)
3740 SCM code;
3741 SCM env;
0f2d19dd
JB
3742{
3743 register SCM z;
3744 SCM_NEWCELL (z);
3745 SCM_SETCODE (z, code);
a23afe53 3746 SCM_SETENV (z, env);
0f2d19dd
JB
3747 return z;
3748}
3749
3750
3751long scm_tc16_promise;
1cc91f1b 3752
0f2d19dd
JB
3753SCM
3754scm_makprom (code)
3755 SCM code;
0f2d19dd 3756{
23a62151 3757 SCM_RETURN_NEWSMOB (scm_tc16_promise, code);
0f2d19dd
JB
3758}
3759
3760
1cc91f1b
JB
3761
3762static int prinprom SCM_P ((SCM exp, SCM port, scm_print_state *pstate));
3763
0f2d19dd 3764static int
19402679 3765prinprom (exp, port, pstate)
0f2d19dd
JB
3766 SCM exp;
3767 SCM port;
19402679 3768 scm_print_state *pstate;
0f2d19dd 3769{
19402679 3770 int writingp = SCM_WRITINGP (pstate);
b7f3516f 3771 scm_puts ("#<promise ", port);
19402679
MD
3772 SCM_SET_WRITINGP (pstate, 1);
3773 scm_iprin1 (SCM_CDR (exp), port, pstate);
3774 SCM_SET_WRITINGP (pstate, writingp);
b7f3516f 3775 scm_putc ('>', port);
0f2d19dd
JB
3776 return !0;
3777}
3778
3779
0f2d19dd 3780SCM_PROC(s_force, "force", 1, 0, 0, scm_force);
1cc91f1b 3781
0f2d19dd
JB
3782SCM
3783scm_force (x)
3784 SCM x;
0f2d19dd 3785{
eed6e03e
JB
3786 SCM_ASSERT (SCM_NIMP(x) && SCM_TYP16 (x) == scm_tc16_promise,
3787 x, SCM_ARG1, s_force);
0f2d19dd
JB
3788 if (!((1L << 16) & SCM_CAR (x)))
3789 {
3790 SCM ans = scm_apply (SCM_CDR (x), SCM_EOL, SCM_EOL);
3791 if (!((1L << 16) & SCM_CAR (x)))
3792 {
3793 SCM_DEFER_INTS;
a23afe53
MD
3794 SCM_SETCDR (x, ans);
3795 SCM_SETOR_CAR (x, (1L << 16));
0f2d19dd
JB
3796 SCM_ALLOW_INTS;
3797 }
3798 }
3799 return SCM_CDR (x);
3800}
3801
3802SCM_PROC (s_promise_p, "promise?", 1, 0, 0, scm_promise_p);
1cc91f1b 3803
0f2d19dd
JB
3804SCM
3805scm_promise_p (x)
3806 SCM x;
0f2d19dd
JB
3807{
3808 return ((SCM_NIMP (x) && (SCM_TYP16 (x) == scm_tc16_promise))
3809 ? SCM_BOOL_T
3810 : SCM_BOOL_F);
3811}
3812
26d5b9b4
MD
3813SCM_PROC (s_cons_source, "cons-source", 3, 0, 0, scm_cons_source);
3814
3815SCM
3816scm_cons_source (SCM xorig, SCM x, SCM y)
3817{
3818 SCM p, z;
3819 SCM_NEWCELL (z);
3820 SCM_SETCAR (z, x);
3821 SCM_SETCDR (z, y);
3822 /* Copy source properties possibly associated with xorig. */
3823 p = scm_whash_lookup (scm_source_whash, xorig);
3824 if (SCM_NIMP (p))
3825 scm_whash_insert (scm_source_whash, z, p);
3826 return z;
3827}
3828
3829SCM_PROC (s_copy_tree, "copy-tree", 1, 0, 0, scm_copy_tree);
1cc91f1b 3830
0f2d19dd
JB
3831SCM
3832scm_copy_tree (obj)
3833 SCM obj;
0f2d19dd
JB
3834{
3835 SCM ans, tl;
26d5b9b4 3836 if (SCM_IMP (obj))
ff467021 3837 return obj;
3910272e
MD
3838 if (SCM_VECTORP (obj))
3839 {
3840 scm_sizet i = SCM_LENGTH (obj);
3841 ans = scm_make_vector (SCM_MAKINUM (i), SCM_UNSPECIFIED);
3842 while (i--)
3843 SCM_VELTS (ans)[i] = scm_copy_tree (SCM_VELTS (obj)[i]);
3844 return ans;
3845 }
ff467021 3846 if (SCM_NCONSP (obj))
0f2d19dd
JB
3847 return obj;
3848/* return scm_cons(scm_copy_tree(SCM_CAR(obj)), scm_copy_tree(SCM_CDR(obj))); */
26d5b9b4
MD
3849 ans = tl = scm_cons_source (obj,
3850 scm_copy_tree (SCM_CAR (obj)),
3851 SCM_UNSPECIFIED);
0f2d19dd 3852 while (SCM_NIMP (obj = SCM_CDR (obj)) && SCM_CONSP (obj))
a23afe53
MD
3853 {
3854 SCM_SETCDR (tl, scm_cons (scm_copy_tree (SCM_CAR (obj)),
3855 SCM_UNSPECIFIED));
3856 tl = SCM_CDR (tl);
3857 }
3858 SCM_SETCDR (tl, obj);
0f2d19dd
JB
3859 return ans;
3860}
3861
1cc91f1b 3862
0f2d19dd
JB
3863SCM
3864scm_eval_3 (obj, copyp, env)
3865 SCM obj;
3866 int copyp;
3867 SCM env;
0f2d19dd
JB
3868{
3869 if (SCM_NIMP (SCM_CDR (scm_system_transformer)))
3870 obj = scm_apply (SCM_CDR (scm_system_transformer), obj, scm_listofnull);
3871 else if (copyp)
3872 obj = scm_copy_tree (obj);
6cb702da 3873 return SCM_XEVAL (obj, env);
0f2d19dd
JB
3874}
3875
0f2d19dd 3876SCM_PROC(s_eval2, "eval2", 2, 0, 0, scm_eval2);
1cc91f1b 3877
0f2d19dd
JB
3878SCM
3879scm_eval2 (obj, env_thunk)
3880 SCM obj;
3881 SCM env_thunk;
0f2d19dd 3882{
6bcb0868 3883 return scm_eval_3 (obj, 1, scm_top_level_env (env_thunk));
0f2d19dd
JB
3884}
3885
3886SCM_PROC(s_eval, "eval", 1, 0, 0, scm_eval);
1cc91f1b 3887
0f2d19dd
JB
3888SCM
3889scm_eval (obj)
3890 SCM obj;
0f2d19dd 3891{
6bcb0868
MD
3892 return scm_eval_3 (obj,
3893 1,
3894 scm_top_level_env
3895 (SCM_CDR (scm_top_level_lookup_closure_var)));
0f2d19dd
JB
3896}
3897
11f77bfc 3898/* SCM_PROC(s_eval_x, "eval!", 1, 0, 0, scm_eval_x); */
1cc91f1b 3899
0f2d19dd
JB
3900SCM
3901scm_eval_x (obj)
3902 SCM obj;
0f2d19dd 3903{
6bcb0868
MD
3904 return scm_eval_3 (obj,
3905 0,
3906 scm_top_level_env
3907 (SCM_CDR (scm_top_level_lookup_closure_var)));
0f2d19dd
JB
3908}
3909
6dbd0af5
MD
3910
3911/* At this point, scm_deval and scm_dapply are generated.
3912 */
3913
0f2d19dd 3914#ifdef DEBUG_EXTENSIONS
6dbd0af5
MD
3915# define DEVAL
3916# include "eval.c"
0f2d19dd
JB
3917#endif
3918
3919
1cc91f1b 3920
0f2d19dd
JB
3921void
3922scm_init_eval ()
0f2d19dd 3923{
33b97402
MD
3924 scm_init_opts (scm_evaluator_traps,
3925 scm_evaluator_trap_table,
3926 SCM_N_EVALUATOR_TRAPS);
3927 scm_init_opts (scm_eval_options_interface,
3928 scm_eval_opts,
3929 SCM_N_EVAL_OPTIONS);
3930
f99c9c28
MD
3931 scm_tc16_promise = scm_make_smob_type ("promise", 0);
3932 scm_set_smob_mark (scm_tc16_promise, scm_markcdr);
3933 scm_set_smob_print (scm_tc16_promise, prinprom);
b8229a3b 3934
81123e6d 3935 scm_f_apply = scm_make_subr ("apply", scm_tc7_lsubr_2, scm_apply);
0f2d19dd 3936 scm_system_transformer = scm_sysintern ("scm:eval-transformer", SCM_UNDEFINED);
2f0d1375
MD
3937 scm_sym_dot = SCM_CAR (scm_sysintern (".", SCM_UNDEFINED));
3938 scm_sym_arrow = SCM_CAR (scm_sysintern ("=>", SCM_UNDEFINED));
3939 scm_sym_else = SCM_CAR (scm_sysintern ("else", SCM_UNDEFINED));
3940 scm_sym_unquote = SCM_CAR (scm_sysintern ("unquote", SCM_UNDEFINED));
3941 scm_sym_uq_splicing = SCM_CAR (scm_sysintern ("unquote-splicing", SCM_UNDEFINED));
0f2d19dd 3942
73b64342
MD
3943 scm_nil = scm_sysintern ("nil", SCM_UNDEFINED);
3944 SCM_SETCDR (scm_nil, SCM_CAR (scm_nil));
3945 scm_nil = SCM_CAR (scm_nil);
3946 scm_t = scm_sysintern ("t", SCM_UNDEFINED);
3947 SCM_SETCDR (scm_t, SCM_CAR (scm_t));
3948 scm_t = SCM_CAR (scm_t);
73b64342 3949
0f2d19dd 3950 /* acros */
0f2d19dd
JB
3951 /* end of acros */
3952
dc19d1d2
JB
3953 scm_top_level_lookup_closure_var =
3954 scm_sysintern("*top-level-lookup-closure*", SCM_BOOL_F);
9b8d3288 3955 scm_can_use_top_level_lookup_closure_var = 1;
0f2d19dd 3956
6dbd0af5 3957#ifdef DEBUG_EXTENSIONS
2f0d1375
MD
3958 scm_sym_enter_frame = SCM_CAR (scm_sysintern ("enter-frame", SCM_UNDEFINED));
3959 scm_sym_apply_frame = SCM_CAR (scm_sysintern ("apply-frame", SCM_UNDEFINED));
3960 scm_sym_exit_frame = SCM_CAR (scm_sysintern ("exit-frame", SCM_UNDEFINED));
3961 scm_sym_trace = SCM_CAR (scm_sysintern ("trace", SCM_UNDEFINED));
6dbd0af5
MD
3962#endif
3963
0f2d19dd 3964#include "eval.x"
25eaf21a
MD
3965
3966 scm_add_feature ("delay");
0f2d19dd 3967}
0f2d19dd 3968
6dbd0af5 3969#endif /* !DEVAL */