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