-
Notifications
You must be signed in to change notification settings - Fork 1
/
expand.scm
144 lines (125 loc) · 3.43 KB
/
expand.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
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
; expand.scm
(define (die msg)
(begin
(display msg)
(exit)))
(define (let-get-vars let-args)
(if (null? let-args)
(list)
(cons (caar let-args)
(let-get-vars (cdr let-args)))))
(define (let-get-vars-value let-args)
(if (null? let-args)
(list)
(cons (cadar (expand let-args))
(let-get-vars-value (cdr let-args)))))
(define (expand-cond body)
(if (and (pair? body) (pair? (car body)))
(if (eq? (caar body) 'else)
(expand (cadar body))
(if (pair? (cdr body))
(list
'if
(expand (caar body))
(expand (cadar body))
(expand-cond (cdr body)))
(list
'if
(expand (caar body))
(expand (cadar body)))))))
(define (expand-and body)
(if (pair? body)
(if (pair? (cdr body))
(list
'if
(expand (car body))
(expand-and (cdr body))
(expand (car body)))
(list
'if
(expand (car body))
(expand (car body))
#f))))
(define (expand-or body)
(if (pair? body)
(if (pair? (cdr body))
(list
'if
(expand (car body))
(expand (car body))
(expand-or (cdr body)))
(list
'if
(expand (car body))
(expand (car body))
#f))))
(define (expand-let* vars exprs body)
(if (and (pair? vars) (pair? exprs))
(append (list
(list
'lambda
(list (car vars))
(expand-let*
(cdr vars)
(cdr exprs)
body))
(car exprs)))
body))
(define (expand-root ast)
(if (pair? ast)
(cons (expand (car ast))
(expand-root (cdr ast)))
(list)))
(define (expand ast)
(if (not (pair? ast))
ast
(cond
((eq? (car ast) 'if)
(if
(or
(< (length (cdr ast)) 2)
(> (length (cdr ast)) 3))
(die "Ill formed if\n")
(cons (expand (car ast))
(expand-root (cdr ast)))))
((eq? (car ast) 'lambda)
(if
(not (= (length (cdr ast)) 2))
(die "Ill formed lambda definition\n")
; TODO: check arguments list sanity.
(cons (expand (car ast))
(expand-root (cdr ast)))))
((eq? (car ast) 'define)
(if
(not (= (length (cdr ast)) 2))
(die "Ill formed define\n")
(if (pair? (cadr ast))
(if (= (length (cadr ast)) 0)
(die "Ill formed special define\n")
(list
'define
(caadr ast)
(list 'lambda (cdadr ast) (expand (caddr ast)))))
(cons (expand (car ast))
(expand-root (cdr ast))))))
((eq? (car ast) 'let)
(append (list (list 'lambda
(let-get-vars (cadr ast))
(append (list 'begin)
(expand-root (cddr ast)))))
(let-get-vars-value (cadr ast))))
((eq? (car ast) 'let*)
(expand-let*
(let-get-vars (cadr ast))
(let-get-vars-value (cadr ast))
(append
(list 'begin)
(expand-root (cddr ast)))))
((eq? (car ast) 'cond)
(expand-cond (cdr ast)))
((eq? (car ast) 'and)
(expand-and (cdr ast)))
((eq? (car ast) 'or)
(expand-or (cdr ast)))
(else (cons (expand (car ast))
(expand-root (cdr ast)))))))