ひとり勉強会

ひとり楽しく勉強会

NODE_RESCUE

rescueやelseがある場合は、メインの命令列は次のようにコンパイルされます。(コンパイルするコードは特別なところはないので省略)

start:
  本体
end:
  if(elseがあれば) pop; elseの中身
lcont:
  if(poped) pop

例外ハンドラの登録はこんな感じ。

  /* resgister catch entry */
  ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lcont);
  ADD_CATCH_ENTRY(CATCH_TYPE_RETRY, lend, lcont, 0, lstart);

startからendのあいだで例外が発生したら、rescue(後述)で捕まえて、正常終了したらlcontに抜ける。lendからlcontの間(要するにelse節)でretryがあったら、lstartに戻る。
各rescue節は、NODE_RESBODYに入っていて、別の命令列オブジェクトとしてコンパイルされています。

VALUE rescue = NEW_CHILD_ISEQVAL(node->nd_resq,
                 rb_str_concat(rb_str_new2
                               ("rescue in "),
                               iseq->name),
                               ISEQ_TYPE_RESCUE);

つづく。