ひとり勉強会

ひとり楽しく勉強会

NODE_MATCH 系

ノードは3種類ありますが、要するにどれも =~ です。基本は、単純に =~ メソッドを呼ぶだけです。

case NODE_MATCH:
case NODE_MATCH2:
case NODE_MATCH3:{
  ... 思いっきり略 ...

  COMPILE(recv, "reciever", node->nd_recv);
  COMPILE(val, "value", node->nd_value);

  ... 思いっきり略 ...

  ADD_SEQ(ret, recv);
  ADD_SEQ(ret, val);
  ADD_SEND(ret, nd_line(node), ID2SYM(idEqTilde), INT2FIX(1));

ただし、るびま で解説されている最適化が入ることがあります。idEqTilde を send する代わりに、「=~が再定義されていなければ、正規表現マッチ処理をする。再定義されていれば諦めてsendする」という意味の opt_regexpmatch 命令を使うという最適化です。Ruby では正規表現のマッチは非常によく使われるので、メソッド呼び出しのコストを回避する価値があるというわけです。
こちらがその最適化版を生成するコード

if (iseq->compile_data->option->specialized_instruction) {
  /* TODO: detect by node */
  if (recv->last == recv->anchor.next &&
      INSN_OF(recv->last) == BIN(putobject) &&
      nd_type(node) == NODE_MATCH2) {
        ADD_SEQ(ret, val);
        ADD_INSN1(ret, nd_line(node), opt_regexpmatch1,
          OPERAND_AT(recv->last, 0));
  }
  else {
    ADD_SEQ(ret, recv);
    ADD_SEQ(ret, val);
    ADD_INSN(ret, nd_line(node), opt_regexpmatch2);
  }
}

使われてる正規表現リテラルなら、opt_regexpmatch1。そうでなければ opt_regexpmatch1 と、さらに細かく分かれています。