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