structured-loops.rkt
#lang scheme/base
(provide until while)
#| Loops Repeating Statements by Condition.

 Two types of effect of the condition.
  (while <pre-condition>  . _): continue  if precondition  true
  (until <post-condition> . _): break out if postcondition true

 An 'until' loop has a value: the logically positive value of the postcondition.

 Commonest form of compound condition.
  (while (and <pre-condition>  ...) . _): continue  if all  preconditions true
  (until (or  <post-condition> ...) . _): break out if some postcondition true,
   with that postcondition's value
 Post-processing based on which subcondition of compound condition ended loop:
   (while (and (<pre-condition>  else <result> ...)
               ...)
    . _)
   (until (or  (<post-condition> then <result> ...)
               ...)
    . _)
  Value of loop is value of  <result> ... . |#

(define-syntax until
  (syntax-rules (or then)
    [(until (or (<post-condition> then <result> ...)
                ...)
            <statement> ...)
     (let/cc result
       (letrec ([loop (λ () (cond [<post-condition>
                                   (result (let () <result> ...))]
                                  ...
                                  [else <statement> ... (loop)]))])
         (loop)))]
    [(until <post-condition> <statement> ...)
     (letrec ([loop (λ () (unless <post-condition>
                            <statement> ... (loop)))])
       (loop))]))

(define-syntax while
  (syntax-rules (and else)
    [(while (and (<pre-condition> else <result> ...)
                 ...)
            <statement> ...)
     (until (or ((not <pre-condition>) then <result> ...)
                ...)
            <statement> ...)]
    [(while <pre-condition> <statement> ...)
     (until (not <pre-condition>) <statement> ...)]))