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 へ変換して
いる箇所の対応がまだ
とりあえず動くレベルなのでコードの整理を
したい