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