kiyoka.2011_03_31 RSSPLAIN

Related pages: !kiyoka.blog.list !kiyoka.blog.2011_03
5555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555
5

[Nendo][Scheme] syntax-rulesの実装中。難航中。

5

オレ処理系のNendoについての開発メモ。

5
 SYKjVO
5

chibi-scheme 0.3のer-macro-expanderとsyntax-rulesをそのままNendoに移植中。

5

今は、make-syntactic-closureをどう実装していいかわからないので、正解を探しているところ。

5

 

5
 syntactic-closuresEXT
5
 Macros offer a way to extend the Scheme language by introducing new
5
 forms of syntax that are transformed into the simpler base
5
 language. Since Scheme's syntax is defined in terms of Scheme objects
5
 -- lists & symbols, mainly --, one would imagine that procedures that
5
 perform such transformations, known as macro transformers, should be
5
 easy: they just operate on lists & symbols, especially in the presence
5
 of quasiquote. However, this is not quite the case: macros need to
5
 also be aware of the underlying lexical scoping of the programs they
5
 transform. This article will not go into the need for that; see my
5
 article hygiene-versus-gensym for discussion of that matter. Macros
5
 need to work with more than S-expressions: they need S-expressions
5
 annotated with lexical scoping information.
5
 (以下略)
5

 

5

この文章を読んでも、具体的にどう実装すればいいのかわからん。

5

MIT Schemeとchibi-scheme 0.3のソースをじっくり読めばわかるのだろうか。

5

 

5

多分、クロージャを作ってそのレキシカル環境でバインドした変数名を返せばいいのだろう。

5

で、それは具体的にRubyでどう実装すればいいのかという問題。

5

受け取ったシンボルを、グローバル環境で(gensym)した変数名に代入してから、その(gensym)したシンボルを返してもいけるかも。

5

 

5

ちなみに、今の嘘実装はこれ。

5

(er-macro-expanederとsyntax-rulesはchibi-scheme 0.3のコードそのまま動いたので、本ブログへの引用は省略)

5
(define (make-syntactic-closure mac-env use-env identifier)
5
  (let* ([id-str     (symbol->string identifier)]
5
         [alias-data (assq-ref id-str mac-env)])
5
    (if alias-data
5
        (string->symbol (car alias-data))
5
        identifier)))
5

グローバルバインドされたシンボル(ifなどの予約語)は別名 /nendo/macroenve/if などを返し、

5

それ以外の未定義のシンボルは、そのままシンボルを返している。

5

 

5

簡単な例では一見動いてように見える。

5
(define-syntax nil!
5
  (syntax-rules ()
5
    ((_ x)
5
     (set! x '()))))
5
nendo> (define a 1)
5
5
nendo> (macroexpand '(nil! a))
5
(/nendo/macroenv/set! a (/nendo/macroenv/quote ()))
5
nendo> (nil! a)
5
()
5
nendo> a
5
()
5

 

5

試しに、以下のchibi-schemeのcutの定義はそのまま通るので、動かしてみた。

5
(define-syntax %cut
5
  (syntax-rules (<> <...>)
5
    ((%cut e? params args)
5
     (lambda params args))
5
    ((%cut e? (params ...) (args ...) <> . rest)
5
     (%cut e? (params ... tmp) (args ... tmp) . rest))
5
    ((%cut e? (params ...) (args ...) <...>)
5
     (%cut e? (params ... . tmp) (apply args ... tmp)))
5
    ((%cut e? (params ...) (args ...) <...> . rest)
5
     (error "cut: non-terminal <...>"))
5
    ((%cut #t (params ...) (args ...) x . rest)
5
     (let ((tmp x)) (%cut #t (params ...) (args ... tmp) . rest)))
5
    ((%cut #f (params ...) (args ...) x . rest)
5
     (%cut #t (params ...) (args ... x) . rest))))
5
(define-syntax cut
5
  (syntax-rules () ((cut args ...) (%cut #f () () args ...))))
5
(define-syntax cute
5
  (syntax-rules () ((cute args ...) (%cut #t () () args ...))))
5

 

5

[expandしてみる]

5
(pretty-print
5
 (macroexpand
5
  '(map (cut + 1 <>) '(1 2 3 4))))
5

 

5

[結果]

5
(map
5
 (let
5
  ((tmp 1))
5
  (lambda
5
   (tmp)
5
   (+ tmp tmp)))
5
 ('
5
  (1 2 3 4)))
5

ヒドい。なんでもかんでもtmpになる

5

 

5

勿論、計算結果もでたらめ。

5
nendo> (map (cut + 1 <>) '(1 2 3 4))
5
(2 4 6 8)
5

 

5

まだまだ挑戦は続くのであった。

5

 

5

...comment disabled...

5