diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2018-03-19 22:07:34 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2018-03-19 22:07:34 -0700 |
commit | 50b3b8a020217910041ece4f380cc97ed6845ae9 (patch) | |
tree | 2ecd4cb89328822ff1997ff82aff15be0fc72e33 /vm.c | |
parent | f0b797d9b99951d9b08bd0c0bddff283401703ec (diff) | |
download | txr-50b3b8a020217910041ece4f380cc97ed6845ae9.tar.gz txr-50b3b8a020217910041ece4f380cc97ed6845ae9.tar.bz2 txr-50b3b8a020217910041ece4f380cc97ed6845ae9.zip |
vm: support deferred resolution of ftab bindings.
This allows a virtual machine's funvec to refer to functions
that are not yet defined. We resolve all the ones that are
defined when the virtual machine description is constructed.
The others are resolved at vm execution time when accessed.
* vm.c (vm_make_desc): When filling ftab with resolved
function bindings, check that lookup_fun has returned nil; in
that case, initialize the binding location to zero,
instead of blowing up calling cdr_l(nil).
(vm_ftab): New static function. Implements the null check
and late resolution.
(vm_gcall, vm_gapply): Acces ftab through vm_ftab instead
of open-coded expression.
Diffstat (limited to 'vm.c')
-rw-r--r-- | vm.c | 24 |
1 files changed, 20 insertions, 4 deletions
@@ -160,7 +160,7 @@ val vm_make_desc(val nlevels, val nregs, val bytecode, for (i = 0; i < fvl; i++) { struct vm_ftent *fe = &ftab[i]; fe->fb = lookup_fun(nil, vecref(funvec, num_fast(i))); - fe->fbloc = cdr_l(fe->fb); + fe->fbloc = if3(fe->fb, cdr_l(fe->fb), nulloc); } return desc; @@ -420,6 +420,23 @@ static void vm_apply(struct vm *vm, vm_word_t insn) vm_set(vm->dspl, dest, result); } +static loc vm_ftab(struct vm *vm, unsigned fun) +{ + struct vm_desc *vd = vm->vd; + struct vm_ftent *fe = &vd->ftab[fun]; + loc fbloc = fe->fbloc; + + if (!nullocp(fbloc)) + return fbloc; + + if (nilp(fe->fb = lookup_fun(nil, vecref(vd->funvec, num_fast(fun))))) + eval_error(vd->bytecode, + lit("function ~s is not defined"), + vecref(vd->funvec, num(fun)), nao); + gc_mutated(vd->self); + return (fe->fbloc = cdr_l(fe->fb)); +} + static void vm_gcall(struct vm *vm, vm_word_t insn) { unsigned nargs = vm_insn_extra(insn); @@ -445,7 +462,7 @@ static void vm_gcall(struct vm *vm, vm_word_t insn) } } - result = generic_funcall(deref(vm->vd->ftab[fun].fbloc), args); + result = generic_funcall(deref(vm_ftab(vm, fun)), args); vm_set(vm->dspl, dest, result); } @@ -474,8 +491,7 @@ static void vm_gapply(struct vm *vm, vm_word_t insn) } } - result = apply_intrinsic(deref(vm->vd->ftab[fun].fbloc), - args_get_list(args)); + result = apply_intrinsic(deref(vm_ftab(vm, fun)), args_get_list(args)); vm_set(vm->dspl, dest, result); } |