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