no title added by anti-freeze on Sun Aug 16 19:31:56 2015

(use-for-syntax bindings)

(define (coroutine thunk)
  "Calls a procedure that can yield a continuation."
  (define (handler cont callback . args)
    (define (resume . args)
      ;; Call continuation that resumes the procedure.
      (call-with-prompt 'coroutine-prompt
                        (lambda () (apply cont args))
                        handler))
    (when (procedure? callback)
      (apply callback resume args)))
  
  ;; Call procedure 
  (call-with-prompt 'coroutine-prompt thunk handler))

(define-syntax-rule (colambda args body ...)
    "Syntactic sugar for a lambda that runs as a coroutine."
    (lambda args
      (coroutine 
        (lambda () body ...))))

(define-syntax-rule (codefine (name ...) . body)
    "Syntactic sugar for defining a procedure that is run as a coroutine."
    (define (name ...)
      ;; Define a procedure with the same name, so as a recursive definition of
      ;; the procedure won't create a new prompt.
      (define (name ...) . body)
      (coroutine 
        (lambda () (name ...)))))

(define-syntax-rule (codefine* (name . formals) . body)
    "Syntactic sugar for defining a procedure that is run as a coroutine."
    (define (name . args)
      (define* (name . formals) . body)
      (coroutine 
        (lambda () (apply name args)))))

(define (yield callback)
  "Yield continuation to a CALLBACK procedure."
  (abort-to-prompt 'coroutine-prompt callback))