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