Merge branch 'master' into boehm-demers-weiser-gc
[bpt/guile.git] / libguile / eval.c
CommitLineData
61b6542a 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008
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
6dbd0af5 21/* SECTION: This code is compiled once.
0f2d19dd
JB
22 */
23
dbb605f5 24#ifdef HAVE_CONFIG_H
3d05f2e0
RB
25# include <config.h>
26#endif
0f2d19dd 27
f7439099 28#include <alloca.h>
3d05f2e0 29
f7439099 30#include "libguile/__scm.h"
48b96f4b 31
e7313a9d 32#include <assert.h>
a0599745 33#include "libguile/_scm.h"
21628685
DH
34#include "libguile/alist.h"
35#include "libguile/async.h"
36#include "libguile/continuations.h"
a0599745 37#include "libguile/debug.h"
328dc9a3 38#include "libguile/deprecation.h"
09074dbf 39#include "libguile/dynwind.h"
a0599745 40#include "libguile/eq.h"
21628685
DH
41#include "libguile/feature.h"
42#include "libguile/fluids.h"
756414cf 43#include "libguile/futures.h"
21628685
DH
44#include "libguile/goops.h"
45#include "libguile/hash.h"
46#include "libguile/hashtab.h"
47#include "libguile/lang.h"
4610b011 48#include "libguile/list.h"
a0599745 49#include "libguile/macros.h"
a0599745 50#include "libguile/modules.h"
21628685 51#include "libguile/objects.h"
a0599745 52#include "libguile/ports.h"
7e6e6b37 53#include "libguile/print.h"
21628685 54#include "libguile/procprop.h"
a0599745 55#include "libguile/root.h"
21628685
DH
56#include "libguile/smob.h"
57#include "libguile/srcprop.h"
58#include "libguile/stackchk.h"
59#include "libguile/strings.h"
9de87eea 60#include "libguile/threads.h"
21628685
DH
61#include "libguile/throw.h"
62#include "libguile/validate.h"
a513ead3 63#include "libguile/values.h"
21628685 64#include "libguile/vectors.h"
a0599745 65
a0599745 66#include "libguile/eval.h"
0ee05b85 67#include "libguile/private-options.h"
89efbff4 68
0f2d19dd
JB
69\f
70
0ee05b85 71
212e58ed 72static SCM unmemoize_exprs (SCM expr, SCM env);
0f572ba7 73static SCM canonicalize_define (SCM expr);
e5156567 74static SCM *scm_lookupcar1 (SCM vloc, SCM genv, int check);
212e58ed 75static SCM unmemoize_builtin_macro (SCM expr, SCM env);
0ee05b85
HWN
76static void ceval_letrec_inits (SCM env, SCM init_forms, SCM **init_values_eol);
77static SCM ceval (SCM x, SCM env);
78static SCM deval (SCM x, SCM env);
0f572ba7
DH
79
80\f
81
e6729603
DH
82/* {Syntax Errors}
83 *
84 * This section defines the message strings for the syntax errors that can be
85 * detected during memoization and the functions and macros that shall be
86 * called by the memoizer code to signal syntax errors. */
87
88
89/* Syntax errors that can be detected during memoization: */
90
91/* Circular or improper lists do not form valid scheme expressions. If a
92 * circular list or an improper list is detected in a place where a scheme
93 * expression is expected, a 'Bad expression' error is signalled. */
94static const char s_bad_expression[] = "Bad expression";
95
89bff2fc
DH
96/* If a form is detected that holds a different number of expressions than are
97 * required in that context, a 'Missing or extra expression' error is
98 * signalled. */
99static const char s_expression[] = "Missing or extra expression in";
100
cc56ba80 101/* If a form is detected that holds less expressions than are required in that
8ae95199 102 * context, a 'Missing expression' error is signalled. */
cc56ba80
DH
103static const char s_missing_expression[] = "Missing expression in";
104
609a8b86 105/* If a form is detected that holds more expressions than are allowed in that
8ae95199 106 * context, an 'Extra expression' error is signalled. */
609a8b86
DH
107static const char s_extra_expression[] = "Extra expression in";
108
89bff2fc
DH
109/* The empty combination '()' is not allowed as an expression in scheme. If
110 * it is detected in a place where an expression is expected, an 'Illegal
111 * empty combination' error is signalled. Note: If you encounter this error
112 * message, it is very likely that you intended to denote the empty list. To
113 * do so, you need to quote the empty list like (quote ()) or '(). */
114static const char s_empty_combination[] = "Illegal empty combination";
115
c86c440b
DH
116/* A body may hold an arbitrary number of internal defines, followed by a
117 * non-empty sequence of expressions. If a body with an empty sequence of
118 * expressions is detected, a 'Missing body expression' error is signalled.
119 */
120static const char s_missing_body_expression[] = "Missing body expression in";
121
122/* A body may hold an arbitrary number of internal defines, followed by a
123 * non-empty sequence of expressions. Each the definitions and the
124 * expressions may be grouped arbitraryly with begin, but it is not allowed to
125 * mix definitions and expressions. If a define form in a body mixes
126 * definitions and expressions, a 'Mixed definitions and expressions' error is
6bff1368 127 * signalled. */
c86c440b 128static const char s_mixed_body_forms[] = "Mixed definitions and expressions in";
6bff1368
DH
129/* Definitions are only allowed on the top level and at the start of a body.
130 * If a definition is detected anywhere else, a 'Bad define placement' error
131 * is signalled. */
132static const char s_bad_define[] = "Bad define placement";
c86c440b 133
2a6f7afe
DH
134/* Case or cond expressions must have at least one clause. If a case or cond
135 * expression without any clauses is detected, a 'Missing clauses' error is
136 * signalled. */
137static const char s_missing_clauses[] = "Missing clauses";
138
609a8b86
DH
139/* If there is an 'else' clause in a case or a cond statement, it must be the
140 * last clause. If after the 'else' case clause further clauses are detected,
141 * a 'Misplaced else clause' error is signalled. */
142static const char s_misplaced_else_clause[] = "Misplaced else clause";
143
2a6f7afe
DH
144/* If a case clause is detected that is not in the format
145 * (<label(s)> <expression1> <expression2> ...)
146 * a 'Bad case clause' error is signalled. */
147static const char s_bad_case_clause[] = "Bad case clause";
148
2a6f7afe
DH
149/* If a case clause is detected where the <label(s)> element is neither a
150 * proper list nor (in case of the last clause) the syntactic keyword 'else',
151 * a 'Bad case labels' error is signalled. Note: If you encounter this error
152 * for an else-clause which seems to be syntactically correct, check if 'else'
153 * is really a syntactic keyword in that context. If 'else' is bound in the
154 * local or global environment, it is not considered a syntactic keyword, but
155 * will be treated as any other variable. */
156static const char s_bad_case_labels[] = "Bad case labels";
157
158/* In a case statement all labels have to be distinct. If in a case statement
159 * a label occurs more than once, a 'Duplicate case label' error is
160 * signalled. */
161static const char s_duplicate_case_label[] = "Duplicate case label";
162
609a8b86
DH
163/* If a cond clause is detected that is not in one of the formats
164 * (<test> <expression1> ...) or (else <expression1> <expression2> ...)
165 * a 'Bad cond clause' error is signalled. */
166static const char s_bad_cond_clause[] = "Bad cond clause";
167
168/* If a cond clause is detected that uses the alternate '=>' form, but does
169 * not hold a recipient element for the test result, a 'Missing recipient'
170 * error is signalled. */
171static const char s_missing_recipient[] = "Missing recipient in";
172
cc56ba80
DH
173/* If in a position where a variable name is required some other object is
174 * detected, a 'Bad variable' error is signalled. */
175static const char s_bad_variable[] = "Bad variable";
176
a954ce1d
DH
177/* Bindings for forms like 'let' and 'do' have to be given in a proper,
178 * possibly empty list. If any other object is detected in a place where a
179 * list of bindings was required, a 'Bad bindings' error is signalled. */
180static const char s_bad_bindings[] = "Bad bindings";
181
182/* Depending on the syntactic context, a binding has to be in the format
183 * (<variable> <expression>) or (<variable> <expression1> <expression2>).
184 * If anything else is detected in a place where a binding was expected, a
185 * 'Bad binding' error is signalled. */
186static const char s_bad_binding[] = "Bad binding";
187
4610b011
DH
188/* Some syntactic forms don't allow variable names to appear more than once in
189 * a list of bindings. If such a situation is nevertheless detected, a
190 * 'Duplicate binding' error is signalled. */
191static const char s_duplicate_binding[] = "Duplicate binding";
192
a954ce1d
DH
193/* If the exit form of a 'do' expression is not in the format
194 * (<test> <expression> ...)
195 * a 'Bad exit clause' error is signalled. */
196static const char s_bad_exit_clause[] = "Bad exit clause";
197
03a3e941
DH
198/* The formal function arguments of a lambda expression have to be either a
199 * single symbol or a non-cyclic list. For anything else a 'Bad formals'
200 * error is signalled. */
201static const char s_bad_formals[] = "Bad formals";
202
203/* If in a lambda expression something else than a symbol is detected at a
204 * place where a formal function argument is required, a 'Bad formal' error is
205 * signalled. */
206static const char s_bad_formal[] = "Bad formal";
207
208/* If in the arguments list of a lambda expression an argument name occurs
209 * more than once, a 'Duplicate formal' error is signalled. */
210static const char s_duplicate_formal[] = "Duplicate formal";
211
6f81708a
DH
212/* If the evaluation of an unquote-splicing expression gives something else
213 * than a proper list, a 'Non-list result for unquote-splicing' error is
214 * signalled. */
215static const char s_splicing[] = "Non-list result for unquote-splicing";
216
9a848baf
DH
217/* If something else than an exact integer is detected as the argument for
218 * @slot-ref and @slot-set!, a 'Bad slot number' error is signalled. */
219static const char s_bad_slot_number[] = "Bad slot number";
220
e6729603
DH
221
222/* Signal a syntax error. We distinguish between the form that caused the
223 * error and the enclosing expression. The error message will print out as
224 * shown in the following pattern. The file name and line number are only
225 * given when they can be determined from the erroneous form or from the
226 * enclosing expression.
227 *
228 * <filename>: In procedure memoization:
229 * <filename>: In file <name>, line <nr>: <error-message> in <expression>. */
230
231SCM_SYMBOL (syntax_error_key, "syntax-error");
232
233/* The prototype is needed to indicate that the function does not return. */
234static void
235syntax_error (const char* const, const SCM, const SCM) SCM_NORETURN;
236
237static void
238syntax_error (const char* const msg, const SCM form, const SCM expr)
239{
cc95e00a 240 SCM msg_string = scm_from_locale_string (msg);
e6729603
DH
241 SCM filename = SCM_BOOL_F;
242 SCM linenr = SCM_BOOL_F;
243 const char *format;
244 SCM args;
245
a61f4e0c 246 if (scm_is_pair (form))
e6729603
DH
247 {
248 filename = scm_source_property (form, scm_sym_filename);
249 linenr = scm_source_property (form, scm_sym_line);
250 }
251
a61f4e0c 252 if (scm_is_false (filename) && scm_is_false (linenr) && scm_is_pair (expr))
e6729603
DH
253 {
254 filename = scm_source_property (expr, scm_sym_filename);
255 linenr = scm_source_property (expr, scm_sym_line);
256 }
257
258 if (!SCM_UNBNDP (expr))
259 {
7888309b 260 if (scm_is_true (filename))
e6729603
DH
261 {
262 format = "In file ~S, line ~S: ~A ~S in expression ~S.";
263 args = scm_list_5 (filename, linenr, msg_string, form, expr);
264 }
7888309b 265 else if (scm_is_true (linenr))
e6729603
DH
266 {
267 format = "In line ~S: ~A ~S in expression ~S.";
268 args = scm_list_4 (linenr, msg_string, form, expr);
269 }
270 else
271 {
272 format = "~A ~S in expression ~S.";
273 args = scm_list_3 (msg_string, form, expr);
274 }
275 }
276 else
277 {
7888309b 278 if (scm_is_true (filename))
e6729603
DH
279 {
280 format = "In file ~S, line ~S: ~A ~S.";
281 args = scm_list_4 (filename, linenr, msg_string, form);
282 }
7888309b 283 else if (scm_is_true (linenr))
e6729603
DH
284 {
285 format = "In line ~S: ~A ~S.";
286 args = scm_list_3 (linenr, msg_string, form);
287 }
288 else
289 {
290 format = "~A ~S.";
291 args = scm_list_2 (msg_string, form);
292 }
293 }
294
295 scm_error (syntax_error_key, "memoization", format, args, SCM_BOOL_F);
296}
297
298
299/* Shortcut macros to simplify syntax error handling. */
9cc37597
LC
300#define ASSERT_SYNTAX(cond, message, form) \
301 { if (SCM_UNLIKELY (!(cond))) \
302 syntax_error (message, form, SCM_UNDEFINED); }
303#define ASSERT_SYNTAX_2(cond, message, form, expr) \
304 { if (SCM_UNLIKELY (!(cond))) \
305 syntax_error (message, form, expr); }
e6729603
DH
306
307\f
308
d0624e39
DH
309/* {Ilocs}
310 *
311 * Ilocs are memoized references to variables in local environment frames.
312 * They are represented as three values: The relative offset of the
313 * environment frame, the number of the binding within that frame, and a
314 * boolean value indicating whether the binding is the last binding in the
315 * frame.
a55c2b68
MV
316 *
317 * Frame numbers have 11 bits, relative offsets have 12 bits.
d0624e39 318 */
7e6e6b37 319
d0624e39 320#define SCM_ILOC00 SCM_MAKE_ITAG8(0L, scm_tc8_iloc)
7e6e6b37
DH
321#define SCM_IFRINC (0x00000100L)
322#define SCM_ICDR (0x00080000L)
d0624e39 323#define SCM_IDINC (0x00100000L)
7e6e6b37
DH
324#define SCM_IFRAME(n) ((long)((SCM_ICDR-SCM_IFRINC)>>8) \
325 & (SCM_UNPACK (n) >> 8))
326#define SCM_IDIST(n) (SCM_UNPACK (n) >> 20)
327#define SCM_ICDRP(n) (SCM_ICDR & SCM_UNPACK (n))
d0624e39 328#define SCM_IDSTMSK (-SCM_IDINC)
a55c2b68
MV
329#define SCM_IFRAMEMAX ((1<<11)-1)
330#define SCM_IDISTMAX ((1<<12)-1)
d0624e39
DH
331#define SCM_MAKE_ILOC(frame_nr, binding_nr, last_p) \
332 SCM_PACK ( \
333 ((frame_nr) << 8) \
334 + ((binding_nr) << 20) \
335 + ((last_p) ? SCM_ICDR : 0) \
336 + scm_tc8_iloc )
337
7e6e6b37
DH
338void
339scm_i_print_iloc (SCM iloc, SCM port)
340{
341 scm_puts ("#@", port);
342 scm_intprint ((long) SCM_IFRAME (iloc), 10, port);
343 scm_putc (SCM_ICDRP (iloc) ? '-' : '+', port);
344 scm_intprint ((long) SCM_IDIST (iloc), 10, port);
345}
346
d0624e39
DH
347#if (SCM_DEBUG_DEBUGGING_SUPPORT == 1)
348
349SCM scm_dbg_make_iloc (SCM frame, SCM binding, SCM cdrp);
90df793f 350
d0624e39
DH
351SCM_DEFINE (scm_dbg_make_iloc, "dbg-make-iloc", 3, 0, 0,
352 (SCM frame, SCM binding, SCM cdrp),
353 "Return a new iloc with frame offset @var{frame}, binding\n"
354 "offset @var{binding} and the cdr flag @var{cdrp}.")
355#define FUNC_NAME s_scm_dbg_make_iloc
356{
c3c97a34
KR
357 return SCM_MAKE_ILOC ((scm_t_bits) scm_to_unsigned_integer (frame, 0, SCM_IFRAMEMAX),
358 (scm_t_bits) scm_to_unsigned_integer (binding, 0, SCM_IDISTMAX),
7888309b 359 scm_is_true (cdrp));
d0624e39
DH
360}
361#undef FUNC_NAME
362
363SCM scm_dbg_iloc_p (SCM obj);
90df793f 364
d0624e39
DH
365SCM_DEFINE (scm_dbg_iloc_p, "dbg-iloc?", 1, 0, 0,
366 (SCM obj),
367 "Return @code{#t} if @var{obj} is an iloc.")
368#define FUNC_NAME s_scm_dbg_iloc_p
369{
7888309b 370 return scm_from_bool (SCM_ILOCP (obj));
d0624e39
DH
371}
372#undef FUNC_NAME
373
374#endif
375
376\f
377
7e6e6b37
DH
378/* {Evaluator byte codes (isyms)}
379 */
380
381#define ISYMNUM(n) (SCM_ITAG8_DATA (n))
382
383/* This table must agree with the list of SCM_IM_ constants in tags.h */
384static const char *const isymnames[] =
385{
386 "#@and",
387 "#@begin",
388 "#@case",
389 "#@cond",
390 "#@do",
391 "#@if",
392 "#@lambda",
393 "#@let",
394 "#@let*",
395 "#@letrec",
396 "#@or",
397 "#@quote",
398 "#@set!",
399 "#@define",
400 "#@apply",
401 "#@call-with-current-continuation",
402 "#@dispatch",
403 "#@slot-ref",
404 "#@slot-set!",
405 "#@delay",
406 "#@future",
407 "#@call-with-values",
408 "#@else",
409 "#@arrow",
410 "#@nil-cond",
411 "#@bind"
412};
413
414void
415scm_i_print_isym (SCM isym, SCM port)
416{
417 const size_t isymnum = ISYMNUM (isym);
418 if (isymnum < (sizeof isymnames / sizeof (char *)))
419 scm_puts (isymnames[isymnum], port);
420 else
421 scm_ipruk ("isym", isym, port);
422}
423
424\f
425
e5156567
DH
426/* The function lookup_symbol is used during memoization: Lookup the symbol in
427 * the environment. If there is no binding for the symbol, SCM_UNDEFINED is
57d23e25
DH
428 * returned. If the symbol is a global variable, the variable object to which
429 * the symbol is bound is returned. Finally, if the symbol is a local
430 * variable the corresponding iloc object is returned. */
6f81708a
DH
431
432/* A helper function for lookup_symbol: Try to find the symbol in the top
433 * level environment frame. The function returns SCM_UNDEFINED if the symbol
57d23e25
DH
434 * is unbound and it returns a variable object if the symbol is a global
435 * variable. */
6f81708a
DH
436static SCM
437lookup_global_symbol (const SCM symbol, const SCM top_level)
438{
439 const SCM variable = scm_sym2var (symbol, top_level, SCM_BOOL_F);
7888309b 440 if (scm_is_false (variable))
57d23e25 441 return SCM_UNDEFINED;
6f81708a 442 else
57d23e25 443 return variable;
6f81708a
DH
444}
445
446static SCM
447lookup_symbol (const SCM symbol, const SCM env)
448{
449 SCM frame_idx;
450 unsigned int frame_nr;
451
452 for (frame_idx = env, frame_nr = 0;
a61f4e0c 453 !scm_is_null (frame_idx);
6f81708a
DH
454 frame_idx = SCM_CDR (frame_idx), ++frame_nr)
455 {
456 const SCM frame = SCM_CAR (frame_idx);
a61f4e0c 457 if (scm_is_pair (frame))
6f81708a
DH
458 {
459 /* frame holds a local environment frame */
460 SCM symbol_idx;
461 unsigned int symbol_nr;
462
463 for (symbol_idx = SCM_CAR (frame), symbol_nr = 0;
a61f4e0c 464 scm_is_pair (symbol_idx);
6f81708a
DH
465 symbol_idx = SCM_CDR (symbol_idx), ++symbol_nr)
466 {
bc36d050 467 if (scm_is_eq (SCM_CAR (symbol_idx), symbol))
6f81708a
DH
468 /* found the symbol, therefore return the iloc */
469 return SCM_MAKE_ILOC (frame_nr, symbol_nr, 0);
470 }
bc36d050 471 if (scm_is_eq (symbol_idx, symbol))
6f81708a
DH
472 /* found the symbol as the last element of the current frame */
473 return SCM_MAKE_ILOC (frame_nr, symbol_nr, 1);
474 }
475 else
476 {
477 /* no more local environment frames */
478 return lookup_global_symbol (symbol, frame);
479 }
480 }
481
482 return lookup_global_symbol (symbol, SCM_BOOL_F);
483}
484
485
486/* Return true if the symbol is - from the point of view of a macro
487 * transformer - a literal in the sense specified in chapter "pattern
488 * language" of R5RS. In the code below, however, we don't match the
489 * definition of R5RS exactly: It returns true if the identifier has no
490 * binding or if it is a syntactic keyword. */
491static int
492literal_p (const SCM symbol, const SCM env)
493{
57d23e25
DH
494 const SCM variable = lookup_symbol (symbol, env);
495 if (SCM_UNBNDP (variable))
496 return 1;
497 if (SCM_VARIABLEP (variable) && SCM_MACROP (SCM_VARIABLE_REF (variable)))
6f81708a
DH
498 return 1;
499 else
500 return 0;
501}
17fa3fcf 502
5fb64383
DH
503
504/* Return true if the expression is self-quoting in the memoized code. Thus,
505 * some other objects (like e. g. vectors) are reported as self-quoting, which
506 * according to R5RS would need to be quoted. */
507static int
508is_self_quoting_p (const SCM expr)
509{
a61f4e0c 510 if (scm_is_pair (expr))
5fb64383 511 return 0;
cc95e00a 512 else if (scm_is_symbol (expr))
5fb64383 513 return 0;
a61f4e0c 514 else if (scm_is_null (expr))
5fb64383
DH
515 return 0;
516 else return 1;
517}
518
0f2d19dd 519
212e58ed
DH
520SCM_SYMBOL (sym_three_question_marks, "???");
521
522static SCM
523unmemoize_expression (const SCM expr, const SCM env)
524{
525 if (SCM_ILOCP (expr))
526 {
527 SCM frame_idx;
528 unsigned long int frame_nr;
529 SCM symbol_idx;
530 unsigned long int symbol_nr;
531
532 for (frame_idx = env, frame_nr = SCM_IFRAME (expr);
533 frame_nr != 0;
534 frame_idx = SCM_CDR (frame_idx), --frame_nr)
535 ;
536 for (symbol_idx = SCM_CAAR (frame_idx), symbol_nr = SCM_IDIST (expr);
537 symbol_nr != 0;
538 symbol_idx = SCM_CDR (symbol_idx), --symbol_nr)
539 ;
540 return SCM_ICDRP (expr) ? symbol_idx : SCM_CAR (symbol_idx);
541 }
542 else if (SCM_VARIABLEP (expr))
543 {
544 const SCM sym = scm_module_reverse_lookup (scm_env_module (env), expr);
7888309b 545 return scm_is_true (sym) ? sym : sym_three_question_marks;
212e58ed 546 }
4057a3e0 547 else if (scm_is_simple_vector (expr))
212e58ed
DH
548 {
549 return scm_list_2 (scm_sym_quote, expr);
550 }
a61f4e0c 551 else if (!scm_is_pair (expr))
212e58ed
DH
552 {
553 return expr;
554 }
555 else if (SCM_ISYMP (SCM_CAR (expr)))
556 {
557 return unmemoize_builtin_macro (expr, env);
558 }
559 else
560 {
561 return unmemoize_exprs (expr, env);
562 }
563}
564
565
566static SCM
567unmemoize_exprs (const SCM exprs, const SCM env)
568{
90df793f 569 SCM r_result = SCM_EOL;
9fcf3cbb 570 SCM expr_idx = exprs;
90df793f
DH
571 SCM um_expr;
572
573 /* Note that due to the current lazy memoizer we may find partially memoized
5fa0939c 574 * code during execution. In such code we have to expect improper lists of
90df793f
DH
575 * expressions: On the one hand, for such code syntax checks have not yet
576 * fully been performed, on the other hand, there may be even legal code
577 * like '(a . b) appear as an improper list of expressions as long as the
578 * quote expression is still in its unmemoized form. For this reason, the
579 * following code handles improper lists of expressions until memoization
580 * and execution have been completely separated. */
a61f4e0c 581 for (; scm_is_pair (expr_idx); expr_idx = SCM_CDR (expr_idx))
212e58ed
DH
582 {
583 const SCM expr = SCM_CAR (expr_idx);
5fa0939c
DH
584
585 /* In partially memoized code, lists of expressions that stem from a
586 * body form may start with an ISYM if the body itself has not yet been
587 * memoized. This isym is just an internal marker to indicate that the
588 * body still needs to be memoized. An isym may occur at the very
589 * beginning of the body or after one or more comment strings. It is
590 * dropped during unmemoization. */
591 if (!SCM_ISYMP (expr))
592 {
593 um_expr = unmemoize_expression (expr, env);
594 r_result = scm_cons (um_expr, r_result);
595 }
90df793f
DH
596 }
597 um_expr = unmemoize_expression (expr_idx, env);
a61f4e0c 598 if (!scm_is_null (r_result))
90df793f
DH
599 {
600 const SCM result = scm_reverse_x (r_result, SCM_UNDEFINED);
601 SCM_SETCDR (r_result, um_expr);
602 return result;
603 }
604 else
605 {
606 return um_expr;
212e58ed 607 }
212e58ed
DH
608}
609
610
34adf7ea
DH
611/* Rewrite the body (which is given as the list of expressions forming the
612 * body) into its internal form. The internal form of a body (<expr> ...) is
613 * just the body itself, but prefixed with an ISYM that denotes to what kind
614 * of outer construct this body belongs: (<ISYM> <expr> ...). A lambda body
615 * starts with SCM_IM_LAMBDA, for example, a body of a let starts with
6bff1368 616 * SCM_IM_LET, etc.
34adf7ea
DH
617 *
618 * It is assumed that the calling expression has already made sure that the
619 * body is a proper list. */
26d5b9b4 620static SCM
430b8401 621m_body (SCM op, SCM exprs)
26d5b9b4 622{
26d5b9b4 623 /* Don't add another ISYM if one is present already. */
34adf7ea
DH
624 if (SCM_ISYMP (SCM_CAR (exprs)))
625 return exprs;
626 else
627 return scm_cons (op, exprs);
26d5b9b4
MD
628}
629
1cc91f1b 630
57d23e25
DH
631/* The function m_expand_body memoizes a proper list of expressions forming a
632 * body. This function takes care of dealing with internal defines and
633 * transforming them into an equivalent letrec expression. The list of
634 * expressions is rewritten in place. */
910b5125 635
57d23e25
DH
636/* This is a helper function for m_expand_body. If the argument expression is
637 * a symbol that denotes a syntactic keyword, the corresponding macro object
638 * is returned, in all other cases the function returns SCM_UNDEFINED. */
910b5125
DH
639static SCM
640try_macro_lookup (const SCM expr, const SCM env)
641{
cc95e00a 642 if (scm_is_symbol (expr))
910b5125 643 {
57d23e25
DH
644 const SCM variable = lookup_symbol (expr, env);
645 if (SCM_VARIABLEP (variable))
646 {
647 const SCM value = SCM_VARIABLE_REF (variable);
648 if (SCM_MACROP (value))
649 return value;
650 }
910b5125 651 }
57d23e25
DH
652
653 return SCM_UNDEFINED;
910b5125
DH
654}
655
656/* This is a helper function for m_expand_body. It expands user macros,
657 * because for the correct translation of a body we need to know whether they
658 * expand to a definition. */
659static SCM
660expand_user_macros (SCM expr, const SCM env)
661{
a61f4e0c 662 while (scm_is_pair (expr))
910b5125
DH
663 {
664 const SCM car_expr = SCM_CAR (expr);
665 const SCM new_car = expand_user_macros (car_expr, env);
666 const SCM value = try_macro_lookup (new_car, env);
667
668 if (SCM_MACROP (value) && SCM_MACRO_TYPE (value) == 2)
669 {
670 /* User macros transform code into code. */
671 expr = scm_call_2 (SCM_MACRO_CODE (value), expr, env);
672 /* We need to reiterate on the transformed code. */
673 }
674 else
675 {
676 /* No user macro: return. */
677 SCM_SETCAR (expr, new_car);
678 return expr;
679 }
680 }
681
682 return expr;
683}
684
685/* This is a helper function for m_expand_body. It determines if a given form
686 * represents an application of a given built-in macro. The built-in macro to
687 * check for is identified by its syntactic keyword. The form is an
688 * application of the given macro if looking up the car of the form in the
689 * given environment actually returns the built-in macro. */
690static int
691is_system_macro_p (const SCM syntactic_keyword, const SCM form, const SCM env)
692{
a61f4e0c 693 if (scm_is_pair (form))
910b5125
DH
694 {
695 const SCM car_form = SCM_CAR (form);
696 const SCM value = try_macro_lookup (car_form, env);
697 if (SCM_BUILTIN_MACRO_P (value))
698 {
699 const SCM macro_name = scm_macro_name (value);
bc36d050 700 return scm_is_eq (macro_name, syntactic_keyword);
910b5125
DH
701 }
702 }
703
704 return 0;
705}
706
9d4bf6d3 707static void
910b5125
DH
708m_expand_body (const SCM forms, const SCM env)
709{
710 /* The first body form can be skipped since it is known to be the ISYM that
711 * was prepended to the body by m_body. */
712 SCM cdr_forms = SCM_CDR (forms);
713 SCM form_idx = cdr_forms;
714 SCM definitions = SCM_EOL;
715 SCM sequence = SCM_EOL;
716
717 /* According to R5RS, the list of body forms consists of two parts: a number
718 * (maybe zero) of definitions, followed by a non-empty sequence of
719 * expressions. Each the definitions and the expressions may be grouped
720 * arbitrarily with begin, but it is not allowed to mix definitions and
721 * expressions. The task of the following loop therefore is to split the
722 * list of body forms into the list of definitions and the sequence of
723 * expressions. */
a61f4e0c 724 while (!scm_is_null (form_idx))
910b5125
DH
725 {
726 const SCM form = SCM_CAR (form_idx);
727 const SCM new_form = expand_user_macros (form, env);
728 if (is_system_macro_p (scm_sym_define, new_form, env))
729 {
730 definitions = scm_cons (new_form, definitions);
731 form_idx = SCM_CDR (form_idx);
732 }
733 else if (is_system_macro_p (scm_sym_begin, new_form, env))
734 {
735 /* We have encountered a group of forms. This has to be either a
736 * (possibly empty) group of (possibly further grouped) definitions,
737 * or a non-empty group of (possibly further grouped)
738 * expressions. */
739 const SCM grouped_forms = SCM_CDR (new_form);
740 unsigned int found_definition = 0;
741 unsigned int found_expression = 0;
742 SCM grouped_form_idx = grouped_forms;
a61f4e0c 743 while (!found_expression && !scm_is_null (grouped_form_idx))
910b5125
DH
744 {
745 const SCM inner_form = SCM_CAR (grouped_form_idx);
746 const SCM new_inner_form = expand_user_macros (inner_form, env);
747 if (is_system_macro_p (scm_sym_define, new_inner_form, env))
748 {
749 found_definition = 1;
750 definitions = scm_cons (new_inner_form, definitions);
751 grouped_form_idx = SCM_CDR (grouped_form_idx);
752 }
753 else if (is_system_macro_p (scm_sym_begin, new_inner_form, env))
754 {
755 const SCM inner_group = SCM_CDR (new_inner_form);
756 grouped_form_idx
757 = scm_append (scm_list_2 (inner_group,
758 SCM_CDR (grouped_form_idx)));
759 }
760 else
761 {
762 /* The group marks the start of the expressions of the body.
763 * We have to make sure that within the same group we have
764 * not encountered a definition before. */
765 ASSERT_SYNTAX (!found_definition, s_mixed_body_forms, form);
766 found_expression = 1;
767 grouped_form_idx = SCM_EOL;
768 }
769 }
770
771 /* We have finished processing the group. If we have not yet
772 * encountered an expression we continue processing the forms of the
773 * body to collect further definition forms. Otherwise, the group
774 * marks the start of the sequence of expressions of the body. */
775 if (!found_expression)
776 {
777 form_idx = SCM_CDR (form_idx);
778 }
779 else
780 {
781 sequence = form_idx;
782 form_idx = SCM_EOL;
783 }
784 }
785 else
786 {
787 /* We have detected a form which is no definition. This marks the
788 * start of the sequence of expressions of the body. */
789 sequence = form_idx;
790 form_idx = SCM_EOL;
791 }
792 }
793
794 /* FIXME: forms does not hold information about the file location. */
a61f4e0c 795 ASSERT_SYNTAX (scm_is_pair (sequence), s_missing_body_expression, cdr_forms);
910b5125 796
a61f4e0c 797 if (!scm_is_null (definitions))
910b5125
DH
798 {
799 SCM definition_idx;
800 SCM letrec_tail;
801 SCM letrec_expression;
802 SCM new_letrec_expression;
910b5125
DH
803
804 SCM bindings = SCM_EOL;
805 for (definition_idx = definitions;
a61f4e0c 806 !scm_is_null (definition_idx);
910b5125
DH
807 definition_idx = SCM_CDR (definition_idx))
808 {
809 const SCM definition = SCM_CAR (definition_idx);
810 const SCM canonical_definition = canonicalize_define (definition);
811 const SCM binding = SCM_CDR (canonical_definition);
812 bindings = scm_cons (binding, bindings);
813 };
814
815 letrec_tail = scm_cons (bindings, sequence);
816 /* FIXME: forms does not hold information about the file location. */
817 letrec_expression = scm_cons_source (forms, scm_sym_letrec, letrec_tail);
818 new_letrec_expression = scm_m_letrec (letrec_expression, env);
9d4bf6d3
MV
819 SCM_SETCAR (forms, new_letrec_expression);
820 SCM_SETCDR (forms, SCM_EOL);
910b5125
DH
821 }
822 else
823 {
824 SCM_SETCAR (forms, SCM_CAR (sequence));
825 SCM_SETCDR (forms, SCM_CDR (sequence));
910b5125
DH
826 }
827}
828
2b189e65
MV
829static SCM
830macroexp (SCM x, SCM env)
831{
832 SCM res, proc, orig_sym;
833
834 /* Don't bother to produce error messages here. We get them when we
835 eventually execute the code for real. */
836
837 macro_tail:
838 orig_sym = SCM_CAR (x);
cc95e00a 839 if (!scm_is_symbol (orig_sym))
2b189e65
MV
840 return x;
841
842 {
843 SCM *proc_ptr = scm_lookupcar1 (x, env, 0);
844 if (proc_ptr == NULL)
845 {
846 /* We have lost the race. */
847 goto macro_tail;
848 }
849 proc = *proc_ptr;
850 }
851
852 /* Only handle memoizing macros. `Acros' and `macros' are really
853 special forms and should not be evaluated here. */
854
855 if (!SCM_MACROP (proc)
856 || (SCM_MACRO_TYPE (proc) != 2 && !SCM_BUILTIN_MACRO_P (proc)))
857 return x;
858
859 SCM_SETCAR (x, orig_sym); /* Undo memoizing effect of lookupcar */
860 res = scm_call_2 (SCM_MACRO_CODE (proc), x, env);
e08f3f7a 861
2b189e65 862 if (scm_ilength (res) <= 0)
e08f3f7a
LC
863 /* Result of expansion is not a list. */
864 return (scm_list_2 (SCM_IM_BEGIN, res));
865 else
866 {
867 /* njrev: Several queries here: (1) I don't see how it can be
868 correct that the SCM_SETCAR 2 lines below this comment needs
869 protection, but the SCM_SETCAR 6 lines above does not, so
870 something here is probably wrong. (2) macroexp() is now only
871 used in one place - scm_m_generalized_set_x - whereas all other
872 macro expansion happens through expand_user_macros. Therefore
873 (2.1) perhaps macroexp() could be eliminated completely now?
874 (2.2) Does expand_user_macros need any critical section
875 protection? */
876
877 SCM_CRITICAL_SECTION_START;
878 SCM_SETCAR (x, SCM_CAR (res));
879 SCM_SETCDR (x, SCM_CDR (res));
880 SCM_CRITICAL_SECTION_END;
881
882 goto macro_tail;
883 }
2b189e65 884}
910b5125 885
9fbee57e 886/* Start of the memoizers for the standard R5RS builtin macros. */
0f2d19dd
JB
887
888
3b88ed2a 889SCM_SYNTAX (s_and, "and", scm_i_makbimacro, scm_m_and);
8ea46249 890SCM_GLOBAL_SYMBOL (scm_sym_and, s_and);
1cc91f1b 891
8ea46249 892SCM
e6729603 893scm_m_and (SCM expr, SCM env SCM_UNUSED)
0f2d19dd 894{
e6729603
DH
895 const SCM cdr_expr = SCM_CDR (expr);
896 const long length = scm_ilength (cdr_expr);
897
898 ASSERT_SYNTAX (length >= 0, s_bad_expression, expr);
899
900 if (length == 0)
901 {
902 /* Special case: (and) is replaced by #t. */
903 return SCM_BOOL_T;
904 }
0f2d19dd 905 else
e6729603
DH
906 {
907 SCM_SETCAR (expr, SCM_IM_AND);
908 return expr;
909 }
0f2d19dd
JB
910}
911
212e58ed
DH
912static SCM
913unmemoize_and (const SCM expr, const SCM env)
914{
915 return scm_cons (scm_sym_and, unmemoize_exprs (SCM_CDR (expr), env));
916}
917
1cc91f1b 918
3b88ed2a 919SCM_SYNTAX (s_begin, "begin", scm_i_makbimacro, scm_m_begin);
9fbee57e 920SCM_GLOBAL_SYMBOL (scm_sym_begin, s_begin);
8ea46249
DH
921
922SCM
2a6f7afe 923scm_m_begin (SCM expr, SCM env SCM_UNUSED)
0f2d19dd 924{
2a6f7afe 925 const SCM cdr_expr = SCM_CDR (expr);
21628685
DH
926 /* Dirk:FIXME:: An empty begin clause is not generally allowed by R5RS.
927 * That means, there should be a distinction between uses of begin where an
928 * empty clause is OK and where it is not. */
2a6f7afe
DH
929 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
930
931 SCM_SETCAR (expr, SCM_IM_BEGIN);
932 return expr;
0f2d19dd
JB
933}
934
212e58ed
DH
935static SCM
936unmemoize_begin (const SCM expr, const SCM env)
937{
938 return scm_cons (scm_sym_begin, unmemoize_exprs (SCM_CDR (expr), env));
939}
940
0f2d19dd 941
3b88ed2a 942SCM_SYNTAX (s_case, "case", scm_i_makbimacro, scm_m_case);
8ea46249 943SCM_GLOBAL_SYMBOL (scm_sym_case, s_case);
6f81708a 944SCM_GLOBAL_SYMBOL (scm_sym_else, "else");
1cc91f1b 945
8ea46249 946SCM
2a6f7afe 947scm_m_case (SCM expr, SCM env)
0f2d19dd 948{
8ea46249 949 SCM clauses;
2a6f7afe
DH
950 SCM all_labels = SCM_EOL;
951
952 /* Check, whether 'else is a literal, i. e. not bound to a value. */
953 const int else_literal_p = literal_p (scm_sym_else, env);
954
955 const SCM cdr_expr = SCM_CDR (expr);
956 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
957 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 2, s_missing_clauses, expr);
958
959 clauses = SCM_CDR (cdr_expr);
a61f4e0c 960 while (!scm_is_null (clauses))
0f2d19dd 961 {
2a6f7afe
DH
962 SCM labels;
963
964 const SCM clause = SCM_CAR (clauses);
965 ASSERT_SYNTAX_2 (scm_ilength (clause) >= 2,
966 s_bad_case_clause, clause, expr);
967
968 labels = SCM_CAR (clause);
a61f4e0c 969 if (scm_is_pair (labels))
2a6f7afe
DH
970 {
971 ASSERT_SYNTAX_2 (scm_ilength (labels) >= 0,
972 s_bad_case_labels, labels, expr);
26ecfa39 973 all_labels = scm_append (scm_list_2 (labels, all_labels));
2a6f7afe 974 }
a61f4e0c 975 else if (scm_is_null (labels))
58a2510b
DH
976 {
977 /* The list of labels is empty. According to R5RS this is allowed.
978 * It means that the sequence of expressions will never be executed.
979 * Therefore, as an optimization, we could remove the whole
980 * clause. */
981 }
2a6f7afe
DH
982 else
983 {
bc36d050 984 ASSERT_SYNTAX_2 (scm_is_eq (labels, scm_sym_else) && else_literal_p,
2a6f7afe 985 s_bad_case_labels, labels, expr);
a61f4e0c 986 ASSERT_SYNTAX_2 (scm_is_null (SCM_CDR (clauses)),
609a8b86 987 s_misplaced_else_clause, clause, expr);
2a6f7afe
DH
988 }
989
990 /* build the new clause */
bc36d050 991 if (scm_is_eq (labels, scm_sym_else))
2a6f7afe
DH
992 SCM_SETCAR (clause, SCM_IM_ELSE);
993
8ea46249 994 clauses = SCM_CDR (clauses);
0f2d19dd 995 }
2a6f7afe
DH
996
997 /* Check whether all case labels are distinct. */
a61f4e0c 998 for (; !scm_is_null (all_labels); all_labels = SCM_CDR (all_labels))
2a6f7afe
DH
999 {
1000 const SCM label = SCM_CAR (all_labels);
7888309b 1001 ASSERT_SYNTAX_2 (scm_is_false (scm_c_memq (label, SCM_CDR (all_labels))),
4610b011 1002 s_duplicate_case_label, label, expr);
2a6f7afe
DH
1003 }
1004
1005 SCM_SETCAR (expr, SCM_IM_CASE);
1006 return expr;
0f2d19dd
JB
1007}
1008
212e58ed
DH
1009static SCM
1010unmemoize_case (const SCM expr, const SCM env)
1011{
1012 const SCM um_key_expr = unmemoize_expression (SCM_CADR (expr), env);
1013 SCM um_clauses = SCM_EOL;
1014 SCM clause_idx;
1015
1016 for (clause_idx = SCM_CDDR (expr);
a61f4e0c 1017 !scm_is_null (clause_idx);
212e58ed
DH
1018 clause_idx = SCM_CDR (clause_idx))
1019 {
1020 const SCM clause = SCM_CAR (clause_idx);
1021 const SCM labels = SCM_CAR (clause);
1022 const SCM exprs = SCM_CDR (clause);
1023
1024 const SCM um_exprs = unmemoize_exprs (exprs, env);
bc36d050 1025 const SCM um_labels = (scm_is_eq (labels, SCM_IM_ELSE))
212e58ed
DH
1026 ? scm_sym_else
1027 : scm_i_finite_list_copy (labels);
1028 const SCM um_clause = scm_cons (um_labels, um_exprs);
1029
1030 um_clauses = scm_cons (um_clause, um_clauses);
1031 }
1032 um_clauses = scm_reverse_x (um_clauses, SCM_UNDEFINED);
1033
1034 return scm_cons2 (scm_sym_case, um_key_expr, um_clauses);
1035}
1036
0f2d19dd 1037
3b88ed2a 1038SCM_SYNTAX (s_cond, "cond", scm_i_makbimacro, scm_m_cond);
8ea46249 1039SCM_GLOBAL_SYMBOL (scm_sym_cond, s_cond);
609a8b86 1040SCM_GLOBAL_SYMBOL (scm_sym_arrow, "=>");
1cc91f1b 1041
8ea46249 1042SCM
609a8b86 1043scm_m_cond (SCM expr, SCM env)
0f2d19dd 1044{
609a8b86
DH
1045 /* Check, whether 'else or '=> is a literal, i. e. not bound to a value. */
1046 const int else_literal_p = literal_p (scm_sym_else, env);
1047 const int arrow_literal_p = literal_p (scm_sym_arrow, env);
1048
1049 const SCM clauses = SCM_CDR (expr);
1050 SCM clause_idx;
1051
1052 ASSERT_SYNTAX (scm_ilength (clauses) >= 0, s_bad_expression, expr);
1053 ASSERT_SYNTAX (scm_ilength (clauses) >= 1, s_missing_clauses, expr);
1054
1055 for (clause_idx = clauses;
a61f4e0c 1056 !scm_is_null (clause_idx);
609a8b86 1057 clause_idx = SCM_CDR (clause_idx))
0f2d19dd 1058 {
609a8b86
DH
1059 SCM test;
1060
1061 const SCM clause = SCM_CAR (clause_idx);
1062 const long length = scm_ilength (clause);
1063 ASSERT_SYNTAX_2 (length >= 1, s_bad_cond_clause, clause, expr);
1064
1065 test = SCM_CAR (clause);
bc36d050 1066 if (scm_is_eq (test, scm_sym_else) && else_literal_p)
0f2d19dd 1067 {
a61f4e0c 1068 const int last_clause_p = scm_is_null (SCM_CDR (clause_idx));
609a8b86
DH
1069 ASSERT_SYNTAX_2 (length >= 2,
1070 s_bad_cond_clause, clause, expr);
1071 ASSERT_SYNTAX_2 (last_clause_p,
1072 s_misplaced_else_clause, clause, expr);
1073 SCM_SETCAR (clause, SCM_IM_ELSE);
0f2d19dd 1074 }
609a8b86 1075 else if (length >= 2
bc36d050 1076 && scm_is_eq (SCM_CADR (clause), scm_sym_arrow)
609a8b86
DH
1077 && arrow_literal_p)
1078 {
1079 ASSERT_SYNTAX_2 (length > 2, s_missing_recipient, clause, expr);
1080 ASSERT_SYNTAX_2 (length == 3, s_extra_expression, clause, expr);
1081 SCM_SETCAR (SCM_CDR (clause), SCM_IM_ARROW);
8ea46249 1082 }
1fe1fc0a
MV
1083 /* SRFI 61 extended cond */
1084 else if (length >= 3
1085 && scm_is_eq (SCM_CADDR (clause), scm_sym_arrow)
1086 && arrow_literal_p)
1087 {
1088 ASSERT_SYNTAX_2 (length > 3, s_missing_recipient, clause, expr);
1089 ASSERT_SYNTAX_2 (length == 4, s_extra_expression, clause, expr);
1090 SCM_SETCAR (SCM_CDDR (clause), SCM_IM_ARROW);
1091 }
0f2d19dd 1092 }
609a8b86
DH
1093
1094 SCM_SETCAR (expr, SCM_IM_COND);
1095 return expr;
0f2d19dd
JB
1096}
1097
212e58ed
DH
1098static SCM
1099unmemoize_cond (const SCM expr, const SCM env)
1100{
1101 SCM um_clauses = SCM_EOL;
1102 SCM clause_idx;
1103
1104 for (clause_idx = SCM_CDR (expr);
a61f4e0c 1105 !scm_is_null (clause_idx);
212e58ed
DH
1106 clause_idx = SCM_CDR (clause_idx))
1107 {
1108 const SCM clause = SCM_CAR (clause_idx);
1109 const SCM sequence = SCM_CDR (clause);
1110 const SCM test = SCM_CAR (clause);
1111 SCM um_test;
1112 SCM um_sequence;
1113 SCM um_clause;
1114
bc36d050 1115 if (scm_is_eq (test, SCM_IM_ELSE))
212e58ed
DH
1116 um_test = scm_sym_else;
1117 else
1118 um_test = unmemoize_expression (test, env);
1119
a61f4e0c 1120 if (!scm_is_null (sequence) && scm_is_eq (SCM_CAR (sequence),
bc36d050 1121 SCM_IM_ARROW))
212e58ed
DH
1122 {
1123 const SCM target = SCM_CADR (sequence);
1124 const SCM um_target = unmemoize_expression (target, env);
1125 um_sequence = scm_list_2 (scm_sym_arrow, um_target);
1126 }
1127 else
1128 {
1129 um_sequence = unmemoize_exprs (sequence, env);
1130 }
1131
1132 um_clause = scm_cons (um_test, um_sequence);
1133 um_clauses = scm_cons (um_clause, um_clauses);
1134 }
1135 um_clauses = scm_reverse_x (um_clauses, SCM_UNDEFINED);
1136
1137 return scm_cons (scm_sym_cond, um_clauses);
1138}
1139
1cc91f1b 1140
0f572ba7
DH
1141SCM_SYNTAX (s_define, "define", scm_i_makbimacro, scm_m_define);
1142SCM_GLOBAL_SYMBOL (scm_sym_define, s_define);
5280aaca 1143
9fbee57e
DH
1144/* Guile provides an extension to R5RS' define syntax to represent function
1145 * currying in a compact way. With this extension, it is allowed to write
1146 * (define <nested-variable> <body>), where <nested-variable> has of one of
1147 * the forms (<nested-variable> <formals>), (<nested-variable> . <formal>),
1148 * (<variable> <formals>) or (<variable> . <formal>). As in R5RS, <formals>
1149 * should be either a sequence of zero or more variables, or a sequence of one
1150 * or more variables followed by a space-delimited period and another
1151 * variable. Each level of argument nesting wraps the <body> within another
1152 * lambda expression. For example, the following forms are allowed, each one
1153 * followed by an equivalent, more explicit implementation.
1154 * Example 1:
1155 * (define ((a b . c) . d) <body>) is equivalent to
1156 * (define a (lambda (b . c) (lambda d <body>)))
1157 * Example 2:
1158 * (define (((a) b) c . d) <body>) is equivalent to
1159 * (define a (lambda () (lambda (b) (lambda (c . d) <body>))))
1160 */
1161/* Dirk:FIXME:: We should provide an implementation for 'define' in the R5RS
1162 * module that does not implement this extension. */
0f572ba7
DH
1163static SCM
1164canonicalize_define (const SCM expr)
5280aaca 1165{
cc56ba80
DH
1166 SCM body;
1167 SCM variable;
1168
1169 const SCM cdr_expr = SCM_CDR (expr);
c86c440b 1170 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
cc56ba80
DH
1171 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 2, s_missing_expression, expr);
1172
1173 body = SCM_CDR (cdr_expr);
1174 variable = SCM_CAR (cdr_expr);
a61f4e0c 1175 while (scm_is_pair (variable))
5280aaca 1176 {
cc56ba80
DH
1177 /* This while loop realizes function currying by variable nesting.
1178 * Variable is known to be a nested-variable. In every iteration of the
1179 * loop another level of lambda expression is created, starting with the
4610b011
DH
1180 * innermost one. Note that we don't check for duplicate formals here:
1181 * This will be done by the memoizer of the lambda expression. */
cc56ba80
DH
1182 const SCM formals = SCM_CDR (variable);
1183 const SCM tail = scm_cons (formals, body);
1184
1185 /* Add source properties to each new lambda expression: */
1186 const SCM lambda = scm_cons_source (variable, scm_sym_lambda, tail);
1187
1188 body = scm_list_1 (lambda);
1189 variable = SCM_CAR (variable);
5280aaca 1190 }
cc95e00a 1191 ASSERT_SYNTAX_2 (scm_is_symbol (variable), s_bad_variable, variable, expr);
cc56ba80
DH
1192 ASSERT_SYNTAX (scm_ilength (body) == 1, s_expression, expr);
1193
0f572ba7
DH
1194 SCM_SETCAR (cdr_expr, variable);
1195 SCM_SETCDR (cdr_expr, body);
1196 return expr;
1197}
1198
3dcf3373
LC
1199/* According to Section 5.2.1 of R5RS we first have to make sure that the
1200 variable is bound, and then perform the `(set! variable expression)'
1201 operation. However, EXPRESSION _can_ be evaluated before VARIABLE is
1202 bound. This means that EXPRESSION won't necessarily be able to assign
1203 values to VARIABLE as in `(define foo (begin (set! foo 1) (+ foo 1)))'. */
0f572ba7
DH
1204SCM
1205scm_m_define (SCM expr, SCM env)
1206{
6bff1368 1207 ASSERT_SYNTAX (SCM_TOP_LEVEL (env), s_bad_define, expr);
0f572ba7 1208
6bff1368
DH
1209 {
1210 const SCM canonical_definition = canonicalize_define (expr);
1211 const SCM cdr_canonical_definition = SCM_CDR (canonical_definition);
1212 const SCM variable = SCM_CAR (cdr_canonical_definition);
3dcf3373 1213 const SCM value = scm_eval_car (SCM_CDR (cdr_canonical_definition), env);
36245b66
DH
1214 const SCM location
1215 = scm_sym2var (variable, scm_env_top_level (env), SCM_BOOL_T);
6bff1368 1216
6bff1368
DH
1217 if (SCM_REC_PROCNAMES_P)
1218 {
1219 SCM tmp = value;
1220 while (SCM_MACROP (tmp))
1221 tmp = SCM_MACRO_CODE (tmp);
23d72566 1222 if (scm_is_true (scm_procedure_p (tmp))
6bff1368 1223 /* Only the first definition determines the name. */
7888309b 1224 && scm_is_false (scm_procedure_property (tmp, scm_sym_name)))
6bff1368
DH
1225 scm_set_procedure_property_x (tmp, scm_sym_name, variable);
1226 }
0f572ba7 1227
36245b66 1228 SCM_VARIABLE_SET (location, value);
6bff1368
DH
1229
1230 return SCM_UNSPECIFIED;
1231 }
0f2d19dd
JB
1232}
1233
1234
8ae95199
DH
1235/* This is a helper function for forms (<keyword> <expression>) that are
1236 * transformed into (#@<keyword> '() <memoized_expression>) in order to allow
1237 * for easy creation of a thunk (i. e. a closure without arguments) using the
1238 * ('() <memoized_expression>) tail of the memoized form. */
1239static SCM
1240memoize_as_thunk_prototype (const SCM expr, const SCM env SCM_UNUSED)
1241{
1242 const SCM cdr_expr = SCM_CDR (expr);
1243 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
1244 ASSERT_SYNTAX (scm_ilength (cdr_expr) == 1, s_expression, expr);
1245
1246 SCM_SETCDR (expr, scm_cons (SCM_EOL, cdr_expr));
1247
1248 return expr;
1249}
1250
1251
3b88ed2a 1252SCM_SYNTAX (s_delay, "delay", scm_i_makbimacro, scm_m_delay);
9fbee57e 1253SCM_GLOBAL_SYMBOL (scm_sym_delay, s_delay);
1cc91f1b 1254
9fbee57e
DH
1255/* Promises are implemented as closures with an empty parameter list. Thus,
1256 * (delay <expression>) is transformed into (#@delay '() <expression>), where
1257 * the empty list represents the empty parameter list. This representation
1258 * allows for easy creation of the closure during evaluation. */
8ea46249 1259SCM
8ae95199 1260scm_m_delay (SCM expr, SCM env)
0f2d19dd 1261{
8ae95199
DH
1262 const SCM new_expr = memoize_as_thunk_prototype (expr, env);
1263 SCM_SETCAR (new_expr, SCM_IM_DELAY);
1264 return new_expr;
0f2d19dd
JB
1265}
1266
212e58ed
DH
1267static SCM
1268unmemoize_delay (const SCM expr, const SCM env)
1269{
1270 const SCM thunk_expr = SCM_CADDR (expr);
acbfb594
NJ
1271 /* A promise is implemented as a closure, and when applying a
1272 closure the evaluator adds a new frame to the environment - even
1273 though, in the case of a promise, the added frame is always
1274 empty. We need to extend the environment here in the same way,
1275 so that any ILOCs in thunk_expr can be unmemoized correctly. */
1276 const SCM new_env = SCM_EXTEND_ENV (SCM_EOL, SCM_EOL, env);
1277 return scm_list_2 (scm_sym_delay, unmemoize_expression (thunk_expr, new_env));
212e58ed
DH
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
2f263a6a
MV
2096#if 0
2097
2098/* See futures.h for a comment why futures are not enabled.
2099 */
b0c5d67b 2100
3b88ed2a 2101SCM_SYNTAX (s_future, "future", scm_i_makbimacro, scm_m_future);
9fbee57e 2102SCM_GLOBAL_SYMBOL (scm_sym_future, s_future);
a513ead3 2103
9fbee57e
DH
2104/* Like promises, futures are implemented as closures with an empty
2105 * parameter list. Thus, (future <expression>) is transformed into
2106 * (#@future '() <expression>), where the empty list represents the
2107 * empty parameter list. This representation allows for easy creation
2108 * of the closure during evaluation. */
a513ead3 2109SCM
8ae95199 2110scm_m_future (SCM expr, SCM env)
a513ead3 2111{
8ae95199
DH
2112 const SCM new_expr = memoize_as_thunk_prototype (expr, env);
2113 SCM_SETCAR (new_expr, SCM_IM_FUTURE);
2114 return new_expr;
a513ead3
MV
2115}
2116
212e58ed
DH
2117static SCM
2118unmemoize_future (const SCM expr, const SCM env)
2119{
2120 const SCM thunk_expr = SCM_CADDR (expr);
2121 return scm_list_2 (scm_sym_future, unmemoize_expression (thunk_expr, env));
2122}
2123
39d27591 2124#endif /* futures disabled. */
9fbee57e 2125
3b88ed2a 2126SCM_SYNTAX (s_gset_x, "set!", scm_i_makbimacro, scm_m_generalized_set_x);
9fbee57e
DH
2127SCM_SYMBOL (scm_sym_setter, "setter");
2128
2129SCM
7893dbbf 2130scm_m_generalized_set_x (SCM expr, SCM env)
9fbee57e 2131{
7893dbbf 2132 SCM target, exp_target;
da48db62
DH
2133
2134 const SCM cdr_expr = SCM_CDR (expr);
2135 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
2136 ASSERT_SYNTAX (scm_ilength (cdr_expr) == 2, s_expression, expr);
2137
2138 target = SCM_CAR (cdr_expr);
a61f4e0c 2139 if (!scm_is_pair (target))
da48db62
DH
2140 {
2141 /* R5RS usage */
2142 return scm_m_set_x (expr, env);
2143 }
9fbee57e 2144 else
da48db62
DH
2145 {
2146 /* (set! (foo bar ...) baz) becomes ((setter foo) bar ... baz) */
7893dbbf
MV
2147 /* Macroexpanding the target might return things of the form
2148 (begin <atom>). In that case, <atom> must be a symbol or a
2149 variable and we memoize to (set! <atom> ...).
2150 */
2b189e65 2151 exp_target = macroexp (target, env);
bc36d050 2152 if (scm_is_eq (SCM_CAR (exp_target), SCM_IM_BEGIN)
a61f4e0c
MV
2153 && !scm_is_null (SCM_CDR (exp_target))
2154 && scm_is_null (SCM_CDDR (exp_target)))
7893dbbf
MV
2155 {
2156 exp_target= SCM_CADR (exp_target);
cc95e00a 2157 ASSERT_SYNTAX_2 (scm_is_symbol (exp_target)
6d1a2e9f
MV
2158 || SCM_VARIABLEP (exp_target),
2159 s_bad_variable, exp_target, expr);
7893dbbf
MV
2160 return scm_cons (SCM_IM_SET_X, scm_cons (exp_target,
2161 SCM_CDR (cdr_expr)));
2162 }
2163 else
2164 {
2165 const SCM setter_proc_tail = scm_list_1 (SCM_CAR (target));
2166 const SCM setter_proc = scm_cons_source (expr, scm_sym_setter,
2167 setter_proc_tail);
da48db62 2168
7893dbbf
MV
2169 const SCM cddr_expr = SCM_CDR (cdr_expr);
2170 const SCM setter_args = scm_append_x (scm_list_2 (SCM_CDR (target),
2171 cddr_expr));
da48db62 2172
7893dbbf
MV
2173 SCM_SETCAR (expr, setter_proc);
2174 SCM_SETCDR (expr, setter_args);
2175 return expr;
2176 }
da48db62 2177 }
9fbee57e
DH
2178}
2179
2180
a4aa2134
DH
2181/* @slot-ref is bound privately in the (oop goops) module from goops.c. As
2182 * soon as the module system allows us to more freely create bindings in
2183 * arbitrary modules during the startup phase, the code from goops.c should be
2184 * moved here. */
212e58ed
DH
2185
2186SCM_SYMBOL (sym_atslot_ref, "@slot-ref");
2187
9fbee57e 2188SCM
9a848baf 2189scm_m_atslot_ref (SCM expr, SCM env SCM_UNUSED)
9fbee57e 2190{
9a848baf
DH
2191 SCM slot_nr;
2192
2193 const SCM cdr_expr = SCM_CDR (expr);
2194 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
2195 ASSERT_SYNTAX (scm_ilength (cdr_expr) == 2, s_expression, expr);
2196 slot_nr = SCM_CADR (cdr_expr);
e11e83f3 2197 ASSERT_SYNTAX_2 (SCM_I_INUMP (slot_nr), s_bad_slot_number, slot_nr, expr);
9fbee57e 2198
9a848baf 2199 SCM_SETCAR (expr, SCM_IM_SLOT_REF);
e7313a9d 2200 SCM_SETCDR (cdr_expr, slot_nr);
9a848baf
DH
2201 return expr;
2202}
9fbee57e 2203
212e58ed
DH
2204static SCM
2205unmemoize_atslot_ref (const SCM expr, const SCM env)
2206{
2207 const SCM instance = SCM_CADR (expr);
2208 const SCM um_instance = unmemoize_expression (instance, env);
2209 const SCM slot_nr = SCM_CDDR (expr);
2210 return scm_list_3 (sym_atslot_ref, um_instance, slot_nr);
2211}
2212
9fbee57e 2213
a4aa2134
DH
2214/* @slot-set! is bound privately in the (oop goops) module from goops.c. As
2215 * soon as the module system allows us to more freely create bindings in
2216 * arbitrary modules during the startup phase, the code from goops.c should be
2217 * moved here. */
212e58ed
DH
2218
2219SCM_SYMBOL (sym_atslot_set_x, "@slot-set!");
2220
9fbee57e 2221SCM
9a848baf 2222scm_m_atslot_set_x (SCM expr, SCM env SCM_UNUSED)
9fbee57e 2223{
9a848baf
DH
2224 SCM slot_nr;
2225
2226 const SCM cdr_expr = SCM_CDR (expr);
2227 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
2228 ASSERT_SYNTAX (scm_ilength (cdr_expr) == 3, s_expression, expr);
2229 slot_nr = SCM_CADR (cdr_expr);
e11e83f3 2230 ASSERT_SYNTAX_2 (SCM_I_INUMP (slot_nr), s_bad_slot_number, slot_nr, expr);
9a848baf
DH
2231
2232 SCM_SETCAR (expr, SCM_IM_SLOT_SET_X);
2233 return expr;
9fbee57e 2234}
9fbee57e 2235
212e58ed
DH
2236static SCM
2237unmemoize_atslot_set_x (const SCM expr, const SCM env)
2238{
2239 const SCM cdr_expr = SCM_CDR (expr);
2240 const SCM instance = SCM_CAR (cdr_expr);
2241 const SCM um_instance = unmemoize_expression (instance, env);
2242 const SCM cddr_expr = SCM_CDR (cdr_expr);
2243 const SCM slot_nr = SCM_CAR (cddr_expr);
2244 const SCM cdddr_expr = SCM_CDR (cddr_expr);
2245 const SCM value = SCM_CAR (cdddr_expr);
2246 const SCM um_value = unmemoize_expression (value, env);
2247 return scm_list_4 (sym_atslot_set_x, um_instance, slot_nr, um_value);
2248}
2249
9fbee57e
DH
2250
2251#if SCM_ENABLE_ELISP
2252
70c1c108
DH
2253static const char s_defun[] = "Symbol's function definition is void";
2254
3b88ed2a 2255SCM_SYNTAX (s_nil_cond, "nil-cond", scm_i_makbimacro, scm_m_nil_cond);
9fbee57e 2256
70c1c108
DH
2257/* nil-cond expressions have the form
2258 * (nil-cond COND VAL COND VAL ... ELSEVAL) */
9fbee57e 2259SCM
70c1c108 2260scm_m_nil_cond (SCM expr, SCM env SCM_UNUSED)
9fbee57e 2261{
70c1c108
DH
2262 const long length = scm_ilength (SCM_CDR (expr));
2263 ASSERT_SYNTAX (length >= 0, s_bad_expression, expr);
2264 ASSERT_SYNTAX (length >= 1 && (length % 2) == 1, s_expression, expr);
2265
2266 SCM_SETCAR (expr, SCM_IM_NIL_COND);
2267 return expr;
9fbee57e
DH
2268}
2269
2270
3b88ed2a 2271SCM_SYNTAX (s_atfop, "@fop", scm_i_makbimacro, scm_m_atfop);
9fbee57e 2272
70c1c108
DH
2273/* The @fop-macro handles procedure and macro applications for elisp. The
2274 * input expression must have the form
2275 * (@fop <var> (transformer-macro <expr> ...))
2276 * where <var> must be a symbol. The expression is transformed into the
2277 * memoized form of either
2278 * (apply <un-aliased var> (transformer-macro <expr> ...))
2279 * if the value of var (across all aliasing) is not a macro, or
2280 * (<un-aliased var> <expr> ...)
2281 * if var is a macro. */
9fbee57e 2282SCM
70c1c108 2283scm_m_atfop (SCM expr, SCM env SCM_UNUSED)
9fbee57e 2284{
70c1c108
DH
2285 SCM location;
2286 SCM symbol;
2287
2288 const SCM cdr_expr = SCM_CDR (expr);
2289 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
2290 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 1, s_missing_expression, expr);
2291
2292 symbol = SCM_CAR (cdr_expr);
cc95e00a 2293 ASSERT_SYNTAX_2 (scm_is_symbol (symbol), s_bad_variable, symbol, expr);
70c1c108
DH
2294
2295 location = scm_symbol_fref (symbol);
2296 ASSERT_SYNTAX_2 (SCM_VARIABLEP (location), s_defun, symbol, expr);
2297
2298 /* The elisp function `defalias' allows to define aliases for symbols. To
2299 * look up such definitions, the chain of symbol definitions has to be
2300 * followed up to the terminal symbol. */
cc95e00a 2301 while (scm_is_symbol (SCM_VARIABLE_REF (location)))
9fbee57e 2302 {
70c1c108
DH
2303 const SCM alias = SCM_VARIABLE_REF (location);
2304 location = scm_symbol_fref (alias);
2305 ASSERT_SYNTAX_2 (SCM_VARIABLEP (location), s_defun, symbol, expr);
9fbee57e 2306 }
70c1c108
DH
2307
2308 /* Memoize the value location belonging to the terminal symbol. */
2309 SCM_SETCAR (cdr_expr, location);
2310
2311 if (!SCM_MACROP (SCM_VARIABLE_REF (location)))
9fbee57e 2312 {
70c1c108
DH
2313 /* Since the location does not contain a macro, the form is a procedure
2314 * application. Replace `@fop' by `@apply' and transform the expression
2315 * including the `transformer-macro'. */
2316 SCM_SETCAR (expr, SCM_IM_APPLY);
2317 return expr;
2318 }
2319 else
2320 {
2321 /* Since the location contains a macro, the arguments should not be
2322 * transformed, so the `transformer-macro' is cut out. The resulting
2323 * expression starts with the memoized variable, that is at the cdr of
2324 * the input expression. */
2325 SCM_SETCDR (cdr_expr, SCM_CDADR (cdr_expr));
2326 return cdr_expr;
9fbee57e 2327 }
9fbee57e
DH
2328}
2329
2330#endif /* SCM_ENABLE_ELISP */
2331
2332
212e58ed
DH
2333static SCM
2334unmemoize_builtin_macro (const SCM expr, const SCM env)
2335{
2336 switch (ISYMNUM (SCM_CAR (expr)))
2337 {
2338 case (ISYMNUM (SCM_IM_AND)):
2339 return unmemoize_and (expr, env);
2340
2341 case (ISYMNUM (SCM_IM_BEGIN)):
2342 return unmemoize_begin (expr, env);
2343
2344 case (ISYMNUM (SCM_IM_CASE)):
2345 return unmemoize_case (expr, env);
2346
2347 case (ISYMNUM (SCM_IM_COND)):
2348 return unmemoize_cond (expr, env);
2349
2350 case (ISYMNUM (SCM_IM_DELAY)):
2351 return unmemoize_delay (expr, env);
2352
2353 case (ISYMNUM (SCM_IM_DO)):
2354 return unmemoize_do (expr, env);
2355
2356 case (ISYMNUM (SCM_IM_IF)):
2357 return unmemoize_if (expr, env);
2358
2359 case (ISYMNUM (SCM_IM_LAMBDA)):
2360 return unmemoize_lambda (expr, env);
2361
2362 case (ISYMNUM (SCM_IM_LET)):
2363 return unmemoize_let (expr, env);
2364
2365 case (ISYMNUM (SCM_IM_LETREC)):
2366 return unmemoize_letrec (expr, env);
2367
2368 case (ISYMNUM (SCM_IM_LETSTAR)):
2369 return unmemoize_letstar (expr, env);
2370
2371 case (ISYMNUM (SCM_IM_OR)):
2372 return unmemoize_or (expr, env);
2373
2374 case (ISYMNUM (SCM_IM_QUOTE)):
2375 return unmemoize_quote (expr, env);
2376
2377 case (ISYMNUM (SCM_IM_SET_X)):
2378 return unmemoize_set_x (expr, env);
2379
2380 case (ISYMNUM (SCM_IM_APPLY)):
2381 return unmemoize_apply (expr, env);
2382
2383 case (ISYMNUM (SCM_IM_BIND)):
2384 return unmemoize_exprs (expr, env); /* FIXME */
2385
2386 case (ISYMNUM (SCM_IM_CONT)):
2387 return unmemoize_atcall_cc (expr, env);
2388
2389 case (ISYMNUM (SCM_IM_CALL_WITH_VALUES)):
2390 return unmemoize_at_call_with_values (expr, env);
2391
2f263a6a
MV
2392#if 0
2393 /* See futures.h for a comment why futures are not enabled.
2394 */
212e58ed
DH
2395 case (ISYMNUM (SCM_IM_FUTURE)):
2396 return unmemoize_future (expr, env);
2f263a6a 2397#endif
212e58ed
DH
2398
2399 case (ISYMNUM (SCM_IM_SLOT_REF)):
2400 return unmemoize_atslot_ref (expr, env);
2401
2402 case (ISYMNUM (SCM_IM_SLOT_SET_X)):
2403 return unmemoize_atslot_set_x (expr, env);
2404
2405 case (ISYMNUM (SCM_IM_NIL_COND)):
2406 return unmemoize_exprs (expr, env); /* FIXME */
2407
2408 default:
2409 return unmemoize_exprs (expr, env); /* FIXME */
2410 }
2411}
2412
2413
9fcf3cbb
DH
2414/* scm_i_unmemocopy_expr and scm_i_unmemocopy_body take a memoized expression
2415 * respectively a memoized body together with its environment and rewrite it
2416 * to its original form. Thus, these functions are the inversion of the
2417 * rewrite rules above. The procedure is not optimized for speed. It's used
2418 * in scm_i_unmemoize_expr, scm_procedure_source, macro_print and scm_iprin1.
212e58ed
DH
2419 *
2420 * Unmemoizing is not a reliable process. You cannot in general expect to get
2421 * the original source back.
2422 *
2423 * However, GOOPS currently relies on this for method compilation. This ought
2424 * to change. */
2425
2426SCM
9fcf3cbb
DH
2427scm_i_unmemocopy_expr (SCM expr, SCM env)
2428{
2429 const SCM source_properties = scm_whash_lookup (scm_source_whash, expr);
2430 const SCM um_expr = unmemoize_expression (expr, env);
2431
7888309b 2432 if (scm_is_true (source_properties))
9fcf3cbb
DH
2433 scm_whash_insert (scm_source_whash, um_expr, source_properties);
2434
2435 return um_expr;
2436}
2437
2438SCM
2439scm_i_unmemocopy_body (SCM forms, SCM env)
212e58ed
DH
2440{
2441 const SCM source_properties = scm_whash_lookup (scm_source_whash, forms);
2442 const SCM um_forms = unmemoize_exprs (forms, env);
2443
7888309b 2444 if (scm_is_true (source_properties))
212e58ed
DH
2445 scm_whash_insert (scm_source_whash, um_forms, source_properties);
2446
2447 return um_forms;
2448}
2449
2450
434f2f7a 2451#if (SCM_ENABLE_DEPRECATED == 1)
f58c472a 2452
434f2f7a
DH
2453/* Deprecated in guile 1.7.0 on 2003-11-09. */
2454SCM
2455scm_m_expand_body (SCM exprs, SCM env)
2456{
2457 scm_c_issue_deprecation_warning
2458 ("`scm_m_expand_body' is deprecated.");
2459 m_expand_body (exprs, env);
2460 return exprs;
2461}
f58c472a 2462
f58c472a
DH
2463
2464SCM_SYNTAX (s_undefine, "undefine", scm_makacro, scm_m_undefine);
2465
2466SCM
70c1c108 2467scm_m_undefine (SCM expr, SCM env)
f58c472a 2468{
70c1c108
DH
2469 SCM variable;
2470 SCM location;
2471
2472 const SCM cdr_expr = SCM_CDR (expr);
2473 ASSERT_SYNTAX (SCM_TOP_LEVEL (env), "Bad undefine placement in", expr);
2474 ASSERT_SYNTAX (scm_ilength (cdr_expr) >= 0, s_bad_expression, expr);
2475 ASSERT_SYNTAX (scm_ilength (cdr_expr) == 1, s_expression, expr);
2476
2b189e65
MV
2477 scm_c_issue_deprecation_warning
2478 ("`undefine' is deprecated.\n");
2479
70c1c108 2480 variable = SCM_CAR (cdr_expr);
cc95e00a 2481 ASSERT_SYNTAX_2 (scm_is_symbol (variable), s_bad_variable, variable, expr);
70c1c108 2482 location = scm_sym2var (variable, scm_env_top_level (env), SCM_BOOL_F);
7888309b 2483 ASSERT_SYNTAX_2 (scm_is_true (location)
70c1c108
DH
2484 && !SCM_UNBNDP (SCM_VARIABLE_REF (location)),
2485 "variable already unbound ", variable, expr);
2486 SCM_VARIABLE_SET (location, SCM_UNDEFINED);
f58c472a 2487 return SCM_UNSPECIFIED;
f58c472a
DH
2488}
2489
26d5b9b4
MD
2490SCM
2491scm_macroexp (SCM x, SCM env)
2492{
2b189e65
MV
2493 scm_c_issue_deprecation_warning
2494 ("`scm_macroexp' is deprecated.");
2495 return macroexp (x, env);
26d5b9b4 2496}
73b64342 2497
6f81708a
DH
2498#endif
2499
60a49842 2500
212e58ed 2501#if (SCM_ENABLE_DEPRECATED == 1)
26d5b9b4 2502
212e58ed
DH
2503SCM
2504scm_unmemocar (SCM form, SCM env)
8ea46249 2505{
212e58ed
DH
2506 scm_c_issue_deprecation_warning
2507 ("`scm_unmemocar' is deprecated.");
60a49842 2508
a61f4e0c 2509 if (!scm_is_pair (form))
60a49842
DH
2510 return form;
2511 else
2512 {
2513 SCM c = SCM_CAR (form);
2514 if (SCM_VARIABLEP (c))
2515 {
2516 SCM sym = scm_module_reverse_lookup (scm_env_module (env), c);
7888309b 2517 if (scm_is_false (sym))
60a49842
DH
2518 sym = sym_three_question_marks;
2519 SCM_SETCAR (form, sym);
2520 }
2521 else if (SCM_ILOCP (c))
2522 {
2523 unsigned long int ir;
2524
2525 for (ir = SCM_IFRAME (c); ir != 0; --ir)
2526 env = SCM_CDR (env);
2527 env = SCM_CAAR (env);
2528 for (ir = SCM_IDIST (c); ir != 0; --ir)
2529 env = SCM_CDR (env);
f62b9dff 2530
60a49842
DH
2531 SCM_SETCAR (form, SCM_ICDRP (c) ? env : SCM_CAR (env));
2532 }
2533 return form;
2534 }
2535}
2536
434f2f7a
DH
2537#endif
2538
6f81708a
DH
2539/*****************************************************************************/
2540/*****************************************************************************/
2541/* The definitions for execution start here. */
2542/*****************************************************************************/
2543/*****************************************************************************/
2544
2545SCM_GLOBAL_SYMBOL (scm_sym_enter_frame, "enter-frame");
2546SCM_GLOBAL_SYMBOL (scm_sym_apply_frame, "apply-frame");
2547SCM_GLOBAL_SYMBOL (scm_sym_exit_frame, "exit-frame");
72f19c26 2548SCM_GLOBAL_SYMBOL (scm_sym_memoize_symbol, "memoize-symbol");
6f81708a 2549SCM_GLOBAL_SYMBOL (scm_sym_trace, "trace");
7c9c0169 2550SCM_SYMBOL (sym_instead, "instead");
6f81708a
DH
2551
2552/* A function object to implement "apply" for non-closure functions. */
2553static SCM f_apply;
2554/* An endless list consisting of #<undefined> objects: */
2555static SCM undefineds;
2556
2557
2558int
6e8d25a6 2559scm_badargsp (SCM formals, SCM args)
0f2d19dd 2560{
a61f4e0c 2561 while (!scm_is_null (formals))
0f2d19dd 2562 {
a61f4e0c 2563 if (!scm_is_pair (formals))
ff467021 2564 return 0;
a61f4e0c 2565 if (scm_is_null (args))
ff467021 2566 return 1;
0f2d19dd
JB
2567 formals = SCM_CDR (formals);
2568 args = SCM_CDR (args);
2569 }
a61f4e0c 2570 return !scm_is_null (args) ? 1 : 0;
0f2d19dd 2571}
a392ee15 2572
0f2d19dd 2573\f
62360b89 2574
0ee05b85 2575/* The evaluator contains a plethora of EVAL symbols.
62360b89 2576 *
62360b89 2577 *
385609b9 2578 * SCM_I_EVALIM is used when it is known that the expression is an
62360b89 2579 * immediate. (This macro never calls an evaluator.)
434f2f7a 2580 *
0ee05b85 2581 * SCM_I_XEVAL evaluates an expression that is expected to have its symbols already
434f2f7a
DH
2582 * memoized. Expressions that are not of the form '(<form> <form> ...)' are
2583 * evaluated inline without calling an evaluator.
2584 *
0ee05b85
HWN
2585 * This macro uses ceval or deval depending on its 3rd argument.
2586 *
2587 * SCM_I_XEVALCAR evaluates the car of an expression 'X:(Y:<form> <form> ...)',
434f2f7a
DH
2588 * potentially replacing a symbol at the position Y:<form> by its memoized
2589 * variable. If Y:<form> is not of the form '(<form> <form> ...)', the
2590 * evaluation is performed inline without calling an evaluator.
62360b89 2591 *
0ee05b85 2592 * This macro uses ceval or deval depending on its 3rd argument.
62360b89 2593 *
62360b89
DH
2594 */
2595
385609b9 2596#define SCM_I_EVALIM2(x) \
bc36d050 2597 ((scm_is_eq ((x), SCM_EOL) \
62360b89
DH
2598 ? syntax_error (s_empty_combination, (x), SCM_UNDEFINED), 0 \
2599 : 0), \
2600 (x))
2601
385609b9 2602#define SCM_I_EVALIM(x, env) (SCM_ILOCP (x) \
434f2f7a 2603 ? *scm_ilookup ((x), (env)) \
385609b9 2604 : SCM_I_EVALIM2(x))
62360b89 2605
0ee05b85 2606#define SCM_I_XEVAL(x, env, debug_p) \
434f2f7a 2607 (SCM_IMP (x) \
385609b9 2608 ? SCM_I_EVALIM2 (x) \
434f2f7a
DH
2609 : (SCM_VARIABLEP (x) \
2610 ? SCM_VARIABLE_REF (x) \
a61f4e0c 2611 : (scm_is_pair (x) \
0ee05b85 2612 ? (debug_p \
434f2f7a
DH
2613 ? deval ((x), (env)) \
2614 : ceval ((x), (env))) \
2615 : (x))))
2616
0ee05b85 2617#define SCM_I_XEVALCAR(x, env, debug_p) \
434f2f7a 2618 (SCM_IMP (SCM_CAR (x)) \
385609b9 2619 ? SCM_I_EVALIM (SCM_CAR (x), (env)) \
434f2f7a
DH
2620 : (SCM_VARIABLEP (SCM_CAR (x)) \
2621 ? SCM_VARIABLE_REF (SCM_CAR (x)) \
a61f4e0c 2622 : (scm_is_pair (SCM_CAR (x)) \
0ee05b85 2623 ? (debug_p \
434f2f7a
DH
2624 ? deval (SCM_CAR (x), (env)) \
2625 : ceval (SCM_CAR (x), (env))) \
cc95e00a 2626 : (!scm_is_symbol (SCM_CAR (x)) \
434f2f7a
DH
2627 ? SCM_CAR (x) \
2628 : *scm_lookupcar ((x), (env), 1)))))
2629
d1138028 2630scm_i_pthread_mutex_t source_mutex;
62360b89
DH
2631
2632
e5156567
DH
2633/* Lookup a given local variable in an environment. The local variable is
2634 * given as an iloc, that is a triple <frame, binding, last?>, where frame
2635 * indicates the relative number of the environment frame (counting upwards
2636 * from the innermost environment frame), binding indicates the number of the
2637 * binding within the frame, and last? (which is extracted from the iloc using
2638 * the macro SCM_ICDRP) indicates whether the binding forms the binding at the
2639 * very end of the improper list of bindings. */
2640SCM *
2641scm_ilookup (SCM iloc, SCM env)
2642{
2643 unsigned int frame_nr = SCM_IFRAME (iloc);
2644 unsigned int binding_nr = SCM_IDIST (iloc);
2645 SCM frames = env;
2646 SCM bindings;
2647
2648 for (; 0 != frame_nr; --frame_nr)
2649 frames = SCM_CDR (frames);
2650
2651 bindings = SCM_CAR (frames);
2652 for (; 0 != binding_nr; --binding_nr)
2653 bindings = SCM_CDR (bindings);
2654
2655 if (SCM_ICDRP (iloc))
2656 return SCM_CDRLOC (bindings);
2657 return SCM_CARLOC (SCM_CDR (bindings));
2658}
2659
2660
2661SCM_SYMBOL (scm_unbound_variable_key, "unbound-variable");
2662
2663static void error_unbound_variable (SCM symbol) SCM_NORETURN;
2d0c133f
MV
2664static void error_defined_variable (SCM symbol) SCM_NORETURN;
2665
2666/* Call this for variables that are unfound.
2667 */
e5156567
DH
2668static void
2669error_unbound_variable (SCM symbol)
2670{
2671 scm_error (scm_unbound_variable_key, NULL,
2672 "Unbound variable: ~S",
2673 scm_list_1 (symbol), SCM_BOOL_F);
2674}
2675
2d0c133f
MV
2676/* Call this for variables that are found but contain SCM_UNDEFINED.
2677 */
2678static void
2679error_defined_variable (SCM symbol)
2680{
2681 /* We use the 'unbound-variable' key here as well, since it
2682 basically is the same kind of error, with a slight variation in
2683 the displayed message.
2684 */
2685 scm_error (scm_unbound_variable_key, NULL,
a03bad87 2686 "Variable used before given a value: ~S",
2d0c133f
MV
2687 scm_list_1 (symbol), SCM_BOOL_F);
2688}
2689
e5156567
DH
2690
2691/* The Lookup Car Race
2692 - by Eva Luator
2693
2694 Memoization of variables and special forms is done while executing
2695 the code for the first time. As long as there is only one thread
2696 everything is fine, but as soon as two threads execute the same
2697 code concurrently `for the first time' they can come into conflict.
2698
2699 This memoization includes rewriting variable references into more
2700 efficient forms and expanding macros. Furthermore, macro expansion
2701 includes `compiling' special forms like `let', `cond', etc. into
2702 tree-code instructions.
2703
2704 There shouldn't normally be a problem with memoizing local and
2705 global variable references (into ilocs and variables), because all
2706 threads will mutate the code in *exactly* the same way and (if I
2707 read the C code correctly) it is not possible to observe a half-way
2708 mutated cons cell. The lookup procedure can handle this
2709 transparently without any critical sections.
2710
2711 It is different with macro expansion, because macro expansion
2712 happens outside of the lookup procedure and can't be
2713 undone. Therefore the lookup procedure can't cope with it. It has
2714 to indicate failure when it detects a lost race and hope that the
2715 caller can handle it. Luckily, it turns out that this is the case.
2716
2717 An example to illustrate this: Suppose that the following form will
2718 be memoized concurrently by two threads
2719
2720 (let ((x 12)) x)
2721
2722 Let's first examine the lookup of X in the body. The first thread
2723 decides that it has to find the symbol "x" in the environment and
2724 starts to scan it. Then the other thread takes over and actually
2725 overtakes the first. It looks up "x" and substitutes an
2726 appropriate iloc for it. Now the first thread continues and
2727 completes its lookup. It comes to exactly the same conclusions as
2728 the second one and could - without much ado - just overwrite the
2729 iloc with the same iloc.
2730
2731 But let's see what will happen when the race occurs while looking
2732 up the symbol "let" at the start of the form. It could happen that
2733 the second thread interrupts the lookup of the first thread and not
2734 only substitutes a variable for it but goes right ahead and
2735 replaces it with the compiled form (#@let* (x 12) x). Now, when
2736 the first thread completes its lookup, it would replace the #@let*
2737 with a variable containing the "let" binding, effectively reverting
2738 the form to (let (x 12) x). This is wrong. It has to detect that
2739 it has lost the race and the evaluator has to reconsider the
2740 changed form completely.
2741
2742 This race condition could be resolved with some kind of traffic
2743 light (like mutexes) around scm_lookupcar, but I think that it is
2744 best to avoid them in this case. They would serialize memoization
2745 completely and because lookup involves calling arbitrary Scheme
2746 code (via the lookup-thunk), threads could be blocked for an
2747 arbitrary amount of time or even deadlock. But with the current
2748 solution a lot of unnecessary work is potentially done. */
2749
2750/* SCM_LOOKUPCAR1 is what SCM_LOOKUPCAR used to be but is allowed to
2751 return NULL to indicate a failed lookup due to some race conditions
2752 between threads. This only happens when VLOC is the first cell of
2753 a special form that will eventually be memoized (like `let', etc.)
2754 In that case the whole lookup is bogus and the caller has to
2755 reconsider the complete special form.
2756
2757 SCM_LOOKUPCAR is still there, of course. It just calls
2758 SCM_LOOKUPCAR1 and aborts on receiving NULL. So SCM_LOOKUPCAR
2759 should only be called when it is known that VLOC is not the first
2760 pair of a special form. Otherwise, use SCM_LOOKUPCAR1 and check
2761 for NULL. I think I've found the only places where this
2762 applies. */
2763
2764static SCM *
2765scm_lookupcar1 (SCM vloc, SCM genv, int check)
2766{
2767 SCM env = genv;
2768 register SCM *al, fl, var = SCM_CAR (vloc);
2769 register SCM iloc = SCM_ILOC00;
2770 for (; SCM_NIMP (env); env = SCM_CDR (env))
2771 {
a61f4e0c 2772 if (!scm_is_pair (SCM_CAR (env)))
e5156567
DH
2773 break;
2774 al = SCM_CARLOC (env);
2775 for (fl = SCM_CAR (*al); SCM_NIMP (fl); fl = SCM_CDR (fl))
2776 {
a61f4e0c 2777 if (!scm_is_pair (fl))
e5156567 2778 {
bc36d050 2779 if (scm_is_eq (fl, var))
e5156567 2780 {
bc36d050 2781 if (!scm_is_eq (SCM_CAR (vloc), var))
e5156567
DH
2782 goto race;
2783 SCM_SET_CELL_WORD_0 (vloc, SCM_UNPACK (iloc) + SCM_ICDR);
2784 return SCM_CDRLOC (*al);
2785 }
2786 else
2787 break;
2788 }
2789 al = SCM_CDRLOC (*al);
bc36d050 2790 if (scm_is_eq (SCM_CAR (fl), var))
e5156567
DH
2791 {
2792 if (SCM_UNBNDP (SCM_CAR (*al)))
2d0c133f 2793 error_defined_variable (var);
bc36d050 2794 if (!scm_is_eq (SCM_CAR (vloc), var))
e5156567
DH
2795 goto race;
2796 SCM_SETCAR (vloc, iloc);
2797 return SCM_CARLOC (*al);
2798 }
2799 iloc = SCM_PACK (SCM_UNPACK (iloc) + SCM_IDINC);
2800 }
2801 iloc = SCM_PACK ((~SCM_IDSTMSK) & (SCM_UNPACK(iloc) + SCM_IFRINC));
2802 }
2803 {
2804 SCM top_thunk, real_var;
2805 if (SCM_NIMP (env))
2806 {
2807 top_thunk = SCM_CAR (env); /* env now refers to a
2808 top level env thunk */
2809 env = SCM_CDR (env);
2810 }
2811 else
2812 top_thunk = SCM_BOOL_F;
2813 real_var = scm_sym2var (var, top_thunk, SCM_BOOL_F);
7888309b 2814 if (scm_is_false (real_var))
e5156567
DH
2815 goto errout;
2816
a61f4e0c 2817 if (!scm_is_null (env) || SCM_UNBNDP (SCM_VARIABLE_REF (real_var)))
e5156567
DH
2818 {
2819 errout:
2820 if (check)
2821 {
a61f4e0c 2822 if (scm_is_null (env))
e5156567
DH
2823 error_unbound_variable (var);
2824 else
2825 scm_misc_error (NULL, "Damaged environment: ~S",
2826 scm_list_1 (var));
2827 }
2828 else
2829 {
2830 /* A variable could not be found, but we shall
2831 not throw an error. */
2832 static SCM undef_object = SCM_UNDEFINED;
2833 return &undef_object;
2834 }
2835 }
2836
bc36d050 2837 if (!scm_is_eq (SCM_CAR (vloc), var))
e5156567
DH
2838 {
2839 /* Some other thread has changed the very cell we are working
2840 on. In effect, it must have done our job or messed it up
2841 completely. */
2842 race:
2843 var = SCM_CAR (vloc);
2844 if (SCM_VARIABLEP (var))
2845 return SCM_VARIABLE_LOC (var);
2846 if (SCM_ILOCP (var))
2847 return scm_ilookup (var, genv);
2848 /* We can't cope with anything else than variables and ilocs. When
2849 a special form has been memoized (i.e. `let' into `#@let') we
2850 return NULL and expect the calling function to do the right
2851 thing. For the evaluator, this means going back and redoing
2852 the dispatch on the car of the form. */
2853 return NULL;
2854 }
2855
2856 SCM_SETCAR (vloc, real_var);
2857 return SCM_VARIABLE_LOC (real_var);
2858 }
2859}
2860
2861SCM *
2862scm_lookupcar (SCM vloc, SCM genv, int check)
2863{
2864 SCM *loc = scm_lookupcar1 (vloc, genv, check);
2865 if (loc == NULL)
2866 abort ();
2867 return loc;
2868}
2869
2870
36245b66
DH
2871/* During execution, look up a symbol in the top level of the given local
2872 * environment and return the corresponding variable object. If no binding
2873 * for the symbol can be found, an 'Unbound variable' error is signalled. */
2874static SCM
2875lazy_memoize_variable (const SCM symbol, const SCM environment)
2876{
2877 const SCM top_level = scm_env_top_level (environment);
2878 const SCM variable = scm_sym2var (symbol, top_level, SCM_BOOL_F);
2879
7888309b 2880 if (scm_is_false (variable))
36245b66
DH
2881 error_unbound_variable (symbol);
2882 else
2883 return variable;
2884}
2885
2886
62360b89
DH
2887SCM
2888scm_eval_car (SCM pair, SCM env)
2889{
0ee05b85 2890 return SCM_I_XEVALCAR (pair, env, scm_debug_mode_p);
6dbd0af5 2891}
c4ac4d88 2892
d0b07b5d 2893
9de33deb
MD
2894SCM
2895scm_eval_body (SCM code, SCM env)
2896{
2897 SCM next;
434f2f7a 2898
9de33deb 2899 again:
01f11e02 2900 next = SCM_CDR (code);
a61f4e0c 2901 while (!scm_is_null (next))
9de33deb
MD
2902 {
2903 if (SCM_IMP (SCM_CAR (code)))
2904 {
2905 if (SCM_ISYMP (SCM_CAR (code)))
2906 {
cce0e9c8 2907 scm_dynwind_begin (0);
2b829bbb 2908 scm_i_dynwind_pthread_mutex_lock (&source_mutex);
9bc4701c
MD
2909 /* check for race condition */
2910 if (SCM_ISYMP (SCM_CAR (code)))
9d4bf6d3 2911 m_expand_body (code, env);
cce0e9c8 2912 scm_dynwind_end ();
9de33deb
MD
2913 goto again;
2914 }
2915 }
2916 else
0ee05b85 2917 SCM_I_XEVAL (SCM_CAR (code), env, scm_debug_mode_p);
9de33deb 2918 code = next;
01f11e02 2919 next = SCM_CDR (code);
9de33deb 2920 }
0ee05b85 2921 return SCM_I_XEVALCAR (code, env, scm_debug_mode_p);
9de33deb
MD
2922}
2923
0f2d19dd 2924
434f2f7a
DH
2925/* scm_last_debug_frame contains a pointer to the last debugging information
2926 * stack frame. It is accessed very often from the debugging evaluator, so it
2927 * should probably not be indirectly addressed. Better to save and restore it
2928 * from the current root at any stack swaps.
6dbd0af5
MD
2929 */
2930
6dbd0af5
MD
2931/* scm_debug_eframe_size is the number of slots available for pseudo
2932 * stack frames at each real stack frame.
2933 */
2934
c014a02e 2935long scm_debug_eframe_size;
6dbd0af5 2936
434f2f7a
DH
2937int scm_debug_mode_p;
2938int scm_check_entry_p;
2939int scm_check_apply_p;
2940int scm_check_exit_p;
72f19c26 2941int scm_check_memoize_p;
6dbd0af5 2942
c014a02e 2943long scm_eval_stack;
a74145b8 2944
92c2555f 2945scm_t_option scm_eval_opts[] = {
62560650
HWN
2946 { SCM_OPTION_INTEGER, "stack", 22000, "Size of thread stacks (in machine words)." },
2947 { 0 }
33b97402
MD
2948};
2949
92c2555f 2950scm_t_option scm_debug_opts[] = {
b7ff98dd 2951 { SCM_OPTION_BOOLEAN, "cheap", 1,
7c9c0169 2952 "*This option is now obsolete. Setting it has no effect." },
b7ff98dd
MD
2953 { SCM_OPTION_BOOLEAN, "breakpoints", 0, "*Check for breakpoints." },
2954 { SCM_OPTION_BOOLEAN, "trace", 0, "*Trace mode." },
2955 { SCM_OPTION_BOOLEAN, "procnames", 1,
2956 "Record procedure names at definition." },
2957 { SCM_OPTION_BOOLEAN, "backwards", 0,
2958 "Display backtrace in anti-chronological order." },
274dc5fd 2959 { SCM_OPTION_INTEGER, "width", 79, "Maximal width of backtrace." },
4e646a03
MD
2960 { SCM_OPTION_INTEGER, "indent", 10, "Maximal indentation in backtrace." },
2961 { SCM_OPTION_INTEGER, "frames", 3,
b7ff98dd 2962 "Maximum number of tail-recursive frames in backtrace." },
4e646a03
MD
2963 { SCM_OPTION_INTEGER, "maxdepth", 1000,
2964 "Maximal number of stored backtrace frames." },
2965 { SCM_OPTION_INTEGER, "depth", 20, "Maximal length of printed backtrace." },
11f77bfc
MD
2966 { SCM_OPTION_BOOLEAN, "backtrace", 0, "Show backtrace on error." },
2967 { SCM_OPTION_BOOLEAN, "debug", 0, "Use the debugging evaluator." },
0ee05b85 2968
863e833b 2969 { SCM_OPTION_INTEGER, "stack", 20000, "Stack size limit (measured in words; 0 = no check)." },
243ebb61
HWN
2970 { SCM_OPTION_SCM, "show-file-name", (unsigned long)SCM_BOOL_T,
2971 "Show file names and line numbers "
2972 "in backtraces when not `#f'. A value of `base' "
2973 "displays only base names, while `#t' displays full names."},
2974 { SCM_OPTION_BOOLEAN, "warn-deprecated", 0,
2975 "Warn when deprecated features are used." },
62560650 2976 { 0 },
6dbd0af5
MD
2977};
2978
62560650 2979
72f19c26 2980/*
0ee05b85
HWN
2981 * this ordering is awkward and illogical, but we maintain it for
2982 * compatibility. --hwn
2983 */
92c2555f 2984scm_t_option scm_evaluator_trap_table[] = {
b6d75948 2985 { SCM_OPTION_BOOLEAN, "traps", 0, "Enable evaluator traps." },
b7ff98dd
MD
2986 { SCM_OPTION_BOOLEAN, "enter-frame", 0, "Trap when eval enters new frame." },
2987 { SCM_OPTION_BOOLEAN, "apply-frame", 0, "Trap when entering apply." },
d95c0b76
NJ
2988 { SCM_OPTION_BOOLEAN, "exit-frame", 0, "Trap when exiting eval or apply." },
2989 { SCM_OPTION_SCM, "enter-frame-handler", (unsigned long)SCM_BOOL_F, "Handler for enter-frame traps." },
2990 { SCM_OPTION_SCM, "apply-frame-handler", (unsigned long)SCM_BOOL_F, "Handler for apply-frame traps." },
62560650 2991 { SCM_OPTION_SCM, "exit-frame-handler", (unsigned long)SCM_BOOL_F, "Handler for exit-frame traps." },
72f19c26
HWN
2992 { SCM_OPTION_BOOLEAN, "memoize-symbol", 0, "Trap when memoizing a symbol." },
2993 { SCM_OPTION_SCM, "memoize-symbol-handler", (unsigned long)SCM_BOOL_F, "The handler for memoization." },
62560650 2994 { 0 }
6dbd0af5
MD
2995};
2996
72f19c26 2997
a1ec6916 2998SCM_DEFINE (scm_eval_options_interface, "eval-options-interface", 0, 1, 0,
1bbd0b84 2999 (SCM setting),
b3f26b14
MG
3000 "Option interface for the evaluation options. Instead of using\n"
3001 "this procedure directly, use the procedures @code{eval-enable},\n"
3939e9df 3002 "@code{eval-disable}, @code{eval-set!} and @code{eval-options}.")
1bbd0b84 3003#define FUNC_NAME s_scm_eval_options_interface
33b97402
MD
3004{
3005 SCM ans;
876099d4 3006
661ae7ab
MV
3007 scm_dynwind_begin (0);
3008 scm_dynwind_critical_section (SCM_BOOL_F);
33b97402
MD
3009 ans = scm_options (setting,
3010 scm_eval_opts,
1bbd0b84 3011 FUNC_NAME);
a74145b8 3012 scm_eval_stack = SCM_EVAL_STACK * sizeof (void *);
661ae7ab 3013 scm_dynwind_end ();
876099d4 3014
33b97402
MD
3015 return ans;
3016}
1bbd0b84 3017#undef FUNC_NAME
33b97402 3018
d0b07b5d 3019
a1ec6916 3020SCM_DEFINE (scm_evaluator_traps, "evaluator-traps-interface", 0, 1, 0,
1bbd0b84 3021 (SCM setting),
b3f26b14 3022 "Option interface for the evaluator trap options.")
1bbd0b84 3023#define FUNC_NAME s_scm_evaluator_traps
33b97402
MD
3024{
3025 SCM ans;
72f19c26
HWN
3026
3027
3028 scm_options_try (setting,
3029 scm_evaluator_trap_table,
3030 FUNC_NAME, 1);
9de87eea 3031 SCM_CRITICAL_SECTION_START;
33b97402
MD
3032 ans = scm_options (setting,
3033 scm_evaluator_trap_table,
1bbd0b84 3034 FUNC_NAME);
72f19c26 3035
2b0fb0a5 3036 /* njrev: same again. */
33b97402 3037 SCM_RESET_DEBUG_MODE;
9de87eea 3038 SCM_CRITICAL_SECTION_END;
33b97402
MD
3039 return ans;
3040}
1bbd0b84 3041#undef FUNC_NAME
33b97402 3042
d0b07b5d 3043
0f2d19dd 3044
fdc28395 3045\f
d0b07b5d 3046
fdc28395
KN
3047/* Simple procedure calls
3048 */
3049
3050SCM
3051scm_call_0 (SCM proc)
3052{
3053 return scm_apply (proc, SCM_EOL, SCM_EOL);
3054}
3055
3056SCM
3057scm_call_1 (SCM proc, SCM arg1)
3058{
3059 return scm_apply (proc, arg1, scm_listofnull);
3060}
3061
3062SCM
3063scm_call_2 (SCM proc, SCM arg1, SCM arg2)
3064{
3065 return scm_apply (proc, arg1, scm_cons (arg2, scm_listofnull));
3066}
3067
3068SCM
3069scm_call_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3)
3070{
3071 return scm_apply (proc, arg1, scm_cons2 (arg2, arg3, scm_listofnull));
3072}
3073
d95c0b76
NJ
3074SCM
3075scm_call_4 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4)
3076{
3077 return scm_apply (proc, arg1, scm_cons2 (arg2, arg3,
3078 scm_cons (arg4, scm_listofnull)));
3079}
3080
fdc28395
KN
3081/* Simple procedure applies
3082 */
3083
3084SCM
3085scm_apply_0 (SCM proc, SCM args)
3086{
3087 return scm_apply (proc, args, SCM_EOL);
3088}
3089
3090SCM
3091scm_apply_1 (SCM proc, SCM arg1, SCM args)
3092{
3093 return scm_apply (proc, scm_cons (arg1, args), SCM_EOL);
3094}
3095
3096SCM
3097scm_apply_2 (SCM proc, SCM arg1, SCM arg2, SCM args)
3098{
3099 return scm_apply (proc, scm_cons2 (arg1, arg2, args), SCM_EOL);
3100}
3101
3102SCM
3103scm_apply_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM args)
3104{
3105 return scm_apply (proc, scm_cons (arg1, scm_cons2 (arg2, arg3, args)),
3106 SCM_EOL);
3107}
3108
82a2622a 3109/* This code processes the arguments to apply:
b145c172
JB
3110
3111 (apply PROC ARG1 ... ARGS)
3112
82a2622a
JB
3113 Given a list (ARG1 ... ARGS), this function conses the ARG1
3114 ... arguments onto the front of ARGS, and returns the resulting
3115 list. Note that ARGS is a list; thus, the argument to this
3116 function is a list whose last element is a list.
3117
3118 Apply calls this function, and applies PROC to the elements of the
b145c172
JB
3119 result. apply:nconc2last takes care of building the list of
3120 arguments, given (ARG1 ... ARGS).
3121
82a2622a
JB
3122 Rather than do new consing, apply:nconc2last destroys its argument.
3123 On that topic, this code came into my care with the following
3124 beautifully cryptic comment on that topic: "This will only screw
3125 you if you do (scm_apply scm_apply '( ... ))" If you know what
3126 they're referring to, send me a patch to this comment. */
b145c172 3127
3b3b36dd 3128SCM_DEFINE (scm_nconc2last, "apply:nconc2last", 1, 0, 0,
b3f26b14
MG
3129 (SCM lst),
3130 "Given a list (@var{arg1} @dots{} @var{args}), this function\n"
3131 "conses the @var{arg1} @dots{} arguments onto the front of\n"
3132 "@var{args}, and returns the resulting list. Note that\n"
3133 "@var{args} is a list; thus, the argument to this function is\n"
3134 "a list whose last element is a list.\n"
3135 "Note: Rather than do new consing, @code{apply:nconc2last}\n"
3136 "destroys its argument, so use with care.")
1bbd0b84 3137#define FUNC_NAME s_scm_nconc2last
0f2d19dd
JB
3138{
3139 SCM *lloc;
34d19ef6 3140 SCM_VALIDATE_NONEMPTYLIST (1, lst);
0f2d19dd 3141 lloc = &lst;
a61f4e0c 3142 while (!scm_is_null (SCM_CDR (*lloc))) /* Perhaps should be
c96d76b8
NJ
3143 SCM_NULL_OR_NIL_P, but not
3144 needed in 99.99% of cases,
3145 and it could seriously hurt
3146 performance. - Neil */
a23afe53 3147 lloc = SCM_CDRLOC (*lloc);
1bbd0b84 3148 SCM_ASSERT (scm_ilength (SCM_CAR (*lloc)) >= 0, lst, SCM_ARG1, FUNC_NAME);
0f2d19dd
JB
3149 *lloc = SCM_CAR (*lloc);
3150 return lst;
3151}
1bbd0b84 3152#undef FUNC_NAME
0f2d19dd 3153
0f2d19dd 3154
6dbd0af5
MD
3155
3156/* SECTION: The rest of this file is only read once.
3157 */
3158
504d99c5
MD
3159/* Trampolines
3160 *
3161 * Trampolines make it possible to move procedure application dispatch
3162 * outside inner loops. The motivation was clean implementation of
3163 * efficient replacements of R5RS primitives in SRFI-1.
3164 *
3165 * The semantics is clear: scm_trampoline_N returns an optimized
3166 * version of scm_call_N (or NULL if the procedure isn't applicable
3167 * on N args).
3168 *
3169 * Applying the optimization to map and for-each increased efficiency
3170 * noticeably. For example, (map abs ls) is now 8 times faster than
3171 * before.
3172 */
3173
756414cf
MD
3174static SCM
3175call_subr0_0 (SCM proc)
3176{
3177 return SCM_SUBRF (proc) ();
3178}
3179
3180static SCM
3181call_subr1o_0 (SCM proc)
3182{
3183 return SCM_SUBRF (proc) (SCM_UNDEFINED);
3184}
3185
3186static SCM
3187call_lsubr_0 (SCM proc)
3188{
3189 return SCM_SUBRF (proc) (SCM_EOL);
3190}
3191
3192SCM
3193scm_i_call_closure_0 (SCM proc)
3194{
6a3f13f0
DH
3195 const SCM env = SCM_EXTEND_ENV (SCM_CLOSURE_FORMALS (proc),
3196 SCM_EOL,
3197 SCM_ENV (proc));
3198 const SCM result = scm_eval_body (SCM_CLOSURE_BODY (proc), env);
d0b07b5d 3199 return result;
756414cf
MD
3200}
3201
3202scm_t_trampoline_0
3203scm_trampoline_0 (SCM proc)
3204{
2510c810
DH
3205 scm_t_trampoline_0 trampoline;
3206
756414cf 3207 if (SCM_IMP (proc))
d0b07b5d 3208 return NULL;
2510c810 3209
756414cf
MD
3210 switch (SCM_TYP7 (proc))
3211 {
3212 case scm_tc7_subr_0:
2510c810
DH
3213 trampoline = call_subr0_0;
3214 break;
756414cf 3215 case scm_tc7_subr_1o:
2510c810
DH
3216 trampoline = call_subr1o_0;
3217 break;
756414cf 3218 case scm_tc7_lsubr:
2510c810
DH
3219 trampoline = call_lsubr_0;
3220 break;
756414cf
MD
3221 case scm_tcs_closures:
3222 {
3223 SCM formals = SCM_CLOSURE_FORMALS (proc);
a61f4e0c 3224 if (scm_is_null (formals) || !scm_is_pair (formals))
2510c810 3225 trampoline = scm_i_call_closure_0;
756414cf 3226 else
d0b07b5d 3227 return NULL;
2510c810 3228 break;
756414cf
MD
3229 }
3230 case scm_tcs_struct:
3231 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
2510c810 3232 trampoline = scm_call_generic_0;
2ca0d207 3233 else if (SCM_I_OPERATORP (proc))
2510c810
DH
3234 trampoline = scm_call_0;
3235 else
3236 return NULL;
3237 break;
756414cf
MD
3238 case scm_tc7_smob:
3239 if (SCM_SMOB_APPLICABLE_P (proc))
2510c810 3240 trampoline = SCM_SMOB_DESCRIPTOR (proc).apply_0;
756414cf 3241 else
d0b07b5d 3242 return NULL;
2510c810 3243 break;
756414cf
MD
3244 case scm_tc7_asubr:
3245 case scm_tc7_rpsubr:
3246 case scm_tc7_cclo:
3247 case scm_tc7_pws:
2510c810
DH
3248 trampoline = scm_call_0;
3249 break;
756414cf 3250 default:
2510c810 3251 return NULL; /* not applicable on zero arguments */
756414cf 3252 }
2510c810
DH
3253 /* We only reach this point if a valid trampoline was determined. */
3254
3255 /* If debugging is enabled, we want to see all calls to proc on the stack.
3256 * Thus, we replace the trampoline shortcut with scm_call_0. */
434f2f7a 3257 if (scm_debug_mode_p)
2510c810
DH
3258 return scm_call_0;
3259 else
3260 return trampoline;
756414cf
MD
3261}
3262
504d99c5
MD
3263static SCM
3264call_subr1_1 (SCM proc, SCM arg1)
3265{
3266 return SCM_SUBRF (proc) (arg1);
3267}
3268
9ed24633
MD
3269static SCM
3270call_subr2o_1 (SCM proc, SCM arg1)
3271{
3272 return SCM_SUBRF (proc) (arg1, SCM_UNDEFINED);
3273}
3274
504d99c5
MD
3275static SCM
3276call_lsubr_1 (SCM proc, SCM arg1)
3277{
3278 return SCM_SUBRF (proc) (scm_list_1 (arg1));
3279}
3280
3281static SCM
3282call_dsubr_1 (SCM proc, SCM arg1)
3283{
e11e83f3 3284 if (SCM_I_INUMP (arg1))
504d99c5 3285 {
0ee05b85 3286 return (scm_from_double (SCM_DSUBRF (proc) ((double) SCM_I_INUM (arg1))));
504d99c5
MD
3287 }
3288 else if (SCM_REALP (arg1))
3289 {
0ee05b85 3290 return (scm_from_double (SCM_DSUBRF (proc) (SCM_REAL_VALUE (arg1))));
504d99c5 3291 }
504d99c5 3292 else if (SCM_BIGP (arg1))
f92e85f7 3293 {
0ee05b85 3294 return (scm_from_double (SCM_DSUBRF (proc) (scm_i_big2dbl (arg1))));
f92e85f7
MV
3295 }
3296 else if (SCM_FRACTIONP (arg1))
3297 {
0ee05b85 3298 return (scm_from_double (SCM_DSUBRF (proc) (scm_i_fraction2double (arg1))));
f92e85f7 3299 }
504d99c5 3300 SCM_WTA_DISPATCH_1 (*SCM_SUBR_GENERIC (proc), arg1,
cc95e00a 3301 SCM_ARG1, scm_i_symbol_chars (SCM_SNAME (proc)));
504d99c5
MD
3302}
3303
3304static SCM
3305call_cxr_1 (SCM proc, SCM arg1)
3306{
a61f4e0c 3307 return scm_i_chase_pairs (arg1, (scm_t_bits) SCM_SUBRF (proc));
504d99c5
MD
3308}
3309
3310static SCM
3311call_closure_1 (SCM proc, SCM arg1)
3312{
6a3f13f0
DH
3313 const SCM env = SCM_EXTEND_ENV (SCM_CLOSURE_FORMALS (proc),
3314 scm_list_1 (arg1),
3315 SCM_ENV (proc));
3316 const SCM result = scm_eval_body (SCM_CLOSURE_BODY (proc), env);
d0b07b5d 3317 return result;
504d99c5
MD
3318}
3319
3320scm_t_trampoline_1
3321scm_trampoline_1 (SCM proc)
3322{
2510c810
DH
3323 scm_t_trampoline_1 trampoline;
3324
504d99c5 3325 if (SCM_IMP (proc))
d0b07b5d 3326 return NULL;
2510c810 3327
504d99c5
MD
3328 switch (SCM_TYP7 (proc))
3329 {
3330 case scm_tc7_subr_1:
3331 case scm_tc7_subr_1o:
2510c810
DH
3332 trampoline = call_subr1_1;
3333 break;
9ed24633 3334 case scm_tc7_subr_2o:
2510c810
DH
3335 trampoline = call_subr2o_1;
3336 break;
504d99c5 3337 case scm_tc7_lsubr:
2510c810
DH
3338 trampoline = call_lsubr_1;
3339 break;
14b18ed6 3340 case scm_tc7_dsubr:
2510c810
DH
3341 trampoline = call_dsubr_1;
3342 break;
504d99c5 3343 case scm_tc7_cxr:
2510c810
DH
3344 trampoline = call_cxr_1;
3345 break;
504d99c5
MD
3346 case scm_tcs_closures:
3347 {
3348 SCM formals = SCM_CLOSURE_FORMALS (proc);
a61f4e0c
MV
3349 if (!scm_is_null (formals)
3350 && (!scm_is_pair (formals) || !scm_is_pair (SCM_CDR (formals))))
2510c810 3351 trampoline = call_closure_1;
504d99c5 3352 else
d0b07b5d 3353 return NULL;
2510c810 3354 break;
504d99c5
MD
3355 }
3356 case scm_tcs_struct:
3357 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
2510c810 3358 trampoline = scm_call_generic_1;
2ca0d207 3359 else if (SCM_I_OPERATORP (proc))
2510c810
DH
3360 trampoline = scm_call_1;
3361 else
3362 return NULL;
3363 break;
504d99c5
MD
3364 case scm_tc7_smob:
3365 if (SCM_SMOB_APPLICABLE_P (proc))
2510c810 3366 trampoline = SCM_SMOB_DESCRIPTOR (proc).apply_1;
504d99c5 3367 else
d0b07b5d 3368 return NULL;
2510c810 3369 break;
504d99c5
MD
3370 case scm_tc7_asubr:
3371 case scm_tc7_rpsubr:
3372 case scm_tc7_cclo:
3373 case scm_tc7_pws:
2510c810
DH
3374 trampoline = scm_call_1;
3375 break;
504d99c5 3376 default:
d0b07b5d 3377 return NULL; /* not applicable on one arg */
504d99c5 3378 }
2510c810
DH
3379 /* We only reach this point if a valid trampoline was determined. */
3380
3381 /* If debugging is enabled, we want to see all calls to proc on the stack.
3382 * Thus, we replace the trampoline shortcut with scm_call_1. */
434f2f7a 3383 if (scm_debug_mode_p)
2510c810
DH
3384 return scm_call_1;
3385 else
3386 return trampoline;
504d99c5
MD
3387}
3388
3389static SCM
3390call_subr2_2 (SCM proc, SCM arg1, SCM arg2)
3391{
3392 return SCM_SUBRF (proc) (arg1, arg2);
3393}
3394
9ed24633
MD
3395static SCM
3396call_lsubr2_2 (SCM proc, SCM arg1, SCM arg2)
3397{
3398 return SCM_SUBRF (proc) (arg1, arg2, SCM_EOL);
3399}
3400
504d99c5
MD
3401static SCM
3402call_lsubr_2 (SCM proc, SCM arg1, SCM arg2)
3403{
3404 return SCM_SUBRF (proc) (scm_list_2 (arg1, arg2));
3405}
3406
3407static SCM
3408call_closure_2 (SCM proc, SCM arg1, SCM arg2)
3409{
6a3f13f0
DH
3410 const SCM env = SCM_EXTEND_ENV (SCM_CLOSURE_FORMALS (proc),
3411 scm_list_2 (arg1, arg2),
3412 SCM_ENV (proc));
3413 const SCM result = scm_eval_body (SCM_CLOSURE_BODY (proc), env);
d0b07b5d 3414 return result;
504d99c5
MD
3415}
3416
3417scm_t_trampoline_2
3418scm_trampoline_2 (SCM proc)
3419{
2510c810
DH
3420 scm_t_trampoline_2 trampoline;
3421
504d99c5 3422 if (SCM_IMP (proc))
d0b07b5d 3423 return NULL;
2510c810 3424
504d99c5
MD
3425 switch (SCM_TYP7 (proc))
3426 {
3427 case scm_tc7_subr_2:
3428 case scm_tc7_subr_2o:
3429 case scm_tc7_rpsubr:
3430 case scm_tc7_asubr:
2510c810
DH
3431 trampoline = call_subr2_2;
3432 break;
9ed24633 3433 case scm_tc7_lsubr_2:
2510c810
DH
3434 trampoline = call_lsubr2_2;
3435 break;
504d99c5 3436 case scm_tc7_lsubr:
2510c810
DH
3437 trampoline = call_lsubr_2;
3438 break;
504d99c5
MD
3439 case scm_tcs_closures:
3440 {
3441 SCM formals = SCM_CLOSURE_FORMALS (proc);
a61f4e0c
MV
3442 if (!scm_is_null (formals)
3443 && (!scm_is_pair (formals)
3444 || (!scm_is_null (SCM_CDR (formals))
3445 && (!scm_is_pair (SCM_CDR (formals))
3446 || !scm_is_pair (SCM_CDDR (formals))))))
2510c810 3447 trampoline = call_closure_2;
504d99c5 3448 else
d0b07b5d 3449 return NULL;
2510c810 3450 break;
504d99c5
MD
3451 }
3452 case scm_tcs_struct:
3453 if (SCM_OBJ_CLASS_FLAGS (proc) & SCM_CLASSF_PURE_GENERIC)
2510c810 3454 trampoline = scm_call_generic_2;
2ca0d207 3455 else if (SCM_I_OPERATORP (proc))
2510c810
DH
3456 trampoline = scm_call_2;
3457 else
3458 return NULL;
3459 break;
504d99c5
MD
3460 case scm_tc7_smob:
3461 if (SCM_SMOB_APPLICABLE_P (proc))
2510c810 3462 trampoline = SCM_SMOB_DESCRIPTOR (proc).apply_2;
504d99c5 3463 else
d0b07b5d 3464 return NULL;
2510c810 3465 break;
504d99c5
MD
3466 case scm_tc7_cclo:
3467 case scm_tc7_pws:
2510c810
DH
3468 trampoline = scm_call_2;
3469 break;
504d99c5 3470 default:
d0b07b5d 3471 return NULL; /* not applicable on two args */
504d99c5 3472 }
2510c810
DH
3473 /* We only reach this point if a valid trampoline was determined. */
3474
3475 /* If debugging is enabled, we want to see all calls to proc on the stack.
3476 * Thus, we replace the trampoline shortcut with scm_call_2. */
434f2f7a 3477 if (scm_debug_mode_p)
2510c810
DH
3478 return scm_call_2;
3479 else
3480 return trampoline;
504d99c5
MD
3481}
3482
d9c393f5
JB
3483/* Typechecking for multi-argument MAP and FOR-EACH.
3484
47c3f06d 3485 Verify that each element of the vector ARGV, except for the first,
d9c393f5 3486 is a proper list whose length is LEN. Attribute errors to WHO,
47c3f06d 3487 and claim that the i'th element of ARGV is WHO's i+2'th argument. */
d9c393f5 3488static inline void
47c3f06d 3489check_map_args (SCM argv,
c014a02e 3490 long len,
47c3f06d
MD
3491 SCM gf,
3492 SCM proc,
3493 SCM args,
3494 const char *who)
d9c393f5 3495{
c014a02e 3496 long i;
d9c393f5 3497
4057a3e0 3498 for (i = SCM_SIMPLE_VECTOR_LENGTH (argv) - 1; i >= 1; i--)
d9c393f5 3499 {
4057a3e0
MV
3500 SCM elt = SCM_SIMPLE_VECTOR_REF (argv, i);
3501 long elt_len = scm_ilength (elt);
d9c393f5
JB
3502
3503 if (elt_len < 0)
47c3f06d
MD
3504 {
3505 if (gf)
3506 scm_apply_generic (gf, scm_cons (proc, args));
3507 else
4057a3e0 3508 scm_wrong_type_arg (who, i + 2, elt);
47c3f06d 3509 }
d9c393f5
JB
3510
3511 if (elt_len != len)
4057a3e0 3512 scm_out_of_range_pos (who, elt, scm_from_long (i + 2));
d9c393f5 3513 }
d9c393f5
JB
3514}
3515
3516
47c3f06d 3517SCM_GPROC (s_map, "map", 2, 0, 1, scm_map, g_map);
1cc91f1b 3518
368bf056
MD
3519/* Note: Currently, scm_map applies PROC to the argument list(s)
3520 sequentially, starting with the first element(s). This is used in
8878f040 3521 evalext.c where the Scheme procedure `map-in-order', which guarantees
368bf056 3522 sequential behaviour, is implemented using scm_map. If the
8878f040 3523 behaviour changes, we need to update `map-in-order'.
368bf056
MD
3524*/
3525
0f2d19dd 3526SCM
1bbd0b84 3527scm_map (SCM proc, SCM arg1, SCM args)
af45e3b0 3528#define FUNC_NAME s_map
0f2d19dd 3529{
c014a02e 3530 long i, len;
0f2d19dd
JB
3531 SCM res = SCM_EOL;
3532 SCM *pres = &res;
0f2d19dd 3533
d9c393f5 3534 len = scm_ilength (arg1);
47c3f06d
MD
3535 SCM_GASSERTn (len >= 0,
3536 g_map, scm_cons2 (proc, arg1, args), SCM_ARG2, s_map);
af45e3b0 3537 SCM_VALIDATE_REST_ARGUMENT (args);
a61f4e0c 3538 if (scm_is_null (args))
0f2d19dd 3539 {
504d99c5
MD
3540 scm_t_trampoline_1 call = scm_trampoline_1 (proc);
3541 SCM_GASSERT2 (call, g_map, proc, arg1, SCM_ARG1, s_map);
3542 while (SCM_NIMP (arg1))
3543 {
3544 *pres = scm_list_1 (call (proc, SCM_CAR (arg1)));
3545 pres = SCM_CDRLOC (*pres);
3546 arg1 = SCM_CDR (arg1);
3547 }
3548 return res;
3549 }
a61f4e0c 3550 if (scm_is_null (SCM_CDR (args)))
504d99c5
MD
3551 {
3552 SCM arg2 = SCM_CAR (args);
3553 int len2 = scm_ilength (arg2);
3554 scm_t_trampoline_2 call = scm_trampoline_2 (proc);
3555 SCM_GASSERTn (call,
3556 g_map, scm_cons2 (proc, arg1, args), SCM_ARG1, s_map);
3557 SCM_GASSERTn (len2 >= 0,
3558 g_map, scm_cons2 (proc, arg1, args), SCM_ARG3, s_map);
3559 if (len2 != len)
3560 SCM_OUT_OF_RANGE (3, arg2);
0f2d19dd
JB
3561 while (SCM_NIMP (arg1))
3562 {
504d99c5 3563 *pres = scm_list_1 (call (proc, SCM_CAR (arg1), SCM_CAR (arg2)));
a23afe53 3564 pres = SCM_CDRLOC (*pres);
0f2d19dd 3565 arg1 = SCM_CDR (arg1);
504d99c5 3566 arg2 = SCM_CDR (arg2);
0f2d19dd
JB
3567 }
3568 return res;
3569 }
05b15362
DH
3570 arg1 = scm_cons (arg1, args);
3571 args = scm_vector (arg1);
47c3f06d 3572 check_map_args (args, len, g_map, proc, arg1, s_map);
0f2d19dd
JB
3573 while (1)
3574 {
3575 arg1 = SCM_EOL;
4057a3e0 3576 for (i = SCM_SIMPLE_VECTOR_LENGTH (args) - 1; i >= 0; i--)
0f2d19dd 3577 {
4057a3e0
MV
3578 SCM elt = SCM_SIMPLE_VECTOR_REF (args, i);
3579 if (SCM_IMP (elt))
d9c393f5 3580 return res;
4057a3e0
MV
3581 arg1 = scm_cons (SCM_CAR (elt), arg1);
3582 SCM_SIMPLE_VECTOR_SET (args, i, SCM_CDR (elt));
0f2d19dd 3583 }
8ea46249 3584 *pres = scm_list_1 (scm_apply (proc, arg1, SCM_EOL));
a23afe53 3585 pres = SCM_CDRLOC (*pres);
0f2d19dd
JB
3586 }
3587}
af45e3b0 3588#undef FUNC_NAME
0f2d19dd
JB
3589
3590
47c3f06d 3591SCM_GPROC (s_for_each, "for-each", 2, 0, 1, scm_for_each, g_for_each);
1cc91f1b 3592
0f2d19dd 3593SCM
1bbd0b84 3594scm_for_each (SCM proc, SCM arg1, SCM args)
af45e3b0 3595#define FUNC_NAME s_for_each
0f2d19dd 3596{
c014a02e 3597 long i, len;
d9c393f5 3598 len = scm_ilength (arg1);
47c3f06d
MD
3599 SCM_GASSERTn (len >= 0, g_for_each, scm_cons2 (proc, arg1, args),
3600 SCM_ARG2, s_for_each);
af45e3b0 3601 SCM_VALIDATE_REST_ARGUMENT (args);
a61f4e0c 3602 if (scm_is_null (args))
0f2d19dd 3603 {
504d99c5
MD
3604 scm_t_trampoline_1 call = scm_trampoline_1 (proc);
3605 SCM_GASSERT2 (call, g_for_each, proc, arg1, SCM_ARG1, s_for_each);
3606 while (SCM_NIMP (arg1))
3607 {
3608 call (proc, SCM_CAR (arg1));
3609 arg1 = SCM_CDR (arg1);
3610 }
3611 return SCM_UNSPECIFIED;
3612 }
a61f4e0c 3613 if (scm_is_null (SCM_CDR (args)))
504d99c5
MD
3614 {
3615 SCM arg2 = SCM_CAR (args);
3616 int len2 = scm_ilength (arg2);
3617 scm_t_trampoline_2 call = scm_trampoline_2 (proc);
3618 SCM_GASSERTn (call, g_for_each,
3619 scm_cons2 (proc, arg1, args), SCM_ARG1, s_for_each);
3620 SCM_GASSERTn (len2 >= 0, g_for_each,
3621 scm_cons2 (proc, arg1, args), SCM_ARG3, s_for_each);
3622 if (len2 != len)
3623 SCM_OUT_OF_RANGE (3, arg2);
c96d76b8 3624 while (SCM_NIMP (arg1))
0f2d19dd 3625 {
504d99c5 3626 call (proc, SCM_CAR (arg1), SCM_CAR (arg2));
0f2d19dd 3627 arg1 = SCM_CDR (arg1);
504d99c5 3628 arg2 = SCM_CDR (arg2);
0f2d19dd
JB
3629 }
3630 return SCM_UNSPECIFIED;
3631 }
05b15362
DH
3632 arg1 = scm_cons (arg1, args);
3633 args = scm_vector (arg1);
47c3f06d 3634 check_map_args (args, len, g_for_each, proc, arg1, s_for_each);
0f2d19dd
JB
3635 while (1)
3636 {
3637 arg1 = SCM_EOL;
4057a3e0 3638 for (i = SCM_SIMPLE_VECTOR_LENGTH (args) - 1; i >= 0; i--)
0f2d19dd 3639 {
4057a3e0
MV
3640 SCM elt = SCM_SIMPLE_VECTOR_REF (args, i);
3641 if (SCM_IMP (elt))
c96d76b8 3642 return SCM_UNSPECIFIED;
4057a3e0
MV
3643 arg1 = scm_cons (SCM_CAR (elt), arg1);
3644 SCM_SIMPLE_VECTOR_SET (args, i, SCM_CDR (elt));
0f2d19dd
JB
3645 }
3646 scm_apply (proc, arg1, SCM_EOL);
3647 }
3648}
af45e3b0 3649#undef FUNC_NAME
0f2d19dd 3650
1cc91f1b 3651
0f2d19dd 3652SCM
6e8d25a6 3653scm_closure (SCM code, SCM env)
0f2d19dd 3654{
16d4699b
MV
3655 SCM z;
3656 SCM closcar = scm_cons (code, SCM_EOL);
3db825b0
LC
3657 z = scm_immutable_cell (SCM_UNPACK (closcar) + scm_tc3_closure,
3658 (scm_t_bits) env);
16d4699b 3659 scm_remember_upto_here (closcar);
0f2d19dd
JB
3660 return z;
3661}
3662
3663
92c2555f 3664scm_t_bits scm_tc16_promise;
1cc91f1b 3665
0f2d19dd 3666SCM
6e8d25a6 3667scm_makprom (SCM code)
0f2d19dd 3668{
28d52ebb
MD
3669 SCM_RETURN_NEWSMOB2 (scm_tc16_promise,
3670 SCM_UNPACK (code),
9de87eea
MV
3671 scm_make_recursive_mutex ());
3672}
3673
1cc91f1b 3674
0f2d19dd 3675static int
e841c3e0 3676promise_print (SCM exp, SCM port, scm_print_state *pstate)
0f2d19dd 3677{
19402679 3678 int writingp = SCM_WRITINGP (pstate);
b7f3516f 3679 scm_puts ("#<promise ", port);
19402679 3680 SCM_SET_WRITINGP (pstate, 1);
28d52ebb 3681 scm_iprin1 (SCM_PROMISE_DATA (exp), port, pstate);
19402679 3682 SCM_SET_WRITINGP (pstate, writingp);
b7f3516f 3683 scm_putc ('>', port);
0f2d19dd
JB
3684 return !0;
3685}
3686
3b3b36dd 3687SCM_DEFINE (scm_force, "force", 1, 0, 0,
28d52ebb 3688 (SCM promise),
67e8151b
MG
3689 "If the promise @var{x} has not been computed yet, compute and\n"
3690 "return @var{x}, otherwise just return the previously computed\n"
3691 "value.")
1bbd0b84 3692#define FUNC_NAME s_scm_force
0f2d19dd 3693{
28d52ebb 3694 SCM_VALIDATE_SMOB (1, promise, promise);
9de87eea 3695 scm_lock_mutex (SCM_PROMISE_MUTEX (promise));
28d52ebb 3696 if (!SCM_PROMISE_COMPUTED_P (promise))
0f2d19dd 3697 {
28d52ebb
MD
3698 SCM ans = scm_call_0 (SCM_PROMISE_DATA (promise));
3699 if (!SCM_PROMISE_COMPUTED_P (promise))
0f2d19dd 3700 {
28d52ebb
MD
3701 SCM_SET_PROMISE_DATA (promise, ans);
3702 SCM_SET_PROMISE_COMPUTED (promise);
0f2d19dd
JB
3703 }
3704 }
9de87eea 3705 scm_unlock_mutex (SCM_PROMISE_MUTEX (promise));
28d52ebb 3706 return SCM_PROMISE_DATA (promise);
0f2d19dd 3707}
1bbd0b84 3708#undef FUNC_NAME
0f2d19dd 3709
445f675c 3710
a1ec6916 3711SCM_DEFINE (scm_promise_p, "promise?", 1, 0, 0,
67e8151b 3712 (SCM obj),
b380b885 3713 "Return true if @var{obj} is a promise, i.e. a delayed computation\n"
7a095584 3714 "(@pxref{Delayed evaluation,,,r5rs.info,The Revised^5 Report on Scheme}).")
1bbd0b84 3715#define FUNC_NAME s_scm_promise_p
0f2d19dd 3716{
7888309b 3717 return scm_from_bool (SCM_TYP16_PREDICATE (scm_tc16_promise, obj));
0f2d19dd 3718}
1bbd0b84 3719#undef FUNC_NAME
0f2d19dd 3720
445f675c 3721
a1ec6916 3722SCM_DEFINE (scm_cons_source, "cons-source", 3, 0, 0,
1bbd0b84 3723 (SCM xorig, SCM x, SCM y),
11768c04
NJ
3724 "Create and return a new pair whose car and cdr are @var{x} and @var{y}.\n"
3725 "Any source properties associated with @var{xorig} are also associated\n"
3726 "with the new pair.")
1bbd0b84 3727#define FUNC_NAME s_scm_cons_source
26d5b9b4
MD
3728{
3729 SCM p, z;
16d4699b 3730 z = scm_cons (x, y);
26d5b9b4
MD
3731 /* Copy source properties possibly associated with xorig. */
3732 p = scm_whash_lookup (scm_source_whash, xorig);
7888309b 3733 if (scm_is_true (p))
26d5b9b4
MD
3734 scm_whash_insert (scm_source_whash, z, p);
3735 return z;
3736}
1bbd0b84 3737#undef FUNC_NAME
26d5b9b4 3738
445f675c 3739
62360b89
DH
3740/* The function scm_copy_tree is used to copy an expression tree to allow the
3741 * memoizer to modify the expression during memoization. scm_copy_tree
3742 * creates deep copies of pairs and vectors, but not of any other data types,
3743 * since only pairs and vectors will be parsed by the memoizer.
3744 *
3745 * To avoid infinite recursion due to cyclic structures, the hare-and-tortoise
3746 * pattern is used to detect cycles. In fact, the pattern is used in two
3747 * dimensions, vertical (indicated in the code by the variable names 'hare'
3748 * and 'tortoise') and horizontal ('rabbit' and 'turtle'). In both
3749 * dimensions, the hare/rabbit will take two steps when the tortoise/turtle
3750 * takes one.
3751 *
3752 * The vertical dimension corresponds to recursive calls to function
3753 * copy_tree: This happens when descending into vector elements, into cars of
3754 * lists and into the cdr of an improper list. In this dimension, the
3755 * tortoise follows the hare by using the processor stack: Every stack frame
3756 * will hold an instance of struct t_trace. These instances are connected in
3757 * a way that represents the trace of the hare, which thus can be followed by
3758 * the tortoise. The tortoise will always point to struct t_trace instances
3759 * relating to SCM objects that have already been copied. Thus, a cycle is
3760 * detected if the tortoise and the hare point to the same object,
3761 *
3762 * The horizontal dimension is within one execution of copy_tree, when the
3763 * function cdr's along the pairs of a list. This is the standard
3764 * hare-and-tortoise implementation, found several times in guile. */
3765
3766struct t_trace {
2b829bbb
KR
3767 struct t_trace *trace; /* These pointers form a trace along the stack. */
3768 SCM obj; /* The object handled at the respective stack frame.*/
62360b89
DH
3769};
3770
3771static SCM
3772copy_tree (
3773 struct t_trace *const hare,
3774 struct t_trace *tortoise,
3775 unsigned int tortoise_delay )
3776{
4057a3e0 3777 if (!scm_is_pair (hare->obj) && !scm_is_simple_vector (hare->obj))
62360b89
DH
3778 {
3779 return hare->obj;
3780 }
3781 else
3782 {
3783 /* Prepare the trace along the stack. */
3784 struct t_trace new_hare;
3785 hare->trace = &new_hare;
3786
3787 /* The tortoise will make its step after the delay has elapsed. Note
3788 * that in contrast to the typical hare-and-tortoise pattern, the step
3789 * of the tortoise happens before the hare takes its steps. This is, in
3790 * principle, no problem, except for the start of the algorithm: Then,
5fb64383 3791 * it has to be made sure that the hare actually gets its advantage of
62360b89
DH
3792 * two steps. */
3793 if (tortoise_delay == 0)
3794 {
3795 tortoise_delay = 1;
3796 tortoise = tortoise->trace;
bc36d050 3797 ASSERT_SYNTAX (!scm_is_eq (hare->obj, tortoise->obj),
62360b89
DH
3798 s_bad_expression, hare->obj);
3799 }
3800 else
3801 {
3802 --tortoise_delay;
3803 }
3804
4057a3e0 3805 if (scm_is_simple_vector (hare->obj))
62360b89 3806 {
4057a3e0
MV
3807 size_t length = SCM_SIMPLE_VECTOR_LENGTH (hare->obj);
3808 SCM new_vector = scm_c_make_vector (length, SCM_UNSPECIFIED);
62360b89
DH
3809
3810 /* Each vector element is copied by recursing into copy_tree, having
3811 * the tortoise follow the hare into the depths of the stack. */
3812 unsigned long int i;
3813 for (i = 0; i < length; ++i)
3814 {
3815 SCM new_element;
4057a3e0 3816 new_hare.obj = SCM_SIMPLE_VECTOR_REF (hare->obj, i);
62360b89 3817 new_element = copy_tree (&new_hare, tortoise, tortoise_delay);
4057a3e0 3818 SCM_SIMPLE_VECTOR_SET (new_vector, i, new_element);
62360b89
DH
3819 }
3820
3821 return new_vector;
3822 }
2b829bbb 3823 else /* scm_is_pair (hare->obj) */
62360b89
DH
3824 {
3825 SCM result;
3826 SCM tail;
3827
3828 SCM rabbit = hare->obj;
3829 SCM turtle = hare->obj;
3830
3831 SCM copy;
3832
3833 /* The first pair of the list is treated specially, in order to
3834 * preserve a potential source code position. */
3835 result = tail = scm_cons_source (rabbit, SCM_EOL, SCM_EOL);
3836 new_hare.obj = SCM_CAR (rabbit);
3837 copy = copy_tree (&new_hare, tortoise, tortoise_delay);
3838 SCM_SETCAR (tail, copy);
3839
3840 /* The remaining pairs of the list are copied by, horizontally,
3841 * having the turtle follow the rabbit, and, vertically, having the
3842 * tortoise follow the hare into the depths of the stack. */
3843 rabbit = SCM_CDR (rabbit);
a61f4e0c 3844 while (scm_is_pair (rabbit))
62360b89
DH
3845 {
3846 new_hare.obj = SCM_CAR (rabbit);
3847 copy = copy_tree (&new_hare, tortoise, tortoise_delay);
3848 SCM_SETCDR (tail, scm_cons (copy, SCM_UNDEFINED));
3849 tail = SCM_CDR (tail);
3850
3851 rabbit = SCM_CDR (rabbit);
a61f4e0c 3852 if (scm_is_pair (rabbit))
62360b89
DH
3853 {
3854 new_hare.obj = SCM_CAR (rabbit);
3855 copy = copy_tree (&new_hare, tortoise, tortoise_delay);
3856 SCM_SETCDR (tail, scm_cons (copy, SCM_UNDEFINED));
3857 tail = SCM_CDR (tail);
3858 rabbit = SCM_CDR (rabbit);
3859
3860 turtle = SCM_CDR (turtle);
bc36d050 3861 ASSERT_SYNTAX (!scm_is_eq (rabbit, turtle),
62360b89
DH
3862 s_bad_expression, rabbit);
3863 }
3864 }
3865
3866 /* We have to recurse into copy_tree again for the last cdr, in
3867 * order to handle the situation that it holds a vector. */
3868 new_hare.obj = rabbit;
3869 copy = copy_tree (&new_hare, tortoise, tortoise_delay);
3870 SCM_SETCDR (tail, copy);
3871
3872 return result;
3873 }
3874 }
3875}
3876
a1ec6916 3877SCM_DEFINE (scm_copy_tree, "copy-tree", 1, 0, 0,
1bbd0b84 3878 (SCM obj),
b380b885 3879 "Recursively copy the data tree that is bound to @var{obj}, and return a\n"
bfefbf18 3880 "the new data structure. @code{copy-tree} recurses down the\n"
b380b885
MD
3881 "contents of both pairs and vectors (since both cons cells and vector\n"
3882 "cells may point to arbitrary objects), and stops recursing when it hits\n"
3883 "any other object.")
1bbd0b84 3884#define FUNC_NAME s_scm_copy_tree
0f2d19dd 3885{
62360b89
DH
3886 /* Prepare the trace along the stack. */
3887 struct t_trace trace;
3888 trace.obj = obj;
3889
3890 /* In function copy_tree, if the tortoise makes its step, it will do this
3891 * before the hare has the chance to move. Thus, we have to make sure that
3892 * the very first step of the tortoise will not happen after the hare has
3893 * really made two steps. This is achieved by passing '2' as the initial
3894 * delay for the tortoise. NOTE: Since cycles are unlikely, giving the hare
3895 * a bigger advantage may improve performance slightly. */
3896 return copy_tree (&trace, &trace, 2);
0f2d19dd 3897}
1bbd0b84 3898#undef FUNC_NAME
0f2d19dd 3899
1cc91f1b 3900
4163eb72
MV
3901/* We have three levels of EVAL here:
3902
3903 - scm_i_eval (exp, env)
3904
3905 evaluates EXP in environment ENV. ENV is a lexical environment
3906 structure as used by the actual tree code evaluator. When ENV is
3907 a top-level environment, then changes to the current module are
a513ead3 3908 tracked by updating ENV so that it continues to be in sync with
4163eb72
MV
3909 the current module.
3910
3911 - scm_primitive_eval (exp)
3912
3913 evaluates EXP in the top-level environment as determined by the
3914 current module. This is done by constructing a suitable
3915 environment and calling scm_i_eval. Thus, changes to the
3916 top-level module are tracked normally.
3917
9de87eea 3918 - scm_eval (exp, mod_or_state)
4163eb72 3919
9de87eea
MV
3920 evaluates EXP while MOD_OR_STATE is the current module or current
3921 dynamic state (as appropriate). This is done by setting the
3922 current module (or dynamic state) to MOD_OR_STATE, invoking
3923 scm_primitive_eval on EXP, and then restoring the current module
3924 (or dynamic state) to the value it had previously. That is,
3925 while EXP is evaluated, changes to the current module (or dynamic
3926 state) are tracked, but these changes do not persist when
4163eb72
MV
3927 scm_eval returns.
3928
3929 For each level of evals, there are two variants, distinguished by a
3930 _x suffix: the ordinary variant does not modify EXP while the _x
3931 variant can destructively modify EXP into something completely
3932 unintelligible. A Scheme data structure passed as EXP to one of the
3933 _x variants should not ever be used again for anything. So when in
3934 doubt, use the ordinary variant.
3935
3936*/
3937
0f2d19dd 3938SCM
68d8be66 3939scm_i_eval_x (SCM exp, SCM env)
0f2d19dd 3940{
cc95e00a 3941 if (scm_is_symbol (exp))
434f2f7a
DH
3942 return *scm_lookupcar (scm_cons (exp, SCM_UNDEFINED), env, 1);
3943 else
0ee05b85 3944 return SCM_I_XEVAL (exp, env, scm_debug_mode_p);
0f2d19dd
JB
3945}
3946
68d8be66
MD
3947SCM
3948scm_i_eval (SCM exp, SCM env)
3949{
26fb6390 3950 exp = scm_copy_tree (exp);
cc95e00a 3951 if (scm_is_symbol (exp))
434f2f7a
DH
3952 return *scm_lookupcar (scm_cons (exp, SCM_UNDEFINED), env, 1);
3953 else
0ee05b85 3954 return SCM_I_XEVAL (exp, env, scm_debug_mode_p);
68d8be66
MD
3955}
3956
3957SCM
4163eb72 3958scm_primitive_eval_x (SCM exp)
0f2d19dd 3959{
a513ead3 3960 SCM env;
bcdab802 3961 SCM transformer = scm_current_module_transformer ();
a513ead3 3962 if (SCM_NIMP (transformer))
fdc28395 3963 exp = scm_call_1 (transformer, exp);
a513ead3 3964 env = scm_top_level_env (scm_current_module_lookup_closure ());
4163eb72 3965 return scm_i_eval_x (exp, env);
0f2d19dd
JB
3966}
3967
4163eb72
MV
3968SCM_DEFINE (scm_primitive_eval, "primitive-eval", 1, 0, 0,
3969 (SCM exp),
2069af38 3970 "Evaluate @var{exp} in the top-level environment specified by\n"
4163eb72
MV
3971 "the current module.")
3972#define FUNC_NAME s_scm_primitive_eval
3973{
a513ead3 3974 SCM env;
bcdab802 3975 SCM transformer = scm_current_module_transformer ();
7888309b 3976 if (scm_is_true (transformer))
fdc28395 3977 exp = scm_call_1 (transformer, exp);
a513ead3 3978 env = scm_top_level_env (scm_current_module_lookup_closure ());
4163eb72
MV
3979 return scm_i_eval (exp, env);
3980}
3981#undef FUNC_NAME
3982
6bff1368 3983
68d8be66
MD
3984/* Eval does not take the second arg optionally. This is intentional
3985 * in order to be R5RS compatible, and to prepare for the new module
3986 * system, where we would like to make the choice of evaluation
4163eb72 3987 * environment explicit. */
549e6ec6 3988
4163eb72 3989SCM
9de87eea 3990scm_eval_x (SCM exp, SCM module_or_state)
4163eb72 3991{
9de87eea 3992 SCM res;
4163eb72 3993
661ae7ab 3994 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
9de87eea 3995 if (scm_is_dynamic_state (module_or_state))
661ae7ab 3996 scm_dynwind_current_dynamic_state (module_or_state);
9de87eea 3997 else
661ae7ab 3998 scm_dynwind_current_module (module_or_state);
4163eb72 3999
9de87eea
MV
4000 res = scm_primitive_eval_x (exp);
4001
661ae7ab 4002 scm_dynwind_end ();
9de87eea 4003 return res;
4163eb72 4004}
09074dbf 4005
68d8be66 4006SCM_DEFINE (scm_eval, "eval", 2, 0, 0,
9de87eea 4007 (SCM exp, SCM module_or_state),
4163eb72 4008 "Evaluate @var{exp}, a list representing a Scheme expression,\n"
9de87eea
MV
4009 "in the top-level environment specified by\n"
4010 "@var{module_or_state}.\n"
8f85c0c6 4011 "While @var{exp} is evaluated (using @code{primitive-eval}),\n"
9de87eea
MV
4012 "@var{module_or_state} is made the current module when\n"
4013 "it is a module, or the current dynamic state when it is\n"
4014 "a dynamic state."
6be1fab9 4015 "Example: (eval '(+ 1 2) (interaction-environment))")
1bbd0b84 4016#define FUNC_NAME s_scm_eval
0f2d19dd 4017{
9de87eea
MV
4018 SCM res;
4019
661ae7ab 4020 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
9de87eea 4021 if (scm_is_dynamic_state (module_or_state))
661ae7ab 4022 scm_dynwind_current_dynamic_state (module_or_state);
9de87eea 4023 else
61b6542a
LC
4024 {
4025 SCM_VALIDATE_MODULE (2, module_or_state);
4026 scm_dynwind_current_module (module_or_state);
4027 }
9de87eea
MV
4028
4029 res = scm_primitive_eval (exp);
09074dbf 4030
661ae7ab 4031 scm_dynwind_end ();
9de87eea 4032 return res;
0f2d19dd 4033}
1bbd0b84 4034#undef FUNC_NAME
0f2d19dd 4035
6dbd0af5 4036
434f2f7a 4037/* At this point, deval and scm_dapply are generated.
6dbd0af5
MD
4038 */
4039
a44a9715 4040#define DEVAL
0ee05b85
HWN
4041#include "eval.i.c"
4042#undef DEVAL
4043#include "eval.i.c"
434f2f7a
DH
4044
4045
0f2d19dd
JB
4046void
4047scm_init_eval ()
0f2d19dd 4048{
d1138028
MV
4049 scm_i_pthread_mutex_init (&source_mutex,
4050 scm_i_pthread_mutexattr_recursive);
4051
33b97402 4052 scm_init_opts (scm_evaluator_traps,
62560650 4053 scm_evaluator_trap_table);
33b97402 4054 scm_init_opts (scm_eval_options_interface,
62560650 4055 scm_eval_opts);
33b97402 4056
f99c9c28 4057 scm_tc16_promise = scm_make_smob_type ("promise", 0);
e841c3e0 4058 scm_set_smob_print (scm_tc16_promise, promise_print);
b8229a3b 4059
a44a9715
DH
4060 undefineds = scm_list_1 (SCM_UNDEFINED);
4061 SCM_SETCDR (undefineds, undefineds);
4062 scm_permanent_object (undefineds);
7c33806a 4063
a44a9715 4064 scm_listofnull = scm_list_1 (SCM_EOL);
0f2d19dd 4065
a44a9715
DH
4066 f_apply = scm_c_define_subr ("apply", scm_tc7_lsubr_2, scm_apply);
4067 scm_permanent_object (f_apply);
86d31dfe 4068
a0599745 4069#include "libguile/eval.x"
60a49842 4070
25eaf21a 4071 scm_add_feature ("delay");
0f2d19dd 4072}
0f2d19dd 4073
89e00824
ML
4074/*
4075 Local Variables:
4076 c-file-style: "gnu"
4077 End:
4078*/
62560650 4079