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