79 | | (define %atomic |
80 | | ($or %string %char %digits %ident %list %tuple)) |
81 | | |
82 | | (define (char->symbol ch) |
83 | | (string->symbol (x->string ch))) |
84 | | |
85 | | (define %infixed |
86 | | (let1 %infix ($or ($one-of #[-+*/<>]) |
87 | | ($string "==") ($string "<=") ($string ">=")) |
88 | | ($do (item1 %atomic);($or %application %atomic)) ;%atomic) |
89 | | ; (seq ($do %ws |
90 | | ; (infix %infix) |
91 | | ; %ws |
92 | | ; (rest ($or %infixed %atomic)) |
93 | | ; ($return (cons infix rest)))) |
94 | | %ws |
95 | | (infix %infix) |
96 | | %ws |
97 | | (item2 %atomic);($or %application %atomic)) ;%atomic) |
98 | | (rest ($many ($do %ws |
99 | | (infix %infix) |
100 | | %ws |
101 | | (item %atomic);($or %application %atomic)) ;%atomic) |
102 | | ($return (list (char->symbol infix) item))))) |
103 | | ($return (let1 expr (append (list item1 (char->symbol infix) item2) |
104 | | (apply append rest)) |
105 | | (case (length expr) |
106 | | ((3) |
107 | | (list ':apply (second expr) (first expr) (third expr))) |
108 | | ((5) ; 優先度まだ |
109 | | (list ':apply (fourth expr) |
110 | | (list ':apply (second expr) (first expr) (third expr)) |
111 | | (fifth expr))) |
112 | | ))) |
113 | | ;(tag :infixed (append (list item1 (char->symbol infix) item2) |
114 | | ;(apply append rest)))) |
115 | | ))) |
116 | | ; (seq ($or ($do %ws |
117 | | ; (infix %infix) |
118 | | ; %ws |
119 | | ; (rest %infixed) |
120 | | ; ($return (cons infix rest))) |
121 | | ; ($do %ws |
122 | | ; (infix %infix) |
123 | | ; %ws |
124 | | ; (rest %atomic) |
125 | | ; ($return (list infix rest))) )) |
126 | | ; ($return (tag :infixed (cons elem1 seq)))))) |
127 | | |
169 | | (define %lambda |
170 | | ($do (($char #\\)) |
171 | | (vars ($my-sep-by %ident %ws)) |
172 | | %ws |
173 | | (($string "->")) |
174 | | %ws |
175 | | (body ($or %do %infixed %application %expr)) |
176 | | ($return (tag ':lambda (list vars body))))) |
177 | | |
178 | | (define %assignment |
179 | | ($do (id %ident) |
180 | | %ws |
181 | | (($string "<-")) |
182 | | %ws |
183 | | (value ($or %infixed %application %expr)) |
184 | | ($return `(:assign ,id ,value)) |
185 | | )) |
186 | | |
187 | | (define %do |
188 | | (let1 %do-line-separator ($seq %ws ($or ($seq newline ($string " ")) ($char #\;)) %ws) |
189 | | ($do (($string "do")) |
190 | | %ws |
191 | | (exprs ($or ($between ($seq ($char #\{) %ws) |
192 | | ($my-sep-by ($or %assignment %infixed %application %expr) |
193 | | ($seq %ws ($char #\;) ($optional ($seq newline ($string " "))) %ws)) |
194 | | ($seq %ws ($char #\}))) |
195 | | ($my-sep-by ($or %assignment %infixed %application %expr) |
196 | | ($seq newline ($string " ") %ws)) )) |
197 | | ($return `(:do ,@exprs))))) |
198 | | |
199 | | (define %defun |
200 | | ($do (id %ident) |
201 | | %ws |
202 | | (args ($my-sep-by %ident %ws)) |
203 | | %ws |
204 | | (($char #\=)) |
205 | | %ws |
206 | | (rightside ($or %do %infixed %application %expr)) |
207 | | ($return `(:defun (,id ,@args) ,rightside)) |
208 | | )) |
209 | | |
210 | | (define %pattern |
211 | | ($do (id %ident) |
212 | | %ws |
213 | | (args ($my-sep-by ($or %ident %digits) %ws)) |
214 | | %ws |
215 | | (($char #\=)) |
216 | | %ws |
217 | | (rightside ($or %do %infixed %application %expr)) |
218 | | ($return `(:pattern (,id ,@args) ,rightside)) |
219 | | )) |
220 | | |
223 | | ) |
224 | | ($or %comment %lambda %defun %pattern %assignment %infixed %if %application %expr |
225 | | %unknown |
226 | | newline) |
| 83 | |
| 84 | [%assignment ($do (id %ident) |
| 85 | %ws |
| 86 | (($string "<-")) |
| 87 | %ws |
| 88 | (value %application) |
| 89 | ($return `(:assign ,id ,value)) |
| 90 | )] |
| 91 | [%do-line-separator ($seq %ws ($or ($seq newline ($string " ")) ($char #\;)) %ws)] |
| 92 | [%do ($do (($string "do")) |
| 93 | %ws |
| 94 | (exprs ($or ($between ($seq ($char #\{) %ws) |
| 95 | ($my-sep-by ($or %assignment %application) |
| 96 | ($seq %ws ($char #\;) ($optional ($seq newline ($string " "))) %ws)) |
| 97 | ($seq %ws ($char #\}))) |
| 98 | ($my-sep-by ($or %assignment %application) |
| 99 | ($seq newline ($string " ") %ws)) )) |
| 100 | ($return `(:do ,@exprs)))] |
| 101 | |
| 102 | [%defun ($do (id %ident) |
| 103 | %ws |
| 104 | (args ($my-sep-by %ident %ws)) |
| 105 | %ws |
| 106 | (($char #\=)) |
| 107 | %ws |
| 108 | (rightside ($or %do %application)) |
| 109 | ($return `(:defun (,id ,@args) ,rightside)) |
| 110 | )] |
| 111 | [%pattern ($do (id %ident) |
| 112 | %ws |
| 113 | (args ($my-sep-by ($or %ident %digits) %ws)) |
| 114 | %ws |
| 115 | (($char #\=)) |
| 116 | %ws |
| 117 | (rightside ($or %do %application)) |
| 118 | ($return `(:pattern (,id ,@args) ,rightside)) |
| 119 | )] |
| 120 | |
| 121 | ) |
| 122 | ($or %defun %pattern %assignment %application %expr |
| 123 | %unknown) |
262 | | ; (print "HEVAL " exp) |
263 | | (cond [(null? exp) *undefined*] |
264 | | [(number? exp) exp] |
265 | | [(string? exp) exp] |
266 | | [(char? exp) exp] |
267 | | [(symbol? exp) (let1 val (lookup exp env) |
268 | | (if val (heval val env) *undefined*))] |
269 | | [else (match exp |
270 | | [(':$ . _) |
271 | | (let loop ([apps (map (lambda (e) (if (or (ident? e) (lambda? e)) |
272 | | (list ':apply e) e)) |
273 | | (cdr exp))]) |
274 | | (if (null? (cdr apps)) |
275 | | (heval (car apps) env) |
276 | | (heval (append (car apps) |
277 | | (list (loop (cdr apps)))) |
278 | | env) |
279 | | )) |
280 | | ] |
281 | | |
282 | | [(':apply f . _) |
283 | | (let ([f (cadr exp)] |
284 | | [args (cddr exp)]) |
285 | | (happly |
286 | | (if (symbol? f) f (heval (second exp) env)) |
287 | | (heval-map args env)) |
288 | | )] |
289 | | |
290 | | [(':assign x y) ; id <- action |
291 | | (assign (ident-body x) (heval y env))] |
292 | | |
293 | | [(':if cond then) |
294 | | (if cond then *undefined*)] |
295 | | [(':if cond then else) |
296 | | (if cond then else)] |
297 | | |
298 | | [(':do . _) ; do { ... ; ... ; ... } |
299 | | `(seq ,@(heval-map (cdr exp) env))] |
300 | | |
301 | | [(':lambda args . lambda-body) |
302 | | (make-procedure (map ident-body args) ;lambda-parameters |
303 | | lambda-body |
304 | | env)] |
305 | | |
306 | | [(':defun id definition) ; id x y z = app x $ app y $ app z |
307 | | (let ([ident (car id)] |
308 | | [args (cdr id)]) |
309 | | (assign (ident-body ident) |
310 | | (make-procedure (map ident-body args) ;lambda-parameters |
311 | | (if (eq? 'seq (car definition)) ; lambda-body |
312 | | ;(heval definition env) |
313 | | ;(list (heval definition env)) ) |
314 | | definition |
315 | | (list definition)) |
316 | | env)))] |
317 | | |
318 | | [(':pattern id definition) ; id x y z = app x $ app y $ app z |
319 | | (let ([ident (car id)] |
320 | | [args (cdr id)]) |
321 | | )] |
322 | | |
323 | | [(':string . str) str] |
324 | | [(':list . l) l];(heval-map l env)] |
325 | | [(':tuple . t) t] |
326 | | [(':ident . id) id] |
327 | | |
328 | | [_ (if (pair? exp) exp ;(happly (car exp) (cdr exp)) |
329 | | (format "unknown: ~a" exp))] |
330 | | |
331 | | )])) |
| 157 | (if (or (null? exp) (not (pair? exp))) *undefined* |
| 158 | (match exp |
| 159 | [(':$ . _) |
| 160 | ; (delay-it |
| 161 | (let loop ([rest (cdr exp)]) |
| 162 | (if (null? (cdr rest)) |
| 163 | (heval (car rest) env) |
| 164 | (heval (append (car rest) (list (loop (cdr rest)))) env) |
| 165 | )) |
| 166 | ; env) |
| 167 | ] |
| 168 | [(':apply f . _) |
| 169 | (if (null? (cddr exp)) |
| 170 | ; (delay-it (list (ident-body f)) env) |
| 171 | (list (ident-body f)) |
| 172 | `(,(ident-body f) ,@(cddr exp)); ,@(map (cut heval <> env) (cdr exp))) |
| 173 | ; (delay-it `(,(ident-body f) |
| 174 | ; ,@(map (cut heval <> env) (cdr exp))) |
| 175 | ; env) |
| 176 | )] |
| 177 | [(':assign x y) ; id <- action |
| 178 | (assign (ident-body x) (heval y env))] |
| 179 | [(':do . _) ; do { ... ; ... ; ... } |
| 180 | `(seq ,@(heval-map (cdr exp) env))] |
| 181 | [(':defun id definition) ; id x y z = app x $ app y $ app z |
| 182 | (let ([ident (car id)] |
| 183 | [args (cdr id)]) |
| 184 | (assign (ident-body ident) |
| 185 | (make-procedure (map ident-body args) ;lambda-parameters |
| 186 | (if (eq? 'seq (car definition)) ; lambda-body |
| 187 | (heval definition env) |
| 188 | (list (heval definition env)) ) |
| 189 | env)))] |
| 190 | [(':pattern id definition) ; id x y z = app x $ app y $ app z |
| 191 | (let ([ident (car id)] |
| 192 | [args (cdr id)]) |
| 193 | (assign (ident-body ident) |
| 194 | (make-procedure (map ident-body args) ;lambda-parameters |
| 195 | (if (eq? 'seq (car definition)) ; lambda-body |
| 196 | (heval definition env) |
| 197 | (list (heval definition env)) ) |
| 198 | env)))] |
| 199 | |
| 200 | [(':string . str) str] |
| 201 | [(':list . l) l] |
| 202 | [(':tuple . t) t] |
| 203 | [(':ident . id) id] |
| 204 | |
| 205 | [_ (if (pair? exp) (happly (car exp) (cdr exp)) |
| 206 | (format "unknown: ~a" exp))] ))) |
399 | | |
400 | | (define (lookup-variable-value var env) |
401 | | (define (env-loop env) |
402 | | (define (scan vars vals) |
403 | | (cond [(null? vars) |
404 | | (env-loop (enclosing-environment env))] |
405 | | [(eq? var (car vars)) |
406 | | (car vals)] |
407 | | [else (scan (cdr vars) (cdr vals))])) |
408 | | (if (eq? env the-empty-environment) |
409 | | #f ; (error "unbound variable" var) |
410 | | (let1 frame (first-frame env) |
411 | | (scan (frame-variables frame) |
412 | | (frame-values frame))))) |
413 | | (env-loop env)) |
414 | | |
415 | | (define (last-exp? seq) (null? (cdr seq))) |
416 | | (define (heval-sequence exps env) |
417 | | (cond [(last-exp? exps) (heval (car exps) env)] |
418 | | [else (heval (car exps) env) |
419 | | (heval-sequence (cdr exps) env)])) |