1;;
2;; SRFI-5: A compatible let form with signatures and rest arguments
3;;
4
5;; This implementation is based on Andy Gaynor's reference implementation.
6
7(define-module srfi-5
8  (export let))
9(select-module srfi-5)
10
11(define-syntax let
12  (syntax-rules ()
13    ;; standard-compatible lambdas.
14    ((let () body ...)
15     ((lambda () body ...)))
16    ((let ((var val) ...) body ...)
17     ((lambda (var ...) body ...) val ...))
18
19    ;; let with rest parameter
20    ((let ((var val) . bindings) body ...)
21     (%let-loop #f bindings (var) (val) (body ...)))
22
23    ;; signature-style name.
24    ((let (name binding ...) body ...)
25     (%let-loop name (binding ...) () () (body ...)))
26
27    ;; standrad named let (which may have rest parameter)
28    ((let name bindings body ...)
29     (%let-loop name bindings () () (body ...)))
30
31    ;; error
32    ((let . _)
33     (syntax-error "malformed let:" (let . _)))
34    ))
35
36;; aux macro to collect bindings
37(define-syntax %let-loop
38  (syntax-rules ()
39    ((%let-loop name ((var0 val0) binding ...) (var ...) (val ...) body)
40     (%let-loop name (binding ...) (var ... var0) (val ... val0) body))
41
42    ;; rest binding, no name
43    ((%let-loop #f (rest-var rest-val ...) (var ...) (val ...) body)
44     ((lambda (var ... . rest-var) . body) val ... rest-val ...))
45
46    ;; no bindings, named
47    ((%let-loop name () (var ...) (val ...) body)
48     ((letrec ((name (lambda (var ...) . body)))
49        name)
50      val ...))
51
52    ;; rest binding, named
53    ((%let-loop name (rest-var rest-val ...) (var ...) (val ...) body)
54     ((letrec ((name (lambda (var ... . rest-var) . body)))
55        name)
56      val ... rest-val ...))))
57
58