ひとり勉強会

ひとり楽しく勉強会

2006-12-15から1日間の記事一覧

まとめ

以上、そろそろ構文木から命令列リストへの変換を読むのに飽きてきたので、一気に駆け抜けて終わらせようとした軌跡でした。あと残っているのはクラス/メソッド定義のような、定義関係のノードです。次回はそこを読んで、一旦ここまで9回分をスライドか何か…

動的文字列&正規表現

文字列リテラルにも色々ありまして NODE 例 NODE_DSTR "a = #{a}" NODE_EVSTR "#{a}" 文字列がputstring命令になるのは、式展開が含まれていない、単純な文字列リテラルのときだけです。 "値は #{a} と #{b} です" のように式展開が含まれる場合は NODE_DSTR…

リテラル系

リテラル式は、そのリテラルをスタックに積む命令1個にコンパイルされます。対応表はこうです。 NODE 命令 NODE_LIT putobject NODE_SELF putself NODE_NIL putnil NODE_TRUE putobject true NODE_FALE putobject false NODE_STR putstring

NODE_OPTBLOCK

YARVの最適化の一つとして、「ブロックのインライン化」があります。例えば 3.times { ブロックの中身 } をブロックを作ったりyieldで呼んだりすると、スタック操作が無駄に発生してしまって効率がよくありません。あと、ブロックを使うとredoやnextが例外に…

BEGIN と END

大文字の BEGIN BEGIN { ... } は、そのファイルの他の部分より先に必ず評価されるブロックで、構文解析の段階で、NODE_PRELUDE というノードになります。構文解析器がソースコードの中のBEGINブロックを全部取り出して node nd_head : ソース中のBEGINブロ…

NODE_MATCH 系

ノードは3種類ありますが、要するにどれも =~ です。基本は、単純に =~ メソッドを呼ぶだけです。 case NODE_MATCH: case NODE_MATCH2: case NODE_MATCH3:{ ... 思いっきり略 ... COMPILE(recv, "reciever", node->nd_recv); COMPILE(val, "value", node->n…

NODE_FLIP系

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

NODE_DOT系

"a".."z" 0...10 のようなRangeオブジェクトを表す式です。ドット2個の NODE_DOT2 とドット3個の NODE_DOT3 があって、どちらもnewrange命令にコンパイルされて引数のフラグで区別されます。 case NODE_DOT2: case NODE_DOT3:{ int flag = type == NODE_DO…

NODE_HASH

ハッシュリテラルです。 {"aaa",3,"bbb",4} {"ccc"=>5,"ddd"=>6} newarrayのハッシュ版命令「newhash」があるので、実はこれも、左から順に要素をスタックに積んで、newhashするだけなのです。重要なとこだけコンパイラのコードを抜粋すると、こうです。 cas…

NODE_VALUES

return 1,2,3 の 1,2,3 などなどの時に出現するノードなようです。要するに配列なので、そのまま順番に評価してnewarray、というコードにコンパイルされます。全部リテラルな時の最適化はこっちにはありませんでした。

NODE_ARRAY

配列式のコンパイルです。たとえば [a,b,c] という式は eval a eval b eval c newarray 3こういう命令列になります。newarray がスタックから値を拾ってきて配列オブジェクトを作る命令です。コンパイル処理は compile_array という補助関数に丸投げです。 c…

変数/定数読み取り

Rubyには変数にも色々種類があります...というのは、代入文のところでやりました。 種類 NODE 命令 メソッドローカル変数 NODE_LVAR getlocal ブロックローカル変数 NODE_DVAR getdynamic グローバル変数 NODE_GVAR getglobal インスタンス変数 NODE_IVAR ge…

NODE_RETURN

return は メソッド定義の直下からreturnする場合 メソッドの中のブロックの中からreturnする場合 でコンパイル結果の命令列が変わってきます。それ以外の場所(クラス定義の直下や、トップレベル)でreturnしようとするとエラーです。 どちらも、breakのコ…

NODE_YIELD

yield は、呼び出すものがブロックに変わるだけで、本質的にはメソッド呼び出しです。ただし、ブロックにブロックを渡したりはしません。あとレシーバを考える必要もないです。その分 call や super より簡単です。 引数をスタックに積んで 呼び出し(invoke…

NODE_SUPER

最初は super のコンパイルです。親クラスの同じメソッドに処理を回すやつです。super には二種類あって、 super(100) # 引数つきsuper super # 引数なしsuper 引数つきの方は NODE_SUPER、引数なしの方は NODE_ZSUPER と構文解析の段階で分かれています。ZS…

YARVソースコード勉強会 (8)

わわわ!オレンジニュースに載ってる!!! まとめエントリは本当に目次だけで不親切だったので(すみません。。。)、さっき少しだけ説明も追記しときました。さて、では第8回を開始します。今回から読むバージョンをr584にあげました。といっても、compil…