けいぞうのメモ帳

言語設計のお勉強

mruby-implerr mgem

github.com

設計上起こり得ないエラーを処理する例外クラスのmgemを公開した。 これは、主に作業中のmgemにおいて使われることを想定している。
分岐や変更の多い処理で一時的に例外をなげて、実装に考慮漏れがあることを明示するために用いる。
テストを走らせたときなどに便利だと思う。

たとえばこんな感じのクラスがあったとして

class Data
  attr_accessor :a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k
  def initialize(a,b,c,d,e,f,g,h,i,j,k)
  end
end

 このクラスのオブジェクトを対応するC言語の構造体に変換したいとする。 rubyは同じ扱いが出来るのであれば、複数のクラスのオブジェクトを同じように扱う方針があるので、 Data::Nameのような特定のデータを示すクラスとStringクラスのどちらも引数に取れたりする。 これをmrubyのmrb_valueからC言語の文字列 char *に変換したい場合それぞれで処理が異なる。 だからオブジェクトの型チェックなどの判定処理を入れることになると思う。 そうして、求められるC言語での実体をそれぞれの変数から取得して構築する。

 このような変換関数を書くとき、未成熟なライブラリにおいて rubyの構造体の方に入る値はかなり柔軟に変更されることが予想できる。 Stringしか受け取らなかったけど任意のクラスの子クラスのオブジェクトはすべて受け取るだとか、 Fixnumも受け取れた方がいいだとかである 。

 このような変更により処理に不整合が起こることが予想できる部分に書く例外として

ImplementationError

をmruby-implerrとして用意した。

NotImplementedErrorは未実装な場合に投げる例外だと思うし、すべてをRuntimeErrorで処理するのは良くないと思ったためだる。

ImplementationErrorはオプショナル引数を2つもち、数字と文字列を受け取れる。

raise ImplementationError.new(__LINE__,__FILE__)

のようにして、使うことを考えている。
引数の順序はどちらを先にしても問題ない。

C言語から例外を投げる

ImplementationErrorC言語から投げられることが多いと思っている。 正直ruby側ではちゃんとrubyとしてStandardErrorを継承したそれ用の例外をガンガン変更していける。
C言語側で、問題の粒度がはっきりしない場合に一時的にmrb_raise(mrb_state*, struct RObject *, char *)を用いて 処理を中止する用途で用いることを推奨する。