psyntax simplification
[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;
105#define RETURN_BOOT_CLOSURE(code, env) SCM_RETURN_NEWSMOB2 (scm_tc16_boot_closure, (code), (env))
106#define BOOT_CLOSURE_P(obj) SCM_TYP16_PREDICATE (scm_tc16_boot_closure, (obj))
107#define BOOT_CLOSURE_CODE(x) SCM_SMOB_OBJECT (x)
108#define BOOT_CLOSURE_ENV(x) SCM_SMOB_OBJECT_2 (x)
8f9c5b58
AW
109#define BOOT_CLOSURE_BODY(x) CAR (BOOT_CLOSURE_CODE (x))
110#define BOOT_CLOSURE_NUM_REQUIRED_ARGS(x) SCM_I_INUM (CADR (BOOT_CLOSURE_CODE (x)))
111#define BOOT_CLOSURE_IS_FIXED(x) scm_is_null (CDDR (BOOT_CLOSURE_CODE (x)))
112/* NB: One may only call the following accessors if the closure is not FIXED. */
113#define BOOT_CLOSURE_HAS_REST_ARGS(x) scm_is_true (CADDR (BOOT_CLOSURE_CODE (x)))
114#define BOOT_CLOSURE_IS_REST(x) scm_is_null (CDDDR (BOOT_CLOSURE_CODE (x)))
115/* NB: One may only call the following accessors if the closure is not REST. */
116#define BOOT_CLOSURE_IS_FULL(x) (1)
dc3e203e
AW
117#define BOOT_CLOSURE_PARSE_FULL(fu_,body,nargs,rest,nopt,kw,inits,alt) \
118 do { SCM fu = fu_; \
119 body = CAR (fu); fu = CDR (fu); \
120 \
121 rest = kw = alt = SCM_BOOL_F; \
122 inits = SCM_EOL; \
123 nopt = 0; \
124 \
125 nreq = SCM_I_INUM (CAR (fu)); fu = CDR (fu); \
126 if (scm_is_pair (fu)) \
127 { \
128 rest = CAR (fu); fu = CDR (fu); \
129 if (scm_is_pair (fu)) \
130 { \
131 nopt = SCM_I_INUM (CAR (fu)); fu = CDR (fu); \
132 kw = CAR (fu); fu = CDR (fu); \
133 inits = CAR (fu); fu = CDR (fu); \
134 alt = CAR (fu); \
135 } \
136 } \
d8a071fc 137 } while (0)
7572ee52
AW
138static void prepare_boot_closure_env_for_apply (SCM proc, SCM args,
139 SCM *out_body, SCM *out_env);
140static void prepare_boot_closure_env_for_eval (SCM proc, unsigned int argc,
141 SCM exps, SCM *out_body,
142 SCM *inout_env);
314b8716
AW
143
144
b7742c6b
AW
145#define CAR(x) SCM_CAR(x)
146#define CDR(x) SCM_CDR(x)
147#define CAAR(x) SCM_CAAR(x)
148#define CADR(x) SCM_CADR(x)
149#define CDAR(x) SCM_CDAR(x)
150#define CDDR(x) SCM_CDDR(x)
151#define CADDR(x) SCM_CADDR(x)
152#define CDDDR(x) SCM_CDDDR(x)
e6729603
DH
153
154
b7742c6b 155SCM_SYMBOL (scm_unbound_variable_key, "unbound-variable");
e6729603 156
b7742c6b 157static void error_used_before_defined (void)
d0624e39 158{
b7742c6b
AW
159 scm_error (scm_unbound_variable_key, NULL,
160 "Variable used before given a value", SCM_EOL, SCM_BOOL_F);
d0624e39 161}
d0624e39 162
d8a071fc
AW
163static void error_invalid_keyword (SCM proc)
164{
4a655e50 165 scm_error_scm (scm_from_latin1_symbol ("keyword-argument-error"), proc,
d8a071fc
AW
166 scm_from_locale_string ("Invalid keyword"), SCM_EOL,
167 SCM_BOOL_F);
168}
169
170static void error_unrecognized_keyword (SCM proc)
171{
4a655e50 172 scm_error_scm (scm_from_latin1_symbol ("keyword-argument-error"), proc,
d8a071fc
AW
173 scm_from_locale_string ("Unrecognized keyword"), SCM_EOL,
174 SCM_BOOL_F);
175}
176
177
f3a9a51d
AW
178/* Multiple values truncation. */
179static SCM
180truncate_values (SCM x)
181{
182 if (SCM_LIKELY (!SCM_VALUESP (x)))
183 return x;
184 else
185 {
186 SCM l = scm_struct_ref (x, SCM_INUM0);
187 if (SCM_LIKELY (scm_is_pair (l)))
188 return scm_car (l);
189 else
190 {
191 scm_ithrow (scm_from_latin1_symbol ("vm-run"),
192 scm_list_3 (scm_from_latin1_symbol ("vm-run"),
193 scm_from_locale_string
194 ("Too few values returned to continuation"),
195 SCM_EOL),
196 1);
197 /* Not reached. */
198 return SCM_BOOL_F;
199 }
200 }
201}
202#define EVAL1(x, env) (truncate_values (eval ((x), (env))))
203
b7742c6b 204/* the environment:
3149a5b6 205 (VAL ... . MOD)
b7742c6b
AW
206 If MOD is #f, it means the environment was captured before modules were
207 booted.
208 If MOD is the literal value '(), we are evaluating at the top level, and so
209 should track changes to the current module. You have to be careful in this
210 case, because further lexical contours should capture the current module.
211*/
212#define CAPTURE_ENV(env) \
213 ((env == SCM_EOL) ? scm_current_module () : \
214 ((env == SCM_BOOL_F) ? scm_the_root_module () : env))
6f81708a
DH
215
216static SCM
b7742c6b 217eval (SCM x, SCM env)
6f81708a 218{
b7742c6b
AW
219 SCM mx;
220 SCM proc = SCM_UNDEFINED, args = SCM_EOL;
b7ecadca 221 unsigned int argc;
6f81708a 222
b7742c6b
AW
223 loop:
224 SCM_TICK;
225 if (!SCM_MEMOIZED_P (x))
226 abort ();
227
228 mx = SCM_MEMOIZED_ARGS (x);
229 switch (SCM_MEMOIZED_TAG (x))
230 {
231 case SCM_M_BEGIN:
232 for (; !scm_is_null (CDR (mx)); mx = CDR (mx))
233 eval (CAR (mx), env);
234 x = CAR (mx);
235 goto loop;
236
237 case SCM_M_IF:
f3a9a51d 238 if (scm_is_true (EVAL1 (CAR (mx), env)))
b7742c6b 239 x = CADR (mx);
6f81708a 240 else
b7742c6b
AW
241 x = CDDR (mx);
242 goto loop;
5fb64383 243
b7742c6b
AW
244 case SCM_M_LET:
245 {
246 SCM inits = CAR (mx);
247 SCM new_env = CAPTURE_ENV (env);
248 for (; scm_is_pair (inits); inits = CDR (inits))
f3a9a51d
AW
249 new_env = scm_cons (EVAL1 (CAR (inits), env),
250 new_env);
b7742c6b
AW
251 env = new_env;
252 x = CDR (mx);
253 goto loop;
254 }
255
256 case SCM_M_LAMBDA:
314b8716 257 RETURN_BOOT_CLOSURE (mx, CAPTURE_ENV (env));
5fb64383 258
b7742c6b
AW
259 case SCM_M_QUOTE:
260 return mx;
0f2d19dd 261
b7742c6b 262 case SCM_M_DEFINE:
f3a9a51d 263 scm_define (CAR (mx), EVAL1 (CDR (mx), env));
b7742c6b 264 return SCM_UNSPECIFIED;
212e58ed 265
d69531e2
AW
266 case SCM_M_DYNWIND:
267 {
268 SCM in, out, res, old_winds;
f3a9a51d
AW
269 in = EVAL1 (CAR (mx), env);
270 out = EVAL1 (CDDR (mx), env);
d69531e2
AW
271 scm_call_0 (in);
272 old_winds = scm_i_dynwinds ();
273 scm_i_set_dynwinds (scm_acons (in, out, old_winds));
274 res = eval (CADR (mx), env);
275 scm_i_set_dynwinds (old_winds);
276 scm_call_0 (out);
277 return res;
278 }
279
bb0229b5
AW
280 case SCM_M_WITH_FLUIDS:
281 {
282 long i, len;
283 SCM *fluidv, *valuesv, walk, wf, res;
284 len = scm_ilength (CAR (mx));
285 fluidv = alloca (sizeof (SCM)*len);
286 for (i = 0, walk = CAR (mx); i < len; i++, walk = CDR (walk))
f3a9a51d 287 fluidv[i] = EVAL1 (CAR (walk), env);
bb0229b5
AW
288 valuesv = alloca (sizeof (SCM)*len);
289 for (i = 0, walk = CADR (mx); i < len; i++, walk = CDR (walk))
f3a9a51d 290 valuesv[i] = EVAL1 (CAR (walk), env);
bb0229b5
AW
291
292 wf = scm_i_make_with_fluids (len, fluidv, valuesv);
293 scm_i_swap_with_fluids (wf, SCM_I_CURRENT_THREAD->dynamic_state);
294 scm_i_set_dynwinds (scm_cons (wf, scm_i_dynwinds ()));
295 res = eval (CDDR (mx), env);
296 scm_i_swap_with_fluids (wf, SCM_I_CURRENT_THREAD->dynamic_state);
297 scm_i_set_dynwinds (CDR (scm_i_dynwinds ()));
298
299 return res;
300 }
301
b7742c6b
AW
302 case SCM_M_APPLY:
303 /* Evaluate the procedure to be applied. */
f3a9a51d 304 proc = EVAL1 (CAR (mx), env);
b7742c6b 305 /* Evaluate the argument holding the list of arguments */
f3a9a51d 306 args = EVAL1 (CADR (mx), env);
b7742c6b
AW
307
308 apply_proc:
309 /* Go here to tail-apply a procedure. PROC is the procedure and
310 * ARGS is the list of arguments. */
314b8716 311 if (BOOT_CLOSURE_P (proc))
b7742c6b 312 {
7572ee52 313 prepare_boot_closure_env_for_apply (proc, args, &x, &env);
b7742c6b
AW
314 goto loop;
315 }
316 else
ea9f4f4b 317 return scm_call_with_vm (scm_the_vm (), proc, args);
212e58ed 318
b7742c6b
AW
319 case SCM_M_CALL:
320 /* Evaluate the procedure to be applied. */
f3a9a51d 321 proc = EVAL1 (CAR (mx), env);
b7ecadca 322 argc = SCM_I_INUM (CADR (mx));
9331f91c 323 mx = CDDR (mx);
212e58ed 324
314b8716 325 if (BOOT_CLOSURE_P (proc))
5fa0939c 326 {
7572ee52 327 prepare_boot_closure_env_for_eval (proc, argc, mx, &x, &env);
b7742c6b 328 goto loop;
5fa0939c 329 }
b7742c6b
AW
330 else
331 {
e2cf8eb9 332 SCM *argv;
b7ecadca
LC
333 unsigned int i;
334
e2cf8eb9 335 argv = alloca (argc * sizeof (SCM));
b7ecadca 336 for (i = 0; i < argc; i++, mx = CDR (mx))
f3a9a51d 337 argv[i] = EVAL1 (CAR (mx), env);
b7ecadca
LC
338
339 return scm_c_vm_run (scm_the_vm (), proc, argv, argc);
b7742c6b 340 }
b7ecadca 341
b7742c6b 342 case SCM_M_CONT:
f3a9a51d 343 return scm_i_call_with_current_continuation (EVAL1 (mx, env));
212e58ed 344
b7742c6b
AW
345 case SCM_M_CALL_WITH_VALUES:
346 {
347 SCM producer;
348 SCM v;
349
f3a9a51d
AW
350 producer = EVAL1 (CAR (mx), env);
351 /* `proc' is the consumer. */
352 proc = EVAL1 (CDR (mx), env);
ea9f4f4b 353 v = scm_call_with_vm (scm_the_vm (), producer, SCM_EOL);
b7742c6b
AW
354 if (SCM_VALUESP (v))
355 args = scm_struct_ref (v, SCM_INUM0);
356 else
357 args = scm_list_1 (v);
358 goto apply_proc;
359 }
26d5b9b4 360
b7742c6b
AW
361 case SCM_M_LEXICAL_REF:
362 {
363 int n;
364 SCM ret;
365 for (n = SCM_I_INUM (mx); n; n--)
366 env = CDR (env);
367 ret = CAR (env);
368 if (SCM_UNLIKELY (SCM_UNBNDP (ret)))
369 /* we don't know what variable, though, because we don't have its
370 name */
371 error_used_before_defined ();
372 return ret;
373 }
1cc91f1b 374
b7742c6b
AW
375 case SCM_M_LEXICAL_SET:
376 {
377 int n;
f3a9a51d 378 SCM val = EVAL1 (CDR (mx), env);
b7742c6b
AW
379 for (n = SCM_I_INUM (CAR (mx)); n; n--)
380 env = CDR (env);
381 SCM_SETCAR (env, val);
382 return SCM_UNSPECIFIED;
383 }
910b5125 384
b7742c6b
AW
385 case SCM_M_TOPLEVEL_REF:
386 if (SCM_VARIABLEP (mx))
387 return SCM_VARIABLE_REF (mx);
388 else
57d23e25 389 {
b7742c6b 390 while (scm_is_pair (env))
f3a8d1b7 391 env = CDR (env);
3149a5b6
AW
392 return SCM_VARIABLE_REF
393 (scm_memoize_variable_access_x (x, CAPTURE_ENV (env)));
57d23e25 394 }
57d23e25 395
b7742c6b
AW
396 case SCM_M_TOPLEVEL_SET:
397 {
398 SCM var = CAR (mx);
f3a9a51d 399 SCM val = EVAL1 (CDR (mx), env);
b7742c6b
AW
400 if (SCM_VARIABLEP (var))
401 {
402 SCM_VARIABLE_SET (var, val);
403 return SCM_UNSPECIFIED;
404 }
405 else
406 {
407 while (scm_is_pair (env))
f3a8d1b7 408 env = CDR (env);
3149a5b6
AW
409 SCM_VARIABLE_SET
410 (scm_memoize_variable_access_x (x, CAPTURE_ENV (env)),
411 val);
b7742c6b
AW
412 return SCM_UNSPECIFIED;
413 }
414 }
910b5125 415
b7742c6b
AW
416 case SCM_M_MODULE_REF:
417 if (SCM_VARIABLEP (mx))
418 return SCM_VARIABLE_REF (mx);
910b5125 419 else
3149a5b6
AW
420 return SCM_VARIABLE_REF
421 (scm_memoize_variable_access_x (x, SCM_BOOL_F));
910b5125 422
b7742c6b
AW
423 case SCM_M_MODULE_SET:
424 if (SCM_VARIABLEP (CDR (mx)))
910b5125 425 {
f3a9a51d 426 SCM_VARIABLE_SET (CDR (mx), EVAL1 (CAR (mx), env));
b7742c6b
AW
427 return SCM_UNSPECIFIED;
428 }
429 else
430 {
3149a5b6
AW
431 SCM_VARIABLE_SET
432 (scm_memoize_variable_access_x (x, SCM_BOOL_F),
f3a9a51d 433 EVAL1 (CAR (mx), env));
b7742c6b 434 return SCM_UNSPECIFIED;
910b5125 435 }
910b5125 436
747022e4
AW
437 case SCM_M_PROMPT:
438 {
7112a34d
AW
439 SCM vm, res;
440 /* We need the prompt and handler values after a longjmp case,
441 so make sure they are volatile. */
442 volatile SCM handler, prompt;
747022e4 443
d2964315 444 vm = scm_the_vm ();
f3a9a51d
AW
445 prompt = scm_c_make_prompt (EVAL1 (CAR (mx), env),
446 SCM_VM_DATA (vm)->fp,
d2964315 447 SCM_VM_DATA (vm)->sp, SCM_VM_DATA (vm)->ip,
adbdfd6d 448 0, -1, scm_i_dynwinds ());
f3a9a51d 449 handler = EVAL1 (CDDR (mx), env);
747022e4
AW
450 scm_i_set_dynwinds (scm_cons (prompt, scm_i_dynwinds ()));
451
452 if (SCM_PROMPT_SETJMP (prompt))
453 {
b8af64db 454 /* The prompt exited nonlocally. */
747022e4 455 proc = handler;
572eef50 456 args = scm_i_prompt_pop_abort_args_x (scm_the_vm ());
747022e4
AW
457 goto apply_proc;
458 }
459
460 res = eval (CADR (mx), env);
461 scm_i_set_dynwinds (CDR (scm_i_dynwinds ()));
462 return res;
463 }
464
b7742c6b
AW
465 default:
466 abort ();
467 }
910b5125
DH
468}
469
b7742c6b 470\f
2a6f7afe 471
b7742c6b
AW
472/* Simple procedure calls
473 */
2a6f7afe 474
b7742c6b
AW
475SCM
476scm_call_0 (SCM proc)
477{
bf5a05f2 478 return scm_c_vm_run (scm_the_vm (), proc, NULL, 0);
0f2d19dd
JB
479}
480
b7742c6b
AW
481SCM
482scm_call_1 (SCM proc, SCM arg1)
212e58ed 483{
bf5a05f2 484 return scm_c_vm_run (scm_the_vm (), proc, &arg1, 1);
b7742c6b 485}
212e58ed 486
b7742c6b
AW
487SCM
488scm_call_2 (SCM proc, SCM arg1, SCM arg2)
489{
bf5a05f2
AW
490 SCM args[] = { arg1, arg2 };
491 return scm_c_vm_run (scm_the_vm (), proc, args, 2);
212e58ed
DH
492}
493
b7742c6b
AW
494SCM
495scm_call_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3)
0f2d19dd 496{
bf5a05f2
AW
497 SCM args[] = { arg1, arg2, arg3 };
498 return scm_c_vm_run (scm_the_vm (), proc, args, 3);
0f2d19dd
JB
499}
500
b7742c6b
AW
501SCM
502scm_call_4 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4)
212e58ed 503{
bf5a05f2
AW
504 SCM args[] = { arg1, arg2, arg3, arg4 };
505 return scm_c_vm_run (scm_the_vm (), proc, args, 4);
212e58ed
DH
506}
507
f32e67be
AW
508SCM
509scm_call_5 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5)
510{
511 SCM args[] = { arg1, arg2, arg3, arg4, arg5 };
512 return scm_c_vm_run (scm_the_vm (), proc, args, 5);
513}
514
515SCM
516scm_call_6 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
517 SCM arg6)
518{
519 SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6 };
520 return scm_c_vm_run (scm_the_vm (), proc, args, 6);
521}
522
86fd6dff
AW
523SCM
524scm_call_n (SCM proc, SCM *argv, size_t nargs)
525{
526 return scm_c_vm_run (scm_the_vm (), proc, argv, nargs);
527}
528
b7742c6b 529/* Simple procedure applies
9fbee57e 530 */
cc56ba80 531
b7742c6b
AW
532SCM
533scm_apply_0 (SCM proc, SCM args)
534{
535 return scm_apply (proc, args, SCM_EOL);
0f572ba7
DH
536}
537
b7742c6b
AW
538SCM
539scm_apply_1 (SCM proc, SCM arg1, SCM args)
0f572ba7 540{
b7742c6b 541 return scm_apply (proc, scm_cons (arg1, args), SCM_EOL);
8ae95199
DH
542}
543
b7742c6b
AW
544SCM
545scm_apply_2 (SCM proc, SCM arg1, SCM arg2, SCM args)
0f2d19dd 546{
b7742c6b 547 return scm_apply (proc, scm_cons2 (arg1, arg2, args), SCM_EOL);
0f2d19dd
JB
548}
549
b7742c6b
AW
550SCM
551scm_apply_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM args)
212e58ed 552{
b7742c6b
AW
553 return scm_apply (proc, scm_cons (arg1, scm_cons2 (arg2, arg3, args)),
554 SCM_EOL);
212e58ed
DH
555}
556
b7742c6b 557/* This code processes the arguments to apply:
8ea46249 558
b7742c6b 559 (apply PROC ARG1 ... ARGS)
302c12b4 560
b7742c6b
AW
561 Given a list (ARG1 ... ARGS), this function conses the ARG1
562 ... arguments onto the front of ARGS, and returns the resulting
563 list. Note that ARGS is a list; thus, the argument to this
564 function is a list whose last element is a list.
302c12b4 565
b7742c6b
AW
566 Apply calls this function, and applies PROC to the elements of the
567 result. apply:nconc2last takes care of building the list of
568 arguments, given (ARG1 ... ARGS).
a954ce1d 569
b7742c6b
AW
570 Rather than do new consing, apply:nconc2last destroys its argument.
571 On that topic, this code came into my care with the following
572 beautifully cryptic comment on that topic: "This will only screw
573 you if you do (scm_apply scm_apply '( ... ))" If you know what
574 they're referring to, send me a patch to this comment. */
0f2d19dd 575
b7742c6b
AW
576SCM_DEFINE (scm_nconc2last, "apply:nconc2last", 1, 0, 0,
577 (SCM lst),
578 "Given a list (@var{arg1} @dots{} @var{args}), this function\n"
579 "conses the @var{arg1} @dots{} arguments onto the front of\n"
580 "@var{args}, and returns the resulting list. Note that\n"
581 "@var{args} is a list; thus, the argument to this function is\n"
582 "a list whose last element is a list.\n"
583 "Note: Rather than do new consing, @code{apply:nconc2last}\n"
584 "destroys its argument, so use with care.")
585#define FUNC_NAME s_scm_nconc2last
212e58ed 586{
b7742c6b
AW
587 SCM *lloc;
588 SCM_VALIDATE_NONEMPTYLIST (1, lst);
589 lloc = &lst;
b6b84131 590 while (!scm_is_null (SCM_CDR (*lloc)))
b7742c6b
AW
591 lloc = SCM_CDRLOC (*lloc);
592 SCM_ASSERT (scm_ilength (SCM_CAR (*lloc)) >= 0, lst, SCM_ARG1, FUNC_NAME);
593 *lloc = SCM_CAR (*lloc);
594 return lst;
212e58ed 595}
b7742c6b 596#undef FUNC_NAME
212e58ed 597
b8229a3b
MS
598
599
b7742c6b 600/* Typechecking for multi-argument MAP and FOR-EACH.
0f2d19dd 601
b7742c6b
AW
602 Verify that each element of the vector ARGV, except for the first,
603 is a proper list whose length is LEN. Attribute errors to WHO,
604 and claim that the i'th element of ARGV is WHO's i+2'th argument. */
605static inline void
606check_map_args (SCM argv,
607 long len,
608 SCM gf,
609 SCM proc,
610 SCM args,
611 const char *who)
212e58ed 612{
b7742c6b 613 long i;
0f2d19dd 614
b7742c6b 615 for (i = SCM_SIMPLE_VECTOR_LENGTH (argv) - 1; i >= 1; i--)
9fbee57e 616 {
b7742c6b
AW
617 SCM elt = SCM_SIMPLE_VECTOR_REF (argv, i);
618 long elt_len = scm_ilength (elt);
5cb22e96 619
b7742c6b
AW
620 if (elt_len < 0)
621 {
622 if (gf)
623 scm_apply_generic (gf, scm_cons (proc, args));
624 else
625 scm_wrong_type_arg (who, i + 2, elt);
626 }
1cc91f1b 627
b7742c6b
AW
628 if (elt_len != len)
629 scm_out_of_range_pos (who, elt, scm_from_long (i + 2));
0f2d19dd 630 }
0f2d19dd 631}
6dbd0af5 632
212e58ed 633
b7742c6b 634SCM_GPROC (s_map, "map", 2, 0, 1, scm_map, g_map);
212e58ed 635
b7742c6b
AW
636/* Note: Currently, scm_map applies PROC to the argument list(s)
637 sequentially, starting with the first element(s). This is used in
638 evalext.c where the Scheme procedure `map-in-order', which guarantees
639 sequential behaviour, is implemented using scm_map. If the
640 behaviour changes, we need to update `map-in-order'.
641*/
0f2d19dd 642
b7742c6b
AW
643SCM
644scm_map (SCM proc, SCM arg1, SCM args)
645#define FUNC_NAME s_map
0f2d19dd 646{
b7742c6b
AW
647 long i, len;
648 SCM res = SCM_EOL;
649 SCM *pres = &res;
0f2d19dd 650
b7742c6b
AW
651 len = scm_ilength (arg1);
652 SCM_GASSERTn (len >= 0,
653 g_map, scm_cons2 (proc, arg1, args), SCM_ARG2, s_map);
654 SCM_VALIDATE_REST_ARGUMENT (args);
655 if (scm_is_null (args))
0f2d19dd 656 {
b7742c6b
AW
657 SCM_GASSERT2 (scm_is_true (scm_procedure_p (proc)), g_map, proc, arg1, SCM_ARG1, s_map);
658 while (SCM_NIMP (arg1))
659 {
660 *pres = scm_list_1 (scm_call_1 (proc, SCM_CAR (arg1)));
661 pres = SCM_CDRLOC (*pres);
662 arg1 = SCM_CDR (arg1);
663 }
664 return res;
0f2d19dd 665 }
b7742c6b
AW
666 if (scm_is_null (SCM_CDR (args)))
667 {
668 SCM arg2 = SCM_CAR (args);
669 int len2 = scm_ilength (arg2);
670 SCM_GASSERTn (scm_is_true (scm_procedure_p (proc)), g_map,
671 scm_cons2 (proc, arg1, args), SCM_ARG1, s_map);
672 SCM_GASSERTn (len2 >= 0,
673 g_map, scm_cons2 (proc, arg1, args), SCM_ARG3, s_map);
674 if (len2 != len)
675 SCM_OUT_OF_RANGE (3, arg2);
676 while (SCM_NIMP (arg1))
677 {
678 *pres = scm_list_1 (scm_call_2 (proc, SCM_CAR (arg1), SCM_CAR (arg2)));
679 pres = SCM_CDRLOC (*pres);
680 arg1 = SCM_CDR (arg1);
681 arg2 = SCM_CDR (arg2);
682 }
683 return res;
684 }
685 arg1 = scm_cons (arg1, args);
686 args = scm_vector (arg1);
687 check_map_args (args, len, g_map, proc, arg1, s_map);
688 while (1)
d6754c23 689 {
b7742c6b
AW
690 arg1 = SCM_EOL;
691 for (i = SCM_SIMPLE_VECTOR_LENGTH (args) - 1; i >= 0; i--)
692 {
693 SCM elt = SCM_SIMPLE_VECTOR_REF (args, i);
694 if (SCM_IMP (elt))
695 return res;
696 arg1 = scm_cons (SCM_CAR (elt), arg1);
697 SCM_SIMPLE_VECTOR_SET (args, i, SCM_CDR (elt));
698 }
699 *pres = scm_list_1 (scm_apply (proc, arg1, SCM_EOL));
700 pres = SCM_CDRLOC (*pres);
d6754c23 701 }
0f2d19dd 702}
b7742c6b 703#undef FUNC_NAME
0f2d19dd 704
302c12b4 705
b7742c6b 706SCM_GPROC (s_for_each, "for-each", 2, 0, 1, scm_for_each, g_for_each);
d6754c23 707
b7742c6b
AW
708SCM
709scm_for_each (SCM proc, SCM arg1, SCM args)
710#define FUNC_NAME s_for_each
0f2d19dd 711{
b7742c6b
AW
712 long i, len;
713 len = scm_ilength (arg1);
714 SCM_GASSERTn (len >= 0, g_for_each, scm_cons2 (proc, arg1, args),
715 SCM_ARG2, s_for_each);
716 SCM_VALIDATE_REST_ARGUMENT (args);
717 if (scm_is_null (args))
26d5b9b4 718 {
b7742c6b
AW
719 SCM_GASSERT2 (scm_is_true (scm_procedure_p (proc)), g_for_each,
720 proc, arg1, SCM_ARG1, s_for_each);
721 while (SCM_NIMP (arg1))
722 {
723 scm_call_1 (proc, SCM_CAR (arg1));
724 arg1 = SCM_CDR (arg1);
725 }
726 return SCM_UNSPECIFIED;
26d5b9b4 727 }
b7742c6b 728 if (scm_is_null (SCM_CDR (args)))
26d5b9b4 729 {
b7742c6b
AW
730 SCM arg2 = SCM_CAR (args);
731 int len2 = scm_ilength (arg2);
732 SCM_GASSERTn (scm_is_true (scm_procedure_p (proc)), g_for_each,
733 scm_cons2 (proc, arg1, args), SCM_ARG1, s_for_each);
734 SCM_GASSERTn (len2 >= 0, g_for_each,
735 scm_cons2 (proc, arg1, args), SCM_ARG3, s_for_each);
736 if (len2 != len)
737 SCM_OUT_OF_RANGE (3, arg2);
738 while (SCM_NIMP (arg1))
739 {
740 scm_call_2 (proc, SCM_CAR (arg1), SCM_CAR (arg2));
741 arg1 = SCM_CDR (arg1);
742 arg2 = SCM_CDR (arg2);
743 }
744 return SCM_UNSPECIFIED;
26d5b9b4 745 }
b7742c6b
AW
746 arg1 = scm_cons (arg1, args);
747 args = scm_vector (arg1);
748 check_map_args (args, len, g_for_each, proc, arg1, s_for_each);
749 while (1)
302c12b4 750 {
b7742c6b
AW
751 arg1 = SCM_EOL;
752 for (i = SCM_SIMPLE_VECTOR_LENGTH (args) - 1; i >= 0; i--)
71560395 753 {
b7742c6b
AW
754 SCM elt = SCM_SIMPLE_VECTOR_REF (args, i);
755 if (SCM_IMP (elt))
756 return SCM_UNSPECIFIED;
757 arg1 = scm_cons (SCM_CAR (elt), arg1);
758 SCM_SIMPLE_VECTOR_SET (args, i, SCM_CDR (elt));
759 }
760 scm_apply (proc, arg1, SCM_EOL);
761 }
762}
763#undef FUNC_NAME
71560395 764
71560395 765
5f161164
AW
766static SCM
767scm_c_primitive_eval (SCM exp)
b7742c6b 768{
a310a1d1 769 if (!SCM_EXPANDED_P (exp))
4f692ace 770 exp = scm_call_1 (scm_current_module_transformer (), exp);
a310a1d1 771 return eval (scm_memoize_expression (exp), SCM_EOL);
b7742c6b 772}
5f161164
AW
773
774static SCM var_primitive_eval;
775SCM
776scm_primitive_eval (SCM exp)
777{
778 return scm_c_vm_run (scm_the_vm (), scm_variable_ref (var_primitive_eval),
779 &exp, 1);
780}
71560395 781
b7742c6b
AW
782
783/* Eval does not take the second arg optionally. This is intentional
784 * in order to be R5RS compatible, and to prepare for the new module
785 * system, where we would like to make the choice of evaluation
786 * environment explicit. */
787
788SCM_DEFINE (scm_eval, "eval", 2, 0, 0,
789 (SCM exp, SCM module_or_state),
790 "Evaluate @var{exp}, a list representing a Scheme expression,\n"
791 "in the top-level environment specified by\n"
792 "@var{module_or_state}.\n"
793 "While @var{exp} is evaluated (using @code{primitive-eval}),\n"
794 "@var{module_or_state} is made the current module when\n"
795 "it is a module, or the current dynamic state when it is\n"
796 "a dynamic state."
797 "Example: (eval '(+ 1 2) (interaction-environment))")
798#define FUNC_NAME s_scm_eval
799{
800 SCM res;
801
802 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
803 if (scm_is_dynamic_state (module_or_state))
804 scm_dynwind_current_dynamic_state (module_or_state);
805 else if (scm_module_system_booted_p)
806 {
807 SCM_VALIDATE_MODULE (2, module_or_state);
808 scm_dynwind_current_module (module_or_state);
71560395 809 }
b7742c6b 810 /* otherwise if the module system isn't booted, ignore the module arg */
71560395 811
b7742c6b
AW
812 res = scm_primitive_eval (exp);
813
814 scm_dynwind_end ();
815 return res;
816}
817#undef FUNC_NAME
71560395
AW
818
819
b7742c6b 820static SCM f_apply;
71560395
AW
821
822/* Apply a function to a list of arguments.
823
824 This function is exported to the Scheme level as taking two
825 required arguments and a tail argument, as if it were:
826 (lambda (proc arg1 . args) ...)
827 Thus, if you just have a list of arguments to pass to a procedure,
828 pass the list as ARG1, and '() for ARGS. If you have some fixed
829 args, pass the first as ARG1, then cons any remaining fixed args
830 onto the front of your argument list, and pass that as ARGS. */
831
832SCM
833scm_apply (SCM proc, SCM arg1, SCM args)
834{
b7742c6b 835 /* Fix things up so that args contains all args. */
71560395 836 if (scm_is_null (args))
b7742c6b 837 args = arg1;
71560395 838 else
b7742c6b 839 args = scm_cons_star (arg1, args);
71560395 840
ea9f4f4b 841 return scm_call_with_vm (scm_the_vm (), proc, args);
b7742c6b 842}
434f2f7a 843
7572ee52
AW
844static void
845prepare_boot_closure_env_for_apply (SCM proc, SCM args,
846 SCM *out_body, SCM *out_env)
314b8716 847{
8f9c5b58
AW
848 int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
849 SCM env = BOOT_CLOSURE_ENV (proc);
dc3e203e 850
8f9c5b58
AW
851 if (BOOT_CLOSURE_IS_FIXED (proc)
852 || (BOOT_CLOSURE_IS_REST (proc)
853 && !BOOT_CLOSURE_HAS_REST_ARGS (proc)))
854 {
855 if (SCM_UNLIKELY (scm_ilength (args) != nreq))
856 scm_wrong_num_args (proc);
857 for (; scm_is_pair (args); args = CDR (args))
858 env = scm_cons (CAR (args), env);
7572ee52
AW
859 *out_body = BOOT_CLOSURE_BODY (proc);
860 *out_env = env;
8f9c5b58
AW
861 }
862 else if (BOOT_CLOSURE_IS_REST (proc))
314b8716
AW
863 {
864 if (SCM_UNLIKELY (scm_ilength (args) < nreq))
8f9c5b58 865 scm_wrong_num_args (proc);
314b8716 866 for (; nreq; nreq--, args = CDR (args))
8f9c5b58
AW
867 env = scm_cons (CAR (args), env);
868 env = scm_cons (args, env);
7572ee52
AW
869 *out_body = BOOT_CLOSURE_BODY (proc);
870 *out_env = env;
314b8716
AW
871 }
872 else
d8a071fc
AW
873 {
874 int i, argc, nreq, nopt;
875 SCM body, rest, kw, inits, alt;
dc3e203e 876 SCM mx = BOOT_CLOSURE_CODE (proc);
d8a071fc 877
7572ee52 878 loop:
dc3e203e 879 BOOT_CLOSURE_PARSE_FULL (mx, body, nargs, rest, nopt, kw, inits, alt);
d8a071fc
AW
880
881 argc = scm_ilength (args);
882 if (argc < nreq)
883 {
884 if (scm_is_true (alt))
7572ee52 885 {
dc3e203e 886 mx = alt;
7572ee52
AW
887 goto loop;
888 }
d8a071fc
AW
889 else
890 scm_wrong_num_args (proc);
891 }
892 if (scm_is_false (kw) && argc > nreq + nopt && scm_is_false (rest))
893 {
894 if (scm_is_true (alt))
7572ee52 895 {
dc3e203e 896 mx = alt;
7572ee52
AW
897 goto loop;
898 }
d8a071fc
AW
899 else
900 scm_wrong_num_args (proc);
901 }
902
903 for (i = 0; i < nreq; i++, args = CDR (args))
904 env = scm_cons (CAR (args), env);
905
906 if (scm_is_false (kw))
907 {
908 /* Optional args (possibly), but no keyword args. */
909 for (; i < argc && i < nreq + nopt;
910 i++, args = CDR (args))
911 {
912 env = scm_cons (CAR (args), env);
913 inits = CDR (inits);
914 }
915
916 for (; i < nreq + nopt; i++, inits = CDR (inits))
f3a9a51d 917 env = scm_cons (EVAL1 (CAR (inits), env), env);
d8a071fc
AW
918
919 if (scm_is_true (rest))
920 env = scm_cons (args, env);
921 }
922 else
923 {
924 SCM aok;
925
926 aok = CAR (kw);
927 kw = CDR (kw);
928
929 /* Keyword args. As before, but stop at the first keyword. */
930 for (; i < argc && i < nreq + nopt && !scm_is_keyword (CAR (args));
931 i++, args = CDR (args), inits = CDR (inits))
932 env = scm_cons (CAR (args), env);
933
934 for (; i < nreq + nopt; i++, inits = CDR (inits))
f3a9a51d 935 env = scm_cons (EVAL1 (CAR (inits), env), env);
d8a071fc
AW
936
937 if (scm_is_true (rest))
938 {
939 env = scm_cons (args, env);
940 i++;
941 }
942
943 /* Now fill in env with unbound values, limn the rest of the args for
944 keywords, and fill in unbound values with their inits. */
945 {
946 int imax = i - 1;
947 int kw_start_idx = i;
948 SCM walk, k, v;
949 for (walk = kw; scm_is_pair (walk); walk = CDR (walk))
950 if (SCM_I_INUM (CDAR (walk)) > imax)
951 imax = SCM_I_INUM (CDAR (walk));
952 for (; i <= imax; i++)
953 env = scm_cons (SCM_UNDEFINED, env);
954
955 if (scm_is_pair (args) && scm_is_pair (CDR (args)))
956 for (; scm_is_pair (args) && scm_is_pair (CDR (args));
957 args = CDR (args))
958 {
959 k = CAR (args); v = CADR (args);
960 if (!scm_is_keyword (k))
961 {
962 if (scm_is_true (rest))
963 continue;
964 else
965 break;
966 }
967 for (walk = kw; scm_is_pair (walk); walk = CDR (walk))
968 if (scm_is_eq (k, CAAR (walk)))
969 {
970 /* Well... ok, list-set! isn't the nicest interface, but
971 hey. */
972 int iset = imax - SCM_I_INUM (CDAR (walk));
973 scm_list_set_x (env, SCM_I_MAKINUM (iset), v);
974 args = CDR (args);
975 break;
976 }
977 if (scm_is_null (walk) && scm_is_false (aok))
978 error_unrecognized_keyword (proc);
979 }
980 if (scm_is_pair (args) && scm_is_false (rest))
981 error_invalid_keyword (proc);
982
983 /* Now fill in unbound values, evaluating init expressions in their
984 appropriate environment. */
985 for (i = imax - kw_start_idx; scm_is_pair (inits); i--, inits = CDR (inits))
986 {
987 SCM tail = scm_list_tail (env, SCM_I_MAKINUM (i));
988 if (SCM_UNBNDP (CAR (tail)))
f3a9a51d 989 SCM_SETCAR (tail, EVAL1 (CAR (inits), CDR (tail)));
d8a071fc
AW
990 }
991 }
992 }
8f9c5b58 993
dc3e203e 994 *out_body = body;
7572ee52
AW
995 *out_env = env;
996 }
8f9c5b58
AW
997}
998
7572ee52 999static void
8f9c5b58 1000prepare_boot_closure_env_for_eval (SCM proc, unsigned int argc,
7572ee52 1001 SCM exps, SCM *out_body, SCM *inout_env)
8f9c5b58
AW
1002{
1003 int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
1004 SCM new_env = BOOT_CLOSURE_ENV (proc);
1005 if (BOOT_CLOSURE_IS_FIXED (proc)
1006 || (BOOT_CLOSURE_IS_REST (proc)
1007 && !BOOT_CLOSURE_HAS_REST_ARGS (proc)))
314b8716 1008 {
8f9c5b58 1009 for (; scm_is_pair (exps); exps = CDR (exps), nreq--)
f3a9a51d
AW
1010 new_env = scm_cons (EVAL1 (CAR (exps), *inout_env),
1011 new_env);
8f9c5b58
AW
1012 if (SCM_UNLIKELY (nreq != 0))
1013 scm_wrong_num_args (proc);
7572ee52
AW
1014 *out_body = BOOT_CLOSURE_BODY (proc);
1015 *inout_env = new_env;
314b8716 1016 }
8f9c5b58
AW
1017 else if (BOOT_CLOSURE_IS_REST (proc))
1018 {
1019 if (SCM_UNLIKELY (argc < nreq))
1020 scm_wrong_num_args (proc);
1021 for (; nreq; nreq--, exps = CDR (exps))
f3a9a51d
AW
1022 new_env = scm_cons (EVAL1 (CAR (exps), *inout_env),
1023 new_env);
8f9c5b58
AW
1024 {
1025 SCM rest = SCM_EOL;
1026 for (; scm_is_pair (exps); exps = CDR (exps))
f3a9a51d 1027 rest = scm_cons (EVAL1 (CAR (exps), *inout_env), rest);
8f9c5b58
AW
1028 new_env = scm_cons (scm_reverse (rest),
1029 new_env);
1030 }
7572ee52
AW
1031 *out_body = BOOT_CLOSURE_BODY (proc);
1032 *inout_env = new_env;
8f9c5b58
AW
1033 }
1034 else
d8a071fc
AW
1035 {
1036 SCM args = SCM_EOL;
1037 for (; scm_is_pair (exps); exps = CDR (exps))
f3a9a51d 1038 args = scm_cons (EVAL1 (CAR (exps), *inout_env), args);
7572ee52
AW
1039 args = scm_reverse_x (args, SCM_UNDEFINED);
1040 prepare_boot_closure_env_for_apply (proc, args, out_body, inout_env);
d8a071fc 1041 }
8f9c5b58
AW
1042}
1043
1044static SCM
1045boot_closure_apply (SCM closure, SCM args)
1046{
7572ee52
AW
1047 SCM body, env;
1048 prepare_boot_closure_env_for_apply (closure, args, &body, &env);
1049 return eval (body, env);
314b8716
AW
1050}
1051
1052static int
1053boot_closure_print (SCM closure, SCM port, scm_print_state *pstate)
1054{
1055 SCM args;
1056 scm_puts ("#<boot-closure ", port);
3d27ef4b 1057 scm_uintprint ((scm_t_bits)SCM2PTR (closure), 16, port);
314b8716
AW
1058 scm_putc (' ', port);
1059 args = scm_make_list (scm_from_int (BOOT_CLOSURE_NUM_REQUIRED_ARGS (closure)),
4a655e50 1060 scm_from_latin1_symbol ("_"));
8f9c5b58 1061 if (!BOOT_CLOSURE_IS_FIXED (closure) && BOOT_CLOSURE_HAS_REST_ARGS (closure))
4a655e50 1062 args = scm_cons_star (scm_from_latin1_symbol ("_"), args);
7572ee52 1063 /* FIXME: optionals and rests */
314b8716
AW
1064 scm_display (args, port);
1065 scm_putc ('>', port);
1066 return 1;
1067}
1068
0f2d19dd
JB
1069void
1070scm_init_eval ()
0f2d19dd 1071{
5f161164
AW
1072 SCM primitive_eval;
1073
df9ca8d8 1074 f_apply = scm_c_define_gsubr ("apply", 2, 0, 1, scm_apply);
86d31dfe 1075
314b8716
AW
1076 scm_tc16_boot_closure = scm_make_smob_type ("boot-closure", 0);
1077 scm_set_smob_apply (scm_tc16_boot_closure, boot_closure_apply, 0, 0, 1);
1078 scm_set_smob_print (scm_tc16_boot_closure, boot_closure_print);
1079
5f161164
AW
1080 primitive_eval = scm_c_make_gsubr ("primitive-eval", 1, 0, 0,
1081 scm_c_primitive_eval);
1082 var_primitive_eval = scm_define (SCM_SUBR_NAME (primitive_eval),
1083 primitive_eval);
1084
a0599745 1085#include "libguile/eval.x"
0f2d19dd 1086}
0f2d19dd 1087
89e00824
ML
1088/*
1089 Local Variables:
1090 c-file-style: "gnu"
1091 End:
1092*/
62560650 1093