ひとり勉強会

ひとり楽しく勉強会

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の実行部分を読むときにチェックしようと思います。コンパイル処理を読むあいだは、名前でだいたい意味をわかったつもりになることにします。(^^;)