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);
つづく。