- 目次ページに戻る / 前 / 次
- 前回からの差分をまとめて見る
今回はブレークポイントを指定できるようにしたのと、後はリファクタリングです。
_debug でブレークポイントを指定
これまで、プログラムの特定の箇所の動作を観察してデバッグしたい場合次のような手順を踏んでいました。
- まず適当に実行(最初からステップ実行するなど)して、調べたい場所が何ステップ目あたりかを調べる
vgvm.rb
を直接書き換え、どのステップまでスキップするか指定する- 実行するとそのステップまでスキップされるので、そこからステップ実行する
参考: (30) 生存カウント / VRAM から値を取得 / ステップ数を表示
スキップできなかった状態に比べればこれでもかなりの進歩だったわけですが、 さらに便利になるようにブレークポイントを指定できるようにしました。
ステップ実行を始めたい箇所に _debug();
と書いて実行すると、
func main() { var a = 1; var b = 10; set a = a + 2; _debug(); // ここからステップ実行開始 set a = a + b; }
指定した箇所までダンプ表示がスキップされ、
次の図のように _debug
命令の箇所で止まります。
あとはこれまで通り Enter キーを押してステップ実行すればOK。
これ、ほんとにちょっとした修正で済むのでたいへんお買い得です。もっと早くやっておけばよかった。
以下の VM の修正を見ての通り、 _debug
命令が来たら Vm#debug
を true にして、
Vm#debug
が true になっていたらステップ実行する、それだけ。
--- a/vgvm.rb +++ b/vgvm.rb @@ -135,6 +135,7 @@ class Vm @bp = stack_size - 1 # base pointer @step = 0 + @debug = false end def test? @@ -178,6 +179,7 @@ class Vm when "set_vram" then set_vram() ; @pc += 1 when "get_vram" then get_vram() ; @pc += 1 when "_cmt" then @pc += 1 + when "_debug" then _debug() ; @pc += 1 else raise "Unknown opcode (#{opcode})" end @@ -199,7 +201,7 @@ class Vm return if do_exit unless test? - if ENV.key?("STEP") + if ENV.key?("STEP") || @debug dump() $stdin.gets # $stdin.gets if @step >= 600 @@ -432,6 +434,10 @@ class Vm raise not_yet_impl("arg2", arg2) end end + + def _debug + @debug = true + end end if $PROGRAM_NAME == __FILE__
ほとんどそのまま受け渡すだけなのでコンパイラ部分も少しの修正でOK。
to_fn_arg_disp, to_lvar_disp
lvar_addr = to_lvar_addr(lvar_names, lvar_name) puts " cp 0 #{lvar_addr}"
のように使っていたやつです。
この lvar_addr
には [bp:-2]
のような文字列が入るわけですが、これって「アドレス」なんだっけ?
値をセットする宛先だからアドレスと呼んでもダメじゃなさそうだけど……
詳しくいえば「宛先アドレスの bp 相対間接参照表現」みたいになるんでしょうか……。
みたいな感じでモヤモヤしていて気になっていました。
そこで、モヤモヤしなくて済むような名前と処理内容に変えました。
[bp:-2]
のような文字列を返すのではなく、 displacement の値 -2
だけを返すようにすれば、次のように書けます。
disp = to_lvar_disp(lvar_names, lvar_name) puts "cp 0 [bp:#{disp}]"
displacement という、呼び方が定まっているものを返しているわけですから、返り値を受ける変数名も素直に disp
とすればよいと(略しているのは置いといて)。
そもそもは何度も同じような処理を繰り返していて煩雑だから共通化していたわけですが、こういう場合は DRY であることよりも意味が明確でモヤモヤしない方が嬉しいです。
また、修正前は
- displacement を求める
- 文字列(間接参照表現)を組み立てる
という2つの処理を行っていたのが、責務も単純になり、その面でも良かったのかなと。
その他の修正
他に気になっていた部分のリファクタリング。
- メソッドの並び順の修正
- その他細かいの
parse_args
まわりを簡素化