Remove @prompt memoizer
[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
b7742c6b 610/* This code processes the arguments to apply:
8ea46249 611
b7742c6b 612 (apply PROC ARG1 ... ARGS)
302c12b4 613
b7742c6b
AW
614 Given a list (ARG1 ... ARGS), this function conses the ARG1
615 ... arguments onto the front of ARGS, and returns the resulting
616 list. Note that ARGS is a list; thus, the argument to this
617 function is a list whose last element is a list.
302c12b4 618
b7742c6b
AW
619 Apply calls this function, and applies PROC to the elements of the
620 result. apply:nconc2last takes care of building the list of
621 arguments, given (ARG1 ... ARGS).
a954ce1d 622
b7742c6b
AW
623 Rather than do new consing, apply:nconc2last destroys its argument.
624 On that topic, this code came into my care with the following
625 beautifully cryptic comment on that topic: "This will only screw
626 you if you do (scm_apply scm_apply '( ... ))" If you know what
627 they're referring to, send me a patch to this comment. */
0f2d19dd 628
b7742c6b
AW
629SCM_DEFINE (scm_nconc2last, "apply:nconc2last", 1, 0, 0,
630 (SCM lst),
631 "Given a list (@var{arg1} @dots{} @var{args}), this function\n"
632 "conses the @var{arg1} @dots{} arguments onto the front of\n"
633 "@var{args}, and returns the resulting list. Note that\n"
634 "@var{args} is a list; thus, the argument to this function is\n"
635 "a list whose last element is a list.\n"
636 "Note: Rather than do new consing, @code{apply:nconc2last}\n"
637 "destroys its argument, so use with care.")
638#define FUNC_NAME s_scm_nconc2last
212e58ed 639{
b7742c6b
AW
640 SCM *lloc;
641 SCM_VALIDATE_NONEMPTYLIST (1, lst);
642 lloc = &lst;
b6b84131 643 while (!scm_is_null (SCM_CDR (*lloc)))
b7742c6b
AW
644 lloc = SCM_CDRLOC (*lloc);
645 SCM_ASSERT (scm_ilength (SCM_CAR (*lloc)) >= 0, lst, SCM_ARG1, FUNC_NAME);
646 *lloc = SCM_CAR (*lloc);
647 return lst;
212e58ed 648}
b7742c6b 649#undef FUNC_NAME
212e58ed 650
b8229a3b 651
b7742c6b
AW
652SCM
653scm_map (SCM proc, SCM arg1, SCM args)
0f2d19dd 654{
a2230b65 655 static SCM var = SCM_BOOL_F;
0f2d19dd 656
a2230b65
AW
657 if (scm_is_false (var))
658 var = scm_private_variable (scm_the_root_module (),
659 scm_from_latin1_symbol ("map"));
302c12b4 660
a2230b65
AW
661 return scm_apply (scm_variable_ref (var),
662 scm_cons (proc, scm_cons (arg1, args)), SCM_EOL);
663}
d6754c23 664
b7742c6b
AW
665SCM
666scm_for_each (SCM proc, SCM arg1, SCM args)
0f2d19dd 667{
a2230b65
AW
668 static SCM var = SCM_BOOL_F;
669
670 if (scm_is_false (var))
671 var = scm_private_variable (scm_the_root_module (),
672 scm_from_latin1_symbol ("for-each"));
673
674 return scm_apply (scm_variable_ref (var),
675 scm_cons (proc, scm_cons (arg1, args)), SCM_EOL);
b7742c6b 676}
71560395 677
71560395 678
5f161164
AW
679static SCM
680scm_c_primitive_eval (SCM exp)
b7742c6b 681{
a310a1d1 682 if (!SCM_EXPANDED_P (exp))
4f692ace 683 exp = scm_call_1 (scm_current_module_transformer (), exp);
a310a1d1 684 return eval (scm_memoize_expression (exp), SCM_EOL);
b7742c6b 685}
5f161164
AW
686
687static SCM var_primitive_eval;
688SCM
689scm_primitive_eval (SCM exp)
690{
691 return scm_c_vm_run (scm_the_vm (), scm_variable_ref (var_primitive_eval),
692 &exp, 1);
693}
71560395 694
b7742c6b
AW
695
696/* Eval does not take the second arg optionally. This is intentional
697 * in order to be R5RS compatible, and to prepare for the new module
698 * system, where we would like to make the choice of evaluation
699 * environment explicit. */
700
701SCM_DEFINE (scm_eval, "eval", 2, 0, 0,
702 (SCM exp, SCM module_or_state),
703 "Evaluate @var{exp}, a list representing a Scheme expression,\n"
704 "in the top-level environment specified by\n"
705 "@var{module_or_state}.\n"
706 "While @var{exp} is evaluated (using @code{primitive-eval}),\n"
707 "@var{module_or_state} is made the current module when\n"
708 "it is a module, or the current dynamic state when it is\n"
709 "a dynamic state."
710 "Example: (eval '(+ 1 2) (interaction-environment))")
711#define FUNC_NAME s_scm_eval
712{
713 SCM res;
714
715 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
716 if (scm_is_dynamic_state (module_or_state))
717 scm_dynwind_current_dynamic_state (module_or_state);
718 else if (scm_module_system_booted_p)
719 {
720 SCM_VALIDATE_MODULE (2, module_or_state);
721 scm_dynwind_current_module (module_or_state);
71560395 722 }
b7742c6b 723 /* otherwise if the module system isn't booted, ignore the module arg */
71560395 724
b7742c6b
AW
725 res = scm_primitive_eval (exp);
726
727 scm_dynwind_end ();
728 return res;
729}
730#undef FUNC_NAME
71560395
AW
731
732
b7742c6b 733static SCM f_apply;
71560395
AW
734
735/* Apply a function to a list of arguments.
736
737 This function is exported to the Scheme level as taking two
738 required arguments and a tail argument, as if it were:
739 (lambda (proc arg1 . args) ...)
740 Thus, if you just have a list of arguments to pass to a procedure,
741 pass the list as ARG1, and '() for ARGS. If you have some fixed
742 args, pass the first as ARG1, then cons any remaining fixed args
743 onto the front of your argument list, and pass that as ARGS. */
744
745SCM
746scm_apply (SCM proc, SCM arg1, SCM args)
747{
b7742c6b 748 /* Fix things up so that args contains all args. */
71560395 749 if (scm_is_null (args))
b7742c6b 750 args = arg1;
71560395 751 else
b7742c6b 752 args = scm_cons_star (arg1, args);
71560395 753
ea9f4f4b 754 return scm_call_with_vm (scm_the_vm (), proc, args);
b7742c6b 755}
434f2f7a 756
7572ee52
AW
757static void
758prepare_boot_closure_env_for_apply (SCM proc, SCM args,
759 SCM *out_body, SCM *out_env)
314b8716 760{
8f9c5b58
AW
761 int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
762 SCM env = BOOT_CLOSURE_ENV (proc);
dc3e203e 763
8f9c5b58
AW
764 if (BOOT_CLOSURE_IS_FIXED (proc)
765 || (BOOT_CLOSURE_IS_REST (proc)
766 && !BOOT_CLOSURE_HAS_REST_ARGS (proc)))
767 {
768 if (SCM_UNLIKELY (scm_ilength (args) != nreq))
769 scm_wrong_num_args (proc);
770 for (; scm_is_pair (args); args = CDR (args))
771 env = scm_cons (CAR (args), env);
7572ee52
AW
772 *out_body = BOOT_CLOSURE_BODY (proc);
773 *out_env = env;
8f9c5b58
AW
774 }
775 else if (BOOT_CLOSURE_IS_REST (proc))
314b8716
AW
776 {
777 if (SCM_UNLIKELY (scm_ilength (args) < nreq))
8f9c5b58 778 scm_wrong_num_args (proc);
314b8716 779 for (; nreq; nreq--, args = CDR (args))
8f9c5b58
AW
780 env = scm_cons (CAR (args), env);
781 env = scm_cons (args, env);
7572ee52
AW
782 *out_body = BOOT_CLOSURE_BODY (proc);
783 *out_env = env;
314b8716
AW
784 }
785 else
d8a071fc
AW
786 {
787 int i, argc, nreq, nopt;
788 SCM body, rest, kw, inits, alt;
dc3e203e 789 SCM mx = BOOT_CLOSURE_CODE (proc);
d8a071fc 790
7572ee52 791 loop:
dc3e203e 792 BOOT_CLOSURE_PARSE_FULL (mx, body, nargs, rest, nopt, kw, inits, alt);
d8a071fc
AW
793
794 argc = scm_ilength (args);
795 if (argc < nreq)
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 }
805 if (scm_is_false (kw) && argc > nreq + nopt && scm_is_false (rest))
806 {
807 if (scm_is_true (alt))
7572ee52 808 {
dc3e203e 809 mx = alt;
7572ee52
AW
810 goto loop;
811 }
d8a071fc
AW
812 else
813 scm_wrong_num_args (proc);
814 }
815
816 for (i = 0; i < nreq; i++, args = CDR (args))
817 env = scm_cons (CAR (args), env);
818
819 if (scm_is_false (kw))
820 {
821 /* Optional args (possibly), but no keyword args. */
822 for (; i < argc && i < nreq + nopt;
823 i++, args = CDR (args))
824 {
825 env = scm_cons (CAR (args), env);
826 inits = CDR (inits);
827 }
828
829 for (; i < nreq + nopt; i++, inits = CDR (inits))
f3a9a51d 830 env = scm_cons (EVAL1 (CAR (inits), env), env);
d8a071fc
AW
831
832 if (scm_is_true (rest))
833 env = scm_cons (args, env);
834 }
835 else
836 {
837 SCM aok;
838
839 aok = CAR (kw);
840 kw = CDR (kw);
841
842 /* Keyword args. As before, but stop at the first keyword. */
843 for (; i < argc && i < nreq + nopt && !scm_is_keyword (CAR (args));
844 i++, args = CDR (args), inits = CDR (inits))
845 env = scm_cons (CAR (args), env);
846
847 for (; i < nreq + nopt; i++, inits = CDR (inits))
f3a9a51d 848 env = scm_cons (EVAL1 (CAR (inits), env), env);
d8a071fc
AW
849
850 if (scm_is_true (rest))
851 {
852 env = scm_cons (args, env);
853 i++;
854 }
581f410f
AW
855 else if (scm_is_true (alt)
856 && scm_is_pair (args) && !scm_is_keyword (CAR (args)))
857 {
858 /* Too many positional args, no rest arg, and we have an
859 alternate clause. */
860 mx = alt;
861 goto loop;
862 }
d8a071fc
AW
863
864 /* Now fill in env with unbound values, limn the rest of the args for
865 keywords, and fill in unbound values with their inits. */
866 {
867 int imax = i - 1;
868 int kw_start_idx = i;
869 SCM walk, k, v;
870 for (walk = kw; scm_is_pair (walk); walk = CDR (walk))
871 if (SCM_I_INUM (CDAR (walk)) > imax)
872 imax = SCM_I_INUM (CDAR (walk));
873 for (; i <= imax; i++)
874 env = scm_cons (SCM_UNDEFINED, env);
875
876 if (scm_is_pair (args) && scm_is_pair (CDR (args)))
877 for (; scm_is_pair (args) && scm_is_pair (CDR (args));
878 args = CDR (args))
879 {
880 k = CAR (args); v = CADR (args);
881 if (!scm_is_keyword (k))
882 {
883 if (scm_is_true (rest))
884 continue;
885 else
886 break;
887 }
888 for (walk = kw; scm_is_pair (walk); walk = CDR (walk))
889 if (scm_is_eq (k, CAAR (walk)))
890 {
891 /* Well... ok, list-set! isn't the nicest interface, but
892 hey. */
893 int iset = imax - SCM_I_INUM (CDAR (walk));
894 scm_list_set_x (env, SCM_I_MAKINUM (iset), v);
895 args = CDR (args);
896 break;
897 }
898 if (scm_is_null (walk) && scm_is_false (aok))
899 error_unrecognized_keyword (proc);
900 }
901 if (scm_is_pair (args) && scm_is_false (rest))
902 error_invalid_keyword (proc);
903
904 /* Now fill in unbound values, evaluating init expressions in their
905 appropriate environment. */
906 for (i = imax - kw_start_idx; scm_is_pair (inits); i--, inits = CDR (inits))
907 {
908 SCM tail = scm_list_tail (env, SCM_I_MAKINUM (i));
909 if (SCM_UNBNDP (CAR (tail)))
f3a9a51d 910 SCM_SETCAR (tail, EVAL1 (CAR (inits), CDR (tail)));
d8a071fc
AW
911 }
912 }
913 }
8f9c5b58 914
dc3e203e 915 *out_body = body;
7572ee52
AW
916 *out_env = env;
917 }
8f9c5b58
AW
918}
919
7572ee52 920static void
8f9c5b58 921prepare_boot_closure_env_for_eval (SCM proc, unsigned int argc,
7572ee52 922 SCM exps, SCM *out_body, SCM *inout_env)
8f9c5b58
AW
923{
924 int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
925 SCM new_env = BOOT_CLOSURE_ENV (proc);
926 if (BOOT_CLOSURE_IS_FIXED (proc)
927 || (BOOT_CLOSURE_IS_REST (proc)
928 && !BOOT_CLOSURE_HAS_REST_ARGS (proc)))
314b8716 929 {
8f9c5b58 930 for (; scm_is_pair (exps); exps = CDR (exps), nreq--)
f3a9a51d
AW
931 new_env = scm_cons (EVAL1 (CAR (exps), *inout_env),
932 new_env);
8f9c5b58
AW
933 if (SCM_UNLIKELY (nreq != 0))
934 scm_wrong_num_args (proc);
7572ee52
AW
935 *out_body = BOOT_CLOSURE_BODY (proc);
936 *inout_env = new_env;
314b8716 937 }
8f9c5b58
AW
938 else if (BOOT_CLOSURE_IS_REST (proc))
939 {
940 if (SCM_UNLIKELY (argc < nreq))
941 scm_wrong_num_args (proc);
942 for (; nreq; nreq--, exps = CDR (exps))
f3a9a51d
AW
943 new_env = scm_cons (EVAL1 (CAR (exps), *inout_env),
944 new_env);
8f9c5b58
AW
945 {
946 SCM rest = SCM_EOL;
947 for (; scm_is_pair (exps); exps = CDR (exps))
f3a9a51d 948 rest = scm_cons (EVAL1 (CAR (exps), *inout_env), rest);
8f9c5b58
AW
949 new_env = scm_cons (scm_reverse (rest),
950 new_env);
951 }
7572ee52
AW
952 *out_body = BOOT_CLOSURE_BODY (proc);
953 *inout_env = new_env;
8f9c5b58
AW
954 }
955 else
d8a071fc
AW
956 {
957 SCM args = SCM_EOL;
958 for (; scm_is_pair (exps); exps = CDR (exps))
f3a9a51d 959 args = scm_cons (EVAL1 (CAR (exps), *inout_env), args);
7572ee52
AW
960 args = scm_reverse_x (args, SCM_UNDEFINED);
961 prepare_boot_closure_env_for_apply (proc, args, out_body, inout_env);
d8a071fc 962 }
8f9c5b58
AW
963}
964
965static SCM
966boot_closure_apply (SCM closure, SCM args)
967{
7572ee52
AW
968 SCM body, env;
969 prepare_boot_closure_env_for_apply (closure, args, &body, &env);
970 return eval (body, env);
314b8716
AW
971}
972
973static int
974boot_closure_print (SCM closure, SCM port, scm_print_state *pstate)
975{
976 SCM args;
0607ebbf 977 scm_puts_unlocked ("#<boot-closure ", port);
fdecb44f 978 scm_uintprint (SCM_UNPACK (closure), 16, port);
0607ebbf 979 scm_putc_unlocked (' ', port);
314b8716 980 args = scm_make_list (scm_from_int (BOOT_CLOSURE_NUM_REQUIRED_ARGS (closure)),
4a655e50 981 scm_from_latin1_symbol ("_"));
8f9c5b58 982 if (!BOOT_CLOSURE_IS_FIXED (closure) && BOOT_CLOSURE_HAS_REST_ARGS (closure))
4a655e50 983 args = scm_cons_star (scm_from_latin1_symbol ("_"), args);
7572ee52 984 /* FIXME: optionals and rests */
314b8716 985 scm_display (args, port);
0607ebbf 986 scm_putc_unlocked ('>', port);
314b8716
AW
987 return 1;
988}
989
0f2d19dd
JB
990void
991scm_init_eval ()
0f2d19dd 992{
5f161164
AW
993 SCM primitive_eval;
994
df9ca8d8 995 f_apply = scm_c_define_gsubr ("apply", 2, 0, 1, scm_apply);
86d31dfe 996
314b8716
AW
997 scm_tc16_boot_closure = scm_make_smob_type ("boot-closure", 0);
998 scm_set_smob_apply (scm_tc16_boot_closure, boot_closure_apply, 0, 0, 1);
999 scm_set_smob_print (scm_tc16_boot_closure, boot_closure_print);
1000
5f161164
AW
1001 primitive_eval = scm_c_make_gsubr ("primitive-eval", 1, 0, 0,
1002 scm_c_primitive_eval);
1003 var_primitive_eval = scm_define (SCM_SUBR_NAME (primitive_eval),
1004 primitive_eval);
1005
a0599745 1006#include "libguile/eval.x"
0f2d19dd 1007}
0f2d19dd 1008
89e00824
ML
1009/*
1010 Local Variables:
1011 c-file-style: "gnu"
1012 End:
1013*/
62560650 1014