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