Rabbit Slide Show

Rubyのリテラルオブジェクト生成をparse.yから卒業させる

Description

Fukuoka.rb #333 Ninja Talk 大会で話した「Rubyのリテラルオブジェクト生成をparse.yから卒業させる」のスライドです。

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

Other slides