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