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