#lang racket
(provide until while
continue break)
(define-syntax while
(syntax-rules (and else)
[(while (and (<sub-condition> else
<result-statement>
...)
...)
<body-statement>
...)
(until (or ((not <sub-condition>) then
<result-statement>
...)
...)
<body-statement>
...)]
[(while <pre-condition>
<body-statement>
...)
(while (and (<pre-condition> else))
<body-statement>
...)]))
(require racket/stxparam)
(define-for-syntax (error-use stx)
(raise-syntax-error
#f "can only be used inside 'until' or 'while' body"
stx))
(define-syntax-parameter break error-use)
(define-syntax-parameter continue error-use)
(define-syntax until
(syntax-rules (or)
[(until (or <alternative>
...)
<body-statement>
...)
(let/ec brk
(let loop ()
(cond [(or-then <alternative> ...)]
[else (let/ec cntn
(syntax-parameterize
([continue (make-rename-transformer #'cntn)]
[break (make-rename-transformer #'brk)])
<body-statement> ...))
(loop)])))]
[(until <post-condition>
<body-statement>
...)
(until (or <post-condition>)
<body-statement>
...)]))
(define-syntax or-then
(syntax-rules (then)
[(or-then (<condition> then
<result>
...)
<clause>
...)
(cond [<condition> <result> ...]
[else (or-then <clause> ...)])]
[(or-then <condition>
<clause>
...)
(or-then (<condition> then)
<clause>
...)]
[(or-then)
#f]))