;; lib/go/sched.sx — Go scheduler primitives: channels + goroutines. ;; ;; This is **the independent implementation** referenced by ;; plans/lib-guest-scheduler.md. The shape that emerges here informs ;; the eventual sister kit; this file's structures are the Phase 5 ;; "first-consumer" cut. ;; ;; v0 concurrency model — IMPORTANT ;; ;; SX has no first-class continuations exposed to guest code, so we ;; can't suspend a goroutine mid-statement. v0 runs `go f()` SYNCHRO- ;; NOUSLY (it's an immediate call whose return value is dropped). This ;; preserves the right semantics for patterns where the spawned ;; goroutine simply pushes to a channel that the main goroutine then ;; receives — because the spawned goroutine runs to completion first ;; and leaves the value in the channel buffer. ;; ;; True preemption with blocking sends/recvs is a Phase 5b refinement. ;; The sister-plan diary tracks the design insight (single ;; sched-spawn primitive, channel-op direction tag) so the eventual ;; kit doesn't bake in v0's synchronous limitation. ;; ;; Channel representation ;; ;; (list :go-chan ACCESSORS-FN-LIST) ;; ;; ACCESSORS-FN-LIST is a list of closures sharing a mutable buffer ;; and a closed flag. The closures expose: ;; index 1: send-fn — (lambda (val) ...) ;; index 2: recv-fn — (lambda () val-or-:empty) ;; index 3: closed?-fn — (lambda () bool) ;; index 4: close!-fn — (lambda () ...) ;; ;; Channel identity: distinct calls to go-make-chan produce closures ;; with distinct identity — `(= ch1 ch2)` is false for distinct ;; channels, matching Go spec § Channel types. (define go-make-chan (fn () (let ((buf (list)) (closed false)) (list :go-chan (fn (v) (append! buf v) nil) (fn () (cond (= (len buf) 0) :empty :else (let ((v (first buf))) (set! buf (rest buf)) v))) (fn () closed) (fn () (set! closed true) nil) (fn () (len buf)))))) (define go-chan? (fn (v) (and (list? v) (not (= (len v) 0)) (= (first v) :go-chan)))) (define go-chan-send! (fn (ch val) ((nth ch 1) val))) (define go-chan-recv! (fn (ch) ((nth ch 2)))) (define go-chan-closed? (fn (ch) ((nth ch 3)))) (define go-chan-close! (fn (ch) ((nth ch 4)))) (define go-chan-len (fn (ch) ((nth ch 5))))