ひとり勉強会

ひとり楽しく勉強会

NODE_FLIP系

NODE_DOTの範囲式が条件式として使われると、特別な意味になります。そういう位置にある範囲式はNODE_DOTではなくNODE_FLIPとしてコンパイルされます。

1 .. 式2

は「式1が真になるまでは偽を返し、その後は式2が真を返すまでは真を返します。式2が真になれば状態は偽に戻ります」となっているそうです。つまり、この範囲式を評価するには、今「式1が真になるまで」の状態なのか、「その後は式2が真を返すまでは」の状態なのかをどこかに記憶しておく必要があります。
現在のYARVの実装では、範囲式の状態を保存する領域へのアクセスは、getspecial で行います。

ADD_INSN2(ret, nd_line(node), getspecial, INT2FIX(node->nd_cnt),
          INT2FIX(0));

構文解析の段階で node->nd_cnt に$1,$2などとは重ならない番号が入っているので、それを利用しています。状態を記憶するために、式1待ちのときはfalse、式2待ちのときはtrueを入れます。というわけで、生成されるコードはこちらの通り。

  getspecial
  branchif lend
    # 状態がtrueならlend:へジャンプ
  eval 式1
  dup
  branchunless lfin
    # 式1 が falseなら式全体がfalse
    # 式1 が trueなら、それを状態に記憶
  setspecial
lend:
  eval 式2
  branchunless ltrue
    # 式2がfalseなら式全体がtrue
    # 式2がtrueなら、falseを状態に記憶
  putobject false
  setspecial
ltrue:
  putobject true
lfin: