-
Notifications
You must be signed in to change notification settings - Fork 1
/
struct-syntax.scm
49 lines (43 loc) · 1.5 KB
/
struct-syntax.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
(import-for-syntax matchable)
(import-for-syntax srfi-1)
(define-syntax define-struct
(syntax-rules ()
((define-struct name (fields ...))
(define-record name fields ...))))
(define-syntax struct-case
(lambda (e r c)
(let* ((%begin (r 'begin))
(%if (r 'if))
(%let (r 'let))
(%block-ref (r '##sys#block-ref))
(%structure? (r '##sys#structure?)))
(define (generate-bindings v fields i)
(match fields
(() '())
((x . x*)
(cons `(,x (,%block-ref ,v ,i)) (generate-bindings v x* (+ i 1))))))
(define (generate-body v clauses)
(match clauses
(() `(error 'struct-case "unmatched " ,v))
((('else expr expr* ...))
`(,%begin ,expr ,@expr*))
((((name fields* ...) expr expr* ...) clause* ...)
(let ((bindings (generate-bindings v fields* 1))
(altern (generate-body v clause*)))
`(,%if (,%structure? ,v ',name)
(,%let ,bindings
,expr ,@expr*)
,altern)))))
(match e
((_ expr clause* ...)
(let* ((v (gensym))
(body (generate-body v clause*)))
`(,%let ((,v ,expr)) ,body)))))))
(define-syntax struct-let*
(syntax-rules ()
((struct-let* () body* ...)
(begin body* ...))
((struct-let* ((pat v) cls* ...) body* ...)
(struct-case v
(pat
(struct-let* (cls* ...) body* ...))))))