add fluid tests
[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"
a0599745 34#include "libguile/debug.h"
328dc9a3 35#include "libguile/deprecation.h"
09074dbf 36#include "libguile/dynwind.h"
a0599745 37#include "libguile/eq.h"
21628685
DH
38#include "libguile/feature.h"
39#include "libguile/fluids.h"
21628685
DH
40#include "libguile/goops.h"
41#include "libguile/hash.h"
42#include "libguile/hashtab.h"
43#include "libguile/lang.h"
4610b011 44#include "libguile/list.h"
a0599745 45#include "libguile/macros.h"
b7742c6b 46#include "libguile/memoize.h"
a0599745
MD
47#include "libguile/modules.h"
48#include "libguile/ports.h"
7e6e6b37 49#include "libguile/print.h"
21628685 50#include "libguile/procprop.h"
4abef68f 51#include "libguile/programs.h"
a0599745 52#include "libguile/root.h"
21628685
DH
53#include "libguile/smob.h"
54#include "libguile/srcprop.h"
55#include "libguile/stackchk.h"
56#include "libguile/strings.h"
9de87eea 57#include "libguile/threads.h"
21628685
DH
58#include "libguile/throw.h"
59#include "libguile/validate.h"
a513ead3 60#include "libguile/values.h"
21628685 61#include "libguile/vectors.h"
4abef68f 62#include "libguile/vm.h"
a0599745 63
a0599745 64#include "libguile/eval.h"
0ee05b85 65#include "libguile/private-options.h"
89efbff4 66
0f2d19dd
JB
67\f
68
0ee05b85 69
b7742c6b 70/* We have three levels of EVAL here:
609a8b86 71
b7742c6b 72 - eval (exp, env)
89bff2fc 73
b7742c6b
AW
74 evaluates EXP in environment ENV. ENV is a lexical environment
75 structure as used by the actual tree code evaluator. When ENV is
76 a top-level environment, then changes to the current module are
77 tracked by updating ENV so that it continues to be in sync with
78 the current module.
e6729603 79
b7742c6b 80 - scm_primitive_eval (exp)
e6729603 81
b7742c6b
AW
82 evaluates EXP in the top-level environment as determined by the
83 current module. This is done by constructing a suitable
84 environment and calling eval. Thus, changes to the
85 top-level module are tracked normally.
e6729603 86
b7742c6b 87 - scm_eval (exp, mod)
e6729603 88
b7742c6b
AW
89 evaluates EXP while MOD is the current module. This is done
90 by setting the current module to MOD_OR_STATE, invoking
91 scm_primitive_eval on EXP, and then restoring the current module
92 to the value it had previously. That is, while EXP is evaluated,
93 changes to the current module (or dynamic state) are tracked,
94 but these changes do not persist when scm_eval returns.
e6729603 95
b7742c6b 96*/
e6729603 97
e6729603 98
314b8716
AW
99/* Boot closures. We only see these when compiling eval.scm, because once
100 eval.scm is in the house, closures are standard VM closures.
101 */
102
103static scm_t_bits scm_tc16_boot_closure;
104#define RETURN_BOOT_CLOSURE(code, env) SCM_RETURN_NEWSMOB2 (scm_tc16_boot_closure, (code), (env))
105#define BOOT_CLOSURE_P(obj) SCM_TYP16_PREDICATE (scm_tc16_boot_closure, (obj))
106#define BOOT_CLOSURE_CODE(x) SCM_SMOB_OBJECT (x)
107#define BOOT_CLOSURE_ENV(x) SCM_SMOB_OBJECT_2 (x)
108#define BOOT_CLOSURE_NUM_REQUIRED_ARGS(x) SCM_I_INUM (CAR (BOOT_CLOSURE_CODE (x)))
109#define BOOT_CLOSURE_HAS_REST_ARGS(x) scm_is_true (CADR (BOOT_CLOSURE_CODE (x)))
110#define BOOT_CLOSURE_BODY(x) CDDR (BOOT_CLOSURE_CODE (x))
111
112
113
b7742c6b
AW
114#if 0
115#define CAR(x) SCM_CAR(x)
116#define CDR(x) SCM_CDR(x)
117#define CAAR(x) SCM_CAAR(x)
118#define CADR(x) SCM_CADR(x)
119#define CDAR(x) SCM_CDAR(x)
120#define CDDR(x) SCM_CDDR(x)
121#define CADDR(x) SCM_CADDR(x)
122#define CDDDR(x) SCM_CDDDR(x)
123#else
124#define CAR(x) scm_car(x)
125#define CDR(x) scm_cdr(x)
126#define CAAR(x) scm_caar(x)
127#define CADR(x) scm_cadr(x)
128#define CDAR(x) scm_cdar(x)
129#define CDDR(x) scm_cddr(x)
130#define CADDR(x) scm_caddr(x)
131#define CDDDR(x) scm_cdddr(x)
132#endif
e6729603
DH
133
134
b7742c6b 135SCM_SYMBOL (scm_unbound_variable_key, "unbound-variable");
e6729603 136
b7742c6b 137static void error_used_before_defined (void)
d0624e39 138{
b7742c6b
AW
139 scm_error (scm_unbound_variable_key, NULL,
140 "Variable used before given a value", SCM_EOL, SCM_BOOL_F);
d0624e39 141}
d0624e39 142
b7742c6b
AW
143int
144scm_badargsp (SCM formals, SCM args)
7e6e6b37 145{
b7742c6b
AW
146 while (!scm_is_null (formals))
147 {
148 if (!scm_is_pair (formals))
149 return 0;
150 if (scm_is_null (args))
151 return 1;
152 formals = CDR (formals);
153 args = CDR (args);
154 }
155 return !scm_is_null (args) ? 1 : 0;
7e6e6b37
DH
156}
157
b7742c6b 158/* the environment:
3149a5b6 159 (VAL ... . MOD)
b7742c6b
AW
160 If MOD is #f, it means the environment was captured before modules were
161 booted.
162 If MOD is the literal value '(), we are evaluating at the top level, and so
163 should track changes to the current module. You have to be careful in this
164 case, because further lexical contours should capture the current module.
165*/
166#define CAPTURE_ENV(env) \
167 ((env == SCM_EOL) ? scm_current_module () : \
168 ((env == SCM_BOOL_F) ? scm_the_root_module () : env))
6f81708a
DH
169
170static SCM
b7742c6b 171eval (SCM x, SCM env)
6f81708a 172{
b7742c6b
AW
173 SCM mx;
174 SCM proc = SCM_UNDEFINED, args = SCM_EOL;
6f81708a 175
b7742c6b
AW
176 loop:
177 SCM_TICK;
178 if (!SCM_MEMOIZED_P (x))
179 abort ();
180
181 mx = SCM_MEMOIZED_ARGS (x);
182 switch (SCM_MEMOIZED_TAG (x))
183 {
184 case SCM_M_BEGIN:
185 for (; !scm_is_null (CDR (mx)); mx = CDR (mx))
186 eval (CAR (mx), env);
187 x = CAR (mx);
188 goto loop;
189
190 case SCM_M_IF:
191 if (scm_is_true (eval (CAR (mx), env)))
192 x = CADR (mx);
6f81708a 193 else
b7742c6b
AW
194 x = CDDR (mx);
195 goto loop;
5fb64383 196
b7742c6b
AW
197 case SCM_M_LET:
198 {
199 SCM inits = CAR (mx);
200 SCM new_env = CAPTURE_ENV (env);
201 for (; scm_is_pair (inits); inits = CDR (inits))
202 new_env = scm_cons (eval (CAR (inits), env), new_env);
203 env = new_env;
204 x = CDR (mx);
205 goto loop;
206 }
207
208 case SCM_M_LAMBDA:
314b8716 209 RETURN_BOOT_CLOSURE (mx, CAPTURE_ENV (env));
5fb64383 210
b7742c6b
AW
211 case SCM_M_QUOTE:
212 return mx;
0f2d19dd 213
b7742c6b
AW
214 case SCM_M_DEFINE:
215 scm_define (CAR (mx), eval (CDR (mx), env));
216 return SCM_UNSPECIFIED;
212e58ed 217
d69531e2
AW
218 case SCM_M_DYNWIND:
219 {
220 SCM in, out, res, old_winds;
221 in = eval (CAR (mx), env);
222 out = eval (CDDR (mx), env);
223 scm_call_0 (in);
224 old_winds = scm_i_dynwinds ();
225 scm_i_set_dynwinds (scm_acons (in, out, old_winds));
226 res = eval (CADR (mx), env);
227 scm_i_set_dynwinds (old_winds);
228 scm_call_0 (out);
229 return res;
230 }
231
b7742c6b
AW
232 case SCM_M_APPLY:
233 /* Evaluate the procedure to be applied. */
234 proc = eval (CAR (mx), env);
235 /* Evaluate the argument holding the list of arguments */
236 args = eval (CADR (mx), env);
237
238 apply_proc:
239 /* Go here to tail-apply a procedure. PROC is the procedure and
240 * ARGS is the list of arguments. */
314b8716 241 if (BOOT_CLOSURE_P (proc))
b7742c6b 242 {
314b8716
AW
243 int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
244 SCM new_env = BOOT_CLOSURE_ENV (proc);
245 if (BOOT_CLOSURE_HAS_REST_ARGS (proc))
b7742c6b
AW
246 {
247 if (SCM_UNLIKELY (scm_ilength (args) < nreq))
248 scm_wrong_num_args (proc);
249 for (; nreq; nreq--, args = CDR (args))
250 new_env = scm_cons (CAR (args), new_env);
251 new_env = scm_cons (args, new_env);
252 }
253 else
254 {
255 if (SCM_UNLIKELY (scm_ilength (args) != nreq))
256 scm_wrong_num_args (proc);
257 for (; scm_is_pair (args); args = CDR (args))
258 new_env = scm_cons (CAR (args), new_env);
259 }
314b8716 260 x = BOOT_CLOSURE_BODY (proc);
b7742c6b
AW
261 env = new_env;
262 goto loop;
263 }
264 else
67e2d80a 265 return scm_vm_apply (scm_the_vm (), proc, args);
212e58ed 266
b7742c6b
AW
267 case SCM_M_CALL:
268 /* Evaluate the procedure to be applied. */
269 proc = eval (CAR (mx), env);
9331f91c
AW
270 /* int nargs = CADR (mx); */
271 mx = CDDR (mx);
212e58ed 272
314b8716 273 if (BOOT_CLOSURE_P (proc))
5fa0939c 274 {
314b8716
AW
275 int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (proc);
276 SCM new_env = BOOT_CLOSURE_ENV (proc);
277 if (BOOT_CLOSURE_HAS_REST_ARGS (proc))
b7742c6b
AW
278 {
279 if (SCM_UNLIKELY (scm_ilength (mx) < nreq))
280 scm_wrong_num_args (proc);
281 for (; nreq; nreq--, mx = CDR (mx))
282 new_env = scm_cons (eval (CAR (mx), env), new_env);
283 {
284 SCM rest = SCM_EOL;
285 for (; scm_is_pair (mx); mx = CDR (mx))
286 rest = scm_cons (eval (CAR (mx), env), rest);
287 new_env = scm_cons (scm_reverse (rest),
288 new_env);
289 }
290 }
291 else
292 {
293 for (; scm_is_pair (mx); mx = CDR (mx), nreq--)
294 new_env = scm_cons (eval (CAR (mx), env), new_env);
295 if (SCM_UNLIKELY (nreq != 0))
296 scm_wrong_num_args (proc);
297 }
314b8716 298 x = BOOT_CLOSURE_BODY (proc);
b7742c6b
AW
299 env = new_env;
300 goto loop;
5fa0939c 301 }
b7742c6b
AW
302 else
303 {
304 SCM rest = SCM_EOL;
9331f91c 305 /* FIXME: use alloca */
b7742c6b
AW
306 for (; scm_is_pair (mx); mx = CDR (mx))
307 rest = scm_cons (eval (CAR (mx), env), rest);
67e2d80a 308 return scm_vm_apply (scm_the_vm (), proc, scm_reverse (rest));
b7742c6b
AW
309 }
310
311 case SCM_M_CONT:
babfc7b2 312 return scm_i_call_with_current_continuation (eval (mx, env));
212e58ed 313
b7742c6b
AW
314 case SCM_M_CALL_WITH_VALUES:
315 {
316 SCM producer;
317 SCM v;
318
319 producer = eval (CAR (mx), env);
320 proc = eval (CDR (mx), env); /* proc is the consumer. */
67e2d80a 321 v = scm_vm_apply (scm_the_vm (), producer, SCM_EOL);
b7742c6b
AW
322 if (SCM_VALUESP (v))
323 args = scm_struct_ref (v, SCM_INUM0);
324 else
325 args = scm_list_1 (v);
326 goto apply_proc;
327 }
26d5b9b4 328
b7742c6b
AW
329 case SCM_M_LEXICAL_REF:
330 {
331 int n;
332 SCM ret;
333 for (n = SCM_I_INUM (mx); n; n--)
334 env = CDR (env);
335 ret = CAR (env);
336 if (SCM_UNLIKELY (SCM_UNBNDP (ret)))
337 /* we don't know what variable, though, because we don't have its
338 name */
339 error_used_before_defined ();
340 return ret;
341 }
1cc91f1b 342
b7742c6b
AW
343 case SCM_M_LEXICAL_SET:
344 {
345 int n;
346 SCM val = eval (CDR (mx), env);
347 for (n = SCM_I_INUM (CAR (mx)); n; n--)
348 env = CDR (env);
349 SCM_SETCAR (env, val);
350 return SCM_UNSPECIFIED;
351 }
910b5125 352
b7742c6b
AW
353 case SCM_M_TOPLEVEL_REF:
354 if (SCM_VARIABLEP (mx))
355 return SCM_VARIABLE_REF (mx);
356 else
57d23e25 357 {
b7742c6b 358 while (scm_is_pair (env))
f3a8d1b7 359 env = CDR (env);
3149a5b6
AW
360 return SCM_VARIABLE_REF
361 (scm_memoize_variable_access_x (x, CAPTURE_ENV (env)));
57d23e25 362 }
57d23e25 363
b7742c6b
AW
364 case SCM_M_TOPLEVEL_SET:
365 {
366 SCM var = CAR (mx);
367 SCM val = eval (CDR (mx), env);
368 if (SCM_VARIABLEP (var))
369 {
370 SCM_VARIABLE_SET (var, val);
371 return SCM_UNSPECIFIED;
372 }
373 else
374 {
375 while (scm_is_pair (env))
f3a8d1b7 376 env = CDR (env);
3149a5b6
AW
377 SCM_VARIABLE_SET
378 (scm_memoize_variable_access_x (x, CAPTURE_ENV (env)),
379 val);
b7742c6b
AW
380 return SCM_UNSPECIFIED;
381 }
382 }
910b5125 383
b7742c6b
AW
384 case SCM_M_MODULE_REF:
385 if (SCM_VARIABLEP (mx))
386 return SCM_VARIABLE_REF (mx);
910b5125 387 else
3149a5b6
AW
388 return SCM_VARIABLE_REF
389 (scm_memoize_variable_access_x (x, SCM_BOOL_F));
910b5125 390
b7742c6b
AW
391 case SCM_M_MODULE_SET:
392 if (SCM_VARIABLEP (CDR (mx)))
910b5125 393 {
b7742c6b
AW
394 SCM_VARIABLE_SET (CDR (mx), eval (CAR (mx), env));
395 return SCM_UNSPECIFIED;
396 }
397 else
398 {
3149a5b6
AW
399 SCM_VARIABLE_SET
400 (scm_memoize_variable_access_x (x, SCM_BOOL_F),
401 eval (CAR (mx), env));
b7742c6b 402 return SCM_UNSPECIFIED;
910b5125 403 }
910b5125 404
b7742c6b
AW
405 default:
406 abort ();
407 }
910b5125
DH
408}
409
b7742c6b
AW
410scm_t_option scm_eval_opts[] = {
411 { SCM_OPTION_INTEGER, "stack", 22000, "Size of thread stacks (in machine words)." },
412 { 0 }
413};
e6729603 414
b7742c6b
AW
415scm_t_option scm_debug_opts[] = {
416 { SCM_OPTION_BOOLEAN, "cheap", 1,
417 "*This option is now obsolete. Setting it has no effect." },
418 { SCM_OPTION_BOOLEAN, "breakpoints", 0, "*Check for breakpoints." },
419 { SCM_OPTION_BOOLEAN, "trace", 0, "*Trace mode." },
420 { SCM_OPTION_BOOLEAN, "procnames", 1,
421 "Record procedure names at definition." },
422 { SCM_OPTION_BOOLEAN, "backwards", 0,
423 "Display backtrace in anti-chronological order." },
424 { SCM_OPTION_INTEGER, "width", 79, "Maximal width of backtrace." },
425 { SCM_OPTION_INTEGER, "indent", 10, "Maximal indentation in backtrace." },
426 { SCM_OPTION_INTEGER, "frames", 3,
427 "Maximum number of tail-recursive frames in backtrace." },
428 { SCM_OPTION_INTEGER, "maxdepth", 1000,
429 "Maximal number of stored backtrace frames." },
430 { SCM_OPTION_INTEGER, "depth", 20, "Maximal length of printed backtrace." },
431 { SCM_OPTION_BOOLEAN, "backtrace", 0, "Show backtrace on error." },
432 { SCM_OPTION_BOOLEAN, "debug", 0, "Use the debugging evaluator." },
433 /* This default stack limit will be overridden by debug.c:init_stack_limit(),
434 if we have getrlimit() and the stack limit is not INFINITY. But it is still
435 important, as some systems have both the soft and the hard limits set to
436 INFINITY; in that case we fall back to this value.
e6729603 437
b7742c6b
AW
438 The situation is aggravated by certain compilers, which can consume
439 "beaucoup de stack", as they say in France.
0f2d19dd 440
b7742c6b
AW
441 See http://thread.gmane.org/gmane.lisp.guile.devel/8599/focus=8662 for
442 more discussion. This setting is 640 KB on 32-bit arches (should be enough
443 for anyone!) or a whoppin' 1280 KB on 64-bit arches.
444 */
445 { SCM_OPTION_INTEGER, "stack", 160000, "Stack size limit (measured in words; 0 = no check)." },
446 { SCM_OPTION_SCM, "show-file-name", (unsigned long)SCM_BOOL_T,
447 "Show file names and line numbers "
448 "in backtraces when not `#f'. A value of `base' "
449 "displays only base names, while `#t' displays full names."},
450 { SCM_OPTION_BOOLEAN, "warn-deprecated", 0,
451 "Warn when deprecated features are used." },
452 { 0 },
453};
212e58ed 454
1cc91f1b 455
b7742c6b
AW
456/*
457 * this ordering is awkward and illogical, but we maintain it for
458 * compatibility. --hwn
459 */
460scm_t_option scm_evaluator_trap_table[] = {
461 { SCM_OPTION_BOOLEAN, "traps", 0, "Enable evaluator traps." },
462 { SCM_OPTION_BOOLEAN, "enter-frame", 0, "Trap when eval enters new frame." },
463 { SCM_OPTION_BOOLEAN, "apply-frame", 0, "Trap when entering apply." },
464 { SCM_OPTION_BOOLEAN, "exit-frame", 0, "Trap when exiting eval or apply." },
465 { SCM_OPTION_SCM, "enter-frame-handler", (unsigned long)SCM_BOOL_F, "Handler for enter-frame traps." },
466 { SCM_OPTION_SCM, "apply-frame-handler", (unsigned long)SCM_BOOL_F, "Handler for apply-frame traps." },
467 { SCM_OPTION_SCM, "exit-frame-handler", (unsigned long)SCM_BOOL_F, "Handler for exit-frame traps." },
468 { SCM_OPTION_BOOLEAN, "memoize-symbol", 0, "Trap when memoizing a symbol." },
469 { SCM_OPTION_SCM, "memoize-symbol-handler", (unsigned long)SCM_BOOL_F, "The handler for memoization." },
470 { 0 }
471};
8ea46249 472
0f2d19dd 473
b7742c6b
AW
474SCM_DEFINE (scm_eval_options_interface, "eval-options-interface", 0, 1, 0,
475 (SCM setting),
476 "Option interface for the evaluation options. Instead of using\n"
477 "this procedure directly, use the procedures @code{eval-enable},\n"
478 "@code{eval-disable}, @code{eval-set!} and @code{eval-options}.")
479#define FUNC_NAME s_scm_eval_options_interface
212e58ed 480{
b7742c6b
AW
481 SCM ans;
482
483 scm_dynwind_begin (0);
484 scm_dynwind_critical_section (SCM_BOOL_F);
485 ans = scm_options (setting,
486 scm_eval_opts,
487 FUNC_NAME);
488 scm_dynwind_end ();
212e58ed 489
b7742c6b
AW
490 return ans;
491}
492#undef FUNC_NAME
0f2d19dd 493
1cc91f1b 494
b7742c6b
AW
495SCM_DEFINE (scm_evaluator_traps, "evaluator-traps-interface", 0, 1, 0,
496 (SCM setting),
497 "Option interface for the evaluator trap options.")
498#define FUNC_NAME s_scm_evaluator_traps
0f2d19dd 499{
b7742c6b 500 SCM ans;
2a6f7afe 501
b7742c6b
AW
502
503 scm_options_try (setting,
504 scm_evaluator_trap_table,
505 FUNC_NAME, 1);
506 SCM_CRITICAL_SECTION_START;
507 ans = scm_options (setting,
508 scm_evaluator_trap_table,
509 FUNC_NAME);
2a6f7afe 510
b7742c6b
AW
511 /* njrev: same again. */
512 SCM_CRITICAL_SECTION_END;
513 return ans;
514}
515#undef FUNC_NAME
2a6f7afe 516
2a6f7afe 517
2a6f7afe 518
b7742c6b 519\f
2a6f7afe 520
b7742c6b
AW
521/* Simple procedure calls
522 */
2a6f7afe 523
b7742c6b
AW
524SCM
525scm_call_0 (SCM proc)
526{
bf5a05f2 527 return scm_c_vm_run (scm_the_vm (), proc, NULL, 0);
0f2d19dd
JB
528}
529
b7742c6b
AW
530SCM
531scm_call_1 (SCM proc, SCM arg1)
212e58ed 532{
bf5a05f2 533 return scm_c_vm_run (scm_the_vm (), proc, &arg1, 1);
b7742c6b 534}
212e58ed 535
b7742c6b
AW
536SCM
537scm_call_2 (SCM proc, SCM arg1, SCM arg2)
538{
bf5a05f2
AW
539 SCM args[] = { arg1, arg2 };
540 return scm_c_vm_run (scm_the_vm (), proc, args, 2);
212e58ed
DH
541}
542
b7742c6b
AW
543SCM
544scm_call_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3)
0f2d19dd 545{
bf5a05f2
AW
546 SCM args[] = { arg1, arg2, arg3 };
547 return scm_c_vm_run (scm_the_vm (), proc, args, 3);
0f2d19dd
JB
548}
549
b7742c6b
AW
550SCM
551scm_call_4 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4)
212e58ed 552{
bf5a05f2
AW
553 SCM args[] = { arg1, arg2, arg3, arg4 };
554 return scm_c_vm_run (scm_the_vm (), proc, args, 4);
212e58ed
DH
555}
556
86fd6dff
AW
557SCM
558scm_call_n (SCM proc, SCM *argv, size_t nargs)
559{
560 return scm_c_vm_run (scm_the_vm (), proc, argv, nargs);
561}
562
b7742c6b 563/* Simple procedure applies
9fbee57e 564 */
cc56ba80 565
b7742c6b
AW
566SCM
567scm_apply_0 (SCM proc, SCM args)
568{
569 return scm_apply (proc, args, SCM_EOL);
0f572ba7
DH
570}
571
b7742c6b
AW
572SCM
573scm_apply_1 (SCM proc, SCM arg1, SCM args)
0f572ba7 574{
b7742c6b 575 return scm_apply (proc, scm_cons (arg1, args), SCM_EOL);
8ae95199
DH
576}
577
b7742c6b
AW
578SCM
579scm_apply_2 (SCM proc, SCM arg1, SCM arg2, SCM args)
0f2d19dd 580{
b7742c6b 581 return scm_apply (proc, scm_cons2 (arg1, arg2, args), SCM_EOL);
0f2d19dd
JB
582}
583
b7742c6b
AW
584SCM
585scm_apply_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM args)
212e58ed 586{
b7742c6b
AW
587 return scm_apply (proc, scm_cons (arg1, scm_cons2 (arg2, arg3, args)),
588 SCM_EOL);
212e58ed
DH
589}
590
b7742c6b 591/* This code processes the arguments to apply:
8ea46249 592
b7742c6b 593 (apply PROC ARG1 ... ARGS)
302c12b4 594
b7742c6b
AW
595 Given a list (ARG1 ... ARGS), this function conses the ARG1
596 ... arguments onto the front of ARGS, and returns the resulting
597 list. Note that ARGS is a list; thus, the argument to this
598 function is a list whose last element is a list.
302c12b4 599
b7742c6b
AW
600 Apply calls this function, and applies PROC to the elements of the
601 result. apply:nconc2last takes care of building the list of
602 arguments, given (ARG1 ... ARGS).
a954ce1d 603
b7742c6b
AW
604 Rather than do new consing, apply:nconc2last destroys its argument.
605 On that topic, this code came into my care with the following
606 beautifully cryptic comment on that topic: "This will only screw
607 you if you do (scm_apply scm_apply '( ... ))" If you know what
608 they're referring to, send me a patch to this comment. */
0f2d19dd 609
b7742c6b
AW
610SCM_DEFINE (scm_nconc2last, "apply:nconc2last", 1, 0, 0,
611 (SCM lst),
612 "Given a list (@var{arg1} @dots{} @var{args}), this function\n"
613 "conses the @var{arg1} @dots{} arguments onto the front of\n"
614 "@var{args}, and returns the resulting list. Note that\n"
615 "@var{args} is a list; thus, the argument to this function is\n"
616 "a list whose last element is a list.\n"
617 "Note: Rather than do new consing, @code{apply:nconc2last}\n"
618 "destroys its argument, so use with care.")
619#define FUNC_NAME s_scm_nconc2last
212e58ed 620{
b7742c6b
AW
621 SCM *lloc;
622 SCM_VALIDATE_NONEMPTYLIST (1, lst);
623 lloc = &lst;
624 while (!scm_is_null (SCM_CDR (*lloc))) /* Perhaps should be
625 SCM_NULL_OR_NIL_P, but not
626 needed in 99.99% of cases,
627 and it could seriously hurt
628 performance. - Neil */
629 lloc = SCM_CDRLOC (*lloc);
630 SCM_ASSERT (scm_ilength (SCM_CAR (*lloc)) >= 0, lst, SCM_ARG1, FUNC_NAME);
631 *lloc = SCM_CAR (*lloc);
632 return lst;
212e58ed 633}
b7742c6b 634#undef FUNC_NAME
212e58ed 635
b8229a3b
MS
636
637
b7742c6b 638/* Typechecking for multi-argument MAP and FOR-EACH.
0f2d19dd 639
b7742c6b
AW
640 Verify that each element of the vector ARGV, except for the first,
641 is a proper list whose length is LEN. Attribute errors to WHO,
642 and claim that the i'th element of ARGV is WHO's i+2'th argument. */
643static inline void
644check_map_args (SCM argv,
645 long len,
646 SCM gf,
647 SCM proc,
648 SCM args,
649 const char *who)
212e58ed 650{
b7742c6b 651 long i;
0f2d19dd 652
b7742c6b 653 for (i = SCM_SIMPLE_VECTOR_LENGTH (argv) - 1; i >= 1; i--)
9fbee57e 654 {
b7742c6b
AW
655 SCM elt = SCM_SIMPLE_VECTOR_REF (argv, i);
656 long elt_len = scm_ilength (elt);
5cb22e96 657
b7742c6b
AW
658 if (elt_len < 0)
659 {
660 if (gf)
661 scm_apply_generic (gf, scm_cons (proc, args));
662 else
663 scm_wrong_type_arg (who, i + 2, elt);
664 }
1cc91f1b 665
b7742c6b
AW
666 if (elt_len != len)
667 scm_out_of_range_pos (who, elt, scm_from_long (i + 2));
0f2d19dd 668 }
0f2d19dd 669}
6dbd0af5 670
212e58ed 671
b7742c6b 672SCM_GPROC (s_map, "map", 2, 0, 1, scm_map, g_map);
212e58ed 673
b7742c6b
AW
674/* Note: Currently, scm_map applies PROC to the argument list(s)
675 sequentially, starting with the first element(s). This is used in
676 evalext.c where the Scheme procedure `map-in-order', which guarantees
677 sequential behaviour, is implemented using scm_map. If the
678 behaviour changes, we need to update `map-in-order'.
679*/
0f2d19dd 680
b7742c6b
AW
681SCM
682scm_map (SCM proc, SCM arg1, SCM args)
683#define FUNC_NAME s_map
0f2d19dd 684{
b7742c6b
AW
685 long i, len;
686 SCM res = SCM_EOL;
687 SCM *pres = &res;
0f2d19dd 688
b7742c6b
AW
689 len = scm_ilength (arg1);
690 SCM_GASSERTn (len >= 0,
691 g_map, scm_cons2 (proc, arg1, args), SCM_ARG2, s_map);
692 SCM_VALIDATE_REST_ARGUMENT (args);
693 if (scm_is_null (args))
0f2d19dd 694 {
b7742c6b
AW
695 SCM_GASSERT2 (scm_is_true (scm_procedure_p (proc)), g_map, proc, arg1, SCM_ARG1, s_map);
696 while (SCM_NIMP (arg1))
697 {
698 *pres = scm_list_1 (scm_call_1 (proc, SCM_CAR (arg1)));
699 pres = SCM_CDRLOC (*pres);
700 arg1 = SCM_CDR (arg1);
701 }
702 return res;
0f2d19dd 703 }
b7742c6b
AW
704 if (scm_is_null (SCM_CDR (args)))
705 {
706 SCM arg2 = SCM_CAR (args);
707 int len2 = scm_ilength (arg2);
708 SCM_GASSERTn (scm_is_true (scm_procedure_p (proc)), g_map,
709 scm_cons2 (proc, arg1, args), SCM_ARG1, s_map);
710 SCM_GASSERTn (len2 >= 0,
711 g_map, scm_cons2 (proc, arg1, args), SCM_ARG3, s_map);
712 if (len2 != len)
713 SCM_OUT_OF_RANGE (3, arg2);
714 while (SCM_NIMP (arg1))
715 {
716 *pres = scm_list_1 (scm_call_2 (proc, SCM_CAR (arg1), SCM_CAR (arg2)));
717 pres = SCM_CDRLOC (*pres);
718 arg1 = SCM_CDR (arg1);
719 arg2 = SCM_CDR (arg2);
720 }
721 return res;
722 }
723 arg1 = scm_cons (arg1, args);
724 args = scm_vector (arg1);
725 check_map_args (args, len, g_map, proc, arg1, s_map);
726 while (1)
d6754c23 727 {
b7742c6b
AW
728 arg1 = SCM_EOL;
729 for (i = SCM_SIMPLE_VECTOR_LENGTH (args) - 1; i >= 0; i--)
730 {
731 SCM elt = SCM_SIMPLE_VECTOR_REF (args, i);
732 if (SCM_IMP (elt))
733 return res;
734 arg1 = scm_cons (SCM_CAR (elt), arg1);
735 SCM_SIMPLE_VECTOR_SET (args, i, SCM_CDR (elt));
736 }
737 *pres = scm_list_1 (scm_apply (proc, arg1, SCM_EOL));
738 pres = SCM_CDRLOC (*pres);
d6754c23 739 }
0f2d19dd 740}
b7742c6b 741#undef FUNC_NAME
0f2d19dd 742
302c12b4 743
b7742c6b 744SCM_GPROC (s_for_each, "for-each", 2, 0, 1, scm_for_each, g_for_each);
d6754c23 745
b7742c6b
AW
746SCM
747scm_for_each (SCM proc, SCM arg1, SCM args)
748#define FUNC_NAME s_for_each
0f2d19dd 749{
b7742c6b
AW
750 long i, len;
751 len = scm_ilength (arg1);
752 SCM_GASSERTn (len >= 0, g_for_each, scm_cons2 (proc, arg1, args),
753 SCM_ARG2, s_for_each);
754 SCM_VALIDATE_REST_ARGUMENT (args);
755 if (scm_is_null (args))
26d5b9b4 756 {
b7742c6b
AW
757 SCM_GASSERT2 (scm_is_true (scm_procedure_p (proc)), g_for_each,
758 proc, arg1, SCM_ARG1, s_for_each);
759 while (SCM_NIMP (arg1))
760 {
761 scm_call_1 (proc, SCM_CAR (arg1));
762 arg1 = SCM_CDR (arg1);
763 }
764 return SCM_UNSPECIFIED;
26d5b9b4 765 }
b7742c6b 766 if (scm_is_null (SCM_CDR (args)))
26d5b9b4 767 {
b7742c6b
AW
768 SCM arg2 = SCM_CAR (args);
769 int len2 = scm_ilength (arg2);
770 SCM_GASSERTn (scm_is_true (scm_procedure_p (proc)), g_for_each,
771 scm_cons2 (proc, arg1, args), SCM_ARG1, s_for_each);
772 SCM_GASSERTn (len2 >= 0, g_for_each,
773 scm_cons2 (proc, arg1, args), SCM_ARG3, s_for_each);
774 if (len2 != len)
775 SCM_OUT_OF_RANGE (3, arg2);
776 while (SCM_NIMP (arg1))
777 {
778 scm_call_2 (proc, SCM_CAR (arg1), SCM_CAR (arg2));
779 arg1 = SCM_CDR (arg1);
780 arg2 = SCM_CDR (arg2);
781 }
782 return SCM_UNSPECIFIED;
26d5b9b4 783 }
b7742c6b
AW
784 arg1 = scm_cons (arg1, args);
785 args = scm_vector (arg1);
786 check_map_args (args, len, g_for_each, proc, arg1, s_for_each);
787 while (1)
302c12b4 788 {
b7742c6b
AW
789 arg1 = SCM_EOL;
790 for (i = SCM_SIMPLE_VECTOR_LENGTH (args) - 1; i >= 0; i--)
71560395 791 {
b7742c6b
AW
792 SCM elt = SCM_SIMPLE_VECTOR_REF (args, i);
793 if (SCM_IMP (elt))
794 return SCM_UNSPECIFIED;
795 arg1 = scm_cons (SCM_CAR (elt), arg1);
796 SCM_SIMPLE_VECTOR_SET (args, i, SCM_CDR (elt));
797 }
798 scm_apply (proc, arg1, SCM_EOL);
799 }
800}
801#undef FUNC_NAME
71560395 802
71560395 803
5f161164
AW
804static SCM
805scm_c_primitive_eval (SCM exp)
b7742c6b
AW
806{
807 SCM transformer = scm_current_module_transformer ();
808 if (scm_is_true (transformer))
809 exp = scm_call_1 (transformer, exp);
810 exp = scm_memoize_expression (exp);
811 return eval (exp, SCM_EOL);
812}
5f161164
AW
813
814static SCM var_primitive_eval;
815SCM
816scm_primitive_eval (SCM exp)
817{
818 return scm_c_vm_run (scm_the_vm (), scm_variable_ref (var_primitive_eval),
819 &exp, 1);
820}
71560395 821
b7742c6b
AW
822
823/* Eval does not take the second arg optionally. This is intentional
824 * in order to be R5RS compatible, and to prepare for the new module
825 * system, where we would like to make the choice of evaluation
826 * environment explicit. */
827
828SCM_DEFINE (scm_eval, "eval", 2, 0, 0,
829 (SCM exp, SCM module_or_state),
830 "Evaluate @var{exp}, a list representing a Scheme expression,\n"
831 "in the top-level environment specified by\n"
832 "@var{module_or_state}.\n"
833 "While @var{exp} is evaluated (using @code{primitive-eval}),\n"
834 "@var{module_or_state} is made the current module when\n"
835 "it is a module, or the current dynamic state when it is\n"
836 "a dynamic state."
837 "Example: (eval '(+ 1 2) (interaction-environment))")
838#define FUNC_NAME s_scm_eval
839{
840 SCM res;
841
842 scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
843 if (scm_is_dynamic_state (module_or_state))
844 scm_dynwind_current_dynamic_state (module_or_state);
845 else if (scm_module_system_booted_p)
846 {
847 SCM_VALIDATE_MODULE (2, module_or_state);
848 scm_dynwind_current_module (module_or_state);
71560395 849 }
b7742c6b 850 /* otherwise if the module system isn't booted, ignore the module arg */
71560395 851
b7742c6b
AW
852 res = scm_primitive_eval (exp);
853
854 scm_dynwind_end ();
855 return res;
856}
857#undef FUNC_NAME
71560395
AW
858
859
b7742c6b 860static SCM f_apply;
71560395
AW
861
862/* Apply a function to a list of arguments.
863
864 This function is exported to the Scheme level as taking two
865 required arguments and a tail argument, as if it were:
866 (lambda (proc arg1 . args) ...)
867 Thus, if you just have a list of arguments to pass to a procedure,
868 pass the list as ARG1, and '() for ARGS. If you have some fixed
869 args, pass the first as ARG1, then cons any remaining fixed args
870 onto the front of your argument list, and pass that as ARGS. */
871
872SCM
873scm_apply (SCM proc, SCM arg1, SCM args)
874{
b7742c6b 875 /* Fix things up so that args contains all args. */
71560395 876 if (scm_is_null (args))
b7742c6b 877 args = arg1;
71560395 878 else
b7742c6b 879 args = scm_cons_star (arg1, args);
71560395 880
67e2d80a 881 return scm_vm_apply (scm_the_vm (), proc, args);
b7742c6b 882}
434f2f7a
DH
883
884
314b8716
AW
885static SCM
886boot_closure_apply (SCM closure, SCM args)
887{
888 int nreq = BOOT_CLOSURE_NUM_REQUIRED_ARGS (closure);
889 SCM new_env = BOOT_CLOSURE_ENV (closure);
890 if (BOOT_CLOSURE_HAS_REST_ARGS (closure))
891 {
892 if (SCM_UNLIKELY (scm_ilength (args) < nreq))
893 scm_wrong_num_args (closure);
894 for (; nreq; nreq--, args = CDR (args))
895 new_env = scm_cons (CAR (args), new_env);
896 new_env = scm_cons (args, new_env);
897 }
898 else
899 {
900 if (SCM_UNLIKELY (scm_ilength (args) != nreq))
901 scm_wrong_num_args (closure);
902 for (; scm_is_pair (args); args = CDR (args))
903 new_env = scm_cons (CAR (args), new_env);
904 }
905 return eval (BOOT_CLOSURE_BODY (closure), new_env);
906}
907
908static int
909boot_closure_print (SCM closure, SCM port, scm_print_state *pstate)
910{
911 SCM args;
912 scm_puts ("#<boot-closure ", port);
913 scm_uintprint ((unsigned long)SCM2PTR (closure), 16, port);
914 scm_putc (' ', port);
915 args = scm_make_list (scm_from_int (BOOT_CLOSURE_NUM_REQUIRED_ARGS (closure)),
916 scm_from_locale_symbol ("_"));
917 if (BOOT_CLOSURE_HAS_REST_ARGS (closure))
918 args = scm_cons_star (scm_from_locale_symbol ("_"), args);
919 scm_display (args, port);
920 scm_putc ('>', port);
921 return 1;
922}
923
0f2d19dd
JB
924void
925scm_init_eval ()
0f2d19dd 926{
5f161164
AW
927 SCM primitive_eval;
928
33b97402 929 scm_init_opts (scm_evaluator_traps,
62560650 930 scm_evaluator_trap_table);
33b97402 931 scm_init_opts (scm_eval_options_interface,
62560650 932 scm_eval_opts);
33b97402 933
df9ca8d8 934 f_apply = scm_c_define_gsubr ("apply", 2, 0, 1, scm_apply);
86d31dfe 935
314b8716
AW
936 scm_tc16_boot_closure = scm_make_smob_type ("boot-closure", 0);
937 scm_set_smob_apply (scm_tc16_boot_closure, boot_closure_apply, 0, 0, 1);
938 scm_set_smob_print (scm_tc16_boot_closure, boot_closure_print);
939
5f161164
AW
940 primitive_eval = scm_c_make_gsubr ("primitive-eval", 1, 0, 0,
941 scm_c_primitive_eval);
942 var_primitive_eval = scm_define (SCM_SUBR_NAME (primitive_eval),
943 primitive_eval);
944
a0599745 945#include "libguile/eval.x"
0f2d19dd 946}
0f2d19dd 947
89e00824
ML
948/*
949 Local Variables:
950 c-file-style: "gnu"
951 End:
952*/
62560650 953