* backtrace.c, debug.c, debug.h, deprecation.c, eq.c, eval.c
[bpt/guile.git] / libguile / eval.c
CommitLineData
2b829bbb 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006
434f2f7a 2 * Free Software Foundation, Inc.
0f2d19dd 3 *
73be1d9e
MV
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
0f2d19dd 8 *
73be1d9e
MV
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
0f2d19dd 13 *
73be1d9e
MV
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
92205699 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
73be1d9e 17 */
1bbd0b84 18
0f2d19dd
JB
19\f
20
de527efb
MV
21#define _GNU_SOURCE
22
434f2f7a
DH
23/* This file is read twice in order to produce debugging versions of ceval and
24 * scm_apply. These functions, deval and scm_dapply, are produced when we
25 * define the preprocessor macro DEVAL. The file is divided into sections
26 * which are treated differently with respect to DEVAL. The heads of these
27 * sections are marked with the string "SECTION:". */
6dbd0af5 28
6dbd0af5 29/* SECTION: This code is compiled once.
0f2d19dd
JB
30 */
31
3d05f2e0
RB
32#if HAVE_CONFIG_H
33# include <config.h>
34#endif
0f2d19dd 35
3d05f2e0
RB
36#include "libguile/__scm.h"
37
38#ifndef DEVAL
d16332b3 39
8ab3d8a0
KR
40/* This blob per the Autoconf manual (under "Particular Functions"). */
41#if HAVE_ALLOCA_H
42# include <alloca.h>
43#elif defined __GNUC__
44# define alloca __builtin_alloca
45#elif defined _AIX
46# define alloca __alloca
47#elif defined _MSC_VER
48# include <malloc.h>
49# define alloca _alloca
50#else
51# include <stddef.h>
52# ifdef __cplusplus
53extern "C"
48b96f4b 54# endif
8ab3d8a0 55void *alloca (size_t);
23f2b9a3 56#endif
48b96f4b 57
e7313a9d 58#include <assert.h>
a0599745 59#include "libguile/_scm.h"
21628685
DH
60#include "libguile/alist.h"
61#include "libguile/async.h"
62#include "libguile/continuations.h"
a0599745 63#include "libguile/debug.h"
328dc9a3 64#include "libguile/deprecation.h"
09074dbf 65#include "libguile/dynwind.h"
a0599745 66#include "libguile/eq.h"
21628685
DH
67#include "libguile/feature.h"
68#include "libguile/fluids.h"
756414cf 69#include "libguile/futures.h"
21628685
DH
70#include "libguile/goops.h"
71#include "libguile/hash.h"
72#include "libguile/hashtab.h"
73#include "libguile/lang.h"
4610b011 74#include "libguile/list.h"
a0599745 75#include "libguile/macros.h"
a0599745 76#include "libguile/modules.h"
21628685 77#include "libguile/objects.h"
a0599745 78#include "libguile/ports.h"
7e6e6b37 79#include "libguile/print.h"
21628685 80#include "libguile/procprop.h"
a0599745 81#include "libguile/root.h"
21628685
DH
82#include "libguile/smob.h"
83#include "libguile/srcprop.h"
84#include "libguile/stackchk.h"
85#include "libguile/strings.h"
9de87eea 86#include "libguile/threads.h"
21628685
DH
87#include "libguile/throw.h"
88#include "libguile/validate.h"
a513ead3 89#include "libguile/values.h"
21628685 90#include "libguile/vectors.h"
a0599745 91
a0599745 92#include "libguile/eval.h"
89efbff4 93
0f2d19dd
JB
94\f
95
212e58ed 96static SCM unmemoize_exprs (SCM expr, SCM env);
0f572ba7 97static SCM canonicalize_define (SCM expr);
e5156567 98static SCM *scm_lookupcar1 (SCM vloc, SCM genv, int check);
212e58ed 99static SCM unmemoize_builtin_macro (SCM expr, SCM env);
5defc05d 100static void eval_letrec_inits (SCM env, SCM init_forms, SCM **init_values_eol);
0f572ba7 101
72f19c26 102
0f572ba7
DH
103\f
104
e6729603
DH
105/* {Syntax Errors}
106 *
107 * This section defines the message strings for the syntax errors that can be
108 * detected during memoization and the functions and macros that shall be
109 * called by the memoizer code to signal syntax errors. */
110
111
112/* Syntax errors that can be detected during memoization: */
113
114/* Circular or improper lists do not form valid scheme expressions. If a
115 * circular list or an improper list is detected in a place where a scheme
116 * expression is expected, a 'Bad expression' error is signalled. */
117static const char s_bad_expression[] = "Bad expression";
118
89bff2fc
DH
119/* If a form is detected that holds a different number of expressions than are
120 * required in that context, a 'Missing or extra expression' error is
121 * signalled. */
122static const char s_expression[] = "Missing or extra expression in";
123
cc56ba80 124/* If a form is detected that holds less expressions than are required in that
8ae95199 125 * context, a 'Missing expression' error is signalled. */
cc56ba80
DH
126static const char s_missing_expression[] = "Missing expression in";
127
609a8b86 128/* If a form is detected that holds more expressions than are allowed in that
8ae95199 129 * context, an 'Extra expression' error is signalled. */
609a8b86
DH
130static const char s_extra_expression[] = "Extra expression in";
131
89bff2fc
DH
132/* The empty combination '()' is not allowed as an expression in scheme. If
133 * it is detected in a place where an expression is expected, an 'Illegal
134 * empty combination' error is signalled. Note: If you encounter this error
135 * message, it is very likely that you intended to denote the empty list. To
136 * do so, you need to quote the empty list like (quote ()) or '(). */
137static const char s_empty_combination[] = "Illegal empty combination";
138
c86c440b
DH
139/* A body may hold an arbitrary number of internal defines, followed by a
140 * non-empty sequence of expressions. If a body with an empty sequence of
141 * expressions is detected, a 'Missing body expression' error is signalled.
142 */
143static const char s_missing_body_expression[] = "Missing body expression in";
144
145/* A body may hold an arbitrary number of internal defines, followed by a
146 * non-empty sequence of expressions. Each the definitions and the
147 * expressions may be grouped arbitraryly with begin, but it is not allowed to
148 * mix definitions and expressions. If a define form in a body mixes
149 * definitions and expressions, a 'Mixed definitions and expressions' error is
6bff1368 150 * signalled. */
c86c440b 151static const char s_mixed_body_forms[] = "Mixed definitions and expressions in";
6bff1368
DH
152/* Definitions are only allowed on the top level and at the start of a body.
153 * If a definition is detected anywhere else, a 'Bad define placement' error
154 * is signalled. */
155static const char s_bad_define[] = "Bad define placement";
c86c440b 156
2a6f7afe
DH
157/* Case or cond expressions must have at least one clause. If a case or cond
158 * expression without any clauses is detected, a 'Missing clauses' error is
159 * signalled. */
160static const char s_missing_clauses[] = "Missing clauses";
161
609a8b86
DH
162/* If there is an 'else' clause in a case or a cond statement, it must be the
163 * last clause. If after the 'else' case clause further clauses are detected,
164 * a 'Misplaced else clause' error is signalled. */
165static const char s_misplaced_else_clause[] = "Misplaced else clause";
166
2a6f7afe
DH
167/* If a case clause is detected that is not in the format
168 * (<label(s)> <expression1> <expression2> ...)
169 * a 'Bad case clause' error is signalled. */
170static const char s_bad_case_clause[] = "Bad case clause";
171
2a6f7afe
DH
172/* If a case clause is detected where the <label(s)> element is neither a
173 * proper list nor (in case of the last clause) the syntactic keyword 'else',
174 * a 'Bad case labels' error is signalled. Note: If you encounter this error
175 * for an else-clause which seems to be syntactically correct, check if 'else'
176 * is really a syntactic keyword in that context. If 'else' is bound in the
177 * local or global environment, it is not considered a syntactic keyword, but
178 * will be treated as any other variable. */
179static const char s_bad_case_labels[] = "Bad case labels";
180
181/* In a case statement all labels have to be distinct. If in a case statement
182 * a label occurs more than once, a 'Duplicate case label' error is
183 * signalled. */
184static const char s_duplicate_case_label[] = "Duplicate case label";
185
609a8b86
DH
186/* If a cond clause is detected that is not in one of the formats
187 * (<test> <expression1> ...) or (else <expression1> <expression2> ...)
188 * a 'Bad cond clause' error is signalled. */
189static const char s_bad_cond_clause[] = "Bad cond clause";
190
191/* If a cond clause is detected that uses the alternate '=>' form, but does
192 * not hold a recipient element for the test result, a 'Missing recipient'
193 * error is signalled. */
194static const char s_missing_recipient[] = "Missing recipient in";
195
cc56ba80
DH
196/* If in a position where a variable name is required some other object is
197 * detected, a 'Bad variable' error is signalled. */
198static const char s_bad_variable[] = "Bad variable";
199
a954ce1d
DH
200/* Bindings for forms like 'let' and 'do' have to be given in a proper,
201 * possibly empty list. If any other object is detected in a place where a
202 * list of bindings was required, a 'Bad bindings' error is signalled. */
203static const char s_bad_bindings[] = "Bad bindings";
204
205/* Depending on the syntactic context, a binding has to be in the format
206 * (<variable> <expression>) or (<variable> <expression1> <expression2>).
207 * If anything else is detected in a place where a binding was expected, a
208 * 'Bad binding' error is signalled. */
209static const char s_bad_binding[] = "Bad binding";
210
4610b011
DH
211/* Some syntactic forms don't allow variable names to appear more than once in
212 * a list of bindings. If such a situation is nevertheless detected, a
213 * 'Duplicate binding' error is signalled. */
214static const char s_duplicate_binding[] = "Duplicate binding";
215
a954ce1d
DH
216/* If the exit form of a 'do' expression is not in the format
217 * (<test> <expression> ...)
218 * a 'Bad exit clause' error is signalled. */
219static const char s_bad_exit_clause[] = "Bad exit clause";
220
03a3e941
DH
221/* The formal function arguments of a lambda expression have to be either a
222 * single symbol or a non-cyclic list. For anything else a 'Bad formals'
223 * error is signalled. */
224static const char s_bad_formals[] = "Bad formals";
225
226/* If in a lambda expression something else than a symbol is detected at a
227 * place where a formal function argument is required, a 'Bad formal' error is
228 * signalled. */
229static const char s_bad_formal[] = "Bad formal";
230
231/* If in the arguments list of a lambda expression an argument name occurs
232 * more than once, a 'Duplicate formal' error is signalled. */
233static const char s_duplicate_formal[] = "Duplicate formal";
234
6f81708a
DH
235/* If the evaluation of an unquote-splicing expression gives something else
236 * than a proper list, a 'Non-list result for unquote-splicing' error is
237 * signalled. */
238static const char s_splicing[] = "Non-list result for unquote-splicing";
239
9a848baf
DH
240/* If something else than an exact integer is detected as the argument for
241 * @slot-ref and @slot-set!, a 'Bad slot number' error is signalled. */
242static const char s_bad_slot_number[] = "Bad slot number";
243
e6729603
DH
244
245/* Signal a syntax error. We distinguish between the form that caused the
246 * error and the enclosing expression. The error message will print out as
247 * shown in the following pattern. The file name and line number are only
248 * given when they can be determined from the erroneous form or from the
249 * enclosing expression.
250 *
251 * <filename>: In procedure memoization:
252 * <filename>: In file <name>, line <nr>: <error-message> in <expression>. */
253
254SCM_SYMBOL (syntax_error_key, "syntax-error");
255
256/* The prototype is needed to indicate that the function does not return. */
257static void
258syntax_error (const char* const, const SCM, const SCM) SCM_NORETURN;
259
260static void
261syntax_error (const char* const msg, const SCM form, const SCM expr)
262{
cc95e00a 263 SCM msg_string = scm_from_locale_string (msg);
e6729603
DH
264 SCM filename = SCM_BOOL_F;
265 SCM linenr = SCM_BOOL_F;
266 const char *format;
267 SCM args;
268
a61f4e0c 269 if (scm_is_pair (form))
e6729603
DH
270 {
271 filename = scm_source_property (form, scm_sym_filename);
272 linenr = scm_source_property (form, scm_sym_line);
273 }
274
a61f4e0c 275 if (scm_is_false (filename) && scm_is_false (linenr) && scm_is_pair (expr))
e6729603
DH
276 {
277 filename = scm_source_property (expr, scm_sym_filename);
278 linenr = scm_source_property (expr, scm_sym_line);
279 }
280
281 if (!SCM_UNBNDP (expr))
282 {
7888309b 283 if (scm_is_true (filename))
e6729603
DH
284 {
285 format = "In file ~S, line ~S: ~A ~S in expression ~S.";
286 args = scm_list_5 (filename, linenr, msg_string, form, expr);
287 }
7888309b 288 else if (scm_is_true (linenr))
e6729603
DH
289 {
290 format = "In line ~S: ~A ~S in expression ~S.";
291 args = scm_list_4 (linenr, msg_string, form, expr);
292 }
293 else
294 {
295 format = "~A ~S in expression ~S.";
296 args = scm_list_3 (msg_string, form, expr);
297 }
298 }
299 else
300 {
7888309b 301 if (scm_is_true (filename))
e6729603
DH
302 {
303 format = "In file ~S, line ~S: ~A ~S.";
304 args = scm_list_4 (filename, linenr, msg_string, form);
305 }
7888309b 306 else if (scm_is_true (linenr))
e6729603
DH
307 {
308 format = "In line ~S: ~A ~S.";
309 args = scm_list_3 (linenr, msg_string, form);
310 }
311 else
312 {
313 format = "~A ~S.";
314 args = scm_list_2 (msg_string, form);
315 }
316 }
317
318 scm_error (syntax_error_key, "memoization", format, args, SCM_BOOL_F);
319}
320
321
322/* Shortcut macros to simplify syntax error handling. */
323#define ASSERT_SYNTAX(cond, message, form) \
324 { if (!(cond)) syntax_error (message, form, SCM_UNDEFINED); }
325#define ASSERT_SYNTAX_2(cond, message, form, expr) \
326 { if (!(cond)) syntax_error (message, form, expr); }
327
328\f
329
d0624e39
DH
330/* {Ilocs}
331 *
332 * Ilocs are memoized references to variables in local environment frames.
333 * They are represented as three values: The relative offset of the
334 * environment frame, the number of the binding within that frame, and a
335 * boolean value indicating whether the binding is the last binding in the
336 * frame.
a55c2b68
MV
337 *
338 * Frame numbers have 11 bits, relative offsets have 12 bits.
d0624e39 339 */
7e6e6b37 340
d0624e39 341#define SCM_ILOC00 SCM_MAKE_ITAG8(0L, scm_tc8_iloc)
7e6e6b37
DH
342#define SCM_IFRINC (0x00000100L)
343#define SCM_ICDR (0x00080000L)
d0624e39 344#define SCM_IDINC (0x00100000L)
7e6e6b37
DH
345#define SCM_IFRAME(n) ((long)((SCM_ICDR-SCM_IFRINC)>>8) \
346 & (SCM_UNPACK (n) >> 8))
347#define SCM_IDIST(n) (SCM_UNPACK (n) >> 20)
348#define SCM_ICDRP(n) (SCM_ICDR & SCM_UNPACK (n))
d0624e39 349#define SCM_IDSTMSK (-SCM_IDINC)
a55c2b68
MV
350#define SCM_IFRAMEMAX ((1<<11)-1)
351#define SCM_IDISTMAX ((1<<12)-1)
d0624e39
DH
352#define SCM_MAKE_ILOC(frame_nr, binding_nr, last_p) \
353 SCM_PACK ( \
354 ((frame_nr) << 8) \
355 + ((binding_nr) << 20) \
356 + ((last_p) ? SCM_ICDR : 0) \
357 + scm_tc8_iloc )
358
7e6e6b37
DH
359void
360scm_i_print_iloc (SCM iloc, SCM port)
361{
362 scm_puts ("#@", port);
363 scm_intprint ((long) SCM_IFRAME (iloc), 10, port);
364 scm_putc (SCM_ICDRP (iloc) ? '-' : '+', port);
365 scm_intprint ((long) SCM_IDIST (iloc), 10, port);
366}
367
d0624e39
DH
368#if (SCM_DEBUG_DEBUGGING_SUPPORT == 1)
369
370SCM scm_dbg_make_iloc (SCM frame, SCM binding, SCM cdrp);
90df793f 371
d0624e39
DH
372SCM_DEFINE (scm_dbg_make_iloc, "dbg-make-iloc", 3, 0, 0,
373 (SCM frame, SCM binding, SCM cdrp),
374 "Return a new iloc with frame offset @var{frame}, binding\n"
375 "offset @var{binding} and the cdr flag @var{cdrp}.")
376#define FUNC_NAME s_scm_dbg_make_iloc
377{
c3c97a34
KR
378 return SCM_MAKE_ILOC ((scm_t_bits) scm_to_unsigned_integer (frame, 0, SCM_IFRAMEMAX),
379 (scm_t_bits) scm_to_unsigned_integer (binding, 0, SCM_IDISTMAX),
7888309b 380 scm_is_true (cdrp));
d0624e39
DH
381}
382#undef FUNC_NAME
383
384SCM scm_dbg_iloc_p (SCM obj);
90df793f 385
d0624e39
DH
386SCM_DEFINE (scm_dbg_iloc_p, "dbg-iloc?", 1, 0, 0,
387 (SCM obj),
388 "Return @code{#t} if @var{obj} is an iloc.")
389#define FUNC_NAME s_scm_dbg_iloc_p
390{
7888309b 391 return scm_from_bool (SCM_ILOCP (obj));
d0624e39
DH
392}
393#undef FUNC_NAME
394
395#endif
396
397\f
398
7e6e6b37
DH
399/* {Evaluator byte codes (isyms)}
400 */
401
402#define ISYMNUM(n) (SCM_ITAG8_DATA (n))
403
404/* This table must agree with the list of SCM_IM_ constants in tags.h */
405static const char *const isymnames[] =
406{
407 "#@and",
408 "#@begin",
409 "#@case",
410 "#@cond",
411 "#@do",
412 "#@if",
413 "#@lambda",
414 "#@let",
415 "#@let*",
416 "#@letrec",
417 "#@or",
418 "#@quote",
419 "#@set!",
420 "#@define",
421 "#@apply",
422 "#@call-with-current-continuation",
423 "#@dispatch",
424 "#@slot-ref",
425 "#@slot-set!",
426 "#@delay",
427 "#@future",
428 "#@call-with-values",
429 "#@else",
430 "#@arrow",
431 "#@nil-cond",
432 "#@bind"
433};
434
435void
436scm_i_print_isym (SCM isym, SCM port)
437{
438 const size_t isymnum = ISYMNUM (isym);
439 if (isymnum < (sizeof isymnames / sizeof (char *)))
440 scm_puts (isymnames[isymnum], port);
441 else
442 scm_ipruk ("isym", isym, port);
443}
444
445\f
446
e5156567
DH
447/* The function lookup_symbol is used during memoization: Lookup the symbol in
448 * the environment. If there is no binding for the symbol, SCM_UNDEFINED is
57d23e25
DH
449 * returned. If the symbol is a global variable, the variable object to which
450 * the symbol is bound is returned. Finally, if the symbol is a local
451 * variable the corresponding iloc object is returned. */
6f81708a
DH
452
453/* A helper function for lookup_symbol: Try to find the symbol in the top
454 * level environment frame. The function returns SCM_UNDEFINED if the symbol
57d23e25
DH
455 * is unbound and it returns a variable object if the symbol is a global
456 * variable. */
6f81708a
DH
457static SCM
458lookup_global_symbol (const SCM symbol, const SCM top_level)
459{
460 const SCM variable = scm_sym2var (symbol, top_level, SCM_BOOL_F);
7888309b 461 if (scm_is_false (variable))
57d23e25 462 return SCM_UNDEFINED;
6f81708a 463 else
57d23e25 464 return variable;
6f81708a
DH
465}
466
467static SCM
468lookup_symbol (const SCM symbol, const SCM env)
469{
470 SCM frame_idx;
471 unsigned int frame_nr;
472
473 for (frame_idx = env, frame_nr = 0;
a61f4e0c 474 !scm_is_null (frame_idx);
6f81708a
DH
475 frame_idx = SCM_CDR (frame_idx), ++frame_nr)
476 {
477 const SCM frame = SCM_CAR (frame_idx);
a61f4e0c 478 if (scm_is_pair (frame))
6f81708a
DH
479 {
480 /* frame holds a local environment frame */
481 SCM symbol_idx;
482 unsigned int symbol_nr;
483
484 for (symbol_idx = SCM_CAR (frame), symbol_nr = 0;
a61f4e0c 485 scm_is_pair (symbol_idx);
6f81708a
DH
486 symbol_idx = SCM_CDR (symbol_idx), ++symbol_nr)
487 {
bc36d050 488 if (scm_is_eq (SCM_CAR (symbol_idx), symbol))
6f81708a
DH
489 /* found the symbol, therefore return the iloc */
490 return SCM_MAKE_ILOC (frame_nr, symbol_nr, 0);
491 }
bc36d050 492 if (scm_is_eq (symbol_idx, symbol))
6f81708a
DH
493 /* found the symbol as the last element of the current frame */
494 return SCM_MAKE_ILOC (frame_nr, symbol_nr, 1);
495 }
496 else
497 {
498 /* no more local environment frames */
499 return lookup_global_symbol (symbol, frame);
500 }
501 }
502
503 return lookup_global_symbol (symbol, SCM_BOOL_F);
504}
505
506
507/* Return true if the symbol is - from the point of view of a macro
508 * transformer - a literal in the sense specified in chapter "pattern
509 * language" of R5RS. In the code below, however, we don't match the
510 * definition of R5RS exactly: It returns true if the identifier has no
511 * binding or if it is a syntactic keyword. */
512static int
513literal_p (const SCM symbol, const SCM env)
514{
57d23e25
DH
515 const SCM variable = lookup_symbol (symbol, env);
516 if (SCM_UNBNDP (variable))
517 return 1;
518 if (SCM_VARIABLEP (variable) && SCM_MACROP (SCM_VARIABLE_REF (variable)))
6f81708a
DH
519 return 1;
520 else
521 return 0;
522}
17fa3fcf 523
5fb64383
DH
524
525/* Return true if the expression is self-quoting in the memoized code. Thus,
526 * some other objects (like e. g. vectors) are reported as self-quoting, which
527 * according to R5RS would need to be quoted. */
528static int
529is_self_quoting_p (const SCM expr)
530{
a61f4e0c 531 if (scm_is_pair (expr))
5fb64383 532 return 0;
cc95e00a 533 else if (scm_is_symbol (expr))
5fb64383 534 return 0;
a61f4e0c 535 else if (scm_is_null (expr))
5fb64383
DH
536 return 0;
537 else return 1;
538}
539
0f2d19dd 540
212e58ed
DH
541SCM_SYMBOL (sym_three_question_marks, "???");
542
543static SCM
544unmemoize_expression (const SCM expr, const SCM env)
545{
546 if (SCM_ILOCP (expr))
547 {
548 SCM frame_idx;
549 unsigned long int frame_nr;
550 SCM symbol_idx;
551 unsigned long int symbol_nr;
552
553 for (frame_idx = env, frame_nr = SCM_IFRAME (expr);
554 frame_nr != 0;
555 frame_idx = SCM_CDR (frame_idx), --frame_nr)
556 ;
557 for (symbol_idx = SCM_CAAR (frame_idx), symbol_nr = SCM_IDIST (expr);
558 symbol_nr != 0;
559 symbol_idx = SCM_CDR (symbol_idx), --symbol_nr)
560 ;
561 return SCM_ICDRP (expr) ? symbol_idx : SCM_CAR (symbol_idx);
562 }
563 else if (SCM_VARIABLEP (expr))
564 {
565 const SCM sym = scm_module_reverse_lookup (scm_env_module (env), expr);
7888309b 566 return scm_is_true (sym) ? sym : sym_three_question_marks;
212e58ed 567 }
4057a3e0 568 else if (scm_is_simple_vector (expr))
212e58ed
DH
569 {
570 return scm_list_2 (scm_sym_quote, expr);
571 }
a61f4e0c 572 else if (!scm_is_pair (expr))
212e58ed
DH
573 {
574 return expr;
575 }
576 else if (SCM_ISYMP (SCM_CAR (expr)))
577 {
578 return unmemoize_builtin_macro (expr, env);
579 }
580 else
581 {
582 return unmemoize_exprs (expr, env);
583 }
584}
585
586
587static SCM
588unmemoize_exprs (const SCM exprs, const SCM env)
589{
90df793f 590 SCM r_result = SCM_EOL;
9fcf3cbb 591 SCM expr_idx = exprs;
90df793f
DH
592 SCM um_expr;
593
594 /* Note that due to the current lazy memoizer we may find partially memoized
5fa0939c 595 * code during execution. In such code we have to expect improper lists of
90df793f
DH
596 * expressions: On the one hand, for such code syntax checks have not yet
597 * fully been performed, on the other hand, there may be even legal code
598 * like '(a . b) appear as an improper list of expressions as long as the
599 * quote expression is still in its unmemoized form. For this reason, the
600 * following code handles improper lists of expressions until memoization
601 * and execution have been completely separated. */
a61f4e0c 602 for (; scm_is_pair (expr_idx); expr_idx = SCM_CDR (expr_idx))
212e58ed
DH
603 {
604 const SCM expr = SCM_CAR (expr_idx);
5fa0939c
DH
605
606 /* In partially memoized code, lists of expressions that stem from a
607 * body form may start with an ISYM if the body itself has not yet been
608 * memoized. This isym is just an internal marker to indicate that the
609 * body still needs to be memoized. An isym may occur at the very
610 * beginning of the body or after one or more comment strings. It is
611 * dropped during unmemoization. */
612 if (!SCM_ISYMP (expr))
613 {
614 um_expr = unmemoize_expression (expr, env);
615 r_result = scm_cons (um_expr, r_result);
616 }
90df793f
DH
617 }
618 um_expr = unmemoize_expression (expr_idx, env);
a61f4e0c 619 if (!scm_is_null (r_result))
90df793f
DH
620 {
621 const SCM result = scm_reverse_x (r_result, SCM_UNDEFINED);
622 SCM_SETCDR (r_result, um_expr);
623 return result;
624 }
625 else
626 {
627 return um_expr;
212e58ed 628 }
212e58ed
DH
629}
630
631
34adf7ea
DH
632/* Rewrite the body (which is given as the list of expressions forming the
633 * body) into its internal form. The internal form of a body (<expr> ...) is
634 * just the body itself, but prefixed with an ISYM that denotes to what kind
635 * of outer construct this body belongs: (<ISYM> <expr> ...). A lambda body
636 * starts with SCM_IM_LAMBDA, for example, a body of a let starts with
6bff1368 637 * SCM_IM_LET, etc.
34adf7ea
DH
638 *
639 * It is assumed that the calling expression has already made sure that the
640 * body is a proper list. */
26d5b9b4 641static SCM
430b8401 642m_body (SCM op, SCM exprs)
26d5b9b4 643{
26d5b9b4 644 /* Don't add another ISYM if one is present already. */
34adf7ea
DH
645 if (SCM_ISYMP (SCM_CAR (exprs)))
646 return exprs;
647 else
648 return scm_cons (op, exprs);
26d5b9b4
MD
649}
650
1cc91f1b 651
57d23e25
DH
652/* The function m_expand_body memoizes a proper list of expressions forming a
653 * body. This function takes care of dealing with internal defines and
654 * transforming them into an equivalent letrec expression. The list of
655 * expressions is rewritten in place. */
910b5125 656
57d23e25
DH
657/* This is a helper function for m_expand_body. If the argument expression is
658 * a symbol that denotes a syntactic keyword, the corresponding macro object
659 * is returned, in all other cases the function returns SCM_UNDEFINED. */
910b5125
DH
660static SCM
661try_macro_lookup (const SCM expr, const SCM env)
662{
cc95e00a 663 if (scm_is_symbol (expr))
910b5125 664 {
57d23e25
DH
665 const SCM variable = lookup_symbol (expr, env);
666 if (SCM_VARIABLEP (variable))
667 {
668 const SCM value = SCM_VARIABLE_REF (variable);
669 if (SCM_MACROP (value))
670 return value;
671 }
910b5125 672 }
57d23e25
DH
673
674 return SCM_UNDEFINED;
910b5125
DH
675}
676
677/* This is a helper function for m_expand_body. It expands user macros,
678 * because for the correct translation of a body we need to know whether they
679 * expand to a definition. */
680static SCM
681expand_user_macros (SCM expr, const SCM env)
682{
a61f4e0c 683 while (scm_is_pair (expr))
910b5125
DH
684 {
685 const SCM car_expr = SCM_CAR (expr);
686 const SCM new_car = expand_user_macros (car_expr, env);
687 const SCM value = try_macro_lookup (new_car, env);
688
689 if (SCM_MACROP (value) && SCM_MACRO_TYPE (value) == 2)
690 {
691 /* User macros transform code into code. */
692 expr = scm_call_2 (SCM_MACRO_CODE (value), expr, env);
693 /* We need to reiterate on the transformed code. */
694 }
695 else
696 {
697 /* No user macro: return. */
698 SCM_SETCAR (expr, new_car);
699 return expr;
700 }
701 }
702
703 return expr;
704}
705
706/* This is a helper function for m_expand_body. It determines if a given form
707 * represents an application of a given built-in macro. The built-in macro to
708 * check for is identified by its syntactic keyword. The form is an
709 * application of the given macro if looking up the car of the form in the
710 * given environment actually returns the built-in macro. */
711static int
712is_system_macro_p (const SCM syntactic_keyword, const SCM form, const SCM env)
713{
a61f4e0c 714 if (scm_is_pair (form))
910b5125
DH
715 {
716 const SCM car_form = SCM_CAR (form);
717 const SCM value = try_macro_lookup (car_form, env);
718 if (SCM_BUILTIN_MACRO_P (value))
719 {
720 const SCM macro_name = scm_macro_name (value);
bc36d050 721 return scm_is_eq (macro_name, syntactic_keyword);
910b5125
DH
722 }
723 }
724
725 return 0;
726}
727
9d4bf6d3 728static void
910b5125
DH
729m_expand_body (const SCM forms, const SCM env)
730{
731 /* The first body form can be skipped since it is known to be the ISYM that
732 * was prepended to the body by m_body. */
733 SCM cdr_forms = SCM_CDR (forms);
734 SCM form_idx = cdr_forms;
735 SCM definitions = SCM_EOL;
736 SCM sequence = SCM_EOL;
737
738 /* According to R5RS, the list of body forms consists of two parts: a number
739 * (maybe zero) of definitions, followed by a non-empty sequence of
740 * expressions. Each the definitions and the expressions may be grouped
741 * arbitrarily with begin, but it is not allowed to mix definitions and
742 * expressions. The task of the following loop therefore is to split the
743 * list of body forms into the list of definitions and the sequence of
744 * expressions. */
a61f4e0c 745 while (!scm_is_null (form_idx))
910b5125
DH
746 {
747 const SCM form = SCM_CAR (form_idx);
748 const SCM new_form = expand_user_macros (form, env);
749 if (is_system_macro_p (scm_sym_define, new_form, env))
750 {
751 definitions = scm_cons (new_form, definitions);
752 form_idx = SCM_CDR (form_idx);
753 }
754 else if (is_system_macro_p (scm_sym_begin, new_form, env))
755 {
756 /* We have encountered a group of forms. This has to be either a
757 * (possibly empty) group of (possibly further grouped) definitions,
758 * or a non-empty group of (possibly further grouped)
759 * expressions. */
760 const SCM grouped_forms = SCM_CDR (new_form);
761 unsigned int found_definition = 0;
762 unsigned int found_expression = 0;
763 SCM grouped_form_idx = grouped_forms;
a61f4e0c 764 while (!found_expression && !scm_is_null (grouped_form_idx))
910b5125
DH
765 {
766 const SCM inner_form = SCM_CAR (grouped_form_idx);
767 const SCM new_inner_form = expand_user_macros (inner_form, env);
768 if (is_system_macro_p (scm_sym_define, new_inner_form, env))
769 {
770 found_definition = 1;
771 definitions = scm_cons (new_inner_form, definitions);
772 grouped_form_idx = SCM_CDR (grouped_form_idx);
773 }
774 else if (is_system_macro_p (scm_sym_begin, new_inner_form, env))
775 {
776 const SCM inner_group = SCM_CDR (new_inner_form);
777 grouped_form_idx
778 = scm_append (scm_list_2 (inner_group,
779 SCM_CDR (grouped_form_idx)));
780 }
781 else
782 {
783 /* The group marks the start of the expressions of the body.
784 * We have to make sure that within the same group we have
785 * not encountered a definition before. */
786 ASSERT_SYNTAX (!found_definition, s_mixed_body_forms, form);
787 found_expression = 1;
788 grouped_form_idx = SCM_EOL;
789 }
790 }
791
792 /* We have finished processing the group. If we have not yet
793 * encountered an expression we continue processing the forms of the
794 * body to collect further definition forms. Otherwise, the group
795 * marks the start of the sequence of expressions of the body. */
796 if (!found_expression)
797 {
798 form_idx = SCM_CDR (form_idx);
799 }
800 else
801 {
802 sequence = form_idx;
803 form_idx = SCM_EOL;
804 }
805 }
806 else
807 {
808 /* We have detected a form which is no definition. This marks the
809 * start of the sequence of expressions of the body. */
810 sequence = form_idx;
811 form_idx = SCM_EOL;
812 }
813 }
814
815 /* FIXME: forms does not hold information about the file location. */
a61f4e0c 816 ASSERT_SYNTAX (scm_is_pair (sequence), s_missing_body_expression, cdr_forms);
910b5125 817
a61f4e0c 818 if (!scm_is_null (definitions))
910b5125
DH
819 {
820 SCM definition_idx;
821 SCM letrec_tail;
822 SCM letrec_expression;
823 SCM new_letrec_expression;
910b5125
DH
824
825 SCM bindings = SCM_EOL;
826 for (definition_idx = definitions;
a61f4e0c 827 !scm_is_null (definition_idx);
910b5125
DH
828 definition_idx = SCM_CDR (definition_idx))
829 {
830 const SCM definition = SCM_CAR (definition_idx);
831 const SCM canonical_definition = canonicalize_define (definition);
832 const SCM binding = SCM_CDR (canonical_definition);
833 bindings = scm_cons (binding, bindings);
834 };
835
836 letrec_tail = scm_cons (bindings, sequence);
837 /* FIXME: forms does not hold information about the file location. */
838 letrec_expression = scm_cons_source (forms, scm_sym_letrec, letrec_tail);
839 new_letrec_expression = scm_m_letrec (letrec_expression, env);
9d4bf6d3
MV
840 SCM_SETCAR (forms, new_letrec_expression);
841 SCM_SETCDR (forms, SCM_EOL);
910b5125
DH
842 }
843 else
844 {
845 SCM_SETCAR (forms, SCM_CAR (sequence));
846 SCM_SETCDR (forms, SCM_CDR (sequence));
910b5125
DH
847 }
848}
849
2b189e65
MV
850static SCM
851macroexp (SCM x, SCM env)
852{
853 SCM res, proc, orig_sym;
854
855 /* Don't bother to produce error messages here. We get them when we
856 eventually execute the code for real. */
857
858 macro_tail:
859 orig_sym = SCM_CAR (x);
cc95e00a 860 if (!scm_is_symbol (orig_sym))
2b189e65
MV
861 return x;
862
863 {
864 SCM *proc_ptr = scm_lookupcar1 (x, env, 0);
865 if (proc_ptr == NULL)
866 {
867 /* We have lost the race. */
868 goto macro_tail;
869 }
870 proc = *proc_ptr;
871 }
872
873 /* Only handle memoizing macros. `Acros' and `macros' are really
874 special forms and should not be evaluated here. */
875
876 if (!SCM_MACROP (proc)
877 || (SCM_MACRO_TYPE (proc) != 2 && !SCM_BUILTIN_MACRO_P (proc)))
878 return x;
879
880 SCM_SETCAR (x, orig_sym); /* Undo memoizing effect of lookupcar */
881 res = scm_call_2 (SCM_MACRO_CODE (proc), x, env);
882
883 if (scm_ilength (res) <= 0)
884 res = scm_list_2 (SCM_IM_BEGIN, res);
2b0fb0a5
NJ
885
886 /* njrev: Several queries here: (1) I don't see how it can be
887 correct that the SCM_SETCAR 2 lines below this comment needs
888 protection, but the SCM_SETCAR 6 lines above does not, so
889 something here is probably wrong. (2) macroexp() is now only
890 used in one place - scm_m_generalized_set_x - whereas all other
891 macro expansion happens through expand_user_macros. Therefore
892 (2.1) perhaps macroexp() could be eliminated completely now?
893 (2.2) Does expand_user_macros need any critical section
894 protection? */
895
9de87eea 896 SCM_CRITICAL_SECTION_START;
2b189e65
MV
897 SCM_SETCAR (x, SCM_CAR (res));
898 SCM_SETCDR (x, SCM_CDR (res));
9de87eea 899 SCM_CRITICAL_SECTION_END;
2b189e65
MV
900
901 goto macro_tail;
902}
910b5125 903
9fbee57e 904/* Start of the memoizers for the standard R5RS builtin macros. */
0f2d19dd
JB
905
906
3b88ed2a 907SCM_SYNTAX (s_and, "and", scm_i_makbimacro, scm_m_and);
8ea46249 908SCM_GLOBAL_SYMBOL (scm_sym_and, s_and);
1cc91f1b 909
8ea46249 910SCM
e6729603 911scm_m_and (SCM expr, SCM env SCM_UNUSED)
0f2d19dd 912{
e6729603
DH
913 const SCM cdr_expr = SCM_CDR (expr);
914 const long length = scm_ilength (cdr_expr);
915
916 ASSERT_SYNTAX (length >= 0, s_bad_expression, expr);
917
918 if (length == 0)
919 {
920 /* Special case: (and) is replaced by #t. */
921 return SCM_BOOL_T;
922 }
0f2d19dd 923 else
e6729603
DH
924 {
925 SCM_SETCAR (expr, SCM_IM_AND);
926 return expr;
927 }
0f2d19dd
JB
928}
929
212e58ed
DH
930static SCM
931unmemoize_and (const SCM expr, const SCM env)
932{
933 return scm_cons (scm_sym_and, unmemoize_exprs (SCM_CDR (expr), env));
934}
935
1cc91f1b 936
3b88ed2a 937SCM_SYNTAX (s_begin, "begin", scm_i_makbimacro, scm_m_begin);
9fbee57e 938SCM_GLOBAL_SYMBOL (scm_sym_begin, s_begin);
8ea46249
DH
939
940SCM
2a6f7afe 941scm_m_begin (SCM expr, SCM env SCM_UNUSED)
0f2d19dd 942{
2a6f7afe 943 const SCM cdr_expr = SCM_CDR (expr);
21628685
DH
944 /* Dirk:FIXME:: An empty begin clause is not generally allowed by R5RS.
945 * That means, there should be a distinction between uses of begin where an
946 * empty clause is OK and where it is not. */
2a6f7afe
DH
947 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
948
949 SCM_SETCAR (expr, SCM_IM_BEGIN);
950 return expr;
0f2d19dd
JB
951}
952
212e58ed
DH
953static SCM
954unmemoize_begin (const SCM expr, const SCM env)
955{
956 return scm_cons (scm_sym_begin, unmemoize_exprs (SCM_CDR (expr), env));
957}
958
0f2d19dd 959
3b88ed2a 960SCM_SYNTAX (s_case, "case", scm_i_makbimacro, scm_m_case);
8ea46249 961SCM_GLOBAL_SYMBOL (scm_sym_case, s_case);
6f81708a 962SCM_GLOBAL_SYMBOL (scm_sym_else, "else");
1cc91f1b 963
8ea46249 964SCM
2a6f7afe 965scm_m_case (SCM expr, SCM env)
0f2d19dd 966{
8ea46249 967 SCM clauses;
2a6f7afe
DH
968 SCM all_labels = SCM_EOL;
969
970 /* Check, whether 'else is a literal, i. e. not bound to a value. */
971 const int else_literal_p = literal_p (scm_sym_else, env);
972
973 const SCM cdr_expr = SCM_CDR (expr);
974 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
975 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 2, s_missing_clauses, expr);
976
977 clauses = SCM_CDR (cdr_expr);
a61f4e0c 978 while (!scm_is_null (clauses))
0f2d19dd 979 {
2a6f7afe
DH
980 SCM labels;
981
982 const SCM clause = SCM_CAR (clauses);
983 ASSERT_SYNTAX_2 (scm_ilength (clause) >= 2,
984 s_bad_case_clause, clause, expr);
985
986 labels = SCM_CAR (clause);
a61f4e0c 987 if (scm_is_pair (labels))
2a6f7afe
DH
988 {
989 ASSERT_SYNTAX_2 (scm_ilength (labels) >= 0,
990 s_bad_case_labels, labels, expr);
26ecfa39 991 all_labels = scm_append (scm_list_2 (labels, all_labels));
2a6f7afe 992 }
a61f4e0c 993 else if (scm_is_null (labels))
58a2510b
DH
994 {
995 /* The list of labels is empty. According to R5RS this is allowed.
996 * It means that the sequence of expressions will never be executed.
997 * Therefore, as an optimization, we could remove the whole
998 * clause. */
999 }
2a6f7afe
DH
1000 else
1001 {
bc36d050 1002 ASSERT_SYNTAX_2 (scm_is_eq (labels, scm_sym_else) && else_literal_p,
2a6f7afe 1003 s_bad_case_labels, labels, expr);
a61f4e0c 1004 ASSERT_SYNTAX_2 (scm_is_null (SCM_CDR (clauses)),
609a8b86 1005 s_misplaced_else_clause, clause, expr);
2a6f7afe
DH
1006 }
1007
1008 /* build the new clause */
bc36d050 1009 if (scm_is_eq (labels, scm_sym_else))
2a6f7afe
DH
1010 SCM_SETCAR (clause, SCM_IM_ELSE);
1011
8ea46249 1012 clauses = SCM_CDR (clauses);
0f2d19dd 1013 }
2a6f7afe
DH
1014
1015 /* Check whether all case labels are distinct. */
a61f4e0c 1016 for (; !scm_is_null (all_labels); all_labels = SCM_CDR (all_labels))
2a6f7afe
DH
1017 {
1018 const SCM label = SCM_CAR (all_labels);
7888309b 1019 ASSERT_SYNTAX_2 (scm_is_false (scm_c_memq (label, SCM_CDR (all_labels))),
4610b011 1020 s_duplicate_case_label, label, expr);
2a6f7afe
DH
1021 }
1022
1023 SCM_SETCAR (expr, SCM_IM_CASE);
1024 return expr;
0f2d19dd
JB
1025}
1026
212e58ed
DH
1027static SCM
1028unmemoize_case (const SCM expr, const SCM env)
1029{
1030 const SCM um_key_expr = unmemoize_expression (SCM_CADR (expr), env);
1031 SCM um_clauses = SCM_EOL;
1032 SCM clause_idx;
1033
1034 for (clause_idx = SCM_CDDR (expr);
a61f4e0c 1035 !scm_is_null (clause_idx);
212e58ed
DH
1036 clause_idx = SCM_CDR (clause_idx))
1037 {
1038 const SCM clause = SCM_CAR (clause_idx);
1039 const SCM labels = SCM_CAR (clause);
1040 const SCM exprs = SCM_CDR (clause);
1041
1042 const SCM um_exprs = unmemoize_exprs (exprs, env);
bc36d050 1043 const SCM um_labels = (scm_is_eq (labels, SCM_IM_ELSE))
212e58ed
DH
1044 ? scm_sym_else
1045 : scm_i_finite_list_copy (labels);
1046 const SCM um_clause = scm_cons (um_labels, um_exprs);
1047
1048 um_clauses = scm_cons (um_clause, um_clauses);
1049 }
1050 um_clauses = scm_reverse_x (um_clauses, SCM_UNDEFINED);
1051
1052 return scm_cons2 (scm_sym_case, um_key_expr, um_clauses);
1053}
1054
0f2d19dd 1055
3b88ed2a 1056SCM_SYNTAX (s_cond, "cond", scm_i_makbimacro, scm_m_cond);
8ea46249 1057SCM_GLOBAL_SYMBOL (scm_sym_cond, s_cond);
609a8b86 1058SCM_GLOBAL_SYMBOL (scm_sym_arrow, "=>");
1cc91f1b 1059
8ea46249 1060SCM
609a8b86 1061scm_m_cond (SCM expr, SCM env)
0f2d19dd 1062{
609a8b86
DH
1063 /* Check, whether 'else or '=> is a literal, i. e. not bound to a value. */
1064 const int else_literal_p = literal_p (scm_sym_else, env);
1065 const int arrow_literal_p = literal_p (scm_sym_arrow, env);
1066
1067 const SCM clauses = SCM_CDR (expr);
1068 SCM clause_idx;
1069
1070 ASSERT_SYNTAX (scm_ilength (clauses) >= 0, s_bad_expression, expr);
1071 ASSERT_SYNTAX (scm_ilength (clauses) >= 1, s_missing_clauses, expr);
1072
1073 for (clause_idx = clauses;
a61f4e0c 1074 !scm_is_null (clause_idx);
609a8b86 1075 clause_idx = SCM_CDR (clause_idx))
0f2d19dd 1076 {
609a8b86
DH
1077 SCM test;
1078
1079 const SCM clause = SCM_CAR (clause_idx);
1080 const long length = scm_ilength (clause);
1081 ASSERT_SYNTAX_2 (length >= 1, s_bad_cond_clause, clause, expr);
1082
1083 test = SCM_CAR (clause);
bc36d050 1084 if (scm_is_eq (test, scm_sym_else) && else_literal_p)
0f2d19dd 1085 {
a61f4e0c 1086 const int last_clause_p = scm_is_null (SCM_CDR (clause_idx));
609a8b86
DH
1087 ASSERT_SYNTAX_2 (length >= 2,
1088 s_bad_cond_clause, clause, expr);
1089 ASSERT_SYNTAX_2 (last_clause_p,
1090 s_misplaced_else_clause, clause, expr);
1091 SCM_SETCAR (clause, SCM_IM_ELSE);
0f2d19dd 1092 }
609a8b86 1093 else if (length >= 2
bc36d050 1094 && scm_is_eq (SCM_CADR (clause), scm_sym_arrow)
609a8b86
DH
1095 && arrow_literal_p)
1096 {
1097 ASSERT_SYNTAX_2 (length > 2, s_missing_recipient, clause, expr);
1098 ASSERT_SYNTAX_2 (length == 3, s_extra_expression, clause, expr);
1099 SCM_SETCAR (SCM_CDR (clause), SCM_IM_ARROW);
8ea46249 1100 }
1fe1fc0a
MV
1101 /* SRFI 61 extended cond */
1102 else if (length >= 3
1103 && scm_is_eq (SCM_CADDR (clause), scm_sym_arrow)
1104 && arrow_literal_p)
1105 {
1106 ASSERT_SYNTAX_2 (length > 3, s_missing_recipient, clause, expr);
1107 ASSERT_SYNTAX_2 (length == 4, s_extra_expression, clause, expr);
1108 SCM_SETCAR (SCM_CDDR (clause), SCM_IM_ARROW);
1109 }
0f2d19dd 1110 }
609a8b86
DH
1111
1112 SCM_SETCAR (expr, SCM_IM_COND);
1113 return expr;
0f2d19dd
JB
1114}
1115
212e58ed
DH
1116static SCM
1117unmemoize_cond (const SCM expr, const SCM env)
1118{
1119 SCM um_clauses = SCM_EOL;
1120 SCM clause_idx;
1121
1122 for (clause_idx = SCM_CDR (expr);
a61f4e0c 1123 !scm_is_null (clause_idx);
212e58ed
DH
1124 clause_idx = SCM_CDR (clause_idx))
1125 {
1126 const SCM clause = SCM_CAR (clause_idx);
1127 const SCM sequence = SCM_CDR (clause);
1128 const SCM test = SCM_CAR (clause);
1129 SCM um_test;
1130 SCM um_sequence;
1131 SCM um_clause;
1132
bc36d050 1133 if (scm_is_eq (test, SCM_IM_ELSE))
212e58ed
DH
1134 um_test = scm_sym_else;
1135 else
1136 um_test = unmemoize_expression (test, env);
1137
a61f4e0c 1138 if (!scm_is_null (sequence) && scm_is_eq (SCM_CAR (sequence),
bc36d050 1139 SCM_IM_ARROW))
212e58ed
DH
1140 {
1141 const SCM target = SCM_CADR (sequence);
1142 const SCM um_target = unmemoize_expression (target, env);
1143 um_sequence = scm_list_2 (scm_sym_arrow, um_target);
1144 }
1145 else
1146 {
1147 um_sequence = unmemoize_exprs (sequence, env);
1148 }
1149
1150 um_clause = scm_cons (um_test, um_sequence);
1151 um_clauses = scm_cons (um_clause, um_clauses);
1152 }
1153 um_clauses = scm_reverse_x (um_clauses, SCM_UNDEFINED);
1154
1155 return scm_cons (scm_sym_cond, um_clauses);
1156}
1157
1cc91f1b 1158
0f572ba7
DH
1159SCM_SYNTAX (s_define, "define", scm_i_makbimacro, scm_m_define);
1160SCM_GLOBAL_SYMBOL (scm_sym_define, s_define);
5280aaca 1161
9fbee57e
DH
1162/* Guile provides an extension to R5RS' define syntax to represent function
1163 * currying in a compact way. With this extension, it is allowed to write
1164 * (define <nested-variable> <body>), where <nested-variable> has of one of
1165 * the forms (<nested-variable> <formals>), (<nested-variable> . <formal>),
1166 * (<variable> <formals>) or (<variable> . <formal>). As in R5RS, <formals>
1167 * should be either a sequence of zero or more variables, or a sequence of one
1168 * or more variables followed by a space-delimited period and another
1169 * variable. Each level of argument nesting wraps the <body> within another
1170 * lambda expression. For example, the following forms are allowed, each one
1171 * followed by an equivalent, more explicit implementation.
1172 * Example 1:
1173 * (define ((a b . c) . d) <body>) is equivalent to
1174 * (define a (lambda (b . c) (lambda d <body>)))
1175 * Example 2:
1176 * (define (((a) b) c . d) <body>) is equivalent to
1177 * (define a (lambda () (lambda (b) (lambda (c . d) <body>))))
1178 */
1179/* Dirk:FIXME:: We should provide an implementation for 'define' in the R5RS
1180 * module that does not implement this extension. */
0f572ba7
DH
1181static SCM
1182canonicalize_define (const SCM expr)
5280aaca 1183{
cc56ba80
DH
1184 SCM body;
1185 SCM variable;
1186
1187 const SCM cdr_expr = SCM_CDR (expr);
c86c440b 1188 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
cc56ba80
DH
1189 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 2, s_missing_expression, expr);
1190
1191 body = SCM_CDR (cdr_expr);
1192 variable = SCM_CAR (cdr_expr);
a61f4e0c 1193 while (scm_is_pair (variable))
5280aaca 1194 {
cc56ba80
DH
1195 /* This while loop realizes function currying by variable nesting.
1196 * Variable is known to be a nested-variable. In every iteration of the
1197 * loop another level of lambda expression is created, starting with the
4610b011
DH
1198 * innermost one. Note that we don't check for duplicate formals here:
1199 * This will be done by the memoizer of the lambda expression. */
cc56ba80
DH
1200 const SCM formals = SCM_CDR (variable);
1201 const SCM tail = scm_cons (formals, body);
1202
1203 /* Add source properties to each new lambda expression: */
1204 const SCM lambda = scm_cons_source (variable, scm_sym_lambda, tail);
1205
1206 body = scm_list_1 (lambda);
1207 variable = SCM_CAR (variable);
5280aaca 1208 }
cc95e00a 1209 ASSERT_SYNTAX_2 (scm_is_symbol (variable), s_bad_variable, variable, expr);
cc56ba80
DH
1210 ASSERT_SYNTAX (scm_ilength (body) == 1, s_expression, expr);
1211
0f572ba7
DH
1212 SCM_SETCAR (cdr_expr, variable);
1213 SCM_SETCDR (cdr_expr, body);
1214 return expr;
1215}
1216
36245b66
DH
1217/* According to section 5.2.1 of R5RS we first have to make sure that the
1218 * variable is bound, and then perform the (set! variable expression)
1219 * operation. This means, that within the expression we may already assign
1220 * values to variable: (define foo (begin (set! foo 1) (+ foo 1))) */
0f572ba7
DH
1221SCM
1222scm_m_define (SCM expr, SCM env)
1223{
6bff1368 1224 ASSERT_SYNTAX (SCM_TOP_LEVEL (env), s_bad_define, expr);
0f572ba7 1225
6bff1368
DH
1226 {
1227 const SCM canonical_definition = canonicalize_define (expr);
1228 const SCM cdr_canonical_definition = SCM_CDR (canonical_definition);
1229 const SCM variable = SCM_CAR (cdr_canonical_definition);
36245b66
DH
1230 const SCM location
1231 = scm_sym2var (variable, scm_env_top_level (env), SCM_BOOL_T);
1232 const SCM value = scm_eval_car (SCM_CDR (cdr_canonical_definition), env);
6bff1368 1233
6bff1368
DH
1234 if (SCM_REC_PROCNAMES_P)
1235 {
1236 SCM tmp = value;
1237 while (SCM_MACROP (tmp))
1238 tmp = SCM_MACRO_CODE (tmp);
23d72566 1239 if (scm_is_true (scm_procedure_p (tmp))
6bff1368 1240 /* Only the first definition determines the name. */
7888309b 1241 && scm_is_false (scm_procedure_property (tmp, scm_sym_name)))
6bff1368
DH
1242 scm_set_procedure_property_x (tmp, scm_sym_name, variable);
1243 }
0f572ba7 1244
36245b66 1245 SCM_VARIABLE_SET (location, value);
6bff1368
DH
1246
1247 return SCM_UNSPECIFIED;
1248 }
0f2d19dd
JB
1249}
1250
1251
8ae95199
DH
1252/* This is a helper function for forms (<keyword> <expression>) that are
1253 * transformed into (#@<keyword> '() <memoized_expression>) in order to allow
1254 * for easy creation of a thunk (i. e. a closure without arguments) using the
1255 * ('() <memoized_expression>) tail of the memoized form. */
1256static SCM
1257memoize_as_thunk_prototype (const SCM expr, const SCM env SCM_UNUSED)
1258{
1259 const SCM cdr_expr = SCM_CDR (expr);
1260 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
1261 ASSERT_SYNTAX (scm_ilength (cdr_expr) == 1, s_expression, expr);
1262
1263 SCM_SETCDR (expr, scm_cons (SCM_EOL, cdr_expr));
1264
1265 return expr;
1266}
1267
1268
3b88ed2a 1269SCM_SYNTAX (s_delay, "delay", scm_i_makbimacro, scm_m_delay);
9fbee57e 1270SCM_GLOBAL_SYMBOL (scm_sym_delay, s_delay);
1cc91f1b 1271
9fbee57e
DH
1272/* Promises are implemented as closures with an empty parameter list. Thus,
1273 * (delay <expression>) is transformed into (#@delay '() <expression>), where
1274 * the empty list represents the empty parameter list. This representation
1275 * allows for easy creation of the closure during evaluation. */
8ea46249 1276SCM
8ae95199 1277scm_m_delay (SCM expr, SCM env)
0f2d19dd 1278{
8ae95199
DH
1279 const SCM new_expr = memoize_as_thunk_prototype (expr, env);
1280 SCM_SETCAR (new_expr, SCM_IM_DELAY);
1281 return new_expr;
0f2d19dd
JB
1282}
1283
212e58ed
DH
1284static SCM
1285unmemoize_delay (const SCM expr, const SCM env)
1286{
1287 const SCM thunk_expr = SCM_CADDR (expr);
1288 return scm_list_2 (scm_sym_delay, unmemoize_expression (thunk_expr, env));
1289}
1290
8ea46249 1291
a954ce1d
DH
1292SCM_SYNTAX(s_do, "do", scm_i_makbimacro, scm_m_do);
1293SCM_GLOBAL_SYMBOL(scm_sym_do, s_do);
1294
302c12b4 1295/* DO gets the most radically altered syntax. The order of the vars is
4610b011
DH
1296 * reversed here. During the evaluation this allows for simple consing of the
1297 * results of the inits and steps:
302c12b4 1298
0f2d19dd 1299 (do ((<var1> <init1> <step1>)
a954ce1d
DH
1300 (<var2> <init2>)
1301 ... )
1302 (<test> <return>)
1303 <body>)
302c12b4 1304
0f2d19dd 1305 ;; becomes
302c12b4 1306
e681d187 1307 (#@do (<init1> <init2> ... <initn>)
a954ce1d
DH
1308 (varn ... var2 var1)
1309 (<test> <return>)
1310 (<body>)
1311 <step1> <step2> ... <stepn>) ;; missing steps replaced by var
302c12b4 1312 */
0f2d19dd 1313SCM
a954ce1d 1314scm_m_do (SCM expr, SCM env SCM_UNUSED)
0f2d19dd 1315{
a954ce1d
DH
1316 SCM variables = SCM_EOL;
1317 SCM init_forms = SCM_EOL;
1318 SCM step_forms = SCM_EOL;
1319 SCM binding_idx;
1320 SCM cddr_expr;
1321 SCM exit_clause;
1322 SCM commands;
1323 SCM tail;
1324
1325 const SCM cdr_expr = SCM_CDR (expr);
1326 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
1327 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 2, s_missing_expression, expr);
1328
1329 /* Collect variables, init and step forms. */
1330 binding_idx = SCM_CAR (cdr_expr);
1331 ASSERT_SYNTAX_2 (scm_ilength (binding_idx) >= 0,
1332 s_bad_bindings, binding_idx, expr);
a61f4e0c 1333 for (; !scm_is_null (binding_idx); binding_idx = SCM_CDR (binding_idx))
0f2d19dd 1334 {
a954ce1d
DH
1335 const SCM binding = SCM_CAR (binding_idx);
1336 const long length = scm_ilength (binding);
1337 ASSERT_SYNTAX_2 (length == 2 || length == 3,
1338 s_bad_binding, binding, expr);
1339
302c12b4 1340 {
a954ce1d
DH
1341 const SCM name = SCM_CAR (binding);
1342 const SCM init = SCM_CADR (binding);
1343 const SCM step = (length == 2) ? name : SCM_CADDR (binding);
cc95e00a 1344 ASSERT_SYNTAX_2 (scm_is_symbol (name), s_bad_variable, name, expr);
7888309b 1345 ASSERT_SYNTAX_2 (scm_is_false (scm_c_memq (name, variables)),
4610b011
DH
1346 s_duplicate_binding, name, expr);
1347
a954ce1d
DH
1348 variables = scm_cons (name, variables);
1349 init_forms = scm_cons (init, init_forms);
1350 step_forms = scm_cons (step, step_forms);
302c12b4 1351 }
0f2d19dd 1352 }
a954ce1d
DH
1353 init_forms = scm_reverse_x (init_forms, SCM_UNDEFINED);
1354 step_forms = scm_reverse_x (step_forms, SCM_UNDEFINED);
1355
1356 /* Memoize the test form and the exit sequence. */
1357 cddr_expr = SCM_CDR (cdr_expr);
1358 exit_clause = SCM_CAR (cddr_expr);
1359 ASSERT_SYNTAX_2 (scm_ilength (exit_clause) >= 1,
1360 s_bad_exit_clause, exit_clause, expr);
1361
1362 commands = SCM_CDR (cddr_expr);
1363 tail = scm_cons2 (exit_clause, commands, step_forms);
1364 tail = scm_cons2 (init_forms, variables, tail);
1365 SCM_SETCAR (expr, SCM_IM_DO);
1366 SCM_SETCDR (expr, tail);
1367 return expr;
0f2d19dd
JB
1368}
1369
212e58ed
DH
1370static SCM
1371unmemoize_do (const SCM expr, const SCM env)
1372{
1373 const SCM cdr_expr = SCM_CDR (expr);
1374 const SCM cddr_expr = SCM_CDR (cdr_expr);
1375 const SCM rnames = SCM_CAR (cddr_expr);
1376 const SCM extended_env = SCM_EXTEND_ENV (rnames, SCM_EOL, env);
1377 const SCM cdddr_expr = SCM_CDR (cddr_expr);
1378 const SCM exit_sequence = SCM_CAR (cdddr_expr);
1379 const SCM um_exit_sequence = unmemoize_exprs (exit_sequence, extended_env);
1380 const SCM cddddr_expr = SCM_CDR (cdddr_expr);
1381 const SCM um_body = unmemoize_exprs (SCM_CAR (cddddr_expr), extended_env);
1382
1383 /* build transformed binding list */
1384 SCM um_names = scm_reverse (rnames);
1385 SCM um_inits = unmemoize_exprs (SCM_CAR (cdr_expr), env);
1386 SCM um_steps = unmemoize_exprs (SCM_CDR (cddddr_expr), extended_env);
1387 SCM um_bindings = SCM_EOL;
a61f4e0c 1388 while (!scm_is_null (um_names))
212e58ed
DH
1389 {
1390 const SCM name = SCM_CAR (um_names);
1391 const SCM init = SCM_CAR (um_inits);
1392 SCM step = SCM_CAR (um_steps);
bc36d050 1393 step = scm_is_eq (step, name) ? SCM_EOL : scm_list_1 (step);
212e58ed
DH
1394
1395 um_bindings = scm_cons (scm_cons2 (name, init, step), um_bindings);
1396
1397 um_names = SCM_CDR (um_names);
1398 um_inits = SCM_CDR (um_inits);
1399 um_steps = SCM_CDR (um_steps);
1400 }
1401 um_bindings = scm_reverse_x (um_bindings, SCM_UNDEFINED);
1402
1403 return scm_cons (scm_sym_do,
1404 scm_cons2 (um_bindings, um_exit_sequence, um_body));
1405}
1406
b8229a3b 1407
3b88ed2a 1408SCM_SYNTAX (s_if, "if", scm_i_makbimacro, scm_m_if);
9fbee57e 1409SCM_GLOBAL_SYMBOL (scm_sym_if, s_if);
b8229a3b 1410
9fbee57e 1411SCM
4610b011 1412scm_m_if (SCM expr, SCM env SCM_UNUSED)
0f2d19dd 1413{
4610b011
DH
1414 const SCM cdr_expr = SCM_CDR (expr);
1415 const long length = scm_ilength (cdr_expr);
1416 ASSERT_SYNTAX (length == 2 || length == 3, s_expression, expr);
1417 SCM_SETCAR (expr, SCM_IM_IF);
1418 return expr;
0f2d19dd
JB
1419}
1420
212e58ed
DH
1421static SCM
1422unmemoize_if (const SCM expr, const SCM env)
1423{
1424 const SCM cdr_expr = SCM_CDR (expr);
1425 const SCM um_condition = unmemoize_expression (SCM_CAR (cdr_expr), env);
1426 const SCM cddr_expr = SCM_CDR (cdr_expr);
1427 const SCM um_then = unmemoize_expression (SCM_CAR (cddr_expr), env);
1428 const SCM cdddr_expr = SCM_CDR (cddr_expr);
1429
a61f4e0c 1430 if (scm_is_null (cdddr_expr))
212e58ed
DH
1431 {
1432 return scm_list_3 (scm_sym_if, um_condition, um_then);
1433 }
1434 else
1435 {
1436 const SCM um_else = unmemoize_expression (SCM_CAR (cdddr_expr), env);
1437 return scm_list_4 (scm_sym_if, um_condition, um_then, um_else);
1438 }
1439}
1440
302c12b4 1441
3b88ed2a 1442SCM_SYNTAX (s_lambda, "lambda", scm_i_makbimacro, scm_m_lambda);
9fbee57e 1443SCM_GLOBAL_SYMBOL (scm_sym_lambda, s_lambda);
0f2d19dd 1444
4610b011
DH
1445/* A helper function for memoize_lambda to support checking for duplicate
1446 * formal arguments: Return true if OBJ is `eq?' to one of the elements of
1447 * LIST or to the cdr of the last cons. Therefore, LIST may have any of the
1448 * forms that a formal argument can have:
1449 * <rest>, (<arg1> ...), (<arg1> ... . <rest>) */
9fbee57e 1450static int
4610b011 1451c_improper_memq (SCM obj, SCM list)
5cb22e96 1452{
a61f4e0c 1453 for (; scm_is_pair (list); list = SCM_CDR (list))
9fbee57e 1454 {
bc36d050 1455 if (scm_is_eq (SCM_CAR (list), obj))
4610b011 1456 return 1;
9fbee57e 1457 }
bc36d050 1458 return scm_is_eq (list, obj);
5cb22e96
DH
1459}
1460
28d52ebb 1461SCM
03a3e941 1462scm_m_lambda (SCM expr, SCM env SCM_UNUSED)
28d52ebb 1463{
9fbee57e 1464 SCM formals;
03a3e941 1465 SCM formals_idx;
34adf7ea
DH
1466 SCM cddr_expr;
1467 int documentation;
1468 SCM body;
1469 SCM new_body;
03a3e941
DH
1470
1471 const SCM cdr_expr = SCM_CDR (expr);
1472 const long length = scm_ilength (cdr_expr);
1473 ASSERT_SYNTAX (length >= 0, s_bad_expression, expr);
1474 ASSERT_SYNTAX (length >= 2, s_missing_expression, expr);
28d52ebb 1475
03a3e941
DH
1476 /* Before iterating the list of formal arguments, make sure the formals
1477 * actually are given as either a symbol or a non-cyclic list. */
1478 formals = SCM_CAR (cdr_expr);
a61f4e0c 1479 if (scm_is_pair (formals))
03a3e941
DH
1480 {
1481 /* Dirk:FIXME:: We should check for a cyclic list of formals, and if
1482 * detected, report a 'Bad formals' error. */
1483 }
1484 else
1485 {
a61f4e0c 1486 ASSERT_SYNTAX_2 (scm_is_symbol (formals) || scm_is_null (formals),
03a3e941
DH
1487 s_bad_formals, formals, expr);
1488 }
1cc91f1b 1489
03a3e941
DH
1490 /* Now iterate the list of formal arguments to check if all formals are
1491 * symbols, and that there are no duplicates. */
1492 formals_idx = formals;
a61f4e0c 1493 while (scm_is_pair (formals_idx))
0f2d19dd 1494 {
03a3e941
DH
1495 const SCM formal = SCM_CAR (formals_idx);
1496 const SCM next_idx = SCM_CDR (formals_idx);
cc95e00a 1497 ASSERT_SYNTAX_2 (scm_is_symbol (formal), s_bad_formal, formal, expr);
03a3e941
DH
1498 ASSERT_SYNTAX_2 (!c_improper_memq (formal, next_idx),
1499 s_duplicate_formal, formal, expr);
1500 formals_idx = next_idx;
0f2d19dd 1501 }
a61f4e0c 1502 ASSERT_SYNTAX_2 (scm_is_null (formals_idx) || scm_is_symbol (formals_idx),
03a3e941 1503 s_bad_formal, formals_idx, expr);
9fbee57e 1504
34adf7ea
DH
1505 /* Memoize the body. Keep a potential documentation string. */
1506 /* Dirk:FIXME:: We should probably extract the documentation string to
1507 * some external database. Otherwise it will slow down execution, since
1508 * the documentation string will have to be skipped with every execution
1509 * of the closure. */
1510 cddr_expr = SCM_CDR (cdr_expr);
7f9994d9 1511 documentation = (length >= 3 && scm_is_string (SCM_CAR (cddr_expr)));
34adf7ea 1512 body = documentation ? SCM_CDR (cddr_expr) : cddr_expr;
430b8401 1513 new_body = m_body (SCM_IM_LAMBDA, body);
34adf7ea
DH
1514
1515 SCM_SETCAR (expr, SCM_IM_LAMBDA);
1516 if (documentation)
1517 SCM_SETCDR (cddr_expr, new_body);
1518 else
1519 SCM_SETCDR (cdr_expr, new_body);
1520 return expr;
0f2d19dd 1521}
6dbd0af5 1522
212e58ed
DH
1523static SCM
1524unmemoize_lambda (const SCM expr, const SCM env)
1525{
1526 const SCM formals = SCM_CADR (expr);
1527 const SCM body = SCM_CDDR (expr);
1528
1529 const SCM new_env = SCM_EXTEND_ENV (formals, SCM_EOL, env);
1530 const SCM um_formals = scm_i_finite_list_copy (formals);
1531 const SCM um_body = unmemoize_exprs (body, new_env);
1532
1533 return scm_cons2 (scm_sym_lambda, um_formals, um_body);
1534}
1535
0f2d19dd 1536
d6754c23 1537/* Check if the format of the bindings is ((<symbol> <init-form>) ...). */
302c12b4 1538static void
d6754c23 1539check_bindings (const SCM bindings, const SCM expr)
0f2d19dd 1540{
d6754c23 1541 SCM binding_idx;
302c12b4 1542
d6754c23
DH
1543 ASSERT_SYNTAX_2 (scm_ilength (bindings) >= 0,
1544 s_bad_bindings, bindings, expr);
0f2d19dd 1545
d6754c23 1546 binding_idx = bindings;
a61f4e0c 1547 for (; !scm_is_null (binding_idx); binding_idx = SCM_CDR (binding_idx))
0f2d19dd 1548 {
d6754c23
DH
1549 SCM name; /* const */
1550
1551 const SCM binding = SCM_CAR (binding_idx);
1552 ASSERT_SYNTAX_2 (scm_ilength (binding) == 2,
1553 s_bad_binding, binding, expr);
1554
1555 name = SCM_CAR (binding);
cc95e00a 1556 ASSERT_SYNTAX_2 (scm_is_symbol (name), s_bad_variable, name, expr);
0f2d19dd 1557 }
d6754c23 1558}
26d5b9b4 1559
d6754c23
DH
1560
1561/* The bindings, which must have the format ((v1 i1) (v2 i2) ... (vn in)), are
1562 * transformed to the lists (vn ... v2 v1) and (i1 i2 ... in). That is, the
1563 * variables are returned in a list with their order reversed, and the init
1564 * forms are returned in a list in the same order as they are given in the
1565 * bindings. If a duplicate variable name is detected, an error is
1566 * signalled. */
1567static void
1568transform_bindings (
1569 const SCM bindings, const SCM expr,
1570 SCM *const rvarptr, SCM *const initptr )
1571{
1572 SCM rvariables = SCM_EOL;
1573 SCM rinits = SCM_EOL;
1574 SCM binding_idx = bindings;
a61f4e0c 1575 for (; !scm_is_null (binding_idx); binding_idx = SCM_CDR (binding_idx))
d6754c23
DH
1576 {
1577 const SCM binding = SCM_CAR (binding_idx);
1578 const SCM cdr_binding = SCM_CDR (binding);
1579 const SCM name = SCM_CAR (binding);
7888309b 1580 ASSERT_SYNTAX_2 (scm_is_false (scm_c_memq (name, rvariables)),
d6754c23
DH
1581 s_duplicate_binding, name, expr);
1582 rvariables = scm_cons (name, rvariables);
1583 rinits = scm_cons (SCM_CAR (cdr_binding), rinits);
1584 }
1585 *rvarptr = rvariables;
1586 *initptr = scm_reverse_x (rinits, SCM_UNDEFINED);
0f2d19dd
JB
1587}
1588
302c12b4 1589
3b88ed2a 1590SCM_SYNTAX(s_let, "let", scm_i_makbimacro, scm_m_let);
2f0d1375 1591SCM_GLOBAL_SYMBOL(scm_sym_let, s_let);
b8229a3b 1592
d6754c23
DH
1593/* This function is a helper function for memoize_let. It transforms
1594 * (let name ((var init) ...) body ...) into
1595 * ((letrec ((name (lambda (var ...) body ...))) name) init ...)
1596 * and memoizes the expression. It is assumed that the caller has checked
1597 * that name is a symbol and that there are bindings and a body. */
1598static SCM
1599memoize_named_let (const SCM expr, const SCM env SCM_UNUSED)
1600{
1601 SCM rvariables;
1602 SCM variables;
1603 SCM inits;
1604
1605 const SCM cdr_expr = SCM_CDR (expr);
1606 const SCM name = SCM_CAR (cdr_expr);
1607 const SCM cddr_expr = SCM_CDR (cdr_expr);
1608 const SCM bindings = SCM_CAR (cddr_expr);
1609 check_bindings (bindings, expr);
1610
1611 transform_bindings (bindings, expr, &rvariables, &inits);
1612 variables = scm_reverse_x (rvariables, SCM_UNDEFINED);
1613
1614 {
1615 const SCM let_body = SCM_CDR (cddr_expr);
430b8401 1616 const SCM lambda_body = m_body (SCM_IM_LET, let_body);
d6754c23
DH
1617 const SCM lambda_tail = scm_cons (variables, lambda_body);
1618 const SCM lambda_form = scm_cons_source (expr, scm_sym_lambda, lambda_tail);
1619
1620 const SCM rvar = scm_list_1 (name);
1621 const SCM init = scm_list_1 (lambda_form);
430b8401 1622 const SCM body = m_body (SCM_IM_LET, scm_list_1 (name));
d6754c23
DH
1623 const SCM letrec_tail = scm_cons (rvar, scm_cons (init, body));
1624 const SCM letrec_form = scm_cons_source (expr, SCM_IM_LETREC, letrec_tail);
1625 return scm_cons_source (expr, letrec_form, inits);
1626 }
1627}
1628
1629/* (let ((v1 i1) (v2 i2) ...) body) with variables v1 .. vn and initializers
1630 * i1 .. in is transformed to (#@let (vn ... v2 v1) (i1 i2 ...) body). */
302c12b4 1631SCM
d6754c23 1632scm_m_let (SCM expr, SCM env)
0f2d19dd 1633{
d6754c23
DH
1634 SCM bindings;
1635
1636 const SCM cdr_expr = SCM_CDR (expr);
1637 const long length = scm_ilength (cdr_expr);
1638 ASSERT_SYNTAX (length >= 0, s_bad_expression, expr);
1639 ASSERT_SYNTAX (length >= 2, s_missing_expression, expr);
302c12b4 1640
d6754c23 1641 bindings = SCM_CAR (cdr_expr);
cc95e00a 1642 if (scm_is_symbol (bindings))
26d5b9b4 1643 {
d6754c23
DH
1644 ASSERT_SYNTAX (length >= 3, s_missing_expression, expr);
1645 return memoize_named_let (expr, env);
26d5b9b4 1646 }
d6754c23
DH
1647
1648 check_bindings (bindings, expr);
a61f4e0c 1649 if (scm_is_null (bindings) || scm_is_null (SCM_CDR (bindings)))
26d5b9b4 1650 {
d6754c23 1651 /* Special case: no bindings or single binding => let* is faster. */
430b8401 1652 const SCM body = m_body (SCM_IM_LET, SCM_CDR (cdr_expr));
d6754c23 1653 return scm_m_letstar (scm_cons2 (SCM_CAR (expr), bindings, body), env);
26d5b9b4 1654 }
302c12b4
DH
1655 else
1656 {
d6754c23
DH
1657 /* plain let */
1658 SCM rvariables;
1659 SCM inits;
1660 transform_bindings (bindings, expr, &rvariables, &inits);
26d5b9b4 1661
302c12b4 1662 {
430b8401 1663 const SCM new_body = m_body (SCM_IM_LET, SCM_CDR (cdr_expr));
d6754c23
DH
1664 const SCM new_tail = scm_cons2 (rvariables, inits, new_body);
1665 SCM_SETCAR (expr, SCM_IM_LET);
1666 SCM_SETCDR (expr, new_tail);
1667 return expr;
302c12b4
DH
1668 }
1669 }
0f2d19dd
JB
1670}
1671
212e58ed
DH
1672static SCM
1673build_binding_list (SCM rnames, SCM rinits)
1674{
1675 SCM bindings = SCM_EOL;
a61f4e0c 1676 while (!scm_is_null (rnames))
212e58ed
DH
1677 {
1678 const SCM binding = scm_list_2 (SCM_CAR (rnames), SCM_CAR (rinits));
1679 bindings = scm_cons (binding, bindings);
1680 rnames = SCM_CDR (rnames);
1681 rinits = SCM_CDR (rinits);
1682 }
1683 return bindings;
1684}
1685
1686static SCM
1687unmemoize_let (const SCM expr, const SCM env)
1688{
1689 const SCM cdr_expr = SCM_CDR (expr);
1690 const SCM um_rnames = SCM_CAR (cdr_expr);
1691 const SCM extended_env = SCM_EXTEND_ENV (um_rnames, SCM_EOL, env);
1692 const SCM cddr_expr = SCM_CDR (cdr_expr);
1693 const SCM um_inits = unmemoize_exprs (SCM_CAR (cddr_expr), env);
1694 const SCM um_rinits = scm_reverse_x (um_inits, SCM_UNDEFINED);
1695 const SCM um_bindings = build_binding_list (um_rnames, um_rinits);
1696 const SCM um_body = unmemoize_exprs (SCM_CDR (cddr_expr), extended_env);
1697
1698 return scm_cons2 (scm_sym_let, um_bindings, um_body);
1699}
1700
1701
1702SCM_SYNTAX(s_letrec, "letrec", scm_i_makbimacro, scm_m_letrec);
1703SCM_GLOBAL_SYMBOL(scm_sym_letrec, s_letrec);
1704
1705SCM
1706scm_m_letrec (SCM expr, SCM env)
1707{
1708 SCM bindings;
1709
1710 const SCM cdr_expr = SCM_CDR (expr);
1711 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
1712 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 2, s_missing_expression, expr);
1713
1714 bindings = SCM_CAR (cdr_expr);
a61f4e0c 1715 if (scm_is_null (bindings))
212e58ed
DH
1716 {
1717 /* no bindings, let* is executed faster */
1718 SCM body = m_body (SCM_IM_LETREC, SCM_CDR (cdr_expr));
1719 return scm_m_letstar (scm_cons2 (SCM_CAR (expr), SCM_EOL, body), env);
1720 }
1721 else
1722 {
1723 SCM rvariables;
1724 SCM inits;
1725 SCM new_body;
1726
1727 check_bindings (bindings, expr);
1728 transform_bindings (bindings, expr, &rvariables, &inits);
1729 new_body = m_body (SCM_IM_LETREC, SCM_CDR (cdr_expr));
1730 return scm_cons2 (SCM_IM_LETREC, rvariables, scm_cons (inits, new_body));
1731 }
1732}
1733
1734static SCM
1735unmemoize_letrec (const SCM expr, const SCM env)
1736{
1737 const SCM cdr_expr = SCM_CDR (expr);
1738 const SCM um_rnames = SCM_CAR (cdr_expr);
1739 const SCM extended_env = SCM_EXTEND_ENV (um_rnames, SCM_EOL, env);
1740 const SCM cddr_expr = SCM_CDR (cdr_expr);
1741 const SCM um_inits = unmemoize_exprs (SCM_CAR (cddr_expr), extended_env);
1742 const SCM um_rinits = scm_reverse_x (um_inits, SCM_UNDEFINED);
1743 const SCM um_bindings = build_binding_list (um_rnames, um_rinits);
1744 const SCM um_body = unmemoize_exprs (SCM_CDR (cddr_expr), extended_env);
1745
1746 return scm_cons2 (scm_sym_letrec, um_bindings, um_body);
1747}
1748
1749
0f2d19dd 1750
3b88ed2a 1751SCM_SYNTAX (s_letstar, "let*", scm_i_makbimacro, scm_m_letstar);
9fbee57e 1752SCM_GLOBAL_SYMBOL (scm_sym_letstar, s_letstar);
1cc91f1b 1753
d6754c23
DH
1754/* (let* ((v1 i1) (v2 i2) ...) body) with variables v1 .. vn and initializers
1755 * i1 .. in is transformed into the form (#@let* (v1 i1 v2 i2 ...) body). */
9fbee57e 1756SCM
d6754c23 1757scm_m_letstar (SCM expr, SCM env SCM_UNUSED)
0f2d19dd 1758{
d6754c23 1759 SCM binding_idx;
d6754c23 1760 SCM new_body;
0f2d19dd 1761
d6754c23
DH
1762 const SCM cdr_expr = SCM_CDR (expr);
1763 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
1764 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 2, s_missing_expression, expr);
9fbee57e 1765
d6754c23
DH
1766 binding_idx = SCM_CAR (cdr_expr);
1767 check_bindings (binding_idx, expr);
1768
461bffb1
DH
1769 /* Transform ((v1 i1) (v2 i2) ...) into (v1 i1 v2 i2 ...). The
1770 * transformation is done in place. At the beginning of one iteration of
1771 * the loop the variable binding_idx holds the form
1772 * P1:( (vn . P2:(in . ())) . P3:( (vn+1 in+1) ... ) ),
1773 * where P1, P2 and P3 indicate the pairs, that are relevant for the
1774 * transformation. P1 and P2 are modified in the loop, P3 remains
1775 * untouched. After the execution of the loop, P1 will hold
1776 * P1:( vn . P2:(in . P3:( (vn+1 in+1) ... )) )
1777 * and binding_idx will hold P3. */
a61f4e0c 1778 while (!scm_is_null (binding_idx))
9fbee57e 1779 {
461bffb1 1780 const SCM cdr_binding_idx = SCM_CDR (binding_idx); /* remember P3 */
d6754c23
DH
1781 const SCM binding = SCM_CAR (binding_idx);
1782 const SCM name = SCM_CAR (binding);
461bffb1
DH
1783 const SCM cdr_binding = SCM_CDR (binding);
1784
1785 SCM_SETCDR (cdr_binding, cdr_binding_idx); /* update P2 */
1786 SCM_SETCAR (binding_idx, name); /* update P1 */
1787 SCM_SETCDR (binding_idx, cdr_binding); /* update P1 */
1788
1789 binding_idx = cdr_binding_idx; /* continue with P3 */
9fbee57e
DH
1790 }
1791
430b8401 1792 new_body = m_body (SCM_IM_LETSTAR, SCM_CDR (cdr_expr));
461bffb1
DH
1793 SCM_SETCAR (expr, SCM_IM_LETSTAR);
1794 /* the bindings have been changed in place */
1795 SCM_SETCDR (cdr_expr, new_body);
1796 return expr;
9fbee57e 1797}
b8229a3b 1798
212e58ed
DH
1799static SCM
1800unmemoize_letstar (const SCM expr, const SCM env)
0f2d19dd 1801{
d6754c23 1802 const SCM cdr_expr = SCM_CDR (expr);
212e58ed
DH
1803 const SCM body = SCM_CDR (cdr_expr);
1804 SCM bindings = SCM_CAR (cdr_expr);
1805 SCM um_bindings = SCM_EOL;
1806 SCM extended_env = env;
1807 SCM um_body;
d6754c23 1808
a61f4e0c 1809 while (!scm_is_null (bindings))
9fbee57e 1810 {
212e58ed
DH
1811 const SCM variable = SCM_CAR (bindings);
1812 const SCM init = SCM_CADR (bindings);
1813 const SCM um_init = unmemoize_expression (init, extended_env);
1814 um_bindings = scm_cons (scm_list_2 (variable, um_init), um_bindings);
1815 extended_env = SCM_EXTEND_ENV (variable, SCM_BOOL_F, extended_env);
1816 bindings = SCM_CDDR (bindings);
9fbee57e 1817 }
212e58ed 1818 um_bindings = scm_reverse_x (um_bindings, SCM_UNDEFINED);
d6754c23 1819
212e58ed
DH
1820 um_body = unmemoize_exprs (body, extended_env);
1821
1822 return scm_cons2 (scm_sym_letstar, um_bindings, um_body);
0f2d19dd
JB
1823}
1824
73b64342 1825
3b88ed2a 1826SCM_SYNTAX (s_or, "or", scm_i_makbimacro, scm_m_or);
9fbee57e 1827SCM_GLOBAL_SYMBOL (scm_sym_or, s_or);
73b64342
MD
1828
1829SCM
21628685 1830scm_m_or (SCM expr, SCM env SCM_UNUSED)
73b64342 1831{
21628685
DH
1832 const SCM cdr_expr = SCM_CDR (expr);
1833 const long length = scm_ilength (cdr_expr);
1834
1835 ASSERT_SYNTAX (length >= 0, s_bad_expression, expr);
1836
1837 if (length == 0)
1838 {
1839 /* Special case: (or) is replaced by #f. */
1840 return SCM_BOOL_F;
1841 }
9fbee57e 1842 else
21628685
DH
1843 {
1844 SCM_SETCAR (expr, SCM_IM_OR);
1845 return expr;
1846 }
73b64342
MD
1847}
1848
212e58ed
DH
1849static SCM
1850unmemoize_or (const SCM expr, const SCM env)
1851{
1852 return scm_cons (scm_sym_or, unmemoize_exprs (SCM_CDR (expr), env));
1853}
1854
73b64342 1855
9fbee57e
DH
1856SCM_SYNTAX (s_quasiquote, "quasiquote", scm_makacro, scm_m_quasiquote);
1857SCM_GLOBAL_SYMBOL (scm_sym_quasiquote, s_quasiquote);
6f81708a
DH
1858SCM_GLOBAL_SYMBOL (scm_sym_unquote, "unquote");
1859SCM_GLOBAL_SYMBOL (scm_sym_uq_splicing, "unquote-splicing");
9fbee57e
DH
1860
1861/* Internal function to handle a quasiquotation: 'form' is the parameter in
1862 * the call (quasiquotation form), 'env' is the environment where unquoted
1863 * expressions will be evaluated, and 'depth' is the current quasiquotation
1864 * nesting level and is known to be greater than zero. */
1865static SCM
1866iqq (SCM form, SCM env, unsigned long int depth)
73b64342 1867{
a61f4e0c 1868 if (scm_is_pair (form))
c96d76b8 1869 {
21628685 1870 const SCM tmp = SCM_CAR (form);
bc36d050 1871 if (scm_is_eq (tmp, scm_sym_quasiquote))
9fbee57e 1872 {
21628685
DH
1873 const SCM args = SCM_CDR (form);
1874 ASSERT_SYNTAX (scm_ilength (args) == 1, s_expression, form);
9fbee57e
DH
1875 return scm_list_2 (tmp, iqq (SCM_CAR (args), env, depth + 1));
1876 }
bc36d050 1877 else if (scm_is_eq (tmp, scm_sym_unquote))
9fbee57e 1878 {
21628685
DH
1879 const SCM args = SCM_CDR (form);
1880 ASSERT_SYNTAX (scm_ilength (args) == 1, s_expression, form);
9fbee57e
DH
1881 if (depth - 1 == 0)
1882 return scm_eval_car (args, env);
1883 else
1884 return scm_list_2 (tmp, iqq (SCM_CAR (args), env, depth - 1));
1885 }
a61f4e0c 1886 else if (scm_is_pair (tmp)
bc36d050 1887 && scm_is_eq (SCM_CAR (tmp), scm_sym_uq_splicing))
9fbee57e 1888 {
21628685
DH
1889 const SCM args = SCM_CDR (tmp);
1890 ASSERT_SYNTAX (scm_ilength (args) == 1, s_expression, form);
9fbee57e
DH
1891 if (depth - 1 == 0)
1892 {
21628685
DH
1893 const SCM list = scm_eval_car (args, env);
1894 const SCM rest = SCM_CDR (form);
1895 ASSERT_SYNTAX_2 (scm_ilength (list) >= 0,
1896 s_splicing, list, form);
9fbee57e
DH
1897 return scm_append (scm_list_2 (list, iqq (rest, env, depth)));
1898 }
1899 else
1900 return scm_cons (iqq (SCM_CAR (form), env, depth - 1),
1901 iqq (SCM_CDR (form), env, depth));
1902 }
1903 else
1904 return scm_cons (iqq (SCM_CAR (form), env, depth),
1905 iqq (SCM_CDR (form), env, depth));
1906 }
4057a3e0
MV
1907 else if (scm_is_vector (form))
1908 return scm_vector (iqq (scm_vector_to_list (form), env, depth));
9fbee57e
DH
1909 else
1910 return form;
1911}
1912
1913SCM
21628685 1914scm_m_quasiquote (SCM expr, SCM env)
9fbee57e 1915{
21628685
DH
1916 const SCM cdr_expr = SCM_CDR (expr);
1917 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
1918 ASSERT_SYNTAX (scm_ilength (cdr_expr) == 1, s_expression, expr);
1919 return iqq (SCM_CAR (cdr_expr), env, 1);
9fbee57e
DH
1920}
1921
1922
3b88ed2a 1923SCM_SYNTAX (s_quote, "quote", scm_i_makbimacro, scm_m_quote);
9fbee57e
DH
1924SCM_GLOBAL_SYMBOL (scm_sym_quote, s_quote);
1925
1926SCM
21628685 1927scm_m_quote (SCM expr, SCM env SCM_UNUSED)
9fbee57e 1928{
21628685
DH
1929 SCM quotee;
1930
1931 const SCM cdr_expr = SCM_CDR (expr);
1932 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
1933 ASSERT_SYNTAX (scm_ilength (cdr_expr) == 1, s_expression, expr);
1934 quotee = SCM_CAR (cdr_expr);
5fb64383 1935 if (is_self_quoting_p (quotee))
21628685 1936 return quotee;
e7313a9d 1937
21628685 1938 SCM_SETCAR (expr, SCM_IM_QUOTE);
e7313a9d 1939 SCM_SETCDR (expr, quotee);
21628685 1940 return expr;
9fbee57e
DH
1941}
1942
e7313a9d
DH
1943static SCM
1944unmemoize_quote (const SCM expr, const SCM env SCM_UNUSED)
1945{
1946 return scm_list_2 (scm_sym_quote, SCM_CDR (expr));
1947}
1948
9fbee57e
DH
1949
1950/* Will go into the RnRS module when Guile is factorized.
3b88ed2a 1951SCM_SYNTAX (s_set_x, "set!", scm_i_makbimacro, scm_m_set_x); */
9fbee57e
DH
1952static const char s_set_x[] = "set!";
1953SCM_GLOBAL_SYMBOL (scm_sym_set_x, s_set_x);
1954
1955SCM
82b3e2c6 1956scm_m_set_x (SCM expr, SCM env SCM_UNUSED)
9fbee57e 1957{
82b3e2c6 1958 SCM variable;
36245b66 1959 SCM new_variable;
82b3e2c6
DH
1960
1961 const SCM cdr_expr = SCM_CDR (expr);
1962 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
1963 ASSERT_SYNTAX (scm_ilength (cdr_expr) == 2, s_expression, expr);
1964 variable = SCM_CAR (cdr_expr);
36245b66
DH
1965
1966 /* Memoize the variable form. */
cc95e00a 1967 ASSERT_SYNTAX_2 (scm_is_symbol (variable), s_bad_variable, variable, expr);
36245b66 1968 new_variable = lookup_symbol (variable, env);
36245b66
DH
1969 /* Leave the memoization of unbound symbols to lazy memoization: */
1970 if (SCM_UNBNDP (new_variable))
1971 new_variable = variable;
82b3e2c6
DH
1972
1973 SCM_SETCAR (expr, SCM_IM_SET_X);
36245b66 1974 SCM_SETCAR (cdr_expr, new_variable);
82b3e2c6 1975 return expr;
9fbee57e
DH
1976}
1977
212e58ed
DH
1978static SCM
1979unmemoize_set_x (const SCM expr, const SCM env)
1980{
1981 return scm_cons (scm_sym_set_x, unmemoize_exprs (SCM_CDR (expr), env));
1982}
1983
9fbee57e
DH
1984
1985/* Start of the memoizers for non-R5RS builtin macros. */
1986
1987
3b88ed2a 1988SCM_SYNTAX (s_atapply, "@apply", scm_i_makbimacro, scm_m_apply);
9fbee57e
DH
1989SCM_GLOBAL_SYMBOL (scm_sym_atapply, s_atapply);
1990SCM_GLOBAL_SYMBOL (scm_sym_apply, s_atapply + 1);
1991
1992SCM
82b3e2c6 1993scm_m_apply (SCM expr, SCM env SCM_UNUSED)
9fbee57e 1994{
82b3e2c6
DH
1995 const SCM cdr_expr = SCM_CDR (expr);
1996 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
1997 ASSERT_SYNTAX (scm_ilength (cdr_expr) == 2, s_missing_expression, expr);
2e171178 1998
82b3e2c6
DH
1999 SCM_SETCAR (expr, SCM_IM_APPLY);
2000 return expr;
2001}
2e171178 2002
212e58ed
DH
2003static SCM
2004unmemoize_apply (const SCM expr, const SCM env)
2005{
2006 return scm_list_2 (scm_sym_atapply, unmemoize_exprs (SCM_CDR (expr), env));
2007}
2008
2e171178 2009
3b88ed2a 2010SCM_SYNTAX (s_atbind, "@bind", scm_i_makbimacro, scm_m_atbind);
73b64342 2011
82b3e2c6
DH
2012/* FIXME: The following explanation should go into the documentation: */
2013/* (@bind ((var init) ...) body ...) will assign the values of the `init's to
2014 * the global variables named by `var's (symbols, not evaluated), creating
2015 * them if they don't exist, executes body, and then restores the previous
2016 * values of the `var's. Additionally, whenever control leaves body, the
2017 * values of the `var's are saved and restored when control returns. It is an
2018 * error when a symbol appears more than once among the `var's. All `init's
2019 * are evaluated before any `var' is set.
2020 *
2021 * Think of this as `let' for dynamic scope.
2022 */
2023
2024/* (@bind ((var1 exp1) ... (varn expn)) body ...) is memoized into
2025 * (#@bind ((varn ... var1) . (exp1 ... expn)) body ...).
2026 *
2027 * FIXME - also implement `@bind*'.
2028 */
73b64342 2029SCM
82b3e2c6 2030scm_m_atbind (SCM expr, SCM env)
73b64342 2031{
82b3e2c6
DH
2032 SCM bindings;
2033 SCM rvariables;
2034 SCM inits;
2035 SCM variable_idx;
2e171178 2036
82b3e2c6 2037 const SCM top_level = scm_env_top_level (env);
73b64342 2038
82b3e2c6
DH
2039 const SCM cdr_expr = SCM_CDR (expr);
2040 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
2041 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 2, s_missing_expression, expr);
2042 bindings = SCM_CAR (cdr_expr);
2043 check_bindings (bindings, expr);
2044 transform_bindings (bindings, expr, &rvariables, &inits);
2045
2046 for (variable_idx = rvariables;
a61f4e0c 2047 !scm_is_null (variable_idx);
82b3e2c6 2048 variable_idx = SCM_CDR (variable_idx))
73b64342 2049 {
82b3e2c6
DH
2050 /* The first call to scm_sym2var will look beyond the current module,
2051 * while the second call wont. */
2052 const SCM variable = SCM_CAR (variable_idx);
2053 SCM new_variable = scm_sym2var (variable, top_level, SCM_BOOL_F);
7888309b 2054 if (scm_is_false (new_variable))
82b3e2c6
DH
2055 new_variable = scm_sym2var (variable, top_level, SCM_BOOL_T);
2056 SCM_SETCAR (variable_idx, new_variable);
73b64342 2057 }
82b3e2c6
DH
2058
2059 SCM_SETCAR (expr, SCM_IM_BIND);
2060 SCM_SETCAR (cdr_expr, scm_cons (rvariables, inits));
2061 return expr;
73b64342 2062}
73b64342 2063
b0c5d67b 2064
3b88ed2a 2065SCM_SYNTAX(s_atcall_cc, "@call-with-current-continuation", scm_i_makbimacro, scm_m_cont);
9fbee57e
DH
2066SCM_GLOBAL_SYMBOL(scm_sym_atcall_cc, s_atcall_cc);
2067
9fbee57e 2068SCM
da48db62 2069scm_m_cont (SCM expr, SCM env SCM_UNUSED)
b0c5d67b 2070{
da48db62
DH
2071 const SCM cdr_expr = SCM_CDR (expr);
2072 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
2073 ASSERT_SYNTAX (scm_ilength (cdr_expr) == 1, s_expression, expr);
2074
2075 SCM_SETCAR (expr, SCM_IM_CONT);
2076 return expr;
b0c5d67b 2077}
b0c5d67b 2078
212e58ed
DH
2079static SCM
2080unmemoize_atcall_cc (const SCM expr, const SCM env)
2081{
2082 return scm_list_2 (scm_sym_atcall_cc, unmemoize_exprs (SCM_CDR (expr), env));
2083}
2084
b0c5d67b 2085
3b88ed2a 2086SCM_SYNTAX (s_at_call_with_values, "@call-with-values", scm_i_makbimacro, scm_m_at_call_with_values);
9fbee57e 2087SCM_GLOBAL_SYMBOL(scm_sym_at_call_with_values, s_at_call_with_values);
b0c5d67b
DH
2088
2089SCM
da48db62 2090scm_m_at_call_with_values (SCM expr, SCM env SCM_UNUSED)
b0c5d67b 2091{
da48db62
DH
2092 const SCM cdr_expr = SCM_CDR (expr);
2093 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
2094 ASSERT_SYNTAX (scm_ilength (cdr_expr) == 2, s_expression, expr);
2095
2096 SCM_SETCAR (expr, SCM_IM_CALL_WITH_VALUES);
2097 return expr;
b0c5d67b 2098}
b0c5d67b 2099
212e58ed
DH
2100static SCM
2101unmemoize_at_call_with_values (const SCM expr, const SCM env)
2102{
2103 return scm_list_2 (scm_sym_at_call_with_values,
2104 unmemoize_exprs (SCM_CDR (expr), env));
2105}
2106
2f263a6a
MV
2107#if 0
2108
2109/* See futures.h for a comment why futures are not enabled.
2110 */
b0c5d67b 2111
3b88ed2a 2112SCM_SYNTAX (s_future, "future", scm_i_makbimacro, scm_m_future);
9fbee57e 2113SCM_GLOBAL_SYMBOL (scm_sym_future, s_future);
a513ead3 2114
9fbee57e
DH
2115/* Like promises, futures are implemented as closures with an empty
2116 * parameter list. Thus, (future <expression>) is transformed into
2117 * (#@future '() <expression>), where the empty list represents the
2118 * empty parameter list. This representation allows for easy creation
2119 * of the closure during evaluation. */
a513ead3 2120SCM
8ae95199 2121scm_m_future (SCM expr, SCM env)
a513ead3 2122{
8ae95199
DH
2123 const SCM new_expr = memoize_as_thunk_prototype (expr, env);
2124 SCM_SETCAR (new_expr, SCM_IM_FUTURE);
2125 return new_expr;
a513ead3
MV
2126}
2127
212e58ed
DH
2128static SCM
2129unmemoize_future (const SCM expr, const SCM env)
2130{
2131 const SCM thunk_expr = SCM_CADDR (expr);
2132 return scm_list_2 (scm_sym_future, unmemoize_expression (thunk_expr, env));
2133}
2134
2f263a6a 2135#endif
9fbee57e 2136
3b88ed2a 2137SCM_SYNTAX (s_gset_x, "set!", scm_i_makbimacro, scm_m_generalized_set_x);
9fbee57e
DH
2138SCM_SYMBOL (scm_sym_setter, "setter");
2139
2140SCM
7893dbbf 2141scm_m_generalized_set_x (SCM expr, SCM env)
9fbee57e 2142{
7893dbbf 2143 SCM target, exp_target;
da48db62
DH
2144
2145 const SCM cdr_expr = SCM_CDR (expr);
2146 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
2147 ASSERT_SYNTAX (scm_ilength (cdr_expr) == 2, s_expression, expr);
2148
2149 target = SCM_CAR (cdr_expr);
a61f4e0c 2150 if (!scm_is_pair (target))
da48db62
DH
2151 {
2152 /* R5RS usage */
2153 return scm_m_set_x (expr, env);
2154 }
9fbee57e 2155 else
da48db62
DH
2156 {
2157 /* (set! (foo bar ...) baz) becomes ((setter foo) bar ... baz) */
7893dbbf
MV
2158 /* Macroexpanding the target might return things of the form
2159 (begin <atom>). In that case, <atom> must be a symbol or a
2160 variable and we memoize to (set! <atom> ...).
2161 */
2b189e65 2162 exp_target = macroexp (target, env);
bc36d050 2163 if (scm_is_eq (SCM_CAR (exp_target), SCM_IM_BEGIN)
a61f4e0c
MV
2164 && !scm_is_null (SCM_CDR (exp_target))
2165 && scm_is_null (SCM_CDDR (exp_target)))
7893dbbf
MV
2166 {
2167 exp_target= SCM_CADR (exp_target);
cc95e00a 2168 ASSERT_SYNTAX_2 (scm_is_symbol (exp_target)
6d1a2e9f
MV
2169 || SCM_VARIABLEP (exp_target),
2170 s_bad_variable, exp_target, expr);
7893dbbf
MV
2171 return scm_cons (SCM_IM_SET_X, scm_cons (exp_target,
2172 SCM_CDR (cdr_expr)));
2173 }
2174 else
2175 {
2176 const SCM setter_proc_tail = scm_list_1 (SCM_CAR (target));
2177 const SCM setter_proc = scm_cons_source (expr, scm_sym_setter,
2178 setter_proc_tail);
da48db62 2179
7893dbbf
MV
2180 const SCM cddr_expr = SCM_CDR (cdr_expr);
2181 const SCM setter_args = scm_append_x (scm_list_2 (SCM_CDR (target),
2182 cddr_expr));
da48db62 2183
7893dbbf
MV
2184 SCM_SETCAR (expr, setter_proc);
2185 SCM_SETCDR (expr, setter_args);
2186 return expr;
2187 }
da48db62 2188 }
9fbee57e
DH
2189}
2190
2191
a4aa2134
DH
2192/* @slot-ref is bound privately in the (oop goops) module from goops.c. As
2193 * soon as the module system allows us to more freely create bindings in
2194 * arbitrary modules during the startup phase, the code from goops.c should be
2195 * moved here. */
212e58ed
DH
2196
2197SCM_SYMBOL (sym_atslot_ref, "@slot-ref");
2198
9fbee57e 2199SCM
9a848baf 2200scm_m_atslot_ref (SCM expr, SCM env SCM_UNUSED)
9fbee57e 2201{
9a848baf
DH
2202 SCM slot_nr;
2203
2204 const SCM cdr_expr = SCM_CDR (expr);
2205 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
2206 ASSERT_SYNTAX (scm_ilength (cdr_expr) == 2, s_expression, expr);
2207 slot_nr = SCM_CADR (cdr_expr);
e11e83f3 2208 ASSERT_SYNTAX_2 (SCM_I_INUMP (slot_nr), s_bad_slot_number, slot_nr, expr);
9fbee57e 2209
9a848baf 2210 SCM_SETCAR (expr, SCM_IM_SLOT_REF);
e7313a9d 2211 SCM_SETCDR (cdr_expr, slot_nr);
9a848baf
DH
2212 return expr;
2213}
9fbee57e 2214
212e58ed
DH
2215static SCM
2216unmemoize_atslot_ref (const SCM expr, const SCM env)
2217{
2218 const SCM instance = SCM_CADR (expr);
2219 const SCM um_instance = unmemoize_expression (instance, env);
2220 const SCM slot_nr = SCM_CDDR (expr);
2221 return scm_list_3 (sym_atslot_ref, um_instance, slot_nr);
2222}
2223
9fbee57e 2224
a4aa2134
DH
2225/* @slot-set! is bound privately in the (oop goops) module from goops.c. As
2226 * soon as the module system allows us to more freely create bindings in
2227 * arbitrary modules during the startup phase, the code from goops.c should be
2228 * moved here. */
212e58ed
DH
2229
2230SCM_SYMBOL (sym_atslot_set_x, "@slot-set!");
2231
9fbee57e 2232SCM
9a848baf 2233scm_m_atslot_set_x (SCM expr, SCM env SCM_UNUSED)
9fbee57e 2234{
9a848baf
DH
2235 SCM slot_nr;
2236
2237 const SCM cdr_expr = SCM_CDR (expr);
2238 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
2239 ASSERT_SYNTAX (scm_ilength (cdr_expr) == 3, s_expression, expr);
2240 slot_nr = SCM_CADR (cdr_expr);
e11e83f3 2241 ASSERT_SYNTAX_2 (SCM_I_INUMP (slot_nr), s_bad_slot_number, slot_nr, expr);
9a848baf
DH
2242
2243 SCM_SETCAR (expr, SCM_IM_SLOT_SET_X);
2244 return expr;
9fbee57e 2245}
9fbee57e 2246
212e58ed
DH
2247static SCM
2248unmemoize_atslot_set_x (const SCM expr, const SCM env)
2249{
2250 const SCM cdr_expr = SCM_CDR (expr);
2251 const SCM instance = SCM_CAR (cdr_expr);
2252 const SCM um_instance = unmemoize_expression (instance, env);
2253 const SCM cddr_expr = SCM_CDR (cdr_expr);
2254 const SCM slot_nr = SCM_CAR (cddr_expr);
2255 const SCM cdddr_expr = SCM_CDR (cddr_expr);
2256 const SCM value = SCM_CAR (cdddr_expr);
2257 const SCM um_value = unmemoize_expression (value, env);
2258 return scm_list_4 (sym_atslot_set_x, um_instance, slot_nr, um_value);
2259}
2260
9fbee57e
DH
2261
2262#if SCM_ENABLE_ELISP
2263
70c1c108
DH
2264static const char s_defun[] = "Symbol's function definition is void";
2265
3b88ed2a 2266SCM_SYNTAX (s_nil_cond, "nil-cond", scm_i_makbimacro, scm_m_nil_cond);
9fbee57e 2267
70c1c108
DH
2268/* nil-cond expressions have the form
2269 * (nil-cond COND VAL COND VAL ... ELSEVAL) */
9fbee57e 2270SCM
70c1c108 2271scm_m_nil_cond (SCM expr, SCM env SCM_UNUSED)
9fbee57e 2272{
70c1c108
DH
2273 const long length = scm_ilength (SCM_CDR (expr));
2274 ASSERT_SYNTAX (length >= 0, s_bad_expression, expr);
2275 ASSERT_SYNTAX (length >= 1 && (length % 2) == 1, s_expression, expr);
2276
2277 SCM_SETCAR (expr, SCM_IM_NIL_COND);
2278 return expr;
9fbee57e
DH
2279}
2280
2281
3b88ed2a 2282SCM_SYNTAX (s_atfop, "@fop", scm_i_makbimacro, scm_m_atfop);
9fbee57e 2283
70c1c108
DH
2284/* The @fop-macro handles procedure and macro applications for elisp. The
2285 * input expression must have the form
2286 * (@fop <var> (transformer-macro <expr> ...))
2287 * where <var> must be a symbol. The expression is transformed into the
2288 * memoized form of either
2289 * (apply <un-aliased var> (transformer-macro <expr> ...))
2290 * if the value of var (across all aliasing) is not a macro, or
2291 * (<un-aliased var> <expr> ...)
2292 * if var is a macro. */
9fbee57e 2293SCM
70c1c108 2294scm_m_atfop (SCM expr, SCM env SCM_UNUSED)
9fbee57e 2295{
70c1c108
DH
2296 SCM location;
2297 SCM symbol;
2298
2299 const SCM cdr_expr = SCM_CDR (expr);
2300 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
2301 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 1, s_missing_expression, expr);
2302
2303 symbol = SCM_CAR (cdr_expr);
cc95e00a 2304 ASSERT_SYNTAX_2 (scm_is_symbol (symbol), s_bad_variable, symbol, expr);
70c1c108
DH
2305
2306 location = scm_symbol_fref (symbol);
2307 ASSERT_SYNTAX_2 (SCM_VARIABLEP (location), s_defun, symbol, expr);
2308
2309 /* The elisp function `defalias' allows to define aliases for symbols. To
2310 * look up such definitions, the chain of symbol definitions has to be
2311 * followed up to the terminal symbol. */
cc95e00a 2312 while (scm_is_symbol (SCM_VARIABLE_REF (location)))
9fbee57e 2313 {
70c1c108
DH
2314 const SCM alias = SCM_VARIABLE_REF (location);
2315 location = scm_symbol_fref (alias);
2316 ASSERT_SYNTAX_2 (SCM_VARIABLEP (location), s_defun, symbol, expr);
9fbee57e 2317 }
70c1c108
DH
2318
2319 /* Memoize the value location belonging to the terminal symbol. */
2320 SCM_SETCAR (cdr_expr, location);
2321
2322 if (!SCM_MACROP (SCM_VARIABLE_REF (location)))
9fbee57e 2323 {
70c1c108
DH
2324 /* Since the location does not contain a macro, the form is a procedure
2325 * application. Replace `@fop' by `@apply' and transform the expression
2326 * including the `transformer-macro'. */
2327 SCM_SETCAR (expr, SCM_IM_APPLY);
2328 return expr;
2329 }
2330 else
2331 {
2332 /* Since the location contains a macro, the arguments should not be
2333 * transformed, so the `transformer-macro' is cut out. The resulting
2334 * expression starts with the memoized variable, that is at the cdr of
2335 * the input expression. */
2336 SCM_SETCDR (cdr_expr, SCM_CDADR (cdr_expr));
2337 return cdr_expr;
9fbee57e 2338 }
9fbee57e
DH
2339}
2340
2341#endif /* SCM_ENABLE_ELISP */
2342
2343
212e58ed
DH
2344static SCM
2345unmemoize_builtin_macro (const SCM expr, const SCM env)
2346{
2347 switch (ISYMNUM (SCM_CAR (expr)))
2348 {
2349 case (ISYMNUM (SCM_IM_AND)):
2350 return unmemoize_and (expr, env);
2351
2352 case (ISYMNUM (SCM_IM_BEGIN)):
2353 return unmemoize_begin (expr, env);
2354
2355 case (ISYMNUM (SCM_IM_CASE)):
2356 return unmemoize_case (expr, env);
2357
2358 case (ISYMNUM (SCM_IM_COND)):
2359 return unmemoize_cond (expr, env);
2360
2361 case (ISYMNUM (SCM_IM_DELAY)):
2362 return unmemoize_delay (expr, env);
2363
2364 case (ISYMNUM (SCM_IM_DO)):
2365 return unmemoize_do (expr, env);
2366
2367 case (ISYMNUM (SCM_IM_IF)):
2368 return unmemoize_if (expr, env);
2369
2370 case (ISYMNUM (SCM_IM_LAMBDA)):
2371 return unmemoize_lambda (expr, env);
2372
2373 case (ISYMNUM (SCM_IM_LET)):
2374 return unmemoize_let (expr, env);
2375
2376 case (ISYMNUM (SCM_IM_LETREC)):
2377 return unmemoize_letrec (expr, env);
2378
2379 case (ISYMNUM (SCM_IM_LETSTAR)):
2380 return unmemoize_letstar (expr, env);
2381
2382 case (ISYMNUM (SCM_IM_OR)):
2383 return unmemoize_or (expr, env);
2384
2385 case (ISYMNUM (SCM_IM_QUOTE)):
2386 return unmemoize_quote (expr, env);
2387
2388 case (ISYMNUM (SCM_IM_SET_X)):
2389 return unmemoize_set_x (expr, env);
2390
2391 case (ISYMNUM (SCM_IM_APPLY)):
2392 return unmemoize_apply (expr, env);
2393
2394 case (ISYMNUM (SCM_IM_BIND)):
2395 return unmemoize_exprs (expr, env); /* FIXME */
2396
2397 case (ISYMNUM (SCM_IM_CONT)):
2398 return unmemoize_atcall_cc (expr, env);
2399
2400 case (ISYMNUM (SCM_IM_CALL_WITH_VALUES)):
2401 return unmemoize_at_call_with_values (expr, env);
2402
2f263a6a
MV
2403#if 0
2404 /* See futures.h for a comment why futures are not enabled.
2405 */
212e58ed
DH
2406 case (ISYMNUM (SCM_IM_FUTURE)):
2407 return unmemoize_future (expr, env);
2f263a6a 2408#endif
212e58ed
DH
2409
2410 case (ISYMNUM (SCM_IM_SLOT_REF)):
2411 return unmemoize_atslot_ref (expr, env);
2412
2413 case (ISYMNUM (SCM_IM_SLOT_SET_X)):
2414 return unmemoize_atslot_set_x (expr, env);
2415
2416 case (ISYMNUM (SCM_IM_NIL_COND)):
2417 return unmemoize_exprs (expr, env); /* FIXME */
2418
2419 default:
2420 return unmemoize_exprs (expr, env); /* FIXME */
2421 }
2422}
2423
2424
9fcf3cbb
DH
2425/* scm_i_unmemocopy_expr and scm_i_unmemocopy_body take a memoized expression
2426 * respectively a memoized body together with its environment and rewrite it
2427 * to its original form. Thus, these functions are the inversion of the
2428 * rewrite rules above. The procedure is not optimized for speed. It's used
2429 * in scm_i_unmemoize_expr, scm_procedure_source, macro_print and scm_iprin1.
212e58ed
DH
2430 *
2431 * Unmemoizing is not a reliable process. You cannot in general expect to get
2432 * the original source back.
2433 *
2434 * However, GOOPS currently relies on this for method compilation. This ought
2435 * to change. */
2436
2437SCM
9fcf3cbb
DH
2438scm_i_unmemocopy_expr (SCM expr, SCM env)
2439{
2440 const SCM source_properties = scm_whash_lookup (scm_source_whash, expr);
2441 const SCM um_expr = unmemoize_expression (expr, env);
2442
7888309b 2443 if (scm_is_true (source_properties))
9fcf3cbb
DH
2444 scm_whash_insert (scm_source_whash, um_expr, source_properties);
2445
2446 return um_expr;
2447}
2448
2449SCM
2450scm_i_unmemocopy_body (SCM forms, SCM env)
212e58ed
DH
2451{
2452 const SCM source_properties = scm_whash_lookup (scm_source_whash, forms);
2453 const SCM um_forms = unmemoize_exprs (forms, env);
2454
7888309b 2455 if (scm_is_true (source_properties))
212e58ed
DH
2456 scm_whash_insert (scm_source_whash, um_forms, source_properties);
2457
2458 return um_forms;
2459}
2460
2461
434f2f7a 2462#if (SCM_ENABLE_DEPRECATED == 1)
f58c472a 2463
434f2f7a
DH
2464/* Deprecated in guile 1.7.0 on 2003-11-09. */
2465SCM
2466scm_m_expand_body (SCM exprs, SCM env)
2467{
2468 scm_c_issue_deprecation_warning
2469 ("`scm_m_expand_body' is deprecated.");
2470 m_expand_body (exprs, env);
2471 return exprs;
2472}
f58c472a 2473
f58c472a
DH
2474
2475SCM_SYNTAX (s_undefine, "undefine", scm_makacro, scm_m_undefine);
2476
2477SCM
70c1c108 2478scm_m_undefine (SCM expr, SCM env)
f58c472a 2479{
70c1c108
DH
2480 SCM variable;
2481 SCM location;
2482
2483 const SCM cdr_expr = SCM_CDR (expr);
2484 ASSERT_SYNTAX (SCM_TOP_LEVEL (env), "Bad undefine placement in", expr);
2485 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
2486 ASSERT_SYNTAX (scm_ilength (cdr_expr) == 1, s_expression, expr);
2487
2b189e65
MV
2488 scm_c_issue_deprecation_warning
2489 ("`undefine' is deprecated.\n");
2490
70c1c108 2491 variable = SCM_CAR (cdr_expr);
cc95e00a 2492 ASSERT_SYNTAX_2 (scm_is_symbol (variable), s_bad_variable, variable, expr);
70c1c108 2493 location = scm_sym2var (variable, scm_env_top_level (env), SCM_BOOL_F);
7888309b 2494 ASSERT_SYNTAX_2 (scm_is_true (location)
70c1c108
DH
2495 && !SCM_UNBNDP (SCM_VARIABLE_REF (location)),
2496 "variable already unbound ", variable, expr);
2497 SCM_VARIABLE_SET (location, SCM_UNDEFINED);
f58c472a 2498 return SCM_UNSPECIFIED;
f58c472a
DH
2499}
2500
26d5b9b4
MD
2501SCM
2502scm_macroexp (SCM x, SCM env)
2503{
2b189e65
MV
2504 scm_c_issue_deprecation_warning
2505 ("`scm_macroexp' is deprecated.");
2506 return macroexp (x, env);
26d5b9b4 2507}
73b64342 2508
6f81708a
DH
2509#endif
2510
60a49842 2511
212e58ed 2512#if (SCM_ENABLE_DEPRECATED == 1)
26d5b9b4 2513
212e58ed
DH
2514SCM
2515scm_unmemocar (SCM form, SCM env)
8ea46249 2516{
212e58ed
DH
2517 scm_c_issue_deprecation_warning
2518 ("`scm_unmemocar' is deprecated.");
60a49842 2519
a61f4e0c 2520 if (!scm_is_pair (form))
60a49842
DH
2521 return form;
2522 else
2523 {
2524 SCM c = SCM_CAR (form);
2525 if (SCM_VARIABLEP (c))
2526 {
2527 SCM sym = scm_module_reverse_lookup (scm_env_module (env), c);
7888309b 2528 if (scm_is_false (sym))
60a49842
DH
2529 sym = sym_three_question_marks;
2530 SCM_SETCAR (form, sym);
2531 }
2532 else if (SCM_ILOCP (c))
2533 {
2534 unsigned long int ir;
2535
2536 for (ir = SCM_IFRAME (c); ir != 0; --ir)
2537 env = SCM_CDR (env);
2538 env = SCM_CAAR (env);
2539 for (ir = SCM_IDIST (c); ir != 0; --ir)
2540 env = SCM_CDR (env);
f62b9dff 2541
60a49842
DH
2542 SCM_SETCAR (form, SCM_ICDRP (c) ? env : SCM_CAR (env));
2543 }
2544 return form;
2545 }
2546}
2547
434f2f7a
DH
2548#endif
2549
6f81708a
DH
2550/*****************************************************************************/
2551/*****************************************************************************/
2552/* The definitions for execution start here. */
2553/*****************************************************************************/
2554/*****************************************************************************/
2555
2556SCM_GLOBAL_SYMBOL (scm_sym_enter_frame, "enter-frame");
2557SCM_GLOBAL_SYMBOL (scm_sym_apply_frame, "apply-frame");
2558SCM_GLOBAL_SYMBOL (scm_sym_exit_frame, "exit-frame");
72f19c26 2559SCM_GLOBAL_SYMBOL (scm_sym_memoize_symbol, "memoize-symbol");
6f81708a 2560SCM_GLOBAL_SYMBOL (scm_sym_trace, "trace");
7c9c0169 2561SCM_SYMBOL (sym_instead, "instead");
6f81708a
DH
2562
2563/* A function object to implement "apply" for non-closure functions. */
2564static SCM f_apply;
2565/* An endless list consisting of #<undefined> objects: */
2566static SCM undefineds;
2567
2568
2569int
6e8d25a6 2570scm_badargsp (SCM formals, SCM args)
0f2d19dd 2571{
a61f4e0c 2572 while (!scm_is_null (formals))
0f2d19dd 2573 {
a61f4e0c 2574 if (!scm_is_pair (formals))
ff467021 2575 return 0;
a61f4e0c 2576 if (scm_is_null (args))
ff467021 2577 return 1;
0f2d19dd
JB
2578 formals = SCM_CDR (formals);
2579 args = SCM_CDR (args);
2580 }
a61f4e0c 2581 return !scm_is_null (args) ? 1 : 0;
0f2d19dd 2582}
a392ee15 2583
0f2d19dd 2584\f
62360b89 2585
434f2f7a
DH
2586/* The evaluator contains a plethora of EVAL symbols. This is an attempt at
2587 * explanation.
62360b89 2588 *
434f2f7a
DH
2589 * The following macros should be used in code which is read twice (where the
2590 * choice of evaluator is hard soldered):
62360b89 2591 *
434f2f7a
DH
2592 * CEVAL is the symbol used within one evaluator to call itself.
2593 * Originally, it is defined to ceval, but is redefined to deval during the
2594 * second pass.
62360b89 2595 *
385609b9 2596 * SCM_I_EVALIM is used when it is known that the expression is an
62360b89 2597 * immediate. (This macro never calls an evaluator.)
434f2f7a
DH
2598 *
2599 * EVAL evaluates an expression that is expected to have its symbols already
2600 * memoized. Expressions that are not of the form '(<form> <form> ...)' are
2601 * evaluated inline without calling an evaluator.
2602 *
2603 * EVALCAR evaluates the car of an expression 'X:(Y:<form> <form> ...)',
2604 * potentially replacing a symbol at the position Y:<form> by its memoized
2605 * variable. If Y:<form> is not of the form '(<form> <form> ...)', the
2606 * evaluation is performed inline without calling an evaluator.
62360b89
DH
2607 *
2608 * The following macros should be used in code which is read once
2609 * (where the choice of evaluator is dynamic):
2610 *
385609b9 2611 * SCM_I_XEVAL corresponds to EVAL, but uses ceval *or* deval depending on the
434f2f7a 2612 * debugging mode.
62360b89 2613 *
385609b9 2614 * SCM_I_XEVALCAR corresponds to EVALCAR, but uses ceval *or* deval depending
434f2f7a 2615 * on the debugging mode.
62360b89
DH
2616 *
2617 * The main motivation for keeping this plethora is efficiency
2618 * together with maintainability (=> locality of code).
2619 */
2620
434f2f7a
DH
2621static SCM ceval (SCM x, SCM env);
2622static SCM deval (SCM x, SCM env);
2623#define CEVAL ceval
2624
62360b89 2625
385609b9 2626#define SCM_I_EVALIM2(x) \
bc36d050 2627 ((scm_is_eq ((x), SCM_EOL) \
62360b89
DH
2628 ? syntax_error (s_empty_combination, (x), SCM_UNDEFINED), 0 \
2629 : 0), \
2630 (x))
2631
385609b9 2632#define SCM_I_EVALIM(x, env) (SCM_ILOCP (x) \
434f2f7a 2633 ? *scm_ilookup ((x), (env)) \
385609b9 2634 : SCM_I_EVALIM2(x))
62360b89 2635
385609b9 2636#define SCM_I_XEVAL(x, env) \
434f2f7a 2637 (SCM_IMP (x) \
385609b9 2638 ? SCM_I_EVALIM2 (x) \
434f2f7a
DH
2639 : (SCM_VARIABLEP (x) \
2640 ? SCM_VARIABLE_REF (x) \
a61f4e0c 2641 : (scm_is_pair (x) \
434f2f7a
DH
2642 ? (scm_debug_mode_p \
2643 ? deval ((x), (env)) \
2644 : ceval ((x), (env))) \
2645 : (x))))
2646
385609b9 2647#define SCM_I_XEVALCAR(x, env) \
434f2f7a 2648 (SCM_IMP (SCM_CAR (x)) \
385609b9 2649 ? SCM_I_EVALIM (SCM_CAR (x), (env)) \
434f2f7a
DH
2650 : (SCM_VARIABLEP (SCM_CAR (x)) \
2651 ? SCM_VARIABLE_REF (SCM_CAR (x)) \
a61f4e0c 2652 : (scm_is_pair (SCM_CAR (x)) \
434f2f7a
DH
2653 ? (scm_debug_mode_p \
2654 ? deval (SCM_CAR (x), (env)) \
2655 : ceval (SCM_CAR (x), (env))) \
cc95e00a 2656 : (!scm_is_symbol (SCM_CAR (x)) \
434f2f7a
DH
2657 ? SCM_CAR (x) \
2658 : *scm_lookupcar ((x), (env), 1)))))
2659
2660#define EVAL(x, env) \
2661 (SCM_IMP (x) \
385609b9 2662 ? SCM_I_EVALIM ((x), (env)) \
434f2f7a
DH
2663 : (SCM_VARIABLEP (x) \
2664 ? SCM_VARIABLE_REF (x) \
a61f4e0c 2665 : (scm_is_pair (x) \
434f2f7a
DH
2666 ? CEVAL ((x), (env)) \
2667 : (x))))
2668
2669#define EVALCAR(x, env) \
2670 (SCM_IMP (SCM_CAR (x)) \
385609b9 2671 ? SCM_I_EVALIM (SCM_CAR (x), (env)) \
434f2f7a
DH
2672 : (SCM_VARIABLEP (SCM_CAR (x)) \
2673 ? SCM_VARIABLE_REF (SCM_CAR (x)) \
a61f4e0c 2674 : (scm_is_pair (SCM_CAR (x)) \
434f2f7a 2675 ? CEVAL (SCM_CAR (x), (env)) \
cc95e00a 2676 : (!scm_is_symbol (SCM_CAR (x)) \
434f2f7a
DH
2677 ? SCM_CAR (x) \
2678 : *scm_lookupcar ((x), (env), 1)))))
62360b89 2679
d1138028 2680scm_i_pthread_mutex_t source_mutex;
62360b89
DH
2681
2682
e5156567
DH
2683/* Lookup a given local variable in an environment. The local variable is
2684 * given as an iloc, that is a triple <frame, binding, last?>, where frame
2685 * indicates the relative number of the environment frame (counting upwards
2686 * from the innermost environment frame), binding indicates the number of the
2687 * binding within the frame, and last? (which is extracted from the iloc using
2688 * the macro SCM_ICDRP) indicates whether the binding forms the binding at the
2689 * very end of the improper list of bindings. */
2690SCM *
2691scm_ilookup (SCM iloc, SCM env)
2692{
2693 unsigned int frame_nr = SCM_IFRAME (iloc);
2694 unsigned int binding_nr = SCM_IDIST (iloc);
2695 SCM frames = env;
2696 SCM bindings;
2697
2698 for (; 0 != frame_nr; --frame_nr)
2699 frames = SCM_CDR (frames);
2700
2701 bindings = SCM_CAR (frames);
2702 for (; 0 != binding_nr; --binding_nr)
2703 bindings = SCM_CDR (bindings);
2704
2705 if (SCM_ICDRP (iloc))
2706 return SCM_CDRLOC (bindings);
2707 return SCM_CARLOC (SCM_CDR (bindings));
2708}
2709
2710
2711SCM_SYMBOL (scm_unbound_variable_key, "unbound-variable");
2712
2713static void error_unbound_variable (SCM symbol) SCM_NORETURN;
2d0c133f
MV
2714static void error_defined_variable (SCM symbol) SCM_NORETURN;
2715
2716/* Call this for variables that are unfound.
2717 */
e5156567
DH
2718static void
2719error_unbound_variable (SCM symbol)
2720{
2721 scm_error (scm_unbound_variable_key, NULL,
2722 "Unbound variable: ~S",
2723 scm_list_1 (symbol), SCM_BOOL_F);
2724}
2725
2d0c133f
MV
2726/* Call this for variables that are found but contain SCM_UNDEFINED.
2727 */
2728static void
2729error_defined_variable (SCM symbol)
2730{
2731 /* We use the 'unbound-variable' key here as well, since it
2732 basically is the same kind of error, with a slight variation in
2733 the displayed message.
2734 */
2735 scm_error (scm_unbound_variable_key, NULL,
a03bad87 2736 "Variable used before given a value: ~S",
2d0c133f
MV
2737 scm_list_1 (symbol), SCM_BOOL_F);
2738}
2739
e5156567
DH
2740
2741/* The Lookup Car Race
2742 - by Eva Luator
2743
2744 Memoization of variables and special forms is done while executing
2745 the code for the first time. As long as there is only one thread
2746 everything is fine, but as soon as two threads execute the same
2747 code concurrently `for the first time' they can come into conflict.
2748
2749 This memoization includes rewriting variable references into more
2750 efficient forms and expanding macros. Furthermore, macro expansion
2751 includes `compiling' special forms like `let', `cond', etc. into
2752 tree-code instructions.
2753
2754 There shouldn't normally be a problem with memoizing local and
2755 global variable references (into ilocs and variables), because all
2756 threads will mutate the code in *exactly* the same way and (if I
2757 read the C code correctly) it is not possible to observe a half-way
2758 mutated cons cell. The lookup procedure can handle this
2759 transparently without any critical sections.
2760
2761 It is different with macro expansion, because macro expansion
2762 happens outside of the lookup procedure and can't be
2763 undone. Therefore the lookup procedure can't cope with it. It has
2764 to indicate failure when it detects a lost race and hope that the
2765 caller can handle it. Luckily, it turns out that this is the case.
2766
2767 An example to illustrate this: Suppose that the following form will
2768 be memoized concurrently by two threads
2769
2770 (let ((x 12)) x)
2771
2772 Let's first examine the lookup of X in the body. The first thread
2773 decides that it has to find the symbol "x" in the environment and
2774 starts to scan it. Then the other thread takes over and actually
2775 overtakes the first. It looks up "x" and substitutes an
2776 appropriate iloc for it. Now the first thread continues and
2777 completes its lookup. It comes to exactly the same conclusions as
2778 the second one and could - without much ado - just overwrite the
2779 iloc with the same iloc.
2780
2781 But let's see what will happen when the race occurs while looking
2782 up the symbol "let" at the start of the form. It could happen that
2783 the second thread interrupts the lookup of the first thread and not
2784 only substitutes a variable for it but goes right ahead and
2785 replaces it with the compiled form (#@let* (x 12) x). Now, when
2786 the first thread completes its lookup, it would replace the #@let*
2787 with a variable containing the "let" binding, effectively reverting
2788 the form to (let (x 12) x). This is wrong. It has to detect that
2789 it has lost the race and the evaluator has to reconsider the
2790 changed form completely.
2791
2792 This race condition could be resolved with some kind of traffic
2793 light (like mutexes) around scm_lookupcar, but I think that it is
2794 best to avoid them in this case. They would serialize memoization
2795 completely and because lookup involves calling arbitrary Scheme
2796 code (via the lookup-thunk), threads could be blocked for an
2797 arbitrary amount of time or even deadlock. But with the current
2798 solution a lot of unnecessary work is potentially done. */
2799
2800/* SCM_LOOKUPCAR1 is what SCM_LOOKUPCAR used to be but is allowed to
2801 return NULL to indicate a failed lookup due to some race conditions
2802 between threads. This only happens when VLOC is the first cell of
2803 a special form that will eventually be memoized (like `let', etc.)
2804 In that case the whole lookup is bogus and the caller has to
2805 reconsider the complete special form.
2806
2807 SCM_LOOKUPCAR is still there, of course. It just calls
2808 SCM_LOOKUPCAR1 and aborts on receiving NULL. So SCM_LOOKUPCAR
2809 should only be called when it is known that VLOC is not the first
2810 pair of a special form. Otherwise, use SCM_LOOKUPCAR1 and check
2811 for NULL. I think I've found the only places where this
2812 applies. */
2813
2814static SCM *
2815scm_lookupcar1 (SCM vloc, SCM genv, int check)
2816{
2817 SCM env = genv;
2818 register SCM *al, fl, var = SCM_CAR (vloc);
2819 register SCM iloc = SCM_ILOC00;
2820 for (; SCM_NIMP (env); env = SCM_CDR (env))
2821 {
a61f4e0c 2822 if (!scm_is_pair (SCM_CAR (env)))
e5156567
DH
2823 break;
2824 al = SCM_CARLOC (env);
2825 for (fl = SCM_CAR (*al); SCM_NIMP (fl); fl = SCM_CDR (fl))
2826 {
a61f4e0c 2827 if (!scm_is_pair (fl))
e5156567 2828 {
bc36d050 2829 if (scm_is_eq (fl, var))
e5156567 2830 {
bc36d050 2831 if (!scm_is_eq (SCM_CAR (vloc), var))
e5156567
DH
2832 goto race;
2833 SCM_SET_CELL_WORD_0 (vloc, SCM_UNPACK (iloc) + SCM_ICDR);
2834 return SCM_CDRLOC (*al);
2835 }
2836 else
2837 break;
2838 }
2839 al = SCM_CDRLOC (*al);
bc36d050 2840 if (scm_is_eq (SCM_CAR (fl), var))
e5156567
DH
2841 {
2842 if (SCM_UNBNDP (SCM_CAR (*al)))
2d0c133f 2843 error_defined_variable (var);
bc36d050 2844 if (!scm_is_eq (SCM_CAR (vloc), var))
e5156567
DH
2845 goto race;
2846 SCM_SETCAR (vloc, iloc);
2847 return SCM_CARLOC (*al);
2848 }
2849 iloc = SCM_PACK (SCM_UNPACK (iloc) + SCM_IDINC);
2850 }
2851 iloc = SCM_PACK ((~SCM_IDSTMSK) & (SCM_UNPACK(iloc) + SCM_IFRINC));
2852 }
2853 {
2854 SCM top_thunk, real_var;
2855 if (SCM_NIMP (env))
2856 {
2857 top_thunk = SCM_CAR (env); /* env now refers to a
2858 top level env thunk */
2859 env = SCM_CDR (env);
2860 }
2861 else
2862 top_thunk = SCM_BOOL_F;
2863 real_var = scm_sym2var (var, top_thunk, SCM_BOOL_F);
7888309b 2864 if (scm_is_false (real_var))
e5156567
DH
2865 goto errout;
2866
a61f4e0c 2867 if (!scm_is_null (env) || SCM_UNBNDP (SCM_VARIABLE_REF (real_var)))
e5156567
DH
2868 {
2869 errout:
2870 if (check)
2871 {
a61f4e0c 2872 if (scm_is_null (env))
e5156567
DH
2873 error_unbound_variable (var);
2874 else
2875 scm_misc_error (NULL, "Damaged environment: ~S",
2876 scm_list_1 (var));
2877 }
2878 else
2879 {
2880 /* A variable could not be found, but we shall
2881 not throw an error. */
2882 static SCM undef_object = SCM_UNDEFINED;
2883 return &undef_object;
2884 }
2885 }
2886
bc36d050 2887 if (!scm_is_eq (SCM_CAR (vloc), var))
e5156567
DH
2888 {
2889 /* Some other thread has changed the very cell we are working
2890 on. In effect, it must have done our job or messed it up
2891 completely. */
2892 race:
2893 var = SCM_CAR (vloc);
2894 if (SCM_VARIABLEP (var))
2895 return SCM_VARIABLE_LOC (var);
2896 if (SCM_ILOCP (var))
2897 return scm_ilookup (var, genv);
2898 /* We can't cope with anything else than variables and ilocs. When
2899 a special form has been memoized (i.e. `let' into `#@let') we
2900 return NULL and expect the calling function to do the right
2901 thing. For the evaluator, this means going back and redoing
2902 the dispatch on the car of the form. */
2903 return NULL;
2904 }
2905
2906 SCM_SETCAR (vloc, real_var);
2907 return SCM_VARIABLE_LOC (real_var);
2908 }
2909}
2910
2911SCM *
2912scm_lookupcar (SCM vloc, SCM genv, int check)
2913{
2914 SCM *loc = scm_lookupcar1 (vloc, genv, check);
2915 if (loc == NULL)
2916 abort ();
2917 return loc;
2918}
2919
2920
36245b66
DH
2921/* During execution, look up a symbol in the top level of the given local
2922 * environment and return the corresponding variable object. If no binding
2923 * for the symbol can be found, an 'Unbound variable' error is signalled. */
2924static SCM
2925lazy_memoize_variable (const SCM symbol, const SCM environment)
2926{
2927 const SCM top_level = scm_env_top_level (environment);
2928 const SCM variable = scm_sym2var (symbol, top_level, SCM_BOOL_F);
2929
7888309b 2930 if (scm_is_false (variable))
36245b66
DH
2931 error_unbound_variable (symbol);
2932 else
2933 return variable;
2934}
2935
2936
62360b89
DH
2937SCM
2938scm_eval_car (SCM pair, SCM env)
2939{
385609b9 2940 return SCM_I_XEVALCAR (pair, env);
62360b89
DH
2941}
2942
2943
6dbd0af5 2944SCM
6e8d25a6 2945scm_eval_args (SCM l, SCM env, SCM proc)
6dbd0af5 2946{
680ed4a8 2947 SCM results = SCM_EOL, *lloc = &results, res;
a61f4e0c 2948 while (scm_is_pair (l))
6dbd0af5 2949 {
680ed4a8 2950 res = EVALCAR (l, env);
904a077d 2951
8ea46249 2952 *lloc = scm_list_1 (res);
a23afe53 2953 lloc = SCM_CDRLOC (*lloc);
6dbd0af5
MD
2954 l = SCM_CDR (l);
2955 }
a61f4e0c 2956 if (!scm_is_null (l))
904a077d 2957 scm_wrong_num_args (proc);
680ed4a8 2958 return results;
6dbd0af5 2959}
c4ac4d88 2960
d0b07b5d 2961
9de33deb
MD
2962SCM
2963scm_eval_body (SCM code, SCM env)
2964{
2965 SCM next;
434f2f7a 2966
9de33deb 2967 again:
01f11e02 2968 next = SCM_CDR (code);
a61f4e0c 2969 while (!scm_is_null (next))
9de33deb
MD
2970 {
2971 if (SCM_IMP (SCM_CAR (code)))
2972 {
2973 if (SCM_ISYMP (SCM_CAR (code)))
2974 {
cce0e9c8 2975 scm_dynwind_begin (0);
2b829bbb 2976 scm_i_dynwind_pthread_mutex_lock (&source_mutex);
9bc4701c
MD
2977 /* check for race condition */
2978 if (SCM_ISYMP (SCM_CAR (code)))
9d4bf6d3 2979 m_expand_body (code, env);
cce0e9c8 2980 scm_dynwind_end ();
9de33deb
MD
2981 goto again;
2982 }
2983 }
2984 else
385609b9 2985 SCM_I_XEVAL (SCM_CAR (code), env);
9de33deb 2986 code = next;
01f11e02 2987 next = SCM_CDR (code);
9de33deb 2988 }
385609b9 2989 return SCM_I_XEVALCAR (code, env);
9de33deb
MD
2990}
2991
0f2d19dd
JB
2992#endif /* !DEVAL */
2993
6dbd0af5
MD
2994
2995/* SECTION: This code is specific for the debugging support. One
2996 * branch is read when DEVAL isn't defined, the other when DEVAL is
2997 * defined.
2998 */
2999
3000#ifndef DEVAL
3001
3002#define SCM_APPLY scm_apply
3003#define PREP_APPLY(proc, args)
3004#define ENTER_APPLY
ddea3325 3005#define RETURN(x) do { return x; } while (0)
b7ff98dd
MD
3006#ifdef STACK_CHECKING
3007#ifndef NO_CEVAL_STACK_CHECKING
3008#define EVAL_STACK_CHECKING
3009#endif
6dbd0af5
MD
3010#endif
3011
3012#else /* !DEVAL */
3013
434f2f7a
DH
3014#undef CEVAL
3015#define CEVAL deval /* Substitute all uses of ceval */
3016
0f2d19dd
JB
3017#undef SCM_APPLY
3018#define SCM_APPLY scm_dapply
434f2f7a 3019
6dbd0af5
MD
3020#undef PREP_APPLY
3021#define PREP_APPLY(p, l) \
3022{ ++debug.info; debug.info->a.proc = p; debug.info->a.args = l; }
434f2f7a 3023
6dbd0af5
MD
3024#undef ENTER_APPLY
3025#define ENTER_APPLY \
d3a6bc94 3026do { \
b7ff98dd 3027 SCM_SET_ARGSREADY (debug);\
5132eef0 3028 if (scm_check_apply_p && SCM_TRAPS_P)\
b0763985 3029 if (SCM_APPLY_FRAME_P || (SCM_TRACE_P && SCM_PROCTRACEP (proc)))\
6dbd0af5 3030 {\
7888309b 3031 SCM tmp, tail = scm_from_bool(SCM_TRACED_FRAME_P (debug)); \
c6a4fbce 3032 SCM_SET_TRACED_FRAME (debug); \
d95c0b76 3033 SCM_TRAPS_P = 0;\
7c9c0169
NJ
3034 tmp = scm_make_debugobj (&debug);\
3035 scm_call_3 (SCM_APPLY_FRAME_HDLR, scm_sym_apply_frame, tmp, tail);\
d95c0b76 3036 SCM_TRAPS_P = 1;\
6dbd0af5 3037 }\
d3a6bc94 3038} while (0)
434f2f7a 3039
0f2d19dd 3040#undef RETURN
ddea3325 3041#define RETURN(e) do { proc = (e); goto exit; } while (0)
434f2f7a 3042
b7ff98dd
MD
3043#ifdef STACK_CHECKING
3044#ifndef EVAL_STACK_CHECKING
3045#define EVAL_STACK_CHECKING
3046#endif
6dbd0af5
MD
3047#endif
3048
0f2d19dd 3049
434f2f7a
DH
3050/* scm_last_debug_frame contains a pointer to the last debugging information
3051 * stack frame. It is accessed very often from the debugging evaluator, so it
3052 * should probably not be indirectly addressed. Better to save and restore it
3053 * from the current root at any stack swaps.
6dbd0af5
MD
3054 */
3055
6dbd0af5
MD
3056/* scm_debug_eframe_size is the number of slots available for pseudo
3057 * stack frames at each real stack frame.
3058 */
3059
c014a02e 3060long scm_debug_eframe_size;
6dbd0af5 3061
434f2f7a
DH
3062int scm_debug_mode_p;
3063int scm_check_entry_p;
3064int scm_check_apply_p;
3065int scm_check_exit_p;
72f19c26 3066int scm_check_memoize_p;
6dbd0af5 3067
c014a02e 3068long scm_eval_stack;
a74145b8 3069
92c2555f 3070scm_t_option scm_eval_opts[] = {
62560650
HWN
3071 { SCM_OPTION_INTEGER, "stack", 22000, "Size of thread stacks (in machine words)." },
3072 { 0 }
33b97402
MD
3073};
3074
92c2555f 3075scm_t_option scm_debug_opts[] = {
b7ff98dd 3076 { SCM_OPTION_BOOLEAN, "cheap", 1,
7c9c0169 3077 "*This option is now obsolete. Setting it has no effect." },
b7ff98dd
MD
3078 { SCM_OPTION_BOOLEAN, "breakpoints", 0, "*Check for breakpoints." },
3079 { SCM_OPTION_BOOLEAN, "trace", 0, "*Trace mode." },
3080 { SCM_OPTION_BOOLEAN, "procnames", 1,
3081 "Record procedure names at definition." },
3082 { SCM_OPTION_BOOLEAN, "backwards", 0,
3083 "Display backtrace in anti-chronological order." },
274dc5fd 3084 { SCM_OPTION_INTEGER, "width", 79, "Maximal width of backtrace." },
4e646a03
MD
3085 { SCM_OPTION_INTEGER, "indent", 10, "Maximal indentation in backtrace." },
3086 { SCM_OPTION_INTEGER, "frames", 3,
b7ff98dd 3087 "Maximum number of tail-recursive frames in backtrace." },
4e646a03
MD
3088 { SCM_OPTION_INTEGER, "maxdepth", 1000,
3089 "Maximal number of stored backtrace frames." },
3090 { SCM_OPTION_INTEGER, "depth", 20, "Maximal length of printed backtrace." },
11f77bfc
MD
3091 { SCM_OPTION_BOOLEAN, "backtrace", 0, "Show backtrace on error." },
3092 { SCM_OPTION_BOOLEAN, "debug", 0, "Use the debugging evaluator." },
863e833b 3093 { SCM_OPTION_INTEGER, "stack", 20000, "Stack size limit (measured in words; 0 = no check)." },
65bc1f7a 3094 { 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."},
62560650
HWN
3095 { SCM_OPTION_BOOLEAN, "warn-deprecated", 0, "Warn when deprecated features are used." },
3096 { 0 },
6dbd0af5
MD
3097};
3098
62560650 3099
72f19c26
HWN
3100/*
3101 this ordering is awkward and illogical, but we maintain it for
3102 compatibility. --hwn
3103*/
92c2555f 3104scm_t_option scm_evaluator_trap_table[] = {
b6d75948 3105 { SCM_OPTION_BOOLEAN, "traps", 0, "Enable evaluator traps." },
b7ff98dd 3106 { SCM_OPTION_BOOLEAN, "enter-frame", 0, "Trap when eval enters new frame." },
62560650 3107 { SCM_OPTION_BOOLEAN, "apply-frame", 0, "Trap when entering apply." },
62560650 3108 { SCM_OPTION_BOOLEAN, "exit-frame", 0, "Trap when exiting eval or apply." },
72f19c26
HWN
3109 { SCM_OPTION_SCM, "enter-frame-handler", (unsigned long)SCM_BOOL_F, "Handler for enter-frame traps." },
3110 { SCM_OPTION_SCM, "apply-frame-handler", (unsigned long)SCM_BOOL_F, "Handler for apply-frame traps." },
62560650 3111 { SCM_OPTION_SCM, "exit-frame-handler", (unsigned long)SCM_BOOL_F, "Handler for exit-frame traps." },
72f19c26
HWN
3112 { SCM_OPTION_BOOLEAN, "memoize-symbol", 0, "Trap when memoizing a symbol." },
3113 { SCM_OPTION_SCM, "memoize-symbol-handler", (unsigned long)SCM_BOOL_F, "The handler for memoization." },
62560650 3114 { 0 }
6dbd0af5
MD
3115};
3116
72f19c26 3117
a1ec6916 3118SCM_DEFINE (scm_eval_options_interface, "eval-options-interface", 0, 1, 0,
1bbd0b84 3119 (SCM setting),
b3f26b14
MG
3120 "Option interface for the evaluation options. Instead of using\n"
3121 "this procedure directly, use the procedures @code{eval-enable},\n"
3939e9df 3122 "@code{eval-disable}, @code{eval-set!} and @code{eval-options}.")
1bbd0b84 3123#define FUNC_NAME s_scm_eval_options_interface
33b97402
MD
3124{
3125 SCM ans;
876099d4 3126
661ae7ab
MV
3127 scm_dynwind_begin (0);
3128 scm_dynwind_critical_section (SCM_BOOL_F);
33b97402
MD
3129 ans = scm_options (setting,
3130 scm_eval_opts,
1bbd0b84 3131 FUNC_NAME);
a74145b8 3132 scm_eval_stack = SCM_EVAL_STACK * sizeof (void *);
661ae7ab 3133 scm_dynwind_end ();
876099d4 3134
33b97402
MD
3135 return ans;
3136}
1bbd0b84 3137#undef FUNC_NAME
33b97402 3138
d0b07b5d 3139
a1ec6916 3140SCM_DEFINE (scm_evaluator_traps, "evaluator-traps-interface", 0, 1, 0,
1bbd0b84 3141 (SCM setting),
b3f26b14 3142 "Option interface for the evaluator trap options.")
1bbd0b84 3143#define FUNC_NAME s_scm_evaluator_traps
33b97402
MD
3144{
3145 SCM ans;
72f19c26
HWN
3146
3147
3148 scm_options_try (setting,
3149 scm_evaluator_trap_table,
3150 FUNC_NAME, 1);
9de87eea 3151 SCM_CRITICAL_SECTION_START;
33b97402
MD
3152 ans = scm_options (setting,
3153 scm_evaluator_trap_table,
1bbd0b84 3154 FUNC_NAME);
72f19c26 3155
2b0fb0a5 3156 /* njrev: same again. */
33b97402 3157 SCM_RESET_DEBUG_MODE;
9de87eea 3158 SCM_CRITICAL_SECTION_END;
33b97402
MD
3159 return ans;
3160}
1bbd0b84 3161#undef FUNC_NAME
33b97402 3162
d0b07b5d 3163
24933780 3164static SCM
a392ee15 3165deval_args (SCM l, SCM env, SCM proc, SCM *lloc)
0f2d19dd 3166{
b1cb24ff 3167 SCM *results = lloc;
a61f4e0c 3168 while (scm_is_pair (l))
0f2d19dd 3169 {
b1cb24ff 3170 const SCM res = EVALCAR (l, env);
904a077d 3171
8ea46249 3172 *lloc = scm_list_1 (res);
a23afe53 3173 lloc = SCM_CDRLOC (*lloc);
0f2d19dd
JB
3174 l = SCM_CDR (l);
3175 }
a61f4e0c 3176 if (!scm_is_null (l))
904a077d 3177 scm_wrong_num_args (proc);
680ed4a8 3178 return *results;
0f2d19dd
JB
3179}
3180
5defc05d
NJ
3181static void
3182eval_letrec_inits (SCM env, SCM init_forms, SCM **init_values_eol)
3183{
3184 SCM argv[10];
3185 int i = 0, imax = sizeof (argv) / sizeof (SCM);
3186
3187 while (!scm_is_null (init_forms))
3188 {
3189 if (imax == i)
3190 {
3191 eval_letrec_inits (env, init_forms, init_values_eol);
3192 break;
3193 }
3194 argv[i++] = EVALCAR (init_forms, env);
3195 init_forms = SCM_CDR (init_forms);
3196 }
3197
3198 for (i--; i >= 0; i--)
3199 {
3200 **init_values_eol = scm_list_1 (argv[i]);
3201 *init_values_eol = SCM_CDRLOC (**init_values_eol);
3202 }
3203}
3204
6dbd0af5
MD
3205#endif /* !DEVAL */
3206
3207
a392ee15 3208/* SECTION: This code is compiled twice.
6dbd0af5
MD
3209 */
3210
a392ee15 3211
d9d39d76 3212/* Update the toplevel environment frame ENV so that it refers to the
a392ee15 3213 * current module. */
d9d39d76
MV
3214#define UPDATE_TOPLEVEL_ENV(env) \
3215 do { \
3216 SCM p = scm_current_module_lookup_closure (); \
d0b07b5d 3217 if (p != SCM_CAR (env)) \
d9d39d76
MV
3218 env = scm_top_level_env (p); \
3219 } while (0)
3220
6dbd0af5 3221
6f81708a 3222#define SCM_VALIDATE_NON_EMPTY_COMBINATION(x) \
bc36d050 3223 ASSERT_SYNTAX (!scm_is_eq ((x), SCM_EOL), s_empty_combination, x)
6f81708a
DH
3224
3225
a392ee15
DH
3226/* This is the evaluator. Like any real monster, it has three heads:
3227 *
434f2f7a
DH
3228 * ceval is the non-debugging evaluator, deval is the debugging version. Both
3229 * are implemented using a common code base, using the following mechanism:
3230 * CEVAL is a macro, which is either defined to ceval or deval. Thus, there
3231 * is no function CEVAL, but the code for CEVAL actually compiles to either
3232 * ceval or deval. When CEVAL is defined to ceval, it is known that the macro
3233 * DEVAL is not defined. When CEVAL is defined to deval, then the macro DEVAL
3234 * is known to be defined. Thus, in CEVAL parts for the debugging evaluator
a392ee15
DH
3235 * are enclosed within #ifdef DEVAL ... #endif.
3236 *
434f2f7a
DH
3237 * All three (ceval, deval and their common implementation CEVAL) take two
3238 * input parameters, x and env: x is a single expression to be evalutated.
3239 * env is the environment in which bindings are searched.
a392ee15 3240 *
434f2f7a
DH
3241 * x is known to be a pair. Since x is a single expression, it is necessarily
3242 * in a tail position. If x is just a call to another function like in the
3243 * expression (foo exp1 exp2 ...), the realization of that call therefore
3244 * _must_not_ increase stack usage (the evaluation of exp1, exp2 etc.,
3245 * however, may do so). This is realized by making extensive use of 'goto'
3246 * statements within the evaluator: The gotos replace recursive calls to
3247 * CEVAL, thus re-using the same stack frame that CEVAL was already using.
3248 * If, however, x represents some form that requires to evaluate a sequence of
3249 * expressions like (begin exp1 exp2 ...), then recursive calls to CEVAL are
3250 * performed for all but the last expression of that sequence. */
6dbd0af5 3251
434f2f7a
DH
3252static SCM
3253CEVAL (SCM x, SCM env)
0f2d19dd 3254{
42030fb2 3255 SCM proc, arg1;
6dbd0af5 3256#ifdef DEVAL
92c2555f
MV
3257 scm_t_debug_frame debug;
3258 scm_t_debug_info *debug_info_end;
9de87eea 3259 debug.prev = scm_i_last_debug_frame ();
020c890c 3260 debug.status = 0;
04b6c081 3261 /*
92c2555f 3262 * The debug.vect contains twice as much scm_t_debug_info frames as the
04b6c081
MD
3263 * user has specified with (debug-set! frames <n>).
3264 *
3265 * Even frames are eval frames, odd frames are apply frames.
3266 */
92c2555f 3267 debug.vect = (scm_t_debug_info *) alloca (scm_debug_eframe_size
a392ee15 3268 * sizeof (scm_t_debug_info));
c0ab1b8d
JB
3269 debug.info = debug.vect;
3270 debug_info_end = debug.vect + scm_debug_eframe_size;
9de87eea 3271 scm_i_set_last_debug_frame (&debug);
6dbd0af5 3272#endif
b7ff98dd 3273#ifdef EVAL_STACK_CHECKING
79f55b7c 3274 if (scm_stack_checking_enabled_p && SCM_STACK_OVERFLOW_P (&proc))
6dbd0af5 3275 {
b7ff98dd 3276#ifdef DEVAL
6dbd0af5
MD
3277 debug.info->e.exp = x;
3278 debug.info->e.env = env;
b7ff98dd 3279#endif
6dbd0af5
MD
3280 scm_report_stack_overflow ();
3281 }
3282#endif
6a0f6ff3 3283
6dbd0af5
MD
3284#ifdef DEVAL
3285 goto start;
3286#endif
6a0f6ff3 3287
6dbd0af5
MD
3288loop:
3289#ifdef DEVAL
b7ff98dd
MD
3290 SCM_CLEAR_ARGSREADY (debug);
3291 if (SCM_OVERFLOWP (debug))
6dbd0af5 3292 --debug.info;
04b6c081
MD
3293 /*
3294 * In theory, this should be the only place where it is necessary to
3295 * check for space in debug.vect since both eval frames and
3296 * available space are even.
3297 *
3298 * For this to be the case, however, it is necessary that primitive
3299 * special forms which jump back to `loop', `begin' or some similar
680516ba 3300 * label call PREP_APPLY.
04b6c081 3301 */
c0ab1b8d 3302 else if (++debug.info >= debug_info_end)
6dbd0af5 3303 {
b7ff98dd 3304 SCM_SET_OVERFLOW (debug);
6dbd0af5
MD
3305 debug.info -= 2;
3306 }
6a0f6ff3 3307
6dbd0af5
MD
3308start:
3309 debug.info->e.exp = x;
3310 debug.info->e.env = env;
5132eef0
DH
3311 if (scm_check_entry_p && SCM_TRAPS_P)
3312 {
bc76d628
DH
3313 if (SCM_ENTER_FRAME_P
3314 || (SCM_BREAKPOINTS_P && scm_c_source_property_breakpoint_p (x)))
5132eef0 3315 {
bc76d628 3316 SCM stackrep;
7888309b 3317 SCM tail = scm_from_bool (SCM_TAILRECP (debug));
5132eef0 3318 SCM_SET_TAILREC (debug);
7c9c0169 3319 stackrep = scm_make_debugobj (&debug);
5132eef0 3320 SCM_TRAPS_P = 0;
7c9c0169
NJ
3321 stackrep = scm_call_4 (SCM_ENTER_FRAME_HDLR,
3322 scm_sym_enter_frame,
3323 stackrep,
3324 tail,
3325 unmemoize_expression (x, env));
5132eef0 3326 SCM_TRAPS_P = 1;
7c9c0169
NJ
3327 if (scm_is_pair (stackrep) &&
3328 scm_is_eq (SCM_CAR (stackrep), sym_instead))
3329 {
3330 /* This gives the possibility for the debugger to modify
3331 the source expression before evaluation. */
3332 x = SCM_CDR (stackrep);
3333 if (SCM_IMP (x))
3334 RETURN (x);
3335 }
5132eef0
DH
3336 }
3337 }
6dbd0af5 3338#endif
f8769b1d 3339dispatch:
9cb5124f 3340 SCM_TICK;
dec40cd2 3341 if (SCM_ISYMP (SCM_CAR (x)))
0f2d19dd 3342 {
7e6e6b37 3343 switch (ISYMNUM (SCM_CAR (x)))
dec40cd2 3344 {
7e6e6b37 3345 case (ISYMNUM (SCM_IM_AND)):
dec40cd2 3346 x = SCM_CDR (x);
a61f4e0c 3347 while (!scm_is_null (SCM_CDR (x)))
dec40cd2
DH
3348 {
3349 SCM test_result = EVALCAR (x, env);
7888309b 3350 if (scm_is_false (test_result) || SCM_NILP (test_result))
dec40cd2
DH
3351 RETURN (SCM_BOOL_F);
3352 else
3353 x = SCM_CDR (x);
3354 }
3355 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
3356 goto carloop;
0f2d19dd 3357
7e6e6b37 3358 case (ISYMNUM (SCM_IM_BEGIN)):
dec40cd2 3359 x = SCM_CDR (x);
a61f4e0c 3360 if (scm_is_null (x))
dec40cd2 3361 RETURN (SCM_UNSPECIFIED);
b8113bc8 3362
dec40cd2 3363 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
0f2d19dd 3364
dec40cd2
DH
3365 begin:
3366 /* If we are on toplevel with a lookup closure, we need to sync
3367 with the current module. */
a61f4e0c 3368 if (scm_is_pair (env) && !scm_is_pair (SCM_CAR (env)))
dec40cd2
DH
3369 {
3370 UPDATE_TOPLEVEL_ENV (env);
a61f4e0c 3371 while (!scm_is_null (SCM_CDR (x)))
dec40cd2
DH
3372 {
3373 EVALCAR (x, env);
3374 UPDATE_TOPLEVEL_ENV (env);
3375 x = SCM_CDR (x);
3376 }
3377 goto carloop;
3378 }
3379 else
3380 goto nontoplevel_begin;
5280aaca 3381
dec40cd2 3382 nontoplevel_begin:
a61f4e0c 3383 while (!scm_is_null (SCM_CDR (x)))
dec40cd2 3384 {
b1cb24ff 3385 const SCM form = SCM_CAR (x);
dec40cd2
DH
3386 if (SCM_IMP (form))
3387 {
3388 if (SCM_ISYMP (form))
3389 {
cce0e9c8 3390 scm_dynwind_begin (0);
2b829bbb 3391 scm_i_dynwind_pthread_mutex_lock (&source_mutex);
dec40cd2
DH
3392 /* check for race condition */
3393 if (SCM_ISYMP (SCM_CAR (x)))
3394 m_expand_body (x, env);
cce0e9c8 3395 scm_dynwind_end ();
dec40cd2
DH
3396 goto nontoplevel_begin;
3397 }
3398 else
3399 SCM_VALIDATE_NON_EMPTY_COMBINATION (form);
3400 }
3401 else
b1cb24ff 3402 (void) EVAL (form, env);
dec40cd2
DH
3403 x = SCM_CDR (x);
3404 }
b1cb24ff 3405
dec40cd2
DH
3406 carloop:
3407 {
3408 /* scm_eval last form in list */
b1cb24ff 3409 const SCM last_form = SCM_CAR (x);
0f2d19dd 3410
a61f4e0c 3411 if (scm_is_pair (last_form))
dec40cd2
DH
3412 {
3413 /* This is by far the most frequent case. */
3414 x = last_form;
3415 goto loop; /* tail recurse */
3416 }
3417 else if (SCM_IMP (last_form))
385609b9 3418 RETURN (SCM_I_EVALIM (last_form, env));
dec40cd2
DH
3419 else if (SCM_VARIABLEP (last_form))
3420 RETURN (SCM_VARIABLE_REF (last_form));
cc95e00a 3421 else if (scm_is_symbol (last_form))
72f19c26 3422 RETURN (*scm_lookupcar (x, env, 1));
dec40cd2
DH
3423 else
3424 RETURN (last_form);
3425 }
0f2d19dd
JB
3426
3427
7e6e6b37 3428 case (ISYMNUM (SCM_IM_CASE)):
dec40cd2
DH
3429 x = SCM_CDR (x);
3430 {
b1cb24ff 3431 const SCM key = EVALCAR (x, env);
dec40cd2 3432 x = SCM_CDR (x);
a61f4e0c 3433 while (!scm_is_null (x))
dec40cd2 3434 {
b1cb24ff 3435 const SCM clause = SCM_CAR (x);
dec40cd2 3436 SCM labels = SCM_CAR (clause);
bc36d050 3437 if (scm_is_eq (labels, SCM_IM_ELSE))
dec40cd2
DH
3438 {
3439 x = SCM_CDR (clause);
3440 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
3441 goto begin;
3442 }
a61f4e0c 3443 while (!scm_is_null (labels))
dec40cd2 3444 {
b1cb24ff 3445 const SCM label = SCM_CAR (labels);
bc36d050 3446 if (scm_is_eq (label, key)
7888309b 3447 || scm_is_true (scm_eqv_p (label, key)))
dec40cd2
DH
3448 {
3449 x = SCM_CDR (clause);
3450 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
3451 goto begin;
3452 }
3453 labels = SCM_CDR (labels);
3454 }
3455 x = SCM_CDR (x);
3456 }
3457 }
3458 RETURN (SCM_UNSPECIFIED);
0f2d19dd
JB
3459
3460
7e6e6b37 3461 case (ISYMNUM (SCM_IM_COND)):
dec40cd2 3462 x = SCM_CDR (x);
a61f4e0c 3463 while (!scm_is_null (x))
dec40cd2 3464 {
b1cb24ff 3465 const SCM clause = SCM_CAR (x);
bc36d050 3466 if (scm_is_eq (SCM_CAR (clause), SCM_IM_ELSE))
dec40cd2
DH
3467 {
3468 x = SCM_CDR (clause);
3469 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
3470 goto begin;
3471 }
3472 else
3473 {
3474 arg1 = EVALCAR (clause, env);
1fe1fc0a
MV
3475 /* SRFI 61 extended cond */
3476 if (!scm_is_null (SCM_CDR (clause))
3477 && !scm_is_null (SCM_CDDR (clause))
3478 && scm_is_eq (SCM_CADDR (clause), SCM_IM_ARROW))
3479 {
3480 SCM xx, guard_result;
3481 if (SCM_VALUESP (arg1))
3482 arg1 = scm_struct_ref (arg1, SCM_INUM0);
3483 else
3484 arg1 = scm_list_1 (arg1);
3485 xx = SCM_CDR (clause);
3486 proc = EVALCAR (xx, env);
3487 guard_result = SCM_APPLY (proc, arg1, SCM_EOL);
3488 if (scm_is_true (guard_result)
3489 && !SCM_NILP (guard_result))
3490 {
3491 proc = SCM_CDDR (xx);
3492 proc = EVALCAR (proc, env);
3493 PREP_APPLY (proc, arg1);
3494 goto apply_proc;
3495 }
3496 }
3497 else if (scm_is_true (arg1) && !SCM_NILP (arg1))
dec40cd2
DH
3498 {
3499 x = SCM_CDR (clause);
a61f4e0c 3500 if (scm_is_null (x))
dec40cd2 3501 RETURN (arg1);
bc36d050 3502 else if (!scm_is_eq (SCM_CAR (x), SCM_IM_ARROW))
dec40cd2
DH
3503 {
3504 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
3505 goto begin;
3506 }
3507 else
3508 {
3509 proc = SCM_CDR (x);
3510 proc = EVALCAR (proc, env);
3511 PREP_APPLY (proc, scm_list_1 (arg1));
3512 ENTER_APPLY;
3513 goto evap1;
3514 }
3515 }
3516 x = SCM_CDR (x);
3517 }
3518 }
3519 RETURN (SCM_UNSPECIFIED);
e5cb71a0 3520
e5cb71a0 3521
7e6e6b37 3522 case (ISYMNUM (SCM_IM_DO)):
dec40cd2
DH
3523 x = SCM_CDR (x);
3524 {
3525 /* Compute the initialization values and the initial environment. */
3526 SCM init_forms = SCM_CAR (x);
3527 SCM init_values = SCM_EOL;
a61f4e0c 3528 while (!scm_is_null (init_forms))
dec40cd2
DH
3529 {
3530 init_values = scm_cons (EVALCAR (init_forms, env), init_values);
3531 init_forms = SCM_CDR (init_forms);
3532 }
3533 x = SCM_CDR (x);
3534 env = SCM_EXTEND_ENV (SCM_CAR (x), init_values, env);
3535 }
3536 x = SCM_CDR (x);
3537 {
3538 SCM test_form = SCM_CAR (x);
3539 SCM body_forms = SCM_CADR (x);
3540 SCM step_forms = SCM_CDDR (x);
e5cb71a0 3541
dec40cd2 3542 SCM test_result = EVALCAR (test_form, env);
e5cb71a0 3543
7888309b 3544 while (scm_is_false (test_result) || SCM_NILP (test_result))
dec40cd2
DH
3545 {
3546 {
3547 /* Evaluate body forms. */
3548 SCM temp_forms;
3549 for (temp_forms = body_forms;
a61f4e0c 3550 !scm_is_null (temp_forms);
dec40cd2
DH
3551 temp_forms = SCM_CDR (temp_forms))
3552 {
3553 SCM form = SCM_CAR (temp_forms);
b1cb24ff
DH
3554 /* Dirk:FIXME: We only need to eval forms that may have
3555 * a side effect here. This is only true for forms that
3556 * start with a pair. All others are just constants.
3557 * Since with the current memoizer 'form' may hold a
3558 * constant, we call EVAL here to handle the constant
3559 * cases. In the long run it would make sense to have
3560 * the macro transformer of 'do' eliminate all forms
3561 * that have no sideeffect. Then instead of EVAL we
3562 * could call CEVAL directly here. */
3563 (void) EVAL (form, env);
dec40cd2
DH
3564 }
3565 }
0f2d19dd 3566
dec40cd2
DH
3567 {
3568 /* Evaluate the step expressions. */
3569 SCM temp_forms;
3570 SCM step_values = SCM_EOL;
3571 for (temp_forms = step_forms;
a61f4e0c 3572 !scm_is_null (temp_forms);
dec40cd2
DH
3573 temp_forms = SCM_CDR (temp_forms))
3574 {
b1cb24ff 3575 const SCM value = EVALCAR (temp_forms, env);
dec40cd2
DH
3576 step_values = scm_cons (value, step_values);
3577 }
3578 env = SCM_EXTEND_ENV (SCM_CAAR (env),
3579 step_values,
3580 SCM_CDR (env));
3581 }
0f2d19dd 3582
dec40cd2
DH
3583 test_result = EVALCAR (test_form, env);
3584 }
3585 }
3586 x = SCM_CDAR (x);
a61f4e0c 3587 if (scm_is_null (x))
dec40cd2
DH
3588 RETURN (SCM_UNSPECIFIED);
3589 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
3590 goto nontoplevel_begin;
0f2d19dd
JB
3591
3592
7e6e6b37 3593 case (ISYMNUM (SCM_IM_IF)):
dec40cd2
DH
3594 x = SCM_CDR (x);
3595 {
3596 SCM test_result = EVALCAR (x, env);
3597 x = SCM_CDR (x); /* then expression */
7888309b 3598 if (scm_is_false (test_result) || SCM_NILP (test_result))
dec40cd2
DH
3599 {
3600 x = SCM_CDR (x); /* else expression */
a61f4e0c 3601 if (scm_is_null (x))
dec40cd2
DH
3602 RETURN (SCM_UNSPECIFIED);
3603 }
3604 }
3605 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
3606 goto carloop;
0f2d19dd
JB
3607
3608
7e6e6b37 3609 case (ISYMNUM (SCM_IM_LET)):
dec40cd2
DH
3610 x = SCM_CDR (x);
3611 {
3612 SCM init_forms = SCM_CADR (x);
3613 SCM init_values = SCM_EOL;
3614 do
3615 {
3616 init_values = scm_cons (EVALCAR (init_forms, env), init_values);
3617 init_forms = SCM_CDR (init_forms);
3618 }
a61f4e0c 3619 while (!scm_is_null (init_forms));
dec40cd2
DH
3620 env = SCM_EXTEND_ENV (SCM_CAR (x), init_values, env);
3621 }
3622 x = SCM_CDDR (x);
3623 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
3624 goto nontoplevel_begin;
0f2d19dd
JB
3625
3626
7e6e6b37 3627 case (ISYMNUM (SCM_IM_LETREC)):
dec40cd2
DH
3628 x = SCM_CDR (x);
3629 env = SCM_EXTEND_ENV (SCM_CAR (x), undefineds, env);
3630 x = SCM_CDR (x);
3631 {
3632 SCM init_forms = SCM_CAR (x);
5defc05d
NJ
3633 SCM init_values = scm_list_1 (SCM_BOOL_T);
3634 SCM *init_values_eol = SCM_CDRLOC (init_values);
3635 eval_letrec_inits (env, init_forms, &init_values_eol);
3636 SCM_SETCDR (SCM_CAR (env), SCM_CDR (init_values));
dec40cd2
DH
3637 }
3638 x = SCM_CDR (x);
3639 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
3640 goto nontoplevel_begin;
0f2d19dd 3641
302c12b4 3642
7e6e6b37 3643 case (ISYMNUM (SCM_IM_LETSTAR)):
dec40cd2
DH
3644 x = SCM_CDR (x);
3645 {
3646 SCM bindings = SCM_CAR (x);
a61f4e0c 3647 if (!scm_is_null (bindings))
dec40cd2
DH
3648 {
3649 do
3650 {
3651 SCM name = SCM_CAR (bindings);
3652 SCM init = SCM_CDR (bindings);
3653 env = SCM_EXTEND_ENV (name, EVALCAR (init, env), env);
3654 bindings = SCM_CDR (init);
3655 }
a61f4e0c 3656 while (!scm_is_null (bindings));
dec40cd2
DH
3657 }
3658 }
3659 x = SCM_CDR (x);
3660 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
3661 goto nontoplevel_begin;
0f2d19dd
JB
3662
3663
7e6e6b37 3664 case (ISYMNUM (SCM_IM_OR)):
dec40cd2 3665 x = SCM_CDR (x);
a61f4e0c 3666 while (!scm_is_null (SCM_CDR (x)))
dec40cd2
DH
3667 {
3668 SCM val = EVALCAR (x, env);
7888309b 3669 if (scm_is_true (val) && !SCM_NILP (val))
dec40cd2
DH
3670 RETURN (val);
3671 else
3672 x = SCM_CDR (x);
3673 }
3674 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
3675 goto carloop;
0f2d19dd
JB
3676
3677
7e6e6b37 3678 case (ISYMNUM (SCM_IM_LAMBDA)):
dec40cd2 3679 RETURN (scm_closure (SCM_CDR (x), env));
0f2d19dd
JB
3680
3681
7e6e6b37 3682 case (ISYMNUM (SCM_IM_QUOTE)):
e7313a9d 3683 RETURN (SCM_CDR (x));
0f2d19dd
JB
3684
3685
7e6e6b37 3686 case (ISYMNUM (SCM_IM_SET_X)):
dec40cd2
DH
3687 x = SCM_CDR (x);
3688 {
3689 SCM *location;
3690 SCM variable = SCM_CAR (x);
3691 if (SCM_ILOCP (variable))
3692 location = scm_ilookup (variable, env);
3693 else if (SCM_VARIABLEP (variable))
3694 location = SCM_VARIABLE_LOC (variable);
36245b66
DH
3695 else
3696 {
cc95e00a 3697 /* (scm_is_symbol (variable)) is known to be true */
36245b66
DH
3698 variable = lazy_memoize_variable (variable, env);
3699 SCM_SETCAR (x, variable);
3700 location = SCM_VARIABLE_LOC (variable);
3701 }
dec40cd2
DH
3702 x = SCM_CDR (x);
3703 *location = EVALCAR (x, env);
3704 }
3705 RETURN (SCM_UNSPECIFIED);
3f04400d
DH
3706
3707
7e6e6b37 3708 case (ISYMNUM (SCM_IM_APPLY)):
6bff1368 3709 /* Evaluate the procedure to be applied. */
e910e9d2
DH
3710 x = SCM_CDR (x);
3711 proc = EVALCAR (x, env);
3712 PREP_APPLY (proc, SCM_EOL);
6bff1368
DH
3713
3714 /* Evaluate the argument holding the list of arguments */
e910e9d2
DH
3715 x = SCM_CDR (x);
3716 arg1 = EVALCAR (x, env);
9a069bdd
DH
3717
3718 apply_proc:
3719 /* Go here to tail-apply a procedure. PROC is the procedure and
3720 * ARG1 is the list of arguments. PREP_APPLY must have been called
3721 * before jumping to apply_proc. */
0f2d19dd
JB
3722 if (SCM_CLOSUREP (proc))
3723 {
9a069bdd 3724 SCM formals = SCM_CLOSURE_FORMALS (proc);
6dbd0af5 3725#ifdef DEVAL
9a069bdd 3726 debug.info->a.args = arg1;
6dbd0af5 3727#endif
9a069bdd
DH
3728 if (scm_badargsp (formals, arg1))
3729 scm_wrong_num_args (proc);
3730 ENTER_APPLY;
3731 /* Copy argument list */
3732 if (SCM_NULL_OR_NIL_P (arg1))
3733 env = SCM_EXTEND_ENV (formals, SCM_EOL, SCM_ENV (proc));
3734 else
3735 {
3736 SCM args = scm_list_1 (SCM_CAR (arg1));
3737 SCM tail = args;
3738 arg1 = SCM_CDR (arg1);
3739 while (!SCM_NULL_OR_NIL_P (arg1))
3740 {
3741 SCM new_tail = scm_list_1 (SCM_CAR (arg1));
3742 SCM_SETCDR (tail, new_tail);
3743 tail = new_tail;
3744 arg1 = SCM_CDR (arg1);
3745 }
3746 env = SCM_EXTEND_ENV (formals, args, SCM_ENV (proc));
3747 }
3748
3749 x = SCM_CLOSURE_BODY (proc);
3750 goto nontoplevel_begin;
0f2d19dd 3751 }
3f04400d
DH
3752 else
3753 {
e910e9d2
DH
3754 ENTER_APPLY;
3755 RETURN (SCM_APPLY (proc, arg1, SCM_EOL));
3f04400d
DH
3756 }
3757
0f2d19dd 3758
7e6e6b37 3759 case (ISYMNUM (SCM_IM_CONT)):
5f144b10
GH
3760 {
3761 int first;
3762 SCM val = scm_make_continuation (&first);
3763
e050d4f8 3764 if (!first)
5f144b10 3765 RETURN (val);
e050d4f8
DH
3766 else
3767 {
3768 arg1 = val;
3769 proc = SCM_CDR (x);
6bff1368 3770 proc = EVALCAR (proc, env);
e050d4f8
DH
3771 PREP_APPLY (proc, scm_list_1 (arg1));
3772 ENTER_APPLY;
e050d4f8
DH
3773 goto evap1;
3774 }
5f144b10 3775 }
e050d4f8 3776
0f2d19dd 3777
7e6e6b37 3778 case (ISYMNUM (SCM_IM_DELAY)):
ddea3325 3779 RETURN (scm_makprom (scm_closure (SCM_CDR (x), env)));
a570e93a 3780
2f263a6a
MV
3781#if 0
3782 /* See futures.h for a comment why futures are not enabled.
3783 */
7e6e6b37 3784 case (ISYMNUM (SCM_IM_FUTURE)):
28d52ebb 3785 RETURN (scm_i_make_future (scm_closure (SCM_CDR (x), env)));
2f263a6a 3786#endif
28d52ebb 3787
7e6e6b37
DH
3788 /* PLACEHOLDER for case (ISYMNUM (SCM_IM_DISPATCH)): The following
3789 code (type_dispatch) is intended to be the tail of the case
3790 clause for the internal macro SCM_IM_DISPATCH. Please don't
3791 remove it from this location without discussing it with Mikael
c8e1d354
MD
3792 <djurfeldt@nada.kth.se> */
3793
f12745b6
DH
3794 /* The type dispatch code is duplicated below
3795 * (c.f. objects.c:scm_mcache_compute_cmethod) since that
3796 * cuts down execution time for type dispatch to 50%. */
dff98306 3797 type_dispatch: /* inputs: x, arg1 */
f12745b6
DH
3798 /* Type dispatch means to determine from the types of the function
3799 * arguments (i. e. the 'signature' of the call), which method from
3800 * a generic function is to be called. This process of selecting
3801 * the right method takes some time. To speed it up, guile uses
3802 * caching: Together with the macro call to dispatch the signatures
3803 * of some previous calls to that generic function from the same
3804 * place are stored (in the code!) in a cache that we call the
3805 * 'method cache'. This is done since it is likely, that
3806 * consecutive calls to dispatch from that position in the code will
3807 * have the same signature. Thus, the type dispatch works as
3808 * follows: First, determine a hash value from the signature of the
3809 * actual arguments. Second, use this hash value as an index to
3810 * find that same signature in the method cache stored at this
3811 * position in the code. If found, you have also found the
3812 * corresponding method that belongs to that signature. If the
3813 * signature is not found in the method cache, you have to perform a
3814 * full search over all signatures stored with the generic
3815 * function. */
3816 {
3817 unsigned long int specializers;
3818 unsigned long int hash_value;
3819 unsigned long int cache_end_pos;
3820 unsigned long int mask;
3821 SCM method_cache;
3822
3823 {
3824 SCM z = SCM_CDDR (x);
3825 SCM tmp = SCM_CADR (z);
e11e83f3 3826 specializers = scm_to_ulong (SCM_CAR (z));
f12745b6
DH
3827
3828 /* Compute a hash value for searching the method cache. There
3829 * are two variants for computing the hash value, a (rather)
3830 * complicated one, and a simple one. For the complicated one
3831 * explained below, tmp holds a number that is used in the
3832 * computation. */
4057a3e0 3833 if (scm_is_simple_vector (tmp))
e11e83f3
MV
3834 {
3835 /* This method of determining the hash value is much
3836 * simpler: Set the hash value to zero and just perform a
3837 * linear search through the method cache. */
3838 method_cache = tmp;
3839 mask = (unsigned long int) ((long) -1);
3840 hash_value = 0;
4057a3e0 3841 cache_end_pos = SCM_SIMPLE_VECTOR_LENGTH (method_cache);
e11e83f3
MV
3842 }
3843 else
f12745b6
DH
3844 {
3845 /* Use the signature of the actual arguments to determine
3846 * the hash value. This is done as follows: Each class has
3847 * an array of random numbers, that are determined when the
3848 * class is created. The integer 'hashset' is an index into
3849 * that array of random numbers. Now, from all classes that
3850 * are part of the signature of the actual arguments, the
3851 * random numbers at index 'hashset' are taken and summed
3852 * up, giving the hash value. The value of 'hashset' is
3853 * stored at the call to dispatch. This allows to have
3854 * different 'formulas' for calculating the hash value at
3855 * different places where dispatch is called. This allows
3856 * to optimize the hash formula at every individual place
3857 * where dispatch is called, such that hopefully the hash
3858 * value that is computed will directly point to the right
3859 * method in the method cache. */
e11e83f3 3860 unsigned long int hashset = scm_to_ulong (tmp);
f12745b6 3861 unsigned long int counter = specializers + 1;
dff98306 3862 SCM tmp_arg = arg1;
f12745b6 3863 hash_value = 0;
a61f4e0c 3864 while (!scm_is_null (tmp_arg) && counter != 0)
61364ba6 3865 {
f12745b6
DH
3866 SCM class = scm_class_of (SCM_CAR (tmp_arg));
3867 hash_value += SCM_INSTANCE_HASH (class, hashset);
3868 tmp_arg = SCM_CDR (tmp_arg);
3869 counter--;
61364ba6 3870 }
f12745b6
DH
3871 z = SCM_CDDR (z);
3872 method_cache = SCM_CADR (z);
e11e83f3 3873 mask = scm_to_ulong (SCM_CAR (z));
f12745b6
DH
3874 hash_value &= mask;
3875 cache_end_pos = hash_value;
3876 }
f12745b6 3877 }
61364ba6 3878
f12745b6
DH
3879 {
3880 /* Search the method cache for a method with a matching
3881 * signature. Start the search at position 'hash_value'. The
3882 * hashing implementation uses linear probing for conflict
3883 * resolution, that is, if the signature in question is not
3884 * found at the starting index in the hash table, the next table
3885 * entry is tried, and so on, until in the worst case the whole
3886 * cache has been searched, but still the signature has not been
3887 * found. */
3888 SCM z;
3889 do
3890 {
dff98306 3891 SCM args = arg1; /* list of arguments */
4057a3e0 3892 z = SCM_SIMPLE_VECTOR_REF (method_cache, hash_value);
a61f4e0c 3893 while (!scm_is_null (args))
61364ba6
MD
3894 {
3895 /* More arguments than specifiers => CLASS != ENV */
f12745b6 3896 SCM class_of_arg = scm_class_of (SCM_CAR (args));
bc36d050 3897 if (!scm_is_eq (class_of_arg, SCM_CAR (z)))
61364ba6 3898 goto next_method;
f12745b6 3899 args = SCM_CDR (args);
61364ba6
MD
3900 z = SCM_CDR (z);
3901 }
f12745b6 3902 /* Fewer arguments than specifiers => CAR != ENV */
a61f4e0c 3903 if (scm_is_null (SCM_CAR (z)) || scm_is_pair (SCM_CAR (z)))
f12745b6
DH
3904 goto apply_cmethod;
3905 next_method:
3906 hash_value = (hash_value + 1) & mask;
3907 } while (hash_value != cache_end_pos);
3908
3909 /* No appropriate method was found in the cache. */
dff98306 3910 z = scm_memoize_method (x, arg1);
f12745b6 3911
dff98306 3912 apply_cmethod: /* inputs: z, arg1 */
f12745b6
DH
3913 {
3914 SCM formals = SCM_CMETHOD_FORMALS (z);
821f18a4 3915 env = SCM_EXTEND_ENV (formals, arg1, SCM_CMETHOD_ENV (z));
f12745b6
DH
3916 x = SCM_CMETHOD_BODY (z);
3917 goto nontoplevel_begin;
3918 }
3919 }
61364ba6 3920 }
73b64342 3921
1d15ecd3 3922
7e6e6b37 3923 case (ISYMNUM (SCM_IM_SLOT_REF)):
ca4be6ea 3924 x = SCM_CDR (x);
1d15ecd3
DH
3925 {
3926 SCM instance = EVALCAR (x, env);
e11e83f3 3927 unsigned long int slot = SCM_I_INUM (SCM_CDR (x));
1d15ecd3
DH
3928 RETURN (SCM_PACK (SCM_STRUCT_DATA (instance) [slot]));
3929 }
3930
3931
7e6e6b37 3932 case (ISYMNUM (SCM_IM_SLOT_SET_X)):
ca4be6ea 3933 x = SCM_CDR (x);
1d15ecd3
DH
3934 {
3935 SCM instance = EVALCAR (x, env);
e11e83f3 3936 unsigned long int slot = SCM_I_INUM (SCM_CADR (x));
1d15ecd3
DH
3937 SCM value = EVALCAR (SCM_CDDR (x), env);
3938 SCM_STRUCT_DATA (instance) [slot] = SCM_UNPACK (value);
3939 RETURN (SCM_UNSPECIFIED);
3940 }
3941
c96d76b8 3942
22721140 3943#if SCM_ENABLE_ELISP
ca4be6ea 3944
7e6e6b37 3945 case (ISYMNUM (SCM_IM_NIL_COND)):
1d15ecd3
DH
3946 {
3947 SCM test_form = SCM_CDR (x);
3948 x = SCM_CDR (test_form);
3949 while (!SCM_NULL_OR_NIL_P (x))
3950 {
3951 SCM test_result = EVALCAR (test_form, env);
7888309b 3952 if (!(scm_is_false (test_result)
1d15ecd3
DH
3953 || SCM_NULL_OR_NIL_P (test_result)))
3954 {
bc36d050 3955 if (scm_is_eq (SCM_CAR (x), SCM_UNSPECIFIED))
1d15ecd3
DH
3956 RETURN (test_result);
3957 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
3958 goto carloop;
3959 }
3960 else
3961 {
3962 test_form = SCM_CDR (x);
3963 x = SCM_CDR (test_form);
3964 }
3965 }
3966 x = test_form;
3967 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
3968 goto carloop;
3969 }
73b64342 3970
c96d76b8 3971#endif /* SCM_ENABLE_ELISP */
73b64342 3972
7e6e6b37 3973 case (ISYMNUM (SCM_IM_BIND)):
2e171178
MV
3974 {
3975 SCM vars, exps, vals;
73b64342 3976
2e171178
MV
3977 x = SCM_CDR (x);
3978 vars = SCM_CAAR (x);
3979 exps = SCM_CDAR (x);
2e171178 3980 vals = SCM_EOL;
a61f4e0c 3981 while (!scm_is_null (exps))
2e171178
MV
3982 {
3983 vals = scm_cons (EVALCAR (exps, env), vals);
3984 exps = SCM_CDR (exps);
3985 }
3986
3987 scm_swap_bindings (vars, vals);
9de87eea 3988 scm_i_set_dynwinds (scm_acons (vars, vals, scm_i_dynwinds ()));
1d15ecd3
DH
3989
3990 /* Ignore all but the last evaluation result. */
a61f4e0c 3991 for (x = SCM_CDR (x); !scm_is_null (SCM_CDR (x)); x = SCM_CDR (x))
2e171178 3992 {
a61f4e0c 3993 if (scm_is_pair (SCM_CAR (x)))
434f2f7a 3994 CEVAL (SCM_CAR (x), env);
2e171178
MV
3995 }
3996 proc = EVALCAR (x, env);
73b64342 3997
9de87eea 3998 scm_i_set_dynwinds (SCM_CDR (scm_i_dynwinds ()));
2e171178 3999 scm_swap_bindings (vars, vals);
73b64342 4000
ddea3325 4001 RETURN (proc);
2e171178 4002 }
c96d76b8 4003
1d15ecd3 4004
7e6e6b37 4005 case (ISYMNUM (SCM_IM_CALL_WITH_VALUES)):
a513ead3 4006 {
9a069bdd
DH
4007 SCM producer;
4008
4009 x = SCM_CDR (x);
4010 producer = EVALCAR (x, env);
4011 x = SCM_CDR (x);
4012 proc = EVALCAR (x, env); /* proc is the consumer. */
4013 arg1 = SCM_APPLY (producer, SCM_EOL, SCM_EOL);
dff98306 4014 if (SCM_VALUESP (arg1))
82b3e2c6
DH
4015 {
4016 /* The list of arguments is not copied. Rather, it is assumed
4017 * that this has been done by the 'values' procedure. */
4018 arg1 = scm_struct_ref (arg1, SCM_INUM0);
4019 }
a513ead3 4020 else
82b3e2c6
DH
4021 {
4022 arg1 = scm_list_1 (arg1);
4023 }
9a069bdd
DH
4024 PREP_APPLY (proc, arg1);
4025 goto apply_proc;
a513ead3
MV
4026 }
4027
b7798e10 4028
0f2d19dd 4029 default:
dec40cd2 4030 break;
0f2d19dd 4031 }
dec40cd2
DH
4032 }
4033 else
4034 {
434f2f7a
DH
4035 if (SCM_VARIABLEP (SCM_CAR (x)))
4036 proc = SCM_VARIABLE_REF (SCM_CAR (x));
f9986767
DH
4037 else if (SCM_ILOCP (SCM_CAR (x)))
4038 proc = *scm_ilookup (SCM_CAR (x), env);
a61f4e0c 4039 else if (scm_is_pair (SCM_CAR (x)))
434f2f7a 4040 proc = CEVAL (SCM_CAR (x), env);
cc95e00a 4041 else if (scm_is_symbol (SCM_CAR (x)))
0f2d19dd 4042 {
e050d4f8 4043 SCM orig_sym = SCM_CAR (x);
b7798e10
DH
4044 {
4045 SCM *location = scm_lookupcar1 (x, env, 1);
4046 if (location == NULL)
4047 {
4048 /* we have lost the race, start again. */
4049 goto dispatch;
4050 }
4051 proc = *location;
72f19c26
HWN
4052#ifdef DEVAL
4053 if (scm_check_memoize_p && SCM_TRAPS_P)
4054 {
4055 SCM_CLEAR_TRACED_FRAME (debug);
4056 SCM arg1 = scm_make_debugobj (&debug);
4057 SCM retval = SCM_BOOL_T;
4058 SCM_TRAPS_P = 0;
4059 retval = scm_call_4 (SCM_MEMOIZE_HDLR,
4060 scm_sym_memoize_symbol,
4061 arg1, x, env);
4062
4063 /*
4064 do something with retval?
4065 */
4066 SCM_TRAPS_P = 1;
4067 }
4068#endif
b7798e10 4069 }
f8769b1d 4070
22a52da1 4071 if (SCM_MACROP (proc))
0f2d19dd 4072 {
86d31dfe
MV
4073 SCM_SETCAR (x, orig_sym); /* Undo memoizing effect of
4074 lookupcar */
e050d4f8 4075 handle_a_macro: /* inputs: x, env, proc */
368bf056 4076#ifdef DEVAL
7c354052
MD
4077 /* Set a flag during macro expansion so that macro
4078 application frames can be deleted from the backtrace. */
4079 SCM_SET_MACROEXP (debug);
368bf056 4080#endif
dff98306 4081 arg1 = SCM_APPLY (SCM_MACRO_CODE (proc), x,
6bff1368 4082 scm_cons (env, scm_listofnull));
7c354052
MD
4083#ifdef DEVAL
4084 SCM_CLEAR_MACROEXP (debug);
4085#endif
22a52da1 4086 switch (SCM_MACRO_TYPE (proc))
0f2d19dd 4087 {
3b88ed2a 4088 case 3:
0f2d19dd 4089 case 2:
a61f4e0c 4090 if (!scm_is_pair (arg1))
dff98306 4091 arg1 = scm_list_2 (SCM_IM_BEGIN, arg1);
e7313a9d 4092
bc36d050
MV
4093 assert (!scm_is_eq (x, SCM_CAR (arg1))
4094 && !scm_is_eq (x, SCM_CDR (arg1)));
e7313a9d 4095
6dbd0af5 4096#ifdef DEVAL
22a52da1 4097 if (!SCM_CLOSUREP (SCM_MACRO_CODE (proc)))
6dbd0af5 4098 {
9de87eea 4099 SCM_CRITICAL_SECTION_START;
dff98306
DH
4100 SCM_SETCAR (x, SCM_CAR (arg1));
4101 SCM_SETCDR (x, SCM_CDR (arg1));
9de87eea 4102 SCM_CRITICAL_SECTION_END;
6dbd0af5
MD
4103 goto dispatch;
4104 }
4105 /* Prevent memoizing of debug info expression. */
6203706f
MD
4106 debug.info->e.exp = scm_cons_source (debug.info->e.exp,
4107 SCM_CAR (x),
4108 SCM_CDR (x));
6dbd0af5 4109#endif
9de87eea 4110 SCM_CRITICAL_SECTION_START;
dff98306
DH
4111 SCM_SETCAR (x, SCM_CAR (arg1));
4112 SCM_SETCDR (x, SCM_CDR (arg1));
9de87eea 4113 SCM_CRITICAL_SECTION_END;
680516ba
DH
4114 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
4115 goto loop;
3063e30a 4116#if SCM_ENABLE_DEPRECATED == 1
0f2d19dd 4117 case 1:
680516ba
DH
4118 x = arg1;
4119 if (SCM_NIMP (x))
4120 {
4121 PREP_APPLY (SCM_UNDEFINED, SCM_EOL);
4122 goto loop;
4123 }
4124 else
4125 RETURN (arg1);
3063e30a 4126#endif
0f2d19dd 4127 case 0:
dff98306 4128 RETURN (arg1);
0f2d19dd
JB
4129 }
4130 }
4131 }
4132 else
72f19c26 4133 proc = SCM_CAR (x);
bd987b8e 4134
ddd8f927 4135 if (SCM_MACROP (proc))
0f2d19dd 4136 goto handle_a_macro;
0f2d19dd
JB
4137 }
4138
4139
dec40cd2
DH
4140 /* When reaching this part of the code, the following is granted: Variable x
4141 * holds the first pair of an expression of the form (<function> arg ...).
4142 * Variable proc holds the object that resulted from the evaluation of
4143 * <function>. In the following, the arguments (if any) will be evaluated,
4144 * and proc will be applied to them. If proc does not really hold a
4145 * function object, this will be signalled as an error on the scheme
4146 * level. If the number of arguments does not match the number of arguments
4147 * that are allowed to be passed to proc, also an error on the scheme level
4148 * will be signalled. */
72f19c26 4149
6dbd0af5 4150 PREP_APPLY (proc, SCM_EOL);
a61f4e0c 4151 if (scm_is_null (SCM_CDR (x))) {
6dbd0af5 4152 ENTER_APPLY;
89efbff4 4153 evap0:
ddd8f927 4154 SCM_ASRTGO (!SCM_IMP (proc), badfun);
0f2d19dd
JB
4155 switch (SCM_TYP7 (proc))
4156 { /* no arguments given */
4157 case scm_tc7_subr_0:
4158 RETURN (SCM_SUBRF (proc) ());
4159 case scm_tc7_subr_1o:
4160 RETURN (SCM_SUBRF (proc) (SCM_UNDEFINED));
4161 case scm_tc7_lsubr:
4162 RETURN (SCM_SUBRF (proc) (SCM_EOL));
4163 case scm_tc7_rpsubr:
4164 RETURN (SCM_BOOL_T);
4165 case scm_tc7_asubr:
4166 RETURN (SCM_SUBRF (proc) (SCM_UNDEFINED, SCM_UNDEFINED));
0717dfd8 4167 case scm_tc7_smob:
68b06924 4168 if (!SCM_SMOB_APPLICABLE_P (proc))
0717dfd8 4169 goto badfun;
68b06924 4170 RETURN (SCM_SMOB_APPLY_0 (proc));
0f2d19dd 4171 case scm_tc7_cclo:
dff98306 4172 arg1 = proc;
0f2d19dd 4173 proc = SCM_CCLO_SUBR (proc);
6dbd0af5
MD
4174#ifdef DEVAL
4175 debug.info->a.proc = proc;
dff98306 4176 debug.info->a.args = scm_list_1 (arg1);
6dbd0af5 4177#endif
0f2d19dd 4178 goto evap1;
89efbff4
MD
4179 case scm_tc7_pws:
4180 proc = SCM_PROCEDURE (proc);
4181#ifdef DEVAL
4182 debug.info->a.proc = proc;
4183#endif
002f1a5d
MD
4184 if (!SCM_CLOSUREP (proc))
4185 goto evap0;
ddd8f927 4186 /* fallthrough */
0f2d19dd 4187 case scm_tcs_closures:
ddd8f927
DH
4188 {
4189 const SCM formals = SCM_CLOSURE_FORMALS (proc);
a61f4e0c 4190 if (scm_is_pair (formals))
212e58ed 4191 goto wrongnumargs;
ddd8f927
DH
4192 x = SCM_CLOSURE_BODY (proc);
4193 env = SCM_EXTEND_ENV (formals, SCM_EOL, SCM_ENV (proc));
4194 goto nontoplevel_begin;
4195 }
904a077d 4196 case scm_tcs_struct:
195847fa
MD
4197 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
4198 {
4199 x = SCM_ENTITY_PROCEDURE (proc);
dff98306 4200 arg1 = SCM_EOL;
195847fa
MD
4201 goto type_dispatch;
4202 }
2ca0d207 4203 else if (SCM_I_OPERATORP (proc))
da7f71d7 4204 {
dff98306 4205 arg1 = proc;
195847fa
MD
4206 proc = (SCM_I_ENTITYP (proc)
4207 ? SCM_ENTITY_PROCEDURE (proc)
4208 : SCM_OPERATOR_PROCEDURE (proc));
da7f71d7 4209#ifdef DEVAL
195847fa 4210 debug.info->a.proc = proc;
dff98306 4211 debug.info->a.args = scm_list_1 (arg1);
da7f71d7 4212#endif
ddd8f927 4213 goto evap1;
da7f71d7 4214 }
2ca0d207
DH
4215 else
4216 goto badfun;
0f2d19dd
JB
4217 case scm_tc7_subr_1:
4218 case scm_tc7_subr_2:
4219 case scm_tc7_subr_2o:
14b18ed6 4220 case scm_tc7_dsubr:
0f2d19dd
JB
4221 case scm_tc7_cxr:
4222 case scm_tc7_subr_3:
4223 case scm_tc7_lsubr_2:
212e58ed 4224 wrongnumargs:
f5bf2977 4225 scm_wrong_num_args (proc);
0f2d19dd 4226 default:
ddd8f927
DH
4227 badfun:
4228 scm_misc_error (NULL, "Wrong type to apply: ~S", scm_list_1 (proc));
0f2d19dd 4229 }
6dbd0af5 4230 }
0f2d19dd
JB
4231
4232 /* must handle macros by here */
4233 x = SCM_CDR (x);
a61f4e0c 4234 if (scm_is_pair (x))
dff98306 4235 arg1 = EVALCAR (x, env);
680ed4a8 4236 else
ab1f1094 4237 scm_wrong_num_args (proc);
6dbd0af5 4238#ifdef DEVAL
dff98306 4239 debug.info->a.args = scm_list_1 (arg1);
6dbd0af5 4240#endif
0f2d19dd 4241 x = SCM_CDR (x);
42030fb2
DH
4242 {
4243 SCM arg2;
a61f4e0c 4244 if (scm_is_null (x))
42030fb2
DH
4245 {
4246 ENTER_APPLY;
4247 evap1: /* inputs: proc, arg1 */
ddd8f927 4248 SCM_ASRTGO (!SCM_IMP (proc), badfun);
42030fb2
DH
4249 switch (SCM_TYP7 (proc))
4250 { /* have one argument in arg1 */
4251 case scm_tc7_subr_2o:
4252 RETURN (SCM_SUBRF (proc) (arg1, SCM_UNDEFINED));
4253 case scm_tc7_subr_1:
4254 case scm_tc7_subr_1o:
4255 RETURN (SCM_SUBRF (proc) (arg1));
14b18ed6 4256 case scm_tc7_dsubr:
e11e83f3 4257 if (SCM_I_INUMP (arg1))
14b18ed6 4258 {
d9a67fc4 4259 RETURN (scm_from_double (SCM_DSUBRF (proc) ((double) SCM_I_INUM (arg1))));
14b18ed6
DH
4260 }
4261 else if (SCM_REALP (arg1))
4262 {
d9a67fc4 4263 RETURN (scm_from_double (SCM_DSUBRF (proc) (SCM_REAL_VALUE (arg1))));
14b18ed6
DH
4264 }
4265 else if (SCM_BIGP (arg1))
4266 {
d9a67fc4 4267 RETURN (scm_from_double (SCM_DSUBRF (proc) (scm_i_big2dbl (arg1))));
14b18ed6 4268 }
f92e85f7
MV
4269 else if (SCM_FRACTIONP (arg1))
4270 {
d9a67fc4 4271 RETURN (scm_from_double (SCM_DSUBRF (proc) (scm_i_fraction2double (arg1))));
f92e85f7
MV
4272 }
4273 SCM_WTA_DISPATCH_1 (*SCM_SUBR_GENERIC (proc), arg1,
cc95e00a
MV
4274 SCM_ARG1,
4275 scm_i_symbol_chars (SCM_SNAME (proc)));
42030fb2 4276 case scm_tc7_cxr:
a61f4e0c 4277 RETURN (scm_i_chase_pairs (arg1, (scm_t_bits) SCM_SUBRF (proc)));
42030fb2
DH
4278 case scm_tc7_rpsubr:
4279 RETURN (SCM_BOOL_T);
4280 case scm_tc7_asubr:
4281 RETURN (SCM_SUBRF (proc) (arg1, SCM_UNDEFINED));
4282 case scm_tc7_lsubr:
0f2d19dd 4283#ifdef DEVAL
42030fb2 4284 RETURN (SCM_SUBRF (proc) (debug.info->a.args));
0f2d19dd 4285#else
42030fb2 4286 RETURN (SCM_SUBRF (proc) (scm_list_1 (arg1)));
0f2d19dd 4287#endif
42030fb2
DH
4288 case scm_tc7_smob:
4289 if (!SCM_SMOB_APPLICABLE_P (proc))
4290 goto badfun;
4291 RETURN (SCM_SMOB_APPLY_1 (proc, arg1));
4292 case scm_tc7_cclo:
4293 arg2 = arg1;
4294 arg1 = proc;
4295 proc = SCM_CCLO_SUBR (proc);
6dbd0af5 4296#ifdef DEVAL
42030fb2
DH
4297 debug.info->a.args = scm_cons (arg1, debug.info->a.args);
4298 debug.info->a.proc = proc;
6dbd0af5 4299#endif
42030fb2
DH
4300 goto evap2;
4301 case scm_tc7_pws:
4302 proc = SCM_PROCEDURE (proc);
89efbff4 4303#ifdef DEVAL
42030fb2 4304 debug.info->a.proc = proc;
89efbff4 4305#endif
42030fb2
DH
4306 if (!SCM_CLOSUREP (proc))
4307 goto evap1;
ddd8f927 4308 /* fallthrough */
42030fb2 4309 case scm_tcs_closures:
ddd8f927
DH
4310 {
4311 /* clos1: */
4312 const SCM formals = SCM_CLOSURE_FORMALS (proc);
a61f4e0c
MV
4313 if (scm_is_null (formals)
4314 || (scm_is_pair (formals) && scm_is_pair (SCM_CDR (formals))))
212e58ed 4315 goto wrongnumargs;
ddd8f927 4316 x = SCM_CLOSURE_BODY (proc);
0f2d19dd 4317#ifdef DEVAL
ddd8f927
DH
4318 env = SCM_EXTEND_ENV (formals,
4319 debug.info->a.args,
4320 SCM_ENV (proc));
0f2d19dd 4321#else
ddd8f927
DH
4322 env = SCM_EXTEND_ENV (formals,
4323 scm_list_1 (arg1),
4324 SCM_ENV (proc));
0f2d19dd 4325#endif
ddd8f927
DH
4326 goto nontoplevel_begin;
4327 }
42030fb2
DH
4328 case scm_tcs_struct:
4329 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
4330 {
4331 x = SCM_ENTITY_PROCEDURE (proc);
f3d2630a 4332#ifdef DEVAL
42030fb2 4333 arg1 = debug.info->a.args;
f3d2630a 4334#else
42030fb2 4335 arg1 = scm_list_1 (arg1);
f3d2630a 4336#endif
42030fb2
DH
4337 goto type_dispatch;
4338 }
2ca0d207 4339 else if (SCM_I_OPERATORP (proc))
42030fb2
DH
4340 {
4341 arg2 = arg1;
4342 arg1 = proc;
4343 proc = (SCM_I_ENTITYP (proc)
4344 ? SCM_ENTITY_PROCEDURE (proc)
4345 : SCM_OPERATOR_PROCEDURE (proc));
0c32d76c 4346#ifdef DEVAL
42030fb2
DH
4347 debug.info->a.args = scm_cons (arg1, debug.info->a.args);
4348 debug.info->a.proc = proc;
0c32d76c 4349#endif
ddd8f927 4350 goto evap2;
42030fb2 4351 }
2ca0d207
DH
4352 else
4353 goto badfun;
42030fb2
DH
4354 case scm_tc7_subr_2:
4355 case scm_tc7_subr_0:
4356 case scm_tc7_subr_3:
4357 case scm_tc7_lsubr_2:
ab1f1094 4358 scm_wrong_num_args (proc);
42030fb2
DH
4359 default:
4360 goto badfun;
4361 }
4362 }
a61f4e0c 4363 if (scm_is_pair (x))
42030fb2
DH
4364 arg2 = EVALCAR (x, env);
4365 else
ab1f1094 4366 scm_wrong_num_args (proc);
bd987b8e 4367
42030fb2 4368 { /* have two or more arguments */
6dbd0af5 4369#ifdef DEVAL
42030fb2 4370 debug.info->a.args = scm_list_2 (arg1, arg2);
6dbd0af5 4371#endif
42030fb2 4372 x = SCM_CDR (x);
a61f4e0c 4373 if (scm_is_null (x)) {
42030fb2
DH
4374 ENTER_APPLY;
4375 evap2:
ddd8f927 4376 SCM_ASRTGO (!SCM_IMP (proc), badfun);
42030fb2
DH
4377 switch (SCM_TYP7 (proc))
4378 { /* have two arguments */
4379 case scm_tc7_subr_2:
4380 case scm_tc7_subr_2o:
4381 RETURN (SCM_SUBRF (proc) (arg1, arg2));
4382 case scm_tc7_lsubr:
0f2d19dd 4383#ifdef DEVAL
42030fb2 4384 RETURN (SCM_SUBRF (proc) (debug.info->a.args));
6dbd0af5 4385#else
42030fb2
DH
4386 RETURN (SCM_SUBRF (proc) (scm_list_2 (arg1, arg2)));
4387#endif
4388 case scm_tc7_lsubr_2:
4389 RETURN (SCM_SUBRF (proc) (arg1, arg2, SCM_EOL));
4390 case scm_tc7_rpsubr:
4391 case scm_tc7_asubr:
4392 RETURN (SCM_SUBRF (proc) (arg1, arg2));
4393 case scm_tc7_smob:
4394 if (!SCM_SMOB_APPLICABLE_P (proc))
4395 goto badfun;
4396 RETURN (SCM_SMOB_APPLY_2 (proc, arg1, arg2));
4397 cclon:
4398 case scm_tc7_cclo:
0f2d19dd 4399#ifdef DEVAL
42030fb2
DH
4400 RETURN (SCM_APPLY (SCM_CCLO_SUBR (proc),
4401 scm_cons (proc, debug.info->a.args),
4402 SCM_EOL));
0f2d19dd 4403#else
42030fb2
DH
4404 RETURN (SCM_APPLY (SCM_CCLO_SUBR (proc),
4405 scm_cons2 (proc, arg1,
4406 scm_cons (arg2,
4407 scm_eval_args (x,
4408 env,
4409 proc))),
4410 SCM_EOL));
4411#endif
4412 case scm_tcs_struct:
4413 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
4414 {
4415 x = SCM_ENTITY_PROCEDURE (proc);
4416#ifdef DEVAL
4417 arg1 = debug.info->a.args;
4418#else
4419 arg1 = scm_list_2 (arg1, arg2);
6dbd0af5 4420#endif
42030fb2
DH
4421 goto type_dispatch;
4422 }
2ca0d207 4423 else if (SCM_I_OPERATORP (proc))
42030fb2
DH
4424 {
4425 operatorn:
f3d2630a 4426#ifdef DEVAL
42030fb2
DH
4427 RETURN (SCM_APPLY (SCM_I_ENTITYP (proc)
4428 ? SCM_ENTITY_PROCEDURE (proc)
4429 : SCM_OPERATOR_PROCEDURE (proc),
4430 scm_cons (proc, debug.info->a.args),
4431 SCM_EOL));
f3d2630a 4432#else
42030fb2
DH
4433 RETURN (SCM_APPLY (SCM_I_ENTITYP (proc)
4434 ? SCM_ENTITY_PROCEDURE (proc)
4435 : SCM_OPERATOR_PROCEDURE (proc),
4436 scm_cons2 (proc, arg1,
4437 scm_cons (arg2,
4438 scm_eval_args (x,
4439 env,
4440 proc))),
4441 SCM_EOL));
f3d2630a 4442#endif
42030fb2 4443 }
2ca0d207
DH
4444 else
4445 goto badfun;
42030fb2 4446 case scm_tc7_subr_0:
14b18ed6 4447 case scm_tc7_dsubr:
42030fb2
DH
4448 case scm_tc7_cxr:
4449 case scm_tc7_subr_1o:
4450 case scm_tc7_subr_1:
4451 case scm_tc7_subr_3:
ab1f1094 4452 scm_wrong_num_args (proc);
42030fb2 4453 default:
9b07e212 4454 goto badfun;
42030fb2
DH
4455 case scm_tc7_pws:
4456 proc = SCM_PROCEDURE (proc);
4457#ifdef DEVAL
4458 debug.info->a.proc = proc;
4459#endif
4460 if (!SCM_CLOSUREP (proc))
4461 goto evap2;
ddd8f927 4462 /* fallthrough */
42030fb2 4463 case scm_tcs_closures:
ddd8f927
DH
4464 {
4465 /* clos2: */
4466 const SCM formals = SCM_CLOSURE_FORMALS (proc);
a61f4e0c
MV
4467 if (scm_is_null (formals)
4468 || (scm_is_pair (formals)
4469 && (scm_is_null (SCM_CDR (formals))
4470 || (scm_is_pair (SCM_CDR (formals))
4471 && scm_is_pair (SCM_CDDR (formals))))))
212e58ed 4472 goto wrongnumargs;
0c32d76c 4473#ifdef DEVAL
ddd8f927
DH
4474 env = SCM_EXTEND_ENV (formals,
4475 debug.info->a.args,
4476 SCM_ENV (proc));
195847fa 4477#else
ddd8f927
DH
4478 env = SCM_EXTEND_ENV (formals,
4479 scm_list_2 (arg1, arg2),
4480 SCM_ENV (proc));
195847fa 4481#endif
ddd8f927
DH
4482 x = SCM_CLOSURE_BODY (proc);
4483 goto nontoplevel_begin;
4484 }
42030fb2
DH
4485 }
4486 }
a61f4e0c 4487 if (!scm_is_pair (x))
ab1f1094 4488 scm_wrong_num_args (proc);
42030fb2
DH
4489#ifdef DEVAL
4490 debug.info->a.args = scm_cons2 (arg1, arg2,
4491 deval_args (x, env, proc,
4492 SCM_CDRLOC (SCM_CDR (debug.info->a.args))));
4493#endif
4494 ENTER_APPLY;
4495 evap3:
ddd8f927 4496 SCM_ASRTGO (!SCM_IMP (proc), badfun);
42030fb2
DH
4497 switch (SCM_TYP7 (proc))
4498 { /* have 3 or more arguments */
4499#ifdef DEVAL
6dbd0af5 4500 case scm_tc7_subr_3:
a61f4e0c 4501 if (!scm_is_null (SCM_CDR (x)))
ab1f1094
DH
4502 scm_wrong_num_args (proc);
4503 else
4504 RETURN (SCM_SUBRF (proc) (arg1, arg2,
4505 SCM_CADDR (debug.info->a.args)));
42030fb2
DH
4506 case scm_tc7_asubr:
4507 arg1 = SCM_SUBRF(proc)(arg1, arg2);
4508 arg2 = SCM_CDDR (debug.info->a.args);
4509 do
4510 {
4511 arg1 = SCM_SUBRF(proc)(arg1, SCM_CAR (arg2));
4512 arg2 = SCM_CDR (arg2);
4513 }
4514 while (SCM_NIMP (arg2));
4515 RETURN (arg1);
4516 case scm_tc7_rpsubr:
7888309b 4517 if (scm_is_false (SCM_SUBRF (proc) (arg1, arg2)))
42030fb2
DH
4518 RETURN (SCM_BOOL_F);
4519 arg1 = SCM_CDDR (debug.info->a.args);
4520 do
4521 {
7888309b 4522 if (scm_is_false (SCM_SUBRF (proc) (arg2, SCM_CAR (arg1))))
42030fb2
DH
4523 RETURN (SCM_BOOL_F);
4524 arg2 = SCM_CAR (arg1);
4525 arg1 = SCM_CDR (arg1);
4526 }
4527 while (SCM_NIMP (arg1));
4528 RETURN (SCM_BOOL_T);
4529 case scm_tc7_lsubr_2:
4530 RETURN (SCM_SUBRF (proc) (arg1, arg2,
4531 SCM_CDDR (debug.info->a.args)));
4532 case scm_tc7_lsubr:
4533 RETURN (SCM_SUBRF (proc) (debug.info->a.args));
4534 case scm_tc7_smob:
4535 if (!SCM_SMOB_APPLICABLE_P (proc))
4536 goto badfun;
4537 RETURN (SCM_SMOB_APPLY_3 (proc, arg1, arg2,
4538 SCM_CDDR (debug.info->a.args)));
4539 case scm_tc7_cclo:
4540 goto cclon;
002f1a5d
MD
4541 case scm_tc7_pws:
4542 proc = SCM_PROCEDURE (proc);
002f1a5d 4543 debug.info->a.proc = proc;
002f1a5d 4544 if (!SCM_CLOSUREP (proc))
42030fb2 4545 goto evap3;
ddd8f927 4546 /* fallthrough */
6dbd0af5 4547 case scm_tcs_closures:
ddd8f927
DH
4548 {
4549 const SCM formals = SCM_CLOSURE_FORMALS (proc);
a61f4e0c
MV
4550 if (scm_is_null (formals)
4551 || (scm_is_pair (formals)
4552 && (scm_is_null (SCM_CDR (formals))
4553 || (scm_is_pair (SCM_CDR (formals))
ddd8f927 4554 && scm_badargsp (SCM_CDDR (formals), x)))))
212e58ed 4555 goto wrongnumargs;
ddd8f927
DH
4556 SCM_SET_ARGSREADY (debug);
4557 env = SCM_EXTEND_ENV (formals,
4558 debug.info->a.args,
4559 SCM_ENV (proc));
4560 x = SCM_CLOSURE_BODY (proc);
4561 goto nontoplevel_begin;
4562 }
6dbd0af5 4563#else /* DEVAL */
42030fb2 4564 case scm_tc7_subr_3:
a61f4e0c 4565 if (!scm_is_null (SCM_CDR (x)))
ab1f1094
DH
4566 scm_wrong_num_args (proc);
4567 else
4568 RETURN (SCM_SUBRF (proc) (arg1, arg2, EVALCAR (x, env)));
42030fb2
DH
4569 case scm_tc7_asubr:
4570 arg1 = SCM_SUBRF (proc) (arg1, arg2);
4571 do
4572 {
4573 arg1 = SCM_SUBRF(proc)(arg1, EVALCAR(x, env));
4574 x = SCM_CDR(x);
4575 }
a61f4e0c 4576 while (!scm_is_null (x));
42030fb2
DH
4577 RETURN (arg1);
4578 case scm_tc7_rpsubr:
7888309b 4579 if (scm_is_false (SCM_SUBRF (proc) (arg1, arg2)))
42030fb2
DH
4580 RETURN (SCM_BOOL_F);
4581 do
4582 {
4583 arg1 = EVALCAR (x, env);
7888309b 4584 if (scm_is_false (SCM_SUBRF (proc) (arg2, arg1)))
42030fb2
DH
4585 RETURN (SCM_BOOL_F);
4586 arg2 = arg1;
4587 x = SCM_CDR (x);
4588 }
a61f4e0c 4589 while (!scm_is_null (x));
42030fb2
DH
4590 RETURN (SCM_BOOL_T);
4591 case scm_tc7_lsubr_2:
4592 RETURN (SCM_SUBRF (proc) (arg1, arg2, scm_eval_args (x, env, proc)));
4593 case scm_tc7_lsubr:
4594 RETURN (SCM_SUBRF (proc) (scm_cons2 (arg1,
4595 arg2,
4596 scm_eval_args (x, env, proc))));
4597 case scm_tc7_smob:
4598 if (!SCM_SMOB_APPLICABLE_P (proc))
4599 goto badfun;
4600 RETURN (SCM_SMOB_APPLY_3 (proc, arg1, arg2,
4601 scm_eval_args (x, env, proc)));
4602 case scm_tc7_cclo:
4603 goto cclon;
4604 case scm_tc7_pws:
4605 proc = SCM_PROCEDURE (proc);
4606 if (!SCM_CLOSUREP (proc))
4607 goto evap3;
ddd8f927
DH
4608 /* fallthrough */
4609 case scm_tcs_closures:
da7f71d7 4610 {
ddd8f927 4611 const SCM formals = SCM_CLOSURE_FORMALS (proc);
a61f4e0c
MV
4612 if (scm_is_null (formals)
4613 || (scm_is_pair (formals)
4614 && (scm_is_null (SCM_CDR (formals))
4615 || (scm_is_pair (SCM_CDR (formals))
42030fb2 4616 && scm_badargsp (SCM_CDDR (formals), x)))))
212e58ed 4617 goto wrongnumargs;
ddd8f927
DH
4618 env = SCM_EXTEND_ENV (formals,
4619 scm_cons2 (arg1,
4620 arg2,
4621 scm_eval_args (x, env, proc)),
4622 SCM_ENV (proc));
4623 x = SCM_CLOSURE_BODY (proc);
4624 goto nontoplevel_begin;
da7f71d7 4625 }
0f2d19dd 4626#endif /* DEVAL */
42030fb2
DH
4627 case scm_tcs_struct:
4628 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
4629 {
f3d2630a 4630#ifdef DEVAL
42030fb2 4631 arg1 = debug.info->a.args;
f3d2630a 4632#else
42030fb2 4633 arg1 = scm_cons2 (arg1, arg2, scm_eval_args (x, env, proc));
f3d2630a 4634#endif
42030fb2
DH
4635 x = SCM_ENTITY_PROCEDURE (proc);
4636 goto type_dispatch;
4637 }
2ca0d207 4638 else if (SCM_I_OPERATORP (proc))
42030fb2 4639 goto operatorn;
2ca0d207
DH
4640 else
4641 goto badfun;
42030fb2
DH
4642 case scm_tc7_subr_2:
4643 case scm_tc7_subr_1o:
4644 case scm_tc7_subr_2o:
4645 case scm_tc7_subr_0:
14b18ed6 4646 case scm_tc7_dsubr:
42030fb2
DH
4647 case scm_tc7_cxr:
4648 case scm_tc7_subr_1:
ab1f1094 4649 scm_wrong_num_args (proc);
42030fb2 4650 default:
9b07e212 4651 goto badfun;
42030fb2
DH
4652 }
4653 }
0f2d19dd
JB
4654 }
4655#ifdef DEVAL
6dbd0af5 4656exit:
5132eef0 4657 if (scm_check_exit_p && SCM_TRAPS_P)
b7ff98dd 4658 if (SCM_EXIT_FRAME_P || (SCM_TRACE_P && SCM_TRACED_FRAME_P (debug)))
6dbd0af5 4659 {
b7ff98dd 4660 SCM_CLEAR_TRACED_FRAME (debug);
7c9c0169 4661 arg1 = scm_make_debugobj (&debug);
d95c0b76 4662 SCM_TRAPS_P = 0;
7c9c0169 4663 arg1 = scm_call_3 (SCM_EXIT_FRAME_HDLR, scm_sym_exit_frame, arg1, proc);
d95c0b76 4664 SCM_TRAPS_P = 1;
7c9c0169
NJ
4665 if (scm_is_pair (arg1) && scm_is_eq (SCM_CAR (arg1), sym_instead))
4666 proc = SCM_CDR (arg1);
6dbd0af5 4667 }
9de87eea 4668 scm_i_set_last_debug_frame (debug.prev);
0f2d19dd
JB
4669 return proc;
4670#endif
4671}
4672
6dbd0af5
MD
4673
4674/* SECTION: This code is compiled once.
4675 */
4676
0f2d19dd
JB
4677#ifndef DEVAL
4678
fdc28395 4679\f
d0b07b5d 4680
fdc28395
KN
4681/* Simple procedure calls
4682 */
4683
4684SCM
4685scm_call_0 (SCM proc)
4686{
4687 return scm_apply (proc, SCM_EOL, SCM_EOL);
4688}
4689
4690SCM
4691scm_call_1 (SCM proc, SCM arg1)
4692{
4693 return scm_apply (proc, arg1, scm_listofnull);
4694}
4695
4696SCM
4697scm_call_2 (SCM proc, SCM arg1, SCM arg2)
4698{
4699 return scm_apply (proc, arg1, scm_cons (arg2, scm_listofnull));
4700}
4701
4702SCM
4703scm_call_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3)
4704{
4705 return scm_apply (proc, arg1, scm_cons2 (arg2, arg3, scm_listofnull));
4706}
4707
d95c0b76
NJ
4708SCM
4709scm_call_4 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4)
4710{
4711 return scm_apply (proc, arg1, scm_cons2 (arg2, arg3,
4712 scm_cons (arg4, scm_listofnull)));
4713}
4714
fdc28395
KN
4715/* Simple procedure applies
4716 */
4717
4718SCM
4719scm_apply_0 (SCM proc, SCM args)
4720{
4721 return scm_apply (proc, args, SCM_EOL);
4722}
4723
4724SCM
4725scm_apply_1 (SCM proc, SCM arg1, SCM args)
4726{
4727 return scm_apply (proc, scm_cons (arg1, args), SCM_EOL);
4728}
4729
4730SCM
4731scm_apply_2 (SCM proc, SCM arg1, SCM arg2, SCM args)
4732{
4733 return scm_apply (proc, scm_cons2 (arg1, arg2, args), SCM_EOL);
4734}
4735
4736SCM
4737scm_apply_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM args)
4738{
4739 return scm_apply (proc, scm_cons (arg1, scm_cons2 (arg2, arg3, args)),
4740 SCM_EOL);
4741}
4742
82a2622a 4743/* This code processes the arguments to apply:
b145c172
JB
4744
4745 (apply PROC ARG1 ... ARGS)
4746
82a2622a
JB
4747 Given a list (ARG1 ... ARGS), this function conses the ARG1
4748 ... arguments onto the front of ARGS, and returns the resulting
4749 list. Note that ARGS is a list; thus, the argument to this
4750 function is a list whose last element is a list.
4751
4752 Apply calls this function, and applies PROC to the elements of the
b145c172
JB
4753 result. apply:nconc2last takes care of building the list of
4754 arguments, given (ARG1 ... ARGS).
4755
82a2622a
JB
4756 Rather than do new consing, apply:nconc2last destroys its argument.
4757 On that topic, this code came into my care with the following
4758 beautifully cryptic comment on that topic: "This will only screw
4759 you if you do (scm_apply scm_apply '( ... ))" If you know what
4760 they're referring to, send me a patch to this comment. */
b145c172 4761
3b3b36dd 4762SCM_DEFINE (scm_nconc2last, "apply:nconc2last", 1, 0, 0,
b3f26b14
MG
4763 (SCM lst),
4764 "Given a list (@var{arg1} @dots{} @var{args}), this function\n"
4765 "conses the @var{arg1} @dots{} arguments onto the front of\n"
4766 "@var{args}, and returns the resulting list. Note that\n"
4767 "@var{args} is a list; thus, the argument to this function is\n"
4768 "a list whose last element is a list.\n"
4769 "Note: Rather than do new consing, @code{apply:nconc2last}\n"
4770 "destroys its argument, so use with care.")
1bbd0b84 4771#define FUNC_NAME s_scm_nconc2last
0f2d19dd
JB
4772{
4773 SCM *lloc;
34d19ef6 4774 SCM_VALIDATE_NONEMPTYLIST (1, lst);
0f2d19dd 4775 lloc = &lst;
a61f4e0c 4776 while (!scm_is_null (SCM_CDR (*lloc))) /* Perhaps should be
c96d76b8
NJ
4777 SCM_NULL_OR_NIL_P, but not
4778 needed in 99.99% of cases,
4779 and it could seriously hurt
4780 performance. - Neil */
a23afe53 4781 lloc = SCM_CDRLOC (*lloc);
1bbd0b84 4782 SCM_ASSERT (scm_ilength (SCM_CAR (*lloc)) >= 0, lst, SCM_ARG1, FUNC_NAME);
0f2d19dd
JB
4783 *lloc = SCM_CAR (*lloc);
4784 return lst;
4785}
1bbd0b84 4786#undef FUNC_NAME
0f2d19dd
JB
4787
4788#endif /* !DEVAL */
4789
6dbd0af5
MD
4790
4791/* SECTION: When DEVAL is defined this code yields scm_dapply.
4792 * It is compiled twice.
4793 */
4794
0f2d19dd 4795#if 0
0f2d19dd 4796SCM
6e8d25a6 4797scm_apply (SCM proc, SCM arg1, SCM args)
0f2d19dd
JB
4798{}
4799#endif
4800
4801#if 0
0f2d19dd 4802SCM
6e8d25a6 4803scm_dapply (SCM proc, SCM arg1, SCM args)
d0b07b5d 4804{}
0f2d19dd
JB
4805#endif
4806
1cc91f1b 4807
82a2622a
JB
4808/* Apply a function to a list of arguments.
4809
4810 This function is exported to the Scheme level as taking two
4811 required arguments and a tail argument, as if it were:
4812 (lambda (proc arg1 . args) ...)
4813 Thus, if you just have a list of arguments to pass to a procedure,
4814 pass the list as ARG1, and '() for ARGS. If you have some fixed
4815 args, pass the first as ARG1, then cons any remaining fixed args
4816 onto the front of your argument list, and pass that as ARGS. */
4817
0f2d19dd 4818SCM
1bbd0b84 4819SCM_APPLY (SCM proc, SCM arg1, SCM args)
0f2d19dd 4820{
0f2d19dd 4821#ifdef DEVAL
92c2555f
MV
4822 scm_t_debug_frame debug;
4823 scm_t_debug_info debug_vect_body;
9de87eea 4824 debug.prev = scm_i_last_debug_frame ();
b7ff98dd 4825 debug.status = SCM_APPLYFRAME;
c0ab1b8d 4826 debug.vect = &debug_vect_body;
6dbd0af5
MD
4827 debug.vect[0].a.proc = proc;
4828 debug.vect[0].a.args = SCM_EOL;
9de87eea 4829 scm_i_set_last_debug_frame (&debug);
0f2d19dd 4830#else
434f2f7a 4831 if (scm_debug_mode_p)
0f2d19dd 4832 return scm_dapply (proc, arg1, args);
0f2d19dd
JB
4833#endif
4834
4835 SCM_ASRTGO (SCM_NIMP (proc), badproc);
82a2622a
JB
4836
4837 /* If ARGS is the empty list, then we're calling apply with only two
4838 arguments --- ARG1 is the list of arguments for PROC. Whatever
4839 the case, futz with things so that ARG1 is the first argument to
4840 give to PROC (or SCM_UNDEFINED if no args), and ARGS contains the
30000774
JB
4841 rest.
4842
4843 Setting the debug apply frame args this way is pretty messy.
4844 Perhaps we should store arg1 and args directly in the frame as
4845 received, and let scm_frame_arguments unpack them, because that's
4846 a relatively rare operation. This works for now; if the Guile
4847 developer archives are still around, see Mikael's post of
4848 11-Apr-97. */
a61f4e0c 4849 if (scm_is_null (args))
0f2d19dd 4850 {
a61f4e0c 4851 if (scm_is_null (arg1))
30000774
JB
4852 {
4853 arg1 = SCM_UNDEFINED;
4854#ifdef DEVAL
4855 debug.vect[0].a.args = SCM_EOL;
4856#endif
4857 }
0f2d19dd
JB
4858 else
4859 {
30000774
JB
4860#ifdef DEVAL
4861 debug.vect[0].a.args = arg1;
4862#endif
0f2d19dd
JB
4863 args = SCM_CDR (arg1);
4864 arg1 = SCM_CAR (arg1);
4865 }
4866 }
4867 else
4868 {
0f2d19dd 4869 args = scm_nconc2last (args);
30000774
JB
4870#ifdef DEVAL
4871 debug.vect[0].a.args = scm_cons (arg1, args);
4872#endif
0f2d19dd 4873 }
0f2d19dd 4874#ifdef DEVAL
b6d75948 4875 if (SCM_ENTER_FRAME_P && SCM_TRAPS_P)
6dbd0af5 4876 {
7c9c0169 4877 SCM tmp = scm_make_debugobj (&debug);
d95c0b76
NJ
4878 SCM_TRAPS_P = 0;
4879 scm_call_2 (SCM_ENTER_FRAME_HDLR, scm_sym_enter_frame, tmp);
4880 SCM_TRAPS_P = 1;
6dbd0af5 4881 }
6dbd0af5
MD
4882 ENTER_APPLY;
4883#endif
6dbd0af5 4884tail:
0f2d19dd
JB
4885 switch (SCM_TYP7 (proc))
4886 {
4887 case scm_tc7_subr_2o:
8ab3d8a0
KR
4888 if (SCM_UNBNDP (arg1))
4889 scm_wrong_num_args (proc);
4890 if (scm_is_null (args))
4891 args = SCM_UNDEFINED;
4892 else
4893 {
4894 if (! scm_is_null (SCM_CDR (args)))
4895 scm_wrong_num_args (proc);
4896 args = SCM_CAR (args);
4897 }
ddea3325 4898 RETURN (SCM_SUBRF (proc) (arg1, args));
0f2d19dd 4899 case scm_tc7_subr_2:
a61f4e0c 4900 if (scm_is_null (args) || !scm_is_null (SCM_CDR (args)))
ab1f1094 4901 scm_wrong_num_args (proc);
0f2d19dd 4902 args = SCM_CAR (args);
ddea3325 4903 RETURN (SCM_SUBRF (proc) (arg1, args));
0f2d19dd 4904 case scm_tc7_subr_0:
ab1f1094
DH
4905 if (!SCM_UNBNDP (arg1))
4906 scm_wrong_num_args (proc);
4907 else
4908 RETURN (SCM_SUBRF (proc) ());
0f2d19dd 4909 case scm_tc7_subr_1:
ab1f1094
DH
4910 if (SCM_UNBNDP (arg1))
4911 scm_wrong_num_args (proc);
0f2d19dd 4912 case scm_tc7_subr_1o:
a61f4e0c 4913 if (!scm_is_null (args))
ab1f1094
DH
4914 scm_wrong_num_args (proc);
4915 else
4916 RETURN (SCM_SUBRF (proc) (arg1));
14b18ed6 4917 case scm_tc7_dsubr:
a61f4e0c 4918 if (SCM_UNBNDP (arg1) || !scm_is_null (args))
14b18ed6 4919 scm_wrong_num_args (proc);
e11e83f3 4920 if (SCM_I_INUMP (arg1))
14b18ed6 4921 {
d9a67fc4 4922 RETURN (scm_from_double (SCM_DSUBRF (proc) ((double) SCM_I_INUM (arg1))));
14b18ed6
DH
4923 }
4924 else if (SCM_REALP (arg1))
4925 {
d9a67fc4 4926 RETURN (scm_from_double (SCM_DSUBRF (proc) (SCM_REAL_VALUE (arg1))));
14b18ed6
DH
4927 }
4928 else if (SCM_BIGP (arg1))
f92e85f7 4929 {
d9a67fc4 4930 RETURN (scm_from_double (SCM_DSUBRF (proc) (scm_i_big2dbl (arg1))));
f92e85f7
MV
4931 }
4932 else if (SCM_FRACTIONP (arg1))
4933 {
d9a67fc4 4934 RETURN (scm_from_double (SCM_DSUBRF (proc) (scm_i_fraction2double (arg1))));
f92e85f7 4935 }
14b18ed6 4936 SCM_WTA_DISPATCH_1 (*SCM_SUBR_GENERIC (proc), arg1,
cc95e00a 4937 SCM_ARG1, scm_i_symbol_chars (SCM_SNAME (proc)));
0f2d19dd 4938 case scm_tc7_cxr:
a61f4e0c 4939 if (SCM_UNBNDP (arg1) || !scm_is_null (args))
ab1f1094 4940 scm_wrong_num_args (proc);
a61f4e0c 4941 RETURN (scm_i_chase_pairs (arg1, (scm_t_bits) SCM_SUBRF (proc)));
0f2d19dd 4942 case scm_tc7_subr_3:
a61f4e0c
MV
4943 if (scm_is_null (args)
4944 || scm_is_null (SCM_CDR (args))
4945 || !scm_is_null (SCM_CDDR (args)))
ab1f1094
DH
4946 scm_wrong_num_args (proc);
4947 else
4948 RETURN (SCM_SUBRF (proc) (arg1, SCM_CAR (args), SCM_CADR (args)));
0f2d19dd
JB
4949 case scm_tc7_lsubr:
4950#ifdef DEVAL
ddea3325 4951 RETURN (SCM_SUBRF (proc) (SCM_UNBNDP (arg1) ? SCM_EOL : debug.vect[0].a.args));
0f2d19dd 4952#else
ddea3325 4953 RETURN (SCM_SUBRF (proc) (SCM_UNBNDP (arg1) ? SCM_EOL : scm_cons (arg1, args)));
0f2d19dd
JB
4954#endif
4955 case scm_tc7_lsubr_2:
a61f4e0c 4956 if (!scm_is_pair (args))
ab1f1094
DH
4957 scm_wrong_num_args (proc);
4958 else
4959 RETURN (SCM_SUBRF (proc) (arg1, SCM_CAR (args), SCM_CDR (args)));
0f2d19dd 4960 case scm_tc7_asubr:
a61f4e0c 4961 if (scm_is_null (args))
ddea3325 4962 RETURN (SCM_SUBRF (proc) (arg1, SCM_UNDEFINED));
0f2d19dd
JB
4963 while (SCM_NIMP (args))
4964 {
a61f4e0c 4965 SCM_ASSERT (scm_is_pair (args), args, SCM_ARG2, "apply");
0f2d19dd
JB
4966 arg1 = SCM_SUBRF (proc) (arg1, SCM_CAR (args));
4967 args = SCM_CDR (args);
4968 }
4969 RETURN (arg1);
4970 case scm_tc7_rpsubr:
a61f4e0c 4971 if (scm_is_null (args))
0f2d19dd
JB
4972 RETURN (SCM_BOOL_T);
4973 while (SCM_NIMP (args))
4974 {
a61f4e0c 4975 SCM_ASSERT (scm_is_pair (args), args, SCM_ARG2, "apply");
7888309b 4976 if (scm_is_false (SCM_SUBRF (proc) (arg1, SCM_CAR (args))))
0f2d19dd
JB
4977 RETURN (SCM_BOOL_F);
4978 arg1 = SCM_CAR (args);
4979 args = SCM_CDR (args);
4980 }
4981 RETURN (SCM_BOOL_T);
4982 case scm_tcs_closures:
4983#ifdef DEVAL
6dbd0af5 4984 arg1 = (SCM_UNBNDP (arg1) ? SCM_EOL : debug.vect[0].a.args);
0f2d19dd
JB
4985#else
4986 arg1 = (SCM_UNBNDP (arg1) ? SCM_EOL : scm_cons (arg1, args));
4987#endif
726d810a 4988 if (scm_badargsp (SCM_CLOSURE_FORMALS (proc), arg1))
ab1f1094 4989 scm_wrong_num_args (proc);
1609038c
MD
4990
4991 /* Copy argument list */
4992 if (SCM_IMP (arg1))
4993 args = arg1;
4994 else
4995 {
4996 SCM tl = args = scm_cons (SCM_CAR (arg1), SCM_UNSPECIFIED);
a61f4e0c 4997 for (arg1 = SCM_CDR (arg1); scm_is_pair (arg1); arg1 = SCM_CDR (arg1))
1609038c 4998 {
05b15362 4999 SCM_SETCDR (tl, scm_cons (SCM_CAR (arg1), SCM_UNSPECIFIED));
1609038c
MD
5000 tl = SCM_CDR (tl);
5001 }
5002 SCM_SETCDR (tl, arg1);
5003 }
5004
821f18a4
DH
5005 args = SCM_EXTEND_ENV (SCM_CLOSURE_FORMALS (proc),
5006 args,
5007 SCM_ENV (proc));
f9450cdb 5008 proc = SCM_CLOSURE_BODY (proc);
e791c18f 5009 again:
05b15362 5010 arg1 = SCM_CDR (proc);
a61f4e0c 5011 while (!scm_is_null (arg1))
2ddb0920
MD
5012 {
5013 if (SCM_IMP (SCM_CAR (proc)))
5014 {
5015 if (SCM_ISYMP (SCM_CAR (proc)))
5016 {
cce0e9c8 5017 scm_dynwind_begin (0);
2b829bbb 5018 scm_i_dynwind_pthread_mutex_lock (&source_mutex);
9bc4701c
MD
5019 /* check for race condition */
5020 if (SCM_ISYMP (SCM_CAR (proc)))
9d4bf6d3 5021 m_expand_body (proc, args);
cce0e9c8 5022 scm_dynwind_end ();
e791c18f 5023 goto again;
2ddb0920 5024 }
5280aaca 5025 else
17fa3fcf 5026 SCM_VALIDATE_NON_EMPTY_COMBINATION (SCM_CAR (proc));
2ddb0920
MD
5027 }
5028 else
b1cb24ff 5029 (void) EVAL (SCM_CAR (proc), args);
e791c18f 5030 proc = arg1;
05b15362 5031 arg1 = SCM_CDR (proc);
2ddb0920 5032 }
e791c18f 5033 RETURN (EVALCAR (proc, args));
0717dfd8 5034 case scm_tc7_smob:
68b06924 5035 if (!SCM_SMOB_APPLICABLE_P (proc))
0717dfd8 5036 goto badproc;
afa38f6e 5037 if (SCM_UNBNDP (arg1))
ddea3325 5038 RETURN (SCM_SMOB_APPLY_0 (proc));
a61f4e0c 5039 else if (scm_is_null (args))
ddea3325 5040 RETURN (SCM_SMOB_APPLY_1 (proc, arg1));
a61f4e0c 5041 else if (scm_is_null (SCM_CDR (args)))
ddea3325 5042 RETURN (SCM_SMOB_APPLY_2 (proc, arg1, SCM_CAR (args)));
0717dfd8 5043 else
68b06924 5044 RETURN (SCM_SMOB_APPLY_3 (proc, arg1, SCM_CAR (args), SCM_CDR (args)));
0f2d19dd
JB
5045 case scm_tc7_cclo:
5046#ifdef DEVAL
6dbd0af5
MD
5047 args = (SCM_UNBNDP(arg1) ? SCM_EOL : debug.vect[0].a.args);
5048 arg1 = proc;
5049 proc = SCM_CCLO_SUBR (proc);
5050 debug.vect[0].a.proc = proc;
5051 debug.vect[0].a.args = scm_cons (arg1, args);
0f2d19dd
JB
5052#else
5053 args = (SCM_UNBNDP(arg1) ? SCM_EOL : scm_cons (arg1, args));
0f2d19dd
JB
5054 arg1 = proc;
5055 proc = SCM_CCLO_SUBR (proc);
6dbd0af5 5056#endif
0f2d19dd 5057 goto tail;
89efbff4
MD
5058 case scm_tc7_pws:
5059 proc = SCM_PROCEDURE (proc);
5060#ifdef DEVAL
5061 debug.vect[0].a.proc = proc;
5062#endif
5063 goto tail;
904a077d 5064 case scm_tcs_struct:
f3d2630a
MD
5065 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
5066 {
5067#ifdef DEVAL
5068 args = (SCM_UNBNDP(arg1) ? SCM_EOL : debug.vect[0].a.args);
5069#else
5070 args = (SCM_UNBNDP(arg1) ? SCM_EOL : scm_cons (arg1, args));
5071#endif
195847fa 5072 RETURN (scm_apply_generic (proc, args));
f3d2630a 5073 }
2ca0d207 5074 else if (SCM_I_OPERATORP (proc))
da7f71d7 5075 {
504d99c5 5076 /* operator */
da7f71d7
MD
5077#ifdef DEVAL
5078 args = (SCM_UNBNDP(arg1) ? SCM_EOL : debug.vect[0].a.args);
5079#else
5080 args = (SCM_UNBNDP(arg1) ? SCM_EOL : scm_cons (arg1, args));
5081#endif
5082 arg1 = proc;
195847fa
MD
5083 proc = (SCM_I_ENTITYP (proc)
5084 ? SCM_ENTITY_PROCEDURE (proc)
5085 : SCM_OPERATOR_PROCEDURE (proc));
da7f71d7
MD
5086#ifdef DEVAL
5087 debug.vect[0].a.proc = proc;
5088 debug.vect[0].a.args = scm_cons (arg1, args);
5089#endif
195847fa
MD
5090 if (SCM_NIMP (proc))
5091 goto tail;
5092 else
5093 goto badproc;
da7f71d7 5094 }
2ca0d207
DH
5095 else
5096 goto badproc;
0f2d19dd
JB
5097 default:
5098 badproc:
db4b4ca6 5099 scm_wrong_type_arg ("apply", SCM_ARG1, proc);
0f2d19dd
JB
5100 }
5101#ifdef DEVAL
6dbd0af5 5102exit:
5132eef0 5103 if (scm_check_exit_p && SCM_TRAPS_P)
b7ff98dd 5104 if (SCM_EXIT_FRAME_P || (SCM_TRACE_P && SCM_TRACED_FRAME_P (debug)))
6dbd0af5 5105 {
b7ff98dd 5106 SCM_CLEAR_TRACED_FRAME (debug);
7c9c0169 5107 arg1 = scm_make_debugobj (&debug);
d95c0b76 5108 SCM_TRAPS_P = 0;
7c9c0169 5109 arg1 = scm_call_3 (SCM_EXIT_FRAME_HDLR, scm_sym_exit_frame, arg1, proc);
d95c0b76 5110 SCM_TRAPS_P = 1;
7c9c0169
NJ
5111 if (scm_is_pair (arg1) && scm_is_eq (SCM_CAR (arg1), sym_instead))
5112 proc = SCM_CDR (arg1);
6dbd0af5 5113 }
9de87eea 5114 scm_i_set_last_debug_frame (debug.prev);
0f2d19dd
JB
5115 return proc;
5116#endif
5117}
5118
6dbd0af5
MD
5119
5120/* SECTION: The rest of this file is only read once.
5121 */
5122
0f2d19dd
JB
5123#ifndef DEVAL
5124
504d99c5
MD
5125/* Trampolines
5126 *
5127 * Trampolines make it possible to move procedure application dispatch
5128 * outside inner loops. The motivation was clean implementation of
5129 * efficient replacements of R5RS primitives in SRFI-1.
5130 *
5131 * The semantics is clear: scm_trampoline_N returns an optimized
5132 * version of scm_call_N (or NULL if the procedure isn't applicable
5133 * on N args).
5134 *
5135 * Applying the optimization to map and for-each increased efficiency
5136 * noticeably. For example, (map abs ls) is now 8 times faster than
5137 * before.
5138 */
5139
756414cf
MD
5140static SCM
5141call_subr0_0 (SCM proc)
5142{
5143 return SCM_SUBRF (proc) ();
5144}
5145
5146static SCM
5147call_subr1o_0 (SCM proc)
5148{
5149 return SCM_SUBRF (proc) (SCM_UNDEFINED);
5150}
5151
5152static SCM
5153call_lsubr_0 (SCM proc)
5154{
5155 return SCM_SUBRF (proc) (SCM_EOL);
5156}
5157
5158SCM
5159scm_i_call_closure_0 (SCM proc)
5160{
6a3f13f0
DH
5161 const SCM env = SCM_EXTEND_ENV (SCM_CLOSURE_FORMALS (proc),
5162 SCM_EOL,
5163 SCM_ENV (proc));
5164 const SCM result = scm_eval_body (SCM_CLOSURE_BODY (proc), env);
d0b07b5d 5165 return result;
756414cf
MD
5166}
5167
5168scm_t_trampoline_0
5169scm_trampoline_0 (SCM proc)
5170{
2510c810
DH
5171 scm_t_trampoline_0 trampoline;
5172
756414cf 5173 if (SCM_IMP (proc))
d0b07b5d 5174 return NULL;
2510c810 5175
756414cf
MD
5176 switch (SCM_TYP7 (proc))
5177 {
5178 case scm_tc7_subr_0:
2510c810
DH
5179 trampoline = call_subr0_0;
5180 break;
756414cf 5181 case scm_tc7_subr_1o:
2510c810
DH
5182 trampoline = call_subr1o_0;
5183 break;
756414cf 5184 case scm_tc7_lsubr:
2510c810
DH
5185 trampoline = call_lsubr_0;
5186 break;
756414cf
MD
5187 case scm_tcs_closures:
5188 {
5189 SCM formals = SCM_CLOSURE_FORMALS (proc);
a61f4e0c 5190 if (scm_is_null (formals) || !scm_is_pair (formals))
2510c810 5191 trampoline = scm_i_call_closure_0;
756414cf 5192 else
d0b07b5d 5193 return NULL;
2510c810 5194 break;
756414cf
MD
5195 }
5196 case scm_tcs_struct:
5197 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
2510c810 5198 trampoline = scm_call_generic_0;
2ca0d207 5199 else if (SCM_I_OPERATORP (proc))
2510c810
DH
5200 trampoline = scm_call_0;
5201 else
5202 return NULL;
5203 break;
756414cf
MD
5204 case scm_tc7_smob:
5205 if (SCM_SMOB_APPLICABLE_P (proc))
2510c810 5206 trampoline = SCM_SMOB_DESCRIPTOR (proc).apply_0;
756414cf 5207 else
d0b07b5d 5208 return NULL;
2510c810 5209 break;
756414cf
MD
5210 case scm_tc7_asubr:
5211 case scm_tc7_rpsubr:
5212 case scm_tc7_cclo:
5213 case scm_tc7_pws:
2510c810
DH
5214 trampoline = scm_call_0;
5215 break;
756414cf 5216 default:
2510c810 5217 return NULL; /* not applicable on zero arguments */
756414cf 5218 }
2510c810
DH
5219 /* We only reach this point if a valid trampoline was determined. */
5220
5221 /* If debugging is enabled, we want to see all calls to proc on the stack.
5222 * Thus, we replace the trampoline shortcut with scm_call_0. */
434f2f7a 5223 if (scm_debug_mode_p)
2510c810
DH
5224 return scm_call_0;
5225 else
5226 return trampoline;
756414cf
MD
5227}
5228
504d99c5
MD
5229static SCM
5230call_subr1_1 (SCM proc, SCM arg1)
5231{
5232 return SCM_SUBRF (proc) (arg1);
5233}
5234
9ed24633
MD
5235static SCM
5236call_subr2o_1 (SCM proc, SCM arg1)
5237{
5238 return SCM_SUBRF (proc) (arg1, SCM_UNDEFINED);
5239}
5240
504d99c5
MD
5241static SCM
5242call_lsubr_1 (SCM proc, SCM arg1)
5243{
5244 return SCM_SUBRF (proc) (scm_list_1 (arg1));
5245}
5246
5247static SCM
5248call_dsubr_1 (SCM proc, SCM arg1)
5249{
e11e83f3 5250 if (SCM_I_INUMP (arg1))
504d99c5 5251 {
d9a67fc4 5252 RETURN (scm_from_double (SCM_DSUBRF (proc) ((double) SCM_I_INUM (arg1))));
504d99c5
MD
5253 }
5254 else if (SCM_REALP (arg1))
5255 {
d9a67fc4 5256 RETURN (scm_from_double (SCM_DSUBRF (proc) (SCM_REAL_VALUE (arg1))));
504d99c5 5257 }
504d99c5 5258 else if (SCM_BIGP (arg1))
f92e85f7 5259 {
d9a67fc4 5260 RETURN (scm_from_double (SCM_DSUBRF (proc) (scm_i_big2dbl (arg1))));
f92e85f7
MV
5261 }
5262 else if (SCM_FRACTIONP (arg1))
5263 {
d9a67fc4 5264 RETURN (scm_from_double (SCM_DSUBRF (proc) (scm_i_fraction2double (arg1))));
f92e85f7 5265 }
504d99c5 5266 SCM_WTA_DISPATCH_1 (*SCM_SUBR_GENERIC (proc), arg1,
cc95e00a 5267 SCM_ARG1, scm_i_symbol_chars (SCM_SNAME (proc)));
504d99c5
MD
5268}
5269
5270static SCM
5271call_cxr_1 (SCM proc, SCM arg1)
5272{
a61f4e0c 5273 return scm_i_chase_pairs (arg1, (scm_t_bits) SCM_SUBRF (proc));
504d99c5
MD
5274}
5275
5276static SCM
5277call_closure_1 (SCM proc, SCM arg1)
5278{
6a3f13f0
DH
5279 const SCM env = SCM_EXTEND_ENV (SCM_CLOSURE_FORMALS (proc),
5280 scm_list_1 (arg1),
5281 SCM_ENV (proc));
5282 const SCM result = scm_eval_body (SCM_CLOSURE_BODY (proc), env);
d0b07b5d 5283 return result;
504d99c5
MD
5284}
5285
5286scm_t_trampoline_1
5287scm_trampoline_1 (SCM proc)
5288{
2510c810
DH
5289 scm_t_trampoline_1 trampoline;
5290
504d99c5 5291 if (SCM_IMP (proc))
d0b07b5d 5292 return NULL;
2510c810 5293
504d99c5
MD
5294 switch (SCM_TYP7 (proc))
5295 {
5296 case scm_tc7_subr_1:
5297 case scm_tc7_subr_1o:
2510c810
DH
5298 trampoline = call_subr1_1;
5299 break;
9ed24633 5300 case scm_tc7_subr_2o:
2510c810
DH
5301 trampoline = call_subr2o_1;
5302 break;
504d99c5 5303 case scm_tc7_lsubr:
2510c810
DH
5304 trampoline = call_lsubr_1;
5305 break;
14b18ed6 5306 case scm_tc7_dsubr:
2510c810
DH
5307 trampoline = call_dsubr_1;
5308 break;
504d99c5 5309 case scm_tc7_cxr:
2510c810
DH
5310 trampoline = call_cxr_1;
5311 break;
504d99c5
MD
5312 case scm_tcs_closures:
5313 {
5314 SCM formals = SCM_CLOSURE_FORMALS (proc);
a61f4e0c
MV
5315 if (!scm_is_null (formals)
5316 && (!scm_is_pair (formals) || !scm_is_pair (SCM_CDR (formals))))
2510c810 5317 trampoline = call_closure_1;
504d99c5 5318 else
d0b07b5d 5319 return NULL;
2510c810 5320 break;
504d99c5
MD
5321 }
5322 case scm_tcs_struct:
5323 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
2510c810 5324 trampoline = scm_call_generic_1;
2ca0d207 5325 else if (SCM_I_OPERATORP (proc))
2510c810
DH
5326 trampoline = scm_call_1;
5327 else
5328 return NULL;
5329 break;
504d99c5
MD
5330 case scm_tc7_smob:
5331 if (SCM_SMOB_APPLICABLE_P (proc))
2510c810 5332 trampoline = SCM_SMOB_DESCRIPTOR (proc).apply_1;
504d99c5 5333 else
d0b07b5d 5334 return NULL;
2510c810 5335 break;
504d99c5
MD
5336 case scm_tc7_asubr:
5337 case scm_tc7_rpsubr:
5338 case scm_tc7_cclo:
5339 case scm_tc7_pws:
2510c810
DH
5340 trampoline = scm_call_1;
5341 break;
504d99c5 5342 default:
d0b07b5d 5343 return NULL; /* not applicable on one arg */
504d99c5 5344 }
2510c810
DH
5345 /* We only reach this point if a valid trampoline was determined. */
5346
5347 /* If debugging is enabled, we want to see all calls to proc on the stack.
5348 * Thus, we replace the trampoline shortcut with scm_call_1. */
434f2f7a 5349 if (scm_debug_mode_p)
2510c810
DH
5350 return scm_call_1;
5351 else
5352 return trampoline;
504d99c5
MD
5353}
5354
5355static SCM
5356call_subr2_2 (SCM proc, SCM arg1, SCM arg2)
5357{
5358 return SCM_SUBRF (proc) (arg1, arg2);
5359}
5360
9ed24633
MD
5361static SCM
5362call_lsubr2_2 (SCM proc, SCM arg1, SCM arg2)
5363{
5364 return SCM_SUBRF (proc) (arg1, arg2, SCM_EOL);
5365}
5366
504d99c5
MD
5367static SCM
5368call_lsubr_2 (SCM proc, SCM arg1, SCM arg2)
5369{
5370 return SCM_SUBRF (proc) (scm_list_2 (arg1, arg2));
5371}
5372
5373static SCM
5374call_closure_2 (SCM proc, SCM arg1, SCM arg2)
5375{
6a3f13f0
DH
5376 const SCM env = SCM_EXTEND_ENV (SCM_CLOSURE_FORMALS (proc),
5377 scm_list_2 (arg1, arg2),
5378 SCM_ENV (proc));
5379 const SCM result = scm_eval_body (SCM_CLOSURE_BODY (proc), env);
d0b07b5d 5380 return result;
504d99c5
MD
5381}
5382
5383scm_t_trampoline_2
5384scm_trampoline_2 (SCM proc)
5385{
2510c810
DH
5386 scm_t_trampoline_2 trampoline;
5387
504d99c5 5388 if (SCM_IMP (proc))
d0b07b5d 5389 return NULL;
2510c810 5390
504d99c5
MD
5391 switch (SCM_TYP7 (proc))
5392 {
5393 case scm_tc7_subr_2:
5394 case scm_tc7_subr_2o:
5395 case scm_tc7_rpsubr:
5396 case scm_tc7_asubr:
2510c810
DH
5397 trampoline = call_subr2_2;
5398 break;
9ed24633 5399 case scm_tc7_lsubr_2:
2510c810
DH
5400 trampoline = call_lsubr2_2;
5401 break;
504d99c5 5402 case scm_tc7_lsubr:
2510c810
DH
5403 trampoline = call_lsubr_2;
5404 break;
504d99c5
MD
5405 case scm_tcs_closures:
5406 {
5407 SCM formals = SCM_CLOSURE_FORMALS (proc);
a61f4e0c
MV
5408 if (!scm_is_null (formals)
5409 && (!scm_is_pair (formals)
5410 || (!scm_is_null (SCM_CDR (formals))
5411 && (!scm_is_pair (SCM_CDR (formals))
5412 || !scm_is_pair (SCM_CDDR (formals))))))
2510c810 5413 trampoline = call_closure_2;
504d99c5 5414 else
d0b07b5d 5415 return NULL;
2510c810 5416 break;
504d99c5
MD
5417 }
5418 case scm_tcs_struct:
5419 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
2510c810 5420 trampoline = scm_call_generic_2;
2ca0d207 5421 else if (SCM_I_OPERATORP (proc))
2510c810
DH
5422 trampoline = scm_call_2;
5423 else
5424 return NULL;
5425 break;
504d99c5
MD
5426 case scm_tc7_smob:
5427 if (SCM_SMOB_APPLICABLE_P (proc))
2510c810 5428 trampoline = SCM_SMOB_DESCRIPTOR (proc).apply_2;
504d99c5 5429 else
d0b07b5d 5430 return NULL;
2510c810 5431 break;
504d99c5
MD
5432 case scm_tc7_cclo:
5433 case scm_tc7_pws:
2510c810
DH
5434 trampoline = scm_call_2;
5435 break;
504d99c5 5436 default:
d0b07b5d 5437 return NULL; /* not applicable on two args */
504d99c5 5438 }
2510c810
DH
5439 /* We only reach this point if a valid trampoline was determined. */
5440
5441 /* If debugging is enabled, we want to see all calls to proc on the stack.
5442 * Thus, we replace the trampoline shortcut with scm_call_2. */
434f2f7a 5443 if (scm_debug_mode_p)
2510c810
DH
5444 return scm_call_2;
5445 else
5446 return trampoline;
504d99c5
MD
5447}
5448
d9c393f5
JB
5449/* Typechecking for multi-argument MAP and FOR-EACH.
5450
47c3f06d 5451 Verify that each element of the vector ARGV, except for the first,
d9c393f5 5452 is a proper list whose length is LEN. Attribute errors to WHO,
47c3f06d 5453 and claim that the i'th element of ARGV is WHO's i+2'th argument. */
d9c393f5 5454static inline void
47c3f06d 5455check_map_args (SCM argv,
c014a02e 5456 long len,
47c3f06d
MD
5457 SCM gf,
5458 SCM proc,
5459 SCM args,
5460 const char *who)
d9c393f5 5461{
c014a02e 5462 long i;
d9c393f5 5463
4057a3e0 5464 for (i = SCM_SIMPLE_VECTOR_LENGTH (argv) - 1; i >= 1; i--)
d9c393f5 5465 {
4057a3e0
MV
5466 SCM elt = SCM_SIMPLE_VECTOR_REF (argv, i);
5467 long elt_len = scm_ilength (elt);
d9c393f5
JB
5468
5469 if (elt_len < 0)
47c3f06d
MD
5470 {
5471 if (gf)
5472 scm_apply_generic (gf, scm_cons (proc, args));
5473 else
4057a3e0 5474 scm_wrong_type_arg (who, i + 2, elt);
47c3f06d 5475 }
d9c393f5
JB
5476
5477 if (elt_len != len)
4057a3e0 5478 scm_out_of_range_pos (who, elt, scm_from_long (i + 2));
d9c393f5 5479 }
d9c393f5
JB
5480}
5481
5482
47c3f06d 5483SCM_GPROC (s_map, "map", 2, 0, 1, scm_map, g_map);
1cc91f1b 5484
368bf056
MD
5485/* Note: Currently, scm_map applies PROC to the argument list(s)
5486 sequentially, starting with the first element(s). This is used in
8878f040 5487 evalext.c where the Scheme procedure `map-in-order', which guarantees
368bf056 5488 sequential behaviour, is implemented using scm_map. If the
8878f040 5489 behaviour changes, we need to update `map-in-order'.
368bf056
MD
5490*/
5491
0f2d19dd 5492SCM
1bbd0b84 5493scm_map (SCM proc, SCM arg1, SCM args)
af45e3b0 5494#define FUNC_NAME s_map
0f2d19dd 5495{
c014a02e 5496 long i, len;
0f2d19dd
JB
5497 SCM res = SCM_EOL;
5498 SCM *pres = &res;
0f2d19dd 5499
d9c393f5 5500 len = scm_ilength (arg1);
47c3f06d
MD
5501 SCM_GASSERTn (len >= 0,
5502 g_map, scm_cons2 (proc, arg1, args), SCM_ARG2, s_map);
af45e3b0 5503 SCM_VALIDATE_REST_ARGUMENT (args);
a61f4e0c 5504 if (scm_is_null (args))
0f2d19dd 5505 {
504d99c5
MD
5506 scm_t_trampoline_1 call = scm_trampoline_1 (proc);
5507 SCM_GASSERT2 (call, g_map, proc, arg1, SCM_ARG1, s_map);
5508 while (SCM_NIMP (arg1))
5509 {
5510 *pres = scm_list_1 (call (proc, SCM_CAR (arg1)));
5511 pres = SCM_CDRLOC (*pres);
5512 arg1 = SCM_CDR (arg1);
5513 }
5514 return res;
5515 }
a61f4e0c 5516 if (scm_is_null (SCM_CDR (args)))
504d99c5
MD
5517 {
5518 SCM arg2 = SCM_CAR (args);
5519 int len2 = scm_ilength (arg2);
5520 scm_t_trampoline_2 call = scm_trampoline_2 (proc);
5521 SCM_GASSERTn (call,
5522 g_map, scm_cons2 (proc, arg1, args), SCM_ARG1, s_map);
5523 SCM_GASSERTn (len2 >= 0,
5524 g_map, scm_cons2 (proc, arg1, args), SCM_ARG3, s_map);
5525 if (len2 != len)
5526 SCM_OUT_OF_RANGE (3, arg2);
0f2d19dd
JB
5527 while (SCM_NIMP (arg1))
5528 {
504d99c5 5529 *pres = scm_list_1 (call (proc, SCM_CAR (arg1), SCM_CAR (arg2)));
a23afe53 5530 pres = SCM_CDRLOC (*pres);
0f2d19dd 5531 arg1 = SCM_CDR (arg1);
504d99c5 5532 arg2 = SCM_CDR (arg2);
0f2d19dd
JB
5533 }
5534 return res;
5535 }
05b15362
DH
5536 arg1 = scm_cons (arg1, args);
5537 args = scm_vector (arg1);
47c3f06d 5538 check_map_args (args, len, g_map, proc, arg1, s_map);
0f2d19dd
JB
5539 while (1)
5540 {
5541 arg1 = SCM_EOL;
4057a3e0 5542 for (i = SCM_SIMPLE_VECTOR_LENGTH (args) - 1; i >= 0; i--)
0f2d19dd 5543 {
4057a3e0
MV
5544 SCM elt = SCM_SIMPLE_VECTOR_REF (args, i);
5545 if (SCM_IMP (elt))
d9c393f5 5546 return res;
4057a3e0
MV
5547 arg1 = scm_cons (SCM_CAR (elt), arg1);
5548 SCM_SIMPLE_VECTOR_SET (args, i, SCM_CDR (elt));
0f2d19dd 5549 }
8ea46249 5550 *pres = scm_list_1 (scm_apply (proc, arg1, SCM_EOL));
a23afe53 5551 pres = SCM_CDRLOC (*pres);
0f2d19dd
JB
5552 }
5553}
af45e3b0 5554#undef FUNC_NAME
0f2d19dd
JB
5555
5556
47c3f06d 5557SCM_GPROC (s_for_each, "for-each", 2, 0, 1, scm_for_each, g_for_each);
1cc91f1b 5558
0f2d19dd 5559SCM
1bbd0b84 5560scm_for_each (SCM proc, SCM arg1, SCM args)
af45e3b0 5561#define FUNC_NAME s_for_each
0f2d19dd 5562{
c014a02e 5563 long i, len;
d9c393f5 5564 len = scm_ilength (arg1);
47c3f06d
MD
5565 SCM_GASSERTn (len >= 0, g_for_each, scm_cons2 (proc, arg1, args),
5566 SCM_ARG2, s_for_each);
af45e3b0 5567 SCM_VALIDATE_REST_ARGUMENT (args);
a61f4e0c 5568 if (scm_is_null (args))
0f2d19dd 5569 {
504d99c5
MD
5570 scm_t_trampoline_1 call = scm_trampoline_1 (proc);
5571 SCM_GASSERT2 (call, g_for_each, proc, arg1, SCM_ARG1, s_for_each);
5572 while (SCM_NIMP (arg1))
5573 {
5574 call (proc, SCM_CAR (arg1));
5575 arg1 = SCM_CDR (arg1);
5576 }
5577 return SCM_UNSPECIFIED;
5578 }
a61f4e0c 5579 if (scm_is_null (SCM_CDR (args)))
504d99c5
MD
5580 {
5581 SCM arg2 = SCM_CAR (args);
5582 int len2 = scm_ilength (arg2);
5583 scm_t_trampoline_2 call = scm_trampoline_2 (proc);
5584 SCM_GASSERTn (call, g_for_each,
5585 scm_cons2 (proc, arg1, args), SCM_ARG1, s_for_each);
5586 SCM_GASSERTn (len2 >= 0, g_for_each,
5587 scm_cons2 (proc, arg1, args), SCM_ARG3, s_for_each);
5588 if (len2 != len)
5589 SCM_OUT_OF_RANGE (3, arg2);
c96d76b8 5590 while (SCM_NIMP (arg1))
0f2d19dd 5591 {
504d99c5 5592 call (proc, SCM_CAR (arg1), SCM_CAR (arg2));
0f2d19dd 5593 arg1 = SCM_CDR (arg1);
504d99c5 5594 arg2 = SCM_CDR (arg2);
0f2d19dd
JB
5595 }
5596 return SCM_UNSPECIFIED;
5597 }
05b15362
DH
5598 arg1 = scm_cons (arg1, args);
5599 args = scm_vector (arg1);
47c3f06d 5600 check_map_args (args, len, g_for_each, proc, arg1, s_for_each);
0f2d19dd
JB
5601 while (1)
5602 {
5603 arg1 = SCM_EOL;
4057a3e0 5604 for (i = SCM_SIMPLE_VECTOR_LENGTH (args) - 1; i >= 0; i--)
0f2d19dd 5605 {
4057a3e0
MV
5606 SCM elt = SCM_SIMPLE_VECTOR_REF (args, i);
5607 if (SCM_IMP (elt))
c96d76b8 5608 return SCM_UNSPECIFIED;
4057a3e0
MV
5609 arg1 = scm_cons (SCM_CAR (elt), arg1);
5610 SCM_SIMPLE_VECTOR_SET (args, i, SCM_CDR (elt));
0f2d19dd
JB
5611 }
5612 scm_apply (proc, arg1, SCM_EOL);
5613 }
5614}
af45e3b0 5615#undef FUNC_NAME
0f2d19dd 5616
1cc91f1b 5617
0f2d19dd 5618SCM
6e8d25a6 5619scm_closure (SCM code, SCM env)
0f2d19dd 5620{
16d4699b
MV
5621 SCM z;
5622 SCM closcar = scm_cons (code, SCM_EOL);
228a24ef 5623 z = scm_cell (SCM_UNPACK (closcar) + scm_tc3_closure, (scm_t_bits) env);
16d4699b 5624 scm_remember_upto_here (closcar);
0f2d19dd
JB
5625 return z;
5626}
5627
5628
92c2555f 5629scm_t_bits scm_tc16_promise;
1cc91f1b 5630
0f2d19dd 5631SCM
6e8d25a6 5632scm_makprom (SCM code)
0f2d19dd 5633{
28d52ebb
MD
5634 SCM_RETURN_NEWSMOB2 (scm_tc16_promise,
5635 SCM_UNPACK (code),
9de87eea
MV
5636 scm_make_recursive_mutex ());
5637}
5638
5639static SCM
5640promise_mark (SCM promise)
5641{
5642 scm_gc_mark (SCM_PROMISE_MUTEX (promise));
5643 return SCM_PROMISE_DATA (promise);
0f2d19dd
JB
5644}
5645
28d52ebb
MD
5646static size_t
5647promise_free (SCM promise)
5648{
28d52ebb
MD
5649 return 0;
5650}
1cc91f1b 5651
0f2d19dd 5652static int
e841c3e0 5653promise_print (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd 5654{
19402679 5655 int writingp = SCM_WRITINGP (pstate);
b7f3516f 5656 scm_puts ("#<promise ", port);
19402679 5657 SCM_SET_WRITINGP (pstate, 1);
28d52ebb 5658 scm_iprin1 (SCM_PROMISE_DATA (exp), port, pstate);
19402679 5659 SCM_SET_WRITINGP (pstate, writingp);
b7f3516f 5660 scm_putc ('>', port);
0f2d19dd
JB
5661 return !0;
5662}
5663
3b3b36dd 5664SCM_DEFINE (scm_force, "force", 1, 0, 0,
28d52ebb 5665 (SCM promise),
67e8151b
MG
5666 "If the promise @var{x} has not been computed yet, compute and\n"
5667 "return @var{x}, otherwise just return the previously computed\n"
5668 "value.")
1bbd0b84 5669#define FUNC_NAME s_scm_force
0f2d19dd 5670{
28d52ebb 5671 SCM_VALIDATE_SMOB (1, promise, promise);
9de87eea 5672 scm_lock_mutex (SCM_PROMISE_MUTEX (promise));
28d52ebb 5673 if (!SCM_PROMISE_COMPUTED_P (promise))
0f2d19dd 5674 {
28d52ebb
MD
5675 SCM ans = scm_call_0 (SCM_PROMISE_DATA (promise));
5676 if (!SCM_PROMISE_COMPUTED_P (promise))
0f2d19dd 5677 {
28d52ebb
MD
5678 SCM_SET_PROMISE_DATA (promise, ans);
5679 SCM_SET_PROMISE_COMPUTED (promise);
0f2d19dd
JB
5680 }
5681 }
9de87eea 5682 scm_unlock_mutex (SCM_PROMISE_MUTEX (promise));
28d52ebb 5683 return SCM_PROMISE_DATA (promise);
0f2d19dd 5684}
1bbd0b84 5685#undef FUNC_NAME
0f2d19dd 5686
445f675c 5687
a1ec6916 5688SCM_DEFINE (scm_promise_p, "promise?", 1, 0, 0,
67e8151b 5689 (SCM obj),
b380b885 5690 "Return true if @var{obj} is a promise, i.e. a delayed computation\n"
7a095584 5691 "(@pxref{Delayed evaluation,,,r5rs.info,The Revised^5 Report on Scheme}).")
1bbd0b84 5692#define FUNC_NAME s_scm_promise_p
0f2d19dd 5693{
7888309b 5694 return scm_from_bool (SCM_TYP16_PREDICATE (scm_tc16_promise, obj));
0f2d19dd 5695}
1bbd0b84 5696#undef FUNC_NAME
0f2d19dd 5697
445f675c 5698
a1ec6916 5699SCM_DEFINE (scm_cons_source, "cons-source", 3, 0, 0,
1bbd0b84 5700 (SCM xorig, SCM x, SCM y),
11768c04
NJ
5701 "Create and return a new pair whose car and cdr are @var{x} and @var{y}.\n"
5702 "Any source properties associated with @var{xorig} are also associated\n"
5703 "with the new pair.")
1bbd0b84 5704#define FUNC_NAME s_scm_cons_source
26d5b9b4
MD
5705{
5706 SCM p, z;
16d4699b 5707 z = scm_cons (x, y);
26d5b9b4
MD
5708 /* Copy source properties possibly associated with xorig. */
5709 p = scm_whash_lookup (scm_source_whash, xorig);
7888309b 5710 if (scm_is_true (p))
26d5b9b4
MD
5711 scm_whash_insert (scm_source_whash, z, p);
5712 return z;
5713}
1bbd0b84 5714#undef FUNC_NAME
26d5b9b4 5715
445f675c 5716
62360b89
DH
5717/* The function scm_copy_tree is used to copy an expression tree to allow the
5718 * memoizer to modify the expression during memoization. scm_copy_tree
5719 * creates deep copies of pairs and vectors, but not of any other data types,
5720 * since only pairs and vectors will be parsed by the memoizer.
5721 *
5722 * To avoid infinite recursion due to cyclic structures, the hare-and-tortoise
5723 * pattern is used to detect cycles. In fact, the pattern is used in two
5724 * dimensions, vertical (indicated in the code by the variable names 'hare'
5725 * and 'tortoise') and horizontal ('rabbit' and 'turtle'). In both
5726 * dimensions, the hare/rabbit will take two steps when the tortoise/turtle
5727 * takes one.
5728 *
5729 * The vertical dimension corresponds to recursive calls to function
5730 * copy_tree: This happens when descending into vector elements, into cars of
5731 * lists and into the cdr of an improper list. In this dimension, the
5732 * tortoise follows the hare by using the processor stack: Every stack frame
5733 * will hold an instance of struct t_trace. These instances are connected in
5734 * a way that represents the trace of the hare, which thus can be followed by
5735 * the tortoise. The tortoise will always point to struct t_trace instances
5736 * relating to SCM objects that have already been copied. Thus, a cycle is
5737 * detected if the tortoise and the hare point to the same object,
5738 *
5739 * The horizontal dimension is within one execution of copy_tree, when the
5740 * function cdr's along the pairs of a list. This is the standard
5741 * hare-and-tortoise implementation, found several times in guile. */
5742
5743struct t_trace {
2b829bbb
KR
5744 struct t_trace *trace; /* These pointers form a trace along the stack. */
5745 SCM obj; /* The object handled at the respective stack frame.*/
62360b89
DH
5746};
5747
5748static SCM
5749copy_tree (
5750 struct t_trace *const hare,
5751 struct t_trace *tortoise,
5752 unsigned int tortoise_delay )
5753{
4057a3e0 5754 if (!scm_is_pair (hare->obj) && !scm_is_simple_vector (hare->obj))
62360b89
DH
5755 {
5756 return hare->obj;
5757 }
5758 else
5759 {
5760 /* Prepare the trace along the stack. */
5761 struct t_trace new_hare;
5762 hare->trace = &new_hare;
5763
5764 /* The tortoise will make its step after the delay has elapsed. Note
5765 * that in contrast to the typical hare-and-tortoise pattern, the step
5766 * of the tortoise happens before the hare takes its steps. This is, in
5767 * principle, no problem, except for the start of the algorithm: Then,
5fb64383 5768 * it has to be made sure that the hare actually gets its advantage of
62360b89
DH
5769 * two steps. */
5770 if (tortoise_delay == 0)
5771 {
5772 tortoise_delay = 1;
5773 tortoise = tortoise->trace;
bc36d050 5774 ASSERT_SYNTAX (!scm_is_eq (hare->obj, tortoise->obj),
62360b89
DH
5775 s_bad_expression, hare->obj);
5776 }
5777 else
5778 {
5779 --tortoise_delay;
5780 }
5781
4057a3e0 5782 if (scm_is_simple_vector (hare->obj))
62360b89 5783 {
4057a3e0
MV
5784 size_t length = SCM_SIMPLE_VECTOR_LENGTH (hare->obj);
5785 SCM new_vector = scm_c_make_vector (length, SCM_UNSPECIFIED);
62360b89
DH
5786
5787 /* Each vector element is copied by recursing into copy_tree, having
5788 * the tortoise follow the hare into the depths of the stack. */
5789 unsigned long int i;
5790 for (i = 0; i < length; ++i)
5791 {
5792 SCM new_element;
4057a3e0 5793 new_hare.obj = SCM_SIMPLE_VECTOR_REF (hare->obj, i);
62360b89 5794 new_element = copy_tree (&new_hare, tortoise, tortoise_delay);
4057a3e0 5795 SCM_SIMPLE_VECTOR_SET (new_vector, i, new_element);
62360b89
DH
5796 }
5797
5798 return new_vector;
5799 }
2b829bbb 5800 else /* scm_is_pair (hare->obj) */
62360b89
DH
5801 {
5802 SCM result;
5803 SCM tail;
5804
5805 SCM rabbit = hare->obj;
5806 SCM turtle = hare->obj;
5807
5808 SCM copy;
5809
5810 /* The first pair of the list is treated specially, in order to
5811 * preserve a potential source code position. */
5812 result = tail = scm_cons_source (rabbit, SCM_EOL, SCM_EOL);
5813 new_hare.obj = SCM_CAR (rabbit);
5814 copy = copy_tree (&new_hare, tortoise, tortoise_delay);
5815 SCM_SETCAR (tail, copy);
5816
5817 /* The remaining pairs of the list are copied by, horizontally,
5818 * having the turtle follow the rabbit, and, vertically, having the
5819 * tortoise follow the hare into the depths of the stack. */
5820 rabbit = SCM_CDR (rabbit);
a61f4e0c 5821 while (scm_is_pair (rabbit))
62360b89
DH
5822 {
5823 new_hare.obj = SCM_CAR (rabbit);
5824 copy = copy_tree (&new_hare, tortoise, tortoise_delay);
5825 SCM_SETCDR (tail, scm_cons (copy, SCM_UNDEFINED));
5826 tail = SCM_CDR (tail);
5827
5828 rabbit = SCM_CDR (rabbit);
a61f4e0c 5829 if (scm_is_pair (rabbit))
62360b89
DH
5830 {
5831 new_hare.obj = SCM_CAR (rabbit);
5832 copy = copy_tree (&new_hare, tortoise, tortoise_delay);
5833 SCM_SETCDR (tail, scm_cons (copy, SCM_UNDEFINED));
5834 tail = SCM_CDR (tail);
5835 rabbit = SCM_CDR (rabbit);
5836
5837 turtle = SCM_CDR (turtle);
bc36d050 5838 ASSERT_SYNTAX (!scm_is_eq (rabbit, turtle),
62360b89
DH
5839 s_bad_expression, rabbit);
5840 }
5841 }
5842
5843 /* We have to recurse into copy_tree again for the last cdr, in
5844 * order to handle the situation that it holds a vector. */
5845 new_hare.obj = rabbit;
5846 copy = copy_tree (&new_hare, tortoise, tortoise_delay);
5847 SCM_SETCDR (tail, copy);
5848
5849 return result;
5850 }
5851 }
5852}
5853
a1ec6916 5854SCM_DEFINE (scm_copy_tree, "copy-tree", 1, 0, 0,
1bbd0b84 5855 (SCM obj),
b380b885 5856 "Recursively copy the data tree that is bound to @var{obj}, and return a\n"
bfefbf18 5857 "the new data structure. @code{copy-tree} recurses down the\n"
b380b885
MD
5858 "contents of both pairs and vectors (since both cons cells and vector\n"
5859 "cells may point to arbitrary objects), and stops recursing when it hits\n"
5860 "any other object.")
1bbd0b84 5861#define FUNC_NAME s_scm_copy_tree
0f2d19dd 5862{
62360b89
DH
5863 /* Prepare the trace along the stack. */
5864 struct t_trace trace;
5865 trace.obj = obj;
5866
5867 /* In function copy_tree, if the tortoise makes its step, it will do this
5868 * before the hare has the chance to move. Thus, we have to make sure that
5869 * the very first step of the tortoise will not happen after the hare has
5870 * really made two steps. This is achieved by passing '2' as the initial
5871 * delay for the tortoise. NOTE: Since cycles are unlikely, giving the hare
5872 * a bigger advantage may improve performance slightly. */
5873 return copy_tree (&trace, &trace, 2);
0f2d19dd 5874}
1bbd0b84 5875#undef FUNC_NAME
0f2d19dd 5876
1cc91f1b 5877
4163eb72
MV
5878/* We have three levels of EVAL here:
5879
5880 - scm_i_eval (exp, env)
5881
5882 evaluates EXP in environment ENV. ENV is a lexical environment
5883 structure as used by the actual tree code evaluator. When ENV is
5884 a top-level environment, then changes to the current module are
a513ead3 5885 tracked by updating ENV so that it continues to be in sync with
4163eb72
MV
5886 the current module.
5887
5888 - scm_primitive_eval (exp)
5889
5890 evaluates EXP in the top-level environment as determined by the
5891 current module. This is done by constructing a suitable
5892 environment and calling scm_i_eval. Thus, changes to the
5893 top-level module are tracked normally.
5894
9de87eea 5895 - scm_eval (exp, mod_or_state)
4163eb72 5896
9de87eea
MV
5897 evaluates EXP while MOD_OR_STATE is the current module or current
5898 dynamic state (as appropriate). This is done by setting the
5899 current module (or dynamic state) to MOD_OR_STATE, invoking
5900 scm_primitive_eval on EXP, and then restoring the current module
5901 (or dynamic state) to the value it had previously. That is,
5902 while EXP is evaluated, changes to the current module (or dynamic
5903 state) are tracked, but these changes do not persist when
4163eb72
MV
5904 scm_eval returns.
5905
5906 For each level of evals, there are two variants, distinguished by a
5907 _x suffix: the ordinary variant does not modify EXP while the _x
5908 variant can destructively modify EXP into something completely
5909 unintelligible. A Scheme data structure passed as EXP to one of the
5910 _x variants should not ever be used again for anything. So when in
5911 doubt, use the ordinary variant.
5912
5913*/
5914
0f2d19dd 5915SCM
68d8be66 5916scm_i_eval_x (SCM exp, SCM env)
0f2d19dd 5917{
cc95e00a 5918 if (scm_is_symbol (exp))
434f2f7a
DH
5919 return *scm_lookupcar (scm_cons (exp, SCM_UNDEFINED), env, 1);
5920 else
385609b9 5921 return SCM_I_XEVAL (exp, env);
0f2d19dd
JB
5922}
5923
68d8be66
MD
5924SCM
5925scm_i_eval (SCM exp, SCM env)
5926{
26fb6390 5927 exp = scm_copy_tree (exp);
cc95e00a 5928 if (scm_is_symbol (exp))
434f2f7a
DH
5929 return *scm_lookupcar (scm_cons (exp, SCM_UNDEFINED), env, 1);
5930 else
385609b9 5931 return SCM_I_XEVAL (exp, env);
68d8be66
MD
5932}
5933
5934SCM
4163eb72 5935scm_primitive_eval_x (SCM exp)
0f2d19dd 5936{
a513ead3 5937 SCM env;
bcdab802 5938 SCM transformer = scm_current_module_transformer ();
a513ead3 5939 if (SCM_NIMP (transformer))
fdc28395 5940 exp = scm_call_1 (transformer, exp);
a513ead3 5941 env = scm_top_level_env (scm_current_module_lookup_closure ());
4163eb72 5942 return scm_i_eval_x (exp, env);
0f2d19dd
JB
5943}
5944
4163eb72
MV
5945SCM_DEFINE (scm_primitive_eval, "primitive-eval", 1, 0, 0,
5946 (SCM exp),
2069af38 5947 "Evaluate @var{exp} in the top-level environment specified by\n"
4163eb72
MV
5948 "the current module.")
5949#define FUNC_NAME s_scm_primitive_eval
5950{
a513ead3 5951 SCM env;
bcdab802 5952 SCM transformer = scm_current_module_transformer ();
7888309b 5953 if (scm_is_true (transformer))
fdc28395 5954 exp = scm_call_1 (transformer, exp);
a513ead3 5955 env = scm_top_level_env (scm_current_module_lookup_closure ());
4163eb72
MV
5956 return scm_i_eval (exp, env);
5957}
5958#undef FUNC_NAME
5959
6bff1368 5960
68d8be66
MD
5961/* Eval does not take the second arg optionally. This is intentional
5962 * in order to be R5RS compatible, and to prepare for the new module
5963 * system, where we would like to make the choice of evaluation
4163eb72 5964 * environment explicit. */
549e6ec6 5965
4163eb72 5966SCM
9de87eea 5967scm_eval_x (SCM exp, SCM module_or_state)
4163eb72 5968{
9de87eea 5969 SCM res;
4163eb72 5970
661ae7ab 5971 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
9de87eea 5972 if (scm_is_dynamic_state (module_or_state))
661ae7ab 5973 scm_dynwind_current_dynamic_state (module_or_state);
9de87eea 5974 else
661ae7ab 5975 scm_dynwind_current_module (module_or_state);
4163eb72 5976
9de87eea
MV
5977 res = scm_primitive_eval_x (exp);
5978
661ae7ab 5979 scm_dynwind_end ();
9de87eea 5980 return res;
4163eb72 5981}
09074dbf 5982
68d8be66 5983SCM_DEFINE (scm_eval, "eval", 2, 0, 0,
9de87eea 5984 (SCM exp, SCM module_or_state),
4163eb72 5985 "Evaluate @var{exp}, a list representing a Scheme expression,\n"
9de87eea
MV
5986 "in the top-level environment specified by\n"
5987 "@var{module_or_state}.\n"
8f85c0c6 5988 "While @var{exp} is evaluated (using @code{primitive-eval}),\n"
9de87eea
MV
5989 "@var{module_or_state} is made the current module when\n"
5990 "it is a module, or the current dynamic state when it is\n"
5991 "a dynamic state."
6be1fab9 5992 "Example: (eval '(+ 1 2) (interaction-environment))")
1bbd0b84 5993#define FUNC_NAME s_scm_eval
0f2d19dd 5994{
9de87eea
MV
5995 SCM res;
5996
661ae7ab 5997 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
9de87eea 5998 if (scm_is_dynamic_state (module_or_state))
661ae7ab 5999 scm_dynwind_current_dynamic_state (module_or_state);
9de87eea 6000 else
661ae7ab 6001 scm_dynwind_current_module (module_or_state);
9de87eea
MV
6002
6003 res = scm_primitive_eval (exp);
09074dbf 6004
661ae7ab 6005 scm_dynwind_end ();
9de87eea 6006 return res;
0f2d19dd 6007}
1bbd0b84 6008#undef FUNC_NAME
0f2d19dd 6009
6dbd0af5 6010
434f2f7a 6011/* At this point, deval and scm_dapply are generated.
6dbd0af5
MD
6012 */
6013
a44a9715
DH
6014#define DEVAL
6015#include "eval.c"
0f2d19dd 6016
1cc91f1b 6017
434f2f7a
DH
6018#if (SCM_ENABLE_DEPRECATED == 1)
6019
6020/* Deprecated in guile 1.7.0 on 2004-03-29. */
6021SCM scm_ceval (SCM x, SCM env)
6022{
a61f4e0c 6023 if (scm_is_pair (x))
434f2f7a 6024 return ceval (x, env);
cc95e00a 6025 else if (scm_is_symbol (x))
434f2f7a
DH
6026 return *scm_lookupcar (scm_cons (x, SCM_UNDEFINED), env, 1);
6027 else
385609b9 6028 return SCM_I_XEVAL (x, env);
434f2f7a
DH
6029}
6030
6031/* Deprecated in guile 1.7.0 on 2004-03-29. */
6032SCM scm_deval (SCM x, SCM env)
6033{
a61f4e0c 6034 if (scm_is_pair (x))
434f2f7a 6035 return deval (x, env);
cc95e00a 6036 else if (scm_is_symbol (x))
434f2f7a
DH
6037 return *scm_lookupcar (scm_cons (x, SCM_UNDEFINED), env, 1);
6038 else
385609b9 6039 return SCM_I_XEVAL (x, env);
434f2f7a
DH
6040}
6041
6042static SCM
6043dispatching_eval (SCM x, SCM env)
6044{
6045 if (scm_debug_mode_p)
6046 return scm_deval (x, env);
6047 else
6048 return scm_ceval (x, env);
6049}
6050
6051/* Deprecated in guile 1.7.0 on 2004-03-29. */
6052SCM (*scm_ceval_ptr) (SCM x, SCM env) = dispatching_eval;
6053
6054#endif
6055
6056
0f2d19dd
JB
6057void
6058scm_init_eval ()
0f2d19dd 6059{
d1138028
MV
6060 scm_i_pthread_mutex_init (&source_mutex,
6061 scm_i_pthread_mutexattr_recursive);
6062
33b97402 6063 scm_init_opts (scm_evaluator_traps,
62560650 6064 scm_evaluator_trap_table);
33b97402 6065 scm_init_opts (scm_eval_options_interface,
62560650 6066 scm_eval_opts);
33b97402 6067
f99c9c28 6068 scm_tc16_promise = scm_make_smob_type ("promise", 0);
9de87eea 6069 scm_set_smob_mark (scm_tc16_promise, promise_mark);
28d52ebb 6070 scm_set_smob_free (scm_tc16_promise, promise_free);
e841c3e0 6071 scm_set_smob_print (scm_tc16_promise, promise_print);
b8229a3b 6072
a44a9715
DH
6073 undefineds = scm_list_1 (SCM_UNDEFINED);
6074 SCM_SETCDR (undefineds, undefineds);
6075 scm_permanent_object (undefineds);
7c33806a 6076
a44a9715 6077 scm_listofnull = scm_list_1 (SCM_EOL);
0f2d19dd 6078
a44a9715
DH
6079 f_apply = scm_c_define_subr ("apply", scm_tc7_lsubr_2, scm_apply);
6080 scm_permanent_object (f_apply);
86d31dfe 6081
a0599745 6082#include "libguile/eval.x"
60a49842 6083
25eaf21a 6084 scm_add_feature ("delay");
0f2d19dd 6085}
0f2d19dd 6086
6dbd0af5 6087#endif /* !DEVAL */
89e00824
ML
6088
6089/*
6090 Local Variables:
6091 c-file-style: "gnu"
6092 End:
6093*/
62560650 6094