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