; intersecting number wheels
(define-syntax define-generator
(lambda (x)
(syntax-case x (lambda)
((stx name (lambda formals e0 e1 ...))
(with-syntax ((yield (datum->syntax (syntax stx) 'yield)))
(syntax (define name
(lambda formals
(let ((resume #f) (return #f))
(define yield
(lambda args
(call-with-current-continuation
(lambda (cont)
(set! resume cont)
(apply return args)))))
(lambda ()
(call-with-current-continuation
(lambda (cont)
(set! return cont)
(cond (resume (resume))
(else (let () e0 e1 ...)
(error 'name "unexpected return"))))))))))))
((stx (name . formals) e0 e1 ...)
(syntax (stx name (lambda formals e0 e1 ...)))))))
(define (cycle xs)
(define (last-pair xs)
(if (null? (cdr xs)) xs
(last-pair (cdr xs))))
(set-cdr! (last-pair xs) xs) xs)
(define (take-gen n gen)
(let loop ((n n) (gs (list)))
(if (zero? n) (reverse gs)
(loop (- n 1) (cons (gen) gs)))))
(define-generator (wheel xs)
(let loop ((ws (cycle xs)))
(if (integer? (car ws))
(yield (car ws))
(yield ((eval (car ws)))))
(loop (cdr ws))))
(define a (wheel '(1 2 3)))
(display (take-gen 20 a)) (newline)
(define a (wheel '(1 b 2)))
(define b (wheel '(3 4)))
(display (take-gen 20 a)) (newline)
(define a (wheel '(1 d d)))
(define d (wheel '(6 7 8)))
(display (take-gen 20 a)) (newline)
(define a (wheel '(1 b c)))
(define b (wheel '(3 4)))
(define c (wheel '(5 b)))
(display (take-gen 20 a)) (newline)