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