はじめに
この記事は、以下の記事にある「リテラルオブジェクトをRubyのオブジェクトから卒業させる」をチャレンジしている途中記録をまとめたものになります。
まだ対応途中ということもあり、不正確な情報も混じっているかもしれません。
「ここ間違ってるよ」とかあればコメントなどでツッコミを入れていただければ幸いです。
やったこと(というか現在やっている作業)
とりあえず、以下のPR内でIntegerのリテラルオブジェクトの生成をparse.y内部ではなくcompile.cで行うように修正しました(ローカルで軽く動作確認はとれているんですが、CIはまだ落ちている状況)
RubyのASTのノードで利用されているRNodeという構造体にrb_literal_structという構造体を追加し、Integerのリテラルオブジェクトを生成する部分でrb_literal_structにパースしたコード(ex: 117などの数字)をchar*で保存しています。
また保存した値などを引き回してRNodeの生成部分まで渡し、最終的にcompile.cでリテラルオブジェクトをISeqへと渡す部分までもっていき、そこでIntegerを生成するようにしています。
困った点など
基本的にポインタで構造体を引き渡したりしており、意図せぬ箇所で初期化漏れがあったりしてSEGVが起き続けていたのは大分困りましたね......。
SEGVで大分時間が溶けたんですが「たぶん、何かしらCRuby用のデバッグツールが同梱されてるんじゃないか?」と思い、ソースコードを調べたところmake gdbという便利コマンドがあり何とかなりました。
make gdbはRubyのソースコードディレクトリ内にtest.rbを置くとそれを実行し、SEGVした際の情報などをgdbでデバッグできるというコマンドです。
これのおかげでバックトレースなどをを詳細に確認でき、意図せぬ初期化漏れなどをつぶすことが出来ました。
今後
とりあえず、Integerのリテラルオブジェクトは剥がせそうな様子になってきたかなと思います。
ただCIがパスしていないことや他のリテラルオブジェクトを対応しないといけないので道のりはかなり長そうです。
ひとまず次は、CIがパスするところを目標に対応を進めたいと思います。
その後はSymbolかFloatを対応していきたいですね。
あと「とりあえず動く」を目標にコードを書いてるので大分アレな感じになっているのも直していきたい......。