mrdbにnextコマンドを追加してみました。
概要
mrdbとは
mrubyのVM上で動作するデバッガです。mruby-1.1.0にてmrbgemsに追加されました。
nextコマンドとは
デバッガ上でプログラムを実行する際、ソースコードの1行分を実行するコマンドです。nextコマンドという名前はC/C++のデバッガであるgdbを参考としています。
例えば以下のプログラムをデバッグするとします。
def sample
p "called sample."
end
p "start."
sample
p "end."
mrdbにてこのプログラムを実行します。試しにp "start."
の行で止めてみましょう。
$ mrdb sample.rb
(sample.rb:1) break 5
Breakpoint 1: file sample.rb, line 5.
(sample.rb:1) continue
Breakpoint 1, at sample.rb:5
5 p "start."
この状態でnextコマンドを実行すると、1行分のプログラムを実行しsample
の行で再び停止します。
(sample.rb:5) next
"start."
sample.rb:6
6 sample
このコマンドは2015/12/15時点のmrdbには存在しておらず、今回の追加対象です。
(参考)stepコマンドとは
nextコマンドに似たコマンドとしてstepコマンドがあります。このコマンドはmrdbに実装されています。
stepコマンドは「メソッド呼び出しを実行する場合に、メソッドの中に入り込んで停止する」という点でnextコマンドと異なります。
$ mrdb sample.rb
(sample.rb:1) break 5
Breakpoint 1: file sample.rb, line 5.
(sample.rb:1) continue
Breakpoint 1, at sample.rb:5
5 p "start."
(sample.rb:5) step
/mruby/mrbgems/mruby-print/mrblib/print.rb:40
40 def p(*args)
このため、メソッドそのものをスキップしたい場合においては少々不便なコマンドです。
nextコマンド追加の流れ
nextコマンドを追加する方法を簡単に説明します。
ソースコードは以下に公開していますので、気になる方は参照ください。
https://github.com/yuuu/mruby/tree/add_next_command
改造するのはmrbgems/mruby-bin-debugger/tools/mrdb/
配下のソースコードです。
nextコマンドを受付可能とする
現状のmrdbにnextと打ち込んでも、コマンドとして認識されません。
$ mrdb sample.rb
(sample.rb:1) break 5
Breakpoint 1: file sample.rb, line 5.
(sample.rb:1) next
invalid command (next)
mrdbは受付可能なコマンドをテーブルに定義しているので、このテーブルにnextコマンドを追加します。追加作業は仕様がほとんど同じであるstepコマンドを参考にしました。
nextコマンドの実処理を追加する
次にnextコマンドの実処理を追加します。nextコマンドで行うべきことは、stepコマンドとほぼ同じであるため、これを参考にしました。
唯一異なるのは、メソッド呼び出しした場合にはメソッドを抜けるまで停止させない、という点です。この動作を実現する方法は以下の記事を参考にしました。
要するに、nextを実行した時点のスタック深さを記憶しておき、これより深い箇所では停止させないようにする、という処置が必要ということです。
まとめ
nextコマンドを追加することで、より快適にmrubyプログラムをデバッグできるようになりました。
ひと通り問題ないことを確認できたら、mruby本家のリポジトリへpull-requestしてみるのも良いかなと思っています。