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