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