diff --git a/lib/fiber.sx b/lib/fiber.sx new file mode 100644 index 00000000..68390720 --- /dev/null +++ b/lib/fiber.sx @@ -0,0 +1,44 @@ +; lib/fiber.sx — pure SX fiber library using call/cc +; +; A fiber is a cooperative coroutine with true suspension (no eager +; pre-execution). Each fiber is a dict {:resume fn :done? fn}. +; +; make-fiber body → fiber dict +; body = (fn (yield init-val) ...) — body receives yield + first resume val +; yield = (fn (val) ...) — suspends fiber, returns val to resumer +; +; fiber-resume f v → next yielded value, or nil when body returns +; fiber-done? f → true after body has returned + +(define make-fiber + (fn (body) + (let + ((resume-k nil) + (caller-k nil) + (done false)) + (let + ((yield + (fn (val) + (call/cc + (fn (k) + (set! resume-k k) + (caller-k val)))))) + {:resume + (fn (val) + (if + done + nil + (call/cc + (fn (k) + (set! caller-k k) + (if + (nil? resume-k) + (begin + (body yield val) + (set! done true) + (k nil)) + (resume-k val)))))) + :done? (fn () done)})))) + +(define fiber-resume (fn (f v) ((get f :resume) v))) +(define fiber-done? (fn (f) ((get f :done?))))