diff --git a/collects/scheme/generator.ss b/collects/scheme/generator.ss index a59bf9414e..b9a9e83737 100644 --- a/collects/scheme/generator.ss +++ b/collects/scheme/generator.ss @@ -6,9 +6,9 @@ (provide yield generator in-generator) -(define-syntax-parameter yield - (lambda (stx) - (raise-syntax-error #f "yield is only bound inside a sequence generator"))) +;; (define-syntax-parameter yield +;; (lambda (stx) +;; (raise-syntax-error #f "yield is only bound inside a sequence generator"))) ;; (define (procedure->generator proc) ;; (define tag (make-continuation-prompt-tag)) @@ -20,18 +20,44 @@ ;; r))) ;; (lambda () (cont))) +(define current-yielder + (make-parameter + (lambda (v) + (error 'yield "yield cannot be called when no generator is active")))) + +(define (yield value) + ((current-yielder) value)) + +(define yield-tag (make-continuation-prompt-tag)) + +(define-syntax-rule (generator body0 body ...) + (let () + (define (cont) + (define (yielder value) + (shift-at yield-tag k (set! cont k) value)) + (reset-at yield-tag + (parameterize ([current-yielder yielder]) + (let ([retval (begin body0 body ...)]) + ;; normal return: + (set! cont (lambda () retval)) + retval)))) + (define (generator) (cont)) + generator)) + +;; not using parameterization +#; (define-syntax-rule (generator body0 body ...) (let ([tag (make-continuation-prompt-tag)]) (define yielder (let ([yield (lambda (value) (shift-at tag k (set! cont k) value))]) yield)) (splicing-syntax-parameterize ([yield (make-rename-transformer #'yielder)]) - (define (cont) - (reset-at tag - (let ([retval (begin body0 body ...)]) - ;; normal return: - (set! cont (lambda () retval)) - retval)))) + (define (cont) + (reset-at tag + (let ([retval (begin body0 body ...)]) + ;; normal return: + (set! cont (lambda () retval)) + retval)))) (define (generator) (cont)) generator)) diff --git a/collects/tests/mzscheme/for.ss b/collects/tests/mzscheme/for.ss index 8084d4ad03..dbb5b4973f 100644 --- a/collects/tests/mzscheme/for.ss +++ b/collects/tests/mzscheme/for.ss @@ -222,4 +222,22 @@ (for/list ([(x i) (in-indexed (in-generator (yield 1) (yield 2) (yield 3)))]) (list x i))) +(let ([helper (lambda (i) + (yield (add1 i)))]) + (test '(1 2 3) 'parameterized-yield + (for/list ([x (in-generator (helper 0) (helper 1) (helper 2))]) + x))) + +(let* ([helper (lambda (pred num) + (for ([i (in-range 0 3)]) + (yield (pred (+ i num)))))] + [g1 (generator + (helper odd? 1) + (yield 'odd))] + [g2 (generator + (helper even? 1) + (yield 'even))]) + (test '(#t #f #f #t #t #f odd even) 'yield-helper + (list (g1) (g2) (g1) (g2) (g1) (g2) (g1) (g2)))) + (report-errs)