rubykaigi.org
1行のRubyプログラムを左から順に評価していきます。
これは意図時にデザインしたルールではなく、実装の結果です。
a[0], a[1] = [b, b]
のときはそうではありません。
発表者のJeremy Evansさんは、Rubyのバグを大量に直しているコミッターの方です。
そのなかでも面白いバグを初回してくれました。
内容はよくわからなかっかです。
ruby --dump=i
を実行するとRubyのinstructionsを表示することがわかりました。
試しに a = 1
のinstructionsを表示してみます。
ledsun@MSI:/m/c/U/led_l►ruby --dump=i -e 'a = 1'
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,5)> (catch: FALSE)
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] a@0
0000 putobject_INT2FIX_1_ ( 1)[Li]
0001 dup
0002 setlocal_WC_0 a@0
0004 leave
表示されている命令の意味はよくわかりません。
a = 2
やb = 1
のinstructionsを表示すると、内容が変わっていることがわかります。
ledsun@MSI:/m/c/U/led_l►ruby --dump=i -e 'a = 2'
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,5)> (catch: FALSE)
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] a@0
0000 putobject 2 ( 1)[Li]
0002 dup
0003 setlocal_WC_0 a@0
0005 leave
ledsun@MSI:/m/c/U/led_l►ruby --dump=i -e 'b = 1'
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,5)> (catch: FALSE)
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] b@0
0000 putobject_INT2FIX_1_ ( 1)[Li]
0001 dup
0002 setlocal_WC_0 b@0
0004 leave
この機能をつかって、a.b, c[0] = d, e
のinstructionsを表示して、Ruby 3.0から3.2までの変更を説明してくれました。
実際に手元のPCで試してみると、発表と同じように表示されるinstructionsが変わっているのがわかります。
ledsun@MSI:/m/c/U/led_l►ruby -v --dump=i -e 'a.b, c[0] = d, e'
ruby 3.0.3p157 (2021-11-24 revision 3fb7d2cadc) [x86_64-linux]
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,16)> (catch: FALSE)
0000 putself ( 1)[Li]
0001 opt_send_without_block <calldata!mid:d, argc:0, FCALL|VCALL|ARGS_SIMPLE>
0003 putself
0004 opt_send_without_block <calldata!mid:e, argc:0, FCALL|VCALL|ARGS_SIMPLE>
0006 newarray 2
0008 dup
0009 expandarray 2, 0
0012 putself
0013 opt_send_without_block <calldata!mid:a, argc:0, FCALL|VCALL|ARGS_SIMPLE>
0015 topn 1
0017 opt_send_without_block <calldata!mid:b=, argc:1, ARGS_SIMPLE>
0019 pop
0020 pop
0021 putself
0022 opt_send_without_block <calldata!mid:c, argc:0, FCALL|VCALL|ARGS_SIMPLE>
0024 putobject_INT2FIX_0_
0025 topn 2
0027 opt_aset <calldata!mid:[]=, argc:2, ARGS_SIMPLE>
0029 pop
0030 pop
0031 leave
ledsun@MSI:/m/c/U/led_l►ruby -v --dump=i -e 'a.b, c[0] = d, e'
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,16)> (catch: FALSE)
0000 putself ( 1)[Li]
0001 opt_send_without_block <calldata!mid:a, argc:0, FCALL|VCALL|ARGS_SIMPLE>
0003 putself
0004 opt_send_without_block <calldata!mid:c, argc:0, FCALL|VCALL|ARGS_SIMPLE>
0006 putobject_INT2FIX_0_
0007 putself
0008 opt_send_without_block <calldata!mid:d, argc:0, FCALL|VCALL|ARGS_SIMPLE>
0010 putself
0011 opt_send_without_block <calldata!mid:e, argc:0, FCALL|VCALL|ARGS_SIMPLE>
0013 newarray 2
0015 dup
0016 expandarray 2, 0
0019 topn 5
0021 swap
0022 opt_send_without_block <calldata!mid:b=, argc:1, ARGS_SIMPLE>
0024 pop
0025 topn 3
0027 topn 3
0029 topn 2
0031 opt_aset <calldata!mid:[]=, argc:2, ARGS_SIMPLE>[CcCr]
0033 pop
0034 pop
0035 setn 3
0037 pop
0038 pop
0039 pop
0040 leave
ledsun@MSI:/m/c/U/led_l►ruby -v --dump=i -e 'a.b, c[0] = d, e'
ruby 3.2.0preview2 (2022-09-09 master 35cfc9a3bb) [x86_64-linux]
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,16)> (catch: false)
0000 putself ( 1)[Li]
0001 opt_send_without_block <calldata!mid:a, argc:0, FCALL|VCALL|ARGS_SIMPLE>
0003 putself
0004 opt_send_without_block <calldata!mid:c, argc:0, FCALL|VCALL|ARGS_SIMPLE>
0006 putobject_INT2FIX_0_
0007 putself
0008 opt_send_without_block <calldata!mid:d, argc:0, FCALL|VCALL|ARGS_SIMPLE>
0010 putself
0011 opt_send_without_block <calldata!mid:e, argc:0, FCALL|VCALL|ARGS_SIMPLE>
0013 newarray 2
0015 dup
0016 expandarray 2, 0
0019 topn 5
0021 swap
0022 opt_send_without_block <calldata!mid:b=, argc:1, ARGS_SIMPLE>
0024 pop
0025 topn 3
0027 topn 3
0029 topn 2
0031 opt_aset <calldata!mid:[]=, argc:2, ARGS_SIMPLE>[CcCr]
0033 pop
0034 pop
0035 setn 3
0037 pop
0038 pop
0039 pop
0040 leave
どうやらJeremy Evansさんはこういうところを直しているみたいです。
instructionsが読めないので、具体的にどうなおしたのかはわかりませんでした。
を読んだら理解できるようになるでしょうか?
tatsu-zine.com