;; Like c{plet}, but each subsequent pattern-datum pair is evaluated in an environment
;; with all previous matches bound.
;; <pre>
#|
(plet* ((p1 d1)
(p2 d2)
...
(pn dn))
e1
e2
...)
|#
;;</pre>
;; is equivalent to
;; <pre>
#|
(plet ((p1 d1))
(plet ((p2 d2))
...
(plet ((pn dn)
e1
e2
...)))).
|#
;; </pre>
;; @args ({(pattern datum)}) body
(define-syntax plet*
(er-macro-transformer
(lambda (expr rename compare)
(let ((pattern-pairs (cadr expr)) ; pattern-pairs := {(pattern_i datum_i)}
(body (cddr expr))) ; body of the plet* (everything after pattern-pairs)
(cond ((null? pattern-pairs) `(let () ,@body)) ; no patterns to match, i.e. (plet () body)
(else ; at least one pattern to match
`(plet ,(list (car pattern-pairs))
(plet* ,(cdr pattern-pairs)
,@body))))))))