Show
Ignore:
Files:
1 modified

Legend:

Unmodified
Added
Removed
  • hh2008/naoya_t/trunk/ihci.scm

    r22 r18  
    1 ;; 
    2 ;; IHC - Ikoma Haskell Compiler 
    3 ;; 
    41(use srfi-1) 
    52 
     
    2623         [%body-char ($or %unescaped)] 
    2724         [%string-body ($do (chars ($many %body-char)) 
    28 ;                                                       ($return (tag :string (list->string chars))))] 
    29                                                         ($return (list->string chars)))] 
     25                                                        ($return (tag :string (list->string chars))))] 
    3026                 ) 
    3127        ($between %dquote %string-body %dquote))) 
    32  
    33 (define %char 
    34   ($do (($char #\')) 
    35            (($optional ($char #\\))) 
    36            (ch anychar) 
    37            (($char #\')) 
    38 ;          ($return (tag :char ch)) 
    39            ($return ch) 
    40            )) 
    4128 
    4229(define %ident ;; scheme-symbolで代用 
     
    4532        ($do (head %ident-head-char) 
    4633                 (rest ($many %ident-rest-char)) 
    47 ;                ($return (tag :ident (string->symbol (list->string (cons head rest)))))))) 
    4834                 ($return (string->symbol (list->string (cons head rest))))))) 
    4935 
    5036(define %digits 
    5137  ($do (d ($many digit 1)) 
    52 ;          ($return (tag :number (string->number (list->string d)))))) 
    53            ($return (string->number (list->string d))))) 
     38           ($return (tag :number (string->number (list->string d)))))) 
    5439 
    5540(define %list 
    56   (let* ([%begin-list ($char #\[)] 
    57                  [%end-list ($char #\])] 
     41  (let* ([%begin-list ($seq %ws ($char #\[) %ws)] 
     42                 [%end-list ($seq %ws ($char #\]) %ws)] 
    5843                 [%item ($or %digits %string %ident)] 
    5944                 [%item-separator ($seq %ws ($char #\,) %ws)] 
     
    6651 
    6752(define %tuple 
    68   (let* ([%begin-list ($char #\()] 
    69                  [%end-list ($char #\))] 
     53  (let* ([%begin-list ($seq %ws ($char #\() %ws)] 
     54                 [%end-list ($seq %ws ($char #\)) %ws)] 
    7055                 [%item ($or %digits %string %ident)] 
    7156                 [%item-separator ($seq %ws ($char #\,) %ws)] 
     
    7762        )) 
    7863 
    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  
    12864(define %expr 
    129   ($or %infixed  
    130 ;          ($between ($char #\() %expr ($char #\))) 
    131            %if %atomic)) 
    132  
    133 (define %comment 
    134   ($or 
    135    ($seq ($string "-- ") ($none-of #[\n]) ($char #\n)) 
    136    ($seq ($string "{-") ($many anychar) ($string "-}")) 
    137    )) 
    138  
    139 (define %if 
    140   ($do (($string "if")) 
    141            %ws 
    142            (cond %expr) 
    143            %ws 
    144            (($string "then")) 
    145            %ws 
    146            (conseq %expr) 
    147            (alt ($optional ($do %ws (($string "else")) %ws  
    148                                                         (alt %expr) 
    149                                                         ($return alt)))) 
    150            ($return (tag :if (list cond conseq alt))))) 
     65  ($or %string %digits %ident %list %tuple)) 
    15166 
    15267(define %application 
     
    15469          ($do (fn %ident) 
    15570                   %ws 
    156                    (arg1 ($or %expr 
    157                                           ($between ($char #\() %expr ($char #\))))) 
    158                    %ws 
    15971                   (args ($my-sep-by %expr %ws)) 
    160                    ($return `(:apply ,fn ,arg1 ,@args))) 
    161         ($do (app1 ($or %infixed %an-application %lambda %ident)) 
     72                   ($return `(:apply ,fn ,@args))) 
     73        ($do (app1 %an-application) 
    16274                 (apps ($many ($do %ws 
    163                                                    (($char #\$)) ; " $ " 
     75                                                   (($char #\$)) 
    16476                                                   %ws 
    165                                                    (app ($or %infixed %an-application %lambda %ident)) 
     77                                                   (app %an-application) 
    16678                                                   ($return app)))) 
    16779                 ($return (if (= 0 (length apps)) app1 `(:$ ,app1 ,@apps)))))) 
    16880 
    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  
    22181(define %haskell 
    22282  (let* ([%unknown ($my-sep-by %expr %ws)] 
    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) 
    227124        )) 
    228125 
     
    237134;(define ident-body untag) 
    238135 
    239 (define lambda? (tagged?$ :lambda)) 
    240  
    241136(define (indent w lines) 
    242137  (string-join (map (lambda (line) (string-append (make-string w #\space) (x->string line))) 
     
    248143  (hash-table-put! *namespace* id val) 
    249144  id) 
    250  
    251 (define (lookup id env) 
    252   (let1 val (lookup-variable-value id env) 
    253         (if val val (hash-table-get *namespace* id)))) 
     145(define (lookup id) 
     146  (let1 val (hash-table-get *namespace* id) 
     147        ; 
     148        val)) 
    254149 
    255150;; 
     
    260155(define (heval-map exps env) (map (cut heval <> env) exps)) 
    261156(define (heval exp env) 
    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))] ))) 
    332207 
    333208(define (primitive-procedure? proc) 
     
    335210                           putStrLn 
    336211                           lines length print 
    337                            tail 
    338                            * + - /))) 
     212                           tail))) 
    339213 
    340214(define (prim-print exp) 
     
    349223                   (list->haskell-string (untag obj))] 
    350224                  [(pair? obj) (haskell-description-of-list obj)] 
    351                   [(number? obj) (number->string obj)] 
    352                   [(string? obj) obj] 
    353225                  [else (x->string obj)])) 
     226 
    354227  (print (haskell-description exp))) 
    355228 
     
    363236  (let1 args* (heval-map args '()) 
    364237        (case proc 
    365           [(putStr) (display (x->string (car args*)))] 
    366           [(putStrLn) (apply prim-print args*)] 
    367           [(print) (apply prim-print args*)] 
    368           [(lines) (length args*)] 
    369           [(length) (if (tagged? :string (car args*)) 
     238          ((putStr) (display (x->string (car args*)))) 
     239          ((putStrLn) (apply prim-print args*)) 
     240          ((print) (apply prim-print args*)) 
     241          ((lines) (length args*)) 
     242          ((length) (if (tagged? :string (car args*)) 
    370243                                        (string-length (car args*)) 
    371                                         (length (car args*)))] 
    372           [(tail) (prim-tail (car args*))] 
    373  
    374           [(*) (apply * args*)] 
    375           [(+) (apply + args*)] 
    376           [(/) (apply / args*)] 
    377           [(-) (apply - args*)] 
    378 ;         [else (error "unknown primitive: " proc)] 
     244                                        (length (car args*)))) 
     245          ((tail) (prim-tail (car args*))) 
    379246          ))) 
    380247 
     
    385252(define (procedure-environment proc) (fourth proc)) 
    386253 
    387 ; SICP pp225-226 
    388 (define (enclosing-environment env) (cdr env)) 
    389 (define (first-frame env) (car env)) 
    390 (define the-empty-environment '()) 
    391  
    392254(define (make-frame vars vals) (cons vars vals)) 
    393 (define (frame-variables frame) (car frame)) 
    394 (define (frame-values frame) (cdr frame)) 
    395255 
    396256(define (extend-environment vars vals base-env) 
    397257  ;; assert-equal (length vars) (length vals) 
    398258  (cons (make-frame vars vals) base-env)) 
    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)])) 
    420259 
    421260(define (happly proc args) 
     
    426265                                                                           args 
    427266                                                                           (procedure-environment proc)) 
    428                    (heval-sequence (procedure-body proc) env))] 
     267                   (heval-map (procedure-body proc) env))] 
    429268                [else 
    430269                 ; 
     
    435274  (let1 input (read-line) 
    436275        (if (eof-object? input) 'eof 
    437                 (begin 
    438                   (when (and (string? input) (< 0 (string-length input))) 
     276                (let1 parsed (parse-haskell input); (haskell->scheme input) 
     277                  (let1 evaled (heval parsed '()) 
    439278                        (print "> " input) 
    440                         (let1 parsed (parse-haskell input); (haskell->scheme input) 
    441                           (print "=> " parsed) 
    442                           (let1 evaled (heval parsed '()) 
    443                                 (print "=> " evaled) 
    444                                                                                 ;                         (if evaled (print ": " (heval evaled '()))) 
    445                                 )) 
    446                         (print "")) 
     279                        (print "=> " parsed) 
     280                        (print "" evaled)) 
    447281                  (repl))))) 
    448282 
    449 ;(define (actual-value exp); env) 
    450 ;  (if (and (pair? exp) (tagged? ':apply exp)) 
    451 ;         ( 
    452 ;  (force-it (heval exp '()))) 
    453  
    454 (let1 main (lookup 'main '()) 
    455   (print "====") 
    456   (happly main '()) 
    457   ) 
     283(define (actual-value exp); env) 
     284  (force-it (heval exp '()))) 
     285 
     286(let1 main (lookup 'main) 
     287  (print "----") 
     288   (happly main '()) 
     289   )