NODE_IF
次はif-then-else文です。elseのないif文やunless文、三項演算子a?b:cも全部構文解析の段階でこのノードにまとめめられるので、コンパイラは1種類のif文だけ気にすれば済むわけです。
コンパイルする処理はこうなっています。
case NODE_IF:{ DECL_ANCHOR(cond_seq); DECL_ANCHOR(then_seq); DECL_ANCHOR(else_seq); LABEL *then_label, *else_label, *end_label; then_label = NEW_LABEL(nd_line(node)); else_label = NEW_LABEL(nd_line(node)); end_label = NEW_LABEL(nd_line(node)); compile_branch_condition(iseq, cond_seq, node->nd_cond, then_label, else_label); COMPILE_(then_seq, "then", node->nd_body, poped); COMPILE_(else_seq, "else", node->nd_else, poped); ADD_SEQ(ret, cond_seq); ADD_LABEL(ret, then_label); ADD_SEQ(ret, then_seq); ADD_INSNL(ret, nd_line(node), jump, end_label); ADD_LABEL(ret, else_label); ADD_SEQ(ret, else_seq); ADD_LABEL(ret, end_label); break; }
条件部 node->nd_cond をコンパイル(詳しくはあとで)して、then部(nd_body)をコンパイルして、else部(nd_else)をコンパイルして、ラベルを挟み込んで並べてます。特に不思議なところもないと思います。
cond_seq (条件判定してジャンプするコード) then_label: then_seq (nd_bodyをコンパイルしたコード) jump end_label else_label: else_seq (nd_elseをコンパイルしたコード) end_label:
ここで始めてYARVの具体的な命令を追加する処理 ADD_INSNL(... jump ...) が出てきました。それぞれの命令については、VMの実行部分を読むときにチェックしようと思います。コンパイル処理を読むあいだは、名前でだいたい意味をわかったつもりになることにします。(^^;)