Let's start Scheme

2013-01-28

evalとdatum->syntax

packとunpackの実装をしていて、実行時にbytevector-**-native-ref/set!系の手続きを生成してごにょごにょしようかなぁと思ってこんなのが有効かちょっと試してみた。別にR6RSな処理系コンパチにする必要はないだけど、なんとなく。以下がちょっとしたテスト用スクリプト:
(import (except (rnrs) string-copy) (rnrs eval)
        (for (only (rnrs) bytevector-u16-native-ref) (meta -1))
        (only (srfi :13) string-index-right))

(define (->native sym)
  (define (finish sym) (datum->syntax #'->native sym))
  (let* ((s (symbol->string sym))
         (i (string-index-right s #\-)))
    (finish
     (string->symbol
      (string-append (substring s 0 i) "-native" 
                     (substring s i (string-length s)))))))

(display (eval `(,(->native 'bytevector-u16-ref) #vu8(1 0) 0)
               (environment)))
(newline)
動作確認はいつもの処理系、Chez、Mosh、NMosh、Racket、Ypsilon。Sagittariusはenvironment手続きにバグがあって、0.4.1までは0引数を受け付けなかった。HEADでは修正済み。後、ChezはSRFIが(恐らく)一切使えないので、実行する際は、string-index-right周りをごっそり削って、datum->syntaxの第二引数にbytevector-u8-native-refを直接渡すようにした。

以下は結果
予定通り動いた処理系:NMosh、Racket、Sagittarius
何かしらエラーな処理系:Chez、Mosh、Ypsilon

正直なところ上記のスクリプトがR6RS的にValidなのかすら自信がないのは確かなのだが、 psyntax的にはアウトみたいである。Ypsilonはなんでだろう?NMoshとRacketはフェーズを明に指定してやる必要がある処理系なのだが、それらではOKだった。関係があるかは謎(多分あるはず)。SagittariusがOKなのは分かっていたことなので省略。

この手ではコンパチにできないっぽいので、まぁやるならどうせその辺りの手続きは(rnrs)にあると割り切ってenvironment手続きに明に指定してやるというものになるだろう。

2 comments:

齊藤 said...

eval の第一引数は datum value であることを求められているので構文オブジェクトを含むのは R6RS 的に invalid であると考えられます。
処理系の設計に対してどういう相互作用が働いて動いたり動かなかったりするのか私にはわかりませんが、NMosh の場合は R6RS よりも緩いというような記述はあるので、この文章は参考になるのではないでしょうか。
http://d.hatena.ne.jp/mjt/20101017/p1

kei said...

何かのテストケースで(meta -1)を使ってごにょごにょしていたのを見た気がしたので、validなのかと思っていたのですが、evalはアウトなんですね。
(eval `(#'car 1) (environment '(rnrs)))がアウトなのと同じと思えば納得できそうな気もします。(これは単にフェーズが違うだけな気もしますが。。。)

NMoshはAndre van Tonderの展開器が提供するevalを使ってるから、eval実行時にidentifierをシンボルの区別がつかずにvalidな式として評価されているのかと推測。
Racketは不明ですけど。

Post a Comment