mrubyデバッガ(mrdb)を使ってみる
これは、ETロボコン Advent Calendar 2014 - Adventarの 24日目のエントリーです。
昨日の記事はyamane (@yuri_at_earth) | Twitterさんによるmrubyの記事でした。mrubyは個人的にもいろいろと関わりがあり、気に入っている言語です。
mrubyは随分前からオープンソースとして公開されていますが、まだ触ったことのない人が多いと思います。本記事ではmrubyの環境を(さくっと)構築して、mrubyを使う方法をまとめます。
また、mruby 1.1.0で登場したデバッガ(mrdb)の使い方をまとめます。
記事を書いていたところ、ボリュームが大きくなり過ぎてしまったため、2記事に分割しました。mrubyについてよく知らないという人は以下の記事も参照ください。
ETロボコン2015の準備。mrubyの開発環境を知る - .logbook
想定する環境
ETロボコン参加者はWindows+cygwinで環境構築している人が多いと予想されるため、cygwin上でmrubyを使えるようにします。
mrubyを使う準備をする
cygwin上で必要なツールをインストール
下記ツールをインストールします。setup-x86.exeまたはsetup-x86_64.exeを使用します。
それぞれ、cygwin上で取得できる最新バージョンを指定します。
make
bison
git
選択したら、インストールします。
mrubyの取得とビルド
githubからmrubyを取得してビルドしましょう。ビルド後は出来上がった実行ファイルを/cygwin/binへコピーします。以下のコマンドを順番に入力してください。
$ git clone https://github.com/mruby/mruby.git $ cd mruby/ $ make $ cp bin/* /bin
以上で環境の準備は完了です。
mrubyを実行しよう
環境が整ったら早速Rubyのソースを書いて、mrubyで実行しましょう。ソースのサンプルとしてFizzBuzzプログラムを作ってみました。(Rubyがオブジェクト指向言語であることがわかるよう、あえてクラス化しています)
fizzbuzz.rb
class FizzBuzz FIZZ = 3 BUZZ = 5 def initialize @take = 0 end def answer(max) @take = @take + 1 print "take #{@take}----------\n" (1..max).each do |count| if (count % (FIZZ * BUZZ)) == 0 print "FizzBuzz\n" elsif (count % FIZZ) == 0 print "Fizz\n" elsif (count % BUZZ) == 0 print "Buss\n" else print "#{count}\n" end end print "----------\n" end end fizzbuzz = FizzBuzz.new fizzbuzz.answer 10 fizzbuzz.answer 30
ソースができたら、実行してみましょう。
$ mruby fizzbuzz.rb take 1---------- 1 2 Fizz 4 Buss Fizz 7 8 Fizz Buss ---------- take 2---------- 1 2 Fizz 4 Buss Fizz 7 8 Fizz Buss 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buss Fizz 22 23 Fizz Buss 26 Fizz 28 29 FizzBuzz ----------
このように、ソースコード通りにFizzBuzzが実行されました。
mrdbを使ってみよう
mrdbを使用することで、プログラムを動かしながら動作を確認したり、問題箇所を特定することができます。mrdbはC言語のプログラムで使われるgdbと同等のインタフェースで操作することができます。
mrdbを起動する
まず、デバッガを起動します。
cygwinの端末上で以下のように入力します。
$ mrdb fizzbuzz.rb
ブレイクポイントを設定する
次に、プログラムを中断させたいポイントにブレイクポイントを設定します。
ブレイクポイントは「ファイル名と行番号」もしくは「クラス名とメソッド名」を指定して設定することができます。設定にはbreakコマンドを使います。
break (ファイル名):行番号
break (クラス名):メソッド名
※()は省略可能、"break"は"b"に省略可能
例えば、こんな感じです。
(fizzbuzz.rb:1) b 27 Breakpoint 1: file fizzbuzz.rb, line 27. (fizzbuzz.rb:1) b FizzBuzz:answer Breakpoint 2: class FizzBuzz, method answer.
登録すると、ブレイクポイントに対して番号が割り振られます。
ブレイクポイントの一覧を確認する
ブレイクポイントが登録されたかどうか、一覧を表示して確認してみましょう。info breakpointsコマンドを入力します。
info breakpoints (ブレイクポイントNo)
※()を省略すると、全ブレイクポイントを表示。"info breakpoints"は"i b"に省略可能。
入力すると、一覧が表示されました。
(fizzbuzz.rb:1) i b Num Type Enb What 1 breakpoint y at fizzbuzz.rb:27 2 breakpoint y in FizzBuzz:answer
プログラムを実行する
いよいよプログラムを起動します。runコマンドを入力します。
(fizzbuzz.rb:1) run Breakpoint 1, at fizzbuzz.rb:27 27 fizzbuzz = FizzBuzz.new
ブレイクポイントを設定した27行目で停止しました。尚、この時点で再度runコマンドを入力すると、プログラムを最初からやり直します。
ブレイクポイント以降のプログラムを実行するためにはcontinueコマンドを入力します。("continue"は"c"に省略可能)
(fizzbuzz.rb:27) c Breakpoint 2, FizzBuzz:answer 9 def answer(max)
ブレイクポイントを設定したFizzBuzzクラスのanswerメソッドで停止しました。
ソースコードを表示する
デバッグ中にソースコードを確認したいときは、listコマンドを入力します。
list (行番号)
※行番号を省略すると、実行中の行数から出力。"list"は"l"に省略可能
入力すると、ソースコードが部分的に表示されました。
(fizzbuzz.rb:9) l 9 def answer(max) 10 @take = @take + 1 11 print "take #{@take}----------\n" 12 (1..max).each do |count| 13 if (count % (FIZZ * BUZZ)) == 0 14 print "FizzBuzz\n" 15 elsif (count % FIZZ) == 0 16 print "Fizz\n" 17 elsif (count % BUZZ) == 0 18 print "Buss\n"
1行だけ実行する
stepコマンドを入力すると、1行だけ進みます。
(fizzbuzz.rb:9) step fizzbuzz.rb:10 10 @take = @take + 1 (fizzbuzz.rb:10) step fizzbuzz.rb:11 11 print "take #{@take}----------\n"
変数の値を書き換える
evalコマンドを使うことで、変数の値を書き換えたり、表示したりすることができます。
eval (実行したい式)
このように使用します。
(fizzbuzz.rb:11) eval @take = 3 $1 = 3
その他のコマンド
その他、使えるコマンドは(mruby debugger 操作マニュアル)http://forum.mruby.org/docs/dmanual.htmlを参考にしてください。
まとめ
このように、mrubyの開発環境は簡単に構築できます。デバッガが登場したことで、プログラムのバグを見つけるのも容易になりました。
mrubyを使うことでETロボコンの戦略が多様化したり、ソースが読みやすくなることで大人数での開発が簡単になったりと、様々なメリットが期待されます。来年度、使ってみたいと思っている人は、ぜひオフシーズン中にmrubyを触ってみてください。その心地良さが体感できるはずです。
ついにクリスマスイブです。明日はいよいよ最終日となりますので、お楽しみに!