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