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