2006-11-24から1日間の記事一覧
今日は break, redo, next などループ制御構文 for やブロックつきメソッド呼び出し構文 rescue, ensure 例外処理 のコンパイル部分をよみました。これ全部一回でやるつもりはなかったんですが、読んでみると全部深く関係しててこんなことになってしまいまし…
ensure節のコードは、YARVでは複数箇所に複製される可能性があります。 begin の本体が正常終了する箇所 break などでensureを抜ける箇所 例外で終わる場合の例外ハンドラとして それぞれ、ensure節が終わったあとに実行するコードが違うので、ひとつにまと…
case NODE_RESBODY:{ NODE *resq = node; NODE *narg; LABEL *label_miss, *label_hit; while (resq) { ... resq = resq->nd_head; } break; 複数のrescue節がありうるので、一個一個順番にコンパイルしていきます。これは上にあるrescue節から順に命令列に…
rescueやelseがある場合は、メインの命令列は次のようにコンパイルされます。(コンパイルするコードは特別なところはないので省略) start: 本体 end: if(elseがあれば) pop; elseの中身 lcont: if(poped) pop例外ハンドラの登録はこんな感じ。 /* resgiste…
begin 〜 end 構文です。rescueやensureがつくと、構文解析の段階でいろいろとノードの種類が変わってきます。まとめると以下の通り。 begin AAA end # NODE_BEGIN(AAA) begin AAA ensure EEE end # NODE_ENSURE(AAA,EEE) begin AAA rescue .. BBB rescue ..…
どんどん行きましょう。retry。NODE_ITERのところで読んだように、retryは例外処理になります。常にthrowに変換しておしまい。 case NODE_RETRY:{ if (iseq->type == ISEQ_TYPE_BLOCK || iseq->type == ISEQ_TYPE_RESCUE) { ADD_INSN(ret, nd_line(node), pu…
ジャンプ先と飛ばす例外の種類が違うだけで、NODE_BREAKとまったくおんなじです。next!
break文のコンパイルでやるべきことのおさらいです。 ジャンプ脱出コードを生成するか、例外脱出コードを生成するか ジャンプ脱出の場合、ensureの扱い case NODE_BREAK:{ unsigned long level = 0; if (iseq->compile_data->redo_label != 0) { /* while/un…
ついでだからブロックについてもここで読んじゃいます。NODE_FORはRubyのこの形の式 for 変数s in 式 本体 end を表す構文木ノードで、意味的には 式.each { |変数s| 本体 } と同じです。NODE_ITERは、メソッド名がeachとは限りませんが↑の形のブロックつき…
case NODE_OPT_N: case NODE_WHILE: case NODE_UNTIL:{ LABEL *prev_start_label = iseq->compile_data->start_label; LABEL *prev_end_label = iseq->compile_data->end_label; LABEL *prev_redo_label = iseq->compile_data->redo_label; VALUE prev_loopv…
個々の break 文などのコンパイルは、いつも通り case NODE_BREAK で行われます。でも、その前に NODE_WHILE で while をコンパイルする時点で、あらかじめ準備しておかなくてはいけないことがいくつもあります。注意点を列挙してみました。 break, next, re…
第5回です。前回はwhileループのコンパイルを途中まで読んだところで終わりました。普通に何事もなくループが回るケースは、前回読んだ範囲でカバーできています。今回は、ループにからむ制御構造 break, next, redo を扱うためのコンパイル処理について見…