-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathast.rkt
72 lines (64 loc) · 1.93 KB
/
ast.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
#lang racket
(provide ast-prim ast-block ast-bind ast-let)
(provide ast-prim? ast-block? ast-bind? ast-let?)
(provide ast-prim-name ast-block-body ast-bind-name
ast-bind-body ast-let-name ast-let-arg ast-let-body)
(provide subst)
#|
type Expr = Word*
type Word
= Prim String
| Int
| Var
| Block Expr
| Bind Var Expr
| Let Var Expr Expr
Int = racket int
Var = racket string
Prim = struct ast-prim
Block = struct ast-block
Bind = struct ast-bind
Let = struct ast-let
|#
(struct ast-prim (name) #:transparent)
(struct ast-block (body) #:transparent)
(struct ast-bind (name body) #:transparent)
(struct ast-let (name arg body) #:transparent)
;; subst :: Var, Expr, Expr -> Expr
;; Substitutes the expression 'rep' for every free
;; occurrence of the variable 'name' in the target
;; expression 'target'.
;; We cannot simply replace 'name' with the substituted
;; expression; rather we must concatenate it with the expressions
;; on either side (since our expressions are lists, not trees).
;; That's why we have 'flatten'.
(define (subst name rep target)
(define (flatten ls)
(match ls
[(list)
(list)]
[(list (list se ...) e ...)
(append se (flatten e))]
[(list x e ...)
(cons x (flatten e))]))
(define (subst-rec t)
(cond
[(list? t)
(flatten (map (lambda (x) (subst-rec x)) t))]
[(string? t)
(if (equal? name t) rep t)]
[(ast-block? t)
(ast-block (subst-rec (ast-block-body t)))]
[(ast-bind? t)
(ast-bind (ast-bind-name t)
(if (equal? name (ast-bind-name t))
(ast-bind-body t)
(subst-rec (ast-bind-body t))))]
[(ast-let? t)
(ast-let (ast-let-name t)
(subst-rec (ast-let-arg t))
(if (equal? name (ast-let-name t))
(ast-let-body t)
(subst-rec (ast-let-body t))))]
[#t t]))
(subst-rec target))