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