diff --git a/interp.c b/interp.c index 18d90e5..13e3a35 100644 --- a/interp.c +++ b/interp.c @@ -328,21 +328,27 @@ break_for_loop: static void perform_tail_call(interp_state_t *state) { - value_t new_lambda, new_argv, new_ctx, new_k; + gc_root_t new_lambda, new_argv, new_ctx, new_k; - new_lambda = get_input(state, get_fixnum(_LAMBDA_SLOT(state->lambda.value, TAIL_CALL))); - new_argv = get_input(state, get_fixnum(_LAMBDA_SLOT(state->lambda.value, ARG_LIST))); - new_ctx = get_input(state, get_fixnum(_LAMBDA_SLOT(state->lambda.value, CONTEXT))); - new_k = get_input(state, get_fixnum(_LAMBDA_SLOT(state->lambda.value, CONTINUATION))); + register_gc_root(&new_lambda, get_input(state, get_fixnum(_LAMBDA_SLOT(state->lambda.value, TAIL_CALL)))); + register_gc_root(&new_argv, get_input(state, get_fixnum(_LAMBDA_SLOT(state->lambda.value, ARG_LIST)))); + register_gc_root(&new_ctx, get_input(state, get_fixnum(_LAMBDA_SLOT(state->lambda.value, CONTEXT)))); + register_gc_root(&new_k, get_input(state, get_fixnum(_LAMBDA_SLOT(state->lambda.value, CONTINUATION)))); - /* If new lambda or continuation is a template, instantiate it here. */ - new_lambda = make_lambda(state, new_lambda); - new_k = make_lambda(state, new_k); + /* If new lambda or continuation is a template, instantiate it here */ + new_lambda.value = make_lambda(state, new_lambda.value); + new_k.value = make_lambda(state, new_k.value); - state->lambda.value = new_lambda; - state->argv.value = new_argv; - state->ctx.value = new_ctx; - state->k.value = new_k; + /* Transfer control to new function */ + state->lambda.value = new_lambda.value; + state->argv.value = new_argv.value; + state->ctx.value = new_ctx.value; + state->k.value = new_k.value; + + unregister_gc_root(&new_lambda); + unregister_gc_root(&new_argv); + unregister_gc_root(&new_ctx); + unregister_gc_root(&new_k); } static value_t eval_expression(interp_state_t *state, uint8_t code, uint8_t in1, uint8_t in2) diff --git a/src/examples/factorial.rla b/src/examples/factorial.rla index ff28eb1..80b296d 100755 --- a/src/examples/factorial.rla +++ b/src/examples/factorial.rla @@ -10,6 +10,7 @@ ; (lambda () (string->number number-string)) ; (lambda (n) (k (fact n)))))) #( + #="string->number" #S(#="template" ; (let/cc k ; (lambda (n) @@ -25,14 +26,13 @@ 0x40 ; i0 0x41 ; i1 ) - #="string->number" ; g2 ) #() - 1 - "\x00\x80\x1b\x01"; (set! f0 (lambda g1)) - 0x02 ; g2 + 0 + "" + 0x01 ; g1 0xfd ; argv 0xfe ; ctx - 0x80 ; f0 + 0x02 ; g2 ) ; vim:set syntax= sw=2 expandtab: diff --git a/src/lib/math/fact.rla b/src/lib/math/fact.rla index fbea33c..322aa88 100755 --- a/src/lib/math/fact.rla +++ b/src/lib/math/fact.rla @@ -50,7 +50,7 @@ #=0 ; fact ) "\x80" - 2 + 1 "\x09\x80\x40\x01\; (set! f0 (fix- i0 g1)) \x02\x80\x80\x00"; (set! f0 (cons f0 nil)) 0x03 ; g3