| 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 | |
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 | | |
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))] ))) |
| 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 | )])) |
| 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)])) |