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