* goops.c (TEST_CHANGE_CLASS, scm_sys_initialize_object): Don't
[bpt/guile.git] / libguile / eval.c
CommitLineData
756414cf 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002, 2003 Free Software Foundation, Inc.
0f2d19dd 2 *
73be1d9e
MV
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
0f2d19dd 7 *
73be1d9e
MV
8 * This library 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 GNU
11 * Lesser General Public License for more details.
0f2d19dd 12 *
73be1d9e
MV
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
1bbd0b84 17
0f2d19dd
JB
18\f
19
6dbd0af5
MD
20/* This file is read twice in order to produce debugging versions of
21 * scm_ceval and scm_apply. These functions, scm_deval and
22 * scm_dapply, are produced when we define the preprocessor macro
23 * DEVAL. The file is divided into sections which are treated
24 * differently with respect to DEVAL. The heads of these sections are
25 * marked with the string "SECTION:".
26 */
27
6dbd0af5 28/* SECTION: This code is compiled once.
0f2d19dd
JB
29 */
30
3d05f2e0
RB
31#if HAVE_CONFIG_H
32# include <config.h>
33#endif
0f2d19dd 34
3d05f2e0
RB
35#include "libguile/__scm.h"
36
37#ifndef DEVAL
d16332b3 38
48b96f4b
JB
39/* AIX requires this to be the first thing in the file. The #pragma
40 directive is indented so pre-ANSI compilers will ignore it, rather
41 than choke on it. */
5862b540 42#ifndef __GNUC__
48b96f4b
JB
43# if HAVE_ALLOCA_H
44# include <alloca.h>
45# else
46# ifdef _AIX
ac13d9d2 47# pragma alloca
48b96f4b
JB
48# else
49# ifndef alloca /* predefined by HP cc +Olibcalls */
50char *alloca ();
51# endif
52# endif
53# endif
54#endif
55
a0599745
MD
56#include "libguile/_scm.h"
57#include "libguile/debug.h"
09074dbf 58#include "libguile/dynwind.h"
a0599745
MD
59#include "libguile/alist.h"
60#include "libguile/eq.h"
61#include "libguile/continuations.h"
756414cf 62#include "libguile/futures.h"
a0599745
MD
63#include "libguile/throw.h"
64#include "libguile/smob.h"
65#include "libguile/macros.h"
66#include "libguile/procprop.h"
67#include "libguile/hashtab.h"
68#include "libguile/hash.h"
69#include "libguile/srcprop.h"
70#include "libguile/stackchk.h"
71#include "libguile/objects.h"
72#include "libguile/async.h"
73#include "libguile/feature.h"
74#include "libguile/modules.h"
75#include "libguile/ports.h"
76#include "libguile/root.h"
77#include "libguile/vectors.h"
549e6ec6 78#include "libguile/fluids.h"
f12745b6 79#include "libguile/goops.h"
a513ead3 80#include "libguile/values.h"
a0599745
MD
81
82#include "libguile/validate.h"
83#include "libguile/eval.h"
c96d76b8 84#include "libguile/lang.h"
89efbff4 85
0f2d19dd
JB
86\f
87
17fa3fcf
DH
88#define SCM_VALIDATE_NON_EMPTY_COMBINATION(x) \
89 do { \
90 if (SCM_EQ_P ((x), SCM_EOL)) \
91 scm_misc_error (NULL, scm_s_expression, SCM_EOL); \
92 } while (0)
93
94\f
95
6dbd0af5
MD
96/* The evaluator contains a plethora of EVAL symbols.
97 * This is an attempt at explanation.
98 *
99 * The following macros should be used in code which is read twice
100 * (where the choice of evaluator is hard soldered):
101 *
102 * SCM_CEVAL is the symbol used within one evaluator to call itself.
103 * Originally, it is defined to scm_ceval, but is redefined to
104 * scm_deval during the second pass.
105 *
6cb702da 106 * SCM_EVALIM is used when it is known that the expression is an
6dbd0af5
MD
107 * immediate. (This macro never calls an evaluator.)
108 *
109 * EVALCAR evaluates the car of an expression.
110 *
6dbd0af5
MD
111 * The following macros should be used in code which is read once
112 * (where the choice of evaluator is dynamic):
113 *
6cb702da 114 * SCM_XEVAL takes care of immediates without calling an evaluator. It
6dbd0af5
MD
115 * then calls scm_ceval *or* scm_deval, depending on the debugging
116 * mode.
117 *
6cb702da 118 * SCM_XEVALCAR corresponds to EVALCAR, but uses scm_ceval *or* scm_deval
6dbd0af5
MD
119 * depending on the debugging mode.
120 *
121 * The main motivation for keeping this plethora is efficiency
122 * together with maintainability (=> locality of code).
123 */
124
6cb702da 125#define SCM_CEVAL scm_ceval
0f2d19dd 126
8c494e99 127#define EVALCAR(x, env) (SCM_IMP (SCM_CAR (x)) \
904a077d 128 ? SCM_EVALIM (SCM_CAR (x), env) \
680516ba
DH
129 : (SCM_SYMBOLP (SCM_CAR (x)) \
130 ? *scm_lookupcar (x, env, 1) \
131 : SCM_CEVAL (SCM_CAR (x), env)))
0f2d19dd 132
e2806c10 133#define EXTEND_ENV SCM_EXTEND_ENV
0f2d19dd 134
28d52ebb 135SCM_REC_MUTEX (source_mutex);
9bc4701c 136
0f2d19dd 137SCM *
6e8d25a6 138scm_ilookup (SCM iloc, SCM env)
0f2d19dd 139{
c014a02e 140 register long ir = SCM_IFRAME (iloc);
0f2d19dd
JB
141 register SCM er = env;
142 for (; 0 != ir; --ir)
143 er = SCM_CDR (er);
144 er = SCM_CAR (er);
145 for (ir = SCM_IDIST (iloc); 0 != ir; --ir)
146 er = SCM_CDR (er);
147 if (SCM_ICDRP (iloc))
a23afe53
MD
148 return SCM_CDRLOC (er);
149 return SCM_CARLOC (SCM_CDR (er));
0f2d19dd 150}
0f2d19dd 151
f8769b1d
MV
152/* The Lookup Car Race
153 - by Eva Luator
154
155 Memoization of variables and special forms is done while executing
156 the code for the first time. As long as there is only one thread
157 everything is fine, but as soon as two threads execute the same
158 code concurrently `for the first time' they can come into conflict.
159
160 This memoization includes rewriting variable references into more
161 efficient forms and expanding macros. Furthermore, macro expansion
162 includes `compiling' special forms like `let', `cond', etc. into
163 tree-code instructions.
164
165 There shouldn't normally be a problem with memoizing local and
904a077d 166 global variable references (into ilocs and variables), because all
f8769b1d
MV
167 threads will mutate the code in *exactly* the same way and (if I
168 read the C code correctly) it is not possible to observe a half-way
169 mutated cons cell. The lookup procedure can handle this
170 transparently without any critical sections.
171
172 It is different with macro expansion, because macro expansion
173 happens outside of the lookup procedure and can't be
904a077d
MV
174 undone. Therefore the lookup procedure can't cope with it. It has
175 to indicate failure when it detects a lost race and hope that the
176 caller can handle it. Luckily, it turns out that this is the case.
f8769b1d 177
904a077d 178 An example to illustrate this: Suppose that the following form will
f8769b1d
MV
179 be memoized concurrently by two threads
180
181 (let ((x 12)) x)
182
183 Let's first examine the lookup of X in the body. The first thread
184 decides that it has to find the symbol "x" in the environment and
185 starts to scan it. Then the other thread takes over and actually
186 overtakes the first. It looks up "x" and substitutes an
187 appropriate iloc for it. Now the first thread continues and
188 completes its lookup. It comes to exactly the same conclusions as
189 the second one and could - without much ado - just overwrite the
190 iloc with the same iloc.
191
192 But let's see what will happen when the race occurs while looking
193 up the symbol "let" at the start of the form. It could happen that
194 the second thread interrupts the lookup of the first thread and not
904a077d
MV
195 only substitutes a variable for it but goes right ahead and
196 replaces it with the compiled form (#@let* (x 12) x). Now, when
197 the first thread completes its lookup, it would replace the #@let*
198 with a variable containing the "let" binding, effectively reverting
199 the form to (let (x 12) x). This is wrong. It has to detect that
200 it has lost the race and the evaluator has to reconsider the
201 changed form completely.
f8769b1d
MV
202
203 This race condition could be resolved with some kind of traffic
204 light (like mutexes) around scm_lookupcar, but I think that it is
205 best to avoid them in this case. They would serialize memoization
206 completely and because lookup involves calling arbitrary Scheme
207 code (via the lookup-thunk), threads could be blocked for an
208 arbitrary amount of time or even deadlock. But with the current
209 solution a lot of unnecessary work is potentially done. */
210
9aa82b39 211/* SCM_LOOKUPCAR1 is what SCM_LOOKUPCAR used to be but is allowed to
f8769b1d
MV
212 return NULL to indicate a failed lookup due to some race conditions
213 between threads. This only happens when VLOC is the first cell of
214 a special form that will eventually be memoized (like `let', etc.)
215 In that case the whole lookup is bogus and the caller has to
216 reconsider the complete special form.
217
218 SCM_LOOKUPCAR is still there, of course. It just calls
de513fa0 219 SCM_LOOKUPCAR1 and aborts on receiving NULL. So SCM_LOOKUPCAR
f8769b1d
MV
220 should only be called when it is known that VLOC is not the first
221 pair of a special form. Otherwise, use SCM_LOOKUPCAR1 and check
26d5b9b4
MD
222 for NULL. I think I've found the only places where this
223 applies. */
f8769b1d 224
f25f761d
GH
225SCM_SYMBOL (scm_unbound_variable_key, "unbound-variable");
226
8ecf1f13 227static SCM *
26d5b9b4 228scm_lookupcar1 (SCM vloc, SCM genv, int check)
0f2d19dd
JB
229{
230 SCM env = genv;
e3173f93 231 register SCM *al, fl, var = SCM_CAR (vloc);
0f2d19dd 232 register SCM iloc = SCM_ILOC00;
0f2d19dd
JB
233 for (; SCM_NIMP (env); env = SCM_CDR (env))
234 {
790071cd 235 if (!SCM_CONSP (SCM_CAR (env)))
0f2d19dd 236 break;
a23afe53 237 al = SCM_CARLOC (env);
0f2d19dd
JB
238 for (fl = SCM_CAR (*al); SCM_NIMP (fl); fl = SCM_CDR (fl))
239 {
01f11e02 240 if (!SCM_CONSP (fl))
33b97402 241 {
cf498326 242 if (SCM_EQ_P (fl, var))
0f2d19dd 243 {
cf498326 244 if (! SCM_EQ_P (SCM_CAR (vloc), var))
f8769b1d 245 goto race;
3201d763 246 SCM_SET_CELL_WORD_0 (vloc, SCM_UNPACK (iloc) + SCM_ICDR);
a23afe53 247 return SCM_CDRLOC (*al);
0f2d19dd 248 }
33b97402
MD
249 else
250 break;
251 }
a23afe53 252 al = SCM_CDRLOC (*al);
cf498326 253 if (SCM_EQ_P (SCM_CAR (fl), var))
0f2d19dd 254 {
0f2d19dd
JB
255 if (SCM_UNBNDP (SCM_CAR (*al)))
256 {
257 env = SCM_EOL;
258 goto errout;
259 }
c6772927 260 if (!SCM_EQ_P (SCM_CAR (vloc), var))
f8769b1d 261 goto race;
a23afe53 262 SCM_SETCAR (vloc, iloc);
a23afe53 263 return SCM_CARLOC (*al);
0f2d19dd 264 }
3201d763 265 iloc = SCM_PACK (SCM_UNPACK (iloc) + SCM_IDINC);
0f2d19dd 266 }
3201d763 267 iloc = SCM_PACK ((~SCM_IDSTMSK) & (SCM_UNPACK(iloc) + SCM_IFRINC));
0f2d19dd
JB
268 }
269 {
86d31dfe 270 SCM top_thunk, real_var;
790071cd 271 if (SCM_NIMP (env))
0f2d19dd 272 {
86d31dfe
MV
273 top_thunk = SCM_CAR (env); /* env now refers to a
274 top level env thunk */
0f2d19dd
JB
275 env = SCM_CDR (env);
276 }
277 else
278 top_thunk = SCM_BOOL_F;
86d31dfe
MV
279 real_var = scm_sym2var (var, top_thunk, SCM_BOOL_F);
280 if (SCM_FALSEP (real_var))
0f2d19dd 281 goto errout;
86d31dfe 282
01f11e02 283 if (!SCM_NULLP (env) || SCM_UNBNDP (SCM_VARIABLE_REF (real_var)))
86d31dfe
MV
284 {
285 errout:
86d31dfe
MV
286 if (check)
287 {
288 if (SCM_NULLP (env))
289 scm_error (scm_unbound_variable_key, NULL,
290 "Unbound variable: ~S",
8ea46249 291 scm_list_1 (var), SCM_BOOL_F);
86d31dfe
MV
292 else
293 scm_misc_error (NULL, "Damaged environment: ~S",
8ea46249 294 scm_list_1 (var));
86d31dfe
MV
295 }
296 else
297 {
298 /* A variable could not be found, but we shall
299 not throw an error. */
300 static SCM undef_object = SCM_UNDEFINED;
301 return &undef_object;
302 }
09e4d064 303 }
86d31dfe 304
c6772927 305 if (!SCM_EQ_P (SCM_CAR (vloc), var))
86d31dfe
MV
306 {
307 /* Some other thread has changed the very cell we are working
308 on. In effect, it must have done our job or messed it up
309 completely. */
310 race:
311 var = SCM_CAR (vloc);
d22a0ea1
MV
312 if (SCM_VARIABLEP (var))
313 return SCM_VARIABLE_LOC (var);
86d31dfe
MV
314 if (SCM_ITAG7 (var) == SCM_ITAG7 (SCM_ILOC00))
315 return scm_ilookup (var, genv);
904a077d 316 /* We can't cope with anything else than variables and ilocs. When
86d31dfe
MV
317 a special form has been memoized (i.e. `let' into `#@let') we
318 return NULL and expect the calling function to do the right
319 thing. For the evaluator, this means going back and redoing
320 the dispatch on the car of the form. */
321 return NULL;
322 }
f8769b1d 323
d22a0ea1 324 SCM_SETCAR (vloc, real_var);
86d31dfe
MV
325 return SCM_VARIABLE_LOC (real_var);
326 }
0f2d19dd
JB
327}
328
f8769b1d 329SCM *
6e8d25a6 330scm_lookupcar (SCM vloc, SCM genv, int check)
f8769b1d 331{
26d5b9b4 332 SCM *loc = scm_lookupcar1 (vloc, genv, check);
f8769b1d
MV
333 if (loc == NULL)
334 abort ();
335 return loc;
336}
f8769b1d 337
0f2d19dd 338#define unmemocar scm_unmemocar
1cc91f1b 339
86d31dfe
MV
340SCM_SYMBOL (sym_three_question_marks, "???");
341
0f2d19dd 342SCM
6e8d25a6 343scm_unmemocar (SCM form, SCM env)
0f2d19dd 344{
302c12b4 345 if (!SCM_CONSP (form))
0f2d19dd 346 return form;
302c12b4 347 else
d22a0ea1 348 {
302c12b4
DH
349 SCM c = SCM_CAR (form);
350 if (SCM_VARIABLEP (c))
351 {
352 SCM sym = scm_module_reverse_lookup (scm_env_module (env), c);
353 if (SCM_FALSEP (sym))
354 sym = sym_three_question_marks;
355 SCM_SETCAR (form, sym);
356 }
302c12b4
DH
357 else if (SCM_ILOCP (c))
358 {
359 unsigned long int ir;
360
361 for (ir = SCM_IFRAME (c); ir != 0; --ir)
362 env = SCM_CDR (env);
363 env = SCM_CAAR (env);
364 for (ir = SCM_IDIST (c); ir != 0; --ir)
365 env = SCM_CDR (env);
366 SCM_SETCAR (form, SCM_ICDRP (c) ? env : SCM_CAR (env));
367 }
302c12b4
DH
368 return form;
369 }
0f2d19dd
JB
370}
371
1cc91f1b 372
0f2d19dd 373SCM
6e8d25a6 374scm_eval_car (SCM pair, SCM env)
0f2d19dd 375{
6cb702da 376 return SCM_XEVALCAR (pair, env);
0f2d19dd
JB
377}
378
379\f
380/*
381 * The following rewrite expressions and
382 * some memoized forms have different syntax
383 */
384
3eeba8d4
JB
385const char scm_s_expression[] = "missing or extra expression";
386const char scm_s_test[] = "bad test";
387const char scm_s_body[] = "bad body";
388const char scm_s_bindings[] = "bad bindings";
185ab0ef 389const char scm_s_duplicate_bindings[] = "duplicate bindings";
3eeba8d4
JB
390const char scm_s_variable[] = "bad variable";
391const char scm_s_clauses[] = "bad or missing clauses";
392const char scm_s_formals[] = "bad formals";
5280aaca 393const char scm_s_duplicate_formals[] = "duplicate formals";
302c12b4 394static const char s_splicing[] = "bad (non-list) result for unquote-splicing";
0f2d19dd 395
85db4a2c
DH
396SCM_GLOBAL_SYMBOL (scm_sym_dot, ".");
397SCM_GLOBAL_SYMBOL (scm_sym_arrow, "=>");
398SCM_GLOBAL_SYMBOL (scm_sym_else, "else");
399SCM_GLOBAL_SYMBOL (scm_sym_unquote, "unquote");
400SCM_GLOBAL_SYMBOL (scm_sym_uq_splicing, "unquote-splicing");
81123e6d 401
85db4a2c
DH
402SCM_GLOBAL_SYMBOL (scm_sym_enter_frame, "enter-frame");
403SCM_GLOBAL_SYMBOL (scm_sym_apply_frame, "apply-frame");
404SCM_GLOBAL_SYMBOL (scm_sym_exit_frame, "exit-frame");
405SCM_GLOBAL_SYMBOL (scm_sym_trace, "trace");
0f2d19dd 406
0f2d19dd 407
26d5b9b4
MD
408/* Check that the body denoted by XORIG is valid and rewrite it into
409 its internal form. The internal form of a body is just the body
410 itself, but prefixed with an ISYM that denotes to what kind of
411 outer construct this body belongs. A lambda body starts with
412 SCM_IM_LAMBDA, for example, a body of a let starts with SCM_IM_LET,
413 etc. The one exception is a body that belongs to a letrec that has
414 been formed by rewriting internal defines: it starts with
415 SCM_IM_DEFINE. */
416
417/* XXX - Besides controlling the rewriting of internal defines, the
418 additional ISYM could be used for improved error messages.
419 This is not done yet. */
420
421static SCM
6e8d25a6 422scm_m_body (SCM op, SCM xorig, const char *what)
26d5b9b4 423{
302c12b4 424 SCM_ASSYNT (scm_ilength (xorig) >= 1, scm_s_body, what);
26d5b9b4
MD
425
426 /* Don't add another ISYM if one is present already. */
427 if (SCM_ISYMP (SCM_CAR (xorig)))
428 return xorig;
429
430 /* Retain possible doc string. */
44d3cb0d 431 if (!SCM_CONSP (SCM_CAR (xorig)))
26d5b9b4 432 {
8ea46249 433 if (!SCM_NULLP (SCM_CDR (xorig)))
26d5b9b4 434 return scm_cons (SCM_CAR (xorig),
8ea46249 435 scm_m_body (op, SCM_CDR (xorig), what));
26d5b9b4
MD
436 return xorig;
437 }
438
ab66ae47 439 return scm_cons (op, xorig);
26d5b9b4
MD
440}
441
1cc91f1b 442
8ea46249
DH
443SCM_SYNTAX (s_quote, "quote", scm_makmmacro, scm_m_quote);
444SCM_GLOBAL_SYMBOL (scm_sym_quote, s_quote);
445
446SCM
e81d98ec 447scm_m_quote (SCM xorig, SCM env SCM_UNUSED)
0f2d19dd 448{
160bb34a 449 SCM_ASSYNT (scm_ilength (SCM_CDR (xorig)) == 1, scm_s_expression, s_quote);
302c12b4 450 return scm_cons (SCM_IM_QUOTE, SCM_CDR (xorig));
0f2d19dd
JB
451}
452
453
8ea46249
DH
454SCM_SYNTAX (s_begin, "begin", scm_makmmacro, scm_m_begin);
455SCM_GLOBAL_SYMBOL (scm_sym_begin, s_begin);
1cc91f1b 456
8ea46249 457SCM
e81d98ec 458scm_m_begin (SCM xorig, SCM env SCM_UNUSED)
0f2d19dd 459{
b8113bc8 460 SCM_ASSYNT (scm_ilength (SCM_CDR (xorig)) >= 0, scm_s_expression, s_begin);
3a3111a8 461 return scm_cons (SCM_IM_BEGIN, SCM_CDR (xorig));
0f2d19dd
JB
462}
463
1cc91f1b 464
8ea46249
DH
465SCM_SYNTAX (s_if, "if", scm_makmmacro, scm_m_if);
466SCM_GLOBAL_SYMBOL (scm_sym_if, s_if);
467
468SCM
e81d98ec 469scm_m_if (SCM xorig, SCM env SCM_UNUSED)
0f2d19dd 470{
c014a02e 471 long len = scm_ilength (SCM_CDR (xorig));
c96d76b8 472 SCM_ASSYNT (len >= 2 && len <= 3, scm_s_expression, s_if);
3a3111a8 473 return scm_cons (SCM_IM_IF, SCM_CDR (xorig));
0f2d19dd
JB
474}
475
476
89efbff4 477/* Will go into the RnRS module when Guile is factorized.
5cb22e96
DH
478SCM_SYNTAX (s_set_x, "set!", scm_makmmacro, scm_m_set_x); */
479static const char s_set_x[] = "set!";
480SCM_GLOBAL_SYMBOL (scm_sym_set_x, s_set_x);
1cc91f1b 481
8ea46249 482SCM
e81d98ec 483scm_m_set_x (SCM xorig, SCM env SCM_UNUSED)
0f2d19dd 484{
6dbd0af5 485 SCM x = SCM_CDR (xorig);
5cb22e96
DH
486 SCM_ASSYNT (scm_ilength (x) == 2, scm_s_expression, s_set_x);
487 SCM_ASSYNT (SCM_SYMBOLP (SCM_CAR (x)), scm_s_variable, s_set_x);
3a3111a8 488 return scm_cons (SCM_IM_SET_X, x);
0f2d19dd
JB
489}
490
491
8ea46249
DH
492SCM_SYNTAX (s_and, "and", scm_makmmacro, scm_m_and);
493SCM_GLOBAL_SYMBOL (scm_sym_and, s_and);
1cc91f1b 494
8ea46249 495SCM
e81d98ec 496scm_m_and (SCM xorig, SCM env SCM_UNUSED)
0f2d19dd 497{
c014a02e 498 long len = scm_ilength (SCM_CDR (xorig));
160bb34a 499 SCM_ASSYNT (len >= 0, scm_s_test, s_and);
0f2d19dd 500 if (len >= 1)
3a3111a8 501 return scm_cons (SCM_IM_AND, SCM_CDR (xorig));
0f2d19dd
JB
502 else
503 return SCM_BOOL_T;
504}
505
1cc91f1b 506
8ea46249
DH
507SCM_SYNTAX (s_or, "or", scm_makmmacro, scm_m_or);
508SCM_GLOBAL_SYMBOL (scm_sym_or, s_or);
509
510SCM
e81d98ec 511scm_m_or (SCM xorig, SCM env SCM_UNUSED)
0f2d19dd 512{
c014a02e 513 long len = scm_ilength (SCM_CDR (xorig));
160bb34a 514 SCM_ASSYNT (len >= 0, scm_s_test, s_or);
0f2d19dd 515 if (len >= 1)
3a3111a8 516 return scm_cons (SCM_IM_OR, SCM_CDR (xorig));
0f2d19dd
JB
517 else
518 return SCM_BOOL_F;
519}
520
521
8ea46249
DH
522SCM_SYNTAX (s_case, "case", scm_makmmacro, scm_m_case);
523SCM_GLOBAL_SYMBOL (scm_sym_case, s_case);
1cc91f1b 524
8ea46249 525SCM
e81d98ec 526scm_m_case (SCM xorig, SCM env SCM_UNUSED)
0f2d19dd 527{
8ea46249
DH
528 SCM clauses;
529 SCM cdrx = SCM_CDR (xorig);
530 SCM_ASSYNT (scm_ilength (cdrx) >= 2, scm_s_clauses, s_case);
531 clauses = SCM_CDR (cdrx);
532 while (!SCM_NULLP (clauses))
0f2d19dd 533 {
8ea46249
DH
534 SCM clause = SCM_CAR (clauses);
535 SCM_ASSYNT (scm_ilength (clause) >= 2, scm_s_clauses, s_case);
536 SCM_ASSYNT (scm_ilength (SCM_CAR (clause)) >= 0
537 || (SCM_EQ_P (scm_sym_else, SCM_CAR (clause))
538 && SCM_NULLP (SCM_CDR (clauses))),
160bb34a 539 scm_s_clauses, s_case);
8ea46249 540 clauses = SCM_CDR (clauses);
0f2d19dd 541 }
3a3111a8 542 return scm_cons (SCM_IM_CASE, cdrx);
0f2d19dd
JB
543}
544
545
8ea46249
DH
546SCM_SYNTAX (s_cond, "cond", scm_makmmacro, scm_m_cond);
547SCM_GLOBAL_SYMBOL (scm_sym_cond, s_cond);
1cc91f1b 548
8ea46249 549SCM
e81d98ec 550scm_m_cond (SCM xorig, SCM env SCM_UNUSED)
0f2d19dd 551{
8ea46249
DH
552 SCM cdrx = SCM_CDR (xorig);
553 SCM clauses = cdrx;
554 SCM_ASSYNT (scm_ilength (clauses) >= 1, scm_s_clauses, s_cond);
555 while (!SCM_NULLP (clauses))
0f2d19dd 556 {
8ea46249
DH
557 SCM clause = SCM_CAR (clauses);
558 long len = scm_ilength (clause);
160bb34a 559 SCM_ASSYNT (len >= 1, scm_s_clauses, s_cond);
8ea46249 560 if (SCM_EQ_P (scm_sym_else, SCM_CAR (clause)))
0f2d19dd 561 {
8ea46249
DH
562 int last_clause_p = SCM_NULLP (SCM_CDR (clauses));
563 SCM_ASSYNT (len >= 2 && last_clause_p, "bad ELSE clause", s_cond);
0f2d19dd 564 }
8ea46249
DH
565 else if (len >= 2 && SCM_EQ_P (scm_sym_arrow, SCM_CADR (clause)))
566 {
567 SCM_ASSYNT (len > 2, "missing recipient", s_cond);
568 SCM_ASSYNT (len == 3, "bad recipient", s_cond);
569 }
570 clauses = SCM_CDR (clauses);
0f2d19dd 571 }
3a3111a8 572 return scm_cons (SCM_IM_COND, cdrx);
0f2d19dd
JB
573}
574
1cc91f1b 575
8ea46249
DH
576SCM_SYNTAX (s_lambda, "lambda", scm_makmmacro, scm_m_lambda);
577SCM_GLOBAL_SYMBOL (scm_sym_lambda, s_lambda);
5280aaca 578
8ea46249
DH
579/* Return true if OBJ is `eq?' to one of the elements of LIST or to the
580 * cdr of the last cons. (Thus, LIST is not required to be a proper
581 * list and OBJ can also be found in the improper ending.) */
5280aaca
MV
582static int
583scm_c_improper_memq (SCM obj, SCM list)
584{
585 for (; SCM_CONSP (list); list = SCM_CDR (list))
586 {
587 if (SCM_EQ_P (SCM_CAR (list), obj))
c6772927 588 return 1;
5280aaca
MV
589 }
590 return SCM_EQ_P (list, obj);
591}
592
8ea46249 593SCM
e81d98ec 594scm_m_lambda (SCM xorig, SCM env SCM_UNUSED)
0f2d19dd 595{
8ea46249
DH
596 SCM formals;
597 SCM x = SCM_CDR (xorig);
302c12b4
DH
598
599 SCM_ASSYNT (SCM_CONSP (x), scm_s_formals, s_lambda);
8ea46249
DH
600
601 formals = SCM_CAR (x);
602 while (SCM_CONSP (formals))
0f2d19dd 603 {
8ea46249
DH
604 SCM formal = SCM_CAR (formals);
605 SCM_ASSYNT (SCM_SYMBOLP (formal), scm_s_formals, s_lambda);
606 if (scm_c_improper_memq (formal, SCM_CDR (formals)))
db4b4ca6 607 scm_misc_error (s_lambda, scm_s_duplicate_formals, SCM_EOL);
8ea46249 608 formals = SCM_CDR (formals);
26d5b9b4 609 }
8ea46249
DH
610 if (!SCM_NULLP (formals) && !SCM_SYMBOLP (formals))
611 scm_misc_error (s_lambda, scm_s_formals, SCM_EOL);
26d5b9b4 612
3a3111a8
MD
613 return scm_cons2 (SCM_IM_LAMBDA, SCM_CAR (x),
614 scm_m_body (SCM_IM_LAMBDA, SCM_CDR (x), s_lambda));
0f2d19dd
JB
615}
616
617
8ea46249
DH
618SCM_SYNTAX (s_letstar, "let*", scm_makmmacro, scm_m_letstar);
619SCM_GLOBAL_SYMBOL (scm_sym_letstar, s_letstar);
1cc91f1b 620
8ea46249
DH
621/* (let* ((v1 i1) (v2 i2) ...) body) with variables v1 .. vk and initializers
622 * i1 .. ik is transformed into the form (#@let* (v1 i1 v2 i2 ...) body*). */
623SCM
e81d98ec 624scm_m_letstar (SCM xorig, SCM env SCM_UNUSED)
0f2d19dd 625{
8ea46249
DH
626 SCM bindings;
627 SCM x = SCM_CDR (xorig);
628 SCM vars = SCM_EOL;
629 SCM *varloc = &vars;
302c12b4
DH
630
631 SCM_ASSYNT (SCM_CONSP (x), scm_s_bindings, s_letstar);
632
8ea46249
DH
633 bindings = SCM_CAR (x);
634 SCM_ASSYNT (scm_ilength (bindings) >= 0, scm_s_bindings, s_letstar);
635 while (!SCM_NULLP (bindings))
0f2d19dd 636 {
8ea46249
DH
637 SCM binding = SCM_CAR (bindings);
638 SCM_ASSYNT (scm_ilength (binding) == 2, scm_s_bindings, s_letstar);
639 SCM_ASSYNT (SCM_SYMBOLP (SCM_CAR (binding)), scm_s_variable, s_letstar);
640 *varloc = scm_list_2 (SCM_CAR (binding), SCM_CADR (binding));
a23afe53 641 varloc = SCM_CDRLOC (SCM_CDR (*varloc));
8ea46249 642 bindings = SCM_CDR (bindings);
0f2d19dd 643 }
302c12b4 644
8ea46249 645 return scm_cons2 (SCM_IM_LETSTAR, vars,
3a3111a8 646 scm_m_body (SCM_IM_LETSTAR, SCM_CDR (x), s_letstar));
0f2d19dd
JB
647}
648
8ea46249 649
302c12b4
DH
650/* DO gets the most radically altered syntax. The order of the vars is
651 * reversed here. In contrast, the order of the inits and steps is reversed
652 * during the evaluation:
653
0f2d19dd
JB
654 (do ((<var1> <init1> <step1>)
655 (<var2> <init2>)
656 ... )
657 (<test> <return>)
658 <body>)
302c12b4 659
0f2d19dd 660 ;; becomes
302c12b4
DH
661
662 (#@do (varn ... var2 var1)
0f2d19dd
JB
663 (<init1> <init2> ... <initn>)
664 (<test> <return>)
665 (<body>)
666 <step1> <step2> ... <stepn>) ;; missing steps replaced by var
302c12b4 667 */
0f2d19dd 668
b8229a3b 669SCM_SYNTAX(s_do, "do", scm_makmmacro, scm_m_do);
2f0d1375 670SCM_GLOBAL_SYMBOL(scm_sym_do, s_do);
1cc91f1b 671
0f2d19dd 672SCM
e81d98ec 673scm_m_do (SCM xorig, SCM env SCM_UNUSED)
0f2d19dd 674{
8ea46249
DH
675 SCM bindings;
676 SCM x = SCM_CDR (xorig);
677 SCM vars = SCM_EOL;
678 SCM inits = SCM_EOL;
679 SCM *initloc = &inits;
680 SCM steps = SCM_EOL;
681 SCM *steploc = &steps;
682 SCM_ASSYNT (scm_ilength (x) >= 2, scm_s_test, "do");
683 bindings = SCM_CAR (x);
684 SCM_ASSYNT (scm_ilength (bindings) >= 0, scm_s_bindings, "do");
685 while (!SCM_NULLP (bindings))
0f2d19dd 686 {
302c12b4
DH
687 SCM binding = SCM_CAR (bindings);
688 long len = scm_ilength (binding);
8ea46249 689 SCM_ASSYNT (len == 2 || len == 3, scm_s_bindings, "do");
302c12b4
DH
690 {
691 SCM name = SCM_CAR (binding);
692 SCM init = SCM_CADR (binding);
693 SCM step = (len == 2) ? name : SCM_CADDR (binding);
694 SCM_ASSYNT (SCM_SYMBOLP (name), scm_s_variable, "do");
695 vars = scm_cons (name, vars);
696 *initloc = scm_list_1 (init);
697 initloc = SCM_CDRLOC (*initloc);
698 *steploc = scm_list_1 (step);
699 steploc = SCM_CDRLOC (*steploc);
700 bindings = SCM_CDR (bindings);
701 }
0f2d19dd
JB
702 }
703 x = SCM_CDR (x);
160bb34a 704 SCM_ASSYNT (scm_ilength (SCM_CAR (x)) >= 1, scm_s_test, "do");
0f2d19dd
JB
705 x = scm_cons2 (SCM_CAR (x), SCM_CDR (x), steps);
706 x = scm_cons2 (vars, inits, x);
3a3111a8 707 return scm_cons (SCM_IM_DO, x);
0f2d19dd
JB
708}
709
b8229a3b 710
302c12b4
DH
711SCM_SYNTAX (s_quasiquote, "quasiquote", scm_makacro, scm_m_quasiquote);
712SCM_GLOBAL_SYMBOL (scm_sym_quasiquote, s_quasiquote);
b8229a3b 713
302c12b4
DH
714/* Internal function to handle a quasiquotation: 'form' is the parameter in
715 * the call (quasiquotation form), 'env' is the environment where unquoted
716 * expressions will be evaluated, and 'depth' is the current quasiquotation
717 * nesting level and is known to be greater than zero. */
0f2d19dd 718static SCM
302c12b4 719iqq (SCM form, SCM env, unsigned long int depth)
0f2d19dd 720{
302c12b4
DH
721 if (SCM_CONSP (form))
722 {
723 SCM tmp = SCM_CAR (form);
724 if (SCM_EQ_P (tmp, scm_sym_quasiquote))
725 {
726 SCM args = SCM_CDR (form);
727 SCM_ASSYNT (scm_ilength (args) == 1, scm_s_expression, s_quasiquote);
728 return scm_list_2 (tmp, iqq (SCM_CAR (args), env, depth + 1));
729 }
730 else if (SCM_EQ_P (tmp, scm_sym_unquote))
731 {
732 SCM args = SCM_CDR (form);
733 SCM_ASSYNT (scm_ilength (args) == 1, scm_s_expression, s_quasiquote);
734 if (depth - 1 == 0)
735 return scm_eval_car (args, env);
736 else
737 return scm_list_2 (tmp, iqq (SCM_CAR (args), env, depth - 1));
738 }
739 else if (SCM_CONSP (tmp)
740 && SCM_EQ_P (SCM_CAR (tmp), scm_sym_uq_splicing))
741 {
742 SCM args = SCM_CDR (tmp);
743 SCM_ASSYNT (scm_ilength (args) == 1, scm_s_expression, s_quasiquote);
744 if (depth - 1 == 0)
745 {
746 SCM list = scm_eval_car (args, env);
747 SCM rest = SCM_CDR (form);
748 SCM_ASSYNT (scm_ilength (list) >= 0, s_splicing, s_quasiquote);
749 return scm_append (scm_list_2 (list, iqq (rest, env, depth)));
750 }
751 else
752 return scm_cons (iqq (SCM_CAR (form), env, depth - 1),
753 iqq (SCM_CDR (form), env, depth));
754 }
755 else
756 return scm_cons (iqq (SCM_CAR (form), env, depth),
757 iqq (SCM_CDR (form), env, depth));
758 }
759 else if (SCM_VECTORP (form))
0f2d19dd 760 {
302c12b4 761 size_t i = SCM_VECTOR_LENGTH (form);
34d19ef6 762 SCM const *data = SCM_VELTS (form);
302c12b4
DH
763 SCM tmp = SCM_EOL;
764 while (i != 0)
765 tmp = scm_cons (data[--i], tmp);
766 scm_remember_upto_here_1 (form);
0f2d19dd
JB
767 return scm_vector (iqq (tmp, env, depth));
768 }
302c12b4 769 else
ff467021 770 return form;
0f2d19dd
JB
771}
772
302c12b4
DH
773SCM
774scm_m_quasiquote (SCM xorig, SCM env)
775{
776 SCM x = SCM_CDR (xorig);
777 SCM_ASSYNT (scm_ilength (x) == 1, scm_s_expression, s_quasiquote);
778 return iqq (SCM_CAR (x), env, 1);
779}
780
0f2d19dd 781
a570e93a
MD
782SCM_SYNTAX (s_delay, "delay", scm_makmmacro, scm_m_delay);
783SCM_GLOBAL_SYMBOL (scm_sym_delay, s_delay);
1cc91f1b 784
302c12b4
DH
785/* Promises are implemented as closures with an empty parameter list. Thus,
786 * (delay <expression>) is transformed into (#@delay '() <expression>), where
787 * the empty list represents the empty parameter list. This representation
788 * allows for easy creation of the closure during evaluation. */
789SCM
e81d98ec 790scm_m_delay (SCM xorig, SCM env SCM_UNUSED)
0f2d19dd 791{
160bb34a 792 SCM_ASSYNT (scm_ilength (xorig) == 2, scm_s_expression, s_delay);
a570e93a 793 return scm_cons2 (SCM_IM_DELAY, SCM_EOL, SCM_CDR (xorig));
0f2d19dd
JB
794}
795
1cc91f1b 796
5cb22e96
DH
797SCM_SYNTAX (s_gset_x, "set!", scm_makmmacro, scm_m_generalized_set_x);
798SCM_SYMBOL (scm_sym_setter, "setter");
799
800SCM
801scm_m_generalized_set_x (SCM xorig, SCM env SCM_UNUSED)
802{
803 SCM x = SCM_CDR (xorig);
804 SCM_ASSYNT (2 == scm_ilength (x), scm_s_expression, s_set_x);
805 if (SCM_SYMBOLP (SCM_CAR (x)))
806 return scm_cons (SCM_IM_SET_X, x);
807 else if (SCM_CONSP (SCM_CAR (x)))
808 return scm_cons (scm_list_2 (scm_sym_setter, SCM_CAAR (x)),
809 scm_append (scm_list_2 (SCM_CDAR (x), SCM_CDR (x))));
810 else
811 scm_misc_error (s_set_x, scm_s_variable, SCM_EOL);
812}
813
814
28d52ebb
MD
815SCM_SYNTAX (s_future, "future", scm_makmmacro, scm_m_future);
816SCM_GLOBAL_SYMBOL (scm_sym_future, s_future);
817
818/* Like promises, futures are implemented as closures with an empty
819 * parameter list. Thus, (future <expression>) is transformed into
820 * (#@future '() <expression>), where the empty list represents the
821 * empty parameter list. This representation allows for easy creation
822 * of the closure during evaluation. */
823SCM
824scm_m_future (SCM xorig, SCM env SCM_UNUSED)
825{
826 SCM_ASSYNT (scm_ilength (xorig) == 2, scm_s_expression, s_future);
827 return scm_cons2 (SCM_IM_FUTURE, SCM_EOL, SCM_CDR (xorig));
828}
829
830
b8229a3b 831SCM_SYNTAX(s_define, "define", scm_makmmacro, scm_m_define);
2f0d1375 832SCM_GLOBAL_SYMBOL(scm_sym_define, s_define);
1cc91f1b 833
302c12b4
DH
834/* Guile provides an extension to R5RS' define syntax to represent function
835 * currying in a compact way. With this extension, it is allowed to write
836 * (define <nested-variable> <body>), where <nested-variable> has of one of
837 * the forms (<nested-variable> <formals>), (<nested-variable> . <formal>),
838 * (<variable> <formals>) or (<variable> . <formal>). As in R5RS, <formals>
839 * should be either a sequence of zero or more variables, or a sequence of one
840 * or more variables followed by a space-delimited period and another
841 * variable. Each level of argument nesting wraps the <body> within another
842 * lambda expression. For example, the following forms are allowed, each one
843 * followed by an equivalent, more explicit implementation.
844 * Example 1:
845 * (define ((a b . c) . d) <body>) is equivalent to
846 * (define a (lambda (b . c) (lambda d <body>)))
847 * Example 2:
848 * (define (((a) b) c . d) <body>) is equivalent to
849 * (define a (lambda () (lambda (b) (lambda (c . d) <body>))))
850 */
851/* Dirk:FIXME:: We should provide an implementation for 'define' in the R5RS
852 * module that does not implement this extension. */
853SCM
6e8d25a6 854scm_m_define (SCM x, SCM env)
0f2d19dd 855{
302c12b4 856 SCM name;
0f2d19dd 857 x = SCM_CDR (x);
160bb34a 858 SCM_ASSYNT (scm_ilength (x) >= 2, scm_s_expression, s_define);
302c12b4 859 name = SCM_CAR (x);
0f2d19dd 860 x = SCM_CDR (x);
302c12b4
DH
861 while (SCM_CONSP (name))
862 {
863 /* This while loop realizes function currying by variable nesting. */
864 SCM formals = SCM_CDR (name);
865 x = scm_list_1 (scm_cons2 (scm_sym_lambda, formals, x));
866 name = SCM_CAR (name);
0f2d19dd 867 }
302c12b4
DH
868 SCM_ASSYNT (SCM_SYMBOLP (name), scm_s_variable, s_define);
869 SCM_ASSYNT (scm_ilength (x) == 1, scm_s_expression, s_define);
0f2d19dd
JB
870 if (SCM_TOP_LEVEL (env))
871 {
302c12b4
DH
872 SCM var;
873 x = scm_eval_car (x, env);
874 if (SCM_REC_PROCNAMES_P)
80ea260c 875 {
302c12b4
DH
876 SCM tmp = x;
877 while (SCM_MACROP (tmp))
878 tmp = SCM_MACRO_CODE (tmp);
879 if (SCM_CLOSUREP (tmp)
80ea260c 880 /* Only the first definition determines the name. */
302c12b4
DH
881 && SCM_FALSEP (scm_procedure_property (tmp, scm_sym_name)))
882 scm_set_procedure_property_x (tmp, scm_sym_name, name);
80ea260c 883 }
302c12b4
DH
884 var = scm_sym2var (name, scm_env_top_level (env), SCM_BOOL_T);
885 SCM_VARIABLE_SET (var, x);
0f2d19dd 886 return SCM_UNSPECIFIED;
0f2d19dd 887 }
302c12b4
DH
888 else
889 return scm_cons2 (SCM_IM_DEFINE, name, x);
0f2d19dd 890}
6dbd0af5 891
0f2d19dd 892
302c12b4
DH
893/* The bindings ((v1 i1) (v2 i2) ... (vn in)) are transformed to the lists
894 * (vn ... v2 v1) and (i1 i2 ... in). That is, the list of variables is
895 * reversed here, the list of inits gets reversed during evaluation. */
896static void
897transform_bindings (SCM bindings, SCM *rvarloc, SCM *initloc, const char *what)
0f2d19dd 898{
302c12b4
DH
899 SCM rvars = SCM_EOL;
900 *rvarloc = SCM_EOL;
901 *initloc = SCM_EOL;
902
903 SCM_ASSYNT (scm_ilength (bindings) >= 1, scm_s_bindings, what);
0f2d19dd 904
0f2d19dd
JB
905 do
906 {
302c12b4
DH
907 SCM binding = SCM_CAR (bindings);
908 SCM_ASSYNT (scm_ilength (binding) == 2, scm_s_bindings, what);
909 SCM_ASSYNT (SCM_SYMBOLP (SCM_CAR (binding)), scm_s_variable, what);
910 if (scm_c_improper_memq (SCM_CAR (binding), rvars))
db4b4ca6 911 scm_misc_error (what, scm_s_duplicate_bindings, SCM_EOL);
302c12b4
DH
912 rvars = scm_cons (SCM_CAR (binding), rvars);
913 *initloc = scm_list_1 (SCM_CADR (binding));
a23afe53 914 initloc = SCM_CDRLOC (*initloc);
302c12b4 915 bindings = SCM_CDR (bindings);
0f2d19dd 916 }
302c12b4 917 while (!SCM_NULLP (bindings));
26d5b9b4 918
302c12b4 919 *rvarloc = rvars;
0f2d19dd
JB
920}
921
302c12b4 922
26d5b9b4 923SCM_SYNTAX(s_letrec, "letrec", scm_makmmacro, scm_m_letrec);
2f0d1375 924SCM_GLOBAL_SYMBOL(scm_sym_letrec, s_letrec);
26d5b9b4
MD
925
926SCM
6e8d25a6 927scm_m_letrec (SCM xorig, SCM env)
26d5b9b4
MD
928{
929 SCM x = SCM_CDR (xorig);
302c12b4 930 SCM_ASSYNT (SCM_CONSP (x), scm_s_bindings, s_letrec);
26d5b9b4 931
302c12b4
DH
932 if (SCM_NULLP (SCM_CAR (x)))
933 {
934 /* null binding, let* faster */
935 SCM body = scm_m_body (SCM_IM_LETREC, SCM_CDR (x), s_letrec);
936 return scm_m_letstar (scm_cons2 (SCM_CAR (xorig), SCM_EOL, body), env);
937 }
26d5b9b4 938 else
302c12b4
DH
939 {
940 SCM rvars, inits, body;
941 transform_bindings (SCM_CAR (x), &rvars, &inits, "letrec");
942 body = scm_m_body (SCM_IM_LETREC, SCM_CDR (x), "letrec");
943 return scm_cons2 (SCM_IM_LETREC, rvars, scm_cons (inits, body));
944 }
26d5b9b4 945}
1cc91f1b 946
302c12b4 947
b8229a3b 948SCM_SYNTAX(s_let, "let", scm_makmmacro, scm_m_let);
2f0d1375 949SCM_GLOBAL_SYMBOL(scm_sym_let, s_let);
b8229a3b 950
302c12b4 951SCM
6e8d25a6 952scm_m_let (SCM xorig, SCM env)
0f2d19dd 953{
302c12b4
DH
954 SCM x = SCM_CDR (xorig);
955 SCM temp;
956
957 SCM_ASSYNT (SCM_CONSP (x), scm_s_bindings, s_let);
958 temp = SCM_CAR (x);
959 if (SCM_NULLP (temp)
960 || (scm_ilength (temp) == 1 && SCM_CONSP (SCM_CAR (temp))))
26d5b9b4
MD
961 {
962 /* null or single binding, let* is faster */
3096b33f 963 SCM bindings = temp;
302c12b4 964 SCM body = scm_m_body (SCM_IM_LET, SCM_CDR (x), s_let);
3096b33f 965 return scm_m_letstar (scm_cons2 (SCM_CAR (xorig), bindings, body), env);
26d5b9b4 966 }
302c12b4 967 else if (SCM_CONSP (temp))
26d5b9b4 968 {
3096b33f
DH
969 /* plain let */
970 SCM bindings = temp;
302c12b4 971 SCM rvars, inits, body;
3096b33f 972 transform_bindings (bindings, &rvars, &inits, "let");
302c12b4
DH
973 body = scm_m_body (SCM_IM_LET, SCM_CDR (x), "let");
974 return scm_cons2 (SCM_IM_LET, rvars, scm_cons (inits, body));
26d5b9b4 975 }
302c12b4
DH
976 else
977 {
978 /* named let: Transform (let name ((var init) ...) body ...) into
979 * ((letrec ((name (lambda (var ...) body ...))) name) init ...) */
26d5b9b4 980
302c12b4
DH
981 SCM name = temp;
982 SCM vars = SCM_EOL;
983 SCM *varloc = &vars;
984 SCM inits = SCM_EOL;
985 SCM *initloc = &inits;
986 SCM bindings;
987
988 SCM_ASSYNT (SCM_SYMBOLP (name), scm_s_bindings, s_let);
989 x = SCM_CDR (x);
990 SCM_ASSYNT (SCM_CONSP (x), scm_s_bindings, s_let);
991 bindings = SCM_CAR (x);
992 SCM_ASSYNT (scm_ilength (bindings) >= 0, scm_s_bindings, s_let);
993 while (!SCM_NULLP (bindings))
994 { /* vars and inits both in order */
995 SCM binding = SCM_CAR (bindings);
996 SCM_ASSYNT (scm_ilength (binding) == 2, scm_s_bindings, s_let);
997 SCM_ASSYNT (SCM_SYMBOLP (SCM_CAR (binding)), scm_s_variable, s_let);
998 *varloc = scm_list_1 (SCM_CAR (binding));
999 varloc = SCM_CDRLOC (*varloc);
1000 *initloc = scm_list_1 (SCM_CADR (binding));
1001 initloc = SCM_CDRLOC (*initloc);
1002 bindings = SCM_CDR (bindings);
1003 }
26d5b9b4 1004
302c12b4
DH
1005 {
1006 SCM lambda_body = scm_m_body (SCM_IM_LET, SCM_CDR (x), "let");
1007 SCM lambda_form = scm_cons2 (scm_sym_lambda, vars, lambda_body);
1008 SCM rvar = scm_list_1 (name);
1009 SCM init = scm_list_1 (lambda_form);
1010 SCM body = scm_m_body (SCM_IM_LET, scm_list_1 (name), "let");
1011 SCM letrec = scm_cons2 (SCM_IM_LETREC, rvar, scm_cons (init, body));
1012 return scm_cons (letrec, inits);
1013 }
1014 }
0f2d19dd
JB
1015}
1016
1017
34d19ef6 1018SCM_SYNTAX (s_atapply, "@apply", scm_makmmacro, scm_m_apply);
81123e6d
MD
1019SCM_GLOBAL_SYMBOL (scm_sym_atapply, s_atapply);
1020SCM_GLOBAL_SYMBOL (scm_sym_apply, s_atapply + 1);
1cc91f1b 1021
0f2d19dd 1022SCM
e81d98ec 1023scm_m_apply (SCM xorig, SCM env SCM_UNUSED)
0f2d19dd 1024{
160bb34a 1025 SCM_ASSYNT (scm_ilength (SCM_CDR (xorig)) == 2, scm_s_expression, s_atapply);
0f2d19dd
JB
1026 return scm_cons (SCM_IM_APPLY, SCM_CDR (xorig));
1027}
1028
b8229a3b 1029
34d19ef6
HWN
1030SCM_SYNTAX(s_atcall_cc, "@call-with-current-continuation", scm_makmmacro, scm_m_cont);
1031SCM_GLOBAL_SYMBOL(scm_sym_atcall_cc, s_atcall_cc);
0f2d19dd 1032
1cc91f1b 1033
0f2d19dd 1034SCM
e81d98ec 1035scm_m_cont (SCM xorig, SCM env SCM_UNUSED)
0f2d19dd 1036{
6cb702da 1037 SCM_ASSYNT (scm_ilength (SCM_CDR (xorig)) == 1,
160bb34a 1038 scm_s_expression, s_atcall_cc);
3a3111a8 1039 return scm_cons (SCM_IM_CONT, SCM_CDR (xorig));
0f2d19dd
JB
1040}
1041
22721140 1042#if SCM_ENABLE_ELISP
73b64342
MD
1043
1044SCM_SYNTAX (s_nil_cond, "nil-cond", scm_makmmacro, scm_m_nil_cond);
1045
1046SCM
e81d98ec 1047scm_m_nil_cond (SCM xorig, SCM env SCM_UNUSED)
73b64342 1048{
c014a02e 1049 long len = scm_ilength (SCM_CDR (xorig));
160bb34a 1050 SCM_ASSYNT (len >= 1 && (len & 1) == 1, scm_s_expression, "nil-cond");
73b64342
MD
1051 return scm_cons (SCM_IM_NIL_COND, SCM_CDR (xorig));
1052}
1053
73b64342
MD
1054SCM_SYNTAX (s_atfop, "@fop", scm_makmmacro, scm_m_atfop);
1055
1056SCM
e81d98ec 1057scm_m_atfop (SCM xorig, SCM env SCM_UNUSED)
73b64342 1058{
86d31dfe 1059 SCM x = SCM_CDR (xorig), var;
160bb34a 1060 SCM_ASSYNT (scm_ilength (x) >= 1, scm_s_expression, "@fop");
86d31dfe 1061 var = scm_symbol_fref (SCM_CAR (x));
c96d76b8
NJ
1062 /* Passing the symbol name as the `subr' arg here isn't really
1063 right, but without it it can be very difficult to work out from
1064 the error message which function definition was missing. In any
1065 case, we shouldn't really use SCM_ASSYNT here at all, but instead
1066 something equivalent to (signal void-function (list SYM)) in
1067 Elisp. */
86d31dfe 1068 SCM_ASSYNT (SCM_VARIABLEP (var),
c96d76b8
NJ
1069 "Symbol's function definition is void",
1070 SCM_SYMBOL_CHARS (SCM_CAR (x)));
1071 /* Support `defalias'. */
1072 while (SCM_SYMBOLP (SCM_VARIABLE_REF (var)))
1073 {
1074 var = scm_symbol_fref (SCM_VARIABLE_REF (var));
1075 SCM_ASSYNT (SCM_VARIABLEP (var),
1076 "Symbol's function definition is void",
1077 SCM_SYMBOL_CHARS (SCM_CAR (x)));
1078 }
1079 /* Use `var' here rather than `SCM_VARIABLE_REF (var)' because the
1080 former allows for automatically picking up redefinitions of the
1081 corresponding symbol. */
904a077d 1082 SCM_SETCAR (x, var);
c96d76b8
NJ
1083 /* If the variable contains a procedure, leave the
1084 `transformer-macro' in place so that the procedure's arguments
1085 get properly transformed, and change the initial @fop to
1086 SCM_IM_APPLY. */
1087 if (!SCM_MACROP (SCM_VARIABLE_REF (var)))
1088 {
1089 SCM_SETCAR (xorig, SCM_IM_APPLY);
1090 return xorig;
1091 }
1092 /* Otherwise (the variable contains a macro), the arguments should
1093 not be transformed, so cut the `transformer-macro' out and return
1094 the resulting expression starting with the variable. */
1095 SCM_SETCDR (x, SCM_CDADR (x));
73b64342
MD
1096 return x;
1097}
1098
c96d76b8
NJ
1099#endif /* SCM_ENABLE_ELISP */
1100
2e171178
MV
1101/* (@bind ((var exp) ...) body ...)
1102
1103 This will assign the values of the `exp's to the global variables
1104 named by `var's (symbols, not evaluated), creating them if they
1105 don't exist, executes body, and then restores the previous values of
1106 the `var's. Additionally, whenever control leaves body, the values
1107 of the `var's are saved and restored when control returns. It is an
1108 error when a symbol appears more than once among the `var's.
1109 All `exp's are evaluated before any `var' is set.
1110
c96d76b8 1111 Think of this as `let' for dynamic scope.
2e171178
MV
1112
1113 It is memoized into (#@bind ((var ...) . (reversed-val ...)) body ...).
1114
1115 XXX - also implement `@bind*'.
1116*/
1117
73b64342
MD
1118SCM_SYNTAX (s_atbind, "@bind", scm_makmmacro, scm_m_atbind);
1119
1120SCM
1121scm_m_atbind (SCM xorig, SCM env)
1122{
1123 SCM x = SCM_CDR (xorig);
2e171178 1124 SCM top_level = scm_env_top_level (env);
311f6782 1125 SCM vars = SCM_EOL, var;
2e171178
MV
1126 SCM exps = SCM_EOL;
1127
1128 SCM_ASSYNT (scm_ilength (x) > 1, scm_s_expression, s_atbind);
73b64342 1129
73b64342
MD
1130 x = SCM_CAR (x);
1131 while (SCM_NIMP (x))
1132 {
2e171178
MV
1133 SCM rest;
1134 SCM sym_exp = SCM_CAR (x);
1135 SCM_ASSYNT (scm_ilength (sym_exp) == 2, scm_s_bindings, s_atbind);
1136 SCM_ASSYNT (SCM_SYMBOLP (SCM_CAR (sym_exp)), scm_s_bindings, s_atbind);
73b64342 1137 x = SCM_CDR (x);
2e171178 1138 for (rest = x; SCM_NIMP (rest); rest = SCM_CDR (rest))
8ea46249 1139 if (SCM_EQ_P (SCM_CAR (sym_exp), SCM_CAAR (rest)))
2e171178 1140 scm_misc_error (s_atbind, scm_s_duplicate_bindings, SCM_EOL);
311f6782
MV
1141 /* The first call to scm_sym2var will look beyond the current
1142 module, while the second call wont. */
1143 var = scm_sym2var (SCM_CAR (sym_exp), top_level, SCM_BOOL_F);
1144 if (SCM_FALSEP (var))
1145 var = scm_sym2var (SCM_CAR (sym_exp), top_level, SCM_BOOL_T);
1146 vars = scm_cons (var, vars);
2e171178 1147 exps = scm_cons (SCM_CADR (sym_exp), exps);
73b64342 1148 }
2e171178
MV
1149 return scm_cons (SCM_IM_BIND,
1150 scm_cons (scm_cons (scm_reverse_x (vars, SCM_EOL), exps),
1151 SCM_CDDR (xorig)));
73b64342 1152}
73b64342 1153
a513ead3
MV
1154SCM_SYNTAX (s_at_call_with_values, "@call-with-values", scm_makmmacro, scm_m_at_call_with_values);
1155SCM_GLOBAL_SYMBOL(scm_sym_at_call_with_values, s_at_call_with_values);
1156
1157SCM
e81d98ec 1158scm_m_at_call_with_values (SCM xorig, SCM env SCM_UNUSED)
a513ead3
MV
1159{
1160 SCM_ASSYNT (scm_ilength (SCM_CDR (xorig)) == 2,
1161 scm_s_expression, s_at_call_with_values);
1162 return scm_cons (SCM_IM_CALL_WITH_VALUES, SCM_CDR (xorig));
1163}
1164
26d5b9b4
MD
1165SCM
1166scm_m_expand_body (SCM xorig, SCM env)
1167{
22a52da1 1168 SCM x = SCM_CDR (xorig), defs = SCM_EOL;
26d5b9b4
MD
1169 char *what = SCM_ISYMCHARS (SCM_CAR (xorig)) + 2;
1170
1171 while (SCM_NIMP (x))
1172 {
22a52da1
DH
1173 SCM form = SCM_CAR (x);
1174 if (!SCM_CONSP (form))
26d5b9b4
MD
1175 break;
1176 if (!SCM_SYMBOLP (SCM_CAR (form)))
1177 break;
22a52da1 1178
3a3111a8
MD
1179 form = scm_macroexp (scm_cons_source (form,
1180 SCM_CAR (form),
1181 SCM_CDR (form)),
1182 env);
26d5b9b4 1183
cf498326 1184 if (SCM_EQ_P (SCM_IM_DEFINE, SCM_CAR (form)))
26d5b9b4
MD
1185 {
1186 defs = scm_cons (SCM_CDR (form), defs);
22a52da1 1187 x = SCM_CDR (x);
26d5b9b4 1188 }
22a52da1 1189 else if (!SCM_IMP (defs))
26d5b9b4
MD
1190 {
1191 break;
1192 }
cf498326 1193 else if (SCM_EQ_P (SCM_IM_BEGIN, SCM_CAR (form)))
26d5b9b4 1194 {
8ea46249 1195 x = scm_append (scm_list_2 (SCM_CDR (form), SCM_CDR (x)));
26d5b9b4
MD
1196 }
1197 else
1198 {
22a52da1 1199 x = scm_cons (form, SCM_CDR (x));
26d5b9b4
MD
1200 break;
1201 }
1202 }
1203
302c12b4 1204 if (!SCM_NULLP (defs))
26d5b9b4 1205 {
302c12b4
DH
1206 SCM rvars, inits, body, letrec;
1207 transform_bindings (defs, &rvars, &inits, what);
1208 body = scm_m_body (SCM_IM_DEFINE, x, what);
1209 letrec = scm_cons2 (SCM_IM_LETREC, rvars, scm_cons (inits, body));
1210 SCM_SETCAR (xorig, letrec);
1211 SCM_SETCDR (xorig, SCM_EOL);
1212 }
1213 else
1214 {
1215 SCM_ASSYNT (SCM_CONSP (x), scm_s_body, what);
1216 SCM_SETCAR (xorig, SCM_CAR (x));
1217 SCM_SETCDR (xorig, SCM_CDR (x));
26d5b9b4 1218 }
26d5b9b4
MD
1219
1220 return xorig;
1221}
1222
1223SCM
1224scm_macroexp (SCM x, SCM env)
1225{
86d31dfe 1226 SCM res, proc, orig_sym;
26d5b9b4
MD
1227
1228 /* Don't bother to produce error messages here. We get them when we
1229 eventually execute the code for real. */
1230
1231 macro_tail:
86d31dfe
MV
1232 orig_sym = SCM_CAR (x);
1233 if (!SCM_SYMBOLP (orig_sym))
26d5b9b4
MD
1234 return x;
1235
26d5b9b4
MD
1236 {
1237 SCM *proc_ptr = scm_lookupcar1 (x, env, 0);
1238 if (proc_ptr == NULL)
1239 {
1240 /* We have lost the race. */
1241 goto macro_tail;
1242 }
1243 proc = *proc_ptr;
1244 }
26d5b9b4
MD
1245
1246 /* Only handle memoizing macros. `Acros' and `macros' are really
1247 special forms and should not be evaluated here. */
1248
22a52da1 1249 if (!SCM_MACROP (proc) || SCM_MACRO_TYPE (proc) != 2)
26d5b9b4
MD
1250 return x;
1251
86d31dfe 1252 SCM_SETCAR (x, orig_sym); /* Undo memoizing effect of lookupcar */
fdc28395 1253 res = scm_call_2 (SCM_MACRO_CODE (proc), x, env);
26d5b9b4
MD
1254
1255 if (scm_ilength (res) <= 0)
8ea46249 1256 res = scm_list_2 (SCM_IM_BEGIN, res);
26d5b9b4 1257
26d5b9b4
MD
1258 SCM_DEFER_INTS;
1259 SCM_SETCAR (x, SCM_CAR (res));
1260 SCM_SETCDR (x, SCM_CDR (res));
1261 SCM_ALLOW_INTS;
1262
1263 goto macro_tail;
1264}
73b64342 1265
a44a9715
DH
1266#define SCM_BIT7(x) (127 & SCM_UNPACK (x))
1267
1268/* A function object to implement "apply" for non-closure functions. */
1269static SCM f_apply;
1270/* An endless list consisting of #<undefined> objects: */
1271static SCM undefineds;
1272
6dbd0af5
MD
1273/* scm_unmemocopy takes a memoized expression together with its
1274 * environment and rewrites it to its original form. Thus, it is the
1275 * inversion of the rewrite rules above. The procedure is not
1276 * optimized for speed. It's used in scm_iprin1 when printing the
220ff1eb
MD
1277 * code of a closure, in scm_procedure_source, in display_frame when
1278 * generating the source for a stackframe in a backtrace, and in
1279 * display_expression.
86d31dfe 1280 *
c96d76b8 1281 * Unmemoizing is not a reliable process. You cannot in general
86d31dfe
MV
1282 * expect to get the original source back.
1283 *
1284 * However, GOOPS currently relies on this for method compilation.
1285 * This ought to change.
26d5b9b4
MD
1286 */
1287
8ea46249
DH
1288static SCM
1289build_binding_list (SCM names, SCM inits)
1290{
1291 SCM bindings = SCM_EOL;
1292 while (!SCM_NULLP (names))
1293 {
1294 SCM binding = scm_list_2 (SCM_CAR (names), SCM_CAR (inits));
1295 bindings = scm_cons (binding, bindings);
1296 names = SCM_CDR (names);
1297 inits = SCM_CDR (inits);
1298 }
1299 return bindings;
1300}
1301
6dbd0af5 1302static SCM
1bbd0b84 1303unmemocopy (SCM x, SCM env)
6dbd0af5
MD
1304{
1305 SCM ls, z;
6dbd0af5 1306 SCM p;
8c494e99 1307 if (!SCM_CONSP (x))
6dbd0af5 1308 return x;
6dbd0af5 1309 p = scm_whash_lookup (scm_source_whash, x);
8ea46249 1310 switch (SCM_ITAG7 (SCM_CAR (x)))
6dbd0af5 1311 {
1b43d24c 1312 case SCM_BIT7 (SCM_IM_AND):
2f0d1375 1313 ls = z = scm_cons (scm_sym_and, SCM_UNSPECIFIED);
6dbd0af5 1314 break;
1b43d24c 1315 case SCM_BIT7 (SCM_IM_BEGIN):
2f0d1375 1316 ls = z = scm_cons (scm_sym_begin, SCM_UNSPECIFIED);
6dbd0af5 1317 break;
1b43d24c 1318 case SCM_BIT7 (SCM_IM_CASE):
2f0d1375 1319 ls = z = scm_cons (scm_sym_case, SCM_UNSPECIFIED);
6dbd0af5 1320 break;
1b43d24c 1321 case SCM_BIT7 (SCM_IM_COND):
2f0d1375 1322 ls = z = scm_cons (scm_sym_cond, SCM_UNSPECIFIED);
6dbd0af5 1323 break;
1b43d24c 1324 case SCM_BIT7 (SCM_IM_DO):
6dbd0af5 1325 {
8ea46249
DH
1326 /* format: (#@do (nk nk-1 ...) (i1 ... ik) (test) (body) s1 ... sk),
1327 * where nx is the name of a local variable, ix is an initializer for
1328 * the local variable, test is the test clause of the do loop, body is
1329 * the body of the do loop and sx are the step clauses for the local
1330 * variables. */
1331 SCM names, inits, test, memoized_body, steps, bindings;
1332
1333 x = SCM_CDR (x);
1334 names = SCM_CAR (x);
6dbd0af5 1335 x = SCM_CDR (x);
8ea46249
DH
1336 inits = scm_reverse (unmemocopy (SCM_CAR (x), env));
1337 env = EXTEND_ENV (names, SCM_EOL, env);
6dbd0af5 1338 x = SCM_CDR (x);
8ea46249
DH
1339 test = unmemocopy (SCM_CAR (x), env);
1340 x = SCM_CDR (x);
1341 memoized_body = SCM_CAR (x);
1342 x = SCM_CDR (x);
1343 steps = scm_reverse (unmemocopy (x, env));
1344
26d5b9b4 1345 /* build transformed binding list */
8ea46249
DH
1346 bindings = SCM_EOL;
1347 while (!SCM_NULLP (names))
6dbd0af5 1348 {
8ea46249
DH
1349 SCM name = SCM_CAR (names);
1350 SCM init = SCM_CAR (inits);
1351 SCM step = SCM_CAR (steps);
1352 step = SCM_EQ_P (step, name) ? SCM_EOL : scm_list_1 (step);
1353
1354 bindings = scm_cons (scm_cons2 (name, init, step), bindings);
1355
1356 names = SCM_CDR (names);
1357 inits = SCM_CDR (inits);
1358 steps = SCM_CDR (steps);
6dbd0af5 1359 }
8ea46249
DH
1360 z = scm_cons (test, SCM_UNSPECIFIED);
1361 ls = scm_cons2 (scm_sym_do, bindings, z);
1362
1363 x = scm_cons (SCM_BOOL_F, memoized_body);
1364 break;
1365 }
1b43d24c 1366 case SCM_BIT7 (SCM_IM_IF):
8ea46249
DH
1367 ls = z = scm_cons (scm_sym_if, SCM_UNSPECIFIED);
1368 break;
1b43d24c 1369 case SCM_BIT7 (SCM_IM_LET):
8ea46249
DH
1370 {
1371 /* format: (#@let (nk nk-1 ...) (i1 ... ik) b1 ...),
1372 * where nx is the name of a local variable, ix is an initializer for
1373 * the local variable and by are the body clauses. */
1374 SCM names, inits, bindings;
1375
1376 x = SCM_CDR (x);
1377 names = SCM_CAR (x);
1378 x = SCM_CDR (x);
1379 inits = scm_reverse (unmemocopy (SCM_CAR (x), env));
1380 env = EXTEND_ENV (names, SCM_EOL, env);
1381
1382 bindings = build_binding_list (names, inits);
1383 z = scm_cons (bindings, SCM_UNSPECIFIED);
1384 ls = scm_cons (scm_sym_let, z);
1385 break;
1386 }
1b43d24c 1387 case SCM_BIT7 (SCM_IM_LETREC):
8ea46249
DH
1388 {
1389 /* format: (#@letrec (nk nk-1 ...) (i1 ... ik) b1 ...),
1390 * where nx is the name of a local variable, ix is an initializer for
1391 * the local variable and by are the body clauses. */
1392 SCM names, inits, bindings;
1393
1394 x = SCM_CDR (x);
1395 names = SCM_CAR (x);
1396 env = EXTEND_ENV (names, SCM_EOL, env);
1397 x = SCM_CDR (x);
1398 inits = scm_reverse (unmemocopy (SCM_CAR (x), env));
1399
1400 bindings = build_binding_list (names, inits);
1401 z = scm_cons (bindings, SCM_UNSPECIFIED);
1402 ls = scm_cons (scm_sym_letrec, z);
6dbd0af5
MD
1403 break;
1404 }
1b43d24c 1405 case SCM_BIT7 (SCM_IM_LETSTAR):
6dbd0af5
MD
1406 {
1407 SCM b, y;
1408 x = SCM_CDR (x);
1409 b = SCM_CAR (x);
1410 y = SCM_EOL;
1411 if SCM_IMP (b)
1412 {
e2806c10 1413 env = EXTEND_ENV (SCM_EOL, SCM_EOL, env);
6dbd0af5
MD
1414 goto letstar;
1415 }
1416 y = z = scm_acons (SCM_CAR (b),
1417 unmemocar (
8ea46249 1418 scm_cons (unmemocopy (SCM_CADR (b), env), SCM_EOL), env),
6dbd0af5 1419 SCM_UNSPECIFIED);
e2806c10 1420 env = EXTEND_ENV (SCM_CAR (b), SCM_BOOL_F, env);
8ea46249 1421 b = SCM_CDDR (b);
6dbd0af5
MD
1422 if (SCM_IMP (b))
1423 {
1424 SCM_SETCDR (y, SCM_EOL);
2f0d1375 1425 ls = scm_cons (scm_sym_let, z = scm_cons (y, SCM_UNSPECIFIED));
6dbd0af5
MD
1426 break;
1427 }
1428 do
1429 {
a23afe53
MD
1430 SCM_SETCDR (z, scm_acons (SCM_CAR (b),
1431 unmemocar (
8ea46249 1432 scm_list_1 (unmemocopy (SCM_CADR (b), env)), env),
a23afe53
MD
1433 SCM_UNSPECIFIED));
1434 z = SCM_CDR (z);
e2806c10 1435 env = EXTEND_ENV (SCM_CAR (b), SCM_BOOL_F, env);
8ea46249 1436 b = SCM_CDDR (b);
6dbd0af5 1437 }
ff467021 1438 while (SCM_NIMP (b));
a23afe53 1439 SCM_SETCDR (z, SCM_EOL);
6dbd0af5 1440 letstar:
2f0d1375 1441 ls = scm_cons (scm_sym_letstar, z = scm_cons (y, SCM_UNSPECIFIED));
6dbd0af5
MD
1442 break;
1443 }
1b43d24c 1444 case SCM_BIT7 (SCM_IM_OR):
2f0d1375 1445 ls = z = scm_cons (scm_sym_or, SCM_UNSPECIFIED);
6dbd0af5 1446 break;
1b43d24c 1447 case SCM_BIT7 (SCM_IM_LAMBDA):
6dbd0af5 1448 x = SCM_CDR (x);
8ea46249
DH
1449 z = scm_cons (SCM_CAR (x), SCM_UNSPECIFIED);
1450 ls = scm_cons (scm_sym_lambda, z);
e2806c10 1451 env = EXTEND_ENV (SCM_CAR (x), SCM_EOL, env);
6dbd0af5 1452 break;
1b43d24c 1453 case SCM_BIT7 (SCM_IM_QUOTE):
2f0d1375 1454 ls = z = scm_cons (scm_sym_quote, SCM_UNSPECIFIED);
6dbd0af5 1455 break;
1b43d24c 1456 case SCM_BIT7 (SCM_IM_SET_X):
89efbff4 1457 ls = z = scm_cons (scm_sym_set_x, SCM_UNSPECIFIED);
6dbd0af5 1458 break;
1b43d24c 1459 case SCM_BIT7 (SCM_IM_DEFINE):
6dbd0af5
MD
1460 {
1461 SCM n;
1462 x = SCM_CDR (x);
8ea46249
DH
1463 n = SCM_CAR (x);
1464 z = scm_cons (n, SCM_UNSPECIFIED);
1465 ls = scm_cons (scm_sym_define, z);
01f11e02 1466 if (!SCM_NULLP (env))
4c5f8e8f
NJ
1467 env = scm_cons (scm_cons (scm_cons (n, SCM_CAAR (env)),
1468 SCM_CDAR (env)),
1469 SCM_CDR (env));
6dbd0af5
MD
1470 break;
1471 }
1b43d24c 1472 case SCM_BIT7 (SCM_MAKISYM (0)):
6dbd0af5
MD
1473 z = SCM_CAR (x);
1474 if (!SCM_ISYMP (z))
1475 goto unmemo;
ff467021 1476 switch (SCM_ISYMNUM (z))
6dbd0af5
MD
1477 {
1478 case (SCM_ISYMNUM (SCM_IM_APPLY)):
2f0d1375 1479 ls = z = scm_cons (scm_sym_atapply, SCM_UNSPECIFIED);
6dbd0af5
MD
1480 goto loop;
1481 case (SCM_ISYMNUM (SCM_IM_CONT)):
2f0d1375 1482 ls = z = scm_cons (scm_sym_atcall_cc, SCM_UNSPECIFIED);
6dbd0af5 1483 goto loop;
a570e93a
MD
1484 case (SCM_ISYMNUM (SCM_IM_DELAY)):
1485 ls = z = scm_cons (scm_sym_delay, SCM_UNSPECIFIED);
1486 x = SCM_CDR (x);
1487 goto loop;
28d52ebb 1488 case (SCM_ISYMNUM (SCM_IM_FUTURE)):
ebf9b47c 1489 ls = z = scm_cons (scm_sym_future, SCM_UNSPECIFIED);
28d52ebb
MD
1490 x = SCM_CDR (x);
1491 goto loop;
a513ead3
MV
1492 case (SCM_ISYMNUM (SCM_IM_CALL_WITH_VALUES)):
1493 ls = z = scm_cons (scm_sym_at_call_with_values, SCM_UNSPECIFIED);
1494 goto loop;
6dbd0af5 1495 default:
fa888178 1496 /* appease the Sun compiler god: */ ;
6dbd0af5
MD
1497 }
1498 unmemo:
1499 default:
1500 ls = z = unmemocar (scm_cons (unmemocopy (SCM_CAR (x), env),
1501 SCM_UNSPECIFIED),
1502 env);
1503 }
1504loop:
8c494e99
DH
1505 x = SCM_CDR (x);
1506 while (SCM_CONSP (x))
a23afe53 1507 {
8c494e99
DH
1508 SCM form = SCM_CAR (x);
1509 if (!SCM_ISYMP (form))
1510 {
1511 SCM copy = scm_cons (unmemocopy (form, env), SCM_UNSPECIFIED);
1512 SCM_SETCDR (z, unmemocar (copy, env));
1513 z = SCM_CDR (z);
1514 }
1515 x = SCM_CDR (x);
a23afe53
MD
1516 }
1517 SCM_SETCDR (z, x);
01f11e02 1518 if (!SCM_FALSEP (p))
6dbd0af5 1519 scm_whash_insert (scm_source_whash, ls, p);
6dbd0af5
MD
1520 return ls;
1521}
1522
1cc91f1b 1523
6dbd0af5 1524SCM
6e8d25a6 1525scm_unmemocopy (SCM x, SCM env)
6dbd0af5 1526{
01f11e02 1527 if (!SCM_NULLP (env))
6dbd0af5
MD
1528 /* Make a copy of the lowest frame to protect it from
1529 modifications by SCM_IM_DEFINE */
1530 return unmemocopy (x, scm_cons (SCM_CAR (env), SCM_CDR (env)));
1531 else
1532 return unmemocopy (x, env);
1533}
1534
1cc91f1b 1535
0f2d19dd 1536int
6e8d25a6 1537scm_badargsp (SCM formals, SCM args)
0f2d19dd 1538{
6a0f6ff3 1539 while (!SCM_NULLP (formals))
0f2d19dd 1540 {
01f11e02 1541 if (!SCM_CONSP (formals))
ff467021 1542 return 0;
6a0f6ff3 1543 if (SCM_NULLP (args))
ff467021 1544 return 1;
0f2d19dd
JB
1545 formals = SCM_CDR (formals);
1546 args = SCM_CDR (args);
1547 }
01f11e02 1548 return !SCM_NULLP (args) ? 1 : 0;
0f2d19dd 1549}
a392ee15 1550
0f2d19dd 1551
002f1a5d
MD
1552static int
1553scm_badformalsp (SCM closure, int n)
1554{
726d810a
DH
1555 SCM formals = SCM_CLOSURE_FORMALS (closure);
1556 while (!SCM_NULLP (formals))
002f1a5d 1557 {
726d810a 1558 if (!SCM_CONSP (formals))
002f1a5d
MD
1559 return 0;
1560 if (n == 0)
1561 return 1;
1562 --n;
1563 formals = SCM_CDR (formals);
1564 }
1565 return n;
1566}
0f2d19dd
JB
1567
1568\f
6dbd0af5 1569SCM
6e8d25a6 1570scm_eval_args (SCM l, SCM env, SCM proc)
6dbd0af5 1571{
680ed4a8 1572 SCM results = SCM_EOL, *lloc = &results, res;
904a077d 1573 while (SCM_CONSP (l))
6dbd0af5 1574 {
680ed4a8 1575 res = EVALCAR (l, env);
904a077d 1576
8ea46249 1577 *lloc = scm_list_1 (res);
a23afe53 1578 lloc = SCM_CDRLOC (*lloc);
6dbd0af5
MD
1579 l = SCM_CDR (l);
1580 }
22a52da1 1581 if (!SCM_NULLP (l))
904a077d 1582 scm_wrong_num_args (proc);
680ed4a8 1583 return results;
6dbd0af5 1584}
c4ac4d88 1585
9de33deb
MD
1586SCM
1587scm_eval_body (SCM code, SCM env)
1588{
1589 SCM next;
1590 again:
01f11e02
DH
1591 next = SCM_CDR (code);
1592 while (!SCM_NULLP (next))
9de33deb
MD
1593 {
1594 if (SCM_IMP (SCM_CAR (code)))
1595 {
1596 if (SCM_ISYMP (SCM_CAR (code)))
1597 {
28d52ebb 1598 scm_rec_mutex_lock (&source_mutex);
9bc4701c
MD
1599 /* check for race condition */
1600 if (SCM_ISYMP (SCM_CAR (code)))
1601 code = scm_m_expand_body (code, env);
28d52ebb 1602 scm_rec_mutex_unlock (&source_mutex);
9de33deb
MD
1603 goto again;
1604 }
1605 }
1606 else
1607 SCM_XEVAL (SCM_CAR (code), env);
1608 code = next;
01f11e02 1609 next = SCM_CDR (code);
9de33deb
MD
1610 }
1611 return SCM_XEVALCAR (code, env);
1612}
1613
c4ac4d88 1614
0f2d19dd
JB
1615#endif /* !DEVAL */
1616
6dbd0af5
MD
1617
1618/* SECTION: This code is specific for the debugging support. One
1619 * branch is read when DEVAL isn't defined, the other when DEVAL is
1620 * defined.
1621 */
1622
1623#ifndef DEVAL
1624
1625#define SCM_APPLY scm_apply
1626#define PREP_APPLY(proc, args)
1627#define ENTER_APPLY
ddea3325 1628#define RETURN(x) do { return x; } while (0)
b7ff98dd
MD
1629#ifdef STACK_CHECKING
1630#ifndef NO_CEVAL_STACK_CHECKING
1631#define EVAL_STACK_CHECKING
1632#endif
6dbd0af5
MD
1633#endif
1634
1635#else /* !DEVAL */
1636
0f2d19dd
JB
1637#undef SCM_CEVAL
1638#define SCM_CEVAL scm_deval /* Substitute all uses of scm_ceval */
1639#undef SCM_APPLY
1640#define SCM_APPLY scm_dapply
6dbd0af5
MD
1641#undef PREP_APPLY
1642#define PREP_APPLY(p, l) \
1643{ ++debug.info; debug.info->a.proc = p; debug.info->a.args = l; }
1644#undef ENTER_APPLY
1645#define ENTER_APPLY \
d3a6bc94 1646do { \
b7ff98dd 1647 SCM_SET_ARGSREADY (debug);\
5132eef0 1648 if (scm_check_apply_p && SCM_TRAPS_P)\
b7ff98dd 1649 if (SCM_APPLY_FRAME_P || (SCM_TRACE_P && PROCTRACEP (proc)))\
6dbd0af5 1650 {\
156dcb09 1651 SCM tmp, tail = SCM_BOOL(SCM_TRACED_FRAME_P (debug)); \
c6a4fbce 1652 SCM_SET_TRACED_FRAME (debug); \
d95c0b76 1653 SCM_TRAPS_P = 0;\
b7ff98dd 1654 if (SCM_CHEAPTRAPS_P)\
6dbd0af5 1655 {\
c0ab1b8d 1656 tmp = scm_make_debugobj (&debug);\
d95c0b76 1657 scm_call_3 (SCM_APPLY_FRAME_HDLR, scm_sym_apply_frame, tmp, tail);\
b6d75948 1658 }\
6dbd0af5
MD
1659 else\
1660 {\
5f144b10
GH
1661 int first;\
1662 tmp = scm_make_continuation (&first);\
1663 if (first)\
d95c0b76 1664 scm_call_3 (SCM_APPLY_FRAME_HDLR, scm_sym_apply_frame, tmp, tail);\
6dbd0af5 1665 }\
d95c0b76 1666 SCM_TRAPS_P = 1;\
6dbd0af5 1667 }\
d3a6bc94 1668} while (0)
0f2d19dd 1669#undef RETURN
ddea3325 1670#define RETURN(e) do { proc = (e); goto exit; } while (0)
b7ff98dd
MD
1671#ifdef STACK_CHECKING
1672#ifndef EVAL_STACK_CHECKING
1673#define EVAL_STACK_CHECKING
1674#endif
6dbd0af5
MD
1675#endif
1676
1677/* scm_ceval_ptr points to the currently selected evaluator.
1678 * *fixme*: Although efficiency is important here, this state variable
1679 * should probably not be a global. It should be related to the
1680 * current repl.
1681 */
1682
1cc91f1b 1683
1bbd0b84 1684SCM (*scm_ceval_ptr) (SCM x, SCM env);
0f2d19dd 1685
1646d37b 1686/* scm_last_debug_frame contains a pointer to the last debugging
6dbd0af5
MD
1687 * information stack frame. It is accessed very often from the
1688 * debugging evaluator, so it should probably not be indirectly
1689 * addressed. Better to save and restore it from the current root at
1690 * any stack swaps.
1691 */
1692
6dbd0af5
MD
1693/* scm_debug_eframe_size is the number of slots available for pseudo
1694 * stack frames at each real stack frame.
1695 */
1696
c014a02e 1697long scm_debug_eframe_size;
6dbd0af5 1698
b7ff98dd 1699int scm_debug_mode, scm_check_entry_p, scm_check_apply_p, scm_check_exit_p;
6dbd0af5 1700
c014a02e 1701long scm_eval_stack;
a74145b8 1702
92c2555f 1703scm_t_option scm_eval_opts[] = {
a74145b8 1704 { SCM_OPTION_INTEGER, "stack", 22000, "Size of thread stacks (in machine words)." }
33b97402
MD
1705};
1706
92c2555f 1707scm_t_option scm_debug_opts[] = {
b7ff98dd
MD
1708 { SCM_OPTION_BOOLEAN, "cheap", 1,
1709 "*Flyweight representation of the stack at traps." },
1710 { SCM_OPTION_BOOLEAN, "breakpoints", 0, "*Check for breakpoints." },
1711 { SCM_OPTION_BOOLEAN, "trace", 0, "*Trace mode." },
1712 { SCM_OPTION_BOOLEAN, "procnames", 1,
1713 "Record procedure names at definition." },
1714 { SCM_OPTION_BOOLEAN, "backwards", 0,
1715 "Display backtrace in anti-chronological order." },
274dc5fd 1716 { SCM_OPTION_INTEGER, "width", 79, "Maximal width of backtrace." },
4e646a03
MD
1717 { SCM_OPTION_INTEGER, "indent", 10, "Maximal indentation in backtrace." },
1718 { SCM_OPTION_INTEGER, "frames", 3,
b7ff98dd 1719 "Maximum number of tail-recursive frames in backtrace." },
4e646a03
MD
1720 { SCM_OPTION_INTEGER, "maxdepth", 1000,
1721 "Maximal number of stored backtrace frames." },
1722 { SCM_OPTION_INTEGER, "depth", 20, "Maximal length of printed backtrace." },
11f77bfc
MD
1723 { SCM_OPTION_BOOLEAN, "backtrace", 0, "Show backtrace on error." },
1724 { SCM_OPTION_BOOLEAN, "debug", 0, "Use the debugging evaluator." },
863e833b 1725 { SCM_OPTION_INTEGER, "stack", 20000, "Stack size limit (measured in words; 0 = no check)." },
d95c0b76 1726 { SCM_OPTION_SCM, "show-file-name", (unsigned long)SCM_BOOL_T, "Show file names and line numbers in backtraces when not `#f'. A value of `base' displays only base names, while `#t' displays full names."}
6dbd0af5
MD
1727};
1728
92c2555f 1729scm_t_option scm_evaluator_trap_table[] = {
b6d75948 1730 { SCM_OPTION_BOOLEAN, "traps", 0, "Enable evaluator traps." },
b7ff98dd
MD
1731 { SCM_OPTION_BOOLEAN, "enter-frame", 0, "Trap when eval enters new frame." },
1732 { SCM_OPTION_BOOLEAN, "apply-frame", 0, "Trap when entering apply." },
d95c0b76
NJ
1733 { SCM_OPTION_BOOLEAN, "exit-frame", 0, "Trap when exiting eval or apply." },
1734 { SCM_OPTION_SCM, "enter-frame-handler", (unsigned long)SCM_BOOL_F, "Handler for enter-frame traps." },
1735 { SCM_OPTION_SCM, "apply-frame-handler", (unsigned long)SCM_BOOL_F, "Handler for apply-frame traps." },
1736 { SCM_OPTION_SCM, "exit-frame-handler", (unsigned long)SCM_BOOL_F, "Handler for exit-frame traps." }
6dbd0af5
MD
1737};
1738
a1ec6916 1739SCM_DEFINE (scm_eval_options_interface, "eval-options-interface", 0, 1, 0,
1bbd0b84 1740 (SCM setting),
b3f26b14
MG
1741 "Option interface for the evaluation options. Instead of using\n"
1742 "this procedure directly, use the procedures @code{eval-enable},\n"
3939e9df 1743 "@code{eval-disable}, @code{eval-set!} and @code{eval-options}.")
1bbd0b84 1744#define FUNC_NAME s_scm_eval_options_interface
33b97402
MD
1745{
1746 SCM ans;
1747 SCM_DEFER_INTS;
1748 ans = scm_options (setting,
1749 scm_eval_opts,
1750 SCM_N_EVAL_OPTIONS,
1bbd0b84 1751 FUNC_NAME);
a74145b8 1752 scm_eval_stack = SCM_EVAL_STACK * sizeof (void *);
33b97402
MD
1753 SCM_ALLOW_INTS;
1754 return ans;
1755}
1bbd0b84 1756#undef FUNC_NAME
33b97402 1757
a1ec6916 1758SCM_DEFINE (scm_evaluator_traps, "evaluator-traps-interface", 0, 1, 0,
1bbd0b84 1759 (SCM setting),
b3f26b14 1760 "Option interface for the evaluator trap options.")
1bbd0b84 1761#define FUNC_NAME s_scm_evaluator_traps
33b97402
MD
1762{
1763 SCM ans;
1764 SCM_DEFER_INTS;
1765 ans = scm_options (setting,
1766 scm_evaluator_trap_table,
1767 SCM_N_EVALUATOR_TRAPS,
1bbd0b84 1768 FUNC_NAME);
33b97402 1769 SCM_RESET_DEBUG_MODE;
bfc69694 1770 SCM_ALLOW_INTS;
33b97402
MD
1771 return ans;
1772}
1bbd0b84 1773#undef FUNC_NAME
33b97402 1774
24933780 1775static SCM
a392ee15 1776deval_args (SCM l, SCM env, SCM proc, SCM *lloc)
0f2d19dd 1777{
680ed4a8 1778 SCM *results = lloc, res;
904a077d 1779 while (SCM_CONSP (l))
0f2d19dd 1780 {
680ed4a8 1781 res = EVALCAR (l, env);
904a077d 1782
8ea46249 1783 *lloc = scm_list_1 (res);
a23afe53 1784 lloc = SCM_CDRLOC (*lloc);
0f2d19dd
JB
1785 l = SCM_CDR (l);
1786 }
22a52da1 1787 if (!SCM_NULLP (l))
904a077d 1788 scm_wrong_num_args (proc);
680ed4a8 1789 return *results;
0f2d19dd
JB
1790}
1791
6dbd0af5
MD
1792#endif /* !DEVAL */
1793
1794
a392ee15 1795/* SECTION: This code is compiled twice.
6dbd0af5
MD
1796 */
1797
a392ee15 1798
d9d39d76 1799/* Update the toplevel environment frame ENV so that it refers to the
a392ee15 1800 * current module. */
d9d39d76
MV
1801#define UPDATE_TOPLEVEL_ENV(env) \
1802 do { \
1803 SCM p = scm_current_module_lookup_closure (); \
1804 if (p != SCM_CAR(env)) \
1805 env = scm_top_level_env (p); \
1806 } while (0)
1807
6dbd0af5 1808
a392ee15
DH
1809/* This is the evaluator. Like any real monster, it has three heads:
1810 *
1811 * scm_ceval is the non-debugging evaluator, scm_deval is the debugging
1812 * version. Both are implemented using a common code base, using the
1813 * following mechanism: SCM_CEVAL is a macro, which is either defined to
1814 * scm_ceval or scm_deval. Thus, there is no function SCM_CEVAL, but the code
1815 * for SCM_CEVAL actually compiles to either scm_ceval or scm_deval. When
1816 * SCM_CEVAL is defined to scm_ceval, it is known that the macro DEVAL is not
1817 * defined. When SCM_CEVAL is defined to scm_deval, then the macro DEVAL is
1818 * known to be defined. Thus, in SCM_CEVAL parts for the debugging evaluator
1819 * are enclosed within #ifdef DEVAL ... #endif.
1820 *
1821 * All three (scm_ceval, scm_deval and their common implementation SCM_CEVAL)
1822 * take two input parameters, x and env: x is a single expression to be
1823 * evalutated. env is the environment in which bindings are searched.
1824 *
1825 * x is known to be a cell (i. e. a pair or any other non-immediate). Since x
1826 * is a single expression, it is necessarily in a tail position. If x is just
1827 * a call to another function like in the expression (foo exp1 exp2 ...), the
1828 * realization of that call therefore _must_not_ increase stack usage (the
1829 * evaluation of exp1, exp2 etc., however, may do so). This is realized by
1830 * making extensive use of 'goto' statements within the evaluator: The gotos
1831 * replace recursive calls to SCM_CEVAL, thus re-using the same stack frame
1832 * that SCM_CEVAL was already using. If, however, x represents some form that
1833 * requires to evaluate a sequence of expressions like (begin exp1 exp2 ...),
1834 * then recursive calls to SCM_CEVAL are performed for all but the last
1835 * expression of that sequence. */
6dbd0af5 1836
0f2d19dd 1837#if 0
0f2d19dd 1838SCM
1bbd0b84 1839scm_ceval (SCM x, SCM env)
0f2d19dd
JB
1840{}
1841#endif
1cc91f1b 1842
a392ee15 1843#if 0
0f2d19dd 1844SCM
1bbd0b84 1845scm_deval (SCM x, SCM env)
0f2d19dd
JB
1846{}
1847#endif
1848
6dbd0af5 1849SCM
1bbd0b84 1850SCM_CEVAL (SCM x, SCM env)
0f2d19dd 1851{
42030fb2 1852 SCM proc, arg1;
6dbd0af5 1853#ifdef DEVAL
92c2555f
MV
1854 scm_t_debug_frame debug;
1855 scm_t_debug_info *debug_info_end;
1646d37b 1856 debug.prev = scm_last_debug_frame;
020c890c 1857 debug.status = 0;
04b6c081 1858 /*
92c2555f 1859 * The debug.vect contains twice as much scm_t_debug_info frames as the
04b6c081
MD
1860 * user has specified with (debug-set! frames <n>).
1861 *
1862 * Even frames are eval frames, odd frames are apply frames.
1863 */
92c2555f 1864 debug.vect = (scm_t_debug_info *) alloca (scm_debug_eframe_size
a392ee15 1865 * sizeof (scm_t_debug_info));
c0ab1b8d
JB
1866 debug.info = debug.vect;
1867 debug_info_end = debug.vect + scm_debug_eframe_size;
1868 scm_last_debug_frame = &debug;
6dbd0af5 1869#endif
b7ff98dd 1870#ifdef EVAL_STACK_CHECKING
6f13f9cb
MD
1871 if (scm_stack_checking_enabled_p
1872 && SCM_STACK_OVERFLOW_P ((SCM_STACKITEM *) &proc))
6dbd0af5 1873 {
b7ff98dd 1874#ifdef DEVAL
6dbd0af5
MD
1875 debug.info->e.exp = x;
1876 debug.info->e.env = env;
b7ff98dd 1877#endif
6dbd0af5
MD
1878 scm_report_stack_overflow ();
1879 }
1880#endif
6a0f6ff3 1881
6dbd0af5
MD
1882#ifdef DEVAL
1883 goto start;
1884#endif
6a0f6ff3 1885
6dbd0af5
MD
1886loop:
1887#ifdef DEVAL
b7ff98dd
MD
1888 SCM_CLEAR_ARGSREADY (debug);
1889 if (SCM_OVERFLOWP (debug))
6dbd0af5 1890 --debug.info;
04b6c081
MD
1891 /*
1892 * In theory, this should be the only place where it is necessary to
1893 * check for space in debug.vect since both eval frames and
1894 * available space are even.
1895 *
1896 * For this to be the case, however, it is necessary that primitive
1897 * special forms which jump back to `loop', `begin' or some similar
680516ba 1898 * label call PREP_APPLY.
04b6c081 1899 */
c0ab1b8d 1900 else if (++debug.info >= debug_info_end)
6dbd0af5 1901 {
b7ff98dd 1902 SCM_SET_OVERFLOW (debug);
6dbd0af5
MD
1903 debug.info -= 2;
1904 }
6a0f6ff3 1905
6dbd0af5
MD
1906start:
1907 debug.info->e.exp = x;
1908 debug.info->e.env = env;
5132eef0
DH
1909 if (scm_check_entry_p && SCM_TRAPS_P)
1910 {
bc76d628
DH
1911 if (SCM_ENTER_FRAME_P
1912 || (SCM_BREAKPOINTS_P && scm_c_source_property_breakpoint_p (x)))
5132eef0 1913 {
bc76d628
DH
1914 SCM stackrep;
1915 SCM tail = SCM_BOOL (SCM_TAILRECP (debug));
5132eef0
DH
1916 SCM_SET_TAILREC (debug);
1917 if (SCM_CHEAPTRAPS_P)
bc76d628 1918 stackrep = scm_make_debugobj (&debug);
5132eef0
DH
1919 else
1920 {
1921 int first;
1922 SCM val = scm_make_continuation (&first);
1923
1924 if (first)
bc76d628 1925 stackrep = val;
5132eef0
DH
1926 else
1927 {
1928 x = val;
1929 if (SCM_IMP (x))
1930 RETURN (x);
1931 else
1932 /* This gives the possibility for the debugger to
1933 modify the source expression before evaluation. */
1934 goto dispatch;
1935 }
1936 }
1937 SCM_TRAPS_P = 0;
1938 scm_call_4 (SCM_ENTER_FRAME_HDLR,
1939 scm_sym_enter_frame,
bc76d628 1940 stackrep,
5132eef0
DH
1941 tail,
1942 scm_unmemocopy (x, env));
1943 SCM_TRAPS_P = 1;
1944 }
1945 }
6dbd0af5 1946#endif
f8769b1d 1947dispatch:
9cb5124f 1948 SCM_TICK;
0f2d19dd
JB
1949 switch (SCM_TYP7 (x))
1950 {
28b06554 1951 case scm_tc7_symbol:
a392ee15 1952 /* Only happens when called at top level. */
0f2d19dd 1953 x = scm_cons (x, SCM_UNDEFINED);
ddea3325 1954 RETURN (*scm_lookupcar (x, env, 1));
0f2d19dd 1955
1b43d24c 1956 case SCM_BIT7 (SCM_IM_AND):
0f2d19dd 1957 x = SCM_CDR (x);
302c12b4
DH
1958 while (!SCM_NULLP (SCM_CDR (x)))
1959 {
38ace99e
DH
1960 SCM test_result = EVALCAR (x, env);
1961 if (SCM_FALSEP (test_result) || SCM_NILP (test_result))
0f2d19dd 1962 RETURN (SCM_BOOL_F);
302c12b4
DH
1963 else
1964 x = SCM_CDR (x);
1965 }
6dbd0af5 1966 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
0f2d19dd
JB
1967 goto carloop;
1968
1b43d24c 1969 case SCM_BIT7 (SCM_IM_BEGIN):
e050d4f8
DH
1970 x = SCM_CDR (x);
1971 if (SCM_NULLP (x))
b8113bc8
MV
1972 RETURN (SCM_UNSPECIFIED);
1973
6dbd0af5 1974 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
0f2d19dd
JB
1975
1976 begin:
4163eb72
MV
1977 /* If we are on toplevel with a lookup closure, we need to sync
1978 with the current module. */
22a52da1 1979 if (SCM_CONSP (env) && !SCM_CONSP (SCM_CAR (env)))
4163eb72 1980 {
d9d39d76 1981 UPDATE_TOPLEVEL_ENV (env);
302c12b4 1982 while (!SCM_NULLP (SCM_CDR (x)))
4163eb72 1983 {
5280aaca 1984 EVALCAR (x, env);
d9d39d76 1985 UPDATE_TOPLEVEL_ENV (env);
302c12b4 1986 x = SCM_CDR (x);
4163eb72 1987 }
5280aaca 1988 goto carloop;
4163eb72
MV
1989 }
1990 else
5280aaca
MV
1991 goto nontoplevel_begin;
1992
5280aaca 1993 nontoplevel_begin:
302c12b4 1994 while (!SCM_NULLP (SCM_CDR (x)))
0f2d19dd 1995 {
6a0f6ff3
DH
1996 SCM form = SCM_CAR (x);
1997 if (SCM_IMP (form))
26d5b9b4 1998 {
6a0f6ff3 1999 if (SCM_ISYMP (form))
26d5b9b4 2000 {
28d52ebb 2001 scm_rec_mutex_lock (&source_mutex);
9bc4701c
MD
2002 /* check for race condition */
2003 if (SCM_ISYMP (SCM_CAR (x)))
2004 x = scm_m_expand_body (x, env);
28d52ebb 2005 scm_rec_mutex_unlock (&source_mutex);
5280aaca 2006 goto nontoplevel_begin;
26d5b9b4 2007 }
4163eb72 2008 else
6a0f6ff3 2009 SCM_VALIDATE_NON_EMPTY_COMBINATION (form);
26d5b9b4 2010 }
5280aaca 2011 else
6a0f6ff3 2012 SCM_CEVAL (form, env);
302c12b4 2013 x = SCM_CDR (x);
0f2d19dd 2014 }
5280aaca 2015
6a0f6ff3
DH
2016 carloop:
2017 {
2018 /* scm_eval last form in list */
2019 SCM last_form = SCM_CAR (x);
0f2d19dd 2020
6a0f6ff3
DH
2021 if (SCM_CONSP (last_form))
2022 {
2023 /* This is by far the most frequent case. */
2024 x = last_form;
2025 goto loop; /* tail recurse */
2026 }
2027 else if (SCM_IMP (last_form))
2028 RETURN (SCM_EVALIM (last_form, env));
2029 else if (SCM_VARIABLEP (last_form))
2030 RETURN (SCM_VARIABLE_REF (last_form));
2031 else if (SCM_SYMBOLP (last_form))
2032 RETURN (*scm_lookupcar (x, env, 1));
2033 else
2034 RETURN (last_form);
2035 }
0f2d19dd
JB
2036
2037
1b43d24c 2038 case SCM_BIT7 (SCM_IM_CASE):
0f2d19dd 2039 x = SCM_CDR (x);
6a0f6ff3
DH
2040 {
2041 SCM key = EVALCAR (x, env);
2042 x = SCM_CDR (x);
2043 while (!SCM_NULLP (x))
2044 {
2045 SCM clause = SCM_CAR (x);
2046 SCM labels = SCM_CAR (clause);
2047 if (SCM_EQ_P (labels, scm_sym_else))
2048 {
2049 x = SCM_CDR (clause);
2050 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2051 goto begin;
2052 }
2053 while (!SCM_NULLP (labels))
2054 {
2055 SCM label = SCM_CAR (labels);
2056 if (SCM_EQ_P (label, key) || !SCM_FALSEP (scm_eqv_p (label, key)))
2057 {
2058 x = SCM_CDR (clause);
2059 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2060 goto begin;
2061 }
2062 labels = SCM_CDR (labels);
2063 }
2064 x = SCM_CDR (x);
2065 }
2066 }
ddea3325 2067 RETURN (SCM_UNSPECIFIED);
0f2d19dd
JB
2068
2069
1b43d24c 2070 case SCM_BIT7 (SCM_IM_COND):
8ea46249
DH
2071 x = SCM_CDR (x);
2072 while (!SCM_NULLP (x))
0f2d19dd 2073 {
e5cb71a0
DH
2074 SCM clause = SCM_CAR (x);
2075 if (SCM_EQ_P (SCM_CAR (clause), scm_sym_else))
8ea46249 2076 {
e5cb71a0 2077 x = SCM_CDR (clause);
8ea46249
DH
2078 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2079 goto begin;
2080 }
e5cb71a0 2081 else
0f2d19dd 2082 {
dff98306
DH
2083 arg1 = EVALCAR (clause, env);
2084 if (!SCM_FALSEP (arg1) && !SCM_NILP (arg1))
6dbd0af5 2085 {
e5cb71a0
DH
2086 x = SCM_CDR (clause);
2087 if (SCM_NULLP (x))
dff98306 2088 RETURN (arg1);
e5cb71a0
DH
2089 else if (!SCM_EQ_P (SCM_CAR (x), scm_sym_arrow))
2090 {
2091 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2092 goto begin;
2093 }
2094 else
2095 {
2096 proc = SCM_CDR (x);
2097 proc = EVALCAR (proc, env);
2098 SCM_ASRTGO (!SCM_IMP (proc), badfun);
dff98306 2099 PREP_APPLY (proc, scm_list_1 (arg1));
e5cb71a0
DH
2100 ENTER_APPLY;
2101 if (SCM_CLOSUREP(proc) && scm_badformalsp (proc, 1))
2102 goto umwrongnumargs;
2103 else
2104 goto evap1;
2105 }
6dbd0af5 2106 }
e5cb71a0 2107 x = SCM_CDR (x);
0f2d19dd
JB
2108 }
2109 }
ddea3325 2110 RETURN (SCM_UNSPECIFIED);
0f2d19dd
JB
2111
2112
1b43d24c 2113 case SCM_BIT7 (SCM_IM_DO):
0f2d19dd 2114 x = SCM_CDR (x);
e5cb71a0
DH
2115 {
2116 /* Compute the initialization values and the initial environment. */
2117 SCM init_forms = SCM_CADR (x);
2118 SCM init_values = SCM_EOL;
2119 while (!SCM_NULLP (init_forms))
2120 {
2121 init_values = scm_cons (EVALCAR (init_forms, env), init_values);
2122 init_forms = SCM_CDR (init_forms);
2123 }
2124 env = EXTEND_ENV (SCM_CAR (x), init_values, env);
2125 }
8ea46249 2126 x = SCM_CDDR (x);
e5cb71a0
DH
2127 {
2128 SCM test_form = SCM_CAR (x);
2129 SCM body_forms = SCM_CADR (x);
2130 SCM step_forms = SCM_CDDR (x);
2131
2132 SCM test_result = EVALCAR (test_form, env);
2133
2134 while (SCM_FALSEP (test_result) || SCM_NILP (test_result))
2135 {
0f2d19dd 2136 {
e5cb71a0
DH
2137 /* Evaluate body forms. */
2138 SCM temp_forms;
2139 for (temp_forms = body_forms;
2140 !SCM_NULLP (temp_forms);
2141 temp_forms = SCM_CDR (temp_forms))
2142 {
2143 SCM form = SCM_CAR (temp_forms);
2144 /* Dirk:FIXME: We only need to eval forms, that may have a
2145 * side effect here. This is only true for forms that start
2146 * with a pair. All others are just constants. However,
2147 * since in the common case there is no constant expression
2148 * in a body of a do form, we just check for immediates here
2149 * and have SCM_CEVAL take care of other cases. In the long
2150 * run it would make sense to get rid of this test and have
2151 * the macro transformer of 'do' eliminate all forms that
2152 * have no sideeffect. */
2153 if (!SCM_IMP (form))
2154 SCM_CEVAL (form, env);
2155 }
0f2d19dd 2156 }
e5cb71a0
DH
2157
2158 {
2159 /* Evaluate the step expressions. */
2160 SCM temp_forms;
2161 SCM step_values = SCM_EOL;
2162 for (temp_forms = step_forms;
2163 !SCM_NULLP (temp_forms);
2164 temp_forms = SCM_CDR (temp_forms))
2165 {
2166 SCM value = EVALCAR (temp_forms, env);
2167 step_values = scm_cons (value, step_values);
2168 }
2169 env = EXTEND_ENV (SCM_CAAR (env), step_values, SCM_CDR (env));
2170 }
2171
2172 test_result = EVALCAR (test_form, env);
2173 }
2174 }
2175 x = SCM_CDAR (x);
0f2d19dd 2176 if (SCM_NULLP (x))
6dbd0af5
MD
2177 RETURN (SCM_UNSPECIFIED);
2178 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
5280aaca 2179 goto nontoplevel_begin;
0f2d19dd
JB
2180
2181
1b43d24c 2182 case SCM_BIT7 (SCM_IM_IF):
0f2d19dd 2183 x = SCM_CDR (x);
38ace99e
DH
2184 {
2185 SCM test_result = EVALCAR (x, env);
2186 if (!SCM_FALSEP (test_result) && !SCM_NILP (test_result))
2187 x = SCM_CDR (x);
2188 else
2189 {
2190 x = SCM_CDDR (x);
2191 if (SCM_NULLP (x))
2192 RETURN (SCM_UNSPECIFIED);
2193 }
2194 }
6dbd0af5 2195 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
0f2d19dd
JB
2196 goto carloop;
2197
2198
1b43d24c 2199 case SCM_BIT7 (SCM_IM_LET):
0f2d19dd 2200 x = SCM_CDR (x);
38ace99e
DH
2201 {
2202 SCM init_forms = SCM_CADR (x);
2203 SCM init_values = SCM_EOL;
2204 do
2205 {
2206 init_values = scm_cons (EVALCAR (init_forms, env), init_values);
2207 init_forms = SCM_CDR (init_forms);
2208 }
2209 while (!SCM_NULLP (init_forms));
2210 env = EXTEND_ENV (SCM_CAR (x), init_values, env);
2211 }
e050d4f8
DH
2212 x = SCM_CDDR (x);
2213 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2214 goto nontoplevel_begin;
0f2d19dd
JB
2215
2216
1b43d24c 2217 case SCM_BIT7 (SCM_IM_LETREC):
0f2d19dd 2218 x = SCM_CDR (x);
a44a9715 2219 env = EXTEND_ENV (SCM_CAR (x), undefineds, env);
0f2d19dd 2220 x = SCM_CDR (x);
38ace99e
DH
2221 {
2222 SCM init_forms = SCM_CAR (x);
2223 SCM init_values = SCM_EOL;
2224 do
2225 {
2226 init_values = scm_cons (EVALCAR (init_forms, env), init_values);
2227 init_forms = SCM_CDR (init_forms);
2228 }
2229 while (!SCM_NULLP (init_forms));
2230 SCM_SETCDR (SCM_CAR (env), init_values);
2231 }
e050d4f8
DH
2232 x = SCM_CDR (x);
2233 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2234 goto nontoplevel_begin;
0f2d19dd
JB
2235
2236
1b43d24c 2237 case SCM_BIT7 (SCM_IM_LETSTAR):
0f2d19dd 2238 x = SCM_CDR (x);
302c12b4
DH
2239 {
2240 SCM bindings = SCM_CAR (x);
2241 if (SCM_NULLP (bindings))
e2806c10 2242 env = EXTEND_ENV (SCM_EOL, SCM_EOL, env);
302c12b4
DH
2243 else
2244 {
2245 do
2246 {
2247 SCM name = SCM_CAR (bindings);
2248 SCM init = SCM_CDR (bindings);
2249 env = EXTEND_ENV (name, EVALCAR (init, env), env);
2250 bindings = SCM_CDR (init);
2251 }
2252 while (!SCM_NULLP (bindings));
2253 }
2254 }
e050d4f8
DH
2255 x = SCM_CDR (x);
2256 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2257 goto nontoplevel_begin;
0f2d19dd 2258
302c12b4 2259
1b43d24c 2260 case SCM_BIT7 (SCM_IM_OR):
0f2d19dd 2261 x = SCM_CDR (x);
302c12b4 2262 while (!SCM_NULLP (SCM_CDR (x)))
0f2d19dd 2263 {
302c12b4 2264 SCM val = EVALCAR (x, env);
c96d76b8 2265 if (!SCM_FALSEP (val) && !SCM_NILP (val))
302c12b4
DH
2266 RETURN (val);
2267 else
2268 x = SCM_CDR (x);
0f2d19dd 2269 }
6dbd0af5 2270 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
0f2d19dd
JB
2271 goto carloop;
2272
2273
1b43d24c 2274 case SCM_BIT7 (SCM_IM_LAMBDA):
0f2d19dd
JB
2275 RETURN (scm_closure (SCM_CDR (x), env));
2276
2277
1b43d24c 2278 case SCM_BIT7 (SCM_IM_QUOTE):
8ea46249 2279 RETURN (SCM_CADR (x));
0f2d19dd
JB
2280
2281
1b43d24c 2282 case SCM_BIT7 (SCM_IM_SET_X):
0f2d19dd 2283 x = SCM_CDR (x);
38ace99e
DH
2284 {
2285 SCM *location;
2286 SCM variable = SCM_CAR (x);
e050d4f8 2287 if (SCM_ILOCP (variable))
38ace99e 2288 location = scm_ilookup (variable, env);
3063e30a 2289 else if (SCM_VARIABLEP (variable))
e050d4f8 2290 location = SCM_VARIABLE_LOC (variable);
38ace99e
DH
2291 else /* (SCM_SYMBOLP (variable)) is known to be true */
2292 location = scm_lookupcar (x, env, 1);
2293 x = SCM_CDR (x);
2294 *location = EVALCAR (x, env);
2295 }
0f2d19dd 2296 RETURN (SCM_UNSPECIFIED);
0f2d19dd
JB
2297
2298
1b43d24c 2299 case SCM_BIT7 (SCM_IM_DEFINE): /* only for internal defines */
26d5b9b4
MD
2300 scm_misc_error (NULL, "Bad define placement", SCM_EOL);
2301
38ace99e 2302
0f2d19dd 2303 /* new syntactic forms go here. */
1b43d24c 2304 case SCM_BIT7 (SCM_MAKISYM (0)):
0f2d19dd
JB
2305 proc = SCM_CAR (x);
2306 SCM_ASRTGO (SCM_ISYMP (proc), badfun);
a392ee15 2307 switch (SCM_ISYMNUM (proc))
0f2d19dd 2308 {
3f04400d
DH
2309
2310
0f2d19dd
JB
2311 case (SCM_ISYMNUM (SCM_IM_APPLY)):
2312 proc = SCM_CDR (x);
2313 proc = EVALCAR (proc, env);
3f04400d 2314 SCM_ASRTGO (!SCM_IMP (proc), badfun);
0f2d19dd
JB
2315 if (SCM_CLOSUREP (proc))
2316 {
6dbd0af5 2317 PREP_APPLY (proc, SCM_EOL);
dff98306
DH
2318 arg1 = SCM_CDDR (x);
2319 arg1 = EVALCAR (arg1, env);
a513ead3
MV
2320 apply_closure:
2321 /* Go here to tail-call a closure. PROC is the closure
dff98306
DH
2322 and ARG1 is the list of arguments. Do not forget to
2323 call PREP_APPLY. */
3f04400d
DH
2324 {
2325 SCM formals = SCM_CLOSURE_FORMALS (proc);
6dbd0af5 2326#ifdef DEVAL
dff98306 2327 debug.info->a.args = arg1;
6dbd0af5 2328#endif
dff98306 2329 if (scm_badargsp (formals, arg1))
ab1f1094 2330 scm_wrong_num_args (proc);
3f04400d
DH
2331 ENTER_APPLY;
2332 /* Copy argument list */
dff98306 2333 if (SCM_NULL_OR_NIL_P (arg1))
3f04400d
DH
2334 env = EXTEND_ENV (formals, SCM_EOL, SCM_ENV (proc));
2335 else
2336 {
dff98306 2337 SCM args = scm_list_1 (SCM_CAR (arg1));
3f04400d 2338 SCM tail = args;
dff98306
DH
2339 arg1 = SCM_CDR (arg1);
2340 while (!SCM_NULL_OR_NIL_P (arg1))
3f04400d 2341 {
dff98306 2342 SCM new_tail = scm_list_1 (SCM_CAR (arg1));
3f04400d
DH
2343 SCM_SETCDR (tail, new_tail);
2344 tail = new_tail;
dff98306 2345 arg1 = SCM_CDR (arg1);
3f04400d
DH
2346 }
2347 env = EXTEND_ENV (formals, args, SCM_ENV (proc));
2348 }
1609038c 2349
3f04400d
DH
2350 x = SCM_CLOSURE_BODY (proc);
2351 goto nontoplevel_begin;
2352 }
0f2d19dd 2353 }
3f04400d
DH
2354 else
2355 {
a44a9715 2356 proc = f_apply;
3f04400d
DH
2357 goto evapply;
2358 }
2359
0f2d19dd
JB
2360
2361 case (SCM_ISYMNUM (SCM_IM_CONT)):
5f144b10
GH
2362 {
2363 int first;
2364 SCM val = scm_make_continuation (&first);
2365
e050d4f8 2366 if (!first)
5f144b10 2367 RETURN (val);
e050d4f8
DH
2368 else
2369 {
2370 arg1 = val;
2371 proc = SCM_CDR (x);
2372 proc = scm_eval_car (proc, env);
2373 SCM_ASRTGO (SCM_NIMP (proc), badfun);
2374 PREP_APPLY (proc, scm_list_1 (arg1));
2375 ENTER_APPLY;
2376 if (SCM_CLOSUREP(proc) && scm_badformalsp (proc, 1))
2377 goto umwrongnumargs;
2378 goto evap1;
2379 }
5f144b10 2380 }
e050d4f8 2381
0f2d19dd 2382
a570e93a 2383 case (SCM_ISYMNUM (SCM_IM_DELAY)):
ddea3325 2384 RETURN (scm_makprom (scm_closure (SCM_CDR (x), env)));
a570e93a 2385
e050d4f8 2386
28d52ebb
MD
2387 case (SCM_ISYMNUM (SCM_IM_FUTURE)):
2388 RETURN (scm_i_make_future (scm_closure (SCM_CDR (x), env)));
2389
2390
89efbff4 2391 case (SCM_ISYMNUM (SCM_IM_DISPATCH)):
61364ba6 2392 {
f12745b6 2393 /* If not done yet, evaluate the operand forms. The result is a
dff98306 2394 * list of arguments stored in arg1, which is used to perform the
f12745b6
DH
2395 * function dispatch. */
2396 SCM operand_forms = SCM_CADR (x);
2397 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2398 if (SCM_ILOCP (operand_forms))
dff98306 2399 arg1 = *scm_ilookup (operand_forms, env);
f12745b6 2400 else if (SCM_VARIABLEP (operand_forms))
dff98306 2401 arg1 = SCM_VARIABLE_REF (operand_forms);
f12745b6 2402 else if (!SCM_CONSP (operand_forms))
dff98306 2403 arg1 = *scm_lookupcar (SCM_CDR (x), env, 1);
61364ba6
MD
2404 else
2405 {
dff98306 2406 SCM tail = arg1 = scm_list_1 (EVALCAR (operand_forms, env));
f12745b6
DH
2407 operand_forms = SCM_CDR (operand_forms);
2408 while (!SCM_NULLP (operand_forms))
2409 {
2410 SCM new_tail = scm_list_1 (EVALCAR (operand_forms, env));
2411 SCM_SETCDR (tail, new_tail);
2412 tail = new_tail;
2413 operand_forms = SCM_CDR (operand_forms);
2414 }
2415 }
2416 }
2417
2418 /* The type dispatch code is duplicated below
2419 * (c.f. objects.c:scm_mcache_compute_cmethod) since that
2420 * cuts down execution time for type dispatch to 50%. */
dff98306 2421 type_dispatch: /* inputs: x, arg1 */
f12745b6
DH
2422 /* Type dispatch means to determine from the types of the function
2423 * arguments (i. e. the 'signature' of the call), which method from
2424 * a generic function is to be called. This process of selecting
2425 * the right method takes some time. To speed it up, guile uses
2426 * caching: Together with the macro call to dispatch the signatures
2427 * of some previous calls to that generic function from the same
2428 * place are stored (in the code!) in a cache that we call the
2429 * 'method cache'. This is done since it is likely, that
2430 * consecutive calls to dispatch from that position in the code will
2431 * have the same signature. Thus, the type dispatch works as
2432 * follows: First, determine a hash value from the signature of the
2433 * actual arguments. Second, use this hash value as an index to
2434 * find that same signature in the method cache stored at this
2435 * position in the code. If found, you have also found the
2436 * corresponding method that belongs to that signature. If the
2437 * signature is not found in the method cache, you have to perform a
2438 * full search over all signatures stored with the generic
2439 * function. */
2440 {
2441 unsigned long int specializers;
2442 unsigned long int hash_value;
2443 unsigned long int cache_end_pos;
2444 unsigned long int mask;
2445 SCM method_cache;
2446
2447 {
2448 SCM z = SCM_CDDR (x);
2449 SCM tmp = SCM_CADR (z);
2450 specializers = SCM_INUM (SCM_CAR (z));
2451
2452 /* Compute a hash value for searching the method cache. There
2453 * are two variants for computing the hash value, a (rather)
2454 * complicated one, and a simple one. For the complicated one
2455 * explained below, tmp holds a number that is used in the
2456 * computation. */
2457 if (SCM_INUMP (tmp))
2458 {
2459 /* Use the signature of the actual arguments to determine
2460 * the hash value. This is done as follows: Each class has
2461 * an array of random numbers, that are determined when the
2462 * class is created. The integer 'hashset' is an index into
2463 * that array of random numbers. Now, from all classes that
2464 * are part of the signature of the actual arguments, the
2465 * random numbers at index 'hashset' are taken and summed
2466 * up, giving the hash value. The value of 'hashset' is
2467 * stored at the call to dispatch. This allows to have
2468 * different 'formulas' for calculating the hash value at
2469 * different places where dispatch is called. This allows
2470 * to optimize the hash formula at every individual place
2471 * where dispatch is called, such that hopefully the hash
2472 * value that is computed will directly point to the right
2473 * method in the method cache. */
2474 unsigned long int hashset = SCM_INUM (tmp);
2475 unsigned long int counter = specializers + 1;
dff98306 2476 SCM tmp_arg = arg1;
f12745b6
DH
2477 hash_value = 0;
2478 while (!SCM_NULLP (tmp_arg) && counter != 0)
61364ba6 2479 {
f12745b6
DH
2480 SCM class = scm_class_of (SCM_CAR (tmp_arg));
2481 hash_value += SCM_INSTANCE_HASH (class, hashset);
2482 tmp_arg = SCM_CDR (tmp_arg);
2483 counter--;
61364ba6 2484 }
f12745b6
DH
2485 z = SCM_CDDR (z);
2486 method_cache = SCM_CADR (z);
2487 mask = SCM_INUM (SCM_CAR (z));
2488 hash_value &= mask;
2489 cache_end_pos = hash_value;
2490 }
2491 else
2492 {
2493 /* This method of determining the hash value is much
2494 * simpler: Set the hash value to zero and just perform a
2495 * linear search through the method cache. */
2496 method_cache = tmp;
2497 mask = (unsigned long int) ((long) -1);
2498 hash_value = 0;
2499 cache_end_pos = SCM_VECTOR_LENGTH (method_cache);
2500 }
2501 }
61364ba6 2502
f12745b6
DH
2503 {
2504 /* Search the method cache for a method with a matching
2505 * signature. Start the search at position 'hash_value'. The
2506 * hashing implementation uses linear probing for conflict
2507 * resolution, that is, if the signature in question is not
2508 * found at the starting index in the hash table, the next table
2509 * entry is tried, and so on, until in the worst case the whole
2510 * cache has been searched, but still the signature has not been
2511 * found. */
2512 SCM z;
2513 do
2514 {
dff98306 2515 SCM args = arg1; /* list of arguments */
f12745b6
DH
2516 z = SCM_VELTS (method_cache)[hash_value];
2517 while (!SCM_NULLP (args))
61364ba6
MD
2518 {
2519 /* More arguments than specifiers => CLASS != ENV */
f12745b6
DH
2520 SCM class_of_arg = scm_class_of (SCM_CAR (args));
2521 if (!SCM_EQ_P (class_of_arg, SCM_CAR (z)))
61364ba6 2522 goto next_method;
f12745b6 2523 args = SCM_CDR (args);
61364ba6
MD
2524 z = SCM_CDR (z);
2525 }
f12745b6
DH
2526 /* Fewer arguments than specifiers => CAR != ENV */
2527 if (SCM_NULLP (SCM_CAR (z)) || SCM_CONSP (SCM_CAR (z)))
2528 goto apply_cmethod;
2529 next_method:
2530 hash_value = (hash_value + 1) & mask;
2531 } while (hash_value != cache_end_pos);
2532
2533 /* No appropriate method was found in the cache. */
dff98306 2534 z = scm_memoize_method (x, arg1);
f12745b6 2535
dff98306 2536 apply_cmethod: /* inputs: z, arg1 */
f12745b6
DH
2537 {
2538 SCM formals = SCM_CMETHOD_FORMALS (z);
dff98306 2539 env = EXTEND_ENV (formals, arg1, SCM_CMETHOD_ENV (z));
f12745b6
DH
2540 x = SCM_CMETHOD_BODY (z);
2541 goto nontoplevel_begin;
2542 }
2543 }
61364ba6 2544 }
73b64342 2545
1d15ecd3 2546
ca4be6ea
MD
2547 case (SCM_ISYMNUM (SCM_IM_SLOT_REF)):
2548 x = SCM_CDR (x);
1d15ecd3
DH
2549 {
2550 SCM instance = EVALCAR (x, env);
2551 unsigned long int slot = SCM_INUM (SCM_CADR (x));
2552 RETURN (SCM_PACK (SCM_STRUCT_DATA (instance) [slot]));
2553 }
2554
2555
ca4be6ea
MD
2556 case (SCM_ISYMNUM (SCM_IM_SLOT_SET_X)):
2557 x = SCM_CDR (x);
1d15ecd3
DH
2558 {
2559 SCM instance = EVALCAR (x, env);
2560 unsigned long int slot = SCM_INUM (SCM_CADR (x));
2561 SCM value = EVALCAR (SCM_CDDR (x), env);
2562 SCM_STRUCT_DATA (instance) [slot] = SCM_UNPACK (value);
2563 RETURN (SCM_UNSPECIFIED);
2564 }
2565
c96d76b8 2566
22721140 2567#if SCM_ENABLE_ELISP
ca4be6ea 2568
73b64342 2569 case (SCM_ISYMNUM (SCM_IM_NIL_COND)):
1d15ecd3
DH
2570 {
2571 SCM test_form = SCM_CDR (x);
2572 x = SCM_CDR (test_form);
2573 while (!SCM_NULL_OR_NIL_P (x))
2574 {
2575 SCM test_result = EVALCAR (test_form, env);
2576 if (!(SCM_FALSEP (test_result)
2577 || SCM_NULL_OR_NIL_P (test_result)))
2578 {
2579 if (SCM_EQ_P (SCM_CAR (x), SCM_UNSPECIFIED))
2580 RETURN (test_result);
2581 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2582 goto carloop;
2583 }
2584 else
2585 {
2586 test_form = SCM_CDR (x);
2587 x = SCM_CDR (test_form);
2588 }
2589 }
2590 x = test_form;
2591 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2592 goto carloop;
2593 }
73b64342 2594
c96d76b8 2595#endif /* SCM_ENABLE_ELISP */
73b64342
MD
2596
2597 case (SCM_ISYMNUM (SCM_IM_BIND)):
2e171178
MV
2598 {
2599 SCM vars, exps, vals;
73b64342 2600
2e171178
MV
2601 x = SCM_CDR (x);
2602 vars = SCM_CAAR (x);
2603 exps = SCM_CDAR (x);
2604
2605 vals = SCM_EOL;
2606
2607 while (SCM_NIMP (exps))
2608 {
2609 vals = scm_cons (EVALCAR (exps, env), vals);
2610 exps = SCM_CDR (exps);
2611 }
2612
2613 scm_swap_bindings (vars, vals);
2614 scm_dynwinds = scm_acons (vars, vals, scm_dynwinds);
1d15ecd3
DH
2615
2616 /* Ignore all but the last evaluation result. */
2617 for (x = SCM_CDR (x); !SCM_NULLP (SCM_CDR (x)); x = SCM_CDR (x))
2e171178 2618 {
1d15ecd3
DH
2619 if (SCM_CONSP (SCM_CAR (x)))
2620 SCM_CEVAL (SCM_CAR (x), env);
2e171178
MV
2621 }
2622 proc = EVALCAR (x, env);
73b64342 2623
2e171178
MV
2624 scm_dynwinds = SCM_CDR (scm_dynwinds);
2625 scm_swap_bindings (vars, vals);
73b64342 2626
ddea3325 2627 RETURN (proc);
2e171178 2628 }
c96d76b8 2629
1d15ecd3 2630
a513ead3
MV
2631 case (SCM_ISYMNUM (SCM_IM_CALL_WITH_VALUES)):
2632 {
2633 proc = SCM_CDR (x);
2634 x = EVALCAR (proc, env);
2635 proc = SCM_CDR (proc);
2636 proc = EVALCAR (proc, env);
dff98306
DH
2637 arg1 = SCM_APPLY (x, SCM_EOL, SCM_EOL);
2638 if (SCM_VALUESP (arg1))
2639 arg1 = scm_struct_ref (arg1, SCM_INUM0);
a513ead3 2640 else
dff98306 2641 arg1 = scm_list_1 (arg1);
a513ead3
MV
2642 if (SCM_CLOSUREP (proc))
2643 {
dff98306 2644 PREP_APPLY (proc, arg1);
a513ead3
MV
2645 goto apply_closure;
2646 }
dff98306 2647 return SCM_APPLY (proc, arg1, SCM_EOL);
a513ead3
MV
2648 }
2649
b7798e10 2650
0f2d19dd
JB
2651 default:
2652 goto badfun;
2653 }
2654
2655 default:
2656 proc = x;
2657 badfun:
1afff620 2658 scm_misc_error (NULL, "Wrong type to apply: ~S", scm_list_1 (proc));
0f2d19dd
JB
2659 case scm_tc7_vector:
2660 case scm_tc7_wvect:
22721140 2661#if SCM_HAVE_ARRAYS
0f2d19dd
JB
2662 case scm_tc7_bvect:
2663 case scm_tc7_byvect:
2664 case scm_tc7_svect:
2665 case scm_tc7_ivect:
2666 case scm_tc7_uvect:
2667 case scm_tc7_fvect:
2668 case scm_tc7_dvect:
2669 case scm_tc7_cvect:
3d05f2e0 2670#if SCM_SIZEOF_LONG_LONG != 0
0f2d19dd 2671 case scm_tc7_llvect:
afe5177e 2672#endif
0f2d19dd
JB
2673#endif
2674 case scm_tc7_string:
0f2d19dd
JB
2675 case scm_tc7_smob:
2676 case scm_tcs_closures:
224822be 2677 case scm_tc7_cclo:
89efbff4 2678 case scm_tc7_pws:
0f2d19dd 2679 case scm_tcs_subrs:
904a077d 2680 case scm_tcs_struct:
0f2d19dd
JB
2681 RETURN (x);
2682
d22a0ea1 2683 case scm_tc7_variable:
a130e982 2684 RETURN (SCM_VARIABLE_REF(x));
d22a0ea1 2685
1b43d24c 2686 case SCM_BIT7 (SCM_ILOC00):
0f2d19dd
JB
2687 proc = *scm_ilookup (SCM_CAR (x), env);
2688 SCM_ASRTGO (SCM_NIMP (proc), badfun);
0f2d19dd 2689 goto checkargs;
b7798e10 2690
0f2d19dd 2691 case scm_tcs_cons_nimcar:
e050d4f8 2692 if (SCM_SYMBOLP (SCM_CAR (x)))
0f2d19dd 2693 {
e050d4f8 2694 SCM orig_sym = SCM_CAR (x);
b7798e10
DH
2695 {
2696 SCM *location = scm_lookupcar1 (x, env, 1);
2697 if (location == NULL)
2698 {
2699 /* we have lost the race, start again. */
2700 goto dispatch;
2701 }
2702 proc = *location;
2703 }
f8769b1d 2704
0f2d19dd
JB
2705 if (SCM_IMP (proc))
2706 {
86d31dfe
MV
2707 SCM_SETCAR (x, orig_sym); /* Undo memoizing effect of
2708 lookupcar */
0f2d19dd
JB
2709 goto badfun;
2710 }
22a52da1 2711 if (SCM_MACROP (proc))
0f2d19dd 2712 {
86d31dfe
MV
2713 SCM_SETCAR (x, orig_sym); /* Undo memoizing effect of
2714 lookupcar */
e050d4f8 2715 handle_a_macro: /* inputs: x, env, proc */
368bf056 2716#ifdef DEVAL
7c354052
MD
2717 /* Set a flag during macro expansion so that macro
2718 application frames can be deleted from the backtrace. */
2719 SCM_SET_MACROEXP (debug);
368bf056 2720#endif
dff98306 2721 arg1 = SCM_APPLY (SCM_MACRO_CODE (proc), x,
f8769b1d
MV
2722 scm_cons (env, scm_listofnull));
2723
7c354052
MD
2724#ifdef DEVAL
2725 SCM_CLEAR_MACROEXP (debug);
2726#endif
22a52da1 2727 switch (SCM_MACRO_TYPE (proc))
0f2d19dd
JB
2728 {
2729 case 2:
dff98306
DH
2730 if (scm_ilength (arg1) <= 0)
2731 arg1 = scm_list_2 (SCM_IM_BEGIN, arg1);
6dbd0af5 2732#ifdef DEVAL
22a52da1 2733 if (!SCM_CLOSUREP (SCM_MACRO_CODE (proc)))
6dbd0af5 2734 {
6dbd0af5 2735 SCM_DEFER_INTS;
dff98306
DH
2736 SCM_SETCAR (x, SCM_CAR (arg1));
2737 SCM_SETCDR (x, SCM_CDR (arg1));
6dbd0af5
MD
2738 SCM_ALLOW_INTS;
2739 goto dispatch;
2740 }
2741 /* Prevent memoizing of debug info expression. */
6203706f
MD
2742 debug.info->e.exp = scm_cons_source (debug.info->e.exp,
2743 SCM_CAR (x),
2744 SCM_CDR (x));
6dbd0af5 2745#endif
0f2d19dd 2746 SCM_DEFER_INTS;
dff98306
DH
2747 SCM_SETCAR (x, SCM_CAR (arg1));
2748 SCM_SETCDR (x, SCM_CDR (arg1));
0f2d19dd 2749 SCM_ALLOW_INTS;
680516ba
DH
2750 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2751 goto loop;
3063e30a 2752#if SCM_ENABLE_DEPRECATED == 1
0f2d19dd 2753 case 1:
680516ba
DH
2754 x = arg1;
2755 if (SCM_NIMP (x))
2756 {
2757 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
2758 goto loop;
2759 }
2760 else
2761 RETURN (arg1);
3063e30a 2762#endif
0f2d19dd 2763 case 0:
dff98306 2764 RETURN (arg1);
0f2d19dd
JB
2765 }
2766 }
2767 }
2768 else
2769 proc = SCM_CEVAL (SCM_CAR (x), env);
22a52da1 2770 SCM_ASRTGO (!SCM_IMP (proc), badfun);
bd987b8e 2771
0f2d19dd 2772 checkargs:
0f2d19dd
JB
2773 if (SCM_CLOSUREP (proc))
2774 {
e050d4f8
DH
2775 SCM formals = SCM_CLOSURE_FORMALS (proc);
2776 SCM args = SCM_CDR (x);
2777 while (!SCM_NULLP (formals))
0f2d19dd 2778 {
e050d4f8 2779 if (!SCM_CONSP (formals))
0f2d19dd 2780 goto evapply;
e050d4f8 2781 if (SCM_IMP (args))
0f2d19dd 2782 goto umwrongnumargs;
e050d4f8
DH
2783 formals = SCM_CDR (formals);
2784 args = SCM_CDR (args);
0f2d19dd 2785 }
e050d4f8 2786 if (!SCM_NULLP (args))
0f2d19dd
JB
2787 goto umwrongnumargs;
2788 }
22a52da1 2789 else if (SCM_MACROP (proc))
0f2d19dd 2790 goto handle_a_macro;
0f2d19dd
JB
2791 }
2792
2793
e050d4f8 2794evapply: /* inputs: x, proc */
6dbd0af5
MD
2795 PREP_APPLY (proc, SCM_EOL);
2796 if (SCM_NULLP (SCM_CDR (x))) {
2797 ENTER_APPLY;
89efbff4 2798 evap0:
0f2d19dd
JB
2799 switch (SCM_TYP7 (proc))
2800 { /* no arguments given */
2801 case scm_tc7_subr_0:
2802 RETURN (SCM_SUBRF (proc) ());
2803 case scm_tc7_subr_1o:
2804 RETURN (SCM_SUBRF (proc) (SCM_UNDEFINED));
2805 case scm_tc7_lsubr:
2806 RETURN (SCM_SUBRF (proc) (SCM_EOL));
2807 case scm_tc7_rpsubr:
2808 RETURN (SCM_BOOL_T);
2809 case scm_tc7_asubr:
2810 RETURN (SCM_SUBRF (proc) (SCM_UNDEFINED, SCM_UNDEFINED));
0717dfd8 2811 case scm_tc7_smob:
68b06924 2812 if (!SCM_SMOB_APPLICABLE_P (proc))
0717dfd8 2813 goto badfun;
68b06924 2814 RETURN (SCM_SMOB_APPLY_0 (proc));
0f2d19dd 2815 case scm_tc7_cclo:
dff98306 2816 arg1 = proc;
0f2d19dd 2817 proc = SCM_CCLO_SUBR (proc);
6dbd0af5
MD
2818#ifdef DEVAL
2819 debug.info->a.proc = proc;
dff98306 2820 debug.info->a.args = scm_list_1 (arg1);
6dbd0af5 2821#endif
0f2d19dd 2822 goto evap1;
89efbff4
MD
2823 case scm_tc7_pws:
2824 proc = SCM_PROCEDURE (proc);
2825#ifdef DEVAL
2826 debug.info->a.proc = proc;
2827#endif
002f1a5d
MD
2828 if (!SCM_CLOSUREP (proc))
2829 goto evap0;
2830 if (scm_badformalsp (proc, 0))
2831 goto umwrongnumargs;
0f2d19dd 2832 case scm_tcs_closures:
f9450cdb 2833 x = SCM_CLOSURE_BODY (proc);
726d810a 2834 env = EXTEND_ENV (SCM_CLOSURE_FORMALS (proc), SCM_EOL, SCM_ENV (proc));
f9450cdb 2835 goto nontoplevel_begin;
904a077d 2836 case scm_tcs_struct:
195847fa
MD
2837 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
2838 {
2839 x = SCM_ENTITY_PROCEDURE (proc);
dff98306 2840 arg1 = SCM_EOL;
195847fa
MD
2841 goto type_dispatch;
2842 }
2843 else if (!SCM_I_OPERATORP (proc))
9b07e212
MD
2844 goto badfun;
2845 else
da7f71d7 2846 {
dff98306 2847 arg1 = proc;
195847fa
MD
2848 proc = (SCM_I_ENTITYP (proc)
2849 ? SCM_ENTITY_PROCEDURE (proc)
2850 : SCM_OPERATOR_PROCEDURE (proc));
da7f71d7 2851#ifdef DEVAL
195847fa 2852 debug.info->a.proc = proc;
dff98306 2853 debug.info->a.args = scm_list_1 (arg1);
da7f71d7 2854#endif
195847fa
MD
2855 if (SCM_NIMP (proc))
2856 goto evap1;
2857 else
2858 goto badfun;
da7f71d7 2859 }
0f2d19dd
JB
2860 case scm_tc7_subr_1:
2861 case scm_tc7_subr_2:
2862 case scm_tc7_subr_2o:
2863 case scm_tc7_cxr:
2864 case scm_tc7_subr_3:
2865 case scm_tc7_lsubr_2:
2866 umwrongnumargs:
2867 unmemocar (x, env);
f5bf2977 2868 scm_wrong_num_args (proc);
0f2d19dd
JB
2869 default:
2870 /* handle macros here */
2871 goto badfun;
2872 }
6dbd0af5 2873 }
0f2d19dd
JB
2874
2875 /* must handle macros by here */
2876 x = SCM_CDR (x);
dff98306
DH
2877 if (SCM_CONSP (x))
2878 arg1 = EVALCAR (x, env);
680ed4a8 2879 else
ab1f1094 2880 scm_wrong_num_args (proc);
6dbd0af5 2881#ifdef DEVAL
dff98306 2882 debug.info->a.args = scm_list_1 (arg1);
6dbd0af5 2883#endif
0f2d19dd 2884 x = SCM_CDR (x);
42030fb2
DH
2885 {
2886 SCM arg2;
2887 if (SCM_NULLP (x))
2888 {
2889 ENTER_APPLY;
2890 evap1: /* inputs: proc, arg1 */
2891 switch (SCM_TYP7 (proc))
2892 { /* have one argument in arg1 */
2893 case scm_tc7_subr_2o:
2894 RETURN (SCM_SUBRF (proc) (arg1, SCM_UNDEFINED));
2895 case scm_tc7_subr_1:
2896 case scm_tc7_subr_1o:
2897 RETURN (SCM_SUBRF (proc) (arg1));
2898 case scm_tc7_cxr:
2899 if (SCM_SUBRF (proc))
2900 {
2901 if (SCM_INUMP (arg1))
2902 {
2903 RETURN (scm_make_real (SCM_DSUBRF (proc) ((double) SCM_INUM (arg1))));
2904 }
2905 else if (SCM_REALP (arg1))
2906 {
2907 RETURN (scm_make_real (SCM_DSUBRF (proc) (SCM_REAL_VALUE (arg1))));
2908 }
42030fb2
DH
2909 else if (SCM_BIGP (arg1))
2910 {
2911 RETURN (scm_make_real (SCM_DSUBRF (proc) (scm_i_big2dbl (arg1))));
2912 }
42030fb2
DH
2913 SCM_WTA_DISPATCH_1 (*SCM_SUBR_GENERIC (proc), arg1,
2914 SCM_ARG1, SCM_SYMBOL_CHARS (SCM_SNAME (proc)));
2915 }
2916 proc = SCM_SNAME (proc);
2917 {
2918 char *chrs = SCM_SYMBOL_CHARS (proc) + SCM_SYMBOL_LENGTH (proc) - 1;
2919 while ('c' != *--chrs)
0f2d19dd 2920 {
42030fb2
DH
2921 SCM_ASSERT (SCM_CONSP (arg1),
2922 arg1, SCM_ARG1, SCM_SYMBOL_CHARS (proc));
2923 arg1 = ('a' == *chrs) ? SCM_CAR (arg1) : SCM_CDR (arg1);
0f2d19dd 2924 }
42030fb2 2925 RETURN (arg1);
0f2d19dd 2926 }
42030fb2
DH
2927 case scm_tc7_rpsubr:
2928 RETURN (SCM_BOOL_T);
2929 case scm_tc7_asubr:
2930 RETURN (SCM_SUBRF (proc) (arg1, SCM_UNDEFINED));
2931 case scm_tc7_lsubr:
0f2d19dd 2932#ifdef DEVAL
42030fb2 2933 RETURN (SCM_SUBRF (proc) (debug.info->a.args));
0f2d19dd 2934#else
42030fb2 2935 RETURN (SCM_SUBRF (proc) (scm_list_1 (arg1)));
0f2d19dd 2936#endif
42030fb2
DH
2937 case scm_tc7_smob:
2938 if (!SCM_SMOB_APPLICABLE_P (proc))
2939 goto badfun;
2940 RETURN (SCM_SMOB_APPLY_1 (proc, arg1));
2941 case scm_tc7_cclo:
2942 arg2 = arg1;
2943 arg1 = proc;
2944 proc = SCM_CCLO_SUBR (proc);
6dbd0af5 2945#ifdef DEVAL
42030fb2
DH
2946 debug.info->a.args = scm_cons (arg1, debug.info->a.args);
2947 debug.info->a.proc = proc;
6dbd0af5 2948#endif
42030fb2
DH
2949 goto evap2;
2950 case scm_tc7_pws:
2951 proc = SCM_PROCEDURE (proc);
89efbff4 2952#ifdef DEVAL
42030fb2 2953 debug.info->a.proc = proc;
89efbff4 2954#endif
42030fb2
DH
2955 if (!SCM_CLOSUREP (proc))
2956 goto evap1;
2957 if (scm_badformalsp (proc, 1))
2958 goto umwrongnumargs;
2959 case scm_tcs_closures:
2960 /* clos1: */
2961 x = SCM_CLOSURE_BODY (proc);
0f2d19dd 2962#ifdef DEVAL
42030fb2 2963 env = EXTEND_ENV (SCM_CLOSURE_FORMALS (proc), debug.info->a.args, SCM_ENV (proc));
0f2d19dd 2964#else
42030fb2 2965 env = EXTEND_ENV (SCM_CLOSURE_FORMALS (proc), scm_list_1 (arg1), SCM_ENV (proc));
0f2d19dd 2966#endif
42030fb2
DH
2967 goto nontoplevel_begin;
2968 case scm_tcs_struct:
2969 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
2970 {
2971 x = SCM_ENTITY_PROCEDURE (proc);
f3d2630a 2972#ifdef DEVAL
42030fb2 2973 arg1 = debug.info->a.args;
f3d2630a 2974#else
42030fb2 2975 arg1 = scm_list_1 (arg1);
f3d2630a 2976#endif
42030fb2
DH
2977 goto type_dispatch;
2978 }
2979 else if (!SCM_I_OPERATORP (proc))
2980 goto badfun;
2981 else
2982 {
2983 arg2 = arg1;
2984 arg1 = proc;
2985 proc = (SCM_I_ENTITYP (proc)
2986 ? SCM_ENTITY_PROCEDURE (proc)
2987 : SCM_OPERATOR_PROCEDURE (proc));
0c32d76c 2988#ifdef DEVAL
42030fb2
DH
2989 debug.info->a.args = scm_cons (arg1, debug.info->a.args);
2990 debug.info->a.proc = proc;
0c32d76c 2991#endif
42030fb2
DH
2992 if (SCM_NIMP (proc))
2993 goto evap2;
2994 else
2995 goto badfun;
2996 }
2997 case scm_tc7_subr_2:
2998 case scm_tc7_subr_0:
2999 case scm_tc7_subr_3:
3000 case scm_tc7_lsubr_2:
ab1f1094 3001 scm_wrong_num_args (proc);
42030fb2
DH
3002 default:
3003 goto badfun;
3004 }
3005 }
42030fb2
DH
3006 if (SCM_CONSP (x))
3007 arg2 = EVALCAR (x, env);
3008 else
ab1f1094 3009 scm_wrong_num_args (proc);
bd987b8e 3010
42030fb2 3011 { /* have two or more arguments */
6dbd0af5 3012#ifdef DEVAL
42030fb2 3013 debug.info->a.args = scm_list_2 (arg1, arg2);
6dbd0af5 3014#endif
42030fb2
DH
3015 x = SCM_CDR (x);
3016 if (SCM_NULLP (x)) {
3017 ENTER_APPLY;
3018 evap2:
3019 switch (SCM_TYP7 (proc))
3020 { /* have two arguments */
3021 case scm_tc7_subr_2:
3022 case scm_tc7_subr_2o:
3023 RETURN (SCM_SUBRF (proc) (arg1, arg2));
3024 case scm_tc7_lsubr:
0f2d19dd 3025#ifdef DEVAL
42030fb2 3026 RETURN (SCM_SUBRF (proc) (debug.info->a.args));
6dbd0af5 3027#else
42030fb2
DH
3028 RETURN (SCM_SUBRF (proc) (scm_list_2 (arg1, arg2)));
3029#endif
3030 case scm_tc7_lsubr_2:
3031 RETURN (SCM_SUBRF (proc) (arg1, arg2, SCM_EOL));
3032 case scm_tc7_rpsubr:
3033 case scm_tc7_asubr:
3034 RETURN (SCM_SUBRF (proc) (arg1, arg2));
3035 case scm_tc7_smob:
3036 if (!SCM_SMOB_APPLICABLE_P (proc))
3037 goto badfun;
3038 RETURN (SCM_SMOB_APPLY_2 (proc, arg1, arg2));
3039 cclon:
3040 case scm_tc7_cclo:
0f2d19dd 3041#ifdef DEVAL
42030fb2
DH
3042 RETURN (SCM_APPLY (SCM_CCLO_SUBR (proc),
3043 scm_cons (proc, debug.info->a.args),
3044 SCM_EOL));
0f2d19dd 3045#else
42030fb2
DH
3046 RETURN (SCM_APPLY (SCM_CCLO_SUBR (proc),
3047 scm_cons2 (proc, arg1,
3048 scm_cons (arg2,
3049 scm_eval_args (x,
3050 env,
3051 proc))),
3052 SCM_EOL));
3053#endif
3054 case scm_tcs_struct:
3055 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
3056 {
3057 x = SCM_ENTITY_PROCEDURE (proc);
3058#ifdef DEVAL
3059 arg1 = debug.info->a.args;
3060#else
3061 arg1 = scm_list_2 (arg1, arg2);
6dbd0af5 3062#endif
42030fb2
DH
3063 goto type_dispatch;
3064 }
3065 else if (!SCM_I_OPERATORP (proc))
3066 goto badfun;
3067 else
3068 {
3069 operatorn:
f3d2630a 3070#ifdef DEVAL
42030fb2
DH
3071 RETURN (SCM_APPLY (SCM_I_ENTITYP (proc)
3072 ? SCM_ENTITY_PROCEDURE (proc)
3073 : SCM_OPERATOR_PROCEDURE (proc),
3074 scm_cons (proc, debug.info->a.args),
3075 SCM_EOL));
f3d2630a 3076#else
42030fb2
DH
3077 RETURN (SCM_APPLY (SCM_I_ENTITYP (proc)
3078 ? SCM_ENTITY_PROCEDURE (proc)
3079 : SCM_OPERATOR_PROCEDURE (proc),
3080 scm_cons2 (proc, arg1,
3081 scm_cons (arg2,
3082 scm_eval_args (x,
3083 env,
3084 proc))),
3085 SCM_EOL));
f3d2630a 3086#endif
42030fb2
DH
3087 }
3088 case scm_tc7_subr_0:
3089 case scm_tc7_cxr:
3090 case scm_tc7_subr_1o:
3091 case scm_tc7_subr_1:
3092 case scm_tc7_subr_3:
ab1f1094 3093 scm_wrong_num_args (proc);
42030fb2 3094 default:
9b07e212 3095 goto badfun;
42030fb2
DH
3096 case scm_tc7_pws:
3097 proc = SCM_PROCEDURE (proc);
3098#ifdef DEVAL
3099 debug.info->a.proc = proc;
3100#endif
3101 if (!SCM_CLOSUREP (proc))
3102 goto evap2;
3103 if (scm_badformalsp (proc, 2))
3104 goto umwrongnumargs;
3105 case scm_tcs_closures:
3106 /* clos2: */
0c32d76c 3107#ifdef DEVAL
42030fb2
DH
3108 env = EXTEND_ENV (SCM_CLOSURE_FORMALS (proc),
3109 debug.info->a.args,
3110 SCM_ENV (proc));
195847fa 3111#else
42030fb2
DH
3112 env = EXTEND_ENV (SCM_CLOSURE_FORMALS (proc),
3113 scm_list_2 (arg1, arg2), SCM_ENV (proc));
195847fa 3114#endif
42030fb2
DH
3115 x = SCM_CLOSURE_BODY (proc);
3116 goto nontoplevel_begin;
3117 }
3118 }
42030fb2 3119 if (!SCM_CONSP (x))
ab1f1094 3120 scm_wrong_num_args (proc);
42030fb2
DH
3121#ifdef DEVAL
3122 debug.info->a.args = scm_cons2 (arg1, arg2,
3123 deval_args (x, env, proc,
3124 SCM_CDRLOC (SCM_CDR (debug.info->a.args))));
3125#endif
3126 ENTER_APPLY;
3127 evap3:
3128 switch (SCM_TYP7 (proc))
3129 { /* have 3 or more arguments */
3130#ifdef DEVAL
6dbd0af5 3131 case scm_tc7_subr_3:
ab1f1094
DH
3132 if (!SCM_NULLP (SCM_CDR (x)))
3133 scm_wrong_num_args (proc);
3134 else
3135 RETURN (SCM_SUBRF (proc) (arg1, arg2,
3136 SCM_CADDR (debug.info->a.args)));
42030fb2
DH
3137 case scm_tc7_asubr:
3138 arg1 = SCM_SUBRF(proc)(arg1, arg2);
3139 arg2 = SCM_CDDR (debug.info->a.args);
3140 do
3141 {
3142 arg1 = SCM_SUBRF(proc)(arg1, SCM_CAR (arg2));
3143 arg2 = SCM_CDR (arg2);
3144 }
3145 while (SCM_NIMP (arg2));
3146 RETURN (arg1);
3147 case scm_tc7_rpsubr:
3148 if (SCM_FALSEP (SCM_SUBRF (proc) (arg1, arg2)))
3149 RETURN (SCM_BOOL_F);
3150 arg1 = SCM_CDDR (debug.info->a.args);
3151 do
3152 {
3153 if (SCM_FALSEP (SCM_SUBRF (proc) (arg2, SCM_CAR (arg1))))
3154 RETURN (SCM_BOOL_F);
3155 arg2 = SCM_CAR (arg1);
3156 arg1 = SCM_CDR (arg1);
3157 }
3158 while (SCM_NIMP (arg1));
3159 RETURN (SCM_BOOL_T);
3160 case scm_tc7_lsubr_2:
3161 RETURN (SCM_SUBRF (proc) (arg1, arg2,
3162 SCM_CDDR (debug.info->a.args)));
3163 case scm_tc7_lsubr:
3164 RETURN (SCM_SUBRF (proc) (debug.info->a.args));
3165 case scm_tc7_smob:
3166 if (!SCM_SMOB_APPLICABLE_P (proc))
3167 goto badfun;
3168 RETURN (SCM_SMOB_APPLY_3 (proc, arg1, arg2,
3169 SCM_CDDR (debug.info->a.args)));
3170 case scm_tc7_cclo:
3171 goto cclon;
002f1a5d
MD
3172 case scm_tc7_pws:
3173 proc = SCM_PROCEDURE (proc);
002f1a5d 3174 debug.info->a.proc = proc;
002f1a5d 3175 if (!SCM_CLOSUREP (proc))
42030fb2
DH
3176 goto evap3;
3177 if (scm_badargsp (SCM_CLOSURE_FORMALS (proc), debug.info->a.args))
002f1a5d 3178 goto umwrongnumargs;
6dbd0af5 3179 case scm_tcs_closures:
42030fb2 3180 SCM_SET_ARGSREADY (debug);
726d810a 3181 env = EXTEND_ENV (SCM_CLOSURE_FORMALS (proc),
da7f71d7
MD
3182 debug.info->a.args,
3183 SCM_ENV (proc));
f9450cdb
DH
3184 x = SCM_CLOSURE_BODY (proc);
3185 goto nontoplevel_begin;
6dbd0af5 3186#else /* DEVAL */
42030fb2 3187 case scm_tc7_subr_3:
ab1f1094
DH
3188 if (!SCM_NULLP (SCM_CDR (x)))
3189 scm_wrong_num_args (proc);
3190 else
3191 RETURN (SCM_SUBRF (proc) (arg1, arg2, EVALCAR (x, env)));
42030fb2
DH
3192 case scm_tc7_asubr:
3193 arg1 = SCM_SUBRF (proc) (arg1, arg2);
3194 do
3195 {
3196 arg1 = SCM_SUBRF(proc)(arg1, EVALCAR(x, env));
3197 x = SCM_CDR(x);
3198 }
3199 while (SCM_NIMP (x));
3200 RETURN (arg1);
3201 case scm_tc7_rpsubr:
3202 if (SCM_FALSEP (SCM_SUBRF (proc) (arg1, arg2)))
3203 RETURN (SCM_BOOL_F);
3204 do
3205 {
3206 arg1 = EVALCAR (x, env);
3207 if (SCM_FALSEP (SCM_SUBRF (proc) (arg2, arg1)))
3208 RETURN (SCM_BOOL_F);
3209 arg2 = arg1;
3210 x = SCM_CDR (x);
3211 }
3212 while (SCM_NIMP (x));
3213 RETURN (SCM_BOOL_T);
3214 case scm_tc7_lsubr_2:
3215 RETURN (SCM_SUBRF (proc) (arg1, arg2, scm_eval_args (x, env, proc)));
3216 case scm_tc7_lsubr:
3217 RETURN (SCM_SUBRF (proc) (scm_cons2 (arg1,
3218 arg2,
3219 scm_eval_args (x, env, proc))));
3220 case scm_tc7_smob:
3221 if (!SCM_SMOB_APPLICABLE_P (proc))
3222 goto badfun;
3223 RETURN (SCM_SMOB_APPLY_3 (proc, arg1, arg2,
3224 scm_eval_args (x, env, proc)));
3225 case scm_tc7_cclo:
3226 goto cclon;
3227 case scm_tc7_pws:
3228 proc = SCM_PROCEDURE (proc);
3229 if (!SCM_CLOSUREP (proc))
3230 goto evap3;
da7f71d7 3231 {
42030fb2
DH
3232 SCM formals = SCM_CLOSURE_FORMALS (proc);
3233 if (SCM_NULLP (formals)
3234 || (SCM_CONSP (formals)
3235 && (SCM_NULLP (SCM_CDR (formals))
3236 || (SCM_CONSP (SCM_CDR (formals))
3237 && scm_badargsp (SCM_CDDR (formals), x)))))
3238 goto umwrongnumargs;
da7f71d7 3239 }
42030fb2 3240 case scm_tcs_closures:
6dbd0af5 3241#ifdef DEVAL
42030fb2 3242 SCM_SET_ARGSREADY (debug);
6dbd0af5 3243#endif
42030fb2
DH
3244 env = EXTEND_ENV (SCM_CLOSURE_FORMALS (proc),
3245 scm_cons2 (arg1,
3246 arg2,
3247 scm_eval_args (x, env, proc)),
3248 SCM_ENV (proc));
3249 x = SCM_CLOSURE_BODY (proc);
3250 goto nontoplevel_begin;
0f2d19dd 3251#endif /* DEVAL */
42030fb2
DH
3252 case scm_tcs_struct:
3253 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
3254 {
f3d2630a 3255#ifdef DEVAL
42030fb2 3256 arg1 = debug.info->a.args;
f3d2630a 3257#else
42030fb2 3258 arg1 = scm_cons2 (arg1, arg2, scm_eval_args (x, env, proc));
f3d2630a 3259#endif
42030fb2
DH
3260 x = SCM_ENTITY_PROCEDURE (proc);
3261 goto type_dispatch;
3262 }
3263 else if (!SCM_I_OPERATORP (proc))
3264 goto badfun;
3265 else
3266 goto operatorn;
3267 case scm_tc7_subr_2:
3268 case scm_tc7_subr_1o:
3269 case scm_tc7_subr_2o:
3270 case scm_tc7_subr_0:
3271 case scm_tc7_cxr:
3272 case scm_tc7_subr_1:
ab1f1094 3273 scm_wrong_num_args (proc);
42030fb2 3274 default:
9b07e212 3275 goto badfun;
42030fb2
DH
3276 }
3277 }
0f2d19dd
JB
3278 }
3279#ifdef DEVAL
6dbd0af5 3280exit:
5132eef0 3281 if (scm_check_exit_p && SCM_TRAPS_P)
b7ff98dd 3282 if (SCM_EXIT_FRAME_P || (SCM_TRACE_P && SCM_TRACED_FRAME_P (debug)))
6dbd0af5 3283 {
b7ff98dd
MD
3284 SCM_CLEAR_TRACED_FRAME (debug);
3285 if (SCM_CHEAPTRAPS_P)
dff98306 3286 arg1 = scm_make_debugobj (&debug);
6dbd0af5
MD
3287 else
3288 {
5f144b10
GH
3289 int first;
3290 SCM val = scm_make_continuation (&first);
e050d4f8 3291
5f144b10 3292 if (first)
dff98306 3293 arg1 = val;
5f144b10 3294 else
6dbd0af5 3295 {
5f144b10 3296 proc = val;
6dbd0af5
MD
3297 goto ret;
3298 }
3299 }
d95c0b76 3300 SCM_TRAPS_P = 0;
dff98306 3301 scm_call_3 (SCM_EXIT_FRAME_HDLR, scm_sym_exit_frame, arg1, proc);
d95c0b76 3302 SCM_TRAPS_P = 1;
6dbd0af5
MD
3303 }
3304ret:
1646d37b 3305 scm_last_debug_frame = debug.prev;
0f2d19dd
JB
3306 return proc;
3307#endif
3308}
3309
6dbd0af5
MD
3310
3311/* SECTION: This code is compiled once.
3312 */
3313
0f2d19dd
JB
3314#ifndef DEVAL
3315
fdc28395
KN
3316\f
3317/* Simple procedure calls
3318 */
3319
3320SCM
3321scm_call_0 (SCM proc)
3322{
3323 return scm_apply (proc, SCM_EOL, SCM_EOL);
3324}
3325
3326SCM
3327scm_call_1 (SCM proc, SCM arg1)
3328{
3329 return scm_apply (proc, arg1, scm_listofnull);
3330}
3331
3332SCM
3333scm_call_2 (SCM proc, SCM arg1, SCM arg2)
3334{
3335 return scm_apply (proc, arg1, scm_cons (arg2, scm_listofnull));
3336}
3337
3338SCM
3339scm_call_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3)
3340{
3341 return scm_apply (proc, arg1, scm_cons2 (arg2, arg3, scm_listofnull));
3342}
3343
d95c0b76
NJ
3344SCM
3345scm_call_4 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4)
3346{
3347 return scm_apply (proc, arg1, scm_cons2 (arg2, arg3,
3348 scm_cons (arg4, scm_listofnull)));
3349}
3350
fdc28395
KN
3351/* Simple procedure applies
3352 */
3353
3354SCM
3355scm_apply_0 (SCM proc, SCM args)
3356{
3357 return scm_apply (proc, args, SCM_EOL);
3358}
3359
3360SCM
3361scm_apply_1 (SCM proc, SCM arg1, SCM args)
3362{
3363 return scm_apply (proc, scm_cons (arg1, args), SCM_EOL);
3364}
3365
3366SCM
3367scm_apply_2 (SCM proc, SCM arg1, SCM arg2, SCM args)
3368{
3369 return scm_apply (proc, scm_cons2 (arg1, arg2, args), SCM_EOL);
3370}
3371
3372SCM
3373scm_apply_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM args)
3374{
3375 return scm_apply (proc, scm_cons (arg1, scm_cons2 (arg2, arg3, args)),
3376 SCM_EOL);
3377}
3378
82a2622a 3379/* This code processes the arguments to apply:
b145c172
JB
3380
3381 (apply PROC ARG1 ... ARGS)
3382
82a2622a
JB
3383 Given a list (ARG1 ... ARGS), this function conses the ARG1
3384 ... arguments onto the front of ARGS, and returns the resulting
3385 list. Note that ARGS is a list; thus, the argument to this
3386 function is a list whose last element is a list.
3387
3388 Apply calls this function, and applies PROC to the elements of the
b145c172
JB
3389 result. apply:nconc2last takes care of building the list of
3390 arguments, given (ARG1 ... ARGS).
3391
82a2622a
JB
3392 Rather than do new consing, apply:nconc2last destroys its argument.
3393 On that topic, this code came into my care with the following
3394 beautifully cryptic comment on that topic: "This will only screw
3395 you if you do (scm_apply scm_apply '( ... ))" If you know what
3396 they're referring to, send me a patch to this comment. */
b145c172 3397
3b3b36dd 3398SCM_DEFINE (scm_nconc2last, "apply:nconc2last", 1, 0, 0,
b3f26b14
MG
3399 (SCM lst),
3400 "Given a list (@var{arg1} @dots{} @var{args}), this function\n"
3401 "conses the @var{arg1} @dots{} arguments onto the front of\n"
3402 "@var{args}, and returns the resulting list. Note that\n"
3403 "@var{args} is a list; thus, the argument to this function is\n"
3404 "a list whose last element is a list.\n"
3405 "Note: Rather than do new consing, @code{apply:nconc2last}\n"
3406 "destroys its argument, so use with care.")
1bbd0b84 3407#define FUNC_NAME s_scm_nconc2last
0f2d19dd
JB
3408{
3409 SCM *lloc;
34d19ef6 3410 SCM_VALIDATE_NONEMPTYLIST (1, lst);
0f2d19dd 3411 lloc = &lst;
c96d76b8
NJ
3412 while (!SCM_NULLP (SCM_CDR (*lloc))) /* Perhaps should be
3413 SCM_NULL_OR_NIL_P, but not
3414 needed in 99.99% of cases,
3415 and it could seriously hurt
3416 performance. - Neil */
a23afe53 3417 lloc = SCM_CDRLOC (*lloc);
1bbd0b84 3418 SCM_ASSERT (scm_ilength (SCM_CAR (*lloc)) >= 0, lst, SCM_ARG1, FUNC_NAME);
0f2d19dd
JB
3419 *lloc = SCM_CAR (*lloc);
3420 return lst;
3421}
1bbd0b84 3422#undef FUNC_NAME
0f2d19dd
JB
3423
3424#endif /* !DEVAL */
3425
6dbd0af5
MD
3426
3427/* SECTION: When DEVAL is defined this code yields scm_dapply.
3428 * It is compiled twice.
3429 */
3430
0f2d19dd 3431#if 0
0f2d19dd 3432SCM
6e8d25a6 3433scm_apply (SCM proc, SCM arg1, SCM args)
0f2d19dd
JB
3434{}
3435#endif
3436
3437#if 0
0f2d19dd 3438SCM
6e8d25a6
GB
3439scm_dapply (SCM proc, SCM arg1, SCM args)
3440{ /* empty */ }
0f2d19dd
JB
3441#endif
3442
1cc91f1b 3443
82a2622a
JB
3444/* Apply a function to a list of arguments.
3445
3446 This function is exported to the Scheme level as taking two
3447 required arguments and a tail argument, as if it were:
3448 (lambda (proc arg1 . args) ...)
3449 Thus, if you just have a list of arguments to pass to a procedure,
3450 pass the list as ARG1, and '() for ARGS. If you have some fixed
3451 args, pass the first as ARG1, then cons any remaining fixed args
3452 onto the front of your argument list, and pass that as ARGS. */
3453
0f2d19dd 3454SCM
1bbd0b84 3455SCM_APPLY (SCM proc, SCM arg1, SCM args)
0f2d19dd 3456{
0f2d19dd 3457#ifdef DEVAL
92c2555f
MV
3458 scm_t_debug_frame debug;
3459 scm_t_debug_info debug_vect_body;
1646d37b 3460 debug.prev = scm_last_debug_frame;
b7ff98dd 3461 debug.status = SCM_APPLYFRAME;
c0ab1b8d 3462 debug.vect = &debug_vect_body;
6dbd0af5
MD
3463 debug.vect[0].a.proc = proc;
3464 debug.vect[0].a.args = SCM_EOL;
1646d37b 3465 scm_last_debug_frame = &debug;
0f2d19dd 3466#else
b7ff98dd 3467 if (SCM_DEBUGGINGP)
0f2d19dd 3468 return scm_dapply (proc, arg1, args);
0f2d19dd
JB
3469#endif
3470
3471 SCM_ASRTGO (SCM_NIMP (proc), badproc);
82a2622a
JB
3472
3473 /* If ARGS is the empty list, then we're calling apply with only two
3474 arguments --- ARG1 is the list of arguments for PROC. Whatever
3475 the case, futz with things so that ARG1 is the first argument to
3476 give to PROC (or SCM_UNDEFINED if no args), and ARGS contains the
30000774
JB
3477 rest.
3478
3479 Setting the debug apply frame args this way is pretty messy.
3480 Perhaps we should store arg1 and args directly in the frame as
3481 received, and let scm_frame_arguments unpack them, because that's
3482 a relatively rare operation. This works for now; if the Guile
3483 developer archives are still around, see Mikael's post of
3484 11-Apr-97. */
0f2d19dd
JB
3485 if (SCM_NULLP (args))
3486 {
3487 if (SCM_NULLP (arg1))
30000774
JB
3488 {
3489 arg1 = SCM_UNDEFINED;
3490#ifdef DEVAL
3491 debug.vect[0].a.args = SCM_EOL;
3492#endif
3493 }
0f2d19dd
JB
3494 else
3495 {
30000774
JB
3496#ifdef DEVAL
3497 debug.vect[0].a.args = arg1;
3498#endif
0f2d19dd
JB
3499 args = SCM_CDR (arg1);
3500 arg1 = SCM_CAR (arg1);
3501 }
3502 }
3503 else
3504 {
0f2d19dd 3505 args = scm_nconc2last (args);
30000774
JB
3506#ifdef DEVAL
3507 debug.vect[0].a.args = scm_cons (arg1, args);
3508#endif
0f2d19dd 3509 }
0f2d19dd 3510#ifdef DEVAL
b6d75948 3511 if (SCM_ENTER_FRAME_P && SCM_TRAPS_P)
6dbd0af5
MD
3512 {
3513 SCM tmp;
b7ff98dd 3514 if (SCM_CHEAPTRAPS_P)
c0ab1b8d 3515 tmp = scm_make_debugobj (&debug);
6dbd0af5
MD
3516 else
3517 {
5f144b10
GH
3518 int first;
3519
3520 tmp = scm_make_continuation (&first);
3521 if (!first)
6dbd0af5
MD
3522 goto entap;
3523 }
d95c0b76
NJ
3524 SCM_TRAPS_P = 0;
3525 scm_call_2 (SCM_ENTER_FRAME_HDLR, scm_sym_enter_frame, tmp);
3526 SCM_TRAPS_P = 1;
6dbd0af5
MD
3527 }
3528entap:
3529 ENTER_APPLY;
3530#endif
6dbd0af5 3531tail:
0f2d19dd
JB
3532 switch (SCM_TYP7 (proc))
3533 {
3534 case scm_tc7_subr_2o:
3535 args = SCM_NULLP (args) ? SCM_UNDEFINED : SCM_CAR (args);
ddea3325 3536 RETURN (SCM_SUBRF (proc) (arg1, args));
0f2d19dd 3537 case scm_tc7_subr_2:
ab1f1094
DH
3538 if (SCM_NULLP (args) || !SCM_NULLP (SCM_CDR (args)))
3539 scm_wrong_num_args (proc);
0f2d19dd 3540 args = SCM_CAR (args);
ddea3325 3541 RETURN (SCM_SUBRF (proc) (arg1, args));
0f2d19dd 3542 case scm_tc7_subr_0:
ab1f1094
DH
3543 if (!SCM_UNBNDP (arg1))
3544 scm_wrong_num_args (proc);
3545 else
3546 RETURN (SCM_SUBRF (proc) ());
0f2d19dd 3547 case scm_tc7_subr_1:
ab1f1094
DH
3548 if (SCM_UNBNDP (arg1))
3549 scm_wrong_num_args (proc);
0f2d19dd 3550 case scm_tc7_subr_1o:
ab1f1094
DH
3551 if (!SCM_NULLP (args))
3552 scm_wrong_num_args (proc);
3553 else
3554 RETURN (SCM_SUBRF (proc) (arg1));
0f2d19dd 3555 case scm_tc7_cxr:
ab1f1094
DH
3556 if (SCM_UNBNDP (arg1) || !SCM_NULLP (args))
3557 scm_wrong_num_args (proc);
0f2d19dd
JB
3558 if (SCM_SUBRF (proc))
3559 {
6dbd0af5
MD
3560 if (SCM_INUMP (arg1))
3561 {
f8de44c1 3562 RETURN (scm_make_real (SCM_DSUBRF (proc) ((double) SCM_INUM (arg1))));
6dbd0af5 3563 }
01f11e02 3564 else if (SCM_REALP (arg1))
6dbd0af5 3565 {
eb42e2f0 3566 RETURN (scm_make_real (SCM_DSUBRF (proc) (SCM_REAL_VALUE (arg1))));
6dbd0af5 3567 }
01f11e02 3568 else if (SCM_BIGP (arg1))
ddea3325 3569 RETURN (scm_make_real (SCM_DSUBRF (proc) (scm_i_big2dbl (arg1))));
9de33deb 3570 SCM_WTA_DISPATCH_1 (*SCM_SUBR_GENERIC (proc), arg1,
3db4adfc 3571 SCM_ARG1, SCM_SYMBOL_CHARS (SCM_SNAME (proc)));
0f2d19dd 3572 }
3201d763 3573 proc = SCM_SNAME (proc);
0f2d19dd 3574 {
b5c2579a 3575 char *chrs = SCM_SYMBOL_CHARS (proc) + SCM_SYMBOL_LENGTH (proc) - 1;
0f2d19dd
JB
3576 while ('c' != *--chrs)
3577 {
0c95b57d 3578 SCM_ASSERT (SCM_CONSP (arg1),
3db4adfc 3579 arg1, SCM_ARG1, SCM_SYMBOL_CHARS (proc));
0f2d19dd
JB
3580 arg1 = ('a' == *chrs) ? SCM_CAR (arg1) : SCM_CDR (arg1);
3581 }
ddea3325 3582 RETURN (arg1);
0f2d19dd
JB
3583 }
3584 case scm_tc7_subr_3:
ab1f1094
DH
3585 if (SCM_NULLP (args)
3586 || SCM_NULLP (SCM_CDR (args))
3587 || !SCM_NULLP (SCM_CDDR (args)))
3588 scm_wrong_num_args (proc);
3589 else
3590 RETURN (SCM_SUBRF (proc) (arg1, SCM_CAR (args), SCM_CADR (args)));
0f2d19dd
JB
3591 case scm_tc7_lsubr:
3592#ifdef DEVAL
ddea3325 3593 RETURN (SCM_SUBRF (proc) (SCM_UNBNDP (arg1) ? SCM_EOL : debug.vect[0].a.args));
0f2d19dd 3594#else
ddea3325 3595 RETURN (SCM_SUBRF (proc) (SCM_UNBNDP (arg1) ? SCM_EOL : scm_cons (arg1, args)));
0f2d19dd
JB
3596#endif
3597 case scm_tc7_lsubr_2:
ab1f1094
DH
3598 if (!SCM_CONSP (args))
3599 scm_wrong_num_args (proc);
3600 else
3601 RETURN (SCM_SUBRF (proc) (arg1, SCM_CAR (args), SCM_CDR (args)));
0f2d19dd
JB
3602 case scm_tc7_asubr:
3603 if (SCM_NULLP (args))
ddea3325 3604 RETURN (SCM_SUBRF (proc) (arg1, SCM_UNDEFINED));
0f2d19dd
JB
3605 while (SCM_NIMP (args))
3606 {
3607 SCM_ASSERT (SCM_CONSP (args), args, SCM_ARG2, "apply");
3608 arg1 = SCM_SUBRF (proc) (arg1, SCM_CAR (args));
3609 args = SCM_CDR (args);
3610 }
3611 RETURN (arg1);
3612 case scm_tc7_rpsubr:
3613 if (SCM_NULLP (args))
3614 RETURN (SCM_BOOL_T);
3615 while (SCM_NIMP (args))
3616 {
3617 SCM_ASSERT (SCM_CONSP (args), args, SCM_ARG2, "apply");
3618 if (SCM_FALSEP (SCM_SUBRF (proc) (arg1, SCM_CAR (args))))
3619 RETURN (SCM_BOOL_F);
3620 arg1 = SCM_CAR (args);
3621 args = SCM_CDR (args);
3622 }
3623 RETURN (SCM_BOOL_T);
3624 case scm_tcs_closures:
3625#ifdef DEVAL
6dbd0af5 3626 arg1 = (SCM_UNBNDP (arg1) ? SCM_EOL : debug.vect[0].a.args);
0f2d19dd
JB
3627#else
3628 arg1 = (SCM_UNBNDP (arg1) ? SCM_EOL : scm_cons (arg1, args));
3629#endif
726d810a 3630 if (scm_badargsp (SCM_CLOSURE_FORMALS (proc), arg1))
ab1f1094 3631 scm_wrong_num_args (proc);
1609038c
MD
3632
3633 /* Copy argument list */
3634 if (SCM_IMP (arg1))
3635 args = arg1;
3636 else
3637 {
3638 SCM tl = args = scm_cons (SCM_CAR (arg1), SCM_UNSPECIFIED);
cabe682c 3639 while (arg1 = SCM_CDR (arg1), SCM_CONSP (arg1))
1609038c
MD
3640 {
3641 SCM_SETCDR (tl, scm_cons (SCM_CAR (arg1),
3642 SCM_UNSPECIFIED));
3643 tl = SCM_CDR (tl);
3644 }
3645 SCM_SETCDR (tl, arg1);
3646 }
3647
726d810a 3648 args = EXTEND_ENV (SCM_CLOSURE_FORMALS (proc), args, SCM_ENV (proc));
f9450cdb 3649 proc = SCM_CLOSURE_BODY (proc);
e791c18f
MD
3650 again:
3651 arg1 = proc;
01f11e02 3652 while (!SCM_NULLP (arg1 = SCM_CDR (arg1)))
2ddb0920
MD
3653 {
3654 if (SCM_IMP (SCM_CAR (proc)))
3655 {
3656 if (SCM_ISYMP (SCM_CAR (proc)))
3657 {
28d52ebb 3658 scm_rec_mutex_lock (&source_mutex);
9bc4701c
MD
3659 /* check for race condition */
3660 if (SCM_ISYMP (SCM_CAR (proc)))
3661 proc = scm_m_expand_body (proc, args);
28d52ebb 3662 scm_rec_mutex_unlock (&source_mutex);
e791c18f 3663 goto again;
2ddb0920 3664 }
5280aaca 3665 else
17fa3fcf 3666 SCM_VALIDATE_NON_EMPTY_COMBINATION (SCM_CAR (proc));
2ddb0920
MD
3667 }
3668 else
e791c18f
MD
3669 SCM_CEVAL (SCM_CAR (proc), args);
3670 proc = arg1;
2ddb0920 3671 }
e791c18f 3672 RETURN (EVALCAR (proc, args));
0717dfd8 3673 case scm_tc7_smob:
68b06924 3674 if (!SCM_SMOB_APPLICABLE_P (proc))
0717dfd8 3675 goto badproc;
afa38f6e 3676 if (SCM_UNBNDP (arg1))
ddea3325 3677 RETURN (SCM_SMOB_APPLY_0 (proc));
afa38f6e 3678 else if (SCM_NULLP (args))
ddea3325 3679 RETURN (SCM_SMOB_APPLY_1 (proc, arg1));
0717dfd8 3680 else if (SCM_NULLP (SCM_CDR (args)))
ddea3325 3681 RETURN (SCM_SMOB_APPLY_2 (proc, arg1, SCM_CAR (args)));
0717dfd8 3682 else
68b06924 3683 RETURN (SCM_SMOB_APPLY_3 (proc, arg1, SCM_CAR (args), SCM_CDR (args)));
0f2d19dd
JB
3684 case scm_tc7_cclo:
3685#ifdef DEVAL
6dbd0af5
MD
3686 args = (SCM_UNBNDP(arg1) ? SCM_EOL : debug.vect[0].a.args);
3687 arg1 = proc;
3688 proc = SCM_CCLO_SUBR (proc);
3689 debug.vect[0].a.proc = proc;
3690 debug.vect[0].a.args = scm_cons (arg1, args);
0f2d19dd
JB
3691#else
3692 args = (SCM_UNBNDP(arg1) ? SCM_EOL : scm_cons (arg1, args));
0f2d19dd
JB
3693 arg1 = proc;
3694 proc = SCM_CCLO_SUBR (proc);
6dbd0af5 3695#endif
0f2d19dd 3696 goto tail;
89efbff4
MD
3697 case scm_tc7_pws:
3698 proc = SCM_PROCEDURE (proc);
3699#ifdef DEVAL
3700 debug.vect[0].a.proc = proc;
3701#endif
3702 goto tail;
904a077d 3703 case scm_tcs_struct:
f3d2630a
MD
3704 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
3705 {
3706#ifdef DEVAL
3707 args = (SCM_UNBNDP(arg1) ? SCM_EOL : debug.vect[0].a.args);
3708#else
3709 args = (SCM_UNBNDP(arg1) ? SCM_EOL : scm_cons (arg1, args));
3710#endif
195847fa 3711 RETURN (scm_apply_generic (proc, args));
f3d2630a
MD
3712 }
3713 else if (!SCM_I_OPERATORP (proc))
9b07e212
MD
3714 goto badproc;
3715 else
da7f71d7 3716 {
504d99c5 3717 /* operator */
da7f71d7
MD
3718#ifdef DEVAL
3719 args = (SCM_UNBNDP(arg1) ? SCM_EOL : debug.vect[0].a.args);
3720#else
3721 args = (SCM_UNBNDP(arg1) ? SCM_EOL : scm_cons (arg1, args));
3722#endif
3723 arg1 = proc;
195847fa
MD
3724 proc = (SCM_I_ENTITYP (proc)
3725 ? SCM_ENTITY_PROCEDURE (proc)
3726 : SCM_OPERATOR_PROCEDURE (proc));
da7f71d7
MD
3727#ifdef DEVAL
3728 debug.vect[0].a.proc = proc;
3729 debug.vect[0].a.args = scm_cons (arg1, args);
3730#endif
195847fa
MD
3731 if (SCM_NIMP (proc))
3732 goto tail;
3733 else
3734 goto badproc;
da7f71d7 3735 }
0f2d19dd
JB
3736 default:
3737 badproc:
db4b4ca6 3738 scm_wrong_type_arg ("apply", SCM_ARG1, proc);
0f2d19dd
JB
3739 }
3740#ifdef DEVAL
6dbd0af5 3741exit:
5132eef0 3742 if (scm_check_exit_p && SCM_TRAPS_P)
b7ff98dd 3743 if (SCM_EXIT_FRAME_P || (SCM_TRACE_P && SCM_TRACED_FRAME_P (debug)))
6dbd0af5 3744 {
b7ff98dd
MD
3745 SCM_CLEAR_TRACED_FRAME (debug);
3746 if (SCM_CHEAPTRAPS_P)
c0ab1b8d 3747 arg1 = scm_make_debugobj (&debug);
6dbd0af5
MD
3748 else
3749 {
5f144b10
GH
3750 int first;
3751 SCM val = scm_make_continuation (&first);
3752
3753 if (first)
3754 arg1 = val;
3755 else
6dbd0af5 3756 {
5f144b10 3757 proc = val;
6dbd0af5
MD
3758 goto ret;
3759 }
3760 }
d95c0b76
NJ
3761 SCM_TRAPS_P = 0;
3762 scm_call_3 (SCM_EXIT_FRAME_HDLR, scm_sym_exit_frame, arg1, proc);
3763 SCM_TRAPS_P = 1;
6dbd0af5
MD
3764 }
3765ret:
1646d37b 3766 scm_last_debug_frame = debug.prev;
0f2d19dd
JB
3767 return proc;
3768#endif
3769}
3770
6dbd0af5
MD
3771
3772/* SECTION: The rest of this file is only read once.
3773 */
3774
0f2d19dd
JB
3775#ifndef DEVAL
3776
504d99c5
MD
3777/* Trampolines
3778 *
3779 * Trampolines make it possible to move procedure application dispatch
3780 * outside inner loops. The motivation was clean implementation of
3781 * efficient replacements of R5RS primitives in SRFI-1.
3782 *
3783 * The semantics is clear: scm_trampoline_N returns an optimized
3784 * version of scm_call_N (or NULL if the procedure isn't applicable
3785 * on N args).
3786 *
3787 * Applying the optimization to map and for-each increased efficiency
3788 * noticeably. For example, (map abs ls) is now 8 times faster than
3789 * before.
3790 */
3791
756414cf
MD
3792static SCM
3793call_subr0_0 (SCM proc)
3794{
3795 return SCM_SUBRF (proc) ();
3796}
3797
3798static SCM
3799call_subr1o_0 (SCM proc)
3800{
3801 return SCM_SUBRF (proc) (SCM_UNDEFINED);
3802}
3803
3804static SCM
3805call_lsubr_0 (SCM proc)
3806{
3807 return SCM_SUBRF (proc) (SCM_EOL);
3808}
3809
3810SCM
3811scm_i_call_closure_0 (SCM proc)
3812{
3813 return scm_eval_body (SCM_CLOSURE_BODY (proc),
3814 SCM_EXTEND_ENV (SCM_CLOSURE_FORMALS (proc),
3815 SCM_EOL,
3816 SCM_ENV (proc)));
3817}
3818
3819scm_t_trampoline_0
3820scm_trampoline_0 (SCM proc)
3821{
3822 if (SCM_IMP (proc))
3823 return 0;
3824 if (SCM_DEBUGGINGP)
3825 return scm_call_0;
3826 switch (SCM_TYP7 (proc))
3827 {
3828 case scm_tc7_subr_0:
3829 return call_subr0_0;
3830 case scm_tc7_subr_1o:
3831 return call_subr1o_0;
3832 case scm_tc7_lsubr:
3833 return call_lsubr_0;
3834 case scm_tcs_closures:
3835 {
3836 SCM formals = SCM_CLOSURE_FORMALS (proc);
4b612c5b 3837 if (SCM_NULLP (formals) || !SCM_CONSP (formals))
756414cf
MD
3838 return scm_i_call_closure_0;
3839 else
3840 return 0;
3841 }
3842 case scm_tcs_struct:
3843 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
3844 return scm_call_generic_0;
3845 else if (!SCM_I_OPERATORP (proc))
3846 return 0;
3847 return scm_call_0;
3848 case scm_tc7_smob:
3849 if (SCM_SMOB_APPLICABLE_P (proc))
3850 return SCM_SMOB_DESCRIPTOR (proc).apply_0;
3851 else
3852 return 0;
3853 /* fall through */
3854 case scm_tc7_asubr:
3855 case scm_tc7_rpsubr:
3856 case scm_tc7_cclo:
3857 case scm_tc7_pws:
3858 return scm_call_0;
3859 default:
3860 return 0; /* not applicable on one arg */
3861 }
3862}
3863
504d99c5
MD
3864static SCM
3865call_subr1_1 (SCM proc, SCM arg1)
3866{
3867 return SCM_SUBRF (proc) (arg1);
3868}
3869
9ed24633
MD
3870static SCM
3871call_subr2o_1 (SCM proc, SCM arg1)
3872{
3873 return SCM_SUBRF (proc) (arg1, SCM_UNDEFINED);
3874}
3875
504d99c5
MD
3876static SCM
3877call_lsubr_1 (SCM proc, SCM arg1)
3878{
3879 return SCM_SUBRF (proc) (scm_list_1 (arg1));
3880}
3881
3882static SCM
3883call_dsubr_1 (SCM proc, SCM arg1)
3884{
3885 if (SCM_INUMP (arg1))
3886 {
3887 RETURN (scm_make_real (SCM_DSUBRF (proc) ((double) SCM_INUM (arg1))));
3888 }
3889 else if (SCM_REALP (arg1))
3890 {
3891 RETURN (scm_make_real (SCM_DSUBRF (proc) (SCM_REAL_VALUE (arg1))));
3892 }
504d99c5
MD
3893 else if (SCM_BIGP (arg1))
3894 RETURN (scm_make_real (SCM_DSUBRF (proc) (scm_i_big2dbl (arg1))));
504d99c5
MD
3895 SCM_WTA_DISPATCH_1 (*SCM_SUBR_GENERIC (proc), arg1,
3896 SCM_ARG1, SCM_SYMBOL_CHARS (SCM_SNAME (proc)));
3897}
3898
3899static SCM
3900call_cxr_1 (SCM proc, SCM arg1)
3901{
3902 proc = SCM_SNAME (proc);
3903 {
3904 char *chrs = SCM_SYMBOL_CHARS (proc) + SCM_SYMBOL_LENGTH (proc) - 1;
3905 while ('c' != *--chrs)
3906 {
3907 SCM_ASSERT (SCM_CONSP (arg1),
3908 arg1, SCM_ARG1, SCM_SYMBOL_CHARS (proc));
3909 arg1 = ('a' == *chrs) ? SCM_CAR (arg1) : SCM_CDR (arg1);
3910 }
3911 return (arg1);
3912 }
3913}
3914
3915static SCM
3916call_closure_1 (SCM proc, SCM arg1)
3917{
3918 return scm_eval_body (SCM_CLOSURE_BODY (proc),
3919 SCM_EXTEND_ENV (SCM_CLOSURE_FORMALS (proc),
3920 scm_list_1 (arg1),
3921 SCM_ENV (proc)));
3922}
3923
3924scm_t_trampoline_1
3925scm_trampoline_1 (SCM proc)
3926{
3927 if (SCM_IMP (proc))
3928 return 0;
3929 if (SCM_DEBUGGINGP)
3930 return scm_call_1;
3931 switch (SCM_TYP7 (proc))
3932 {
3933 case scm_tc7_subr_1:
3934 case scm_tc7_subr_1o:
3935 return call_subr1_1;
9ed24633
MD
3936 case scm_tc7_subr_2o:
3937 return call_subr2o_1;
504d99c5
MD
3938 case scm_tc7_lsubr:
3939 return call_lsubr_1;
3940 case scm_tc7_cxr:
3941 if (SCM_SUBRF (proc))
3942 return call_dsubr_1;
3943 else
3944 return call_cxr_1;
3945 case scm_tcs_closures:
3946 {
3947 SCM formals = SCM_CLOSURE_FORMALS (proc);
4b612c5b
MD
3948 if (!SCM_NULLP (formals)
3949 && (!SCM_CONSP (formals) || !SCM_CONSP (SCM_CDR (formals))))
504d99c5
MD
3950 return call_closure_1;
3951 else
3952 return 0;
3953 }
3954 case scm_tcs_struct:
3955 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
3956 return scm_call_generic_1;
3957 else if (!SCM_I_OPERATORP (proc))
3958 return 0;
3959 return scm_call_1;
3960 case scm_tc7_smob:
3961 if (SCM_SMOB_APPLICABLE_P (proc))
3962 return SCM_SMOB_DESCRIPTOR (proc).apply_1;
3963 else
3964 return 0;
3965 /* fall through */
3966 case scm_tc7_asubr:
3967 case scm_tc7_rpsubr:
3968 case scm_tc7_cclo:
3969 case scm_tc7_pws:
3970 return scm_call_1;
3971 default:
3972 return 0; /* not applicable on one arg */
3973 }
3974}
3975
3976static SCM
3977call_subr2_2 (SCM proc, SCM arg1, SCM arg2)
3978{
3979 return SCM_SUBRF (proc) (arg1, arg2);
3980}
3981
9ed24633
MD
3982static SCM
3983call_lsubr2_2 (SCM proc, SCM arg1, SCM arg2)
3984{
3985 return SCM_SUBRF (proc) (arg1, arg2, SCM_EOL);
3986}
3987
504d99c5
MD
3988static SCM
3989call_lsubr_2 (SCM proc, SCM arg1, SCM arg2)
3990{
3991 return SCM_SUBRF (proc) (scm_list_2 (arg1, arg2));
3992}
3993
3994static SCM
3995call_closure_2 (SCM proc, SCM arg1, SCM arg2)
3996{
3997 return scm_eval_body (SCM_CLOSURE_BODY (proc),
3998 SCM_EXTEND_ENV (SCM_CLOSURE_FORMALS (proc),
3999 scm_list_2 (arg1, arg2),
4000 SCM_ENV (proc)));
4001}
4002
4003scm_t_trampoline_2
4004scm_trampoline_2 (SCM proc)
4005{
4006 if (SCM_IMP (proc))
4007 return 0;
4008 if (SCM_DEBUGGINGP)
4009 return scm_call_2;
4010 switch (SCM_TYP7 (proc))
4011 {
4012 case scm_tc7_subr_2:
4013 case scm_tc7_subr_2o:
4014 case scm_tc7_rpsubr:
4015 case scm_tc7_asubr:
4016 return call_subr2_2;
9ed24633
MD
4017 case scm_tc7_lsubr_2:
4018 return call_lsubr2_2;
504d99c5
MD
4019 case scm_tc7_lsubr:
4020 return call_lsubr_2;
4021 case scm_tcs_closures:
4022 {
4023 SCM formals = SCM_CLOSURE_FORMALS (proc);
4b612c5b
MD
4024 if (!SCM_NULLP (formals)
4025 && (!SCM_CONSP (formals)
4026 || (!SCM_NULLP (SCM_CDR (formals))
4027 && (!SCM_CONSP (SCM_CDR (formals))
4028 || !SCM_CONSP (SCM_CDDR (formals))))))
504d99c5
MD
4029 return call_closure_2;
4030 else
4031 return 0;
4032 }
4033 case scm_tcs_struct:
4034 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
4035 return scm_call_generic_2;
4036 else if (!SCM_I_OPERATORP (proc))
4037 return 0;
4038 return scm_call_2;
4039 case scm_tc7_smob:
4040 if (SCM_SMOB_APPLICABLE_P (proc))
4041 return SCM_SMOB_DESCRIPTOR (proc).apply_2;
4042 else
4043 return 0;
4044 /* fall through */
4045 case scm_tc7_cclo:
4046 case scm_tc7_pws:
4047 return scm_call_2;
4048 default:
4049 return 0; /* not applicable on two args */
4050 }
4051}
4052
d9c393f5
JB
4053/* Typechecking for multi-argument MAP and FOR-EACH.
4054
47c3f06d 4055 Verify that each element of the vector ARGV, except for the first,
d9c393f5 4056 is a proper list whose length is LEN. Attribute errors to WHO,
47c3f06d 4057 and claim that the i'th element of ARGV is WHO's i+2'th argument. */
d9c393f5 4058static inline void
47c3f06d 4059check_map_args (SCM argv,
c014a02e 4060 long len,
47c3f06d
MD
4061 SCM gf,
4062 SCM proc,
4063 SCM args,
4064 const char *who)
d9c393f5 4065{
34d19ef6 4066 SCM const *ve = SCM_VELTS (argv);
c014a02e 4067 long i;
d9c393f5 4068
b5c2579a 4069 for (i = SCM_VECTOR_LENGTH (argv) - 1; i >= 1; i--)
d9c393f5 4070 {
c014a02e 4071 long elt_len = scm_ilength (ve[i]);
d9c393f5
JB
4072
4073 if (elt_len < 0)
47c3f06d
MD
4074 {
4075 if (gf)
4076 scm_apply_generic (gf, scm_cons (proc, args));
4077 else
4078 scm_wrong_type_arg (who, i + 2, ve[i]);
4079 }
d9c393f5
JB
4080
4081 if (elt_len != len)
504d99c5 4082 scm_out_of_range_pos (who, ve[i], SCM_MAKINUM (i + 2));
d9c393f5
JB
4083 }
4084
5d2b97cd 4085 scm_remember_upto_here_1 (argv);
d9c393f5
JB
4086}
4087
4088
47c3f06d 4089SCM_GPROC (s_map, "map", 2, 0, 1, scm_map, g_map);
1cc91f1b 4090
368bf056
MD
4091/* Note: Currently, scm_map applies PROC to the argument list(s)
4092 sequentially, starting with the first element(s). This is used in
8878f040 4093 evalext.c where the Scheme procedure `map-in-order', which guarantees
368bf056 4094 sequential behaviour, is implemented using scm_map. If the
8878f040 4095 behaviour changes, we need to update `map-in-order'.
368bf056
MD
4096*/
4097
0f2d19dd 4098SCM
1bbd0b84 4099scm_map (SCM proc, SCM arg1, SCM args)
af45e3b0 4100#define FUNC_NAME s_map
0f2d19dd 4101{
c014a02e 4102 long i, len;
0f2d19dd
JB
4103 SCM res = SCM_EOL;
4104 SCM *pres = &res;
34d19ef6 4105 SCM const *ve = &args; /* Keep args from being optimized away. */
0f2d19dd 4106
d9c393f5 4107 len = scm_ilength (arg1);
47c3f06d
MD
4108 SCM_GASSERTn (len >= 0,
4109 g_map, scm_cons2 (proc, arg1, args), SCM_ARG2, s_map);
af45e3b0 4110 SCM_VALIDATE_REST_ARGUMENT (args);
0f2d19dd
JB
4111 if (SCM_NULLP (args))
4112 {
504d99c5
MD
4113 scm_t_trampoline_1 call = scm_trampoline_1 (proc);
4114 SCM_GASSERT2 (call, g_map, proc, arg1, SCM_ARG1, s_map);
4115 while (SCM_NIMP (arg1))
4116 {
4117 *pres = scm_list_1 (call (proc, SCM_CAR (arg1)));
4118 pres = SCM_CDRLOC (*pres);
4119 arg1 = SCM_CDR (arg1);
4120 }
4121 return res;
4122 }
4123 if (SCM_NULLP (SCM_CDR (args)))
4124 {
4125 SCM arg2 = SCM_CAR (args);
4126 int len2 = scm_ilength (arg2);
4127 scm_t_trampoline_2 call = scm_trampoline_2 (proc);
4128 SCM_GASSERTn (call,
4129 g_map, scm_cons2 (proc, arg1, args), SCM_ARG1, s_map);
4130 SCM_GASSERTn (len2 >= 0,
4131 g_map, scm_cons2 (proc, arg1, args), SCM_ARG3, s_map);
4132 if (len2 != len)
4133 SCM_OUT_OF_RANGE (3, arg2);
0f2d19dd
JB
4134 while (SCM_NIMP (arg1))
4135 {
504d99c5 4136 *pres = scm_list_1 (call (proc, SCM_CAR (arg1), SCM_CAR (arg2)));
a23afe53 4137 pres = SCM_CDRLOC (*pres);
0f2d19dd 4138 arg1 = SCM_CDR (arg1);
504d99c5 4139 arg2 = SCM_CDR (arg2);
0f2d19dd
JB
4140 }
4141 return res;
4142 }
47c3f06d 4143 args = scm_vector (arg1 = scm_cons (arg1, args));
0f2d19dd 4144 ve = SCM_VELTS (args);
47c3f06d 4145 check_map_args (args, len, g_map, proc, arg1, s_map);
0f2d19dd
JB
4146 while (1)
4147 {
4148 arg1 = SCM_EOL;
b5c2579a 4149 for (i = SCM_VECTOR_LENGTH (args) - 1; i >= 0; i--)
0f2d19dd 4150 {
d9c393f5
JB
4151 if (SCM_IMP (ve[i]))
4152 return res;
0f2d19dd 4153 arg1 = scm_cons (SCM_CAR (ve[i]), arg1);
34d19ef6 4154 SCM_VECTOR_SET (args, i, SCM_CDR (ve[i]));
0f2d19dd 4155 }
8ea46249 4156 *pres = scm_list_1 (scm_apply (proc, arg1, SCM_EOL));
a23afe53 4157 pres = SCM_CDRLOC (*pres);
0f2d19dd
JB
4158 }
4159}
af45e3b0 4160#undef FUNC_NAME
0f2d19dd
JB
4161
4162
47c3f06d 4163SCM_GPROC (s_for_each, "for-each", 2, 0, 1, scm_for_each, g_for_each);
1cc91f1b 4164
0f2d19dd 4165SCM
1bbd0b84 4166scm_for_each (SCM proc, SCM arg1, SCM args)
af45e3b0 4167#define FUNC_NAME s_for_each
0f2d19dd 4168{
34d19ef6 4169 SCM const *ve = &args; /* Keep args from being optimized away. */
c014a02e 4170 long i, len;
d9c393f5 4171 len = scm_ilength (arg1);
47c3f06d
MD
4172 SCM_GASSERTn (len >= 0, g_for_each, scm_cons2 (proc, arg1, args),
4173 SCM_ARG2, s_for_each);
af45e3b0 4174 SCM_VALIDATE_REST_ARGUMENT (args);
c96d76b8 4175 if (SCM_NULLP (args))
0f2d19dd 4176 {
504d99c5
MD
4177 scm_t_trampoline_1 call = scm_trampoline_1 (proc);
4178 SCM_GASSERT2 (call, g_for_each, proc, arg1, SCM_ARG1, s_for_each);
4179 while (SCM_NIMP (arg1))
4180 {
4181 call (proc, SCM_CAR (arg1));
4182 arg1 = SCM_CDR (arg1);
4183 }
4184 return SCM_UNSPECIFIED;
4185 }
4186 if (SCM_NULLP (SCM_CDR (args)))
4187 {
4188 SCM arg2 = SCM_CAR (args);
4189 int len2 = scm_ilength (arg2);
4190 scm_t_trampoline_2 call = scm_trampoline_2 (proc);
4191 SCM_GASSERTn (call, g_for_each,
4192 scm_cons2 (proc, arg1, args), SCM_ARG1, s_for_each);
4193 SCM_GASSERTn (len2 >= 0, g_for_each,
4194 scm_cons2 (proc, arg1, args), SCM_ARG3, s_for_each);
4195 if (len2 != len)
4196 SCM_OUT_OF_RANGE (3, arg2);
c96d76b8 4197 while (SCM_NIMP (arg1))
0f2d19dd 4198 {
504d99c5 4199 call (proc, SCM_CAR (arg1), SCM_CAR (arg2));
0f2d19dd 4200 arg1 = SCM_CDR (arg1);
504d99c5 4201 arg2 = SCM_CDR (arg2);
0f2d19dd
JB
4202 }
4203 return SCM_UNSPECIFIED;
4204 }
47c3f06d 4205 args = scm_vector (arg1 = scm_cons (arg1, args));
0f2d19dd 4206 ve = SCM_VELTS (args);
47c3f06d 4207 check_map_args (args, len, g_for_each, proc, arg1, s_for_each);
0f2d19dd
JB
4208 while (1)
4209 {
4210 arg1 = SCM_EOL;
b5c2579a 4211 for (i = SCM_VECTOR_LENGTH (args) - 1; i >= 0; i--)
0f2d19dd 4212 {
c96d76b8
NJ
4213 if (SCM_IMP (ve[i]))
4214 return SCM_UNSPECIFIED;
0f2d19dd 4215 arg1 = scm_cons (SCM_CAR (ve[i]), arg1);
34d19ef6 4216 SCM_VECTOR_SET (args, i, SCM_CDR (ve[i]));
0f2d19dd
JB
4217 }
4218 scm_apply (proc, arg1, SCM_EOL);
4219 }
4220}
af45e3b0 4221#undef FUNC_NAME
0f2d19dd 4222
1cc91f1b 4223
0f2d19dd 4224SCM
6e8d25a6 4225scm_closure (SCM code, SCM env)
0f2d19dd 4226{
16d4699b
MV
4227 SCM z;
4228 SCM closcar = scm_cons (code, SCM_EOL);
228a24ef 4229 z = scm_cell (SCM_UNPACK (closcar) + scm_tc3_closure, (scm_t_bits) env);
16d4699b 4230 scm_remember_upto_here (closcar);
0f2d19dd
JB
4231 return z;
4232}
4233
4234
92c2555f 4235scm_t_bits scm_tc16_promise;
1cc91f1b 4236
0f2d19dd 4237SCM
6e8d25a6 4238scm_makprom (SCM code)
0f2d19dd 4239{
28d52ebb
MD
4240 SCM_RETURN_NEWSMOB2 (scm_tc16_promise,
4241 SCM_UNPACK (code),
4242 scm_make_rec_mutex ());
0f2d19dd
JB
4243}
4244
28d52ebb
MD
4245static size_t
4246promise_free (SCM promise)
4247{
4248 scm_rec_mutex_free (SCM_PROMISE_MUTEX (promise));
4249 return 0;
4250}
1cc91f1b 4251
0f2d19dd 4252static int
e841c3e0 4253promise_print (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd 4254{
19402679 4255 int writingp = SCM_WRITINGP (pstate);
b7f3516f 4256 scm_puts ("#<promise ", port);
19402679 4257 SCM_SET_WRITINGP (pstate, 1);
28d52ebb 4258 scm_iprin1 (SCM_PROMISE_DATA (exp), port, pstate);
19402679 4259 SCM_SET_WRITINGP (pstate, writingp);
b7f3516f 4260 scm_putc ('>', port);
0f2d19dd
JB
4261 return !0;
4262}
4263
3b3b36dd 4264SCM_DEFINE (scm_force, "force", 1, 0, 0,
28d52ebb 4265 (SCM promise),
67e8151b
MG
4266 "If the promise @var{x} has not been computed yet, compute and\n"
4267 "return @var{x}, otherwise just return the previously computed\n"
4268 "value.")
1bbd0b84 4269#define FUNC_NAME s_scm_force
0f2d19dd 4270{
28d52ebb
MD
4271 SCM_VALIDATE_SMOB (1, promise, promise);
4272 scm_rec_mutex_lock (SCM_PROMISE_MUTEX (promise));
4273 if (!SCM_PROMISE_COMPUTED_P (promise))
0f2d19dd 4274 {
28d52ebb
MD
4275 SCM ans = scm_call_0 (SCM_PROMISE_DATA (promise));
4276 if (!SCM_PROMISE_COMPUTED_P (promise))
0f2d19dd 4277 {
28d52ebb
MD
4278 SCM_SET_PROMISE_DATA (promise, ans);
4279 SCM_SET_PROMISE_COMPUTED (promise);
0f2d19dd
JB
4280 }
4281 }
28d52ebb
MD
4282 scm_rec_mutex_unlock (SCM_PROMISE_MUTEX (promise));
4283 return SCM_PROMISE_DATA (promise);
0f2d19dd 4284}
1bbd0b84 4285#undef FUNC_NAME
0f2d19dd 4286
445f675c 4287
a1ec6916 4288SCM_DEFINE (scm_promise_p, "promise?", 1, 0, 0,
67e8151b 4289 (SCM obj),
b380b885 4290 "Return true if @var{obj} is a promise, i.e. a delayed computation\n"
7a095584 4291 "(@pxref{Delayed evaluation,,,r5rs.info,The Revised^5 Report on Scheme}).")
1bbd0b84 4292#define FUNC_NAME s_scm_promise_p
0f2d19dd 4293{
67e8151b 4294 return SCM_BOOL (SCM_TYP16_PREDICATE (scm_tc16_promise, obj));
0f2d19dd 4295}
1bbd0b84 4296#undef FUNC_NAME
0f2d19dd 4297
445f675c 4298
a1ec6916 4299SCM_DEFINE (scm_cons_source, "cons-source", 3, 0, 0,
1bbd0b84 4300 (SCM xorig, SCM x, SCM y),
11768c04
NJ
4301 "Create and return a new pair whose car and cdr are @var{x} and @var{y}.\n"
4302 "Any source properties associated with @var{xorig} are also associated\n"
4303 "with the new pair.")
1bbd0b84 4304#define FUNC_NAME s_scm_cons_source
26d5b9b4
MD
4305{
4306 SCM p, z;
16d4699b 4307 z = scm_cons (x, y);
26d5b9b4
MD
4308 /* Copy source properties possibly associated with xorig. */
4309 p = scm_whash_lookup (scm_source_whash, xorig);
445f675c 4310 if (!SCM_IMP (p))
26d5b9b4
MD
4311 scm_whash_insert (scm_source_whash, z, p);
4312 return z;
4313}
1bbd0b84 4314#undef FUNC_NAME
26d5b9b4 4315
445f675c 4316
a1ec6916 4317SCM_DEFINE (scm_copy_tree, "copy-tree", 1, 0, 0,
1bbd0b84 4318 (SCM obj),
b380b885
MD
4319 "Recursively copy the data tree that is bound to @var{obj}, and return a\n"
4320 "pointer to the new data structure. @code{copy-tree} recurses down the\n"
4321 "contents of both pairs and vectors (since both cons cells and vector\n"
4322 "cells may point to arbitrary objects), and stops recursing when it hits\n"
4323 "any other object.")
1bbd0b84 4324#define FUNC_NAME s_scm_copy_tree
0f2d19dd
JB
4325{
4326 SCM ans, tl;
26d5b9b4 4327 if (SCM_IMP (obj))
ff467021 4328 return obj;
3910272e
MD
4329 if (SCM_VECTORP (obj))
4330 {
c014a02e 4331 unsigned long i = SCM_VECTOR_LENGTH (obj);
00ffa0e7 4332 ans = scm_c_make_vector (i, SCM_UNSPECIFIED);
3910272e 4333 while (i--)
34d19ef6 4334 SCM_VECTOR_SET (ans, i, scm_copy_tree (SCM_VELTS (obj)[i]));
3910272e
MD
4335 return ans;
4336 }
01f11e02 4337 if (!SCM_CONSP (obj))
0f2d19dd 4338 return obj;
26d5b9b4
MD
4339 ans = tl = scm_cons_source (obj,
4340 scm_copy_tree (SCM_CAR (obj)),
4341 SCM_UNSPECIFIED);
cabe682c 4342 while (obj = SCM_CDR (obj), SCM_CONSP (obj))
a23afe53
MD
4343 {
4344 SCM_SETCDR (tl, scm_cons (scm_copy_tree (SCM_CAR (obj)),
4345 SCM_UNSPECIFIED));
4346 tl = SCM_CDR (tl);
4347 }
4348 SCM_SETCDR (tl, obj);
0f2d19dd
JB
4349 return ans;
4350}
1bbd0b84 4351#undef FUNC_NAME
0f2d19dd 4352
1cc91f1b 4353
4163eb72
MV
4354/* We have three levels of EVAL here:
4355
4356 - scm_i_eval (exp, env)
4357
4358 evaluates EXP in environment ENV. ENV is a lexical environment
4359 structure as used by the actual tree code evaluator. When ENV is
4360 a top-level environment, then changes to the current module are
a513ead3 4361 tracked by updating ENV so that it continues to be in sync with
4163eb72
MV
4362 the current module.
4363
4364 - scm_primitive_eval (exp)
4365
4366 evaluates EXP in the top-level environment as determined by the
4367 current module. This is done by constructing a suitable
4368 environment and calling scm_i_eval. Thus, changes to the
4369 top-level module are tracked normally.
4370
4371 - scm_eval (exp, mod)
4372
a513ead3 4373 evaluates EXP while MOD is the current module. This is done by
4163eb72
MV
4374 setting the current module to MOD, invoking scm_primitive_eval on
4375 EXP, and then restoring the current module to the value it had
4376 previously. That is, while EXP is evaluated, changes to the
4377 current module are tracked, but these changes do not persist when
4378 scm_eval returns.
4379
4380 For each level of evals, there are two variants, distinguished by a
4381 _x suffix: the ordinary variant does not modify EXP while the _x
4382 variant can destructively modify EXP into something completely
4383 unintelligible. A Scheme data structure passed as EXP to one of the
4384 _x variants should not ever be used again for anything. So when in
4385 doubt, use the ordinary variant.
4386
4387*/
4388
0f2d19dd 4389SCM
68d8be66 4390scm_i_eval_x (SCM exp, SCM env)
0f2d19dd 4391{
68d8be66 4392 return SCM_XEVAL (exp, env);
0f2d19dd
JB
4393}
4394
68d8be66
MD
4395SCM
4396scm_i_eval (SCM exp, SCM env)
4397{
26fb6390 4398 exp = scm_copy_tree (exp);
e37a4fba 4399 return SCM_XEVAL (exp, env);
68d8be66
MD
4400}
4401
4402SCM
4163eb72 4403scm_primitive_eval_x (SCM exp)
0f2d19dd 4404{
a513ead3 4405 SCM env;
bcdab802 4406 SCM transformer = scm_current_module_transformer ();
a513ead3 4407 if (SCM_NIMP (transformer))
fdc28395 4408 exp = scm_call_1 (transformer, exp);
a513ead3 4409 env = scm_top_level_env (scm_current_module_lookup_closure ());
4163eb72 4410 return scm_i_eval_x (exp, env);
0f2d19dd
JB
4411}
4412
4163eb72
MV
4413SCM_DEFINE (scm_primitive_eval, "primitive-eval", 1, 0, 0,
4414 (SCM exp),
2069af38 4415 "Evaluate @var{exp} in the top-level environment specified by\n"
4163eb72
MV
4416 "the current module.")
4417#define FUNC_NAME s_scm_primitive_eval
4418{
a513ead3 4419 SCM env;
bcdab802 4420 SCM transformer = scm_current_module_transformer ();
a513ead3 4421 if (SCM_NIMP (transformer))
fdc28395 4422 exp = scm_call_1 (transformer, exp);
a513ead3 4423 env = scm_top_level_env (scm_current_module_lookup_closure ());
4163eb72
MV
4424 return scm_i_eval (exp, env);
4425}
4426#undef FUNC_NAME
4427
68d8be66
MD
4428/* Eval does not take the second arg optionally. This is intentional
4429 * in order to be R5RS compatible, and to prepare for the new module
4430 * system, where we would like to make the choice of evaluation
4163eb72 4431 * environment explicit. */
549e6ec6 4432
09074dbf
DH
4433static void
4434change_environment (void *data)
4435{
4436 SCM pair = SCM_PACK (data);
4437 SCM new_module = SCM_CAR (pair);
aa767bc5 4438 SCM old_module = scm_current_module ();
09074dbf 4439 SCM_SETCDR (pair, old_module);
aa767bc5 4440 scm_set_current_module (new_module);
09074dbf
DH
4441}
4442
4443
09074dbf
DH
4444static void
4445restore_environment (void *data)
4446{
4447 SCM pair = SCM_PACK (data);
4448 SCM old_module = SCM_CDR (pair);
aa767bc5 4449 SCM new_module = scm_current_module ();
2e9c835d 4450 SCM_SETCAR (pair, new_module);
aa767bc5 4451 scm_set_current_module (old_module);
09074dbf
DH
4452}
4453
4163eb72
MV
4454static SCM
4455inner_eval_x (void *data)
4456{
4457 return scm_primitive_eval_x (SCM_PACK(data));
4458}
4459
4460SCM
4461scm_eval_x (SCM exp, SCM module)
4462#define FUNC_NAME "eval!"
4463{
4464 SCM_VALIDATE_MODULE (2, module);
4465
4466 return scm_internal_dynamic_wind
4467 (change_environment, inner_eval_x, restore_environment,
4468 (void *) SCM_UNPACK (exp),
4469 (void *) SCM_UNPACK (scm_cons (module, SCM_BOOL_F)));
4470}
4471#undef FUNC_NAME
4472
4473static SCM
4474inner_eval (void *data)
4475{
4476 return scm_primitive_eval (SCM_PACK(data));
4477}
09074dbf 4478
68d8be66 4479SCM_DEFINE (scm_eval, "eval", 2, 0, 0,
4163eb72
MV
4480 (SCM exp, SCM module),
4481 "Evaluate @var{exp}, a list representing a Scheme expression,\n"
4482 "in the top-level environment specified by @var{module}.\n"
8f85c0c6 4483 "While @var{exp} is evaluated (using @code{primitive-eval}),\n"
4163eb72
MV
4484 "@var{module} is made the current module. The current module\n"
4485 "is reset to its previous value when @var{eval} returns.")
1bbd0b84 4486#define FUNC_NAME s_scm_eval
0f2d19dd 4487{
4163eb72 4488 SCM_VALIDATE_MODULE (2, module);
09074dbf
DH
4489
4490 return scm_internal_dynamic_wind
4491 (change_environment, inner_eval, restore_environment,
4163eb72
MV
4492 (void *) SCM_UNPACK (exp),
4493 (void *) SCM_UNPACK (scm_cons (module, SCM_BOOL_F)));
0f2d19dd 4494}
1bbd0b84 4495#undef FUNC_NAME
0f2d19dd 4496
6dbd0af5
MD
4497
4498/* At this point, scm_deval and scm_dapply are generated.
4499 */
4500
a44a9715
DH
4501#define DEVAL
4502#include "eval.c"
0f2d19dd 4503
1cc91f1b 4504
0f2d19dd
JB
4505void
4506scm_init_eval ()
0f2d19dd 4507{
33b97402
MD
4508 scm_init_opts (scm_evaluator_traps,
4509 scm_evaluator_trap_table,
4510 SCM_N_EVALUATOR_TRAPS);
4511 scm_init_opts (scm_eval_options_interface,
4512 scm_eval_opts,
4513 SCM_N_EVAL_OPTIONS);
4514
f99c9c28
MD
4515 scm_tc16_promise = scm_make_smob_type ("promise", 0);
4516 scm_set_smob_mark (scm_tc16_promise, scm_markcdr);
28d52ebb 4517 scm_set_smob_free (scm_tc16_promise, promise_free);
e841c3e0 4518 scm_set_smob_print (scm_tc16_promise, promise_print);
b8229a3b 4519
a44a9715
DH
4520 undefineds = scm_list_1 (SCM_UNDEFINED);
4521 SCM_SETCDR (undefineds, undefineds);
4522 scm_permanent_object (undefineds);
7c33806a 4523
a44a9715 4524 scm_listofnull = scm_list_1 (SCM_EOL);
0f2d19dd 4525
a44a9715
DH
4526 f_apply = scm_c_define_subr ("apply", scm_tc7_lsubr_2, scm_apply);
4527 scm_permanent_object (f_apply);
86d31dfe 4528
a0599745 4529#include "libguile/eval.x"
86d31dfe 4530
25eaf21a 4531 scm_add_feature ("delay");
0f2d19dd 4532}
0f2d19dd 4533
6dbd0af5 4534#endif /* !DEVAL */
89e00824
ML
4535
4536/*
4537 Local Variables:
4538 c-file-style: "gnu"
4539 End:
4540*/