feat: implement fiber primitives with create, run, yield and caller tracking

Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
This commit is contained in:
Bob Nystrom
2014-01-12 19:02:07 +00:00
parent d0d92971d8
commit fc4880774e
15 changed files with 306 additions and 40 deletions
+19
View File
@@ -0,0 +1,19 @@
var b = Fiber.create(fn {
IO.print("fiber b")
})
var a = Fiber.create(fn {
IO.print("begin fiber a")
b.run
IO.print("end fiber a")
})
IO.print("begin main")
a.run
IO.print("end main")
// expect: begin main
// expect: begin fiber a
// expect: fiber b
// expect: end fiber a
// expect: end main
+12
View File
@@ -0,0 +1,12 @@
var fiber = Fiber.create(fn {
IO.print("fiber")
})
IO.print("before") // expect: before
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.
+6
View File
@@ -0,0 +1,6 @@
var fiber = Fiber.create(fn {
IO.print("fiber")
})
var result = fiber.run // expect: fiber
IO.print(result) // expect: null
+7
View File
@@ -0,0 +1,7 @@
var fiber = Fiber.create(fn {
IO.print("fiber")
return "result"
})
var result = fiber.run // expect: fiber
IO.print(result) // expect: result
+9
View File
@@ -0,0 +1,9 @@
var fiber = Fiber.create(fn {
IO.print("fiber")
})
// The first value passed to the fiber is ignored, since there's no yield call
// to return it.
IO.print("before") // expect: before
fiber.run("ignored") // expect: fiber
IO.print("after") // expect: after
+5
View File
@@ -0,0 +1,5 @@
var fiber = Fiber.create(fn null)
IO.print(fiber is Fiber) // expect: true
IO.print(fiber is Object) // expect: true
IO.print(fiber is Bool) // expect: false
IO.print(fiber.type == Fiber) // expect: true
+14
View File
@@ -0,0 +1,14 @@
var fiber = Fiber.create(fn {
IO.print("fiber 1")
Fiber.yield
IO.print("fiber 2")
Fiber.yield
IO.print("fiber 3")
})
var result = fiber.run // expect: fiber 1
IO.print("main 1") // expect: main 1
result = fiber.run // expect: fiber 2
IO.print("main 2") // expect: main 2
result = fiber.run // expect: fiber 3
IO.print("main 3") // expect: main 3
+14
View File
@@ -0,0 +1,14 @@
var fiber = Fiber.create(fn {
IO.print("fiber 1")
var result = Fiber.yield
IO.print(result)
result = Fiber.yield
IO.print(result)
})
fiber.run // expect: fiber 1
IO.print("main 1") // expect: main 1
fiber.run("run 1") // expect: run 1
IO.print("main 2") // expect: main 2
fiber.run // expect: null
IO.print("main 3") // expect: main 3
+14
View File
@@ -0,0 +1,14 @@
var fiber = Fiber.create(fn {
IO.print("fiber 1")
Fiber.yield("yield 1")
IO.print("fiber 2")
Fiber.yield("yield 2")
IO.print("fiber 3")
})
var result = fiber.run // expect: fiber 1
IO.print(result) // expect: yield 1
result = fiber.run // expect: fiber 2
IO.print(result) // expect: yield 2
result = fiber.run // expect: fiber 3
IO.print(result) // expect: null