Add capture-env to evaluator
[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
99fb07e1
AW
283 case SCM_M_CAPTURE_ENV:
284 {
285 SCM locs = CAR (mx);
286 SCM new_env;
287 int i;
288
289 new_env = make_env (VECTOR_LENGTH (locs), SCM_BOOL_F, env);
290 for (i = 0; i < VECTOR_LENGTH (locs); i++)
291 {
292 SCM loc = VECTOR_REF (locs, i);
293 int depth, width;
294
295 depth = SCM_I_INUM (CAR (loc));
296 width = SCM_I_INUM (CDR (loc));
297 env_set (new_env, 0, i, env_ref (env, depth, width));
298 }
299
300 env = new_env;
301 x = CDR (mx);
302 goto loop;
303 }
304
b7742c6b
AW
305 case SCM_M_QUOTE:
306 return mx;
0f2d19dd 307
b7742c6b 308 case SCM_M_DEFINE:
f3a9a51d 309 scm_define (CAR (mx), EVAL1 (CDR (mx), env));
b7742c6b 310 return SCM_UNSPECIFIED;
212e58ed 311
ef47c422
AW
312 case SCM_M_CAPTURE_MODULE:
313 return eval (mx, scm_current_module ());
314
b7742c6b
AW
315 case SCM_M_APPLY:
316 /* Evaluate the procedure to be applied. */
f3a9a51d 317 proc = EVAL1 (CAR (mx), env);
b7742c6b 318 /* Evaluate the argument holding the list of arguments */
f3a9a51d 319 args = EVAL1 (CADR (mx), env);
b7742c6b
AW
320
321 apply_proc:
322 /* Go here to tail-apply a procedure. PROC is the procedure and
323 * ARGS is the list of arguments. */
314b8716 324 if (BOOT_CLOSURE_P (proc))
b7742c6b 325 {
7572ee52 326 prepare_boot_closure_env_for_apply (proc, args, &x, &env);
b7742c6b
AW
327 goto loop;
328 }
329 else
6b4ba76d 330 return scm_apply_0 (proc, args);
212e58ed 331
b7742c6b
AW
332 case SCM_M_CALL:
333 /* Evaluate the procedure to be applied. */
f3a9a51d 334 proc = EVAL1 (CAR (mx), env);
b7ecadca 335 argc = SCM_I_INUM (CADR (mx));
9331f91c 336 mx = CDDR (mx);
212e58ed 337
314b8716 338 if (BOOT_CLOSURE_P (proc))
5fa0939c 339 {
7572ee52 340 prepare_boot_closure_env_for_eval (proc, argc, mx, &x, &env);
b7742c6b 341 goto loop;
5fa0939c 342 }
b7742c6b
AW
343 else
344 {
e2cf8eb9 345 SCM *argv;
b7ecadca
LC
346 unsigned int i;
347
e2cf8eb9 348 argv = alloca (argc * sizeof (SCM));
b7ecadca 349 for (i = 0; i < argc; i++, mx = CDR (mx))
f3a9a51d 350 argv[i] = EVAL1 (CAR (mx), env);
b7ecadca 351
55ee3607 352 return scm_call_n (proc, argv, argc);
b7742c6b 353 }
b7ecadca 354
b7742c6b 355 case SCM_M_CONT:
f3a9a51d 356 return scm_i_call_with_current_continuation (EVAL1 (mx, env));
212e58ed 357
b7742c6b
AW
358 case SCM_M_CALL_WITH_VALUES:
359 {
360 SCM producer;
361 SCM v;
362
f3a9a51d
AW
363 producer = EVAL1 (CAR (mx), env);
364 /* `proc' is the consumer. */
365 proc = EVAL1 (CDR (mx), env);
6b4ba76d 366 v = scm_call_0 (producer);
b7742c6b
AW
367 if (SCM_VALUESP (v))
368 args = scm_struct_ref (v, SCM_INUM0);
369 else
370 args = scm_list_1 (v);
371 goto apply_proc;
372 }
26d5b9b4 373
b7742c6b
AW
374 case SCM_M_LEXICAL_REF:
375 {
cfdc8416 376 SCM pos;
cfc28c80
AW
377 int depth, width;
378
379 pos = mx;
380 depth = SCM_I_INUM (CAR (pos));
381 width = SCM_I_INUM (CDR (pos));
382
cfdc8416 383 return env_ref (env, depth, width);
b7742c6b 384 }
1cc91f1b 385
b7742c6b
AW
386 case SCM_M_LEXICAL_SET:
387 {
cfc28c80
AW
388 SCM pos;
389 int depth, width;
f3a9a51d 390 SCM val = EVAL1 (CDR (mx), env);
cfc28c80
AW
391
392 pos = CAR (mx);
393 depth = SCM_I_INUM (CAR (pos));
394 width = SCM_I_INUM (CDR (pos));
395
396 env_set (env, depth, width, val);
397
b7742c6b
AW
398 return SCM_UNSPECIFIED;
399 }
910b5125 400
b7742c6b
AW
401 case SCM_M_TOPLEVEL_REF:
402 if (SCM_VARIABLEP (mx))
403 return SCM_VARIABLE_REF (mx);
404 else
57d23e25 405 {
cfc28c80 406 env = env_tail (env);
ef47c422 407 return SCM_VARIABLE_REF (scm_memoize_variable_access_x (x, env));
57d23e25 408 }
57d23e25 409
b7742c6b
AW
410 case SCM_M_TOPLEVEL_SET:
411 {
412 SCM var = CAR (mx);
f3a9a51d 413 SCM val = EVAL1 (CDR (mx), env);
b7742c6b
AW
414 if (SCM_VARIABLEP (var))
415 {
416 SCM_VARIABLE_SET (var, val);
417 return SCM_UNSPECIFIED;
418 }
419 else
420 {
cfc28c80 421 env = env_tail (env);
ef47c422 422 SCM_VARIABLE_SET (scm_memoize_variable_access_x (x, env), val);
b7742c6b
AW
423 return SCM_UNSPECIFIED;
424 }
425 }
910b5125 426
b7742c6b
AW
427 case SCM_M_MODULE_REF:
428 if (SCM_VARIABLEP (mx))
429 return SCM_VARIABLE_REF (mx);
910b5125 430 else
3149a5b6
AW
431 return SCM_VARIABLE_REF
432 (scm_memoize_variable_access_x (x, SCM_BOOL_F));
910b5125 433
b7742c6b
AW
434 case SCM_M_MODULE_SET:
435 if (SCM_VARIABLEP (CDR (mx)))
910b5125 436 {
f3a9a51d 437 SCM_VARIABLE_SET (CDR (mx), EVAL1 (CAR (mx), env));
b7742c6b
AW
438 return SCM_UNSPECIFIED;
439 }
440 else
441 {
3149a5b6
AW
442 SCM_VARIABLE_SET
443 (scm_memoize_variable_access_x (x, SCM_BOOL_F),
f3a9a51d 444 EVAL1 (CAR (mx), env));
b7742c6b 445 return SCM_UNSPECIFIED;
910b5125 446 }
910b5125 447
1773bc7d 448 case SCM_M_CALL_WITH_PROMPT:
747022e4 449 {
4fcbc1b0
AW
450 struct scm_vm *vp;
451 SCM k, res;
9d381ba4 452 scm_i_jmp_buf registers;
9ede013f
AW
453 /* We need the handler after nonlocal return to the setjmp, so
454 make sure it is volatile. */
455 volatile SCM handler;
456
457 k = EVAL1 (CAR (mx), env);
f3a9a51d 458 handler = EVAL1 (CDDR (mx), env);
e7f9abab 459 vp = scm_the_vm ();
9ede013f
AW
460
461 /* Push the prompt onto the dynamic stack. */
4fcbc1b0
AW
462 scm_dynstack_push_prompt (&SCM_I_CURRENT_THREAD->dynstack,
463 SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY
464 | SCM_F_DYNSTACK_PROMPT_PUSH_NARGS,
465 k,
466 vp->fp - vp->stack_base,
467 vp->sp - vp->stack_base,
468 vp->ip,
469 &registers);
9d381ba4
AW
470
471 if (SCM_I_SETJMP (registers))
747022e4 472 {
b8af64db 473 /* The prompt exited nonlocally. */
c2247b78 474 scm_gc_after_nonlocal_exit ();
747022e4 475 proc = handler;
e7f9abab 476 vp = scm_the_vm ();
4fcbc1b0 477 args = scm_i_prompt_pop_abort_args_x (vp);
747022e4
AW
478 goto apply_proc;
479 }
480
1773bc7d 481 res = scm_call_0 (eval (CADR (mx), env));
9ede013f 482 scm_dynstack_pop (&SCM_I_CURRENT_THREAD->dynstack);
747022e4
AW
483 return res;
484 }
485
b7742c6b
AW
486 default:
487 abort ();
488 }
910b5125
DH
489}
490
b7742c6b 491\f
2a6f7afe 492
b7742c6b
AW
493/* Simple procedure calls
494 */
2a6f7afe 495
b7742c6b
AW
496SCM
497scm_call_0 (SCM proc)
498{
55ee3607 499 return scm_call_n (proc, NULL, 0);
0f2d19dd
JB
500}
501
b7742c6b
AW
502SCM
503scm_call_1 (SCM proc, SCM arg1)
212e58ed 504{
55ee3607 505 return scm_call_n (proc, &arg1, 1);
b7742c6b 506}
212e58ed 507
b7742c6b
AW
508SCM
509scm_call_2 (SCM proc, SCM arg1, SCM arg2)
510{
bf5a05f2 511 SCM args[] = { arg1, arg2 };
55ee3607 512 return scm_call_n (proc, args, 2);
212e58ed
DH
513}
514
b7742c6b
AW
515SCM
516scm_call_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3)
0f2d19dd 517{
bf5a05f2 518 SCM args[] = { arg1, arg2, arg3 };
55ee3607 519 return scm_call_n (proc, args, 3);
0f2d19dd
JB
520}
521
b7742c6b
AW
522SCM
523scm_call_4 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4)
212e58ed 524{
bf5a05f2 525 SCM args[] = { arg1, arg2, arg3, arg4 };
55ee3607 526 return scm_call_n (proc, args, 4);
212e58ed
DH
527}
528
f32e67be
AW
529SCM
530scm_call_5 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5)
531{
532 SCM args[] = { arg1, arg2, arg3, arg4, arg5 };
55ee3607 533 return scm_call_n (proc, args, 5);
f32e67be
AW
534}
535
536SCM
537scm_call_6 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
538 SCM arg6)
539{
540 SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6 };
55ee3607 541 return scm_call_n (proc, args, 6);
f32e67be
AW
542}
543
741b8a23
MW
544SCM
545scm_call_7 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
546 SCM arg6, SCM arg7)
547{
548 SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7 };
55ee3607 549 return scm_call_n (proc, args, 7);
741b8a23
MW
550}
551
552SCM
553scm_call_8 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
554 SCM arg6, SCM arg7, SCM arg8)
555{
556 SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 };
55ee3607 557 return scm_call_n (proc, args, 8);
741b8a23
MW
558}
559
560SCM
561scm_call_9 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
562 SCM arg6, SCM arg7, SCM arg8, SCM arg9)
563{
564 SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 };
55ee3607 565 return scm_call_n (proc, args, 9);
741b8a23
MW
566}
567
55ee3607 568/* scm_call_n defined in vm.c */
86fd6dff 569
741b8a23 570SCM
07c2ca0f 571scm_call (SCM proc, ...)
741b8a23
MW
572{
573 va_list argp;
574 SCM *argv = NULL;
575 size_t i, nargs = 0;
576
577 va_start (argp, proc);
578 while (!SCM_UNBNDP (va_arg (argp, SCM)))
579 nargs++;
580 va_end (argp);
581
582 argv = alloca (nargs * sizeof (SCM));
583 va_start (argp, proc);
584 for (i = 0; i < nargs; i++)
585 argv[i] = va_arg (argp, SCM);
586 va_end (argp);
587
55ee3607 588 return scm_call_n (proc, argv, nargs);
741b8a23
MW
589}
590
b7742c6b 591/* Simple procedure applies
9fbee57e 592 */
cc56ba80 593
b7742c6b
AW
594SCM
595scm_apply_0 (SCM proc, SCM args)
596{
6b4ba76d
AW
597 SCM *argv;
598 int i, nargs;
599
600 nargs = scm_ilength (args);
601 if (SCM_UNLIKELY (nargs < 0))
602 scm_wrong_type_arg_msg ("apply", 2, args, "list");
603
604 /* FIXME: Use vm_builtin_apply instead of alloca. */
605 argv = alloca (nargs * sizeof(SCM));
606 for (i = 0; i < nargs; i++)
607 {
608 argv[i] = SCM_CAR (args);
609 args = SCM_CDR (args);
610 }
611
55ee3607 612 return scm_call_n (proc, argv, nargs);
0f572ba7
DH
613}
614
b7742c6b
AW
615SCM
616scm_apply_1 (SCM proc, SCM arg1, SCM args)
0f572ba7 617{
6b4ba76d 618 return scm_apply_0 (proc, scm_cons (arg1, args));
8ae95199
DH
619}
620
b7742c6b
AW
621SCM
622scm_apply_2 (SCM proc, SCM arg1, SCM arg2, SCM args)
0f2d19dd 623{
6b4ba76d 624 return scm_apply_0 (proc, scm_cons2 (arg1, arg2, args));
0f2d19dd
JB
625}
626
b7742c6b
AW
627SCM
628scm_apply_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM args)
212e58ed 629{
6b4ba76d 630 return scm_apply_0 (proc, scm_cons (arg1, scm_cons2 (arg2, arg3, args)));
212e58ed
DH
631}
632
60617d81
MW
633static SCM map_var, for_each_var;
634
635static void init_map_var (void)
636{
637 map_var = scm_private_variable (scm_the_root_module (),
638 scm_from_latin1_symbol ("map"));
639}
640
641static void init_for_each_var (void)
642{
643 for_each_var = scm_private_variable (scm_the_root_module (),
644 scm_from_latin1_symbol ("for-each"));
645}
b8229a3b 646
b7742c6b
AW
647SCM
648scm_map (SCM proc, SCM arg1, SCM args)
0f2d19dd 649{
60617d81
MW
650 static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT;
651 scm_i_pthread_once (&once, init_map_var);
0f2d19dd 652
dc7a33fa 653 return scm_apply_0 (scm_variable_ref (map_var),
6b4ba76d 654 scm_cons (proc, scm_cons (arg1, args)));
a2230b65 655}
d6754c23 656
b7742c6b
AW
657SCM
658scm_for_each (SCM proc, SCM arg1, SCM args)
0f2d19dd 659{
60617d81
MW
660 static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT;
661 scm_i_pthread_once (&once, init_for_each_var);
a2230b65 662
dc7a33fa 663 return scm_apply_0 (scm_variable_ref (for_each_var),
6b4ba76d 664 scm_cons (proc, scm_cons (arg1, args)));
b7742c6b 665}
71560395 666
71560395 667
5f161164
AW
668static SCM
669scm_c_primitive_eval (SCM exp)
b7742c6b 670{
a310a1d1 671 if (!SCM_EXPANDED_P (exp))
4f692ace 672 exp = scm_call_1 (scm_current_module_transformer (), exp);
ef47c422 673 return eval (scm_memoize_expression (exp), SCM_BOOL_F);
b7742c6b 674}
5f161164
AW
675
676static SCM var_primitive_eval;
677SCM
678scm_primitive_eval (SCM exp)
679{
55ee3607
AW
680 return scm_call_n (scm_variable_ref (var_primitive_eval),
681 &exp, 1);
5f161164 682}
71560395 683
b7742c6b
AW
684
685/* Eval does not take the second arg optionally. This is intentional
686 * in order to be R5RS compatible, and to prepare for the new module
687 * system, where we would like to make the choice of evaluation
688 * environment explicit. */
689
690SCM_DEFINE (scm_eval, "eval", 2, 0, 0,
691 (SCM exp, SCM module_or_state),
692 "Evaluate @var{exp}, a list representing a Scheme expression,\n"
693 "in the top-level environment specified by\n"
694 "@var{module_or_state}.\n"
695 "While @var{exp} is evaluated (using @code{primitive-eval}),\n"
696 "@var{module_or_state} is made the current module when\n"
697 "it is a module, or the current dynamic state when it is\n"
698 "a dynamic state."
699 "Example: (eval '(+ 1 2) (interaction-environment))")
700#define FUNC_NAME s_scm_eval
701{
702 SCM res;
703
704 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
705 if (scm_is_dynamic_state (module_or_state))
706 scm_dynwind_current_dynamic_state (module_or_state);
707 else if (scm_module_system_booted_p)
708 {
709 SCM_VALIDATE_MODULE (2, module_or_state);
710 scm_dynwind_current_module (module_or_state);
71560395 711 }
b7742c6b 712 /* otherwise if the module system isn't booted, ignore the module arg */
71560395 713
b7742c6b
AW
714 res = scm_primitive_eval (exp);
715
716 scm_dynwind_end ();
717 return res;
718}
719#undef FUNC_NAME
71560395
AW
720
721
b7742c6b 722static SCM f_apply;
71560395
AW
723
724/* Apply a function to a list of arguments.
725
6b4ba76d
AW
726 This function's interface is a bit wonly. It takes two required
727 arguments and a tail argument, as if it were:
728
71560395 729 (lambda (proc arg1 . args) ...)
6b4ba76d
AW
730
731 Usually you want to use scm_apply_0 or one of its cousins. */
71560395
AW
732
733SCM
734scm_apply (SCM proc, SCM arg1, SCM args)
735{
6b4ba76d
AW
736 return scm_apply_0 (proc,
737 scm_is_null (args) ? arg1 : scm_cons_star (arg1, args));
b7742c6b 738}
434f2f7a 739
7572ee52
AW
740static void
741prepare_boot_closure_env_for_apply (SCM proc, SCM args,
742 SCM *out_body, SCM *out_env)
314b8716 743{
8f9c5b58
AW
744 int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
745 SCM env = BOOT_CLOSURE_ENV (proc);
cfc28c80
AW
746 int i;
747
8f9c5b58
AW
748 if (BOOT_CLOSURE_IS_FIXED (proc)
749 || (BOOT_CLOSURE_IS_REST (proc)
750 && !BOOT_CLOSURE_HAS_REST_ARGS (proc)))
751 {
752 if (SCM_UNLIKELY (scm_ilength (args) != nreq))
753 scm_wrong_num_args (proc);
cfc28c80
AW
754
755 env = make_env (nreq, SCM_UNDEFINED, env);
756 for (i = 0; i < nreq; args = CDR (args), i++)
757 env_set (env, 0, i, CAR (args));
7572ee52
AW
758 *out_body = BOOT_CLOSURE_BODY (proc);
759 *out_env = env;
8f9c5b58
AW
760 }
761 else if (BOOT_CLOSURE_IS_REST (proc))
314b8716
AW
762 {
763 if (SCM_UNLIKELY (scm_ilength (args) < nreq))
8f9c5b58 764 scm_wrong_num_args (proc);
cfc28c80
AW
765
766 env = make_env (nreq + 1, SCM_UNDEFINED, env);
767 for (i = 0; i < nreq; args = CDR (args), i++)
768 env_set (env, 0, i, CAR (args));
769 env_set (env, 0, i++, args);
770
7572ee52
AW
771 *out_body = BOOT_CLOSURE_BODY (proc);
772 *out_env = env;
314b8716
AW
773 }
774 else
d8a071fc 775 {
cfdc8416
AW
776 int i, argc, nreq, nopt, ninits, nenv;
777 SCM body, rest, kw, unbound, alt;
dc3e203e 778 SCM mx = BOOT_CLOSURE_CODE (proc);
d8a071fc 779
7572ee52 780 loop:
cfdc8416
AW
781 BOOT_CLOSURE_PARSE_FULL (mx, body, nargs, rest, nopt, kw,
782 ninits, unbound, alt);
d8a071fc
AW
783
784 argc = scm_ilength (args);
785 if (argc < nreq)
786 {
787 if (scm_is_true (alt))
7572ee52 788 {
dc3e203e 789 mx = alt;
7572ee52
AW
790 goto loop;
791 }
d8a071fc
AW
792 else
793 scm_wrong_num_args (proc);
794 }
795 if (scm_is_false (kw) && argc > nreq + nopt && scm_is_false (rest))
796 {
797 if (scm_is_true (alt))
7572ee52 798 {
dc3e203e 799 mx = alt;
7572ee52
AW
800 goto loop;
801 }
d8a071fc
AW
802 else
803 scm_wrong_num_args (proc);
804 }
cfc28c80
AW
805 if (scm_is_true (kw) && scm_is_false (rest))
806 {
807 int npos = 0;
808 SCM walk;
809 for (walk = args; scm_is_pair (walk); walk = CDR (walk), npos++)
810 if (npos >= nreq && scm_is_keyword (CAR (walk)))
811 break;
812
813 if (npos > nreq + nopt)
814 {
815 /* Too many positional args and no rest arg. */
816 if (scm_is_true (alt))
817 {
818 mx = alt;
819 goto loop;
820 }
821 else
822 scm_wrong_num_args (proc);
823 }
824 }
825
826 /* At this point we are committed to the chosen clause. */
cfdc8416
AW
827 nenv = nreq + (scm_is_true (rest) ? 1 : 0) + ninits;
828 env = make_env (nenv, unbound, env);
d8a071fc
AW
829
830 for (i = 0; i < nreq; i++, args = CDR (args))
cfc28c80 831 env_set (env, 0, i, CAR (args));
d8a071fc
AW
832
833 if (scm_is_false (kw))
834 {
835 /* Optional args (possibly), but no keyword args. */
cfdc8416 836 for (; i < argc && i < nreq + nopt; i++, args = CDR (args))
cfc28c80 837 env_set (env, 0, i, CAR (args));
d8a071fc 838 if (scm_is_true (rest))
cfdc8416 839 env_set (env, 0, nreq + nopt, args);
d8a071fc
AW
840 }
841 else
842 {
843 SCM aok;
844
845 aok = CAR (kw);
846 kw = CDR (kw);
847
cfc28c80 848 /* Optional args. As before, but stop at the first keyword. */
d8a071fc 849 for (; i < argc && i < nreq + nopt && !scm_is_keyword (CAR (args));
cfdc8416 850 i++, args = CDR (args))
cfc28c80 851 env_set (env, 0, i, CAR (args));
d8a071fc 852 if (scm_is_true (rest))
cfdc8416 853 env_set (env, 0, nreq + nopt, args);
d8a071fc 854
cfc28c80 855 /* Parse keyword args. */
d8a071fc 856 {
cfc28c80 857 SCM walk;
d8a071fc
AW
858
859 if (scm_is_pair (args) && scm_is_pair (CDR (args)))
860 for (; scm_is_pair (args) && scm_is_pair (CDR (args));
861 args = CDR (args))
862 {
cfc28c80 863 SCM k = CAR (args), v = CADR (args);
d8a071fc
AW
864 if (!scm_is_keyword (k))
865 {
866 if (scm_is_true (rest))
867 continue;
868 else
869 break;
870 }
871 for (walk = kw; scm_is_pair (walk); walk = CDR (walk))
872 if (scm_is_eq (k, CAAR (walk)))
873 {
cfc28c80 874 env_set (env, 0, SCM_I_INUM (CDAR (walk)), v);
d8a071fc
AW
875 args = CDR (args);
876 break;
877 }
878 if (scm_is_null (walk) && scm_is_false (aok))
4af0d97e 879 error_unrecognized_keyword (proc, k);
d8a071fc
AW
880 }
881 if (scm_is_pair (args) && scm_is_false (rest))
4af0d97e 882 error_invalid_keyword (proc, CAR (args));
d8a071fc
AW
883 }
884 }
8f9c5b58 885
dc3e203e 886 *out_body = body;
7572ee52
AW
887 *out_env = env;
888 }
8f9c5b58
AW
889}
890
7572ee52 891static void
8f9c5b58 892prepare_boot_closure_env_for_eval (SCM proc, unsigned int argc,
7572ee52 893 SCM exps, SCM *out_body, SCM *inout_env)
8f9c5b58
AW
894{
895 int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
896 SCM new_env = BOOT_CLOSURE_ENV (proc);
cfc28c80
AW
897 if ((BOOT_CLOSURE_IS_FIXED (proc)
898 || (BOOT_CLOSURE_IS_REST (proc)
899 && !BOOT_CLOSURE_HAS_REST_ARGS (proc)))
900 && nreq == argc)
314b8716 901 {
cfc28c80
AW
902 int i;
903
904 new_env = make_env (nreq, SCM_UNDEFINED, new_env);
905 for (i = 0; i < nreq; exps = CDR (exps), i++)
906 env_set (new_env, 0, i, EVAL1 (CAR (exps), *inout_env));
907
7572ee52
AW
908 *out_body = BOOT_CLOSURE_BODY (proc);
909 *inout_env = new_env;
314b8716 910 }
cfc28c80 911 else if (BOOT_CLOSURE_IS_REST (proc) && argc >= nreq)
8f9c5b58 912 {
cfc28c80
AW
913 SCM rest;
914 int i;
915
916 new_env = make_env (nreq + 1, SCM_UNDEFINED, new_env);
917 for (i = 0; i < nreq; exps = CDR (exps), i++)
918 env_set (new_env, 0, i, EVAL1 (CAR (exps), *inout_env));
919 for (rest = SCM_EOL; scm_is_pair (exps); exps = CDR (exps))
920 rest = scm_cons (EVAL1 (CAR (exps), *inout_env), rest);
921 env_set (new_env, 0, i++, scm_reverse_x (rest, SCM_UNDEFINED));
922
7572ee52
AW
923 *out_body = BOOT_CLOSURE_BODY (proc);
924 *inout_env = new_env;
8f9c5b58
AW
925 }
926 else
d8a071fc
AW
927 {
928 SCM args = SCM_EOL;
929 for (; scm_is_pair (exps); exps = CDR (exps))
f3a9a51d 930 args = scm_cons (EVAL1 (CAR (exps), *inout_env), args);
7572ee52
AW
931 args = scm_reverse_x (args, SCM_UNDEFINED);
932 prepare_boot_closure_env_for_apply (proc, args, out_body, inout_env);
d8a071fc 933 }
8f9c5b58
AW
934}
935
936static SCM
937boot_closure_apply (SCM closure, SCM args)
938{
7572ee52
AW
939 SCM body, env;
940 prepare_boot_closure_env_for_apply (closure, args, &body, &env);
941 return eval (body, env);
314b8716
AW
942}
943
944static int
945boot_closure_print (SCM closure, SCM port, scm_print_state *pstate)
946{
947 SCM args;
0607ebbf 948 scm_puts_unlocked ("#<boot-closure ", port);
fdecb44f 949 scm_uintprint (SCM_UNPACK (closure), 16, port);
0607ebbf 950 scm_putc_unlocked (' ', port);
314b8716 951 args = scm_make_list (scm_from_int (BOOT_CLOSURE_NUM_REQUIRED_ARGS (closure)),
4a655e50 952 scm_from_latin1_symbol ("_"));
8f9c5b58 953 if (!BOOT_CLOSURE_IS_FIXED (closure) && BOOT_CLOSURE_HAS_REST_ARGS (closure))
4a655e50 954 args = scm_cons_star (scm_from_latin1_symbol ("_"), args);
7572ee52 955 /* FIXME: optionals and rests */
314b8716 956 scm_display (args, port);
0607ebbf 957 scm_putc_unlocked ('>', port);
314b8716
AW
958 return 1;
959}
960
0f2d19dd
JB
961void
962scm_init_eval ()
0f2d19dd 963{
5f161164
AW
964 SCM primitive_eval;
965
df9ca8d8 966 f_apply = scm_c_define_gsubr ("apply", 2, 0, 1, scm_apply);
86d31dfe 967
314b8716
AW
968 scm_tc16_boot_closure = scm_make_smob_type ("boot-closure", 0);
969 scm_set_smob_apply (scm_tc16_boot_closure, boot_closure_apply, 0, 0, 1);
970 scm_set_smob_print (scm_tc16_boot_closure, boot_closure_print);
971
5f161164
AW
972 primitive_eval = scm_c_make_gsubr ("primitive-eval", 1, 0, 0,
973 scm_c_primitive_eval);
974 var_primitive_eval = scm_define (SCM_SUBR_NAME (primitive_eval),
975 primitive_eval);
976
a0599745 977#include "libguile/eval.x"
0f2d19dd 978}
0f2d19dd 979
89e00824
ML
980/*
981 Local Variables:
982 c-file-style: "gnu"
983 End:
984*/
62560650 985