Simplify the interpreter for trivial inits and no letrec
[bpt/guile.git] / libguile / eval.c
CommitLineData
747bd534 1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,
dc7a33fa 2 * 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014
434f2f7a 3 * Free Software Foundation, Inc.
0f2d19dd 4 *
73be1d9e 5 * This library is free software; you can redistribute it and/or
53befeb7
NJ
6 * modify it under the terms of the GNU Lesser General Public License
7 * as published by the Free Software Foundation; either version 3 of
8 * the License, or (at your option) any later version.
0f2d19dd 9 *
53befeb7
NJ
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
0f2d19dd 14 *
73be1d9e
MV
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
53befeb7
NJ
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301 USA
73be1d9e 19 */
1bbd0b84 20
0f2d19dd
JB
21\f
22
dbb605f5 23#ifdef HAVE_CONFIG_H
3d05f2e0
RB
24# include <config.h>
25#endif
0f2d19dd 26
f7439099 27#include <alloca.h>
741b8a23 28#include <stdarg.h>
3d05f2e0 29
f7439099 30#include "libguile/__scm.h"
48b96f4b 31
a0599745 32#include "libguile/_scm.h"
21628685
DH
33#include "libguile/alist.h"
34#include "libguile/async.h"
35#include "libguile/continuations.h"
747022e4 36#include "libguile/control.h"
a0599745 37#include "libguile/debug.h"
328dc9a3 38#include "libguile/deprecation.h"
09074dbf 39#include "libguile/dynwind.h"
a0599745 40#include "libguile/eq.h"
a310a1d1 41#include "libguile/expand.h"
21628685 42#include "libguile/feature.h"
21628685
DH
43#include "libguile/goops.h"
44#include "libguile/hash.h"
45#include "libguile/hashtab.h"
4610b011 46#include "libguile/list.h"
a0599745 47#include "libguile/macros.h"
b7742c6b 48#include "libguile/memoize.h"
a0599745
MD
49#include "libguile/modules.h"
50#include "libguile/ports.h"
7e6e6b37 51#include "libguile/print.h"
21628685 52#include "libguile/procprop.h"
4abef68f 53#include "libguile/programs.h"
a0599745 54#include "libguile/root.h"
21628685
DH
55#include "libguile/smob.h"
56#include "libguile/srcprop.h"
57#include "libguile/stackchk.h"
58#include "libguile/strings.h"
9de87eea 59#include "libguile/threads.h"
21628685
DH
60#include "libguile/throw.h"
61#include "libguile/validate.h"
a513ead3 62#include "libguile/values.h"
21628685 63#include "libguile/vectors.h"
4abef68f 64#include "libguile/vm.h"
a0599745 65
a0599745 66#include "libguile/eval.h"
0ee05b85 67#include "libguile/private-options.h"
89efbff4 68
0f2d19dd
JB
69\f
70
0ee05b85 71
b7742c6b 72/* We have three levels of EVAL here:
609a8b86 73
b7742c6b 74 - eval (exp, env)
89bff2fc 75
b7742c6b
AW
76 evaluates EXP in environment ENV. ENV is a lexical environment
77 structure as used by the actual tree code evaluator. When ENV is
78 a top-level environment, then changes to the current module are
79 tracked by updating ENV so that it continues to be in sync with
80 the current module.
e6729603 81
b7742c6b 82 - scm_primitive_eval (exp)
e6729603 83
b7742c6b
AW
84 evaluates EXP in the top-level environment as determined by the
85 current module. This is done by constructing a suitable
86 environment and calling eval. Thus, changes to the
87 top-level module are tracked normally.
e6729603 88
b7742c6b 89 - scm_eval (exp, mod)
e6729603 90
b7742c6b
AW
91 evaluates EXP while MOD is the current module. This is done
92 by setting the current module to MOD_OR_STATE, invoking
93 scm_primitive_eval on EXP, and then restoring the current module
94 to the value it had previously. That is, while EXP is evaluated,
95 changes to the current module (or dynamic state) are tracked,
96 but these changes do not persist when scm_eval returns.
e6729603 97
b7742c6b 98*/
e6729603 99
e6729603 100
314b8716
AW
101/* Boot closures. We only see these when compiling eval.scm, because once
102 eval.scm is in the house, closures are standard VM closures.
103 */
104
105static scm_t_bits scm_tc16_boot_closure;
b2b33168
AW
106#define RETURN_BOOT_CLOSURE(code, env) \
107 SCM_RETURN_NEWSMOB2 (scm_tc16_boot_closure, SCM_UNPACK (code), SCM_UNPACK (env))
314b8716
AW
108#define BOOT_CLOSURE_P(obj) SCM_TYP16_PREDICATE (scm_tc16_boot_closure, (obj))
109#define BOOT_CLOSURE_CODE(x) SCM_SMOB_OBJECT (x)
110#define BOOT_CLOSURE_ENV(x) SCM_SMOB_OBJECT_2 (x)
8f9c5b58 111#define BOOT_CLOSURE_BODY(x) CAR (BOOT_CLOSURE_CODE (x))
c438cd71
LC
112#define BOOT_CLOSURE_NUM_REQUIRED_ARGS(x) (SCM_I_INUM (CADDR (BOOT_CLOSURE_CODE (x))))
113#define BOOT_CLOSURE_IS_FIXED(x) (scm_is_null (CDDDR (BOOT_CLOSURE_CODE (x))))
8f9c5b58 114/* NB: One may only call the following accessors if the closure is not FIXED. */
c438cd71
LC
115#define BOOT_CLOSURE_HAS_REST_ARGS(x) scm_is_true (CADDR (SCM_CDR (BOOT_CLOSURE_CODE (x))))
116#define BOOT_CLOSURE_IS_REST(x) scm_is_null (SCM_CDR (CDDDR (BOOT_CLOSURE_CODE (x))))
8f9c5b58
AW
117/* NB: One may only call the following accessors if the closure is not REST. */
118#define BOOT_CLOSURE_IS_FULL(x) (1)
cfdc8416 119#define BOOT_CLOSURE_PARSE_FULL(fu_,body,nargs,rest,nopt,kw,ninits,unbound,alt) \
dc3e203e 120 do { SCM fu = fu_; \
c438cd71 121 body = CAR (fu); fu = CDDR (fu); \
dc3e203e
AW
122 \
123 rest = kw = alt = SCM_BOOL_F; \
cfdc8416
AW
124 unbound = SCM_BOOL_F; \
125 nopt = ninits = 0; \
dc3e203e
AW
126 \
127 nreq = SCM_I_INUM (CAR (fu)); fu = CDR (fu); \
128 if (scm_is_pair (fu)) \
129 { \
130 rest = CAR (fu); fu = CDR (fu); \
131 if (scm_is_pair (fu)) \
132 { \
133 nopt = SCM_I_INUM (CAR (fu)); fu = CDR (fu); \
134 kw = CAR (fu); fu = CDR (fu); \
cfdc8416
AW
135 ninits = SCM_I_INUM (CAR (fu)); fu = CDR (fu); \
136 unbound = CAR (fu); fu = CDR (fu); \
dc3e203e
AW
137 alt = CAR (fu); \
138 } \
139 } \
d8a071fc 140 } while (0)
7572ee52
AW
141static void prepare_boot_closure_env_for_apply (SCM proc, SCM args,
142 SCM *out_body, SCM *out_env);
143static void prepare_boot_closure_env_for_eval (SCM proc, unsigned int argc,
144 SCM exps, SCM *out_body,
145 SCM *inout_env);
314b8716
AW
146
147
b7742c6b
AW
148#define CAR(x) SCM_CAR(x)
149#define CDR(x) SCM_CDR(x)
150#define CAAR(x) SCM_CAAR(x)
151#define CADR(x) SCM_CADR(x)
152#define CDAR(x) SCM_CDAR(x)
153#define CDDR(x) SCM_CDDR(x)
154#define CADDR(x) SCM_CADDR(x)
155#define CDDDR(x) SCM_CDDDR(x)
e6729603 156
cfc28c80
AW
157#define VECTOR_REF(v, i) (SCM_SIMPLE_VECTOR_REF (v, i))
158#define VECTOR_SET(v, i, x) (SCM_SIMPLE_VECTOR_SET (v, i, x))
159#define VECTOR_LENGTH(v) (SCM_SIMPLE_VECTOR_LENGTH (v))
160
161static SCM
162make_env (int n, SCM init, SCM next)
163{
164 SCM env = scm_c_make_vector (n + 1, init);
165 VECTOR_SET (env, 0, next);
166 return env;
167}
168
169static SCM
170next_rib (SCM env)
171{
172 return VECTOR_REF (env, 0);
173}
174
175static SCM
176env_tail (SCM env)
177{
178 while (SCM_I_IS_VECTOR (env))
179 env = next_rib (env);
180 return env;
181}
182
183static SCM
184env_ref (SCM env, int depth, int width)
185{
186 while (depth--)
187 env = next_rib (env);
188 return VECTOR_REF (env, width + 1);
189}
190
191static void
192env_set (SCM env, int depth, int width, SCM val)
193{
194 while (depth--)
195 env = next_rib (env);
196 VECTOR_SET (env, width + 1, val);
197}
198
e6729603 199
4af0d97e 200static void error_invalid_keyword (SCM proc, SCM obj)
d8a071fc 201{
4a655e50 202 scm_error_scm (scm_from_latin1_symbol ("keyword-argument-error"), proc,
d8a071fc 203 scm_from_locale_string ("Invalid keyword"), SCM_EOL,
4af0d97e 204 scm_list_1 (obj));
d8a071fc
AW
205}
206
4af0d97e 207static void error_unrecognized_keyword (SCM proc, SCM kw)
d8a071fc 208{
4a655e50 209 scm_error_scm (scm_from_latin1_symbol ("keyword-argument-error"), proc,
d8a071fc 210 scm_from_locale_string ("Unrecognized keyword"), SCM_EOL,
4af0d97e 211 scm_list_1 (kw));
d8a071fc
AW
212}
213
214
f3a9a51d
AW
215/* Multiple values truncation. */
216static SCM
217truncate_values (SCM x)
218{
219 if (SCM_LIKELY (!SCM_VALUESP (x)))
220 return x;
221 else
222 {
223 SCM l = scm_struct_ref (x, SCM_INUM0);
224 if (SCM_LIKELY (scm_is_pair (l)))
225 return scm_car (l);
226 else
227 {
228 scm_ithrow (scm_from_latin1_symbol ("vm-run"),
229 scm_list_3 (scm_from_latin1_symbol ("vm-run"),
230 scm_from_locale_string
231 ("Too few values returned to continuation"),
232 SCM_EOL),
233 1);
234 /* Not reached. */
235 return SCM_BOOL_F;
236 }
237 }
238}
239#define EVAL1(x, env) (truncate_values (eval ((x), (env))))
240
6f81708a 241static SCM
b7742c6b 242eval (SCM x, SCM env)
6f81708a 243{
b7742c6b
AW
244 SCM mx;
245 SCM proc = SCM_UNDEFINED, args = SCM_EOL;
b7ecadca 246 unsigned int argc;
6f81708a 247
b7742c6b
AW
248 loop:
249 SCM_TICK;
b7742c6b
AW
250
251 mx = SCM_MEMOIZED_ARGS (x);
0720f70e 252 switch (SCM_I_INUM (SCM_CAR (x)))
b7742c6b 253 {
6fc3eae4
AW
254 case SCM_M_SEQ:
255 eval (CAR (mx), env);
256 x = CDR (mx);
b7742c6b
AW
257 goto loop;
258
259 case SCM_M_IF:
f3a9a51d 260 if (scm_is_true (EVAL1 (CAR (mx), env)))
b7742c6b 261 x = CADR (mx);
6f81708a 262 else
b7742c6b
AW
263 x = CDDR (mx);
264 goto loop;
5fb64383 265
b7742c6b
AW
266 case SCM_M_LET:
267 {
268 SCM inits = CAR (mx);
cfc28c80
AW
269 SCM new_env;
270 int i;
271
ef47c422 272 new_env = make_env (VECTOR_LENGTH (inits), SCM_UNDEFINED, env);
cfc28c80
AW
273 for (i = 0; i < VECTOR_LENGTH (inits); i++)
274 env_set (new_env, 0, i, EVAL1 (VECTOR_REF (inits, i), env));
b7742c6b
AW
275 env = new_env;
276 x = CDR (mx);
277 goto loop;
278 }
279
280 case SCM_M_LAMBDA:
ef47c422 281 RETURN_BOOT_CLOSURE (mx, env);
5fb64383 282
b7742c6b
AW
283 case SCM_M_QUOTE:
284 return mx;
0f2d19dd 285
b7742c6b 286 case SCM_M_DEFINE:
f3a9a51d 287 scm_define (CAR (mx), EVAL1 (CDR (mx), env));
b7742c6b 288 return SCM_UNSPECIFIED;
212e58ed 289
ef47c422
AW
290 case SCM_M_CAPTURE_MODULE:
291 return eval (mx, scm_current_module ());
292
b7742c6b
AW
293 case SCM_M_APPLY:
294 /* Evaluate the procedure to be applied. */
f3a9a51d 295 proc = EVAL1 (CAR (mx), env);
b7742c6b 296 /* Evaluate the argument holding the list of arguments */
f3a9a51d 297 args = EVAL1 (CADR (mx), env);
b7742c6b
AW
298
299 apply_proc:
300 /* Go here to tail-apply a procedure. PROC is the procedure and
301 * ARGS is the list of arguments. */
314b8716 302 if (BOOT_CLOSURE_P (proc))
b7742c6b 303 {
7572ee52 304 prepare_boot_closure_env_for_apply (proc, args, &x, &env);
b7742c6b
AW
305 goto loop;
306 }
307 else
6b4ba76d 308 return scm_apply_0 (proc, args);
212e58ed 309
b7742c6b
AW
310 case SCM_M_CALL:
311 /* Evaluate the procedure to be applied. */
f3a9a51d 312 proc = EVAL1 (CAR (mx), env);
b7ecadca 313 argc = SCM_I_INUM (CADR (mx));
9331f91c 314 mx = CDDR (mx);
212e58ed 315
314b8716 316 if (BOOT_CLOSURE_P (proc))
5fa0939c 317 {
7572ee52 318 prepare_boot_closure_env_for_eval (proc, argc, mx, &x, &env);
b7742c6b 319 goto loop;
5fa0939c 320 }
b7742c6b
AW
321 else
322 {
e2cf8eb9 323 SCM *argv;
b7ecadca
LC
324 unsigned int i;
325
e2cf8eb9 326 argv = alloca (argc * sizeof (SCM));
b7ecadca 327 for (i = 0; i < argc; i++, mx = CDR (mx))
f3a9a51d 328 argv[i] = EVAL1 (CAR (mx), env);
b7ecadca 329
55ee3607 330 return scm_call_n (proc, argv, argc);
b7742c6b 331 }
b7ecadca 332
b7742c6b 333 case SCM_M_CONT:
f3a9a51d 334 return scm_i_call_with_current_continuation (EVAL1 (mx, env));
212e58ed 335
b7742c6b
AW
336 case SCM_M_CALL_WITH_VALUES:
337 {
338 SCM producer;
339 SCM v;
340
f3a9a51d
AW
341 producer = EVAL1 (CAR (mx), env);
342 /* `proc' is the consumer. */
343 proc = EVAL1 (CDR (mx), env);
6b4ba76d 344 v = scm_call_0 (producer);
b7742c6b
AW
345 if (SCM_VALUESP (v))
346 args = scm_struct_ref (v, SCM_INUM0);
347 else
348 args = scm_list_1 (v);
349 goto apply_proc;
350 }
26d5b9b4 351
b7742c6b
AW
352 case SCM_M_LEXICAL_REF:
353 {
cfdc8416 354 SCM pos;
cfc28c80
AW
355 int depth, width;
356
357 pos = mx;
358 depth = SCM_I_INUM (CAR (pos));
359 width = SCM_I_INUM (CDR (pos));
360
cfdc8416 361 return env_ref (env, depth, width);
b7742c6b 362 }
1cc91f1b 363
b7742c6b
AW
364 case SCM_M_LEXICAL_SET:
365 {
cfc28c80
AW
366 SCM pos;
367 int depth, width;
f3a9a51d 368 SCM val = EVAL1 (CDR (mx), env);
cfc28c80
AW
369
370 pos = CAR (mx);
371 depth = SCM_I_INUM (CAR (pos));
372 width = SCM_I_INUM (CDR (pos));
373
374 env_set (env, depth, width, val);
375
b7742c6b
AW
376 return SCM_UNSPECIFIED;
377 }
910b5125 378
b7742c6b
AW
379 case SCM_M_TOPLEVEL_REF:
380 if (SCM_VARIABLEP (mx))
381 return SCM_VARIABLE_REF (mx);
382 else
57d23e25 383 {
cfc28c80 384 env = env_tail (env);
ef47c422 385 return SCM_VARIABLE_REF (scm_memoize_variable_access_x (x, env));
57d23e25 386 }
57d23e25 387
b7742c6b
AW
388 case SCM_M_TOPLEVEL_SET:
389 {
390 SCM var = CAR (mx);
f3a9a51d 391 SCM val = EVAL1 (CDR (mx), env);
b7742c6b
AW
392 if (SCM_VARIABLEP (var))
393 {
394 SCM_VARIABLE_SET (var, val);
395 return SCM_UNSPECIFIED;
396 }
397 else
398 {
cfc28c80 399 env = env_tail (env);
ef47c422 400 SCM_VARIABLE_SET (scm_memoize_variable_access_x (x, env), val);
b7742c6b
AW
401 return SCM_UNSPECIFIED;
402 }
403 }
910b5125 404
b7742c6b
AW
405 case SCM_M_MODULE_REF:
406 if (SCM_VARIABLEP (mx))
407 return SCM_VARIABLE_REF (mx);
910b5125 408 else
3149a5b6
AW
409 return SCM_VARIABLE_REF
410 (scm_memoize_variable_access_x (x, SCM_BOOL_F));
910b5125 411
b7742c6b
AW
412 case SCM_M_MODULE_SET:
413 if (SCM_VARIABLEP (CDR (mx)))
910b5125 414 {
f3a9a51d 415 SCM_VARIABLE_SET (CDR (mx), EVAL1 (CAR (mx), env));
b7742c6b
AW
416 return SCM_UNSPECIFIED;
417 }
418 else
419 {
3149a5b6
AW
420 SCM_VARIABLE_SET
421 (scm_memoize_variable_access_x (x, SCM_BOOL_F),
f3a9a51d 422 EVAL1 (CAR (mx), env));
b7742c6b 423 return SCM_UNSPECIFIED;
910b5125 424 }
910b5125 425
1773bc7d 426 case SCM_M_CALL_WITH_PROMPT:
747022e4 427 {
4fcbc1b0
AW
428 struct scm_vm *vp;
429 SCM k, res;
9d381ba4 430 scm_i_jmp_buf registers;
9ede013f
AW
431 /* We need the handler after nonlocal return to the setjmp, so
432 make sure it is volatile. */
433 volatile SCM handler;
434
435 k = EVAL1 (CAR (mx), env);
f3a9a51d 436 handler = EVAL1 (CDDR (mx), env);
e7f9abab 437 vp = scm_the_vm ();
9ede013f
AW
438
439 /* Push the prompt onto the dynamic stack. */
4fcbc1b0
AW
440 scm_dynstack_push_prompt (&SCM_I_CURRENT_THREAD->dynstack,
441 SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY
442 | SCM_F_DYNSTACK_PROMPT_PUSH_NARGS,
443 k,
444 vp->fp - vp->stack_base,
445 vp->sp - vp->stack_base,
446 vp->ip,
447 &registers);
9d381ba4
AW
448
449 if (SCM_I_SETJMP (registers))
747022e4 450 {
b8af64db 451 /* The prompt exited nonlocally. */
c2247b78 452 scm_gc_after_nonlocal_exit ();
747022e4 453 proc = handler;
e7f9abab 454 vp = scm_the_vm ();
4fcbc1b0 455 args = scm_i_prompt_pop_abort_args_x (vp);
747022e4
AW
456 goto apply_proc;
457 }
458
1773bc7d 459 res = scm_call_0 (eval (CADR (mx), env));
9ede013f 460 scm_dynstack_pop (&SCM_I_CURRENT_THREAD->dynstack);
747022e4
AW
461 return res;
462 }
463
b7742c6b
AW
464 default:
465 abort ();
466 }
910b5125
DH
467}
468
b7742c6b 469\f
2a6f7afe 470
b7742c6b
AW
471/* Simple procedure calls
472 */
2a6f7afe 473
b7742c6b
AW
474SCM
475scm_call_0 (SCM proc)
476{
55ee3607 477 return scm_call_n (proc, NULL, 0);
0f2d19dd
JB
478}
479
b7742c6b
AW
480SCM
481scm_call_1 (SCM proc, SCM arg1)
212e58ed 482{
55ee3607 483 return scm_call_n (proc, &arg1, 1);
b7742c6b 484}
212e58ed 485
b7742c6b
AW
486SCM
487scm_call_2 (SCM proc, SCM arg1, SCM arg2)
488{
bf5a05f2 489 SCM args[] = { arg1, arg2 };
55ee3607 490 return scm_call_n (proc, args, 2);
212e58ed
DH
491}
492
b7742c6b
AW
493SCM
494scm_call_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3)
0f2d19dd 495{
bf5a05f2 496 SCM args[] = { arg1, arg2, arg3 };
55ee3607 497 return scm_call_n (proc, args, 3);
0f2d19dd
JB
498}
499
b7742c6b
AW
500SCM
501scm_call_4 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4)
212e58ed 502{
bf5a05f2 503 SCM args[] = { arg1, arg2, arg3, arg4 };
55ee3607 504 return scm_call_n (proc, args, 4);
212e58ed
DH
505}
506
f32e67be
AW
507SCM
508scm_call_5 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5)
509{
510 SCM args[] = { arg1, arg2, arg3, arg4, arg5 };
55ee3607 511 return scm_call_n (proc, args, 5);
f32e67be
AW
512}
513
514SCM
515scm_call_6 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
516 SCM arg6)
517{
518 SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6 };
55ee3607 519 return scm_call_n (proc, args, 6);
f32e67be
AW
520}
521
741b8a23
MW
522SCM
523scm_call_7 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
524 SCM arg6, SCM arg7)
525{
526 SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7 };
55ee3607 527 return scm_call_n (proc, args, 7);
741b8a23
MW
528}
529
530SCM
531scm_call_8 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
532 SCM arg6, SCM arg7, SCM arg8)
533{
534 SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 };
55ee3607 535 return scm_call_n (proc, args, 8);
741b8a23
MW
536}
537
538SCM
539scm_call_9 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
540 SCM arg6, SCM arg7, SCM arg8, SCM arg9)
541{
542 SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 };
55ee3607 543 return scm_call_n (proc, args, 9);
741b8a23
MW
544}
545
55ee3607 546/* scm_call_n defined in vm.c */
86fd6dff 547
741b8a23 548SCM
07c2ca0f 549scm_call (SCM proc, ...)
741b8a23
MW
550{
551 va_list argp;
552 SCM *argv = NULL;
553 size_t i, nargs = 0;
554
555 va_start (argp, proc);
556 while (!SCM_UNBNDP (va_arg (argp, SCM)))
557 nargs++;
558 va_end (argp);
559
560 argv = alloca (nargs * sizeof (SCM));
561 va_start (argp, proc);
562 for (i = 0; i < nargs; i++)
563 argv[i] = va_arg (argp, SCM);
564 va_end (argp);
565
55ee3607 566 return scm_call_n (proc, argv, nargs);
741b8a23
MW
567}
568
b7742c6b 569/* Simple procedure applies
9fbee57e 570 */
cc56ba80 571
b7742c6b
AW
572SCM
573scm_apply_0 (SCM proc, SCM args)
574{
6b4ba76d
AW
575 SCM *argv;
576 int i, nargs;
577
578 nargs = scm_ilength (args);
579 if (SCM_UNLIKELY (nargs < 0))
580 scm_wrong_type_arg_msg ("apply", 2, args, "list");
581
582 /* FIXME: Use vm_builtin_apply instead of alloca. */
583 argv = alloca (nargs * sizeof(SCM));
584 for (i = 0; i < nargs; i++)
585 {
586 argv[i] = SCM_CAR (args);
587 args = SCM_CDR (args);
588 }
589
55ee3607 590 return scm_call_n (proc, argv, nargs);
0f572ba7
DH
591}
592
b7742c6b
AW
593SCM
594scm_apply_1 (SCM proc, SCM arg1, SCM args)
0f572ba7 595{
6b4ba76d 596 return scm_apply_0 (proc, scm_cons (arg1, args));
8ae95199
DH
597}
598
b7742c6b
AW
599SCM
600scm_apply_2 (SCM proc, SCM arg1, SCM arg2, SCM args)
0f2d19dd 601{
6b4ba76d 602 return scm_apply_0 (proc, scm_cons2 (arg1, arg2, args));
0f2d19dd
JB
603}
604
b7742c6b
AW
605SCM
606scm_apply_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM args)
212e58ed 607{
6b4ba76d 608 return scm_apply_0 (proc, scm_cons (arg1, scm_cons2 (arg2, arg3, args)));
212e58ed
DH
609}
610
60617d81
MW
611static SCM map_var, for_each_var;
612
613static void init_map_var (void)
614{
615 map_var = scm_private_variable (scm_the_root_module (),
616 scm_from_latin1_symbol ("map"));
617}
618
619static void init_for_each_var (void)
620{
621 for_each_var = scm_private_variable (scm_the_root_module (),
622 scm_from_latin1_symbol ("for-each"));
623}
b8229a3b 624
b7742c6b
AW
625SCM
626scm_map (SCM proc, SCM arg1, SCM args)
0f2d19dd 627{
60617d81
MW
628 static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT;
629 scm_i_pthread_once (&once, init_map_var);
0f2d19dd 630
dc7a33fa 631 return scm_apply_0 (scm_variable_ref (map_var),
6b4ba76d 632 scm_cons (proc, scm_cons (arg1, args)));
a2230b65 633}
d6754c23 634
b7742c6b
AW
635SCM
636scm_for_each (SCM proc, SCM arg1, SCM args)
0f2d19dd 637{
60617d81
MW
638 static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT;
639 scm_i_pthread_once (&once, init_for_each_var);
a2230b65 640
dc7a33fa 641 return scm_apply_0 (scm_variable_ref (for_each_var),
6b4ba76d 642 scm_cons (proc, scm_cons (arg1, args)));
b7742c6b 643}
71560395 644
71560395 645
5f161164
AW
646static SCM
647scm_c_primitive_eval (SCM exp)
b7742c6b 648{
a310a1d1 649 if (!SCM_EXPANDED_P (exp))
4f692ace 650 exp = scm_call_1 (scm_current_module_transformer (), exp);
ef47c422 651 return eval (scm_memoize_expression (exp), SCM_BOOL_F);
b7742c6b 652}
5f161164
AW
653
654static SCM var_primitive_eval;
655SCM
656scm_primitive_eval (SCM exp)
657{
55ee3607
AW
658 return scm_call_n (scm_variable_ref (var_primitive_eval),
659 &exp, 1);
5f161164 660}
71560395 661
b7742c6b
AW
662
663/* Eval does not take the second arg optionally. This is intentional
664 * in order to be R5RS compatible, and to prepare for the new module
665 * system, where we would like to make the choice of evaluation
666 * environment explicit. */
667
668SCM_DEFINE (scm_eval, "eval", 2, 0, 0,
669 (SCM exp, SCM module_or_state),
670 "Evaluate @var{exp}, a list representing a Scheme expression,\n"
671 "in the top-level environment specified by\n"
672 "@var{module_or_state}.\n"
673 "While @var{exp} is evaluated (using @code{primitive-eval}),\n"
674 "@var{module_or_state} is made the current module when\n"
675 "it is a module, or the current dynamic state when it is\n"
676 "a dynamic state."
677 "Example: (eval '(+ 1 2) (interaction-environment))")
678#define FUNC_NAME s_scm_eval
679{
680 SCM res;
681
682 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
683 if (scm_is_dynamic_state (module_or_state))
684 scm_dynwind_current_dynamic_state (module_or_state);
685 else if (scm_module_system_booted_p)
686 {
687 SCM_VALIDATE_MODULE (2, module_or_state);
688 scm_dynwind_current_module (module_or_state);
71560395 689 }
b7742c6b 690 /* otherwise if the module system isn't booted, ignore the module arg */
71560395 691
b7742c6b
AW
692 res = scm_primitive_eval (exp);
693
694 scm_dynwind_end ();
695 return res;
696}
697#undef FUNC_NAME
71560395
AW
698
699
b7742c6b 700static SCM f_apply;
71560395
AW
701
702/* Apply a function to a list of arguments.
703
6b4ba76d
AW
704 This function's interface is a bit wonly. It takes two required
705 arguments and a tail argument, as if it were:
706
71560395 707 (lambda (proc arg1 . args) ...)
6b4ba76d
AW
708
709 Usually you want to use scm_apply_0 or one of its cousins. */
71560395
AW
710
711SCM
712scm_apply (SCM proc, SCM arg1, SCM args)
713{
6b4ba76d
AW
714 return scm_apply_0 (proc,
715 scm_is_null (args) ? arg1 : scm_cons_star (arg1, args));
b7742c6b 716}
434f2f7a 717
7572ee52
AW
718static void
719prepare_boot_closure_env_for_apply (SCM proc, SCM args,
720 SCM *out_body, SCM *out_env)
314b8716 721{
8f9c5b58
AW
722 int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
723 SCM env = BOOT_CLOSURE_ENV (proc);
cfc28c80
AW
724 int i;
725
8f9c5b58
AW
726 if (BOOT_CLOSURE_IS_FIXED (proc)
727 || (BOOT_CLOSURE_IS_REST (proc)
728 && !BOOT_CLOSURE_HAS_REST_ARGS (proc)))
729 {
730 if (SCM_UNLIKELY (scm_ilength (args) != nreq))
731 scm_wrong_num_args (proc);
cfc28c80
AW
732
733 env = make_env (nreq, SCM_UNDEFINED, env);
734 for (i = 0; i < nreq; args = CDR (args), i++)
735 env_set (env, 0, i, CAR (args));
7572ee52
AW
736 *out_body = BOOT_CLOSURE_BODY (proc);
737 *out_env = env;
8f9c5b58
AW
738 }
739 else if (BOOT_CLOSURE_IS_REST (proc))
314b8716
AW
740 {
741 if (SCM_UNLIKELY (scm_ilength (args) < nreq))
8f9c5b58 742 scm_wrong_num_args (proc);
cfc28c80
AW
743
744 env = make_env (nreq + 1, SCM_UNDEFINED, env);
745 for (i = 0; i < nreq; args = CDR (args), i++)
746 env_set (env, 0, i, CAR (args));
747 env_set (env, 0, i++, args);
748
7572ee52
AW
749 *out_body = BOOT_CLOSURE_BODY (proc);
750 *out_env = env;
314b8716
AW
751 }
752 else
d8a071fc 753 {
cfdc8416
AW
754 int i, argc, nreq, nopt, ninits, nenv;
755 SCM body, rest, kw, unbound, alt;
dc3e203e 756 SCM mx = BOOT_CLOSURE_CODE (proc);
d8a071fc 757
7572ee52 758 loop:
cfdc8416
AW
759 BOOT_CLOSURE_PARSE_FULL (mx, body, nargs, rest, nopt, kw,
760 ninits, unbound, alt);
d8a071fc
AW
761
762 argc = scm_ilength (args);
763 if (argc < nreq)
764 {
765 if (scm_is_true (alt))
7572ee52 766 {
dc3e203e 767 mx = alt;
7572ee52
AW
768 goto loop;
769 }
d8a071fc
AW
770 else
771 scm_wrong_num_args (proc);
772 }
773 if (scm_is_false (kw) && argc > nreq + nopt && scm_is_false (rest))
774 {
775 if (scm_is_true (alt))
7572ee52 776 {
dc3e203e 777 mx = alt;
7572ee52
AW
778 goto loop;
779 }
d8a071fc
AW
780 else
781 scm_wrong_num_args (proc);
782 }
cfc28c80
AW
783 if (scm_is_true (kw) && scm_is_false (rest))
784 {
785 int npos = 0;
786 SCM walk;
787 for (walk = args; scm_is_pair (walk); walk = CDR (walk), npos++)
788 if (npos >= nreq && scm_is_keyword (CAR (walk)))
789 break;
790
791 if (npos > nreq + nopt)
792 {
793 /* Too many positional args and no rest arg. */
794 if (scm_is_true (alt))
795 {
796 mx = alt;
797 goto loop;
798 }
799 else
800 scm_wrong_num_args (proc);
801 }
802 }
803
804 /* At this point we are committed to the chosen clause. */
cfdc8416
AW
805 nenv = nreq + (scm_is_true (rest) ? 1 : 0) + ninits;
806 env = make_env (nenv, unbound, env);
d8a071fc
AW
807
808 for (i = 0; i < nreq; i++, args = CDR (args))
cfc28c80 809 env_set (env, 0, i, CAR (args));
d8a071fc
AW
810
811 if (scm_is_false (kw))
812 {
813 /* Optional args (possibly), but no keyword args. */
cfdc8416 814 for (; i < argc && i < nreq + nopt; i++, args = CDR (args))
cfc28c80 815 env_set (env, 0, i, CAR (args));
d8a071fc 816 if (scm_is_true (rest))
cfdc8416 817 env_set (env, 0, nreq + nopt, args);
d8a071fc
AW
818 }
819 else
820 {
821 SCM aok;
822
823 aok = CAR (kw);
824 kw = CDR (kw);
825
cfc28c80 826 /* Optional args. As before, but stop at the first keyword. */
d8a071fc 827 for (; i < argc && i < nreq + nopt && !scm_is_keyword (CAR (args));
cfdc8416 828 i++, args = CDR (args))
cfc28c80 829 env_set (env, 0, i, CAR (args));
d8a071fc 830 if (scm_is_true (rest))
cfdc8416 831 env_set (env, 0, nreq + nopt, args);
d8a071fc 832
cfc28c80 833 /* Parse keyword args. */
d8a071fc 834 {
cfc28c80 835 SCM walk;
d8a071fc
AW
836
837 if (scm_is_pair (args) && scm_is_pair (CDR (args)))
838 for (; scm_is_pair (args) && scm_is_pair (CDR (args));
839 args = CDR (args))
840 {
cfc28c80 841 SCM k = CAR (args), v = CADR (args);
d8a071fc
AW
842 if (!scm_is_keyword (k))
843 {
844 if (scm_is_true (rest))
845 continue;
846 else
847 break;
848 }
849 for (walk = kw; scm_is_pair (walk); walk = CDR (walk))
850 if (scm_is_eq (k, CAAR (walk)))
851 {
cfc28c80 852 env_set (env, 0, SCM_I_INUM (CDAR (walk)), v);
d8a071fc
AW
853 args = CDR (args);
854 break;
855 }
856 if (scm_is_null (walk) && scm_is_false (aok))
4af0d97e 857 error_unrecognized_keyword (proc, k);
d8a071fc
AW
858 }
859 if (scm_is_pair (args) && scm_is_false (rest))
4af0d97e 860 error_invalid_keyword (proc, CAR (args));
d8a071fc
AW
861 }
862 }
8f9c5b58 863
dc3e203e 864 *out_body = body;
7572ee52
AW
865 *out_env = env;
866 }
8f9c5b58
AW
867}
868
7572ee52 869static void
8f9c5b58 870prepare_boot_closure_env_for_eval (SCM proc, unsigned int argc,
7572ee52 871 SCM exps, SCM *out_body, SCM *inout_env)
8f9c5b58
AW
872{
873 int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
874 SCM new_env = BOOT_CLOSURE_ENV (proc);
cfc28c80
AW
875 if ((BOOT_CLOSURE_IS_FIXED (proc)
876 || (BOOT_CLOSURE_IS_REST (proc)
877 && !BOOT_CLOSURE_HAS_REST_ARGS (proc)))
878 && nreq == argc)
314b8716 879 {
cfc28c80
AW
880 int i;
881
882 new_env = make_env (nreq, SCM_UNDEFINED, new_env);
883 for (i = 0; i < nreq; exps = CDR (exps), i++)
884 env_set (new_env, 0, i, EVAL1 (CAR (exps), *inout_env));
885
7572ee52
AW
886 *out_body = BOOT_CLOSURE_BODY (proc);
887 *inout_env = new_env;
314b8716 888 }
cfc28c80 889 else if (BOOT_CLOSURE_IS_REST (proc) && argc >= nreq)
8f9c5b58 890 {
cfc28c80
AW
891 SCM rest;
892 int i;
893
894 new_env = make_env (nreq + 1, SCM_UNDEFINED, new_env);
895 for (i = 0; i < nreq; exps = CDR (exps), i++)
896 env_set (new_env, 0, i, EVAL1 (CAR (exps), *inout_env));
897 for (rest = SCM_EOL; scm_is_pair (exps); exps = CDR (exps))
898 rest = scm_cons (EVAL1 (CAR (exps), *inout_env), rest);
899 env_set (new_env, 0, i++, scm_reverse_x (rest, SCM_UNDEFINED));
900
7572ee52
AW
901 *out_body = BOOT_CLOSURE_BODY (proc);
902 *inout_env = new_env;
8f9c5b58
AW
903 }
904 else
d8a071fc
AW
905 {
906 SCM args = SCM_EOL;
907 for (; scm_is_pair (exps); exps = CDR (exps))
f3a9a51d 908 args = scm_cons (EVAL1 (CAR (exps), *inout_env), args);
7572ee52
AW
909 args = scm_reverse_x (args, SCM_UNDEFINED);
910 prepare_boot_closure_env_for_apply (proc, args, out_body, inout_env);
d8a071fc 911 }
8f9c5b58
AW
912}
913
914static SCM
915boot_closure_apply (SCM closure, SCM args)
916{
7572ee52
AW
917 SCM body, env;
918 prepare_boot_closure_env_for_apply (closure, args, &body, &env);
919 return eval (body, env);
314b8716
AW
920}
921
922static int
923boot_closure_print (SCM closure, SCM port, scm_print_state *pstate)
924{
925 SCM args;
0607ebbf 926 scm_puts_unlocked ("#<boot-closure ", port);
fdecb44f 927 scm_uintprint (SCM_UNPACK (closure), 16, port);
0607ebbf 928 scm_putc_unlocked (' ', port);
314b8716 929 args = scm_make_list (scm_from_int (BOOT_CLOSURE_NUM_REQUIRED_ARGS (closure)),
4a655e50 930 scm_from_latin1_symbol ("_"));
8f9c5b58 931 if (!BOOT_CLOSURE_IS_FIXED (closure) && BOOT_CLOSURE_HAS_REST_ARGS (closure))
4a655e50 932 args = scm_cons_star (scm_from_latin1_symbol ("_"), args);
7572ee52 933 /* FIXME: optionals and rests */
314b8716 934 scm_display (args, port);
0607ebbf 935 scm_putc_unlocked ('>', port);
314b8716
AW
936 return 1;
937}
938
0f2d19dd
JB
939void
940scm_init_eval ()
0f2d19dd 941{
5f161164
AW
942 SCM primitive_eval;
943
df9ca8d8 944 f_apply = scm_c_define_gsubr ("apply", 2, 0, 1, scm_apply);
86d31dfe 945
314b8716
AW
946 scm_tc16_boot_closure = scm_make_smob_type ("boot-closure", 0);
947 scm_set_smob_apply (scm_tc16_boot_closure, boot_closure_apply, 0, 0, 1);
948 scm_set_smob_print (scm_tc16_boot_closure, boot_closure_print);
949
5f161164
AW
950 primitive_eval = scm_c_make_gsubr ("primitive-eval", 1, 0, 0,
951 scm_c_primitive_eval);
952 var_primitive_eval = scm_define (SCM_SUBR_NAME (primitive_eval),
953 primitive_eval);
954
a0599745 955#include "libguile/eval.x"
0f2d19dd 956}
0f2d19dd 957
89e00824
ML
958/*
959 Local Variables:
960 c-file-style: "gnu"
961 End:
962*/
62560650 963