@@ -156,7 +156,6 @@ accumulator-functions in Redex.
156
156
157
157
Now α equivalence is straightforward:
158
158
159
-
160
159
@code-from-file["code/mon-aft.rkt "
161
160
#rx"determines whether e_1 and e_2 are α equivalent "
162
161
#:exp-count 3 ]
@@ -165,6 +164,7 @@ Now α equivalence is straightforward:
165
164
@; -----------------------------------------------------------------------------
166
165
@section{Extending a Language: @racket[any ]}
167
166
167
+
168
168
Suppose we wish to extend @racket[Lambda] with @racket[if ] and Booleans,
169
169
like this:
170
170
@;%
@@ -178,7 +178,7 @@ like this:
178
178
(if e e e)))
179
179
))
180
180
@;%
181
- Guess what? @racket[(term (fv (lambda (x y) (if x y false ))))] doesn't
181
+ Guess what? @racket[(term (sd (lambda (x y) (if x y false ))))] doesn't
182
182
work because @racket[false ] and @racket[if ] are not covered.
183
183
184
184
We want metafunctions that are as generic as possible for computing such
@@ -187,45 +187,11 @@ equivalences.
187
187
188
188
Redex contracts come with @racket[any ] and Redex patterns really are over
189
189
Racket's S-expressions. This definition now works for extensions that don't
190
- add binders:
191
- @;%
192
- @(begin
193
- #reader scribble/comment-reader
194
- (racketblock
195
- (module+ test
196
- (test-equal (SD? sd1) #true ))
197
-
198
- (define-metafunction SD
199
- sd : e -> e
200
- [(sd e) (sd/a e ())])
201
-
202
- (module+ test
203
- (test-equal (term (sd/a x ())) (term x))
204
- (test-equal (term (sd/a x (y z x))) (term (K 2 )))
205
- (test-equal (term (sd/a ((lambda (x) x) (lambda (y) y)) ()))
206
- (term ((lambda (K 0 )) (lambda (K 0 )))))
207
- (test-equal (term (sd/a (lambda (x) (x (lambda (y) y))) ()))
208
- (term (lambda ((K 0 ) (lambda (K 0 ))))))
209
- (test-equal (term (sd/a (lambda (z) (lambda (x) (x (lambda (y) z)))) ()))
210
- (term (lambda (lambda ((K 0 ) (lambda (K 2 ))))))))
211
-
212
- (define-metafunction SD
213
- sd/a : e (x ... ) -> e
214
- [(sd/a x (x_1 ... x x_2 ... ))
215
- ;; bound variable
216
- (K n)
217
- (where n ,(length (term (x_1 ... ))))
218
- (where #false (in x (x_1 ... )))]
219
- [(sd/a (lambda (x) e) (x_rest ... ))
220
- (lambda (sd/a e (x x_rest ... )))
221
- (where n ,(length (term (x_rest ... ))))]
222
- [(sd/a (e_fun e_arg) (x_rib ... ))
223
- ((sd/a e_fun (x_rib ... )) (sd/a e_arg (x_rib ... )))]
224
- [(sd/a any_1 (x ... ))
225
- ;; free variable or constant
226
- any_1])
227
- ))
228
- @;%
190
+ add binders:
191
+
192
+ @code-from-file["code/common.rkt "
193
+ #rx"define-extended-language SD Lambda "
194
+ #:exp-count 6 ]
229
195
230
196
@; -----------------------------------------------------------------------------
231
197
@section{Substitution}
@@ -234,49 +200,6 @@ The last thing we need is substitution, because it @emph{is} the syntactic
234
200
equivalent of function application. We define it with @emph{any } having
235
201
future extensions in mind.
236
202
237
- @;%
238
- @(begin
239
- #reader scribble/comment-reader
240
- (racketblock
241
- ;; (subst ([e x] ...) e_*) substitutes e ... for x ... in e_* (hygienically)
242
-
243
- (module+ test
244
- (test-equal (term (subst ([1 x][2 y]) x)) 1 )
245
- (test-equal (term (subst ([1 x][2 y]) y)) 2 )
246
- (test-equal (term (subst ([1 x][2 y]) z)) (term z))
247
- (test-equal (term (subst ([1 x][2 y]) (lambda (z) (lambda (w) (x y)))))
248
- (term (lambda (z) (lambda (w) (1 2 )))))
249
- (test-equal (term (subst ([1 x][2 y]) (lambda (z) (lambda (w) (lambda (x) (x y))))))
250
- (term (lambda (z) (lambda (w) (lambda (x) (x 2 )))))
251
- #:equiv =α/racket)
252
- (test-equal (term (subst ((2 x)) ((lambda (x) (1 x)) x)))
253
- (term ((lambda (x) (1 x)) 2 ))
254
- #:equiv =α/racket))
255
-
256
- (define-metafunction Lambda
257
- subst : ((any x) ... ) any -> any
258
- [(subst [(any_1 x_1) ... (any_x x) (any_2 x_2) ... ] x) any_x]
259
- [(subst [(any_1 x_1) ... ] x) x]
260
- [(subst [(any_1 x_1) ... ] (lambda (x) any_body))
261
- (lambda (x_new)
262
- (subst ((any_1 x_1) ... )
263
- (subst-raw (x_new x) any_body)))
264
- (where x_new ,(variable-not-in (term any_body) (term x)))]
265
- [(subst [(any_1 x_1) ... ] (any ... )) ((subst [(any_1 x_1) ... ] any ) ... )]
266
- [(subst [(any_1 x_1) ... ] any_*) any_*])
267
-
268
- (define-metafunction Lambda
269
- subst-raw : (x x) any -> any
270
- [(subst-raw (x_new x_) x_) x_new]
271
- [(subst-raw (x_new x_) x) x]
272
- [(subst-raw (x_new x_) (lambda (x) any ))
273
- (lambda (x) (subst-raw (x_new x_) any ))]
274
- [(subst-raw (x_new x_) (any ... ))
275
- ((subst-raw (x_new x_) any ) ... )]
276
- [(subst-raw (x_new x_) any_*) any_*])
277
-
278
- ))
279
- @;%
280
-
281
-
282
- }
203
+ @code-from-file["code/common.rkt "
204
+ #rx"substitutes e [.][.][.] for x [.][.][.] in e_[*] "
205
+ #:exp-count 3 ]
0 commit comments