suggested revision

svn: r15812
This commit is contained in:
Eli Barzilay 2009-08-27 12:16:26 +00:00
parent ec9fc2571a
commit 572f7f849b

View File

@ -2,63 +2,53 @@
(require (for-syntax scheme/base) (require (for-syntax scheme/base)
scheme/control scheme/control
scheme/stxparam) scheme/stxparam scheme/splicing)
(provide yield lambda-generator (provide yield generator in-generator)
define-generator in-generator)
(define-syntax-parameter yield (define-syntax-parameter yield
(lambda (stx) (lambda (stx)
(raise-syntax-error #f "yield is only bound inside a sequence generator"))) (raise-syntax-error #f "yield is only bound inside a sequence generator")))
;; better version of shift/reset using continuation tags also use a ;; (define (procedure->generator proc)
;; unique value to determine the end of the sequence instead of using #f ;; (define tag (make-continuation-prompt-tag))
(define-syntax lambda-generator ;; (define (cont)
(syntax-rules () ;; (reset-at tag
[(_ (args ...) body0 bodies ...) ;; (let ([r (proc (lambda (r) (shift-at tag k (set! cont k) r)))])
(lambda (args ...) ;; ;; normal return:
(let* ([last (gensym)] ;; (set! cont (lambda () r))
;; current is a function that invokes user code and ;; r)))
;; produces values ;; (lambda () (cont)))
[current
(lambda ()
;; a unique tag to jump to
(define tag (make-continuation-prompt-tag))
;; give the value to the sequence
(define (next value) (shift-at tag f (values value f)))
(syntax-parameterize ([yield (make-rename-transformer #'next)])
(reset-at tag body0 bodies ... (values #f last))))]
[seq
(make-do-sequence
(lambda ()
(values
;; produce a value and a continuation
(lambda (i)
(let-values ([(value next) (current)])
;; set! is ugly but can we do better?
(set! current next)
value))
void
(void)
(lambda (x) (not (eq? last current)))
(lambda (v) (not (eq? last current)))
(lambda (x v) (not (eq? last current))))))])
seq))]))
;; use define-sequence-syntax to be more in sync with other for loop constructs (define-syntax-rule (generator body0 body ...)
(define-syntax in-generator (let ([tag (make-continuation-prompt-tag)])
(syntax-rules () (define y
[(_ body0 bodies ...) (let ([yield (lambda (r) (shift-at tag k (set! cont k) r))]) yield))
((lambda-generator () body0 bodies ...))])) (splicing-syntax-parameterize ([yield (make-rename-transformer #'y)])
(define (cont)
(reset-at tag
(let ([r (begin body0 body ...)])
;; normal return:
(set! cont (lambda () r))
r))))
(lambda () (cont))))
(define-syntax define-generator (define stop-value (gensym))
(define-sequence-syntax in-generator
(syntax-rules () (syntax-rules ()
[(_ (name args ...) body0 bodies ...) [(_ body0 body ...)
(define name (lambda-generator (args ...) body0 bodies ...))])) (in-producer (generator body0 body ... stop-value) stop-value)])
(lambda (stx)
(syntax-case stx ()
[((id ...) (_ body0 body ...))
#'[(id ...)
(in-producer (generator body0 body ... stop-value) stop-value)]])))
#| #|
;; example ;; examples
(define-generator (blah) (for/list ([i (in-generator (for-each yield '(1 2 3)) (yield 'four))]) i)
(for ([x (in-range 0 10)]) (for*/list ([i (in-generator (for-each yield '(1 2 3)) (yield 'four))]
(yield x))) [j (in-generator (yield 'X) (yield '-))])
(list i j))
|# |#