diff --git a/src/wren_vm.c b/src/wren_vm.c index 2f852a37..8cbc6901 100644 --- a/src/wren_vm.c +++ b/src/wren_vm.c @@ -883,14 +883,20 @@ static bool runInterpreter(WrenVM* vm) Value result = POP(); fiber->numFrames--; + // Close any upvalues still in scope. + Value* firstValue = &fiber->stack[frame->stackStart]; + while (fiber->openUpvalues != NULL && + fiber->openUpvalues->value >= firstValue) + { + closeUpvalue(fiber); + } + // If the fiber is complete, end it. if (fiber->numFrames == 0) { // If this is the main fiber, we're done. if (fiber->caller == NULL) return true; - // TODO: Do we need to close upvalues here? - // We have a calling fiber to resume. fiber = fiber->caller; @@ -899,14 +905,6 @@ static bool runInterpreter(WrenVM* vm) } else { - // Close any upvalues still in scope. - Value* firstValue = &fiber->stack[frame->stackStart]; - while (fiber->openUpvalues != NULL && - fiber->openUpvalues->value >= firstValue) - { - closeUpvalue(fiber); - } - // Store the result of the block in the first slot, which is where the // caller expects it. fiber->stack[frame->stackStart] = result; diff --git a/test/fiber/closure.wren b/test/fiber/closure.wren new file mode 100644 index 00000000..d0bfff7e --- /dev/null +++ b/test/fiber/closure.wren @@ -0,0 +1,25 @@ +var fiber +var closure + +{ + var a = "before" + fiber = Fiber.create(fn { + IO.print(a) + Fiber.yield + a = "after" + Fiber.yield + IO.print(a) + a = "final" + }) + + closure = fn { + IO.print(a) + } +} + +fiber.run // expect: before +closure.call // expect: before +fiber.run +closure.call // expect: after +fiber.run // expect: after +closure.call // expect: final diff --git a/test/fiber/create_wrong_arg_type.wren b/test/fiber/create_wrong_arg_type.wren new file mode 100644 index 00000000..e5209216 --- /dev/null +++ b/test/fiber/create_wrong_arg_type.wren @@ -0,0 +1 @@ +var fiber = Fiber.create("not fn") // expect runtime error: Argument must be a function. diff --git a/test/fiber/run.wren b/test/fiber/run.wren index fd54fd9f..cdf0b85a 100644 --- a/test/fiber/run.wren +++ b/test/fiber/run.wren @@ -7,6 +7,3 @@ fiber.run // expect: fiber IO.print("after") // expect: after // TODO: Test handles error if fiber tries to run itself. -// TODO: Test create is passed right argument type. -// TODO: Test closing over stuff in fiber function. -// TODO: Test running a finished fiber.