はじめに
この記事は、以下の記事の続きです
parse.yリファクタリングチャレンジの中の一つ「リテラルオブジェクトをRubyのオブジェクトから卒業させる」をチャレンジしている途中記録をまとめたものになります。
前回から今回の記事までにやったこと
マイナスがついているIntegerのリテラルオブジェクトを生成できるように対応
前回の記事までの対応だと、以下のようなコードが正しく処理されませんでした。
p -117 # => 117と出力される
これは parse.y
の以下の部分で行っている -117
へと変換する処理がすり抜けているため、117
という正の数になってしまっていた感じでした。
なので、以下のコミットでマイナスがついている場合も負のIntegerを生成できるように修正した。
やっていることとしては rb_integer_literal_info_t
というInteger関連の情報を保持する構造体を追加し、そこへ負の値かどうかの情報を渡すようにしています。
それを compile.c
のリテラルオブジェクトを生成する部分でチェックし、チェックに引っかかれば負の値として値を返すようにしています。
0の場合だけIntegerのリテラルオブジェクトを正しく生成できない問題に対応
次になんとかしたのは 0
の場合だけ正しくリテラルオブジェクトを生成できていない部分です。
具体的には以下のコードが false
を返していました。
p 117 - 117 == 0 # => falseが返される
挙動などを調べたところ、これは以下のようにリテラルオブジェクトを生成していることが分かりました。
117 - 117 == 117
何故か 0
の部分が 117
となっているため 0 == 117
という式になり、結果として false
が返っていたというわけです。
で、こちらに関しては以下のコミットで修正しました。
どうも tok(p)
で値を取得している際に以前の値が残ったままになっているケースがあり、そのエッジケースに遭遇したということのようです。
そのため tokfix(p)
を追加して、その辺をいい感じに処理しています。
ここは現状のRubyでは問題になっていませんが、あとでPR投げてもいいかなと思っています。
今後
とりあえず、 make btest
でパスしていないテストの数が17件くらいになってきたので残りの部分を直していきたいですね。
たぶん次に対応するのは 1.2r
とかのリテラルオブジェクトを生成する部分などになりそう。
宣伝
parse.y リファクタリングチャレンジとかUniversal Parserの話、またはCRubyの内部実装の話などは以下のイベントでアレコレ話してたりするので興味のある方は是非是非ご参加くださいー。