diff --git a/src/wren_core.c b/src/wren_core.c index 0b9aba1d..4b0d9bd4 100644 --- a/src/wren_core.c +++ b/src/wren_core.c @@ -196,11 +196,18 @@ DEF_NATIVE(fiber_create) RETURN_VAL(OBJ_VAL(newFiber)); } +DEF_NATIVE(fiber_isDone) +{ + ObjFiber* runFiber = AS_FIBER(args[0]); + RETURN_BOOL(runFiber->numFrames == 0); +} + DEF_NATIVE(fiber_run) { - // TODO: Error if the fiber is already complete. ObjFiber* runFiber = AS_FIBER(args[0]); + if (runFiber->numFrames == 0) RETURN_ERROR("Cannot run a finished fiber."); + // Remember who ran it. runFiber->caller = fiber; @@ -215,9 +222,10 @@ DEF_NATIVE(fiber_run) DEF_NATIVE(fiber_run1) { - // TODO: Error if the fiber is already complete. ObjFiber* runFiber = AS_FIBER(args[0]); + if (runFiber->numFrames == 0) RETURN_ERROR("Cannot run a finished fiber."); + // Remember who ran it. runFiber->caller = fiber; @@ -239,7 +247,7 @@ DEF_NATIVE(fiber_run1) DEF_NATIVE(fiber_yield) { - // TODO: Handle caller being null. + if (fiber->caller == NULL) RETURN_ERROR("No fiber to yield to."); // Make the caller's run method return null. fiber->caller->stack[fiber->caller->stackSize - 1] = NULL_VAL; @@ -251,7 +259,7 @@ DEF_NATIVE(fiber_yield) DEF_NATIVE(fiber_yield1) { - // TODO: Handle caller being null. + if (fiber->caller == NULL) RETURN_ERROR("No fiber to yield to."); // Make the caller's run method return the argument passed to yield. fiber->caller->stack[fiber->caller->stackSize - 1] = args[1]; @@ -698,6 +706,7 @@ void wrenInitializeCore(WrenVM* vm) NATIVE(vm->fiberClass->metaclass, "create ", fiber_create); NATIVE(vm->fiberClass->metaclass, "yield", fiber_yield); NATIVE(vm->fiberClass->metaclass, "yield ", fiber_yield1); + NATIVE(vm->fiberClass, "isDone", fiber_isDone); NATIVE(vm->fiberClass, "run", fiber_run); NATIVE(vm->fiberClass, "run ", fiber_run1); // TODO: Primitives for switching to a fiber without setting the caller. diff --git a/test/fiber/is_done.wren b/test/fiber/is_done.wren new file mode 100644 index 00000000..49fd5a18 --- /dev/null +++ b/test/fiber/is_done.wren @@ -0,0 +1,11 @@ +var fiber = Fiber.create(fn { + IO.print("1") + Fiber.yield + IO.print("2") +}) + +IO.print(fiber.isDone) // expect: false +fiber.run // expect: 1 +IO.print(fiber.isDone) // expect: false +fiber.run // expect: 2 +IO.print(fiber.isDone) // expect: true diff --git a/test/fiber/run_when_done.wren b/test/fiber/run_when_done.wren new file mode 100644 index 00000000..7282f1e0 --- /dev/null +++ b/test/fiber/run_when_done.wren @@ -0,0 +1,6 @@ +var fiber = Fiber.create(fn { + IO.print("run") +}) + +fiber.run // expect: run +fiber.run // expect runtime error: Cannot run a finished fiber. diff --git a/test/fiber/run_with_value_when_done.wren b/test/fiber/run_with_value_when_done.wren new file mode 100644 index 00000000..09542b40 --- /dev/null +++ b/test/fiber/run_with_value_when_done.wren @@ -0,0 +1,6 @@ +var fiber = Fiber.create(fn { + IO.print("run") +}) + +fiber.run(1) // expect: run +fiber.run(2) // expect runtime error: Cannot run a finished fiber. diff --git a/test/fiber/yield_from_main.wren b/test/fiber/yield_from_main.wren new file mode 100644 index 00000000..b887c2ea --- /dev/null +++ b/test/fiber/yield_from_main.wren @@ -0,0 +1 @@ +Fiber.yield // expect runtime error: No fiber to yield to. diff --git a/test/fiber/yield_with_value_from_main.wren b/test/fiber/yield_with_value_from_main.wren new file mode 100644 index 00000000..0b890db0 --- /dev/null +++ b/test/fiber/yield_with_value_from_main.wren @@ -0,0 +1 @@ +Fiber.yield(1) // expect runtime error: No fiber to yield to.