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