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