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