tweaks to default program printer
[bpt/guile.git] / libguile / vm.c
CommitLineData
a6029b97 1/* Copyright (C) 2001, 2009, 2010 Free Software Foundation, Inc.
a98cef7e 2 *
560b9c25 3 * This library is free software; you can redistribute it and/or
53befeb7
NJ
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
a98cef7e 7 *
53befeb7
NJ
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
560b9c25
AW
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
a98cef7e 12 *
560b9c25
AW
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
53befeb7
NJ
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
560b9c25 17 */
a98cef7e 18
13c47753
AW
19#if HAVE_CONFIG_H
20# include <config.h>
21#endif
22
da8b4747 23#include <stdlib.h>
6d14383e 24#include <alloca.h>
17e90c5e 25#include <string.h>
e3eb628d 26
1c44468d 27#include "libguile/bdw-gc.h"
e3eb628d
LC
28#include <gc/gc_mark.h>
29
560b9c25 30#include "_scm.h"
adaf86ec 31#include "control.h"
ac99cb0c 32#include "frames.h"
17e90c5e 33#include "instructions.h"
8f5cfc81 34#include "objcodes.h"
ac99cb0c 35#include "programs.h"
fb10a008 36#include "lang.h" /* NULL_OR_NIL_P */
a98cef7e
KN
37#include "vm.h"
38
a98cef7e
KN
39/* I sometimes use this for debugging. */
40#define vm_puts(OBJ) \
41{ \
22bcbe8c
AW
42 scm_display (OBJ, scm_current_error_port ()); \
43 scm_newline (scm_current_error_port ()); \
a98cef7e
KN
44}
45
11ea1aba
AW
46/* The VM has a number of internal assertions that shouldn't normally be
47 necessary, but might be if you think you found a bug in the VM. */
48#define VM_ENABLE_ASSERTIONS
49
50/* We can add a mode that ensures that all stack items above the stack pointer
51 are NULL. This is useful for checking the internal consistency of the VM's
52 assumptions and its operators, but isn't necessary for normal operation. It
616167fc 53 will ensure that assertions are enabled. Slows down the VM by about 30%. */
747a1635 54/* NB! If you enable this, search for NULLING in throw.c */
616167fc 55/* #define VM_ENABLE_STACK_NULLING */
11ea1aba 56
53e28ed9
AW
57/* #define VM_ENABLE_PARANOID_ASSERTIONS */
58
11ea1aba
AW
59#if defined (VM_ENABLE_STACK_NULLING) && !defined (VM_ENABLE_ASSERTIONS)
60#define VM_ENABLE_ASSERTIONS
61#endif
62
e3eb628d
LC
63/* When defined, arrange so that the GC doesn't scan the VM stack beyond its
64 current SP. This should help avoid excess data retention. See
65 http://thread.gmane.org/gmane.comp.programming.garbage-collection.boehmgc/3001
66 for a discussion. */
67#define VM_ENABLE_PRECISE_STACK_GC_SCAN
68
69
a98cef7e 70\f
a98cef7e
KN
71/*
72 * VM Continuation
73 */
74
6f3b0cc2
AW
75void
76scm_i_vm_cont_print (SCM x, SCM port, scm_print_state *pstate)
77{
78 scm_puts ("#<vm-continuation ", port);
79 scm_uintprint (SCM_UNPACK (x), 16, port);
80 scm_puts (">", port);
81}
17e90c5e 82
d8873dfe
AW
83/* In theory, a number of vm instances can be active in the call trace, and we
84 only want to reify the continuations of those in the current continuation
85 root. I don't see a nice way to do this -- ideally it would involve dynwinds,
86 and previous values of the *the-vm* fluid within the current continuation
87 root. But we don't have access to continuation roots in the dynwind stack.
88 So, just punt for now, we just capture the continuation for the current VM.
89
90 While I'm on the topic, ideally we could avoid copying the C stack if the
91 continuation root is inside VM code, and call/cc was invoked within that same
92 call to vm_run; but that's currently not implemented.
93 */
a98cef7e 94static SCM
d8873dfe
AW
95vm_capture_continuation (SCM *stack_base,
96 SCM *fp, SCM *sp, scm_t_uint8 *ra, scm_t_uint8 *mvra)
a98cef7e 97{
d8873dfe
AW
98 struct scm_vm_cont *p;
99
100 p = scm_gc_malloc (sizeof (*p), "capture_vm_cont");
101 p->stack_size = sp - stack_base + 1;
d8eeb67c
LC
102 p->stack_base = scm_gc_malloc (p->stack_size * sizeof (SCM),
103 "capture_vm_cont");
d8873dfe
AW
104#if defined(VM_ENABLE_STACK_NULLING) && 0
105 /* Tail continuations leave their frame on the stack for subsequent
106 application, but don't capture the frame -- so there are some elements on
107 the stack then, and this check doesn't work, so disable it for now. */
108 if (sp >= vp->stack_base)
66db076a
AW
109 if (!vp->sp[0] || vp->sp[1])
110 abort ();
11ea1aba
AW
111 memset (p->stack_base, 0, p->stack_size * sizeof (SCM));
112#endif
d8873dfe
AW
113 p->ra = ra;
114 p->mvra = mvra;
115 p->sp = sp;
116 p->fp = fp;
117 memcpy (p->stack_base, stack_base, (sp + 1 - stack_base) * sizeof (SCM));
118 p->reloc = p->stack_base - stack_base;
6f3b0cc2 119 return scm_cell (scm_tc7_vm_cont, (scm_t_bits)p);
a98cef7e
KN
120}
121
122static void
d8873dfe 123vm_return_to_continuation (SCM vm, SCM cont, size_t n, SCM *argv)
a98cef7e 124{
d8873dfe
AW
125 struct scm_vm *vp;
126 struct scm_vm_cont *cp;
127 SCM *argv_copy;
128
129 argv_copy = alloca (n * sizeof(SCM));
130 memcpy (argv_copy, argv, n * sizeof(SCM));
131
132 vp = SCM_VM_DATA (vm);
133 cp = SCM_VM_CONT_DATA (cont);
134
135 if (n == 0 && !cp->mvra)
136 scm_misc_error (NULL, "Too few values returned to continuation",
137 SCM_EOL);
138
139 if (vp->stack_size < cp->stack_size + n + 1)
a98cef7e 140 {
17e90c5e 141 /* puts ("FIXME: Need to expand"); */
a98cef7e
KN
142 abort ();
143 }
11ea1aba
AW
144#ifdef VM_ENABLE_STACK_NULLING
145 {
d8873dfe 146 scm_t_ptrdiff nzero = (vp->sp - cp->sp);
11ea1aba 147 if (nzero > 0)
d8873dfe 148 memset (vp->stack_base + cp->stack_size, 0, nzero * sizeof (SCM));
66db076a
AW
149 /* actually nzero should always be negative, because vm_reset_stack will
150 unwind the stack to some point *below* this continuation */
11ea1aba
AW
151 }
152#endif
d8873dfe
AW
153 vp->sp = cp->sp;
154 vp->fp = cp->fp;
155 memcpy (vp->stack_base, cp->stack_base, cp->stack_size * sizeof (SCM));
bfffd258 156
d8873dfe
AW
157 if (n == 1 || !cp->mvra)
158 {
159 vp->ip = cp->ra;
160 vp->sp++;
161 *vp->sp = argv_copy[0];
162 }
163 else
164 {
165 size_t i;
166 for (i = 0; i < n; i++)
167 {
168 vp->sp++;
169 *vp->sp = argv_copy[i];
170 }
171 vp->sp++;
172 *vp->sp = scm_from_size_t (n);
173 vp->ip = cp->mvra;
174 }
175}
bfffd258 176
bfffd258 177SCM
269479e3 178scm_i_vm_capture_continuation (SCM vm)
bfffd258 179{
d8873dfe
AW
180 struct scm_vm *vp = SCM_VM_DATA (vm);
181 return vm_capture_continuation (vp->stack_base, vp->fp, vp->sp, vp->ip, NULL);
a98cef7e
KN
182}
183
b1b942b7 184static void
7656f194 185vm_dispatch_hook (SCM vm, int hook_num)
b1b942b7 186{
7656f194
AW
187 struct scm_vm *vp;
188 SCM hook;
189 SCM frame;
b1b942b7 190
7656f194
AW
191 vp = SCM_VM_DATA (vm);
192 hook = vp->hooks[hook_num];
b1b942b7 193
7656f194
AW
194 if (SCM_LIKELY (scm_is_false (hook))
195 || scm_is_null (SCM_HOOK_PROCEDURES (hook)))
196 return;
197
198 vp->trace_level--;
199 frame = scm_c_make_frame (vm, vp->fp, vp->sp, vp->ip, 0);
200 scm_c_run_hookn (hook, &frame, 1);
201 vp->trace_level++;
b1b942b7
AW
202}
203
eaefabee 204static void vm_abort (SCM vm, size_t n) SCM_NORETURN;
4f66bcde 205static void
eaefabee 206vm_abort (SCM vm, size_t n)
4f66bcde 207{
eaefabee 208 size_t i;
2d026f04
AW
209 ssize_t tail_len;
210 SCM tag, tail, *argv;
eaefabee 211
2d026f04
AW
212 /* FIXME: VM_ENABLE_STACK_NULLING */
213 tail = *(SCM_VM_DATA (vm)->sp--);
214 /* NULLSTACK (1) */
215 tail_len = scm_ilength (tail);
216 if (tail_len < 0)
217 abort ();
eaefabee 218 tag = SCM_VM_DATA (vm)->sp[-n];
2d026f04 219 argv = alloca ((n + tail_len) * sizeof (SCM));
eaefabee
AW
220 for (i = 0; i < n; i++)
221 argv[i] = SCM_VM_DATA (vm)->sp[-(n-1-i)];
2d026f04
AW
222 for (; i < n + tail_len; i++, tail = scm_cdr (tail))
223 argv[i] = scm_car (tail);
224 /* NULLSTACK (n + 1) */
eaefabee
AW
225 SCM_VM_DATA (vm)->sp -= n + 1;
226
2d026f04 227 scm_c_abort (vm, tag, n + tail_len, argv);
4f66bcde
AW
228}
229
230\f
17e90c5e
KN
231/*
232 * VM Internal functions
233 */
234
f6a8e791
AW
235SCM_SYMBOL (sym_vm_run, "vm-run");
236SCM_SYMBOL (sym_vm_error, "vm-error");
237SCM_SYMBOL (sym_keyword_argument_error, "keyword-argument-error");
238SCM_SYMBOL (sym_debug, "debug");
17e90c5e 239
6f3b0cc2
AW
240void
241scm_i_vm_print (SCM x, SCM port, scm_print_state *pstate)
242{
243 scm_puts ("#<vm ", port);
244 scm_uintprint (SCM_UNPACK (x), 16, port);
245 scm_puts (">", port);
246}
247
2fda0242 248static SCM
d2d7acd5 249really_make_boot_program (long nargs)
2fda0242 250{
5bd047ce 251 SCM u8vec;
97fcf583
AW
252 scm_t_uint8 text[] = { scm_op_mv_call, 0, 0, 0, 1,
253 scm_op_make_int8_1, scm_op_halt };
28b119ee 254 struct scm_objcode *bp;
3b9e095b 255 SCM ret;
5bd047ce 256
53e28ed9 257 if (SCM_UNLIKELY (nargs > 255 || nargs < 0))
2fda0242 258 abort ();
28b119ee
AW
259 text[1] = (scm_t_uint8)nargs;
260
d7e7a02a 261 bp = scm_malloc (sizeof (struct scm_objcode) + sizeof (text));
3dbbe28d 262 memcpy (SCM_C_OBJCODE_BASE (bp), text, sizeof (text));
28b119ee
AW
263 bp->len = sizeof(text);
264 bp->metalen = 0;
28b119ee 265
7055591c
AW
266 u8vec = scm_c_take_bytevector ((scm_t_int8*)bp,
267 sizeof (struct scm_objcode) + sizeof (text));
5bd047ce 268 ret = scm_make_program (scm_bytecode_to_objcode (u8vec),
20d47c39 269 SCM_BOOL_F, SCM_BOOL_F);
ba20f78a 270 SCM_SET_CELL_WORD_0 (ret, SCM_CELL_WORD_0 (ret) | SCM_F_PROGRAM_IS_BOOT);
5bd047ce 271
3b9e095b 272 return ret;
2fda0242 273}
d2d7acd5
AW
274#define NUM_BOOT_PROGS 8
275static SCM
276vm_make_boot_program (long nargs)
277{
278 static SCM programs[NUM_BOOT_PROGS] = { 0, };
279
280 if (SCM_UNLIKELY (!programs[0]))
281 {
282 int i;
283 for (i = 0; i < NUM_BOOT_PROGS; i++)
f39448c5 284 programs[i] = really_make_boot_program (i);
d2d7acd5
AW
285 }
286
287 if (SCM_LIKELY (nargs < NUM_BOOT_PROGS))
288 return programs[nargs];
289 else
290 return really_make_boot_program (nargs);
291}
2fda0242 292
a98cef7e
KN
293\f
294/*
295 * VM
296 */
297
b7393ea1
AW
298static SCM
299resolve_variable (SCM what, SCM program_module)
300{
9bd48cb1 301 if (SCM_LIKELY (scm_is_symbol (what)))
b7393ea1
AW
302 {
303 if (SCM_LIKELY (scm_module_system_booted_p
304 && scm_is_true (program_module)))
305 /* might longjmp */
306 return scm_module_lookup (program_module, what);
307 else
308 {
309 SCM v = scm_sym2var (what, SCM_BOOL_F, SCM_BOOL_F);
310 if (scm_is_false (v))
311 scm_misc_error (NULL, "unbound variable: ~S", scm_list_1 (what));
312 else
313 return v;
314 }
315 }
316 else
317 {
318 SCM mod;
319 /* compilation of @ or @@
320 `what' is a three-element list: (MODNAME SYM INTERFACE?)
321 INTERFACE? is #t if we compiled @ or #f if we compiled @@
322 */
323 mod = scm_resolve_module (SCM_CAR (what));
324 if (scm_is_true (SCM_CADDR (what)))
325 mod = scm_module_public_interface (mod);
5c8cefe5 326 if (scm_is_false (mod))
b7393ea1
AW
327 scm_misc_error (NULL, "no such module: ~S",
328 scm_list_1 (SCM_CAR (what)));
329 /* might longjmp */
330 return scm_module_lookup (mod, SCM_CADR (what));
331 }
332}
333
51e9ba2f 334#define VM_DEFAULT_STACK_SIZE (64 * 1024)
17e90c5e 335
17e90c5e 336#define VM_NAME vm_regular_engine
6d14383e
AW
337#define FUNC_NAME "vm-regular-engine"
338#define VM_ENGINE SCM_VM_REGULAR_ENGINE
83495480 339#include "vm-engine.c"
17e90c5e 340#undef VM_NAME
6d14383e 341#undef FUNC_NAME
17e90c5e 342#undef VM_ENGINE
17e90c5e
KN
343
344#define VM_NAME vm_debug_engine
6d14383e
AW
345#define FUNC_NAME "vm-debug-engine"
346#define VM_ENGINE SCM_VM_DEBUG_ENGINE
83495480 347#include "vm-engine.c"
17e90c5e 348#undef VM_NAME
6d14383e 349#undef FUNC_NAME
17e90c5e
KN
350#undef VM_ENGINE
351
6d14383e
AW
352static const scm_t_vm_engine vm_engines[] =
353 { vm_regular_engine, vm_debug_engine };
354
e3eb628d
LC
355#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
356
357/* The GC "kind" for the VM stack. */
358static int vm_stack_gc_kind;
359
360#endif
361
a98cef7e 362static SCM
17e90c5e
KN
363make_vm (void)
364#define FUNC_NAME "make_vm"
a98cef7e 365{
17e90c5e 366 int i;
7f991c7d 367 struct scm_vm *vp;
747a1635 368
7f991c7d 369 vp = scm_gc_malloc (sizeof (struct scm_vm), "vm");
d8eeb67c 370
3d5ee0cd 371 vp->stack_size = VM_DEFAULT_STACK_SIZE;
e3eb628d
LC
372
373#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
4168aa46
TTN
374 vp->stack_base = (SCM *)
375 GC_generic_malloc (vp->stack_size * sizeof (SCM), vm_stack_gc_kind);
e3eb628d
LC
376
377 /* Keep a pointer to VP so that `vm_stack_mark ()' can know what the stack
378 top is. */
379 *vp->stack_base = PTR2SCM (vp);
380 vp->stack_base++;
381 vp->stack_size--;
382#else
d8eeb67c
LC
383 vp->stack_base = scm_gc_malloc (vp->stack_size * sizeof (SCM),
384 "stack-base");
e3eb628d
LC
385#endif
386
2bbe1533
AW
387#ifdef VM_ENABLE_STACK_NULLING
388 memset (vp->stack_base, 0, vp->stack_size * sizeof (SCM));
389#endif
75d315e1 390 vp->stack_limit = vp->stack_base + vp->stack_size;
3616e9e9
KN
391 vp->ip = NULL;
392 vp->sp = vp->stack_base - 1;
393 vp->fp = NULL;
6d14383e 394 vp->engine = SCM_VM_DEBUG_ENGINE;
3d5ee0cd 395 vp->options = SCM_EOL;
7656f194 396 vp->trace_level = 0;
17e90c5e 397 for (i = 0; i < SCM_VM_NUM_HOOKS; i++)
3d5ee0cd 398 vp->hooks[i] = SCM_BOOL_F;
2d026f04 399 vp->cookie = 0;
6f3b0cc2 400 return scm_cell (scm_tc7_vm, (scm_t_bits)vp);
a98cef7e 401}
17e90c5e 402#undef FUNC_NAME
a98cef7e 403
e3eb628d
LC
404#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
405
406/* Mark the VM stack region between its base and its current top. */
407static struct GC_ms_entry *
408vm_stack_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
409 struct GC_ms_entry *mark_stack_limit, GC_word env)
410{
411 GC_word *word;
412 const struct scm_vm *vm;
413
414 /* The first word of the VM stack should contain a pointer to the
415 corresponding VM. */
416 vm = * ((struct scm_vm **) addr);
417
8071c490
LC
418 if (vm == NULL
419 || (SCM *) addr != vm->stack_base - 1
78747ac6 420 || vm->stack_limit - vm->stack_base != vm->stack_size)
e3eb628d
LC
421 /* ADDR must be a pointer to a free-list element, which we must ignore
422 (see warning in <gc/gc_mark.h>). */
423 return mark_stack_ptr;
424
e3eb628d
LC
425 for (word = (GC_word *) vm->stack_base; word <= (GC_word *) vm->sp; word++)
426 mark_stack_ptr = GC_MARK_AND_PUSH ((* (GC_word **) word),
427 mark_stack_ptr, mark_stack_limit,
428 NULL);
429
430 return mark_stack_ptr;
431}
432
433#endif /* VM_ENABLE_PRECISE_STACK_GC_SCAN */
434
435
6d14383e 436SCM
4abef68f 437scm_c_vm_run (SCM vm, SCM program, SCM *argv, int nargs)
6d14383e 438{
4abef68f 439 struct scm_vm *vp = SCM_VM_DATA (vm);
7656f194 440 return vm_engines[vp->engine](vm, program, argv, nargs);
6d14383e
AW
441}
442
6f3b0cc2
AW
443SCM_DEFINE (scm_vm_apply, "vm-apply", 3, 0, 0,
444 (SCM vm, SCM program, SCM args),
445 "")
446#define FUNC_NAME s_scm_vm_apply
a98cef7e 447{
6d14383e
AW
448 SCM *argv;
449 int i, nargs;
450
451 SCM_VALIDATE_VM (1, vm);
67e2d80a 452 SCM_VALIDATE_PROC (2, program);
6d14383e
AW
453
454 nargs = scm_ilength (args);
455 if (SCM_UNLIKELY (nargs < 0))
456 scm_wrong_type_arg_msg (FUNC_NAME, 3, args, "list");
457
458 argv = alloca(nargs * sizeof(SCM));
459 for (i = 0; i < nargs; i++)
460 {
461 argv[i] = SCM_CAR (args);
462 args = SCM_CDR (args);
463 }
464
4abef68f 465 return scm_c_vm_run (vm, program, argv, nargs);
a98cef7e 466}
17e90c5e 467#undef FUNC_NAME
a98cef7e 468
14aa25e4
AW
469SCM
470scm_vm_call_with_new_stack (SCM vm, SCM thunk, SCM id)
471{
472 return scm_c_vm_run (vm, thunk, NULL, 0);
473}
474
a98cef7e
KN
475/* Scheme interface */
476
477SCM_DEFINE (scm_vm_version, "vm-version", 0, 0, 0,
17e90c5e
KN
478 (void),
479 "")
a98cef7e
KN
480#define FUNC_NAME s_scm_vm_version
481{
d3518113 482 return scm_from_locale_string (PACKAGE_VERSION);
a98cef7e
KN
483}
484#undef FUNC_NAME
485
499a4c07 486SCM_DEFINE (scm_the_vm, "the-vm", 0, 0, 0,
fcd4901b 487 (void),
499a4c07
KN
488 "")
489#define FUNC_NAME s_scm_the_vm
490{
2bbe1533 491 scm_i_thread *t = SCM_I_CURRENT_THREAD;
f63ea2ce 492
8b22ed7a 493 if (SCM_UNLIKELY (scm_is_false ((t->vm))))
2bbe1533 494 t->vm = make_vm ();
f63ea2ce 495
2bbe1533 496 return t->vm;
499a4c07
KN
497}
498#undef FUNC_NAME
499
500
a98cef7e
KN
501SCM_DEFINE (scm_vm_p, "vm?", 1, 0, 0,
502 (SCM obj),
17e90c5e 503 "")
a98cef7e
KN
504#define FUNC_NAME s_scm_vm_p
505{
9bd48cb1 506 return scm_from_bool (SCM_VM_P (obj));
a98cef7e
KN
507}
508#undef FUNC_NAME
509
510SCM_DEFINE (scm_make_vm, "make-vm", 0, 0, 0,
17e90c5e
KN
511 (void),
512 "")
513#define FUNC_NAME s_scm_make_vm,
a98cef7e 514{
17e90c5e 515 return make_vm ();
a98cef7e
KN
516}
517#undef FUNC_NAME
518
17e90c5e 519SCM_DEFINE (scm_vm_ip, "vm:ip", 1, 0, 0,
a98cef7e 520 (SCM vm),
17e90c5e
KN
521 "")
522#define FUNC_NAME s_scm_vm_ip
a98cef7e
KN
523{
524 SCM_VALIDATE_VM (1, vm);
f41cb00c 525 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->ip);
a98cef7e
KN
526}
527#undef FUNC_NAME
528
529SCM_DEFINE (scm_vm_sp, "vm:sp", 1, 0, 0,
530 (SCM vm),
17e90c5e 531 "")
a98cef7e
KN
532#define FUNC_NAME s_scm_vm_sp
533{
534 SCM_VALIDATE_VM (1, vm);
f41cb00c 535 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->sp);
a98cef7e
KN
536}
537#undef FUNC_NAME
538
539SCM_DEFINE (scm_vm_fp, "vm:fp", 1, 0, 0,
540 (SCM vm),
17e90c5e 541 "")
a98cef7e
KN
542#define FUNC_NAME s_scm_vm_fp
543{
544 SCM_VALIDATE_VM (1, vm);
f41cb00c 545 return scm_from_ulong ((unsigned long) SCM_VM_DATA (vm)->fp);
a98cef7e
KN
546}
547#undef FUNC_NAME
548
17e90c5e
KN
549#define VM_DEFINE_HOOK(n) \
550{ \
3d5ee0cd 551 struct scm_vm *vp; \
17e90c5e 552 SCM_VALIDATE_VM (1, vm); \
3d5ee0cd 553 vp = SCM_VM_DATA (vm); \
8b22ed7a 554 if (scm_is_false (vp->hooks[n])) \
238e7a11 555 vp->hooks[n] = scm_make_hook (SCM_I_MAKINUM (1)); \
3d5ee0cd 556 return vp->hooks[n]; \
17e90c5e
KN
557}
558
559SCM_DEFINE (scm_vm_boot_hook, "vm-boot-hook", 1, 0, 0,
a98cef7e 560 (SCM vm),
17e90c5e
KN
561 "")
562#define FUNC_NAME s_scm_vm_boot_hook
a98cef7e 563{
17e90c5e 564 VM_DEFINE_HOOK (SCM_VM_BOOT_HOOK);
a98cef7e
KN
565}
566#undef FUNC_NAME
567
17e90c5e
KN
568SCM_DEFINE (scm_vm_halt_hook, "vm-halt-hook", 1, 0, 0,
569 (SCM vm),
570 "")
571#define FUNC_NAME s_scm_vm_halt_hook
a98cef7e 572{
17e90c5e 573 VM_DEFINE_HOOK (SCM_VM_HALT_HOOK);
a98cef7e
KN
574}
575#undef FUNC_NAME
576
17e90c5e 577SCM_DEFINE (scm_vm_next_hook, "vm-next-hook", 1, 0, 0,
a98cef7e 578 (SCM vm),
17e90c5e
KN
579 "")
580#define FUNC_NAME s_scm_vm_next_hook
a98cef7e 581{
17e90c5e 582 VM_DEFINE_HOOK (SCM_VM_NEXT_HOOK);
a98cef7e
KN
583}
584#undef FUNC_NAME
585
7a0d0cee
KN
586SCM_DEFINE (scm_vm_break_hook, "vm-break-hook", 1, 0, 0,
587 (SCM vm),
588 "")
589#define FUNC_NAME s_scm_vm_break_hook
590{
591 VM_DEFINE_HOOK (SCM_VM_BREAK_HOOK);
592}
593#undef FUNC_NAME
594
17e90c5e
KN
595SCM_DEFINE (scm_vm_enter_hook, "vm-enter-hook", 1, 0, 0,
596 (SCM vm),
597 "")
598#define FUNC_NAME s_scm_vm_enter_hook
a98cef7e 599{
17e90c5e 600 VM_DEFINE_HOOK (SCM_VM_ENTER_HOOK);
a98cef7e
KN
601}
602#undef FUNC_NAME
603
17e90c5e
KN
604SCM_DEFINE (scm_vm_apply_hook, "vm-apply-hook", 1, 0, 0,
605 (SCM vm),
606 "")
607#define FUNC_NAME s_scm_vm_apply_hook
a98cef7e 608{
17e90c5e 609 VM_DEFINE_HOOK (SCM_VM_APPLY_HOOK);
a98cef7e
KN
610}
611#undef FUNC_NAME
612
17e90c5e 613SCM_DEFINE (scm_vm_exit_hook, "vm-exit-hook", 1, 0, 0,
a98cef7e 614 (SCM vm),
17e90c5e
KN
615 "")
616#define FUNC_NAME s_scm_vm_exit_hook
a98cef7e 617{
17e90c5e 618 VM_DEFINE_HOOK (SCM_VM_EXIT_HOOK);
a98cef7e
KN
619}
620#undef FUNC_NAME
621
17e90c5e 622SCM_DEFINE (scm_vm_return_hook, "vm-return-hook", 1, 0, 0,
a98cef7e 623 (SCM vm),
17e90c5e
KN
624 "")
625#define FUNC_NAME s_scm_vm_return_hook
a98cef7e 626{
17e90c5e 627 VM_DEFINE_HOOK (SCM_VM_RETURN_HOOK);
a98cef7e
KN
628}
629#undef FUNC_NAME
630
17e90c5e
KN
631SCM_DEFINE (scm_vm_option, "vm-option", 2, 0, 0,
632 (SCM vm, SCM key),
633 "")
634#define FUNC_NAME s_scm_vm_option
a98cef7e
KN
635{
636 SCM_VALIDATE_VM (1, vm);
17e90c5e 637 return scm_assq_ref (SCM_VM_DATA (vm)->options, key);
a98cef7e
KN
638}
639#undef FUNC_NAME
640
17e90c5e
KN
641SCM_DEFINE (scm_set_vm_option_x, "set-vm-option!", 3, 0, 0,
642 (SCM vm, SCM key, SCM val),
643 "")
644#define FUNC_NAME s_scm_set_vm_option_x
a98cef7e
KN
645{
646 SCM_VALIDATE_VM (1, vm);
17e90c5e
KN
647 SCM_VM_DATA (vm)->options
648 = scm_assq_set_x (SCM_VM_DATA (vm)->options, key, val);
649 return SCM_UNSPECIFIED;
a98cef7e
KN
650}
651#undef FUNC_NAME
652
7656f194 653SCM_DEFINE (scm_vm_trace_level, "vm-trace-level", 1, 0, 0,
17e90c5e
KN
654 (SCM vm),
655 "")
7656f194 656#define FUNC_NAME s_scm_vm_trace_level
a98cef7e 657{
a98cef7e 658 SCM_VALIDATE_VM (1, vm);
7656f194
AW
659 return scm_from_int (SCM_VM_DATA (vm)->trace_level);
660}
661#undef FUNC_NAME
662
663SCM_DEFINE (scm_set_vm_trace_level_x, "set-vm-trace-level!", 2, 0, 0,
664 (SCM vm, SCM level),
665 "")
666#define FUNC_NAME s_scm_set_vm_trace_level_x
667{
668 SCM_VALIDATE_VM (1, vm);
669 SCM_VM_DATA (vm)->trace_level = scm_to_int (level);
670 return SCM_UNSPECIFIED;
a98cef7e
KN
671}
672#undef FUNC_NAME
673
674\f
675/*
17e90c5e 676 * Initialize
a98cef7e
KN
677 */
678
07e56b27
AW
679SCM scm_load_compiled_with_vm (SCM file)
680{
53e28ed9 681 SCM program = scm_make_program (scm_load_objcode (file),
20d47c39 682 SCM_BOOL_F, SCM_BOOL_F);
07e56b27 683
4abef68f 684 return scm_c_vm_run (scm_the_vm (), program, NULL, 0);
07e56b27
AW
685}
686
17e90c5e 687void
07e56b27 688scm_bootstrap_vm (void)
17e90c5e 689{
60ae5ca2
AW
690 scm_c_register_extension ("libguile", "scm_init_vm",
691 (scm_t_extension_init_func)scm_init_vm, NULL);
692
e3eb628d
LC
693#ifdef VM_ENABLE_PRECISE_STACK_GC_SCAN
694 vm_stack_gc_kind =
695 GC_new_kind (GC_new_free_list (),
696 GC_MAKE_PROC (GC_new_proc (vm_stack_mark), 0),
697 0, 1);
698
699#endif
07e56b27
AW
700}
701
702void
703scm_init_vm (void)
704{
17e90c5e 705#ifndef SCM_MAGIC_SNARFER
aeeff258 706#include "libguile/vm.x"
17e90c5e 707#endif
a98cef7e 708}
17e90c5e
KN
709
710/*
711 Local Variables:
712 c-file-style: "gnu"
713 End:
714*/