#lang plait
(define yield-param (make-parameter
(lambda (v) (error 'yield! "outside generator"))))
(define (yield v) ((parameter-ref yield-param) v))
(define-syntax-rule (generator (arg) exprs ...)
(let ([last-checkpoint (none)])
(lambda (v)
(let/cc dyn-k ;; generator call site
(parameterize ([yield-param
(lambda (v)
(let/cc gen-k ;; yield call site
(begin
(set! last-checkpoint
(some gen-k))
(dyn-k v))))])
(type-case (Optionof ('a -> 'b)) last-checkpoint
[(none) (let ([arg v]) (begin exprs ...))]
[(some k) (k v)])))
)))
(define g1
(generator (v)
(letrec ([loop (lambda (n)
(begin
(yield n)
(loop (+ n 1))))])
(loop v))))
(g1 10) (g1 10) (g1 10)
(define g2
(generator (v)
(letrec ([loop (lambda (n)
(loop (+ (yield n) n)))])
(loop v))))
(g2 10) (g2 10) (g2 10)