This repository has been archived by the owner on Apr 17, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
qq.scm
107 lines (98 loc) · 2.82 KB
/
qq.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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
;;; qq.scm
;;; A naive, one-level quasiquote implementation + optimizations
;;;
;;; Programmer: Mayer Goldberg, 2016
(load "pattern-matcher.scm")
;;;
(define ^quote?
(lambda (tag)
(lambda (e)
(and (pair? e)
(eq? (car e) tag)
(pair? (cdr e))
(null? (cddr e))))))
(define quote? (^quote? 'quote))
(define unquote? (^quote? 'unquote))
(define unquote-splicing? (^quote? 'unquote-splicing))
(define const?
(let ((simple-sexprs-predicates
(list boolean? char? number? string?)))
(lambda (e)
(or (ormap (lambda (p?) (p? e))
simple-sexprs-predicates)
(quote? e)))))
(define quotify
(lambda (e)
(if (or (null? e)
(pair? e)
(symbol? e)
(vector? e))
`',e
e)))
(define unquotify
(lambda (e)
(if (quote? e)
(cadr e)
e)))
(define const-pair?
(lambda (e)
(and (quote? e)
(pair? (cadr e)))))
(define expand-qq
(letrec ((expand-qq
(lambda (e)
(cond ((unquote? e) (cadr e))
((unquote-splicing? e)
(error 'expand-qq
"unquote-splicing here makes no sense!"))
((pair? e)
(let ((a (car e))
(b (cdr e)))
(cond ((unquote-splicing? a)
`(append ,(cadr a) ,(expand-qq b)))
((unquote-splicing? b)
`(cons ,(expand-qq a) ,(cadr b)))
(else `(cons ,(expand-qq a) ,(expand-qq b))))))
((vector? e) `(list->vector ,(expand-qq (vector->list e))))
((or (null? e) (symbol? e)) `',e)
(else e))))
(optimize-qq-expansion (lambda (e) (optimizer e (lambda () e))))
(optimizer
(compose-patterns
(pattern-rule
`(append ,(? 'e) '())
(lambda (e) (optimize-qq-expansion e)))
(pattern-rule
`(append ,(? 'c1 const-pair?) (cons ,(? 'c2 const?) ,(? 'e)))
(lambda (c1 c2 e)
(let ((c (quotify `(,@(unquotify c1) ,(unquotify c2))))
(e (optimize-qq-expansion e)))
(optimize-qq-expansion `(append ,c ,e)))))
(pattern-rule
`(append ,(? 'c1 const-pair?) ,(? 'c2 const-pair?))
(lambda (c1 c2)
(let ((c (quotify (append (unquotify c1) (unquotify c2)))))
c)))
(pattern-rule
`(append ,(? 'e1) ,(? 'e2))
(lambda (e1 e2)
(let ((e1 (optimize-qq-expansion e1))
(e2 (optimize-qq-expansion e2)))
`(append ,e1 ,e2))))
(pattern-rule
`(cons ,(? 'c1 const?) (cons ,(? 'c2 const?) ,(? 'e)))
(lambda (c1 c2 e)
(let ((c (quotify (list (unquotify c1) (unquotify c2))))
(e (optimize-qq-expansion e)))
(optimize-qq-expansion `(append ,c ,e)))))
(pattern-rule
`(cons ,(? 'e1) ,(? 'e2))
(lambda (e1 e2)
(let ((e1 (optimize-qq-expansion e1))
(e2 (optimize-qq-expansion e2)))
(if (and (const? e1) (const? e2))
(quotify (cons (unquotify e1) (unquotify e2)))
`(cons ,e1 ,e2))))))))
(lambda (e)
(optimize-qq-expansion
(expand-qq e)))))