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