Text
        
        
          Page: 1
          Rubyのリテラルオブ
ジェクト生成をparse.y
から卒業させる
Fukuoka.rb #333 Ninja Talk 大会
         
        
        
          Page: 2
          自己紹介
S.H.
永和システムマネジメント
アジャイル事業部所属 & 構文解析研究部員
Hamada.rb
時々Rubyにパッチを投げてます
         
        
        
          Page: 3
          話すこと
リテラルオブジェクトの生成をparse.y以外
でしたい背景
リテラルオブジェクトの生成をparse.y以外
でさせる方法
今後の対応
         
        
        
          Page: 4
          背景(1)
Numeric などのリテラルが parse.y で
Ruby のオブジェクトとして生成されている
Ruby のオブジェクトを作っているので GC
から離せない
parse.y を Universal Parser として扱うた
めには C API を自前で用意する必要がある
         
        
        
          Page: 5
          背景(2)
リテラルの生成を別の場所へ移行できれば
GC との切り離しができる
Universal Parser の C API への依存を減らすことが
できる
         
        
        
          Page: 6
          背景(3)
より詳しい話は Ruby Parser開発日誌 (10) -
parse.y リファクタリングチャレンジ はじ
めました
         
        
        
          Page: 7
          対応方法(ex: Numeric)
rubyparser.hにリテラルの生成に必要な構
造体を追加
compile.cで、その構造体を使ってリテラ
ルを生成する
parse.yで構造体を使って値をセットする
         
        
        
          Page: 8
          rubyparser.hに構造体を追加
enum rb_literal_type {
integer_literal,
float_literal,
rational_literal
};
         
        
        
          Page: 9
          rubyparser.hに構造体を追加
typedef struct rb_numeric_literal_info {
int tminus;
int base;
int seen_point;
int is_imaginary;
} rb_numeric_literal_info_t;
         
        
        
          Page: 10
          rubyparser.hに構造体を追加
typedef struct rb_literal_struct {
char *val;
enum rb_literal_type type;
rb_numeric_literal_info_t numeric_literal_info;
} rb_literal_t;
         
        
        
          Page: 11
          rubyparser.hに構造体を追加
typedef struct RNode_LIT {
NODE node;
VALUE nd_lit;
VALUE not_used;
VALUE not_used2;
rb_literal_t *literal;
} rb_node_lit_t;
         
        
        
          Page: 12
          compile.cでリテラルを生成
VALUE
rb_compile_numeric_literal(rb_literal_t *literal)
{
if (literal->type == integer_literal) {
return rb_compile_integer_literal(literal);
} else if (literal->type == float_literal) {
return rb_compile_float_literal(literal);
} else if (literal->type == rational_literal) {
return rb_compile_rational_literal(literal);
}
return 0;
}
         
        
        
          Page: 13
          compile.cでリテラルを生成
static VALUE
rb_compile_integer_literal(rb_literal_t *literal)
{
VALUE lit = rb_cstr_to_inum(literal->val, literal->numeric_literal_info.base, FALSE);
return compile_numeric_literal(literal, lit);
}
         
        
        
          Page: 14
          compile.cでリテラルを生成
static VALUE
compile_numeric_literal(rb_literal_t *literal, VALUE val)
{
if (literal->numeric_literal_info.tminus) {
val = compile_negative_numeric(val);
}
if (literal->numeric_literal_info.is_imaginary) {
val = rb_complex_raw(INT2FIX(0), val);
}
return val;
}
         
        
        
          Page: 15
          parse.yで構造体に値をセット
static enum yytokentype
set_number_literal(struct parser_params *p, enum yytokentype type, int suffix, int base, int seen_point)
{
/* ... */
rb_literal_t *literal = malloc(sizeof(rb_literal_t));
literal->val = strdup(tok(p));
literal->numeric_literal_info.tminus = FALSE;
literal->numeric_literal_info.base = base;
literal->numeric_literal_info.seen_point = seen_point;
literal->numeric_literal_info.is_imaginary = FALSE;
literal->numeric_literal_info.is_tokenline = FALSE;
/* ... */
}
         
        
        
          Page: 16
          できたもの
[WIP] Introduce rb_literal_t struct for
purge literal generation in parse.y
         
        
        
          Page: 17
          対応状況
Numeric(Fixnum, Bignum, Float,
Rational, Complex) は対応完了
Symbol は一部対応
そのほか細々としたものにも対応中
         
        
        
          Page: 18
          今後の対応
Ractor 周りでのリテラルオブジェクトの処
理
NODE_STR などから NODE_LIT へ変換して
いる箇所の対応がまだ
とりあえず動くレベルなのでコードの整理を
したい