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