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