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

 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
    }