kaneko.y × hasumikin parser Slack Thread Log
ログ消えるの忍びないなって思ったので転記した
kaneko.y
出来上がるsoの未解決のsymbolは以下の通りです
code:c
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w __cxa_finalize@@GLIBC_2.2.5
w __gmon_start__
U __stack_chk_fail@@GLIBC_2.4
U exit@@GLIBC_2.2.5
U free@@GLIBC_2.2.5
U malloc@@GLIBC_2.2.5
U memchr@@GLIBC_2.2.5
U memcpy@@GLIBC_2.14
U memmove@@GLIBC_2.2.5
U memset@@GLIBC_2.2.5
U stpcpy@@GLIBC_2.2.5
U strcmp@@GLIBC_2.2.5
U strlen@@GLIBC_2.2.5
U strncmp@@GLIBC_2.2.5
2023-12-30 17:29:29
hasumikin
正月からやります!!!
2023-12-30 20:12:28
hasumikin
ビルドできることだけとりあえず確認した
2023-12-31 09:28:04
hasumikin
@kaneko.y
RubyオブジェクトのArrayを追い出す作業をちょっとずつ進めています。
ひとつ基本的な確認をわすれていたのですが、 cppflags=-DUNIVERSAL_PARSER で./configureしてmakeする、でいいんですよね?
現在の状況:
• parse.y内の rb_ary_xxxx() を無くしていこうとしている
• (上で話したように) #ifdef RIPPER 内はよくわからないのでいったん無視している
• 新たに rb_parser_ary_t という素朴な構造体と rb_parser_ary_xxxx() という素朴な関数群を書いて、 rb_ary_xxxx() を素朴に置き換えてみた
• make main は通る
• make all とか main test-all TESTS=./test/ruby とかはコアダンプする(後述)
で、いくつか質問させてください:
• ここ、 rb_ractor_make_shareable() に渡すにはRubyのArrayじゃないと難しそうなので、WIPコミットのようにいったんコメントアウトしてますが、どうなんでしょうか
• 現在、 オレオレrb_parser_ary_xxxx() 内でのアロケートにひとまず xmalloc() を使用しているのですが、これはどうなんでしょうか
• make でのコアダンプはGenerating RDoc documentationのなかでGCまわりで起きるので、てきとうに GC.stop すると回避できたりする(その先で別の原因でコアダンプするけど、それは追々考える)、のですが、オレオレrb_parser_ary_t構造体自体のGCはどう考えるべきなんでしょうか(なにもわからない)
ほかにもいろいろ聞きたいけど、いったんここまで書いておきます。
きょうこれから研究つづけます
2024-01-28 09:05:11
kaneko.y
buildについては一度 make clean してから make DEFS="-DUNIVERSAL_PARSER=1" -j4 main をするのがよいかと思います。
2024-01-28 09:41:36
kaneko.y
あ、cppflags でもいいか。
2024-01-28 09:42:00
kaneko.y
• rb_ractor_make_shareable はそのものをcompile.cに持っていくつもりで手元にwipなpatchがあるので一旦いじらなくて大丈夫です。
• xmalloc でいいと思います。 struct parser_params *p を関数の引数に渡しておいてください。macroで p->config->malloc に展開されるので (universal_parser.c を参照)
• GCについては理想的にはしなくていいようにするのが正解だと思います。つまり rb_parser_ary_t にVALUEを持たせてはいけない。なぜかというと、GC markは基本的にtree構造なんですよね。Aをmarkする、Aが参照しているBをmarkする、Bが参照しているCをmarkする。Bを rb_parser_ary_t , C を rb_parser_ary_t の中のVALUEたちとすると、Bのmarkをだれかがトリガーしないといけないけど、それを誰がやるのかということを考えないといけない。いまのparserの実装だとそれは p->ast になるんですが、そうするとparse中に rb_ast_t から rb_parser_ary_t が参照できるようにしないといけないくてちょっと面倒 (いまは yycompile0 で最後に rb_ast_set_tokens(p->ast, tokens); してparserからastに渡している)。であれば parser_append_tokens で rb_parser_ary_t にいれている内容も同時に脱Objectするのがいいかと。そのうえで rb_ast_t に渡す時 or rb_ast_t が解放されるときにfreeする。
2024-01-28 09:56:12
hasumikin
最後の項はソースと見比べなからこれからよく考えますが、いまのところ大きく間違えたことにはなってなさそうだと理解しました。あざます!
2024-01-28 10:12:19
kaneko.y
RubyのGCについて僕の理解を一応書いておくと、
• mark & sweepなので、markをしていってmarkされてないobjectは回収される
• markをするには起点となるobjectが必要で、それはglobalに置かれていたり(rb_cArrayなど)、Cのstack上にあったりする(保守的GC)
• とすると多くのobjectはglobalではないし、stack上に常にいるわけではないので、どこか他のobjectから参照されていて、参照元のobjectの rb_gc_mark によってmarkされる
2024-01-28 10:44:16
kaneko.y
あー。そういう意味では rb_ruby_parser_mark の rb_gc_mark(p->tokens); で p->tokens の中身を個別にmarkすると一旦は動く気がします。
2024-01-28 10:44:55
hasumikin
Cの構造体に移植しないといけない
これをやってみようと思います。
方針は以下のどっちがよいでしょう?(あるいはなにか別の方法?)
• parser_append_token()に渡ってきたVALUE strをrb_parser_string_tに変換する
• parser_append_token()の第2引数の型をrb_parser_string_tに変更して、呼び出し側がrb_parser_string_tをつくるようにする
後者のほうが筋がよさそうとは思うのですが、 parser_dispatch_delayed_token() のなかの p->delayed.token はVALUEのままがよさそうですよね?(すくなくとも当面は)
2024-01-30 16:10:21
kaneko.y
呼び出し箇所も3ヶ所ですし。どちらでもいいかなと思います。最終的にはRStringが消えて、parser_append_tokensの引数は rb_parser_string_tになることを考えると後者のほうがよいかもですね。
delayed.token まで一度にやると大変だと思います。
2024-01-30 18:39:20
hasumikin
おkです!
2024-01-30 18:43:44
hasumikin
ところで、ぼくのプロポーザルはこんな感じです。
Prismにもすこしちょっかい出すことにしました。
なんとなくことしは通らなそうな気がするけど、仮に通ったら金子さんの話の中のユニバーサルパーサのところと齟齬のないようにやっていきましょう....
code:text
# Title
Unlock Universality: Headway in PicoRuby Compiler and Universal Parsers
# Abstraction
Lrama and Prism are attempting to create a universal parser for Ruby.
However, making a universal parser and using it is not straightforward.
I will show you a new PicoRuby compiler, which has to be the most memory-efficient among all Ruby compilers, designed to leverage the universal parsers.
This journey involves writing an efficient VM code generator and investigating CRuby's internal implementation because, especially, Lrama-generating-parser deeply depends on CRuby.
We need to replace the dependency with a bunch of code so to make the parser universal.
Improving the parsers themselves regarding portability and pluggability is also a challenge.
Let's delve into the concept of universality and give careful consideration to it.
2024-01-30 18:55:17
kaneko.y
完全に立場を忘れていうと、めっちゃききたい
2024-01-30 18:57:48
kaneko.y
ここでいう立場というのは “making a universal parser and using it is not straightforward.” などいろいろなところが僕の力不足なことですね….
2024-01-30 18:58:36
hasumikin
めっちゃがんばる(わたしが
ネタに関しては僕の場合無限にあるので、いかようにでも調整可能ですよ。
2024-01-30 19:00:44
hasumikin
はいw
2024-01-30 19:01:05
kaneko.y
いや、これ通らないですかね。はじめて第三者が評価する話だと思うんですよね
2024-01-30 19:02:27
hasumikin
まあそうですね
2024-01-30 19:02:51
hasumikin
ユニバーサルパーサの評価(というか利用、とパッチ充て)を前面に出すか、
オレの書くエムルビー互換コンパイラを前面に出すか、
でちょっと悩んではいます。detailsをどう書くか
2024-01-30 19:04:53
kaneko.y
そう、ちょっと方向がいくつかに分散しているなとは思いました
2024-01-30 19:05:23
hasumikin
あと一晩かんがえます
2024-01-30 19:06:00
hasumikin
たとえばこういうあたりの rb_ary_new() をオレオレパーサ専用アレイに置き換えても、 lit がGCが処理できるデータじゃないとSEGVしてしまうので、そのオレオレアレイ構造体を TypedData_Wrap_Struct でラップして動かしてみました。
そしたらSEGVはしなくなったっぽいのですが、それって結局まだVALUEじゃん:thinking_face:?ってなってます。
これは「すくなくともRArrayではなくなった」ということにある程度の価値があると考えていいんでしょうか...?
あとからGCを剥がすタイミングでこのパッチにさらにパッチを充てるという方法で、先に進める?
あるいは、なにかやるべきことを間違ってるでしょうか?
いまは(とにかくGCで落ちなくはなったので)、
ast_node_all_tokens でRubyのobjectを生成するようにしたいです。
これをやってます
2024-02-09 16:19:38
kaneko.y
shareable_literal_constant はまるっとcompile.cに持って行くので一旦無視して大丈夫です。
一方で keep_tokens はparserとastの管理するデータなので、compile.cに持っていきようがないので、parser_arrayのようなデータ構造が必要になります
2024-02-10 13:12:49
hasumikin
いったん無視していいと言うのは、TypedData_Wrapしないで、GCで落ちる状態のままでいい、という意味ですか?
2024-02-10 15:40:22
kaneko.y
shareable_literal_constant が rb_ary_new などのRubyのarrayに依存していますが、そこはそのまま依存させておいて大丈夫です。
2024-02-10 18:22:53
hasumikin
把握
2024-02-10 18:36:51
hasumikin
@kaneko.y
「token情報からVALUEを剥がしておいて、 ast_node_all_tokens() でVALUEをつくる」にあたって、
現状↑ここでは INT2NUM が使われていて、つまりBignumになる可能性を排除していないですが(ですよね?)、
オレオレtoken構造体のメンバ型は uint64_t じゃまずいでしょうか?
2024-02-13 10:44:50
hasumikin
code:c
typedef struct rb_code_position_struct {
int lineno;
int column;
} rb_code_position_t;
typedef struct rb_code_location_struct {
rb_code_position_t beg_pos;
rb_code_position_t end_pos;
} rb_code_location_t;
こうなっているから、単純にintでいいのかな、と思った
2024-02-13 10:54:16
kaneko.y
intでいい気がします
2024-02-13 10:55:55
hasumikin
はい
2024-02-13 10:56:22
hasumikin
@kaneko.y
p->tokens をオレオレアレイで組み立てて ast_node_all_tokens() のなかでRArrayにしてやるというパッチが、テストではコアダンプしなくなった(2つエラーがでるが、あとで考える)のですが、
これはつまり p->ast->node_buffer->tokens = p->tokens にしちゃっていいんでしょうか?
言い換えると、 node_buffer->tokens はもはやVALUEじゃないというか、GCの対象じゃないってこと?
(ただ、xmallocしたオブジェクトってどうやって(いつ)freeするのか、そのへんの作法はまだ考えていない)
2024-02-13 17:33:48
hasumikin
もうひとつ質問がありまして、 p->debug_lines はオレオレ化したほうがいいんでしょうか?(いまはまだVALUEのままにしてあります)
2024-02-13 17:57:41
kaneko.y
1つ目の質問について。
ast_node_all_tokens でRubyのarrayにしているのであれば、 ast->node_buffer->tokens も p->tokens もオレオレ Arrayにできると思いますし、そのほうがいいです。
freeについては nodeは rb_node_buffer_free で、parser側は rb_ruby_parser_freeです。parserは parser_set_encode で例外を出して大域脱出するケースがあったはずなので、 yycompile0 の rb_ast_set_tokens の直後に p->tokens = NULL; にしてどちらか一方でだけfreeするようにするのがいいと思います。
2024-02-13 18:16:11
kaneko.y
2つ目。
debug_lines は一旦そのままにしておいてください。最終的には置き換えると思いますが、ちょっとまだ細かい部分で挙動を把握しきれていないので
2024-02-13 18:17:03
hasumikin
オレオレアレイの要素になるのは rb_parser_string_t * だけじゃないので、freeしていくにあたってそれぞれのfreeの仕方(関数)を知らないといけないと思うんです。
そうするとたとえば、rb_parser_string_tのメンバにrb_parser_value_tみたいなメンバを生やすような必要がありそうでは、と思ったですがどうでしょうね?
2024-02-13 19:00:21
kaneko.y
• tag付き構造体
• arrayにenumを埋め込む
• arrayにfree関数を埋め込む
うーん
2024-02-13 19:12:48
kaneko.y
いまって rb_parser_string_t * 以外が要素になることあるんでしたっけ。小さく始めたいという気持ちがあり
2024-02-13 19:16:28
hasumikin
いまのところ要素はastのトークンだけなので、決め打ちでもfreeできますね。とりあえずそのようにしておきます
2024-02-13 19:46:12
hasumikin
@kaneko.y
rb_ruby_parser_free() の中で p->ast->node_buffer->tokens をfreeするっていうのを素朴に書いてみたところ、 make test-all TESTS=./test/ruby 中にgc.cのなかでSEGVします。
どうも p->ast のアドレスがxmallocで確保するアドレス範囲になくて、スタックアドレス?IMEMO?のやつが渡ってきてSEGVしているっぽいようで、ひきつづき調査中なのですけど、なにかヒントがあれば教えてくださいmm
2024-02-14 18:23:51
kaneko.y
rb_ruby_parser_freeでfreeしていいのは p->tokens で、 p->ast->node_buffer->tokens のfreeは rb_node_buffer_free でやるのが正しいと思います
2024-02-14 18:38:10
hasumikin
そうか….
ここで
rb_ast_set_tokens の直後に p->tokens = NULL; にして
って言ってたのは、astより先にpが消えるからですね、というのを理解して直していったら動くようになりました。
((TEST_RIPPER_RATIO=1) make test-all TESTS=./test/ruby は何やらエラーがでる=添付画像=けど、masterブランチでも同じエラーがでるので別にいいのかなと思っています)
PRできるようにリファクタリングなどやっていきまする
2024-02-15 17:29:16
kaneko.y
astより先にpが消えるから
すごく厳密にいうとparser paramsもastも元を辿るとGCで管理されています(今後もparse.yの外側のCRubyの世界ではdata_wrapするはず)。
GCなのでどちらから消えるかは実装依存です。
なのでどちらかというとそのタイミングで所有権が移動するからですね
2024-02-15 17:51:27
hasumikin
なるへそ
2024-02-15 17:57:43
hasumikin
ドラフトでPRつくりました。
~CIが落ちているのはアラン・ウーさんのYJITの関係ぽいので置いといて、~(ややこしそうなのでmasterのマージを取り消してforce pushしなおした)
気になっているのは↓ここ、
node.hにオレオレrb_parser_ary_t *型がにじみ出てしまうのはマズいですかね?
あとrb_parser_ary_free()関数が-Wunused-function警告に引っかかってしまった。既存のrb_parser_str_hash()も同じ警告がでているけど
2024-02-17 10:48:08
kaneko.y
ありがとうございます。
node.hにオレオレrb_parser_ary_t *型がにじみ出てしまう
これはOKです。秘匿したいのであれば、node_buffer_structを丸ごとopaqueにする必要がありますが、いまはしていないので
2024-02-18 18:00:03
hasumikin
@kaneko.y
parser_append_tokens()に渡ってきたenum yytokentype tをCの文字列表現に変換する方法を探しているのですが
rb_id2str()だとVALUEになってしまって残念な気がします....
なんかいい方法ありますか?
2024-02-19 19:34:09
hasumikin
rb_id2nameか....
2024-02-19 19:36:18
hasumikin
でも中ではVALUEをつかっているそれはそう
2024-02-19 19:37:44
kaneko.y
parser_token2idを変更して、char * もしくは rb_parser_string_t * を返すようにしてしまっていいと思います。この関数はこのためだけにある関数のはずなので
2024-02-20 09:20:54
hasumikin
あーなるほど、それよさそうですね。
code:c
// master
if (p->debug) {
rb_parser_printf(p, "Append tokens (line: %d) %"PRIsVALUE"\n", line, ary);
}`
これを、VALUEつかわず単純に再現しようと思うとこんな感じになってしまうの、なんだかなぁ:thinking_face: という感じなのですがどう思いますか?
` // 作業
if (p->debug) {
char *debug_token;
case '\n':
debug_token = "\\n";
break;
case '\r':
debug_token = "\\r";
break;
case '\t':
debug_token = "\\t";
break;
case '\\':
debug_token = "\\\\";
break;
case '"':
debug_token = "\\\"";
break;
default:
debug_token = str->ptr;
break;
}
line,
token->id,
"parser_token2idを改変した関数の結果",
debug_token,
token->loc.beg_pos.lineno,
token->loc.beg_pos.column,
token->loc.end_pos.lineno,
token->loc.end_pos.column);
}
2024-02-20 09:32:19
kaneko.y
ruby_escaped_char などと似たような関数が必要ということですよね。必要なのであれば実装するのでいいと思います。
String Objectに近しいものを作らないといけないのはわかっていて、そこは愚直に実装していくという腹をくくっているので、関数を足すことに抵抗はないです。
すでに coderange を実装したので、今更1つ2つ増えたところでw という感じです
2024-02-20 10:05:43
hasumikin
了解です!(確認できてよかった
2024-02-20 10:07:48
kaneko.y
このescapeって対象がtokenじゃなくて rb_parser_string_t * ですよね。そうすると全文字をloopでなめないとダメだったりしません?
2024-02-20 10:10:27
hasumikin
そうなんですよ!
2024-02-20 10:13:36
hasumikin
しかも文字コード問題があるのでは
2024-02-20 10:15:19
kaneko.y
rb_str_escape のportが必要かも、そしてそいつは rb_enc_precise_mbclen を呼んでいる
2024-02-20 10:23:50
kaneko.y
• rb_inspect
◦ rb_str_escape
▪︎ ruby_escaped_char
ははは
2024-02-20 10:29:56
kaneko.y
まあでも幸いいまある道具立てでいけるとおもいますよ
2024-02-20 10:30:30
hasumikin
mrubyはUTF-8だけでいいってまつもとさんが言ってたので、関数をビルド仕分けることになるのかな
2024-02-20 10:35:23
kaneko.y
encodingをとってくるところの関数をuser側が定義することになると思うので、そこで調整するんだと思います
2024-02-20 10:37:13
kaneko.y
例えばいま parse.y には parser_set_encode というマジコメを処理する関数があるんですが、この部分は整理したうえで外からもらうようになります。
2024-02-20 10:38:13
hasumikin
ところで、parser_append_tokens()のなかでif (p->debug)が真になるのってどういうときなんでしょうか?
RubyVM::AbstractSyntaxTree.parseメソッドにdebug: trueのようなオプションを渡すとp->debug=1になる、みたいなコードを探したけど、なさそうで
2024-02-20 14:36:59
kaneko.y
rubyのコマンドラインオプションでいうと -y や --dump=y を渡した時です。
2024-02-20 16:50:09
hasumikin
おかしいな。なにか勘違いしているかな...
ruby -y -e "RubyVM::AbstractSyntaxTree.parse('1 + 2')"
ってやったとき、AbstractSyntaxTreeが内部でつくるparser_paramsには-yオプションは渡りませんよね?
2024-02-20 16:54:15
hasumikin
code:console
ruby -y -e "RubyVM::AbstractSyntaxTree.parse('1 + 2', keep_tokens: true)"
• トップレベル(ruby.c)の処理が"RubyVM::AbstractSyntaxTree.parse('1 + 2', keep_tokens: true)"をパースするときには、keep_tokens: trueがパーサに渡らない(渡すための起動オプションがない←ここが違う?)ので、parser_append_tokens()に入るルートがない
• Rubyのランタイム内でAbstractSyntaxTreeが'1 + 2'をパースするときは、keep_tokens: trueがパーサに渡るが、p->debug=1にするAPIがない(←ここが違う?)ので、parser_append_tokens()のなかのif (p->debug)が真になるルートがない
と思っています。見落としがあるかな...???
2024-02-20 17:23:04
kaneko.y
たしかに両方設定できるパスはないかも…
2024-02-20 22:43:54
kaneko.y
常にdebugモードでよければ
code:console
diff --git a/parse.y b/parse.y
index b8f03b5473..50cfa20930 100644
--- a/parse.y
+++ b/parse.y
@@ -16052,6 +16052,7 @@ rb_ruby_parser_keep_tokens(rb_parser_t *p)
p->keep_tokens = 1;
// TODO
p->tokens = rb_ary_new();
+ p->debug = 1;
}
2024-02-20 22:47:53
kaneko.y
ruby側で制御できるようにするには
code:console
$ git diff
diff --git a/ast.c b/ast.c
index b76547a8e8..b5c0e97366 100644
--- a/ast.c
+++ b/ast.c
@@ -64,7 +64,7 @@ ast_new_internal(rb_ast_t *ast, const NODE *node)
return obj;
}
-static VALUE rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens);
+static VALUE rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens, VALUE yydebug);
static VALUE rb_ast_parse_file(VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens);
static VALUE
@@ -85,13 +85,13 @@ ast_parse_done(rb_ast_t *ast)
}
static VALUE
-ast_s_parse(rb_execution_context_t *ec, VALUE module, VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
+ast_s_parse(rb_execution_context_t *ec, VALUE module, VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens, VALUE yydebug)
{
- return rb_ast_parse_str(str, keep_script_lines, error_tolerant, keep_tokens);
+ return rb_ast_parse_str(str, keep_script_lines, error_tolerant, keep_tokens, yydebug);
}
static VALUE
-rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
+rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens, VALUE yydebug)
{
rb_ast_t *ast = 0;
@@ -100,6 +100,7 @@ rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE
if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser, Qtrue);
if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
+ if (RTEST(yydebug)) rb_parser_set_yydebug(vparser, Qtrue);
ast = rb_parser_compile_string_path(vparser, Qnil, str, 1);
return ast_parse_done(ast);
}
@@ -266,7 +267,7 @@ ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script
node = rb_ast_parse_array(lines, keep_script_lines, error_tolerant, keep_tokens);
}
else if (e_option) {
- node = rb_ast_parse_str(rb_e_script, keep_script_lines, error_tolerant, keep_tokens);
+ node = rb_ast_parse_str(rb_e_script, keep_script_lines, error_tolerant, keep_tokens, Qfalse);
}
else {
node = rb_ast_parse_file(path, keep_script_lines, error_tolerant, keep_tokens);
diff --git a/ast.rb b/ast.rb
index 51ee5b3d59..395302c39d 100644
--- a/ast.rb
+++ b/ast.rb
@@ -55,8 +55,8 @@ module RubyVM::AbstractSyntaxTree
#
# Note that parsing continues even after the errored expression.
#
- def self.parse string, keep_script_lines: RubyVM.keep_script_lines, error_tolerant: false, keep_tokens: false
- Primitive.ast_s_parse string, keep_script_lines, error_tolerant, keep_tokens
+ def self.parse string, keep_script_lines: RubyVM.keep_script_lines, error_tolerant: false, keep_tokens: false, yydebug: false
+ Primitive.ast_s_parse string, keep_script_lines, error_tolerant, keep_tokens, yydebug
end
# call-seq:
2024-02-20 22:51:11
kaneko.y
code:console
RubyVM::AbstractSyntaxTree.parse('1 + 2', keep_tokens: true, yydebug: true)
add_delayed_token:7910 (0: 0|0|0)
Starting parse
Entering state 0
Stack now 0
Reducing stack by rule 1 (line 2889):
lex_state: NONE -> BEG at line 2890
vtable_alloc:15271: 0x00006000012bb500
vtable_alloc:15272: 0x00006000012bb520
cmdarg_stack(push): 0 at line 15286
cond_stack(push): 0 at line 15287
-> $$ = nterm $@1 (1.0-1.0: )
....
2024-02-20 22:57:05
hasumikin
yydebugオプションがいいと思います
2024-02-20 22:57:40
kaneko.y
インターフェイスの変更なのでmatz approveが必要なので、masterにいれるにはしばらくかかると思いますmm
2024-02-20 22:58:42
hasumikin
はい
2024-02-20 23:00:07
hasumikin
Parser勢は何人アクセプトされたんだろう。決起集会やりたい
2024-02-21 09:21:52
hasumikin
yydebugの追加ってbugsにチケットつくります?(つくったら教えてください。ぼくのドラフトPRからrefするので)
2024-02-21 09:23:25
kaneko.y
決起集会やりたい。チケットはRipperのも合わせて切る予定です
2024-02-21 09:30:00
hasumikin
universal_parser.cにある#define ruby_snprintf p->config->snprintf って実体は存在してない?ですか?(エスケープ文字列をつくるのにsnprintf的なものがほしいのです)
2024-02-21 17:40:35
hasumikin
snprintf的な関数は、必要なフォーマットが非常に限定的だったので自前の実装でなんとかなりそうだからいったんいいことにして、
別の質問:
UNIVERSAL_PARSERでは#define rb_encoding voidなのってどういう意図ですか?
(onigmo使わないと文字列エスケープするの厳しい....)
2024-02-21 18:36:09
kaneko.y
void * にして扱っているだけなので、 rb_encoding * と書いて大丈夫ですし、onigmoは今後も使う想定です!
2024-02-21 18:47:29
kaneko.y
意図としては rb_encoding に関連するheaderをincludeしなくていいようにするためのマクロです
もうちょっと詳しくいうとparserから見て正規表現とエンコーディングは外にあるものなんですよ。
parserはその中身に関して詳しくは知らないという態度をとる必要があります。
なので、find_encodingのような関数がparserの利用者から渡され、そこに "UTF-8" などを渡すと rb_parser_encoding_t * という実質 void *が返ってくる。で文字列を読むときは rb_parser_enc_precise_mbclen という関数がparserの利用者から渡されるので、そこに rb_parser_encoding_t * を渡す。という感じで中身についてなにも触れずに処理を進めていくようにする方針です。
2024-02-21 18:58:23
kaneko.y
途中の実装としてはこれがあります
2024-02-21 18:58:46
hasumikin
うんうん、たぶん理解しました。
たとえばenc->min_enc_lenが必要だとして、将来的にはint minlen = p->config->enc_mbminlen((rb_parser_encoding_t *)enc);みたいに取得するんだと思いますが、いまいまのところではどうしたらいいでしょう?
↓のモンキーパッチをparse.yにぶっ込んだら動いた、というところまでは来てます:
code:c
typedef rb_encoding _rb_encoding;
typedef OnigEncodingType rb_encoding;
static inline int
rb_enc_mbminlen(rb_encoding *enc)
{
return enc->min_enc_len;
}
2024-02-21 20:39:01
hasumikin
文字列をエスケープする実装の全体はこんな感じで書いたら動いてます
2024-02-21 20:41:40
kaneko.y
普通に rb_enc_mbminlen をつかっていいですよ。
universal parser buildで落ちるとおもうので
• universal_parser.c に #define rb_enc_mbminlen p->config->enc_mbminlen を追加
• rubyparser.h にある rb_parser_config_struct に enc_mbminlen の関数ポインタを追加
• ruby_parser.c で rb_global_parser_config に .enc_mbminlen = rb_enc_mbminlen を追加
でうごくはずです
2024-02-21 22:02:15
hasumikin
ラジャー!
2024-02-21 22:06:10
hasumikin
@kaneko.y
↑これを実装してオレオレarrayのfreeをこう書いた(node.cの中)のですが、
code:c
static void
parser_ary_free(rb_ast_t *ast, rb_parser_ary_t *ary)
{
if (!ary) return;
if (ary->data) {
for (long i = 0; i < ary->len; i++) {
/*
* WIP Items in rb_parser_ary_t are now only rb_parser_string_t. * This may change in the future, so we'll need to check the type of
* the item before freeing it.
*/
parser_string_free(ast, (rb_parser_string_t *)ary->datai); }
xfree(ary->data);
}
xfree(ary);
}
make -j8 test-all TESTS=./test/rubyを回すと、
GC→rb_node_buffer_free()→ast_tokens_free()→parser_ary_free()→parser_string_free()と来て、xfree(str->ptr);でSEGVしてしまいます。
それ以前のどこかでrb_parser_string_t要素がすでに回収されるっていうことですかね?(あいかわらずGCが難しい....
2024-02-23 17:49:46
kaneko.y
いや、rb_parser_string_t 自体はGCで管理していないので他のobjectたとえばNODEとかに渡さなければfreeされることはないと思います
2024-02-24 11:27:10
kaneko.y
2024-02-24 11:28:07
kaneko.y
もしよければSEGVする状態のbranchを僕がみれるところにおいていただけますか? (hasumi/rubyとかでも大丈夫です)
2024-02-24 11:32:25
hasumikin
いま外出してて、戻ったらやります。早くて14時くらいになります :bow::skin-tone-2:
2024-02-24 12:25:11
kaneko.y
あせらずー。ぼくも早くても夜じゃないと見れそうにないので
2024-02-24 12:29:20
hasumikin
お騒がせしました。ただのアホな実装ミスでした。rb_parser_ary_t[rb_parser_ast_token_t->rb_parser_string_t]という構造なのを忘れてrb_parser_ary_t[rb_parser_string_t] としていたり、完全にアホなダブルfreeをやらかしたりしてました:sweat_smile:
2024-02-24 16:16:48
hasumikin
rebaseすると全体のdiffはこうなります
2024-02-25 18:26:37
kaneko.y
ありがとうございます。コメントしました。
2024-02-25 22:17:37
hasumikin
なるほどー。(あした直します)
2024-02-25 22:42:59
hasumikin
このコメントに関連して質問です。freeの関数をparse.yに書くことになるのですが、
同じ作用の関数(群)をparse.yとその他の場所(ast.cやnode.cなど)にも重複して書くことをどの程度まで許容する感じですか?
ぼくの作業より前から、node.c:parser_string_free()とparse.y:rb_parser_string_free()がすでに重複していましたが、こういうのがあんまり増えるのもよくないのかなと思いまして、今後の予定含めて聞かせてください。温度感というか思想というかそんなあたりについて。
(伝わっていると思うけど、いちおう画像で補足するとこうです:左がnode.cで右がparse.y。英語で聞くの面倒だったのでGitHubじゃなくこっちで質問しました)
温度感というか思想というかそんなあたりについて。
当面は重複していても気にせず書いていいよ、ということならそれはそれでいいと思います
2024-02-26 13:18:49
hasumikin
金子さんasakusaのSlack入ってないですね?3/1に東京で何人かあつまって飲むと思うので、もし空いてたら来てください
2024-02-26 14:12:43
kaneko.y
一旦はnode.cとparse.yで重複してもっていてもいいですよ。
2024-02-27 07:59:53
kaneko.y
3/1の件はasakusaのslackのほうに返信しました
2024-02-27 09:55:33
hasumikin
いくつか質問があるのでお手すきのときにお願いしますmm
2024-02-27 15:56:22
kaneko.y
たぶん全部の質問にお返事しました
2024-02-27 19:40:02
kaneko.y
漏れてたら教えてください…
2024-02-27 19:40:02
hasumikin
あざます!漏れてないです
2024-02-27 21:12:11
hasumikin
もらったコメントに対応して、CI通ったようなのでDraftを外しました。中田さんのchange requestがついたままなのですが、これは中田さんにメンションして見てもらえばいいですか
2024-02-29 18:45:52
kaneko.y
そうですね。それでお願いします
2024-02-29 21:03:52
hasumikin
いえーい:v:やんちゃさん見てるー?
2024-03-03 11:45:38
hasumikin
@kaneko.y
(忘れてたけどこれを相談したかった...)rb_parser_ary_tのitemは現状ではrb_parser_ast_token_t*しかこないけ、近い将来はそうじゃないかもしれず、
でも現状rb_parser_ast_token_t*しかこないならそのように書いておいて、用途が拡張されたら引数の宣言を変更するっていうのがいいでしょうか?どう思います?
2024-03-04 15:51:19
kaneko.y
そうですね。次回必要になったときに考えればいいと思うので今回は rb_parser_ast_token_t でいいと思います
2024-03-04 21:12:00
hasumikin
中田さんがapproveしてくれました。
あとは....squash用のコミットメッセージを書きました:
code:md
- Introduce rb_parser_ary_t struct to partly eliminate RArray from parse.y
- In this patch, parser_params->tokens and parser_params->ast->node_buffer->tokens are now rb_parser_ary_t *
- Instead, ast_node_all_tokens() internally creates a Ruby Array object from the rb_parser_ary_t
- Delete rb_ast_tokens() and rb_ast_set_tokens() in node.c
- Implement rb_parser_str_escape()
- This is a port of the rb_str_escape() function in string.c
- It does not depend on VALUE
- Instead, it uses rb_parser_stirng_t *
- This function works when --dump=y option passed
- Because WIP of the universal parser, similar functions like rb_parser_tokens_free() exist in both node.c and parse.y.
Refactoring them may be needed in some way in the future
- Although we considered redesigning the structure: ast->node_buffer->tokens into ast->tokens, we leave it as it is because rb_ast_t is an imemo.
(We will address it in the future)
いかがでしょう (edited)
2024-03-05 18:08:25
kaneko.y
よいと思います!
Instead, it uses rb_parser_stirng_t* の rb_parser_stirng_t と * の間はspaceがあった方が統一感があるかなとおもいました (edited)
2024-03-05 20:25:35
hasumikin
はい、調整お願いします!
2024-03-05 20:49:43
kaneko.y
あれなにかぼくのほうで調整することありますか?
2024-03-05 22:11:34
hasumikin
(こちらで*の前にスペース入れときました。が、)
このコミットメッセージを金子さんがコピペしてGitHub上でsquash mergeしてもらう、という意図でしたが、ぼくの方でsquash rebaseしたほうがいいです?(ruby/rubyのお作法よくしらないので…
2024-03-05 22:20:30
kaneko.y
なるほど、hasumiさんのほうでsquash rebaseしていただけますか? とくに作法はないんですが、僕がGHでの操作が苦手なので。PR作成者の方でやっていただけると楽です。
2024-03-06 09:44:53
hasumikin
リベースしてプッシュしました。CIも通りました(いちどWindowsのテストが落ちて、ポートの競合のせいで落ちたみたいだったので再プッシュしたら通った) (edited)
2024-03-06 13:57:55
hasumikin
(念のためリマインド @kaneko.y )
2024-03-08 09:38:04
kaneko.y
Mergeしました!
2024-03-12 17:18:18
hasumikin
ありがとうございます!つぎにやることを考えます。これやれってのあればください
2024-03-12 18:26:12