ひとり勉強会

ひとり楽しく勉強会

データ構造・構文木のノード

Rubyプログラムはいったん構文木に変換されます。YARVのコアではRubyプログラムを文字列として扱うのではなく、常にこの構文木になった状態を使います。構文木は、以下のような構造体で表現されます。

typedef struct RNode {
    unsigned long flags;
    char *nd_file;
    union {
	struct RNode *node;
	ID id;
	VALUE value;
	VALUE (*cfunc)(ANYARGS);
	ID *tbl;
    } u1;
    union {
	struct RNode *node;
	ID id;
	long argc;
	VALUE value;
    } u2;
    union {
	struct RNode *node;
	ID id;
	long state;
	struct global_entry *entry;
	long cnt;
	VALUE value;
    } u3;
} NODE;

えーとなんだか長いですが。ありがたいことに、RHG 第12章 に完全な解説があります。

  • flags に、ノードの種類(NODE_METHOD, NODE_IF, NODE_STR, 等々) が入っている
  • nd_type(node) というマクロで、ノードの種類をとりだせる
    • switch(nd_type(node)) で処理を切り分けるのが定型パターン
  • ノードの種類に応じて、最大3個の子ノードがある。u1, u2, u3 に入っている
    • 例えばifなら条件式、then式、else式の3つ
    • "u1"のような素っ気ない名前の代わりに、nd_cond や nd_else などのマクロが用意されてて、普通はそれでnode.nd_else のようにアクセスする
    • 要は、node.nd_*** と来たら何か子ノードへのアクセス

これだけ覚えておけばあとはだいたい読めそうです。