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