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