define! is an interesting primitive
[bpt/guile.git] / libguile / eval.c
CommitLineData
747bd534
AW
1/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,
2 * 2005,2006,2007,2008,2009,2010,2011,2012,2013
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)
dc3e203e
AW
119#define BOOT_CLOSURE_PARSE_FULL(fu_,body,nargs,rest,nopt,kw,inits,alt) \
120 do { SCM fu = fu_; \
c438cd71 121 body = CAR (fu); fu = CDDR (fu); \
dc3e203e
AW
122 \
123 rest = kw = alt = SCM_BOOL_F; \
124 inits = SCM_EOL; \
125 nopt = 0; \
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); \
135 inits = CAR (fu); fu = CDR (fu); \
136 alt = CAR (fu); \
137 } \
138 } \
d8a071fc 139 } while (0)
7572ee52
AW
140static void prepare_boot_closure_env_for_apply (SCM proc, SCM args,
141 SCM *out_body, SCM *out_env);
142static void prepare_boot_closure_env_for_eval (SCM proc, unsigned int argc,
143 SCM exps, SCM *out_body,
144 SCM *inout_env);
314b8716
AW
145
146
b7742c6b
AW
147#define CAR(x) SCM_CAR(x)
148#define CDR(x) SCM_CDR(x)
149#define CAAR(x) SCM_CAAR(x)
150#define CADR(x) SCM_CADR(x)
151#define CDAR(x) SCM_CDAR(x)
152#define CDDR(x) SCM_CDDR(x)
153#define CADDR(x) SCM_CADDR(x)
154#define CDDDR(x) SCM_CDDDR(x)
e6729603 155
cfc28c80
AW
156#define VECTOR_REF(v, i) (SCM_SIMPLE_VECTOR_REF (v, i))
157#define VECTOR_SET(v, i, x) (SCM_SIMPLE_VECTOR_SET (v, i, x))
158#define VECTOR_LENGTH(v) (SCM_SIMPLE_VECTOR_LENGTH (v))
159
160static SCM
161make_env (int n, SCM init, SCM next)
162{
163 SCM env = scm_c_make_vector (n + 1, init);
164 VECTOR_SET (env, 0, next);
165 return env;
166}
167
168static SCM
169next_rib (SCM env)
170{
171 return VECTOR_REF (env, 0);
172}
173
174static SCM
175env_tail (SCM env)
176{
177 while (SCM_I_IS_VECTOR (env))
178 env = next_rib (env);
179 return env;
180}
181
182static SCM
183env_ref (SCM env, int depth, int width)
184{
185 while (depth--)
186 env = next_rib (env);
187 return VECTOR_REF (env, width + 1);
188}
189
190static void
191env_set (SCM env, int depth, int width, SCM val)
192{
193 while (depth--)
194 env = next_rib (env);
195 VECTOR_SET (env, width + 1, val);
196}
197
e6729603 198
b7742c6b 199SCM_SYMBOL (scm_unbound_variable_key, "unbound-variable");
e6729603 200
b7742c6b 201static void error_used_before_defined (void)
d0624e39 202{
b7742c6b
AW
203 scm_error (scm_unbound_variable_key, NULL,
204 "Variable used before given a value", SCM_EOL, SCM_BOOL_F);
d0624e39 205}
d0624e39 206
4af0d97e 207static void error_invalid_keyword (SCM proc, SCM obj)
d8a071fc 208{
4a655e50 209 scm_error_scm (scm_from_latin1_symbol ("keyword-argument-error"), proc,
d8a071fc 210 scm_from_locale_string ("Invalid keyword"), SCM_EOL,
4af0d97e 211 scm_list_1 (obj));
d8a071fc
AW
212}
213
4af0d97e 214static void error_unrecognized_keyword (SCM proc, SCM kw)
d8a071fc 215{
4a655e50 216 scm_error_scm (scm_from_latin1_symbol ("keyword-argument-error"), proc,
d8a071fc 217 scm_from_locale_string ("Unrecognized keyword"), SCM_EOL,
4af0d97e 218 scm_list_1 (kw));
d8a071fc
AW
219}
220
221
f3a9a51d
AW
222/* Multiple values truncation. */
223static SCM
224truncate_values (SCM x)
225{
226 if (SCM_LIKELY (!SCM_VALUESP (x)))
227 return x;
228 else
229 {
230 SCM l = scm_struct_ref (x, SCM_INUM0);
231 if (SCM_LIKELY (scm_is_pair (l)))
232 return scm_car (l);
233 else
234 {
235 scm_ithrow (scm_from_latin1_symbol ("vm-run"),
236 scm_list_3 (scm_from_latin1_symbol ("vm-run"),
237 scm_from_locale_string
238 ("Too few values returned to continuation"),
239 SCM_EOL),
240 1);
241 /* Not reached. */
242 return SCM_BOOL_F;
243 }
244 }
245}
246#define EVAL1(x, env) (truncate_values (eval ((x), (env))))
247
b7742c6b 248/* the environment:
3149a5b6 249 (VAL ... . MOD)
b7742c6b
AW
250 If MOD is #f, it means the environment was captured before modules were
251 booted.
252 If MOD is the literal value '(), we are evaluating at the top level, and so
253 should track changes to the current module. You have to be careful in this
254 case, because further lexical contours should capture the current module.
255*/
256#define CAPTURE_ENV(env) \
393baa8a
AW
257 (scm_is_null (env) ? scm_current_module () : \
258 (scm_is_false (env) ? scm_the_root_module () : env))
6f81708a
DH
259
260static SCM
b7742c6b 261eval (SCM x, SCM env)
6f81708a 262{
b7742c6b
AW
263 SCM mx;
264 SCM proc = SCM_UNDEFINED, args = SCM_EOL;
b7ecadca 265 unsigned int argc;
6f81708a 266
b7742c6b
AW
267 loop:
268 SCM_TICK;
b7742c6b
AW
269
270 mx = SCM_MEMOIZED_ARGS (x);
0720f70e 271 switch (SCM_I_INUM (SCM_CAR (x)))
b7742c6b 272 {
6fc3eae4
AW
273 case SCM_M_SEQ:
274 eval (CAR (mx), env);
275 x = CDR (mx);
b7742c6b
AW
276 goto loop;
277
278 case SCM_M_IF:
f3a9a51d 279 if (scm_is_true (EVAL1 (CAR (mx), env)))
b7742c6b 280 x = CADR (mx);
6f81708a 281 else
b7742c6b
AW
282 x = CDDR (mx);
283 goto loop;
5fb64383 284
b7742c6b
AW
285 case SCM_M_LET:
286 {
287 SCM inits = CAR (mx);
cfc28c80
AW
288 SCM new_env;
289 int i;
290
291 new_env = make_env (VECTOR_LENGTH (inits), SCM_UNDEFINED,
292 CAPTURE_ENV (env));
293 for (i = 0; i < VECTOR_LENGTH (inits); i++)
294 env_set (new_env, 0, i, EVAL1 (VECTOR_REF (inits, i), env));
b7742c6b
AW
295 env = new_env;
296 x = CDR (mx);
297 goto loop;
298 }
299
300 case SCM_M_LAMBDA:
314b8716 301 RETURN_BOOT_CLOSURE (mx, CAPTURE_ENV (env));
5fb64383 302
b7742c6b
AW
303 case SCM_M_QUOTE:
304 return mx;
0f2d19dd 305
b7742c6b 306 case SCM_M_DEFINE:
f3a9a51d 307 scm_define (CAR (mx), EVAL1 (CDR (mx), env));
b7742c6b 308 return SCM_UNSPECIFIED;
212e58ed 309
b7742c6b
AW
310 case SCM_M_APPLY:
311 /* Evaluate the procedure to be applied. */
f3a9a51d 312 proc = EVAL1 (CAR (mx), env);
b7742c6b 313 /* Evaluate the argument holding the list of arguments */
f3a9a51d 314 args = EVAL1 (CADR (mx), env);
b7742c6b
AW
315
316 apply_proc:
317 /* Go here to tail-apply a procedure. PROC is the procedure and
318 * ARGS is the list of arguments. */
314b8716 319 if (BOOT_CLOSURE_P (proc))
b7742c6b 320 {
7572ee52 321 prepare_boot_closure_env_for_apply (proc, args, &x, &env);
b7742c6b
AW
322 goto loop;
323 }
324 else
ea9f4f4b 325 return scm_call_with_vm (scm_the_vm (), proc, args);
212e58ed 326
b7742c6b
AW
327 case SCM_M_CALL:
328 /* Evaluate the procedure to be applied. */
f3a9a51d 329 proc = EVAL1 (CAR (mx), env);
b7ecadca 330 argc = SCM_I_INUM (CADR (mx));
9331f91c 331 mx = CDDR (mx);
212e58ed 332
314b8716 333 if (BOOT_CLOSURE_P (proc))
5fa0939c 334 {
7572ee52 335 prepare_boot_closure_env_for_eval (proc, argc, mx, &x, &env);
b7742c6b 336 goto loop;
5fa0939c 337 }
b7742c6b
AW
338 else
339 {
e2cf8eb9 340 SCM *argv;
b7ecadca
LC
341 unsigned int i;
342
e2cf8eb9 343 argv = alloca (argc * sizeof (SCM));
b7ecadca 344 for (i = 0; i < argc; i++, mx = CDR (mx))
f3a9a51d 345 argv[i] = EVAL1 (CAR (mx), env);
b7ecadca
LC
346
347 return scm_c_vm_run (scm_the_vm (), proc, argv, argc);
b7742c6b 348 }
b7ecadca 349
b7742c6b 350 case SCM_M_CONT:
f3a9a51d 351 return scm_i_call_with_current_continuation (EVAL1 (mx, env));
212e58ed 352
b7742c6b
AW
353 case SCM_M_CALL_WITH_VALUES:
354 {
355 SCM producer;
356 SCM v;
357
f3a9a51d
AW
358 producer = EVAL1 (CAR (mx), env);
359 /* `proc' is the consumer. */
360 proc = EVAL1 (CDR (mx), env);
ea9f4f4b 361 v = scm_call_with_vm (scm_the_vm (), producer, SCM_EOL);
b7742c6b
AW
362 if (SCM_VALUESP (v))
363 args = scm_struct_ref (v, SCM_INUM0);
364 else
365 args = scm_list_1 (v);
366 goto apply_proc;
367 }
26d5b9b4 368
b7742c6b
AW
369 case SCM_M_LEXICAL_REF:
370 {
cfc28c80
AW
371 SCM pos, ret;
372 int depth, width;
373
374 pos = mx;
375 depth = SCM_I_INUM (CAR (pos));
376 width = SCM_I_INUM (CDR (pos));
377
378 ret = env_ref (env, depth, width);
379
b7742c6b
AW
380 if (SCM_UNLIKELY (SCM_UNBNDP (ret)))
381 /* we don't know what variable, though, because we don't have its
382 name */
383 error_used_before_defined ();
384 return ret;
385 }
1cc91f1b 386
b7742c6b
AW
387 case SCM_M_LEXICAL_SET:
388 {
cfc28c80
AW
389 SCM pos;
390 int depth, width;
f3a9a51d 391 SCM val = EVAL1 (CDR (mx), env);
cfc28c80
AW
392
393 pos = CAR (mx);
394 depth = SCM_I_INUM (CAR (pos));
395 width = SCM_I_INUM (CDR (pos));
396
397 env_set (env, depth, width, val);
398
b7742c6b
AW
399 return SCM_UNSPECIFIED;
400 }
910b5125 401
b7742c6b
AW
402 case SCM_M_TOPLEVEL_REF:
403 if (SCM_VARIABLEP (mx))
404 return SCM_VARIABLE_REF (mx);
405 else
57d23e25 406 {
cfc28c80 407 env = env_tail (env);
3149a5b6
AW
408 return SCM_VARIABLE_REF
409 (scm_memoize_variable_access_x (x, CAPTURE_ENV (env)));
57d23e25 410 }
57d23e25 411
b7742c6b
AW
412 case SCM_M_TOPLEVEL_SET:
413 {
414 SCM var = CAR (mx);
f3a9a51d 415 SCM val = EVAL1 (CDR (mx), env);
b7742c6b
AW
416 if (SCM_VARIABLEP (var))
417 {
418 SCM_VARIABLE_SET (var, val);
419 return SCM_UNSPECIFIED;
420 }
421 else
422 {
cfc28c80 423 env = env_tail (env);
3149a5b6
AW
424 SCM_VARIABLE_SET
425 (scm_memoize_variable_access_x (x, CAPTURE_ENV (env)),
426 val);
b7742c6b
AW
427 return SCM_UNSPECIFIED;
428 }
429 }
910b5125 430
b7742c6b
AW
431 case SCM_M_MODULE_REF:
432 if (SCM_VARIABLEP (mx))
433 return SCM_VARIABLE_REF (mx);
910b5125 434 else
3149a5b6
AW
435 return SCM_VARIABLE_REF
436 (scm_memoize_variable_access_x (x, SCM_BOOL_F));
910b5125 437
b7742c6b
AW
438 case SCM_M_MODULE_SET:
439 if (SCM_VARIABLEP (CDR (mx)))
910b5125 440 {
f3a9a51d 441 SCM_VARIABLE_SET (CDR (mx), EVAL1 (CAR (mx), env));
b7742c6b
AW
442 return SCM_UNSPECIFIED;
443 }
444 else
445 {
3149a5b6
AW
446 SCM_VARIABLE_SET
447 (scm_memoize_variable_access_x (x, SCM_BOOL_F),
f3a9a51d 448 EVAL1 (CAR (mx), env));
b7742c6b 449 return SCM_UNSPECIFIED;
910b5125 450 }
910b5125 451
1773bc7d 452 case SCM_M_CALL_WITH_PROMPT:
747022e4 453 {
9ede013f 454 SCM vm, k, res;
9d381ba4 455 scm_i_jmp_buf registers;
9ede013f
AW
456 /* We need the handler after nonlocal return to the setjmp, so
457 make sure it is volatile. */
458 volatile SCM handler;
459
460 k = EVAL1 (CAR (mx), env);
f3a9a51d 461 handler = EVAL1 (CDDR (mx), env);
9ede013f
AW
462 vm = scm_the_vm ();
463
464 /* Push the prompt onto the dynamic stack. */
9ede013f 465 scm_dynstack_push_prompt (&SCM_I_CURRENT_THREAD->dynstack,
c6cd692f
AW
466 SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY
467 | SCM_F_DYNSTACK_PROMPT_PUSH_NARGS,
9d381ba4
AW
468 k,
469 SCM_VM_DATA (vm)->fp,
470 SCM_VM_DATA (vm)->sp,
471 SCM_VM_DATA (vm)->ip,
472 &registers);
473
474 if (SCM_I_SETJMP (registers))
747022e4 475 {
b8af64db 476 /* The prompt exited nonlocally. */
747022e4 477 proc = handler;
572eef50 478 args = scm_i_prompt_pop_abort_args_x (scm_the_vm ());
747022e4
AW
479 goto apply_proc;
480 }
481
1773bc7d 482 res = scm_call_0 (eval (CADR (mx), env));
9ede013f 483 scm_dynstack_pop (&SCM_I_CURRENT_THREAD->dynstack);
747022e4
AW
484 return res;
485 }
486
b7742c6b
AW
487 default:
488 abort ();
489 }
910b5125
DH
490}
491
b7742c6b 492\f
2a6f7afe 493
b7742c6b
AW
494/* Simple procedure calls
495 */
2a6f7afe 496
b7742c6b
AW
497SCM
498scm_call_0 (SCM proc)
499{
bf5a05f2 500 return scm_c_vm_run (scm_the_vm (), proc, NULL, 0);
0f2d19dd
JB
501}
502
b7742c6b
AW
503SCM
504scm_call_1 (SCM proc, SCM arg1)
212e58ed 505{
bf5a05f2 506 return scm_c_vm_run (scm_the_vm (), proc, &arg1, 1);
b7742c6b 507}
212e58ed 508
b7742c6b
AW
509SCM
510scm_call_2 (SCM proc, SCM arg1, SCM arg2)
511{
bf5a05f2
AW
512 SCM args[] = { arg1, arg2 };
513 return scm_c_vm_run (scm_the_vm (), proc, args, 2);
212e58ed
DH
514}
515
b7742c6b
AW
516SCM
517scm_call_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3)
0f2d19dd 518{
bf5a05f2
AW
519 SCM args[] = { arg1, arg2, arg3 };
520 return scm_c_vm_run (scm_the_vm (), proc, args, 3);
0f2d19dd
JB
521}
522
b7742c6b
AW
523SCM
524scm_call_4 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4)
212e58ed 525{
bf5a05f2
AW
526 SCM args[] = { arg1, arg2, arg3, arg4 };
527 return scm_c_vm_run (scm_the_vm (), proc, args, 4);
212e58ed
DH
528}
529
f32e67be
AW
530SCM
531scm_call_5 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5)
532{
533 SCM args[] = { arg1, arg2, arg3, arg4, arg5 };
534 return scm_c_vm_run (scm_the_vm (), proc, args, 5);
535}
536
537SCM
538scm_call_6 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
539 SCM arg6)
540{
541 SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6 };
542 return scm_c_vm_run (scm_the_vm (), proc, args, 6);
543}
544
741b8a23
MW
545SCM
546scm_call_7 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
547 SCM arg6, SCM arg7)
548{
549 SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7 };
550 return scm_c_vm_run (scm_the_vm (), proc, args, 7);
551}
552
553SCM
554scm_call_8 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
555 SCM arg6, SCM arg7, SCM arg8)
556{
557 SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 };
558 return scm_c_vm_run (scm_the_vm (), proc, args, 8);
559}
560
561SCM
562scm_call_9 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
563 SCM arg6, SCM arg7, SCM arg8, SCM arg9)
564{
565 SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 };
566 return scm_c_vm_run (scm_the_vm (), proc, args, 9);
567}
568
86fd6dff
AW
569SCM
570scm_call_n (SCM proc, SCM *argv, size_t nargs)
571{
572 return scm_c_vm_run (scm_the_vm (), proc, argv, nargs);
573}
574
741b8a23 575SCM
07c2ca0f 576scm_call (SCM proc, ...)
741b8a23
MW
577{
578 va_list argp;
579 SCM *argv = NULL;
580 size_t i, nargs = 0;
581
582 va_start (argp, proc);
583 while (!SCM_UNBNDP (va_arg (argp, SCM)))
584 nargs++;
585 va_end (argp);
586
587 argv = alloca (nargs * sizeof (SCM));
588 va_start (argp, proc);
589 for (i = 0; i < nargs; i++)
590 argv[i] = va_arg (argp, SCM);
591 va_end (argp);
592
593 return scm_c_vm_run (scm_the_vm (), proc, argv, nargs);
594}
595
b7742c6b 596/* Simple procedure applies
9fbee57e 597 */
cc56ba80 598
b7742c6b
AW
599SCM
600scm_apply_0 (SCM proc, SCM args)
601{
602 return scm_apply (proc, args, SCM_EOL);
0f572ba7
DH
603}
604
b7742c6b
AW
605SCM
606scm_apply_1 (SCM proc, SCM arg1, SCM args)
0f572ba7 607{
b7742c6b 608 return scm_apply (proc, scm_cons (arg1, args), SCM_EOL);
8ae95199
DH
609}
610
b7742c6b
AW
611SCM
612scm_apply_2 (SCM proc, SCM arg1, SCM arg2, SCM args)
0f2d19dd 613{
b7742c6b 614 return scm_apply (proc, scm_cons2 (arg1, arg2, args), SCM_EOL);
0f2d19dd
JB
615}
616
b7742c6b
AW
617SCM
618scm_apply_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM args)
212e58ed 619{
b7742c6b
AW
620 return scm_apply (proc, scm_cons (arg1, scm_cons2 (arg2, arg3, args)),
621 SCM_EOL);
212e58ed
DH
622}
623
b8229a3b 624
b7742c6b
AW
625SCM
626scm_map (SCM proc, SCM arg1, SCM args)
0f2d19dd 627{
a2230b65 628 static SCM var = SCM_BOOL_F;
0f2d19dd 629
a2230b65
AW
630 if (scm_is_false (var))
631 var = scm_private_variable (scm_the_root_module (),
632 scm_from_latin1_symbol ("map"));
302c12b4 633
a2230b65
AW
634 return scm_apply (scm_variable_ref (var),
635 scm_cons (proc, scm_cons (arg1, args)), SCM_EOL);
636}
d6754c23 637
b7742c6b
AW
638SCM
639scm_for_each (SCM proc, SCM arg1, SCM args)
0f2d19dd 640{
a2230b65
AW
641 static SCM var = SCM_BOOL_F;
642
643 if (scm_is_false (var))
644 var = scm_private_variable (scm_the_root_module (),
645 scm_from_latin1_symbol ("for-each"));
646
647 return scm_apply (scm_variable_ref (var),
648 scm_cons (proc, scm_cons (arg1, args)), SCM_EOL);
b7742c6b 649}
71560395 650
71560395 651
5f161164
AW
652static SCM
653scm_c_primitive_eval (SCM exp)
b7742c6b 654{
a310a1d1 655 if (!SCM_EXPANDED_P (exp))
4f692ace 656 exp = scm_call_1 (scm_current_module_transformer (), exp);
a310a1d1 657 return eval (scm_memoize_expression (exp), SCM_EOL);
b7742c6b 658}
5f161164
AW
659
660static SCM var_primitive_eval;
661SCM
662scm_primitive_eval (SCM exp)
663{
664 return scm_c_vm_run (scm_the_vm (), scm_variable_ref (var_primitive_eval),
665 &exp, 1);
666}
71560395 667
b7742c6b
AW
668
669/* Eval does not take the second arg optionally. This is intentional
670 * in order to be R5RS compatible, and to prepare for the new module
671 * system, where we would like to make the choice of evaluation
672 * environment explicit. */
673
674SCM_DEFINE (scm_eval, "eval", 2, 0, 0,
675 (SCM exp, SCM module_or_state),
676 "Evaluate @var{exp}, a list representing a Scheme expression,\n"
677 "in the top-level environment specified by\n"
678 "@var{module_or_state}.\n"
679 "While @var{exp} is evaluated (using @code{primitive-eval}),\n"
680 "@var{module_or_state} is made the current module when\n"
681 "it is a module, or the current dynamic state when it is\n"
682 "a dynamic state."
683 "Example: (eval '(+ 1 2) (interaction-environment))")
684#define FUNC_NAME s_scm_eval
685{
686 SCM res;
687
688 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
689 if (scm_is_dynamic_state (module_or_state))
690 scm_dynwind_current_dynamic_state (module_or_state);
691 else if (scm_module_system_booted_p)
692 {
693 SCM_VALIDATE_MODULE (2, module_or_state);
694 scm_dynwind_current_module (module_or_state);
71560395 695 }
b7742c6b 696 /* otherwise if the module system isn't booted, ignore the module arg */
71560395 697
b7742c6b
AW
698 res = scm_primitive_eval (exp);
699
700 scm_dynwind_end ();
701 return res;
702}
703#undef FUNC_NAME
71560395
AW
704
705
b7742c6b 706static SCM f_apply;
71560395
AW
707
708/* Apply a function to a list of arguments.
709
710 This function is exported to the Scheme level as taking two
711 required arguments and a tail argument, as if it were:
712 (lambda (proc arg1 . args) ...)
713 Thus, if you just have a list of arguments to pass to a procedure,
714 pass the list as ARG1, and '() for ARGS. If you have some fixed
715 args, pass the first as ARG1, then cons any remaining fixed args
716 onto the front of your argument list, and pass that as ARGS. */
717
718SCM
719scm_apply (SCM proc, SCM arg1, SCM args)
720{
b7742c6b 721 /* Fix things up so that args contains all args. */
71560395 722 if (scm_is_null (args))
b7742c6b 723 args = arg1;
71560395 724 else
b7742c6b 725 args = scm_cons_star (arg1, args);
71560395 726
ea9f4f4b 727 return scm_call_with_vm (scm_the_vm (), proc, args);
b7742c6b 728}
434f2f7a 729
7572ee52
AW
730static void
731prepare_boot_closure_env_for_apply (SCM proc, SCM args,
732 SCM *out_body, SCM *out_env)
314b8716 733{
8f9c5b58
AW
734 int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
735 SCM env = BOOT_CLOSURE_ENV (proc);
cfc28c80
AW
736 int i;
737
8f9c5b58
AW
738 if (BOOT_CLOSURE_IS_FIXED (proc)
739 || (BOOT_CLOSURE_IS_REST (proc)
740 && !BOOT_CLOSURE_HAS_REST_ARGS (proc)))
741 {
742 if (SCM_UNLIKELY (scm_ilength (args) != nreq))
743 scm_wrong_num_args (proc);
cfc28c80
AW
744
745 env = make_env (nreq, SCM_UNDEFINED, env);
746 for (i = 0; i < nreq; args = CDR (args), i++)
747 env_set (env, 0, i, CAR (args));
7572ee52
AW
748 *out_body = BOOT_CLOSURE_BODY (proc);
749 *out_env = env;
8f9c5b58
AW
750 }
751 else if (BOOT_CLOSURE_IS_REST (proc))
314b8716
AW
752 {
753 if (SCM_UNLIKELY (scm_ilength (args) < nreq))
8f9c5b58 754 scm_wrong_num_args (proc);
cfc28c80
AW
755
756 env = make_env (nreq + 1, SCM_UNDEFINED, env);
757 for (i = 0; i < nreq; args = CDR (args), i++)
758 env_set (env, 0, i, CAR (args));
759 env_set (env, 0, i++, args);
760
7572ee52
AW
761 *out_body = BOOT_CLOSURE_BODY (proc);
762 *out_env = env;
314b8716
AW
763 }
764 else
d8a071fc 765 {
cfc28c80 766 int i, argc, nreq, nopt, nenv;
d8a071fc 767 SCM body, rest, kw, inits, alt;
dc3e203e 768 SCM mx = BOOT_CLOSURE_CODE (proc);
d8a071fc 769
7572ee52 770 loop:
dc3e203e 771 BOOT_CLOSURE_PARSE_FULL (mx, body, nargs, rest, nopt, kw, inits, alt);
d8a071fc
AW
772
773 argc = scm_ilength (args);
774 if (argc < nreq)
775 {
776 if (scm_is_true (alt))
7572ee52 777 {
dc3e203e 778 mx = alt;
7572ee52
AW
779 goto loop;
780 }
d8a071fc
AW
781 else
782 scm_wrong_num_args (proc);
783 }
784 if (scm_is_false (kw) && argc > nreq + nopt && scm_is_false (rest))
785 {
786 if (scm_is_true (alt))
7572ee52 787 {
dc3e203e 788 mx = alt;
7572ee52
AW
789 goto loop;
790 }
d8a071fc
AW
791 else
792 scm_wrong_num_args (proc);
793 }
cfc28c80
AW
794 if (scm_is_true (kw) && scm_is_false (rest))
795 {
796 int npos = 0;
797 SCM walk;
798 for (walk = args; scm_is_pair (walk); walk = CDR (walk), npos++)
799 if (npos >= nreq && scm_is_keyword (CAR (walk)))
800 break;
801
802 if (npos > nreq + nopt)
803 {
804 /* Too many positional args and no rest arg. */
805 if (scm_is_true (alt))
806 {
807 mx = alt;
808 goto loop;
809 }
810 else
811 scm_wrong_num_args (proc);
812 }
813 }
814
815 /* At this point we are committed to the chosen clause. */
816 nenv = nreq + (scm_is_true (rest) ? 1 : 0) + scm_ilength (inits);
817 env = make_env (nenv, SCM_UNDEFINED, env);
d8a071fc
AW
818
819 for (i = 0; i < nreq; i++, args = CDR (args))
cfc28c80 820 env_set (env, 0, i, CAR (args));
d8a071fc
AW
821
822 if (scm_is_false (kw))
823 {
824 /* Optional args (possibly), but no keyword args. */
825 for (; i < argc && i < nreq + nopt;
cfc28c80
AW
826 i++, args = CDR (args), inits = CDR (inits))
827 env_set (env, 0, i, CAR (args));
d8a071fc
AW
828
829 for (; i < nreq + nopt; i++, inits = CDR (inits))
cfc28c80 830 env_set (env, 0, i, EVAL1 (CAR (inits), env));
d8a071fc
AW
831
832 if (scm_is_true (rest))
cfc28c80 833 env_set (env, 0, i++, args);
d8a071fc
AW
834 }
835 else
836 {
837 SCM aok;
838
839 aok = CAR (kw);
840 kw = CDR (kw);
841
cfc28c80 842 /* Optional args. As before, but stop at the first keyword. */
d8a071fc
AW
843 for (; i < argc && i < nreq + nopt && !scm_is_keyword (CAR (args));
844 i++, args = CDR (args), inits = CDR (inits))
cfc28c80 845 env_set (env, 0, i, CAR (args));
d8a071fc
AW
846
847 for (; i < nreq + nopt; i++, inits = CDR (inits))
cfc28c80 848 env_set (env, 0, i, EVAL1 (CAR (inits), env));
d8a071fc
AW
849
850 if (scm_is_true (rest))
cfc28c80 851 env_set (env, 0, i++, args);
d8a071fc 852
cfc28c80 853 /* Parse keyword args. */
d8a071fc 854 {
d8a071fc 855 int kw_start_idx = i;
cfc28c80 856 SCM walk;
d8a071fc
AW
857
858 if (scm_is_pair (args) && scm_is_pair (CDR (args)))
859 for (; scm_is_pair (args) && scm_is_pair (CDR (args));
860 args = CDR (args))
861 {
cfc28c80 862 SCM k = CAR (args), v = CADR (args);
d8a071fc
AW
863 if (!scm_is_keyword (k))
864 {
865 if (scm_is_true (rest))
866 continue;
867 else
868 break;
869 }
870 for (walk = kw; scm_is_pair (walk); walk = CDR (walk))
871 if (scm_is_eq (k, CAAR (walk)))
872 {
cfc28c80 873 env_set (env, 0, SCM_I_INUM (CDAR (walk)), v);
d8a071fc
AW
874 args = CDR (args);
875 break;
876 }
877 if (scm_is_null (walk) && scm_is_false (aok))
4af0d97e 878 error_unrecognized_keyword (proc, k);
d8a071fc
AW
879 }
880 if (scm_is_pair (args) && scm_is_false (rest))
4af0d97e 881 error_invalid_keyword (proc, CAR (args));
d8a071fc
AW
882
883 /* Now fill in unbound values, evaluating init expressions in their
884 appropriate environment. */
cfc28c80
AW
885 for (i = kw_start_idx; scm_is_pair (inits); i++, inits = CDR (inits))
886 if (SCM_UNBNDP (env_ref (env, 0, i)))
887 env_set (env, 0, i, EVAL1 (CAR (inits), env));
d8a071fc
AW
888 }
889 }
8f9c5b58 890
cfc28c80
AW
891 if (!scm_is_null (inits))
892 abort ();
893 if (i != nenv)
894 abort ();
895
dc3e203e 896 *out_body = body;
7572ee52
AW
897 *out_env = env;
898 }
8f9c5b58
AW
899}
900
7572ee52 901static void
8f9c5b58 902prepare_boot_closure_env_for_eval (SCM proc, unsigned int argc,
7572ee52 903 SCM exps, SCM *out_body, SCM *inout_env)
8f9c5b58
AW
904{
905 int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
906 SCM new_env = BOOT_CLOSURE_ENV (proc);
cfc28c80
AW
907 if ((BOOT_CLOSURE_IS_FIXED (proc)
908 || (BOOT_CLOSURE_IS_REST (proc)
909 && !BOOT_CLOSURE_HAS_REST_ARGS (proc)))
910 && nreq == argc)
314b8716 911 {
cfc28c80
AW
912 int i;
913
914 new_env = make_env (nreq, SCM_UNDEFINED, new_env);
915 for (i = 0; i < nreq; exps = CDR (exps), i++)
916 env_set (new_env, 0, i, EVAL1 (CAR (exps), *inout_env));
917
7572ee52
AW
918 *out_body = BOOT_CLOSURE_BODY (proc);
919 *inout_env = new_env;
314b8716 920 }
cfc28c80 921 else if (BOOT_CLOSURE_IS_REST (proc) && argc >= nreq)
8f9c5b58 922 {
cfc28c80
AW
923 SCM rest;
924 int i;
925
926 new_env = make_env (nreq + 1, SCM_UNDEFINED, new_env);
927 for (i = 0; i < nreq; exps = CDR (exps), i++)
928 env_set (new_env, 0, i, EVAL1 (CAR (exps), *inout_env));
929 for (rest = SCM_EOL; scm_is_pair (exps); exps = CDR (exps))
930 rest = scm_cons (EVAL1 (CAR (exps), *inout_env), rest);
931 env_set (new_env, 0, i++, scm_reverse_x (rest, SCM_UNDEFINED));
932
7572ee52
AW
933 *out_body = BOOT_CLOSURE_BODY (proc);
934 *inout_env = new_env;
8f9c5b58
AW
935 }
936 else
d8a071fc
AW
937 {
938 SCM args = SCM_EOL;
939 for (; scm_is_pair (exps); exps = CDR (exps))
f3a9a51d 940 args = scm_cons (EVAL1 (CAR (exps), *inout_env), args);
7572ee52
AW
941 args = scm_reverse_x (args, SCM_UNDEFINED);
942 prepare_boot_closure_env_for_apply (proc, args, out_body, inout_env);
d8a071fc 943 }
8f9c5b58
AW
944}
945
946static SCM
947boot_closure_apply (SCM closure, SCM args)
948{
7572ee52
AW
949 SCM body, env;
950 prepare_boot_closure_env_for_apply (closure, args, &body, &env);
951 return eval (body, env);
314b8716
AW
952}
953
954static int
955boot_closure_print (SCM closure, SCM port, scm_print_state *pstate)
956{
957 SCM args;
0607ebbf 958 scm_puts_unlocked ("#<boot-closure ", port);
fdecb44f 959 scm_uintprint (SCM_UNPACK (closure), 16, port);
0607ebbf 960 scm_putc_unlocked (' ', port);
314b8716 961 args = scm_make_list (scm_from_int (BOOT_CLOSURE_NUM_REQUIRED_ARGS (closure)),
4a655e50 962 scm_from_latin1_symbol ("_"));
8f9c5b58 963 if (!BOOT_CLOSURE_IS_FIXED (closure) && BOOT_CLOSURE_HAS_REST_ARGS (closure))
4a655e50 964 args = scm_cons_star (scm_from_latin1_symbol ("_"), args);
7572ee52 965 /* FIXME: optionals and rests */
314b8716 966 scm_display (args, port);
0607ebbf 967 scm_putc_unlocked ('>', port);
314b8716
AW
968 return 1;
969}
970
0f2d19dd
JB
971void
972scm_init_eval ()
0f2d19dd 973{
5f161164
AW
974 SCM primitive_eval;
975
df9ca8d8 976 f_apply = scm_c_define_gsubr ("apply", 2, 0, 1, scm_apply);
86d31dfe 977
314b8716
AW
978 scm_tc16_boot_closure = scm_make_smob_type ("boot-closure", 0);
979 scm_set_smob_apply (scm_tc16_boot_closure, boot_closure_apply, 0, 0, 1);
980 scm_set_smob_print (scm_tc16_boot_closure, boot_closure_print);
981
5f161164
AW
982 primitive_eval = scm_c_make_gsubr ("primitive-eval", 1, 0, 0,
983 scm_c_primitive_eval);
984 var_primitive_eval = scm_define (SCM_SUBR_NAME (primitive_eval),
985 primitive_eval);
986
a0599745 987#include "libguile/eval.x"
0f2d19dd 988}
0f2d19dd 989
89e00824
ML
990/*
991 Local Variables:
992 c-file-style: "gnu"
993 End:
994*/
62560650 995