Hatena::ブログ(Diary)

miura1729の日記 このページをアンテナに追加 RSSフィード

2009-08-28

型推論できない場合に遭遇

19:04 |  型推論できない場合に遭遇を含むブックマーク  型推論できない場合に遭遇のブックマークコメント

 bm_so_nsieve.rbを動くようにしています。これも、一見簡単だと思ったのですが曲者が隠れていました.

  Flags = ("\x1" * ( 2 ** n * 10_000)).unpack("c*")

String#unpackの型推論は完全には不可能かと思います。幸い、unpackのテンプレート文字列リテラルで使うことが多そうなので、リテラルの時はテンプレート文字列を解析するといいかなと思っています。

追記

 結局、bm_so_nsieve.rbはunpackについて特別な対策をしなくても動いちゃいました。たまたま、unpackの戻り値配列の要素に整数を書き込んでいるので整数配列として推論出来たからでした。でも、ラッキーは続かないのでunpackの対策は入れるべきかなーと思います.

でも、出力が変です。最適化を掛けないと正常に出力されるのでオプティマイザのバグかもしれないな、でも自分のバグコンパイラのせいにしてよく怒られたなーちゃんと追ってみよう、とそんな感じです。

追記2

 ユーザが引数戻り値型推論のポリシーをカスタマイズできるようにしようとしています。String#unpackやprintfのようなメソッドを定義した場合、より適切な型推論ができるようになります。

型推論カスタマイズそのものは前から考えていたのですが、実際に必要になってきたかなと思います。

機能の実現だけなら簡単なんですが、使いやすいAPIをデザインするのがとても難しい。

追記3

String#unpackの型推論カスタマイズは今のところこんなところ。:copy_rettypeの内容がが戻り値を推論する必要があるときに呼び出されてその結果を戻り値の型として採用します。

  MethodDefinition::RubyMethod[:unpack][:String] = {
    :argtype => [RubyType.string],
    :rettype => nil,
    :copy_rettype => lambda { |rect, argt|
      rt = RubyType.array(nil, "Return type of String#unpack")
      fmt = argt[0].content
      if !UNDEF.equal?(fmt) then
        fmt.each_char do |ch|
          case ch
          when 'c', 'C', 's', 'S', 'i', 'I', 'l', 'L', 'n', 'N', 'v', 'V'
            RubyType.fixnum.add_same_type(rt.type.element_type)

          when 'a', 'A', 'Z', 'b', 'B', 'h', 'H', 'm', 'M', 'u', 'U', 'w'
            RubyType.string.add_same_type(rt.type.element_type)

          when 'f', 'd', 'e', 'E', 'g', 'G'
            RubyType.float.add_same_type(rt.type.element_type)
          end
        end
      end
      rt
    }
トラックバック - http://d.hatena.ne.jp/miura1729/20090828/1251453865