横道はこれくらいにして、いよいよ irb > eval_input の総本山と思える @scanner.each_top_level_statement メソッドをのぞいてみよう。eval_input のこの部分の最初の部分は次のようになる。
@scanner.each_top_level_statement do |line, line_no| signal_status(:IN_EVAL) do begin line.untaint @context.evaluate(line, line_no) output_value if @context.echo? rescue StandardError, ScriptError, Abort ....... RubyLex#each_top_level_statement メソッドはコードブロックを引数にとる高階関数だ。したがって、上のコードでは do |line, line_no| ... 以下のコードブロックがこのメソッドの引数として渡される。do ... end は次のように、{|line, line_no| ... } とも書けるので each_top_level_statement の引数としてみるときは、こっちの表示の方が直観的にわかりやすい。 さてこのコードブロックを見てみよう。 最初は signal_status(:IN_EVAL) do ... end となっているが、これは引数のコードブロックを実行するときに一時的にそのシグナル状態を :IN_EVAL に変更するという関数なので当座は無視することにする。 そうすると、本質的な部分は begin 以下の部分になるが、なんと begin 以下4行目は rescue になっている。つまりこの長いコードブロックの実質的な機能は3行だけであとはすべてエラー処理にあてられているのだ。 そこで、この3行が何をしているかというと、引数の line (おそらくコンソールから入力したRubyの文が入っていると思われる。)を untaint して、@context.evaluate(line, line_no) メソッドで line に代入されている文を実行し、その結果を output_value メソッドで表示している。 line や line_no の情報は each_top_level_statement メソッドが持っていて、このコードブロックを使って line を実行するのだろう。 なぜこのようなスタイルにしたのかはわからないが、しかし、each_top_level_statement メソッドに、{|line, line_no| print line_no, " : ", line, "\n"} のようなコードブロックを引数として与えると、line は実行されず、行番号とともに表示されることになる。 ともあれ、irb のプロンプトから入力された Ruby の文がどこで実行されているのかが分かった。 ところで、文を一行実行させるだけなら次のような micro_irb.rb でも十分だ。 while true print '> ' p eval(gets) end しかし、これでは、複数行の文からなる制御構造は扱えない。それらを扱うためにはどうしても部分的な構文解析が必要なのだ。それをやっているのが irb の処理なのだろう。 micro_irb.rb だが、これくらい小さいと、次のように一行ですませることができる。 > ruby -e "loop {print '> '; p eval(gets)}"
by tnomura9
| 2008-04-04 23:22
| Ruby
|
Comments(0)
|
カテゴリ
新型コロナウイルス 主インデックス Haskell 記事リスト 圏論記事リスト 考えるということのリスト 考えるということ ラッセルのパラドックス Haskell Prelude Ocaml ボーカロイド 圏論 jQuery デモ HTML Python ツールボックス XAMPP Ruby ubuntu WordPress 脳の話 話のネタ リンク 幸福論 キリスト教 心の話 メモ 電子カルテ Dojo JavaScript C# NetWalker ed と sed HTML Raspberry Pi C 言語 命題論理 以前の記事
最新のトラックバック
最新のコメント
ファン
記事ランキング
ブログジャンル
画像一覧
|
ファン申請 |
||