goof-loop/ref-let.scm
Linus 2d35c9d6cf Polishing the README and iterator protocol.
* README.md: added some small documentation and loop expansion.
 * goof.scm: Changed the iterator protocol to not use unnecessary :acc and :fors.
 * iterators.scm: see above.
 * ref-let.scm: a new macro to allow multiple values and pattern matching to co-exist for body-bindings.
2020-12-16 19:54:55 +01:00

51 lines
1.6 KiB
Scheme

(define-module (ref-let)
#:export (ref-let)
#:use-module (ice-9 match)
#:use-module (srfi srfi-71))
(define-syntax ref-let
(syntax-rules ()
((ref-let ids body ...)
(rl () () ids body ...))))
(define-syntax rl
(syntax-rules (values)
;; emit simple case, no match
((_ (lets ...) () () body ...)
(let (lets ...)
body ...))
;; emit, hard case.
((rl (lets ...) (matches ...) () body ...)
(let (lets ...)
(match-let (matches ...)
body ...)))
;; a (values ...) clause:
((rl (l ...) m (((values . v) expr) . clause-rest) . body)
(rl (l ... ((values . v) expr)) m clause-rest . body))
;; Simple cases
;; (rl ((a 5)) () (((b . _) (cons 1 2))) (+ a b))
((_ (l ...) (m ...) (((p . p-rest) expr) . clause-rest) body ...)
(rl (l ... (dummy expr)) (m ... ((p . p-rest) dummy)) clause-rest body ...))
((rl (l ...) (m ...) ((binding expr) . clause-rest) body ...)
(rl (l ... (binding expr)) (m ...) clause-rest body ...))
;; More than one id
((rl l m ((id id* ... expr) . clause-rest) . body)
(extract () () (id id* ... expr) l m clause-rest . body))))
(define-syntax extract
(syntax-rules ()
((_ let-binding (match-bindings ...) () (l ...) (m ...) clauses . body)
(rl (l ... let-binding) (m ... match-bindings ...) clauses . body))
((_ (lb ...) mb (expr) . rest)
(extract (lb ... expr) mb () . rest))
;; Pattern
((_ (lb ...) (mb ...) ((p . p-rest) ids ...) . rest)
(extract (lb ... dummy) (mb ... ((p . p-rest) dummy)) (ids ...) . rest))
((_ (lb ...) mb (id ids ...) . rest)
(extract (lb ... id) mb (ids ...) . rest))))