(module loops mzscheme
(provide loop loop-stx
loop->syntax
(rename checked-make-loop make-loop)
loop? )
(let (<ob>*) <oc>* (let loop (<lb>*) (if <ne1?> (let (<ib>*) <ic>* <payload> (if <ne2?> (loop <ls>*))))))
(define-struct loop (stx))
(define (checked-make-loop stx)
(define (check-values-bindings stx)
(syntax-case stx ()
[(((name ...) expr) ...)
(begin
(unless (andmap identifier? (syntax->list #'(name ... ...)))
(raise-syntax-error
'make-loop "expected list of bindings, got: " stx)))]))
(define (check-bindings stx)
(syntax-case stx ()
[((name expr) ...)
(begin
(unless (andmap identifier? (syntax->list #'(name ...)))
(raise-syntax-error
'make-loop "expected list of bindings, got: " stx)))]))
(define (check-list-of stx what)
(syntax-case stx ()
[(x ...) 'ok]
[_ (raise-syntax-error
'make-loop (format "expected list of ~a, got: " what) stx)]))
(syntax-case stx ()
[(ob* oc* lb* ne1 ib* ic* ne2 ls*)
(begin
(check-values-bindings #'ob*)
(check-values-bindings #'ib*)
(check-list-of #'oc* "outer commands")
(check-list-of #'ic* "inner commands")
(check-list-of #'ls* "loop steppers"))]
[_else
(raise-syntax-error
'make-loop
"expected (ob* oc* lb* ne1 ib* ic* ne2 ls*), got: " stx)])
(make-loop stx))
(let loop (<lb>*)
(if <ne1?>
(loop <ls>*)))
(require-for-template mzscheme)
(require-for-template "simplifier.scm")
(define (loop->syntax src-stx l payload)
(syntax-case (loop-stx l) ()
[((ob ...) (oc ...) (lb ...) ne1 (ib ...) (ic ...) ne2 (ls ...))
(with-syntax ([payload payload])
(syntax/loc src-stx
(let-values (ob ...)
oc ...
(let loop (lb ...)
(ec-simplify
(if ne1
(let-values (ib ...)
ic ...
(ec-simplify payload)
(ec-simplify
(if ne2
(loop ls ...))))))))))]))
)