%null-pointer properly aligned
[bpt/guile.git] / libguile / eval.c
CommitLineData
997659f8 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010
434f2f7a 2 * Free Software Foundation, Inc.
0f2d19dd 3 *
73be1d9e 4 * This library is free software; you can redistribute it and/or
53befeb7
NJ
5 * modify it under the terms of the GNU Lesser General Public License
6 * as published by the Free Software Foundation; either version 3 of
7 * the License, or (at your option) any later version.
0f2d19dd 8 *
53befeb7
NJ
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
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
53befeb7
NJ
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301 USA
73be1d9e 18 */
1bbd0b84 19
0f2d19dd
JB
20\f
21
dbb605f5 22#ifdef HAVE_CONFIG_H
3d05f2e0
RB
23# include <config.h>
24#endif
0f2d19dd 25
f7439099 26#include <alloca.h>
b7ecadca 27#include <assert.h>
3d05f2e0 28
f7439099 29#include "libguile/__scm.h"
48b96f4b 30
a0599745 31#include "libguile/_scm.h"
21628685
DH
32#include "libguile/alist.h"
33#include "libguile/async.h"
34#include "libguile/continuations.h"
747022e4 35#include "libguile/control.h"
a0599745 36#include "libguile/debug.h"
328dc9a3 37#include "libguile/deprecation.h"
09074dbf 38#include "libguile/dynwind.h"
a0599745 39#include "libguile/eq.h"
21628685
DH
40#include "libguile/feature.h"
41#include "libguile/fluids.h"
21628685
DH
42#include "libguile/goops.h"
43#include "libguile/hash.h"
44#include "libguile/hashtab.h"
4610b011 45#include "libguile/list.h"
a0599745 46#include "libguile/macros.h"
b7742c6b 47#include "libguile/memoize.h"
a0599745
MD
48#include "libguile/modules.h"
49#include "libguile/ports.h"
7e6e6b37 50#include "libguile/print.h"
21628685 51#include "libguile/procprop.h"
4abef68f 52#include "libguile/programs.h"
a0599745 53#include "libguile/root.h"
21628685
DH
54#include "libguile/smob.h"
55#include "libguile/srcprop.h"
56#include "libguile/stackchk.h"
57#include "libguile/strings.h"
9de87eea 58#include "libguile/threads.h"
21628685
DH
59#include "libguile/throw.h"
60#include "libguile/validate.h"
a513ead3 61#include "libguile/values.h"
21628685 62#include "libguile/vectors.h"
4abef68f 63#include "libguile/vm.h"
a0599745 64
a0599745 65#include "libguile/eval.h"
0ee05b85 66#include "libguile/private-options.h"
89efbff4 67
0f2d19dd
JB
68\f
69
0ee05b85 70
b7742c6b 71/* We have three levels of EVAL here:
609a8b86 72
b7742c6b 73 - eval (exp, env)
89bff2fc 74
b7742c6b
AW
75 evaluates EXP in environment ENV. ENV is a lexical environment
76 structure as used by the actual tree code evaluator. When ENV is
77 a top-level environment, then changes to the current module are
78 tracked by updating ENV so that it continues to be in sync with
79 the current module.
e6729603 80
b7742c6b 81 - scm_primitive_eval (exp)
e6729603 82
b7742c6b
AW
83 evaluates EXP in the top-level environment as determined by the
84 current module. This is done by constructing a suitable
85 environment and calling eval. Thus, changes to the
86 top-level module are tracked normally.
e6729603 87
b7742c6b 88 - scm_eval (exp, mod)
e6729603 89
b7742c6b
AW
90 evaluates EXP while MOD is the current module. This is done
91 by setting the current module to MOD_OR_STATE, invoking
92 scm_primitive_eval on EXP, and then restoring the current module
93 to the value it had previously. That is, while EXP is evaluated,
94 changes to the current module (or dynamic state) are tracked,
95 but these changes do not persist when scm_eval returns.
e6729603 96
b7742c6b 97*/
e6729603 98
e6729603 99
314b8716
AW
100/* Boot closures. We only see these when compiling eval.scm, because once
101 eval.scm is in the house, closures are standard VM closures.
102 */
103
104static scm_t_bits scm_tc16_boot_closure;
105#define RETURN_BOOT_CLOSURE(code, env) SCM_RETURN_NEWSMOB2 (scm_tc16_boot_closure, (code), (env))
106#define BOOT_CLOSURE_P(obj) SCM_TYP16_PREDICATE (scm_tc16_boot_closure, (obj))
107#define BOOT_CLOSURE_CODE(x) SCM_SMOB_OBJECT (x)
108#define BOOT_CLOSURE_ENV(x) SCM_SMOB_OBJECT_2 (x)
8f9c5b58
AW
109#define BOOT_CLOSURE_BODY(x) CAR (BOOT_CLOSURE_CODE (x))
110#define BOOT_CLOSURE_NUM_REQUIRED_ARGS(x) SCM_I_INUM (CADR (BOOT_CLOSURE_CODE (x)))
111#define BOOT_CLOSURE_IS_FIXED(x) scm_is_null (CDDR (BOOT_CLOSURE_CODE (x)))
112/* NB: One may only call the following accessors if the closure is not FIXED. */
113#define BOOT_CLOSURE_HAS_REST_ARGS(x) scm_is_true (CADDR (BOOT_CLOSURE_CODE (x)))
114#define BOOT_CLOSURE_IS_REST(x) scm_is_null (CDDDR (BOOT_CLOSURE_CODE (x)))
115/* NB: One may only call the following accessors if the closure is not REST. */
116#define BOOT_CLOSURE_IS_FULL(x) (1)
dc3e203e
AW
117#define BOOT_CLOSURE_PARSE_FULL(fu_,body,nargs,rest,nopt,kw,inits,alt) \
118 do { SCM fu = fu_; \
119 body = CAR (fu); fu = CDR (fu); \
120 \
121 rest = kw = alt = SCM_BOOL_F; \
122 inits = SCM_EOL; \
123 nopt = 0; \
124 \
125 nreq = SCM_I_INUM (CAR (fu)); fu = CDR (fu); \
126 if (scm_is_pair (fu)) \
127 { \
128 rest = CAR (fu); fu = CDR (fu); \
129 if (scm_is_pair (fu)) \
130 { \
131 nopt = SCM_I_INUM (CAR (fu)); fu = CDR (fu); \
132 kw = CAR (fu); fu = CDR (fu); \
133 inits = CAR (fu); fu = CDR (fu); \
134 alt = CAR (fu); \
135 } \
136 } \
d8a071fc 137 } while (0)
7572ee52
AW
138static void prepare_boot_closure_env_for_apply (SCM proc, SCM args,
139 SCM *out_body, SCM *out_env);
140static void prepare_boot_closure_env_for_eval (SCM proc, unsigned int argc,
141 SCM exps, SCM *out_body,
142 SCM *inout_env);
314b8716
AW
143
144
b7742c6b
AW
145#define CAR(x) SCM_CAR(x)
146#define CDR(x) SCM_CDR(x)
147#define CAAR(x) SCM_CAAR(x)
148#define CADR(x) SCM_CADR(x)
149#define CDAR(x) SCM_CDAR(x)
150#define CDDR(x) SCM_CDDR(x)
151#define CADDR(x) SCM_CADDR(x)
152#define CDDDR(x) SCM_CDDDR(x)
e6729603
DH
153
154
b7742c6b 155SCM_SYMBOL (scm_unbound_variable_key, "unbound-variable");
e6729603 156
b7742c6b 157static void error_used_before_defined (void)
d0624e39 158{
b7742c6b
AW
159 scm_error (scm_unbound_variable_key, NULL,
160 "Variable used before given a value", SCM_EOL, SCM_BOOL_F);
d0624e39 161}
d0624e39 162
d8a071fc
AW
163static void error_invalid_keyword (SCM proc)
164{
165 scm_error_scm (scm_from_locale_symbol ("keyword-argument-error"), proc,
166 scm_from_locale_string ("Invalid keyword"), SCM_EOL,
167 SCM_BOOL_F);
168}
169
170static void error_unrecognized_keyword (SCM proc)
171{
172 scm_error_scm (scm_from_locale_symbol ("keyword-argument-error"), proc,
173 scm_from_locale_string ("Unrecognized keyword"), SCM_EOL,
174 SCM_BOOL_F);
175}
176
177
b7742c6b 178/* the environment:
3149a5b6 179 (VAL ... . MOD)
b7742c6b
AW
180 If MOD is #f, it means the environment was captured before modules were
181 booted.
182 If MOD is the literal value '(), we are evaluating at the top level, and so
183 should track changes to the current module. You have to be careful in this
184 case, because further lexical contours should capture the current module.
185*/
186#define CAPTURE_ENV(env) \
187 ((env == SCM_EOL) ? scm_current_module () : \
188 ((env == SCM_BOOL_F) ? scm_the_root_module () : env))
6f81708a
DH
189
190static SCM
b7742c6b 191eval (SCM x, SCM env)
6f81708a 192{
b7742c6b
AW
193 SCM mx;
194 SCM proc = SCM_UNDEFINED, args = SCM_EOL;
b7ecadca 195 unsigned int argc;
6f81708a 196
b7742c6b
AW
197 loop:
198 SCM_TICK;
199 if (!SCM_MEMOIZED_P (x))
200 abort ();
201
202 mx = SCM_MEMOIZED_ARGS (x);
203 switch (SCM_MEMOIZED_TAG (x))
204 {
205 case SCM_M_BEGIN:
206 for (; !scm_is_null (CDR (mx)); mx = CDR (mx))
207 eval (CAR (mx), env);
208 x = CAR (mx);
209 goto loop;
210
211 case SCM_M_IF:
212 if (scm_is_true (eval (CAR (mx), env)))
213 x = CADR (mx);
6f81708a 214 else
b7742c6b
AW
215 x = CDDR (mx);
216 goto loop;
5fb64383 217
b7742c6b
AW
218 case SCM_M_LET:
219 {
220 SCM inits = CAR (mx);
221 SCM new_env = CAPTURE_ENV (env);
222 for (; scm_is_pair (inits); inits = CDR (inits))
223 new_env = scm_cons (eval (CAR (inits), env), new_env);
224 env = new_env;
225 x = CDR (mx);
226 goto loop;
227 }
228
229 case SCM_M_LAMBDA:
314b8716 230 RETURN_BOOT_CLOSURE (mx, CAPTURE_ENV (env));
5fb64383 231
b7742c6b
AW
232 case SCM_M_QUOTE:
233 return mx;
0f2d19dd 234
b7742c6b
AW
235 case SCM_M_DEFINE:
236 scm_define (CAR (mx), eval (CDR (mx), env));
237 return SCM_UNSPECIFIED;
212e58ed 238
d69531e2
AW
239 case SCM_M_DYNWIND:
240 {
241 SCM in, out, res, old_winds;
242 in = eval (CAR (mx), env);
243 out = eval (CDDR (mx), env);
244 scm_call_0 (in);
245 old_winds = scm_i_dynwinds ();
246 scm_i_set_dynwinds (scm_acons (in, out, old_winds));
247 res = eval (CADR (mx), env);
248 scm_i_set_dynwinds (old_winds);
249 scm_call_0 (out);
250 return res;
251 }
252
bb0229b5
AW
253 case SCM_M_WITH_FLUIDS:
254 {
255 long i, len;
256 SCM *fluidv, *valuesv, walk, wf, res;
257 len = scm_ilength (CAR (mx));
258 fluidv = alloca (sizeof (SCM)*len);
259 for (i = 0, walk = CAR (mx); i < len; i++, walk = CDR (walk))
260 fluidv[i] = eval (CAR (walk), env);
261 valuesv = alloca (sizeof (SCM)*len);
262 for (i = 0, walk = CADR (mx); i < len; i++, walk = CDR (walk))
263 valuesv[i] = eval (CAR (walk), env);
264
265 wf = scm_i_make_with_fluids (len, fluidv, valuesv);
266 scm_i_swap_with_fluids (wf, SCM_I_CURRENT_THREAD->dynamic_state);
267 scm_i_set_dynwinds (scm_cons (wf, scm_i_dynwinds ()));
268 res = eval (CDDR (mx), env);
269 scm_i_swap_with_fluids (wf, SCM_I_CURRENT_THREAD->dynamic_state);
270 scm_i_set_dynwinds (CDR (scm_i_dynwinds ()));
271
272 return res;
273 }
274
b7742c6b
AW
275 case SCM_M_APPLY:
276 /* Evaluate the procedure to be applied. */
277 proc = eval (CAR (mx), env);
278 /* Evaluate the argument holding the list of arguments */
279 args = eval (CADR (mx), env);
280
281 apply_proc:
282 /* Go here to tail-apply a procedure. PROC is the procedure and
283 * ARGS is the list of arguments. */
314b8716 284 if (BOOT_CLOSURE_P (proc))
b7742c6b 285 {
7572ee52 286 prepare_boot_closure_env_for_apply (proc, args, &x, &env);
b7742c6b
AW
287 goto loop;
288 }
289 else
67e2d80a 290 return scm_vm_apply (scm_the_vm (), proc, args);
212e58ed 291
b7742c6b
AW
292 case SCM_M_CALL:
293 /* Evaluate the procedure to be applied. */
294 proc = eval (CAR (mx), env);
b7ecadca 295 argc = SCM_I_INUM (CADR (mx));
9331f91c 296 mx = CDDR (mx);
212e58ed 297
314b8716 298 if (BOOT_CLOSURE_P (proc))
5fa0939c 299 {
7572ee52 300 prepare_boot_closure_env_for_eval (proc, argc, mx, &x, &env);
b7742c6b 301 goto loop;
5fa0939c 302 }
b7742c6b
AW
303 else
304 {
e2cf8eb9 305 SCM *argv;
b7ecadca
LC
306 unsigned int i;
307
e2cf8eb9 308 argv = alloca (argc * sizeof (SCM));
b7ecadca
LC
309 for (i = 0; i < argc; i++, mx = CDR (mx))
310 argv[i] = eval (CAR (mx), env);
311
312 return scm_c_vm_run (scm_the_vm (), proc, argv, argc);
b7742c6b 313 }
b7ecadca 314
b7742c6b 315 case SCM_M_CONT:
babfc7b2 316 return scm_i_call_with_current_continuation (eval (mx, env));
212e58ed 317
b7742c6b
AW
318 case SCM_M_CALL_WITH_VALUES:
319 {
320 SCM producer;
321 SCM v;
322
323 producer = eval (CAR (mx), env);
324 proc = eval (CDR (mx), env); /* proc is the consumer. */
67e2d80a 325 v = scm_vm_apply (scm_the_vm (), producer, SCM_EOL);
b7742c6b
AW
326 if (SCM_VALUESP (v))
327 args = scm_struct_ref (v, SCM_INUM0);
328 else
329 args = scm_list_1 (v);
330 goto apply_proc;
331 }
26d5b9b4 332
b7742c6b
AW
333 case SCM_M_LEXICAL_REF:
334 {
335 int n;
336 SCM ret;
337 for (n = SCM_I_INUM (mx); n; n--)
338 env = CDR (env);
339 ret = CAR (env);
340 if (SCM_UNLIKELY (SCM_UNBNDP (ret)))
341 /* we don't know what variable, though, because we don't have its
342 name */
343 error_used_before_defined ();
344 return ret;
345 }
1cc91f1b 346
b7742c6b
AW
347 case SCM_M_LEXICAL_SET:
348 {
349 int n;
350 SCM val = eval (CDR (mx), env);
351 for (n = SCM_I_INUM (CAR (mx)); n; n--)
352 env = CDR (env);
353 SCM_SETCAR (env, val);
354 return SCM_UNSPECIFIED;
355 }
910b5125 356
b7742c6b
AW
357 case SCM_M_TOPLEVEL_REF:
358 if (SCM_VARIABLEP (mx))
359 return SCM_VARIABLE_REF (mx);
360 else
57d23e25 361 {
b7742c6b 362 while (scm_is_pair (env))
f3a8d1b7 363 env = CDR (env);
3149a5b6
AW
364 return SCM_VARIABLE_REF
365 (scm_memoize_variable_access_x (x, CAPTURE_ENV (env)));
57d23e25 366 }
57d23e25 367
b7742c6b
AW
368 case SCM_M_TOPLEVEL_SET:
369 {
370 SCM var = CAR (mx);
371 SCM val = eval (CDR (mx), env);
372 if (SCM_VARIABLEP (var))
373 {
374 SCM_VARIABLE_SET (var, val);
375 return SCM_UNSPECIFIED;
376 }
377 else
378 {
379 while (scm_is_pair (env))
f3a8d1b7 380 env = CDR (env);
3149a5b6
AW
381 SCM_VARIABLE_SET
382 (scm_memoize_variable_access_x (x, CAPTURE_ENV (env)),
383 val);
b7742c6b
AW
384 return SCM_UNSPECIFIED;
385 }
386 }
910b5125 387
b7742c6b
AW
388 case SCM_M_MODULE_REF:
389 if (SCM_VARIABLEP (mx))
390 return SCM_VARIABLE_REF (mx);
910b5125 391 else
3149a5b6
AW
392 return SCM_VARIABLE_REF
393 (scm_memoize_variable_access_x (x, SCM_BOOL_F));
910b5125 394
b7742c6b
AW
395 case SCM_M_MODULE_SET:
396 if (SCM_VARIABLEP (CDR (mx)))
910b5125 397 {
b7742c6b
AW
398 SCM_VARIABLE_SET (CDR (mx), eval (CAR (mx), env));
399 return SCM_UNSPECIFIED;
400 }
401 else
402 {
3149a5b6
AW
403 SCM_VARIABLE_SET
404 (scm_memoize_variable_access_x (x, SCM_BOOL_F),
405 eval (CAR (mx), env));
b7742c6b 406 return SCM_UNSPECIFIED;
910b5125 407 }
910b5125 408
747022e4
AW
409 case SCM_M_PROMPT:
410 {
d2964315 411 SCM vm, prompt, handler, res;
747022e4 412
d2964315
AW
413 vm = scm_the_vm ();
414 prompt = scm_c_make_prompt (eval (CAR (mx), env), SCM_VM_DATA (vm)->fp,
415 SCM_VM_DATA (vm)->sp, SCM_VM_DATA (vm)->ip,
adbdfd6d 416 0, -1, scm_i_dynwinds ());
747022e4
AW
417 handler = eval (CDDR (mx), env);
418 scm_i_set_dynwinds (scm_cons (prompt, scm_i_dynwinds ()));
419
420 if (SCM_PROMPT_SETJMP (prompt))
421 {
b8af64db 422 /* The prompt exited nonlocally. */
747022e4 423 proc = handler;
b8af64db 424 args = scm_i_prompt_pop_abort_args_x (prompt);
747022e4
AW
425 goto apply_proc;
426 }
427
428 res = eval (CADR (mx), env);
429 scm_i_set_dynwinds (CDR (scm_i_dynwinds ()));
430 return res;
431 }
432
b7742c6b
AW
433 default:
434 abort ();
435 }
910b5125
DH
436}
437
b7742c6b
AW
438scm_t_option scm_eval_opts[] = {
439 { SCM_OPTION_INTEGER, "stack", 22000, "Size of thread stacks (in machine words)." },
440 { 0 }
441};
e6729603 442
b7742c6b
AW
443scm_t_option scm_debug_opts[] = {
444 { SCM_OPTION_BOOLEAN, "cheap", 1,
445 "*This option is now obsolete. Setting it has no effect." },
446 { SCM_OPTION_BOOLEAN, "breakpoints", 0, "*Check for breakpoints." },
447 { SCM_OPTION_BOOLEAN, "trace", 0, "*Trace mode." },
448 { SCM_OPTION_BOOLEAN, "procnames", 1,
449 "Record procedure names at definition." },
450 { SCM_OPTION_BOOLEAN, "backwards", 0,
451 "Display backtrace in anti-chronological order." },
452 { SCM_OPTION_INTEGER, "width", 79, "Maximal width of backtrace." },
453 { SCM_OPTION_INTEGER, "indent", 10, "Maximal indentation in backtrace." },
454 { SCM_OPTION_INTEGER, "frames", 3,
455 "Maximum number of tail-recursive frames in backtrace." },
456 { SCM_OPTION_INTEGER, "maxdepth", 1000,
457 "Maximal number of stored backtrace frames." },
458 { SCM_OPTION_INTEGER, "depth", 20, "Maximal length of printed backtrace." },
459 { SCM_OPTION_BOOLEAN, "backtrace", 0, "Show backtrace on error." },
460 { SCM_OPTION_BOOLEAN, "debug", 0, "Use the debugging evaluator." },
461 /* This default stack limit will be overridden by debug.c:init_stack_limit(),
462 if we have getrlimit() and the stack limit is not INFINITY. But it is still
463 important, as some systems have both the soft and the hard limits set to
464 INFINITY; in that case we fall back to this value.
e6729603 465
b7742c6b
AW
466 The situation is aggravated by certain compilers, which can consume
467 "beaucoup de stack", as they say in France.
0f2d19dd 468
b7742c6b
AW
469 See http://thread.gmane.org/gmane.lisp.guile.devel/8599/focus=8662 for
470 more discussion. This setting is 640 KB on 32-bit arches (should be enough
471 for anyone!) or a whoppin' 1280 KB on 64-bit arches.
472 */
473 { SCM_OPTION_INTEGER, "stack", 160000, "Stack size limit (measured in words; 0 = no check)." },
474 { SCM_OPTION_SCM, "show-file-name", (unsigned long)SCM_BOOL_T,
475 "Show file names and line numbers "
476 "in backtraces when not `#f'. A value of `base' "
477 "displays only base names, while `#t' displays full names."},
478 { SCM_OPTION_BOOLEAN, "warn-deprecated", 0,
479 "Warn when deprecated features are used." },
480 { 0 },
481};
212e58ed 482
1cc91f1b 483
b7742c6b
AW
484/*
485 * this ordering is awkward and illogical, but we maintain it for
486 * compatibility. --hwn
487 */
488scm_t_option scm_evaluator_trap_table[] = {
489 { SCM_OPTION_BOOLEAN, "traps", 0, "Enable evaluator traps." },
490 { SCM_OPTION_BOOLEAN, "enter-frame", 0, "Trap when eval enters new frame." },
491 { SCM_OPTION_BOOLEAN, "apply-frame", 0, "Trap when entering apply." },
492 { SCM_OPTION_BOOLEAN, "exit-frame", 0, "Trap when exiting eval or apply." },
493 { SCM_OPTION_SCM, "enter-frame-handler", (unsigned long)SCM_BOOL_F, "Handler for enter-frame traps." },
494 { SCM_OPTION_SCM, "apply-frame-handler", (unsigned long)SCM_BOOL_F, "Handler for apply-frame traps." },
495 { SCM_OPTION_SCM, "exit-frame-handler", (unsigned long)SCM_BOOL_F, "Handler for exit-frame traps." },
496 { SCM_OPTION_BOOLEAN, "memoize-symbol", 0, "Trap when memoizing a symbol." },
497 { SCM_OPTION_SCM, "memoize-symbol-handler", (unsigned long)SCM_BOOL_F, "The handler for memoization." },
498 { 0 }
499};
8ea46249 500
0f2d19dd 501
b7742c6b
AW
502SCM_DEFINE (scm_eval_options_interface, "eval-options-interface", 0, 1, 0,
503 (SCM setting),
504 "Option interface for the evaluation options. Instead of using\n"
505 "this procedure directly, use the procedures @code{eval-enable},\n"
506 "@code{eval-disable}, @code{eval-set!} and @code{eval-options}.")
507#define FUNC_NAME s_scm_eval_options_interface
212e58ed 508{
b7742c6b
AW
509 SCM ans;
510
511 scm_dynwind_begin (0);
512 scm_dynwind_critical_section (SCM_BOOL_F);
513 ans = scm_options (setting,
514 scm_eval_opts,
515 FUNC_NAME);
516 scm_dynwind_end ();
212e58ed 517
b7742c6b
AW
518 return ans;
519}
520#undef FUNC_NAME
0f2d19dd 521
1cc91f1b 522
b7742c6b
AW
523SCM_DEFINE (scm_evaluator_traps, "evaluator-traps-interface", 0, 1, 0,
524 (SCM setting),
525 "Option interface for the evaluator trap options.")
526#define FUNC_NAME s_scm_evaluator_traps
0f2d19dd 527{
b7742c6b 528 SCM ans;
2a6f7afe 529
b7742c6b
AW
530
531 scm_options_try (setting,
532 scm_evaluator_trap_table,
533 FUNC_NAME, 1);
534 SCM_CRITICAL_SECTION_START;
535 ans = scm_options (setting,
536 scm_evaluator_trap_table,
537 FUNC_NAME);
2a6f7afe 538
b7742c6b
AW
539 /* njrev: same again. */
540 SCM_CRITICAL_SECTION_END;
541 return ans;
542}
543#undef FUNC_NAME
2a6f7afe 544
2a6f7afe 545
2a6f7afe 546
b7742c6b 547\f
2a6f7afe 548
b7742c6b
AW
549/* Simple procedure calls
550 */
2a6f7afe 551
b7742c6b
AW
552SCM
553scm_call_0 (SCM proc)
554{
bf5a05f2 555 return scm_c_vm_run (scm_the_vm (), proc, NULL, 0);
0f2d19dd
JB
556}
557
b7742c6b
AW
558SCM
559scm_call_1 (SCM proc, SCM arg1)
212e58ed 560{
bf5a05f2 561 return scm_c_vm_run (scm_the_vm (), proc, &arg1, 1);
b7742c6b 562}
212e58ed 563
b7742c6b
AW
564SCM
565scm_call_2 (SCM proc, SCM arg1, SCM arg2)
566{
bf5a05f2
AW
567 SCM args[] = { arg1, arg2 };
568 return scm_c_vm_run (scm_the_vm (), proc, args, 2);
212e58ed
DH
569}
570
b7742c6b
AW
571SCM
572scm_call_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3)
0f2d19dd 573{
bf5a05f2
AW
574 SCM args[] = { arg1, arg2, arg3 };
575 return scm_c_vm_run (scm_the_vm (), proc, args, 3);
0f2d19dd
JB
576}
577
b7742c6b
AW
578SCM
579scm_call_4 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4)
212e58ed 580{
bf5a05f2
AW
581 SCM args[] = { arg1, arg2, arg3, arg4 };
582 return scm_c_vm_run (scm_the_vm (), proc, args, 4);
212e58ed
DH
583}
584
86fd6dff
AW
585SCM
586scm_call_n (SCM proc, SCM *argv, size_t nargs)
587{
588 return scm_c_vm_run (scm_the_vm (), proc, argv, nargs);
589}
590
b7742c6b 591/* Simple procedure applies
9fbee57e 592 */
cc56ba80 593
b7742c6b
AW
594SCM
595scm_apply_0 (SCM proc, SCM args)
596{
597 return scm_apply (proc, args, SCM_EOL);
0f572ba7
DH
598}
599
b7742c6b
AW
600SCM
601scm_apply_1 (SCM proc, SCM arg1, SCM args)
0f572ba7 602{
b7742c6b 603 return scm_apply (proc, scm_cons (arg1, args), SCM_EOL);
8ae95199
DH
604}
605
b7742c6b
AW
606SCM
607scm_apply_2 (SCM proc, SCM arg1, SCM arg2, SCM args)
0f2d19dd 608{
b7742c6b 609 return scm_apply (proc, scm_cons2 (arg1, arg2, args), SCM_EOL);
0f2d19dd
JB
610}
611
b7742c6b
AW
612SCM
613scm_apply_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM args)
212e58ed 614{
b7742c6b
AW
615 return scm_apply (proc, scm_cons (arg1, scm_cons2 (arg2, arg3, args)),
616 SCM_EOL);
212e58ed
DH
617}
618
b7742c6b 619/* This code processes the arguments to apply:
8ea46249 620
b7742c6b 621 (apply PROC ARG1 ... ARGS)
302c12b4 622
b7742c6b
AW
623 Given a list (ARG1 ... ARGS), this function conses the ARG1
624 ... arguments onto the front of ARGS, and returns the resulting
625 list. Note that ARGS is a list; thus, the argument to this
626 function is a list whose last element is a list.
302c12b4 627
b7742c6b
AW
628 Apply calls this function, and applies PROC to the elements of the
629 result. apply:nconc2last takes care of building the list of
630 arguments, given (ARG1 ... ARGS).
a954ce1d 631
b7742c6b
AW
632 Rather than do new consing, apply:nconc2last destroys its argument.
633 On that topic, this code came into my care with the following
634 beautifully cryptic comment on that topic: "This will only screw
635 you if you do (scm_apply scm_apply '( ... ))" If you know what
636 they're referring to, send me a patch to this comment. */
0f2d19dd 637
b7742c6b
AW
638SCM_DEFINE (scm_nconc2last, "apply:nconc2last", 1, 0, 0,
639 (SCM lst),
640 "Given a list (@var{arg1} @dots{} @var{args}), this function\n"
641 "conses the @var{arg1} @dots{} arguments onto the front of\n"
642 "@var{args}, and returns the resulting list. Note that\n"
643 "@var{args} is a list; thus, the argument to this function is\n"
644 "a list whose last element is a list.\n"
645 "Note: Rather than do new consing, @code{apply:nconc2last}\n"
646 "destroys its argument, so use with care.")
647#define FUNC_NAME s_scm_nconc2last
212e58ed 648{
b7742c6b
AW
649 SCM *lloc;
650 SCM_VALIDATE_NONEMPTYLIST (1, lst);
651 lloc = &lst;
652 while (!scm_is_null (SCM_CDR (*lloc))) /* Perhaps should be
653 SCM_NULL_OR_NIL_P, but not
654 needed in 99.99% of cases,
655 and it could seriously hurt
656 performance. - Neil */
657 lloc = SCM_CDRLOC (*lloc);
658 SCM_ASSERT (scm_ilength (SCM_CAR (*lloc)) >= 0, lst, SCM_ARG1, FUNC_NAME);
659 *lloc = SCM_CAR (*lloc);
660 return lst;
212e58ed 661}
b7742c6b 662#undef FUNC_NAME
212e58ed 663
b8229a3b
MS
664
665
b7742c6b 666/* Typechecking for multi-argument MAP and FOR-EACH.
0f2d19dd 667
b7742c6b
AW
668 Verify that each element of the vector ARGV, except for the first,
669 is a proper list whose length is LEN. Attribute errors to WHO,
670 and claim that the i'th element of ARGV is WHO's i+2'th argument. */
671static inline void
672check_map_args (SCM argv,
673 long len,
674 SCM gf,
675 SCM proc,
676 SCM args,
677 const char *who)
212e58ed 678{
b7742c6b 679 long i;
0f2d19dd 680
b7742c6b 681 for (i = SCM_SIMPLE_VECTOR_LENGTH (argv) - 1; i >= 1; i--)
9fbee57e 682 {
b7742c6b
AW
683 SCM elt = SCM_SIMPLE_VECTOR_REF (argv, i);
684 long elt_len = scm_ilength (elt);
5cb22e96 685
b7742c6b
AW
686 if (elt_len < 0)
687 {
688 if (gf)
689 scm_apply_generic (gf, scm_cons (proc, args));
690 else
691 scm_wrong_type_arg (who, i + 2, elt);
692 }
1cc91f1b 693
b7742c6b
AW
694 if (elt_len != len)
695 scm_out_of_range_pos (who, elt, scm_from_long (i + 2));
0f2d19dd 696 }
0f2d19dd 697}
6dbd0af5 698
212e58ed 699
b7742c6b 700SCM_GPROC (s_map, "map", 2, 0, 1, scm_map, g_map);
212e58ed 701
b7742c6b
AW
702/* Note: Currently, scm_map applies PROC to the argument list(s)
703 sequentially, starting with the first element(s). This is used in
704 evalext.c where the Scheme procedure `map-in-order', which guarantees
705 sequential behaviour, is implemented using scm_map. If the
706 behaviour changes, we need to update `map-in-order'.
707*/
0f2d19dd 708
b7742c6b
AW
709SCM
710scm_map (SCM proc, SCM arg1, SCM args)
711#define FUNC_NAME s_map
0f2d19dd 712{
b7742c6b
AW
713 long i, len;
714 SCM res = SCM_EOL;
715 SCM *pres = &res;
0f2d19dd 716
b7742c6b
AW
717 len = scm_ilength (arg1);
718 SCM_GASSERTn (len >= 0,
719 g_map, scm_cons2 (proc, arg1, args), SCM_ARG2, s_map);
720 SCM_VALIDATE_REST_ARGUMENT (args);
721 if (scm_is_null (args))
0f2d19dd 722 {
b7742c6b
AW
723 SCM_GASSERT2 (scm_is_true (scm_procedure_p (proc)), g_map, proc, arg1, SCM_ARG1, s_map);
724 while (SCM_NIMP (arg1))
725 {
726 *pres = scm_list_1 (scm_call_1 (proc, SCM_CAR (arg1)));
727 pres = SCM_CDRLOC (*pres);
728 arg1 = SCM_CDR (arg1);
729 }
730 return res;
0f2d19dd 731 }
b7742c6b
AW
732 if (scm_is_null (SCM_CDR (args)))
733 {
734 SCM arg2 = SCM_CAR (args);
735 int len2 = scm_ilength (arg2);
736 SCM_GASSERTn (scm_is_true (scm_procedure_p (proc)), g_map,
737 scm_cons2 (proc, arg1, args), SCM_ARG1, s_map);
738 SCM_GASSERTn (len2 >= 0,
739 g_map, scm_cons2 (proc, arg1, args), SCM_ARG3, s_map);
740 if (len2 != len)
741 SCM_OUT_OF_RANGE (3, arg2);
742 while (SCM_NIMP (arg1))
743 {
744 *pres = scm_list_1 (scm_call_2 (proc, SCM_CAR (arg1), SCM_CAR (arg2)));
745 pres = SCM_CDRLOC (*pres);
746 arg1 = SCM_CDR (arg1);
747 arg2 = SCM_CDR (arg2);
748 }
749 return res;
750 }
751 arg1 = scm_cons (arg1, args);
752 args = scm_vector (arg1);
753 check_map_args (args, len, g_map, proc, arg1, s_map);
754 while (1)
d6754c23 755 {
b7742c6b
AW
756 arg1 = SCM_EOL;
757 for (i = SCM_SIMPLE_VECTOR_LENGTH (args) - 1; i >= 0; i--)
758 {
759 SCM elt = SCM_SIMPLE_VECTOR_REF (args, i);
760 if (SCM_IMP (elt))
761 return res;
762 arg1 = scm_cons (SCM_CAR (elt), arg1);
763 SCM_SIMPLE_VECTOR_SET (args, i, SCM_CDR (elt));
764 }
765 *pres = scm_list_1 (scm_apply (proc, arg1, SCM_EOL));
766 pres = SCM_CDRLOC (*pres);
d6754c23 767 }
0f2d19dd 768}
b7742c6b 769#undef FUNC_NAME
0f2d19dd 770
302c12b4 771
b7742c6b 772SCM_GPROC (s_for_each, "for-each", 2, 0, 1, scm_for_each, g_for_each);
d6754c23 773
b7742c6b
AW
774SCM
775scm_for_each (SCM proc, SCM arg1, SCM args)
776#define FUNC_NAME s_for_each
0f2d19dd 777{
b7742c6b
AW
778 long i, len;
779 len = scm_ilength (arg1);
780 SCM_GASSERTn (len >= 0, g_for_each, scm_cons2 (proc, arg1, args),
781 SCM_ARG2, s_for_each);
782 SCM_VALIDATE_REST_ARGUMENT (args);
783 if (scm_is_null (args))
26d5b9b4 784 {
b7742c6b
AW
785 SCM_GASSERT2 (scm_is_true (scm_procedure_p (proc)), g_for_each,
786 proc, arg1, SCM_ARG1, s_for_each);
787 while (SCM_NIMP (arg1))
788 {
789 scm_call_1 (proc, SCM_CAR (arg1));
790 arg1 = SCM_CDR (arg1);
791 }
792 return SCM_UNSPECIFIED;
26d5b9b4 793 }
b7742c6b 794 if (scm_is_null (SCM_CDR (args)))
26d5b9b4 795 {
b7742c6b
AW
796 SCM arg2 = SCM_CAR (args);
797 int len2 = scm_ilength (arg2);
798 SCM_GASSERTn (scm_is_true (scm_procedure_p (proc)), g_for_each,
799 scm_cons2 (proc, arg1, args), SCM_ARG1, s_for_each);
800 SCM_GASSERTn (len2 >= 0, g_for_each,
801 scm_cons2 (proc, arg1, args), SCM_ARG3, s_for_each);
802 if (len2 != len)
803 SCM_OUT_OF_RANGE (3, arg2);
804 while (SCM_NIMP (arg1))
805 {
806 scm_call_2 (proc, SCM_CAR (arg1), SCM_CAR (arg2));
807 arg1 = SCM_CDR (arg1);
808 arg2 = SCM_CDR (arg2);
809 }
810 return SCM_UNSPECIFIED;
26d5b9b4 811 }
b7742c6b
AW
812 arg1 = scm_cons (arg1, args);
813 args = scm_vector (arg1);
814 check_map_args (args, len, g_for_each, proc, arg1, s_for_each);
815 while (1)
302c12b4 816 {
b7742c6b
AW
817 arg1 = SCM_EOL;
818 for (i = SCM_SIMPLE_VECTOR_LENGTH (args) - 1; i >= 0; i--)
71560395 819 {
b7742c6b
AW
820 SCM elt = SCM_SIMPLE_VECTOR_REF (args, i);
821 if (SCM_IMP (elt))
822 return SCM_UNSPECIFIED;
823 arg1 = scm_cons (SCM_CAR (elt), arg1);
824 SCM_SIMPLE_VECTOR_SET (args, i, SCM_CDR (elt));
825 }
826 scm_apply (proc, arg1, SCM_EOL);
827 }
828}
829#undef FUNC_NAME
71560395 830
71560395 831
5f161164
AW
832static SCM
833scm_c_primitive_eval (SCM exp)
b7742c6b 834{
4f692ace
AW
835 if (!SCM_MEMOIZED_P (exp))
836 exp = scm_call_1 (scm_current_module_transformer (), exp);
837 if (!SCM_MEMOIZED_P (exp))
838 scm_misc_error ("primitive-eval",
839 "expander did not return a memoized expression",
840 scm_list_1 (exp));
b7742c6b
AW
841 return eval (exp, SCM_EOL);
842}
5f161164
AW
843
844static SCM var_primitive_eval;
845SCM
846scm_primitive_eval (SCM exp)
847{
848 return scm_c_vm_run (scm_the_vm (), scm_variable_ref (var_primitive_eval),
849 &exp, 1);
850}
71560395 851
b7742c6b
AW
852
853/* Eval does not take the second arg optionally. This is intentional
854 * in order to be R5RS compatible, and to prepare for the new module
855 * system, where we would like to make the choice of evaluation
856 * environment explicit. */
857
858SCM_DEFINE (scm_eval, "eval", 2, 0, 0,
859 (SCM exp, SCM module_or_state),
860 "Evaluate @var{exp}, a list representing a Scheme expression,\n"
861 "in the top-level environment specified by\n"
862 "@var{module_or_state}.\n"
863 "While @var{exp} is evaluated (using @code{primitive-eval}),\n"
864 "@var{module_or_state} is made the current module when\n"
865 "it is a module, or the current dynamic state when it is\n"
866 "a dynamic state."
867 "Example: (eval '(+ 1 2) (interaction-environment))")
868#define FUNC_NAME s_scm_eval
869{
870 SCM res;
871
872 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
873 if (scm_is_dynamic_state (module_or_state))
874 scm_dynwind_current_dynamic_state (module_or_state);
875 else if (scm_module_system_booted_p)
876 {
877 SCM_VALIDATE_MODULE (2, module_or_state);
878 scm_dynwind_current_module (module_or_state);
71560395 879 }
b7742c6b 880 /* otherwise if the module system isn't booted, ignore the module arg */
71560395 881
b7742c6b
AW
882 res = scm_primitive_eval (exp);
883
884 scm_dynwind_end ();
885 return res;
886}
887#undef FUNC_NAME
71560395
AW
888
889
b7742c6b 890static SCM f_apply;
71560395
AW
891
892/* Apply a function to a list of arguments.
893
894 This function is exported to the Scheme level as taking two
895 required arguments and a tail argument, as if it were:
896 (lambda (proc arg1 . args) ...)
897 Thus, if you just have a list of arguments to pass to a procedure,
898 pass the list as ARG1, and '() for ARGS. If you have some fixed
899 args, pass the first as ARG1, then cons any remaining fixed args
900 onto the front of your argument list, and pass that as ARGS. */
901
902SCM
903scm_apply (SCM proc, SCM arg1, SCM args)
904{
b7742c6b 905 /* Fix things up so that args contains all args. */
71560395 906 if (scm_is_null (args))
b7742c6b 907 args = arg1;
71560395 908 else
b7742c6b 909 args = scm_cons_star (arg1, args);
71560395 910
67e2d80a 911 return scm_vm_apply (scm_the_vm (), proc, args);
b7742c6b 912}
434f2f7a 913
7572ee52
AW
914static void
915prepare_boot_closure_env_for_apply (SCM proc, SCM args,
916 SCM *out_body, SCM *out_env)
314b8716 917{
8f9c5b58
AW
918 int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
919 SCM env = BOOT_CLOSURE_ENV (proc);
dc3e203e 920
8f9c5b58
AW
921 if (BOOT_CLOSURE_IS_FIXED (proc)
922 || (BOOT_CLOSURE_IS_REST (proc)
923 && !BOOT_CLOSURE_HAS_REST_ARGS (proc)))
924 {
925 if (SCM_UNLIKELY (scm_ilength (args) != nreq))
926 scm_wrong_num_args (proc);
927 for (; scm_is_pair (args); args = CDR (args))
928 env = scm_cons (CAR (args), env);
7572ee52
AW
929 *out_body = BOOT_CLOSURE_BODY (proc);
930 *out_env = env;
8f9c5b58
AW
931 }
932 else if (BOOT_CLOSURE_IS_REST (proc))
314b8716
AW
933 {
934 if (SCM_UNLIKELY (scm_ilength (args) < nreq))
8f9c5b58 935 scm_wrong_num_args (proc);
314b8716 936 for (; nreq; nreq--, args = CDR (args))
8f9c5b58
AW
937 env = scm_cons (CAR (args), env);
938 env = scm_cons (args, env);
7572ee52
AW
939 *out_body = BOOT_CLOSURE_BODY (proc);
940 *out_env = env;
314b8716
AW
941 }
942 else
d8a071fc
AW
943 {
944 int i, argc, nreq, nopt;
945 SCM body, rest, kw, inits, alt;
dc3e203e 946 SCM mx = BOOT_CLOSURE_CODE (proc);
d8a071fc 947
7572ee52 948 loop:
dc3e203e 949 BOOT_CLOSURE_PARSE_FULL (mx, body, nargs, rest, nopt, kw, inits, alt);
d8a071fc
AW
950
951 argc = scm_ilength (args);
952 if (argc < nreq)
953 {
954 if (scm_is_true (alt))
7572ee52 955 {
dc3e203e 956 mx = alt;
7572ee52
AW
957 goto loop;
958 }
d8a071fc
AW
959 else
960 scm_wrong_num_args (proc);
961 }
962 if (scm_is_false (kw) && argc > nreq + nopt && scm_is_false (rest))
963 {
964 if (scm_is_true (alt))
7572ee52 965 {
dc3e203e 966 mx = alt;
7572ee52
AW
967 goto loop;
968 }
d8a071fc
AW
969 else
970 scm_wrong_num_args (proc);
971 }
972
973 for (i = 0; i < nreq; i++, args = CDR (args))
974 env = scm_cons (CAR (args), env);
975
976 if (scm_is_false (kw))
977 {
978 /* Optional args (possibly), but no keyword args. */
979 for (; i < argc && i < nreq + nopt;
980 i++, args = CDR (args))
981 {
982 env = scm_cons (CAR (args), env);
983 inits = CDR (inits);
984 }
985
986 for (; i < nreq + nopt; i++, inits = CDR (inits))
987 env = scm_cons (eval (CAR (inits), env), env);
988
989 if (scm_is_true (rest))
990 env = scm_cons (args, env);
991 }
992 else
993 {
994 SCM aok;
995
996 aok = CAR (kw);
997 kw = CDR (kw);
998
999 /* Keyword args. As before, but stop at the first keyword. */
1000 for (; i < argc && i < nreq + nopt && !scm_is_keyword (CAR (args));
1001 i++, args = CDR (args), inits = CDR (inits))
1002 env = scm_cons (CAR (args), env);
1003
1004 for (; i < nreq + nopt; i++, inits = CDR (inits))
1005 env = scm_cons (eval (CAR (inits), env), env);
1006
1007 if (scm_is_true (rest))
1008 {
1009 env = scm_cons (args, env);
1010 i++;
1011 }
1012
1013 /* Now fill in env with unbound values, limn the rest of the args for
1014 keywords, and fill in unbound values with their inits. */
1015 {
1016 int imax = i - 1;
1017 int kw_start_idx = i;
1018 SCM walk, k, v;
1019 for (walk = kw; scm_is_pair (walk); walk = CDR (walk))
1020 if (SCM_I_INUM (CDAR (walk)) > imax)
1021 imax = SCM_I_INUM (CDAR (walk));
1022 for (; i <= imax; i++)
1023 env = scm_cons (SCM_UNDEFINED, env);
1024
1025 if (scm_is_pair (args) && scm_is_pair (CDR (args)))
1026 for (; scm_is_pair (args) && scm_is_pair (CDR (args));
1027 args = CDR (args))
1028 {
1029 k = CAR (args); v = CADR (args);
1030 if (!scm_is_keyword (k))
1031 {
1032 if (scm_is_true (rest))
1033 continue;
1034 else
1035 break;
1036 }
1037 for (walk = kw; scm_is_pair (walk); walk = CDR (walk))
1038 if (scm_is_eq (k, CAAR (walk)))
1039 {
1040 /* Well... ok, list-set! isn't the nicest interface, but
1041 hey. */
1042 int iset = imax - SCM_I_INUM (CDAR (walk));
1043 scm_list_set_x (env, SCM_I_MAKINUM (iset), v);
1044 args = CDR (args);
1045 break;
1046 }
1047 if (scm_is_null (walk) && scm_is_false (aok))
1048 error_unrecognized_keyword (proc);
1049 }
1050 if (scm_is_pair (args) && scm_is_false (rest))
1051 error_invalid_keyword (proc);
1052
1053 /* Now fill in unbound values, evaluating init expressions in their
1054 appropriate environment. */
1055 for (i = imax - kw_start_idx; scm_is_pair (inits); i--, inits = CDR (inits))
1056 {
1057 SCM tail = scm_list_tail (env, SCM_I_MAKINUM (i));
1058 if (SCM_UNBNDP (CAR (tail)))
1059 SCM_SETCAR (tail, eval (CAR (inits), CDR (tail)));
1060 }
1061 }
1062 }
8f9c5b58 1063
dc3e203e 1064 *out_body = body;
7572ee52
AW
1065 *out_env = env;
1066 }
8f9c5b58
AW
1067}
1068
7572ee52 1069static void
8f9c5b58 1070prepare_boot_closure_env_for_eval (SCM proc, unsigned int argc,
7572ee52 1071 SCM exps, SCM *out_body, SCM *inout_env)
8f9c5b58
AW
1072{
1073 int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
1074 SCM new_env = BOOT_CLOSURE_ENV (proc);
1075 if (BOOT_CLOSURE_IS_FIXED (proc)
1076 || (BOOT_CLOSURE_IS_REST (proc)
1077 && !BOOT_CLOSURE_HAS_REST_ARGS (proc)))
314b8716 1078 {
8f9c5b58 1079 for (; scm_is_pair (exps); exps = CDR (exps), nreq--)
7572ee52 1080 new_env = scm_cons (eval (CAR (exps), *inout_env), new_env);
8f9c5b58
AW
1081 if (SCM_UNLIKELY (nreq != 0))
1082 scm_wrong_num_args (proc);
7572ee52
AW
1083 *out_body = BOOT_CLOSURE_BODY (proc);
1084 *inout_env = new_env;
314b8716 1085 }
8f9c5b58
AW
1086 else if (BOOT_CLOSURE_IS_REST (proc))
1087 {
1088 if (SCM_UNLIKELY (argc < nreq))
1089 scm_wrong_num_args (proc);
1090 for (; nreq; nreq--, exps = CDR (exps))
7572ee52 1091 new_env = scm_cons (eval (CAR (exps), *inout_env), new_env);
8f9c5b58
AW
1092 {
1093 SCM rest = SCM_EOL;
1094 for (; scm_is_pair (exps); exps = CDR (exps))
7572ee52 1095 rest = scm_cons (eval (CAR (exps), *inout_env), rest);
8f9c5b58
AW
1096 new_env = scm_cons (scm_reverse (rest),
1097 new_env);
1098 }
7572ee52
AW
1099 *out_body = BOOT_CLOSURE_BODY (proc);
1100 *inout_env = new_env;
8f9c5b58
AW
1101 }
1102 else
d8a071fc
AW
1103 {
1104 SCM args = SCM_EOL;
1105 for (; scm_is_pair (exps); exps = CDR (exps))
7572ee52
AW
1106 args = scm_cons (eval (CAR (exps), *inout_env), args);
1107 args = scm_reverse_x (args, SCM_UNDEFINED);
1108 prepare_boot_closure_env_for_apply (proc, args, out_body, inout_env);
d8a071fc 1109 }
8f9c5b58
AW
1110}
1111
1112static SCM
1113boot_closure_apply (SCM closure, SCM args)
1114{
7572ee52
AW
1115 SCM body, env;
1116 prepare_boot_closure_env_for_apply (closure, args, &body, &env);
1117 return eval (body, env);
314b8716
AW
1118}
1119
1120static int
1121boot_closure_print (SCM closure, SCM port, scm_print_state *pstate)
1122{
1123 SCM args;
1124 scm_puts ("#<boot-closure ", port);
1125 scm_uintprint ((unsigned long)SCM2PTR (closure), 16, port);
1126 scm_putc (' ', port);
1127 args = scm_make_list (scm_from_int (BOOT_CLOSURE_NUM_REQUIRED_ARGS (closure)),
1128 scm_from_locale_symbol ("_"));
8f9c5b58 1129 if (!BOOT_CLOSURE_IS_FIXED (closure) && BOOT_CLOSURE_HAS_REST_ARGS (closure))
314b8716 1130 args = scm_cons_star (scm_from_locale_symbol ("_"), args);
7572ee52 1131 /* FIXME: optionals and rests */
314b8716
AW
1132 scm_display (args, port);
1133 scm_putc ('>', port);
1134 return 1;
1135}
1136
0f2d19dd
JB
1137void
1138scm_init_eval ()
0f2d19dd 1139{
5f161164
AW
1140 SCM primitive_eval;
1141
33b97402 1142 scm_init_opts (scm_evaluator_traps,
62560650 1143 scm_evaluator_trap_table);
33b97402 1144 scm_init_opts (scm_eval_options_interface,
62560650 1145 scm_eval_opts);
33b97402 1146
df9ca8d8 1147 f_apply = scm_c_define_gsubr ("apply", 2, 0, 1, scm_apply);
86d31dfe 1148
314b8716
AW
1149 scm_tc16_boot_closure = scm_make_smob_type ("boot-closure", 0);
1150 scm_set_smob_apply (scm_tc16_boot_closure, boot_closure_apply, 0, 0, 1);
1151 scm_set_smob_print (scm_tc16_boot_closure, boot_closure_print);
1152
5f161164
AW
1153 primitive_eval = scm_c_make_gsubr ("primitive-eval", 1, 0, 0,
1154 scm_c_primitive_eval);
1155 var_primitive_eval = scm_define (SCM_SUBR_NAME (primitive_eval),
1156 primitive_eval);
1157
a0599745 1158#include "libguile/eval.x"
0f2d19dd 1159}
0f2d19dd 1160
89e00824
ML
1161/*
1162 Local Variables:
1163 c-file-style: "gnu"
1164 End:
1165*/
62560650 1166