-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmacros.rkt
212 lines (197 loc) · 8.19 KB
/
macros.rkt
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#lang racket
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Transform functions for essential macros.
(require "data.rkt"
"mutrec.rkt")
(provide let*-tf cond-tf case-tf delay-tf
cons-limit quote-tf quasiquote-tf do-tf
recur-tf
special primitive syntax-err
set-cons-limit!)
(define special (string->symbol "#special"))
(define primitive (string->symbol "#primitive"))
(define syntax-err
(lambda (context expr format . args)
(newline)
#;(when expr (limited-pretty-print expr 4))
(apply error 'syntax
(string-append "Syntax Error~a~a"
(if (zero? (string-length format))
""
": ")
format)
(if (empty-context? context) "" " ")
(if (empty-context? context) "" (pcontext context))
args)))
;(export (cons-limit
; let*-tf cond-tf case-tf quote-tf quasiquote-tf do-tf)
(define let*-tf
(lambda (let-expr env context)
(match let-expr
[`(,_ () . ,body)
`(,primitive let () ,@body)]
[`(,_ ((,(? symbol? s) ,exp)) . ,body)
`(,primitive let ((,s ,exp)) ,@body)]
[`(,k ((,(? symbol? s) ,exp) ,rest ...) . ,body)
`(,primitive let ((,s ,exp)) (,k ,rest ,@body))])))
(define cond-tf
(lambda (cond-expr env context)
(let loop ((e (cdr cond-expr)))
(match e
[`() `((,primitive void))]
[`[(else ,b1 . ,body)] `(,primitive begin ,b1 ,@body)]
[`((else . ,_) . ,_)
(syntax-err context cond-expr "invalid cond expression")]
[`((,test => ,proc) . ,rest)
(let ((g (gensym)))
`(,primitive let ((,g ,test))
(,primitive if ,g (,proc ,g) ,(loop rest))))]
[`((#t ,b1 . ,body)) `(,primitive begin ,b1 ,@body)] ; only diff from Chez?
[`((,test) . ,rest) `(,primitive or ,test ,(loop rest))]
[`((,test . ,body) . ,rest)
`(,primitive if ,test (,primitive begin ,@body) ,(loop rest))]
[_ (syntax-err context cond-expr "invalid cond expression")]))))
(define recur-tf
(lambda (rec-expr env context)
(match rec-expr
[`(recur ,name ([,id ,e] ...) ,body ...)
`(letrec ([,name (lambda ,id ,@body)])
(,name ,@e))]
[_ (syntax-err context rec-expr "invalid recur expression")])))
(define case-tf
(lambda (case-expr env context)
(let loop ((e (cdr case-expr)))
(match e
[`(,exp) `(,primitive begin ,exp ((,primitive void)))]
[`(,exp (else ,b1 . ,body)) `(,primitive begin ,b1 ,@body)]
[`(,exp (else . ,_) . ,_)
(syntax-err context case-expr "invalid case expression")]
[`(,(? symbol? exp) (,(? list? test) ,b1 . ,body) . ,rest)
`(,primitive if ((,primitive memv) ,exp (,primitive quote ,test))
(,primitive begin ,b1 ,@body)
,(loop (cons exp rest)))]
[`(,(? symbol? exp) (,test ,b1 . ,body) . ,rest)
`(,primitive if ((,primitive memv) ,exp (,primitive quote (,test))) ; Chez extension
(,primitive begin ,b1 ,@body)
,(loop (cons exp rest)))]
[(cons exp rest)
(if (not (symbol? exp))
(let ((g (gensym)))
`(,primitive let ((,g ,exp))
,(loop (cons g rest))))
(syntax-err context case-expr "invalid case expression"))]
[_ (syntax-err context case-expr "invalid case expression")]))))
(define delay-tf
(lambda (delay-expr env context)
(match delay-expr
[(list _ exp)
`((,primitive make-promise) (,primitive lambda () ,exp))]
[_ (syntax-err context delay-expr "invalid delay expression")])))
(define cons-limit 8)
(define (set-cons-limit! v) (set! cons-limit v))
(define quote-tf
(lambda (exp env context)
(letrec ((qloop
(match-lambda
((? vector? q) `((,special qvector) ,@(map qloop (vector->list q))))
((? box? q) `((,special qbox) ,(qloop (unbox q))))
((? symbol? q) `(,special quote ,q))
((? null? q) q)
((? list? q)
(if (< (length q) cons-limit)
`((,special qcons) ,(qloop (car q)) ,(qloop (cdr q)))
`((,special qmerge-list) ,@(map qloop q))))
((cons x y) `((,special qcons) ,(qloop x) ,(qloop y)))
((? boolean? q) q)
((? number? q) q)
((? char? q) q)
((? string? q) q)
(q (syntax-err context exp "invalid quote expression at ~a" q)))))
(match exp
(`(quote ,q) (qloop q))
((? vector? q) (qloop q))
((? box? q) (qloop q))))))
(define quasiquote-tf
(lambda (exp env context)
(letrec ((make-cons
(lambda (x y)
(cond ((null? y) `(,(primitive 'list) ,x))
((and (pair? y) (equal? (car y) (primitive 'list)))
(cons (car y) (cons x (cdr y))))
(else `(,(primitive 'cons) ,x ,y)))))
(qloop
(lambda (e n)
(match e
[`(quasiquote ,e)
(make-cons 'quasiquote (qloop `(,e) (+ 1 n)))]
[(list 'unquote e)
(if (zero? n)
e
(make-cons 'unquote (qloop `(,e) (- n 1))))]
[`(unquote-splicing ,e)
(if (zero? n)
e
(make-cons 'unquote-splicing (qloop `(,e) (- n 1))))]
[(cons (list 'unquote-splicing e) y)
(=> fail)
(if (zero? n)
(if (null? y)
e
`(,(primitive 'append) ,e ,(qloop y n)))
(fail))]
[(? box? q) `(,(primitive 'box) ,(qloop (unbox q) n))]
[(? symbol? q)
(if (memq q '(quasiquote unquote unquote-splicing))
(syntax-err context exp
"invalid use of ~a inside quasiquote" q)
`(quote ,q))]
[(? null? q) q]
[(cons x y) (make-cons (qloop x n) (qloop y n))]
[(? vector? q) `(,(primitive 'vector)
,@(map (lambda (z) (qloop z n))
(vector->list q)))]
[(? boolean? q) q]
[(? number? q) q]
[(? char? q) q]
[(? string? q) q]
[q (syntax-err context exp
"invalid quasiquote expression at ~a" q)]))))
(match exp
(`(quasiquote ,q) (qloop q 0))))))
(define do-tf
(lambda (do-expr env context)
(let loop ((e (cdr do-expr)))
(match e
; (((var init . step) ...) (e0 e1 ...) c ...)
[(list-rest (? list? vis) (cons e0 (? list? e1)) (? list? c))
(if (andmap (match-lambda
[(list-rest _ _ _) #t]
[_ #f])
vis)
(let* ((var (map car vis))
(init (map cadr vis))
(step (map cddr vis))
(step (map (lambda (v s)
(match s
[`() v]
[`(,e) e]
[_ (syntax-err context do-expr
"invalid do expression")]))
var
step)))
(let ((doloop (gensym)))
(match e1
['()
`(let ,doloop ,(map list var init)
(if (not ,e0)
(begin ,@c (,doloop ,@step) (void))
(void)))]
[(list body0 body ...)
`(let ,doloop ,(map list var init)
(if ,e0
(begin ,body0 ,@body)
(begin ,@c (,doloop ,@step))))]
[_ (syntax-err context do-expr "invalid do expression")])))
(syntax-err context do-expr "invalid do expression"))]
(_ (syntax-err context do-expr "invalid do expression"))))))
;)