; FILE          "Coroutines.scm"
; IMPLEMENTS    Coroutines based on Springer & Friedman's _Scheme and the
;               Art of Programming_, MIT Press, 1989.
; AUTHOR        Ken Dickey
; DATE          1992 May 8
; LAST UPDATED  1992 May 10

;;(require 'format)

;; make-coutoutine takes a coroutine proc, <co-proc>.
;; <co-proc> takes a resumer and a state argument, does
;; its thing, and resumes by calling the resumer with a
;; new state argument.

(define (MAKE-COROUTINE <co-proc>) 
  (letrec ( (saved-cont 'bogus)
            (run-once? #f)
            ;; The resumer captures a continuation..
            ;; which can "re-call" next-guy.
            (resumer
              (lambda (next-guy arg)
                (call-with-current-continuation
                   (lambda (cont)
                      (set! saved-cont cont)
                      (next-guy arg))
            ) ) )
          )

    ;; Return a coroutine "resume" function.  The resumer
    ;; will remember the continuation to re-call the other
    ;; guy after it has been called the 1st time.

    (lambda (arg)
      (if run-once?
          (saved-cont arg)
          (begin
             (set! run-once? #t)
             (<co-proc> resumer arg)
      )   )

) ) )
  


;;----------------------------------------------------------------
;; TEST CODE

(define A 
  (make-coroutine 
    (lambda (resume ignored)
      (format #t "This is A~%")
      (format #t "Came From ~a~%" (resume B "A"))
      (format #t "Back in A~%")
      (format #t "Came From ~a~%" (resume C "A"))
) ) )

(define B
  (make-coroutine 
    (lambda (resume ignored)
      (format #t "~T~T~TThis is B~%")
      (format #t "~T~T~TCame From ~a~%" (resume C "B"))
      (format #t "~T~T~TBack in B~%")
      (format #t "~T~T~TCame From ~a~%" (resume A "B"))
) ) )

(define C
  (make-coroutine 
    (lambda (resume ignored)
      (format #t "~T~T~T~T~T~TThis is C~%")
      (format #t "~T~T~T~T~T~TCame From ~a~%" (resume A "C"))
      (format #t "~T~T~T~T~T~TBack in C~%")
      (format #t "~T~T~T~T~T~TCame From ~a~%" (resume B "C"))
) ) )

;; results of (A '*)

;This is A
;                        This is B
;                                                This is C
;Came From C
;Back in A
;                                                Came From A
;                                                Back in C
;                        Came From C
;                        Back in B
;Came From B

;;                           --- E O F ---                       ;;
