Ruby Issue Tracking System: Issues
https://bugs.ruby-lang.org/
https://bugs.ruby-lang.org/favicon.ico?1711330511
2024-03-12T13:15:42Z
Ruby Issue Tracking System
Redmine
Ruby master - Feature #20331 (Open): Should parser warn hash duplication and when clause?
https://bugs.ruby-lang.org/issues/20331
2024-03-12T13:15:42Z
yui-knk (Kaneko Yuichiro)
<a name="Background"></a>
<h1 >Background<a href="#Background" class="wiki-anchor">¶</a></h1>
<p>Right now, parser warns duplicated hash keys (#1) and when clause (#2).<br>
For example,</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">{</span><span class="mi">1</span> <span class="o">=></span> <span class="ss">:a</span><span class="p">,</span> <span class="mi">1</span> <span class="o">=></span> <span class="ss">:b</span><span class="p">}</span>
<span class="c1"># => warning: key 1 is duplicated and overwritten on line 1</span>
</code></pre>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">case</span> <span class="mi">2</span>
<span class="k">when</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span>
<span class="k">else</span>
<span class="k">end</span>
<span class="c1"># => test.rb:2: warning: duplicated `when' clause with line 2 is ignored</span>
</code></pre>
<p>The parser compares different cardinality numbers.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">{</span>
<span class="mi">1</span> <span class="o">=></span> <span class="ss">:a</span><span class="p">,</span>
<span class="mh">0x1</span> <span class="o">=></span> <span class="ss">:b</span><span class="p">,</span>
<span class="mb">0b1</span> <span class="o">=></span> <span class="ss">:b</span><span class="p">,</span>
<span class="mi">0</span><span class="n">d1</span> <span class="o">=></span> <span class="ss">:b</span><span class="p">,</span>
<span class="mi">0</span><span class="n">o1</span> <span class="o">=></span> <span class="ss">:b</span><span class="p">,</span>
<span class="p">}</span>
<span class="c1"># => test.rb:2: warning: key 1 is duplicated and overwritten on line 3</span>
<span class="c1"># => test.rb:3: warning: key 1 is duplicated and overwritten on line 4</span>
<span class="c1"># => test.rb:4: warning: key 1 is duplicated and overwritten on line 5</span>
<span class="c1"># => test.rb:5: warning: key 1 is duplicated and overwritten on line 6</span>
</code></pre>
<a name="Problem"></a>
<h1 >Problem<a href="#Problem" class="wiki-anchor">¶</a></h1>
<p>Currently this is implemeted by converting string like <code>"123"</code> to Ruby Object and compare them.<br>
It's needed to remove Ruby Object from parse.y for Universal Parser.<br>
I created PR <a href="https://github.com/ruby/ruby/pull/10079" class="external">https://github.com/ruby/ruby/pull/10079</a> which implements bignum for parse.y without dependency on Ruby Object, however nobu and mame express concern about the cost and benefit of implmenting bignum for parser.<br>
I want to discuss which is the best approach for this problem.</p>
<p>By the way, it's needed to calculate irreducible fraction for Rational key if we will keep warning messages.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="err">$</span> <span class="n">ruby</span> <span class="o">-</span><span class="n">wc</span> <span class="o">-</span><span class="n">e</span> <span class="s1">'{10.2r => :a, 10.2r => :b}'</span>
<span class="o">-</span><span class="n">e</span><span class="p">:</span><span class="mi">1</span><span class="p">:</span> <span class="ss">warning: </span><span class="n">key</span> <span class="p">(</span><span class="mi">51</span><span class="o">/</span><span class="mi">5</span><span class="p">)</span> <span class="n">is</span> <span class="n">duplicated</span> <span class="ow">and</span> <span class="n">overwritten</span> <span class="n">on</span> <span class="n">line</span> <span class="mi">1</span>
<span class="o">-</span><span class="n">e</span><span class="p">:</span><span class="mi">1</span><span class="p">:</span> <span class="ss">warning: </span><span class="n">unused</span> <span class="n">literal</span> <span class="n">ignored</span>
<span class="no">Syntax</span> <span class="no">OK</span>
</code></pre>
<a name="Options"></a>
<h1 >Options<a href="#Options" class="wiki-anchor">¶</a></h1>
<a name="1-Warnings-on-parser"></a>
<h2 >1. Warnings on parser<a href="#1-Warnings-on-parser" class="wiki-anchor">¶</a></h2>
<p>Pros:</p>
<ul>
<li>Users of Universal Parser don't need to implement warnings by themselves. I guess developers of other Ruby implementation may get benefit of reducing their effort.</li>
<li>Warnings are shown by <code>ruby -wc</code>.</li>
</ul>
<p>Cons:</p>
<ul>
<li>We need to maintain bignum implementation for parser.</li>
</ul>
<p>There are two approaches for this option.</p>
<a name="1-1-Implement-bignum-for-parser"></a>
<h3 >1-1. Implement bignum for parser<a href="#1-1-Implement-bignum-for-parser" class="wiki-anchor">¶</a></h3>
<p>The PR is this approach, implementing sub set of Ruby bignum for parser.</p>
<a name="1-2-Extract-existing-bignum-implementation-then-use-it"></a>
<h3 >1-2. Extract existing bignum implementation then use it<a href="#1-2-Extract-existing-bignum-implementation-then-use-it" class="wiki-anchor">¶</a></h3>
<p>Make existing bignum implementation to be independent of Ruby Object and use it from both bignum.c and parse.y.</p>
<a name="2-Moving-warnings-logic-into-compile-phase"></a>
<h2 >2. Moving warnings logic into compile phase<a href="#2-Moving-warnings-logic-into-compile-phase" class="wiki-anchor">¶</a></h2>
<p>We can use Ruby Object in compile.c. Then moving the logic into compile.c solves this problem.</p>
<p>Pros:</p>
<ul>
<li>No need to implement bignum for parser.</li>
</ul>
<p>Cons:</p>
<ul>
<li>Users of Universal Parser need to implement warnings by themselves.</li>
<li>Warnings are not shown by <code>ruby -wc</code>.</li>
</ul>
Ruby master - Feature #20257 (Closed): Rearchitect Ripper
https://bugs.ruby-lang.org/issues/20257
2024-02-12T00:46:05Z
yui-knk (Kaneko Yuichiro)
<a name="Abstract"></a>
<h1 >Abstract<a href="#Abstract" class="wiki-anchor">¶</a></h1>
<p>Rearchitect Ripper to provide whole semantic analysis support for Ripper and improve maintainability of Ripper.<br>
This rearchitecture is achieved by modifying Lrama parser generator.</p>
<a name="Background-and-problem"></a>
<h1 >Background and problem<a href="#Background-and-problem" class="wiki-anchor">¶</a></h1>
<p>Ripper is used for parsing ruby code, for example irb and rdoc use Ripper for parsing source codes.<br>
Ripper and Ruby parser share the algorithm of parsing, however internal logic of Ripper is different from parser.<br>
The differences cause three problems:</p>
<ol>
<li>Ripper can not execute some semantic analysis. <a href="https://bugs.ruby-lang.org/issues/10436" class="external">https://bugs.ruby-lang.org/issues/10436</a> is an example of this limitaion. <code>m(&nil) {}</code> raises syntax error but <code>Ripper.sexp("m(&nil) {}")</code> doesn't.</li>
<li>Ripper can not recognize regexp named capture. <a href="https://bugs.ruby-lang.org/issues/18988" class="external">https://bugs.ruby-lang.org/issues/18988</a> is an example.</li>
<li>Makes prase.y complex. For example, the implementation of <code>new_array_pattern</code> is completely different between <a href="https://github.com/ruby/ruby/blob/1949a04f81311660e2d0ec002c48115c63742d0b/parse.y#L14960" class="external">parser</a> and <a href="https://github.com/ruby/ruby/blob/1949a04f81311660e2d0ec002c48115c63742d0b/parse.y#L1707" class="external">ripper</a>.</li>
</ol>
<p>These problems come from the fact parser and Ripper use semantic value stack differently.<br>
Parser stores Node on the stack in many rules but Ripper stores Ruby Object returned by callback method.<br>
Therefore Ripper can not execute semantic analysis which requires Node (#1).<br>
Values on the stack are different then they need to implement same name functions differently (#3).<br>
This leads different behavior like #2 because they have different <code>match_op</code> function.</p>
<a name="Proposal"></a>
<h1 >Proposal<a href="#Proposal" class="wiki-anchor">¶</a></h1>
<p>Introduce new semantic value stack for Ripper so that Ripper can manage both Node and Ruby Object separately.<br>
Lrama will provide some callback entry points and new special variable for actions.</p>
<p>Lrama will support these callback directives, specified function is called when the event happens</p>
<ul>
<li>%after-shift function_name</li>
<li>%before-reduce function_name</li>
<li>%after-reduce function_name</li>
<li>%after-shift-error-token function_name</li>
<li>%after-pop-stack function_name</li>
</ul>
<p>Lrama also provides <code>$:n</code> variable to access index of each grammar symbols. The variable is translated to the minus index from the top of the stack.<br>
For example</p>
<pre><code class="c syntaxhl" data-language="c"><span class="nl">primary:</span> <span class="n">k_if</span> <span class="n">expr_value</span> <span class="n">then</span> <span class="n">compstmt</span> <span class="n">if_tail</span> <span class="n">k_end</span>
<span class="p">{</span>
<span class="cm">/*% ripper: if!($:2, $:4, $:5) %*/</span>
<span class="cm">/* $:2 = -5, $:4 = -3, $:5 = -2. */</span>
<span class="p">}</span>
</code></pre>
<p>We can implement separated stack for Ruby Object by these features.</p>
<a name="Implementation-note"></a>
<h1 >Implementation note<a href="#Implementation-note" class="wiki-anchor">¶</a></h1>
<a name="New-fields-of-struct-parser_params"></a>
<h2 >New fields of struct parser_params<a href="#New-fields-of-struct-parser_params" class="wiki-anchor">¶</a></h2>
<ul>
<li>
<code>VALUE s_value</code>: Holds Ruby Object returned by Ripper callback method call.</li>
<li>
<code>VALUE s_lvalue</code>: Holds Ruby Object responding to LHS of the rule.</li>
<li>
<code>VALUE s_value_stack</code>: Stack for Ruby Object. It's actually ruby array.</li>
</ul>
<p>These fields are added only when it's Ripper.</p>
<a name="The-role-of-callback-functions"></a>
<h2 >The role of callback functions<a href="#The-role-of-callback-functions" class="wiki-anchor">¶</a></h2>
<ul>
<li>%after-shift: Push <code>s_value</code> to <code>s_value_stack</code>.</li>
<li>%before-reduce: Assign the first Ruby Object of RHS to <code>s_lvalue</code> (similar with <code>$$ = $1</code>).</li>
<li>%after-reduce: Pop <code>s_value_stack</code> <code>rhs.len</code> times then push <code>s_lvalue</code> to <code>s_value_stack</code>.</li>
<li>%after-shift-error-token: Push <code>nil</code> to <code>s_value_stack</code>. This <code>nil</code> stands for <code>error</code> token.</li>
<li>%after-pop-stack: Pop <code>s_value_stack</code> <code>len</code> times. This is needed to emulate panic mode.</li>
</ul>
<a name="Achievement"></a>
<h1 >Achievement<a href="#Achievement" class="wiki-anchor">¶</a></h1>
<p>These bugs are fixed.</p>
<ul>
<li>
<a href="https://bugs.ruby-lang.org/issues/10436" class="external">Bug 10436</a> "ruby -c and ripper inconsistency: m(&nil) {}"</li>
<li>
<a href="https://bugs.ruby-lang.org/issues/18988" class="external">Bug 18988</a> "Ripper cannot parse some code that has regexp named capture"</li>
<li>
<a href="https://bugs.ruby-lang.org/issues/20055" class="external">Bug 20055</a> "Ripper seems to skip some checks like <code>void value expression</code> and <code>duplicated variable name</code>"</li>
</ul>
<p>This means <a href="https://bugs.ruby-lang.org/projects/ruby-master/issues?utf8=%E2%9C%93&set_filter=1&sort=id%3Adesc&f%5B%5D=subject&op%5Bsubject%5D=%7E&v%5Bsubject%5D%5B%5D=ripper&f%5B%5D=status_id&op%5Bstatus_id%5D=o&f%5B%5D=tracker_id&op%5Btracker_id%5D=%3D&v%5Btracker_id%5D%5B%5D=1&f%5B%5D=&c%5B%5D=tracker&c%5B%5D=status&c%5B%5D=subject&c%5B%5D=assigned_to&c%5B%5D=updated_on&group_by=" class="external">all of Ripper open bugs tickets</a> which are related current architecture will be closed.</p>
<a name="Links"></a>
<h1 >Links<a href="#Links" class="wiki-anchor">¶</a></h1>
<ul>
<li>Lrama Implementaion: <a href="https://github.com/ruby/lrama/pull/367" class="external">https://github.com/ruby/lrama/pull/367</a>
</li>
<li>Ruby Implementaion: <a href="https://github.com/ruby/ruby/pull/9923" class="external">https://github.com/ruby/ruby/pull/9923</a>
</li>
</ul>
Ruby master - Bug #20224 (Closed): Backport https://github.com/ruby/ruby/pull/9634 to Ruby 3.3
https://bugs.ruby-lang.org/issues/20224
2024-01-30T01:39:10Z
yui-knk (Kaneko Yuichiro)
<p>It's nice if we can backport <a href="https://github.com/ruby/ruby/pull/9634" class="external">https://github.com/ruby/ruby/pull/9634</a> (3d19409637de1462b6790d2a92344bf0a10d8c52) to Ruby 3.3 branch.<br>
Even so previous codes work as expected but it depends on how parse.c works and misleading.</p>
Ruby master - Bug #19919 (Closed): Variable assignments in condition are warned however class var...
https://bugs.ruby-lang.org/issues/19919
2023-10-11T09:37:07Z
yui-knk (Kaneko Yuichiro)
<p>Is it better to warn for class variable assignment and constant declaration in condition?</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="p">?</span> <span class="n">x</span> <span class="p">:</span> <span class="n">y</span> <span class="c1"># test.rb:1: warning: found `= literal' in conditional, should be ==</span>
<span class="k">if</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># test.rb:3: warning: found `= literal' in conditional, should be ==</span>
<span class="k">end</span>
<span class="n">b</span> <span class="o">=</span> <span class="mi">1</span>
<span class="mi">1</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">2</span> <span class="c1"># test.rb:8: warning: found `= literal' in conditional, should be ==</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">if</span> <span class="vg">$a</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># test.rb:12: warning: found `= literal' in conditional, should be ==</span>
<span class="k">end</span>
<span class="k">if</span> <span class="vi">@a</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># test.rb:15: warning: found `= literal' in conditional, should be ==</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">A</span>
<span class="k">if</span> <span class="vc">@@a</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># no warning</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">if</span> <span class="no">B</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># no warning</span>
<span class="k">end</span>
</code></pre>
<p>I use <code>ruby 3.3.0preview2 (2023-09-14 master e50fcca9a7)</code>.</p>
Ruby master - Bug #19862 (Closed): argument stack underflow compile error happens for the combina...
https://bugs.ruby-lang.org/issues/19862
2023-09-05T10:05:39Z
yui-knk (Kaneko Yuichiro)
<p>This code raises argument stack underflow compile error on ruby 3.3 which is under development.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># test3.rb</span>
<span class="k">if</span> <span class="kp">true</span> <span class="ow">or</span> <span class="p">{</span><span class="ss">a: </span><span class="mi">0</span><span class="p">}</span> <span class="k">in</span> <span class="p">{</span><span class="n">a</span><span class="p">:}</span>
<span class="nb">p</span> <span class="mi">1</span>
<span class="k">else</span>
<span class="nb">p</span> <span class="mi">0</span>
<span class="k">end</span>
</code></pre>
<pre><code class="shell syntaxhl" data-language="shell">% ruby <span class="nt">-v</span> test3.rb
ruby 3.3.0preview1 <span class="o">(</span>2023-05-12 master a1b01e7701<span class="o">)</span> <span class="o">[</span>arm64-darwin21]
test3.rb:2: warning: assigned but unused variable - a
<span class="nt">--</span> raw disasm--------
trace: 1
0000 jump <L000> <span class="o">(</span> 2<span class="o">)</span>
<L006> <span class="o">[</span>sp: 0]
<L004> <span class="o">[</span>sp: 0]
<span class="k">*</span> 0002 pop <span class="o">(</span> 2<span class="o">)</span>
0003 pop <span class="o">(</span> 2<span class="o">)</span>
0004 jump <L001> <span class="o">(</span> 2<span class="o">)</span>
<L000> <span class="o">[</span>sp: 0]
trace: 1
0006 putself <span class="o">(</span> 3<span class="o">)</span>
0007 putobject_INT2FIX_1_ <span class="o">(</span> 3<span class="o">)</span>
0008 opt_send_without_block <calldata:p, 1> <span class="o">(</span> 3<span class="o">)</span>
0010 leave <span class="o">(</span> 5<span class="o">)</span>
<L001> <span class="o">[</span>sp: <span class="nt">-1</span><span class="o">]</span>
trace: 1
0011 putself <span class="o">(</span> 5<span class="o">)</span>
0012 putobject_INT2FIX_0_ <span class="o">(</span> 5<span class="o">)</span>
0013 opt_send_without_block <calldata:p, 1> <span class="o">(</span> 5<span class="o">)</span>
0015 leave <span class="o">(</span> 5<span class="o">)</span>
<span class="nt">---------------------</span>
test3.rb:2: argument stack underflow <span class="o">(</span><span class="nt">-1</span><span class="o">)</span>
test3.rb: compile error <span class="o">(</span>SyntaxError<span class="o">)</span>
% ./ruby <span class="nt">-v</span> ../../test3.rb
ruby 3.3.0dev <span class="o">(</span>2023-09-04T18:01:33Z master db3b814cb0<span class="o">)</span> <span class="o">[</span>arm64-darwin21]
<span class="sb">`</span>RubyGems<span class="s1">' were not loaded.
`error_highlight'</span> was not loaded.
<span class="sb">`</span>did_you_mean<span class="s1">' was not loaded.
`syntax_suggest'</span> was not loaded.
../../test3.rb:2: warning: assigned but unused variable - a
<span class="nt">--</span> raw disasm--------
trace: 1
0000 jump <L000> <span class="o">(</span> 2<span class="o">)</span>
<L006> <span class="o">[</span>sp: 0]
<L004> <span class="o">[</span>sp: 0]
<span class="k">*</span> 0002 pop <span class="o">(</span> 2<span class="o">)</span>
0003 pop <span class="o">(</span> 2<span class="o">)</span>
0004 jump <L001> <span class="o">(</span> 2<span class="o">)</span>
<L000> <span class="o">[</span>sp: 0]
trace: 1
0006 putself <span class="o">(</span> 3<span class="o">)</span>
0007 putobject_INT2FIX_1_ <span class="o">(</span> 3<span class="o">)</span>
0008 opt_send_without_block <calldata:p, 1> <span class="o">(</span> 3<span class="o">)</span>
0010 leave <span class="o">(</span> 5<span class="o">)</span>
<L001> <span class="o">[</span>sp: <span class="nt">-1</span><span class="o">]</span>
trace: 1
0011 putself <span class="o">(</span> 5<span class="o">)</span>
0012 putobject_INT2FIX_0_ <span class="o">(</span> 5<span class="o">)</span>
0013 opt_send_without_block <calldata:p, 1> <span class="o">(</span> 5<span class="o">)</span>
0015 leave <span class="o">(</span> 5<span class="o">)</span>
<span class="nt">---------------------</span>
../../test3.rb:2: argument stack underflow <span class="o">(</span><span class="nt">-1</span><span class="o">)</span>
../../test3.rb: compile error <span class="o">(</span>SyntaxError<span class="o">)</span>
</code></pre>
<p>This also raises same error.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># test4.rb</span>
<span class="k">if</span> <span class="kp">false</span> <span class="ow">and</span> <span class="p">{</span><span class="ss">a: </span><span class="mi">0</span><span class="p">}</span> <span class="k">in</span> <span class="p">{</span><span class="n">a</span><span class="p">:}</span>
<span class="nb">p</span> <span class="mi">1</span>
<span class="k">else</span>
<span class="nb">p</span> <span class="mi">0</span>
<span class="k">end</span>
</code></pre>
<p>As far as I checked, 3.0.0, 3.1.0, 3.2.0 don't raise the error.</p>
Ruby master - Feature #19719 (Closed): Universal Parser
https://bugs.ruby-lang.org/issues/19719
2023-06-08T02:14:16Z
yui-knk (Kaneko Yuichiro)
<a name="Background"></a>
<h1 >Background<a href="#Background" class="wiki-anchor">¶</a></h1>
<p>There are three use cases where we need a CRuby parser which is independent of other CRuby features like Object, GC. I call such a parser a Universal Parser.</p>
<ol>
<li>Use Universal Parser from Ruby applications.<br>
For example RuboCop. RuboCop needs a parser to get AST of source code. Currently RuboCop uses parser gem. In this sense Universal Parser is a replacement of parser gem.</li>
<li>Use Universal Parser from C/C++ or other language.<br>
For example Sorbet. Sorbet is written in C++. It has its own parser. Universal Parser can be used in such scenario.</li>
<li>Use Universal Parser for other Ruby implementations.<br>
mruby, JRuby and other Ruby implementations will use Universal Parser so that they don’t need to develop & manage their own parser.</li>
</ol>
<a name="Design"></a>
<h1 >Design<a href="#Design" class="wiki-anchor">¶</a></h1>
<ul>
<li>Implement Universal Parser by changing CRuby source code, especially parse.y and node.c.<br>
Introduce <code>UNIVERSAL_PARSER</code> macro and implement Universal Parser by passing all necessary CRuby related functions via <code>struct rb_parser_config_struct</code>. In this step there are two build modes with/without Universal Parser.</li>
<li>Reduce CRuby related functions passed by <code>struct rb_parser_config_struct</code>. Some of them are copied into parse.y, e.g. <code>rb_isspace</code>. Other are reimplemented, e.g. <code>NODE_LIT</code> has new String struct instead of <code>VALUE</code>.</li>
<li>Once CRuby related functions needed for Universal Parser are minimized, replace rest CRuby function references with functions provided by <code>struct rb_parser_config_struct</code> and remove <code>UNIVERSAL_PARSER</code> macro.</li>
</ul>
<a name="Release-management"></a>
<h1 >Release management<a href="#Release-management" class="wiki-anchor">¶</a></h1>
<p>There are three options for releasing a binary for Universal Parser (“librubyparser”).</p>
<ol>
<li>Release it as so/dll<br>
a. Include it into Ruby release process<br>
b. Create another repository for release management of "librubyparser"</li>
<li>Release it as gem (ruby/universal_parser)<br>
"librubyparser" has only pure C interface and data structure. If you want to use it from Ruby code, you need C extension code to translate "librubyparser" data and Ruby objects. I propose to create "universal_parser" gem for this purpose.</li>
</ol>
<p>I prefer #1-b to #1-a because it doesn’t increase tasks for Ruby release process. I want to make #2 as a first milestone.</p>
Ruby master - Feature #19637 (Closed): Use Lrama LALR parser generator instead of Bison
https://bugs.ruby-lang.org/issues/19637
2023-05-10T07:31:37Z
yui-knk (Kaneko Yuichiro)
<p>I want to propose to use Lrama LALR parser generator instead of Bison.</p>
<p><a href="https://github.com/yui-knk/lrama" class="external">https://github.com/yui-knk/lrama</a> is a pure ruby parser generator which accepts Ruby's "parse.y" and generate compatible "parse.c" file.<br>
By this change, we never depend on Bison whose version is different for each environment.<br>
Future improvement, like Nonterminal attributes and so on, will be discussed other tickets.</p>
Ruby master - Feature #19070 (Closed): Enhance keep_tokens option for RubyVM::AbstractSyntaxTree ...
https://bugs.ruby-lang.org/issues/19070
2022-10-19T10:20:31Z
yui-knk (Kaneko Yuichiro)
<a name="Background"></a>
<h1 >Background<a href="#Background" class="wiki-anchor">¶</a></h1>
<p>Implementation for Language Server Protocol (LSP) sometimes needs token information. For example both <code>m(1)</code> and <code>m(1, )</code> has same AST structure other than node locations then it's impossible to check the existence of <code>,</code> from AST. However in later case, it might be better to suggest variables list for the second argument. Token information is important for such case.</p>
<a name="Example"></a>
<h1 >Example<a href="#Example" class="wiki-anchor">¶</a></h1>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s2">"pp"</span>
<span class="n">node</span> <span class="o">=</span> <span class="no">RubyVM</span><span class="o">::</span><span class="no">AbstractSyntaxTree</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="o"><<~</span><span class="no">STR</span><span class="p">,</span> <span class="ss">keep_tokens: </span><span class="kp">true</span><span class="p">)</span><span class="sh">
def m(a, b = 1, *rest, &block)
end
m(1, )
</span><span class="no">STR</span>
<span class="n">defn</span> <span class="o">=</span> <span class="n">node</span><span class="p">.</span><span class="nf">children</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="nf">children</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">fcall</span> <span class="o">=</span> <span class="n">node</span><span class="p">.</span><span class="nf">children</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="nf">children</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="nb">puts</span> <span class="s2">"defn.tokens"</span>
<span class="n">pp</span> <span class="n">defn</span><span class="p">.</span><span class="nf">tokens</span>
<span class="nb">puts</span> <span class="s2">"</span><span class="se">\n\n</span><span class="s2">"</span>
<span class="nb">puts</span> <span class="s2">"fcall.tokens"</span>
<span class="n">pp</span> <span class="n">fcall</span><span class="p">.</span><span class="nf">tokens</span>
<span class="nb">puts</span> <span class="s2">"</span><span class="se">\n\n</span><span class="s2">"</span>
<span class="nb">puts</span> <span class="n">defn</span><span class="p">.</span><span class="nf">tokens</span><span class="p">.</span><span class="nf">map</span><span class="p">{</span><span class="n">_1</span><span class="p">[</span><span class="mi">2</span><span class="p">]}.</span><span class="nf">join</span>
<span class="nb">puts</span> <span class="n">fcall</span><span class="p">.</span><span class="nf">tokens</span><span class="p">.</span><span class="nf">map</span><span class="p">{</span><span class="n">_1</span><span class="p">[</span><span class="mi">2</span><span class="p">]}.</span><span class="nf">join</span>
</code></pre>
<p>shows below, where token is <code>[sequence_id, token_type, token_string, [first_line, first_column, last_line, last_column]]</code></p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">defn</span><span class="p">.</span><span class="nf">tokens</span>
<span class="p">[[</span><span class="mi">0</span><span class="p">,</span> <span class="ss">:kw</span><span class="p">,</span> <span class="s2">"def"</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="ss">:sp</span><span class="p">,</span> <span class="s2">" "</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="ss">:ident</span><span class="p">,</span> <span class="s2">"m"</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="ss">:lparen</span><span class="p">,</span> <span class="s2">"("</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">4</span><span class="p">,</span> <span class="ss">:ident</span><span class="p">,</span> <span class="s2">"a"</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">7</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">5</span><span class="p">,</span> <span class="ss">:comma</span><span class="p">,</span> <span class="s2">","</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">8</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">6</span><span class="p">,</span> <span class="ss">:sp</span><span class="p">,</span> <span class="s2">" "</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">9</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">7</span><span class="p">,</span> <span class="ss">:ident</span><span class="p">,</span> <span class="s2">"b"</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">10</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">8</span><span class="p">,</span> <span class="ss">:sp</span><span class="p">,</span> <span class="s2">" "</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">11</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">9</span><span class="p">,</span> <span class="ss">:op</span><span class="p">,</span> <span class="s2">"="</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">12</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">10</span><span class="p">,</span> <span class="ss">:sp</span><span class="p">,</span> <span class="s2">" "</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">13</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">11</span><span class="p">,</span> <span class="ss">:int</span><span class="p">,</span> <span class="s2">"1"</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">14</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">12</span><span class="p">,</span> <span class="ss">:comma</span><span class="p">,</span> <span class="s2">","</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">14</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">15</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">13</span><span class="p">,</span> <span class="ss">:sp</span><span class="p">,</span> <span class="s2">" "</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">15</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">16</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">14</span><span class="p">,</span> <span class="ss">:op</span><span class="p">,</span> <span class="s2">"*"</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">16</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">17</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">15</span><span class="p">,</span> <span class="ss">:ident</span><span class="p">,</span> <span class="s2">"rest"</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">17</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">21</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">16</span><span class="p">,</span> <span class="ss">:comma</span><span class="p">,</span> <span class="s2">","</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">21</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">22</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">17</span><span class="p">,</span> <span class="ss">:sp</span><span class="p">,</span> <span class="s2">" "</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">22</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">23</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">18</span><span class="p">,</span> <span class="ss">:op</span><span class="p">,</span> <span class="s2">"&"</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">23</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">24</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">19</span><span class="p">,</span> <span class="ss">:ident</span><span class="p">,</span> <span class="s2">"block"</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">24</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">29</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">20</span><span class="p">,</span> <span class="ss">:rparen</span><span class="p">,</span> <span class="s2">")"</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">29</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">30</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">21</span><span class="p">,</span> <span class="ss">:ignored_nl</span><span class="p">,</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">31</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">22</span><span class="p">,</span> <span class="ss">:kw</span><span class="p">,</span> <span class="s2">"end"</span><span class="p">,</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]]]</span>
<span class="n">fcall</span><span class="p">.</span><span class="nf">tokens</span>
<span class="p">[[</span><span class="mi">25</span><span class="p">,</span> <span class="ss">:ident</span><span class="p">,</span> <span class="s2">"m"</span><span class="p">,</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">26</span><span class="p">,</span> <span class="ss">:lparen</span><span class="p">,</span> <span class="s2">"("</span><span class="p">,</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">27</span><span class="p">,</span> <span class="ss">:int</span><span class="p">,</span> <span class="s2">"1"</span><span class="p">,</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">3</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">28</span><span class="p">,</span> <span class="ss">:comma</span><span class="p">,</span> <span class="s2">","</span><span class="p">,</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">4</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">29</span><span class="p">,</span> <span class="ss">:sp</span><span class="p">,</span> <span class="s2">" "</span><span class="p">,</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">]],</span>
<span class="p">[</span><span class="mi">30</span><span class="p">,</span> <span class="ss">:rparen</span><span class="p">,</span> <span class="s2">")"</span><span class="p">,</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">]]]</span>
<span class="k">def</span> <span class="nf">m</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="o">*</span><span class="n">rest</span><span class="p">,</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="k">end</span>
<span class="n">m</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="p">)</span>
</code></pre>
<a name="Interface"></a>
<h1 >Interface<a href="#Interface" class="wiki-anchor">¶</a></h1>
<ul>
<li>Add <code>keep_tokens</code> option for <code>RubyVM::AbstractSyntaxTree.parse</code>, <code>.parse_file</code> and <code>.of</code>
</li>
<li>Add <code>RubyVM::AbstractSyntaxTree::Node#tokens</code> which returns tokens for the node including tokens for descendants nodes.</li>
<li>Add <code>RubyVM::AbstractSyntaxTree::Node#all_tokens</code> which returns all tokens for the input script regardless the receiver node.</li>
</ul>
<a name="Implementation"></a>
<h1 >Implementation<a href="#Implementation" class="wiki-anchor">¶</a></h1>
<p><a href="https://github.com/yui-knk/ruby/tree/cst5" class="external">https://github.com/yui-knk/ruby/tree/cst5</a></p>
Ruby master - Feature #19068 (Closed): Upgrades required Bison version for development
https://bugs.ruby-lang.org/issues/19068
2022-10-18T08:52:17Z
yui-knk (Kaneko Yuichiro)
<a name="Background"></a>
<h1 >Background<a href="#Background" class="wiki-anchor">¶</a></h1>
<p>Printing node type, e.g. <code>NODE_LIT</code>, for <code>yydebug</code> option is helpful when developing parse.y.</p>
<p>Before:</p>
<pre><code>Reducing stack by rule 639 (line 5062):
$1 = token "integer literal" (1.0-1.1: 1)
-> $$ = nterm simple_numeric (1.0-1.1: )
</code></pre>
<p>After:</p>
<pre><code>Reducing stack by rule 641 (line 5078):
$1 = token "integer literal" (1.0-1.1: 1)
-> $$ = nterm simple_numeric (1.0-1.1: NODE_LIT)
</code></pre>
<a name="Consideration"></a>
<h1 >Consideration<a href="#Consideration" class="wiki-anchor">¶</a></h1>
<p>IIRC, CRuby tries to keep it be able to build with old Bison, I guess this is because default Bison for Mac is very old (might be 2.3).<br>
However Bison is still developed and new version has new feature. Therefore I want to confirm it is able to update Bison version required for CRuby development.</p>
<a name="Implementation"></a>
<h1 >Implementation<a href="#Implementation" class="wiki-anchor">¶</a></h1>
<p><a href="https://github.com/ruby/ruby/pull/6579" class="external">https://github.com/ruby/ruby/pull/6579</a></p>
Ruby master - Feature #19013 (Closed): Error Tolerant Parser
https://bugs.ruby-lang.org/issues/19013
2022-09-21T12:28:28Z
yui-knk (Kaneko Yuichiro)
<a name="Background"></a>
<h1 >Background<a href="#Background" class="wiki-anchor">¶</a></h1>
<p>Implementation for Language Server Protocol (LSP) sometimes needs to parse incomplete ruby script for example users want to complement expressions in the middle of statement like below:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">A</span>
<span class="k">def</span> <span class="nf">m</span>
<span class="n">a</span> <span class="o">=</span> <span class="mi">10</span>
<span class="k">if</span> <span class="c1"># here users want to run completion</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>In such case, LSP implementation wants to get partial AST instead of syntax error.</p>
<a name="Proposal"></a>
<h1 >Proposal<a href="#Proposal" class="wiki-anchor">¶</a></h1>
<p>At the moment I want to propose 3 types of tolerance</p>
<a name="1-Complement-end-when-lexer-hits-to-end-of-input-but-end-is-not-enough"></a>
<h2 >1. Complement <code>end</code> when lexer hits to end-of-input but <code>end</code> is not enough<a href="#1-Complement-end-when-lexer-hits-to-end-of-input-but-end-is-not-enough" class="wiki-anchor">¶</a></h2>
<p>This is a case. Lexer will generate 1 <code>end</code> before generates end-of-input.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">describe</span> <span class="s2">"1"</span> <span class="k">do</span>
<span class="n">describe</span> <span class="s2">"2"</span> <span class="k">do</span>
<span class="n">describe</span> <span class="s2">"3"</span> <span class="k">do</span>
<span class="n">it</span> <span class="s2">"here"</span> <span class="k">do</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<a name="2-Extract-end-as-keyword-not-identifier-based-on-an-indent"></a>
<h2 >2. Extract "end" as keyword not identifier based on an indent<a href="#2-Extract-end-as-keyword-not-identifier-based-on-an-indent" class="wiki-anchor">¶</a></h2>
<p>This is a case. Normal parser recognizes "end" on line 4 as "local variable or method".<br>
This causes not only syntax error but also <code>bar</code> method definition is assumed as <code>Z::Foo#bar</code>.<br>
Other approach is suppress <code>!IS_lex_state(EXPR_DOT)</code> checks for "end".</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Z</span>
<span class="k">class</span> <span class="nc">Foo</span>
<span class="n">foo</span><span class="p">.</span>
<span class="nf">end</span>
<span class="k">def</span> <span class="nf">bar</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<h2>3. Change locations of <code>error</code>
</h2>
<p>Currently <code>error</code> is put into <code>top_stmts</code> and <code>stmts</code> like <code>top_stmts: error top_stmt</code> and <code>stmts: error stmt</code>.<br>
However these are too strict to catch syntax error then want to move it to <code>stmt: error</code> and <code>expr_value: error</code>.</p>
<a name="Interface"></a>
<h1 >Interface<a href="#Interface" class="wiki-anchor">¶</a></h1>
<ul>
<li>Adding <code>error_tolerant</code> option to <code>RubyVM::AbstractSyntaxTree.parse</code>
</li>
<li>Adding <code>--error-tolerant-parser</code> option to ruby command for debugging
<ul>
<li>This option is valid only when <code>–dump=yydebug</code>, <code>--dump=parsetree</code> or <code>--dump=parsetree_with_comment</code> is passed</li>
</ul>
</li>
</ul>
<a name="Compatibility"></a>
<h1 >Compatibility<a href="#Compatibility" class="wiki-anchor">¶</a></h1>
<p>Changing the location of <code>error</code> can lead incompatibility. At least I observed 2 test cases in ruby/ruby are broken by this change.<br>
I think both of them depend on how ripper behaves after ripper raises syntax error.</p>
<ul>
<li>RDoc: <a href="https://github.com/yui-knk/ruby/commit/1dabbe508f0cc3dd4f83aa72502bbf347029dd8c" class="external">https://github.com/yui-knk/ruby/commit/1dabbe508f0cc3dd4f83aa72502bbf347029dd8c</a>
<ul>
<li>However ruby script in heredoc is invalid...</li>
</ul>
</li>
<li>irb: <a href="https://github.com/yui-knk/ruby/commit/e18be19ecd044eb26a56f6f9ba4f19d40c01a9c7" class="external">https://github.com/yui-knk/ruby/commit/e18be19ecd044eb26a56f6f9ba4f19d40c01a9c7</a>
<ul>
<li>Range of error coloring is changed</li>
</ul>
</li>
</ul>
<p>All other changes are related to not parser but lexer and they are controlled by <code>error_tolerant</code> option. Therefore no behavior change is expected for ruby parser and ripper.</p>
<a name="Implementation"></a>
<h1 >Implementation<a href="#Implementation" class="wiki-anchor">¶</a></h1>
<p><a href="https://github.com/yui-knk/ruby/tree/error_recovery_indent_aware" class="external">https://github.com/yui-knk/ruby/tree/error_recovery_indent_aware</a></p>
Ruby master - Bug #14756 (Closed): `Exception` may cause SEGV when `#backtrace` returns a string
https://bugs.ruby-lang.org/issues/14756
2018-05-14T00:12:33Z
yui-knk (Kaneko Yuichiro)
<p>This code causes SEGV, because <code>print_backtrace</code> expects second argument to be an array but a string is given.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Exception</span>
<span class="k">def</span> <span class="nf">backtrace</span>
<span class="s2">"backtrace"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="s2">""</span><span class="p">.</span><span class="nf">a</span>
</code></pre>
<p>Also in ruby 2.3.7, 2.4.4, 2.5.1.</p>
Ruby master - Bug #14214 (Closed): The direction of branch instruction is broken when block argum...
https://bugs.ruby-lang.org/issues/14214
2017-12-21T08:12:30Z
yui-knk (Kaneko Yuichiro)
<p>The result of this code is changed</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">a</span><span class="p">(</span><span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="n">block</span> <span class="o">=</span> <span class="mi">1</span>
<span class="nb">p</span> <span class="n">block</span>
<span class="nb">p</span> <span class="mi">2</span> <span class="k">if</span> <span class="n">block</span>
<span class="k">end</span>
<span class="n">a</span><span class="p">()</span>
</code></pre>
<pre><code>ruby 2.5.0rc1 (2017-12-14 trunk 61243) [x86_64-darwin17]
1
2
</code></pre>
<pre><code>ruby 2.5.0dev (2017-12-21 trunk 61384) [x86_64-darwin17]
1
</code></pre>
Ruby master - Feature #13838 (Closed): Add the ability to detect Coverage status
https://bugs.ruby-lang.org/issues/13838
2017-08-25T00:30:41Z
yui-knk (Kaneko Yuichiro)
<a name="Description"></a>
<h2 >Description<a href="#Description" class="wiki-anchor">¶</a></h2>
<p>I want to detect current status of Coverage, which is enabled or not.<br>
Now we can detect status only trying <code>Coverage.peek_result</code> or <code>Coverage.result</code> and catch RuntimeError.<br>
Attached patch enable us to detect status without any exceptions.</p>
<a name="Why"></a>
<h2 >Why<a href="#Why" class="wiki-anchor">¶</a></h2>
<p>My daily work is developing a web application with Ruby.</p>
<p>I am using <code>Coverage.peek_result</code> to record coverage information on a per-request basis.</p>
<p>When recording coverage information, I want to start Coverage on a part of production servers,<br>
because Coverage tool may have some overhead.</p>
<p>In this case, the code of my program looks like</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># Implement as Rack middleware</span>
<span class="k">class</span> <span class="nc">CoverageMiddleware</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
<span class="vi">@app</span> <span class="o">=</span> <span class="n">app</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">call</span><span class="p">(</span><span class="n">env</span><span class="p">)</span>
<span class="c1"># To ensure return response, rescue exceptions</span>
<span class="n">before</span> <span class="o">=</span> <span class="no">Coverage</span><span class="p">.</span><span class="nf">peek_result</span> <span class="k">rescue</span> <span class="kp">nil</span>
<span class="n">res</span> <span class="o">=</span> <span class="vi">@app</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="n">env</span><span class="p">)</span>
<span class="n">after</span> <span class="o">=</span> <span class="no">Coverage</span><span class="p">.</span><span class="nf">peek_result</span> <span class="k">rescue</span> <span class="kp">nil</span>
<span class="k">if</span> <span class="p">(</span><span class="n">before</span> <span class="o">&&</span> <span class="n">after</span><span class="p">)</span>
<span class="n">write_file</span><span class="p">(</span><span class="n">diff</span><span class="p">(</span><span class="n">before</span><span class="p">,</span> <span class="n">after</span><span class="p">))</span>
<span class="k">end</span>
<span class="k">return</span> <span class="n">res</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<a name="Example"></a>
<h2 >Example<a href="#Example" class="wiki-anchor">¶</a></h2>
<p>By using `Coverage.enabled?, I can</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">CoverageMiddleware</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
<span class="vi">@app</span> <span class="o">=</span> <span class="n">app</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">call</span><span class="p">(</span><span class="n">env</span><span class="p">)</span>
<span class="k">if</span> <span class="no">Coverage</span><span class="p">.</span><span class="nf">enabled?</span>
<span class="n">before</span> <span class="o">=</span> <span class="no">Coverage</span><span class="p">.</span><span class="nf">peek_result</span>
<span class="n">res</span> <span class="o">=</span> <span class="vi">@app</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="n">env</span><span class="p">)</span>
<span class="n">after</span> <span class="o">=</span> <span class="no">Coverage</span><span class="p">.</span><span class="nf">peek_result</span>
<span class="n">write_file</span><span class="p">(</span><span class="n">diff</span><span class="p">(</span><span class="n">before</span><span class="p">,</span> <span class="n">after</span><span class="p">))</span>
<span class="k">else</span>
<span class="n">res</span> <span class="o">=</span> <span class="vi">@app</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="n">env</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">return</span> <span class="n">res</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
Ruby master - Bug #12952 (Closed): Incompatibility of a method signature between `Float#round` an...
https://bugs.ruby-lang.org/issues/12952
2016-11-18T06:41:02Z
yui-knk (Kaneko Yuichiro)
<p>We can not call <code>BigDecimal("0.5").round(half: :up)</code>.<br>
This prevents us from duck typing Float objects and BigDecimal objects.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">001</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="nb">require</span> <span class="s2">"bigdecimal"</span>
<span class="o">=></span> <span class="kp">true</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">002</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="mf">0.5</span><span class="p">.</span><span class="nf">round</span><span class="p">(</span><span class="ss">half: :up</span><span class="p">)</span>
<span class="o">=></span> <span class="mi">1</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">003</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="no">BigDecimal</span><span class="p">(</span><span class="s2">"0.5"</span><span class="p">).</span><span class="nf">round</span><span class="p">(</span><span class="ss">half: :up</span><span class="p">)</span>
<span class="no">TypeError</span><span class="p">:</span> <span class="n">no</span> <span class="n">implicit</span> <span class="n">conversion</span> <span class="n">of</span> <span class="no">Hash</span> <span class="n">into</span> <span class="no">Integer</span>
<span class="n">from</span> <span class="p">(</span><span class="n">irb</span><span class="p">):</span><span class="mi">3</span><span class="ss">:in</span> <span class="sb">`round'
from (irb):3
from /Users/kaneko/.rbenv/versions/2.4.0-preview3/bin/irb:11:in `</span><span class="o"><</span><span class="n">main</span><span class="o">></span><span class="err">'</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">004</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="no">BigDecimal</span><span class="p">.</span><span class="nf">ver</span>
<span class="o">=></span> <span class="s2">"1.1.0"</span>
</code></pre>
Ruby master - Bug #12330 (Closed): vm_trace.c (get_event_id) returns :specified_line if SPECIFIED...
https://bugs.ruby-lang.org/issues/12330
2016-04-29T14:47:19Z
yui-knk (Kaneko Yuichiro)
<p>Because r38728 is last commit about this line, I think this is not intended behavior.</p>
<p>To check which symbol is returned,</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git a/ext/-test-/tracepoint/tracepoint.c b/ext/-test-/tracepoint/tracepoint.c
index aa8c212..8979853 100644
</span><span class="gd">--- a/ext/-test-/tracepoint/tracepoint.c
</span><span class="gi">+++ b/ext/-test-/tracepoint/tracepoint.c
</span><span class="p">@@ -84,6 +84,18 @@</span> tracepoint_specify_normal_and_internal_events(VALUE self)
return Qnil; /* should not be reached */
}
<span class="gi">+static VALUE
+tracepoint_line_event_sym(VALUE self)
+{
+ return ID2SYM(get_event_id(RUBY_EVENT_LINE));
+}
+
+static VALUE
+tracepoint_specified_line_event_sym(VALUE self)
+{
+ return ID2SYM(get_event_id(RUBY_EVENT_SPECIFIED_LINE));
+}
+
</span> void Init_gc_hook(VALUE);
void
<span class="p">@@ -93,4 +105,6 @@</span> Init_tracepoint(void)
Init_gc_hook(mBug);
rb_define_module_function(mBug, "tracepoint_track_objspace_events", tracepoint_track_objspace_events, 0);
rb_define_module_function(mBug, "tracepoint_specify_normal_and_internal_events", tracepoint_specify_normal_and_internal_events, 0);
<span class="gi">+ rb_define_module_function(mBug, "tracepoint_line_event_sym", tracepoint_line_event_sym, 0);
+ rb_define_module_function(mBug, "tracepoint_specified_line_event_sym", tracepoint_specified_line_event_sym, 0);
</span> }
<span class="gh">diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index ef6caa1..36d472d 100644
</span><span class="gd">--- a/include/ruby/ruby.h
</span><span class="gi">+++ b/include/ruby/ruby.h
</span><span class="p">@@ -2126,6 +2126,7 @@</span> typedef void (*rb_event_hook_func_t)(rb_event_flag_t evflag, VALUE data, VALUE s
#define RB_EVENT_HOOKS_HAVE_CALLBACK_DATA 1
void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data);
int rb_remove_event_hook(rb_event_hook_func_t func);
<span class="gi">+ID get_event_id(rb_event_flag_t);
</span>
/* locale insensitive functions */
<span class="gh">diff --git a/test/-ext-/tracepoint/test_tracepoint.rb b/test/-ext-/tracepoint/test_tracepoint.rb
index 33d0c3e..8db8c77 100644
</span><span class="gd">--- a/test/-ext-/tracepoint/test_tracepoint.rb
</span><span class="gi">+++ b/test/-ext-/tracepoint/test_tracepoint.rb
</span><span class="p">@@ -58,6 +58,14 @@</span> def test_tracepoint_specify_normal_and_internal_events
assert_raise(TypeError){ Bug.tracepoint_specify_normal_and_internal_events }
end
<span class="gi">+ def test_tracepoint_line_event_sym
+ assert_equal :line, Bug.tracepoint_line_event_sym
+ end
+
+ def test_tracepoint_specified_line_event_sym
+ assert_equal :line, Bug.tracepoint_specified_line_event_sym
+ end
+
</span> def test_after_gc_start_hook_with_GC_stress
bug8492 = '<a href="/issues/8492">[ruby-dev:47400]</a> [Bug #8492]: infinite after_gc_start_hook reentrance'
assert_nothing_raised(Timeout::Error, bug8492) do
<span class="gh">diff --git a/vm_trace.c b/vm_trace.c
index b814a12..eb54569 100644
</span><span class="gd">--- a/vm_trace.c
</span><span class="gi">+++ b/vm_trace.c
</span><span class="p">@@ -577,7 +577,7 @@</span> get_event_name(rb_event_flag_t event)
}
}
<span class="gd">-static ID
</span><span class="gi">+ID
</span> get_event_id(rb_event_flag_t event)
{
ID id;
<span class="err">
</span></code></pre>
<p>and</p>
<pre><code class="shell syntaxhl" data-language="shell"><span class="nv">$ </span>make test-all <span class="nv">TESTS</span><span class="o">=</span><span class="s2">"-- -ext-/tracepoint/test_tracepoint.rb"</span>
CC <span class="o">=</span> clang
LD <span class="o">=</span> ld
LDSHARED <span class="o">=</span> clang <span class="nt">-dynamic</span> <span class="nt">-bundle</span>
CFLAGS <span class="o">=</span> <span class="nt">-O0</span> <span class="nt">-fno-fast-math</span> <span class="nt">-g3</span> <span class="nt">-Wall</span> <span class="nt">-Wextra</span> <span class="nt">-Wno-unused-parameter</span> <span class="nt">-Wno-parentheses</span> <span class="nt">-Wno-long-long</span> <span class="nt">-Wno-missing-field-initializers</span> <span class="nt">-Wno-tautological-compare</span> <span class="nt">-Wno-parentheses-equality</span> <span class="nt">-Wno-constant-logical-operand</span> <span class="nt">-Wno-self-assign</span> <span class="nt">-Wunused-variable</span> <span class="nt">-Werror</span><span class="o">=</span>pointer-arith <span class="nt">-Werror</span><span class="o">=</span>write-strings <span class="nt">-Werror</span><span class="o">=</span>declaration-after-statement <span class="nt">-Werror</span><span class="o">=</span>shorten-64-to-32 <span class="nt">-Werror</span><span class="o">=</span>implicit-function-declaration <span class="nt">-Werror</span><span class="o">=</span>division-by-zero <span class="nt">-Werror</span><span class="o">=</span>deprecated-declarations <span class="nt">-Werror</span><span class="o">=</span>extra-tokens <span class="nt">-pipe</span>
XCFLAGS <span class="o">=</span> <span class="nt">-fstack-protector</span> <span class="nt">-fno-strict-overflow</span> <span class="nt">-fvisibility</span><span class="o">=</span>hidden <span class="nt">-DRUBY_EXPORT</span> <span class="nt">-fPIE</span>
CPPFLAGS <span class="o">=</span> <span class="nt">-DRUBY_DEBUG_ENV</span> <span class="nt">-DARRAY_DEBUG</span> <span class="nt">-D_XOPEN_SOURCE</span> <span class="nt">-D_DARWIN_C_SOURCE</span> <span class="nt">-D_DARWIN_UNLIMITED_SELECT</span> <span class="nt">-D_REENTRANT</span> <span class="nt">-I</span><span class="nb">.</span> <span class="nt">-I</span>.ext/include/x86_64-darwin14 <span class="nt">-I</span>./include <span class="nt">-I</span><span class="nb">.</span>
DLDFLAGS <span class="o">=</span> <span class="nt">-Wl</span>,-undefined,dynamic_lookup <span class="nt">-Wl</span>,-multiply_defined,suppress <span class="nt">-fstack-protector</span> <span class="nt">-Wl</span>,-u,_objc_msgSend <span class="nt">-Wl</span>,-pie <span class="nt">-framework</span> CoreFoundation
SOLIBS <span class="o">=</span> <span class="nt">-lgmp</span>
Apple LLVM version 6.1.0 <span class="o">(</span>clang-602.0.53<span class="o">)</span> <span class="o">(</span>based on LLVM 3.6.0svn<span class="o">)</span>
Target: x86_64-apple-darwin14.4.0
Thread model: posix
generating known_errors.inc
known_errors.inc unchanged
generating prelude.c
prelude.c unchanged
Run options: <span class="s2">"--ruby=./miniruby -I./lib -I. -I.ext/common ./tool/runruby.rb --extout=.ext -- --disable-gems"</span> <span class="nt">--excludes-dir</span><span class="o">=</span>./test/excludes <span class="nt">--name</span><span class="o">=!</span>/memory_leak/ <span class="nt">--</span>
<span class="c"># Running tests:</span>
<span class="o">[</span>4/7] TestTracepointObj#test_tracepoint_specified_line_event_sym <span class="o">=</span> 0.00 s
1<span class="o">)</span> Failure:
TestTracepointObj#test_tracepoint_specified_line_event_sym <span class="o">[</span>/Users/yuichirokaneko/ruby/ruby/test/-ext-/tracepoint/test_tracepoint.rb:66]:
<:line> expected but was
<:specified_line>.
Finished tests <span class="k">in </span>0.726435s, 9.6361 tests/s, 60.5698 assertions/s.
7 tests, 44 assertions, 1 failures, 0 errors, 0 skips
ruby <span class="nt">-v</span>: ruby 2.4.0dev <span class="o">(</span>2016-04-29 trunk 54818<span class="o">)</span> <span class="o">[</span>x86_64-darwin14]
make: <span class="k">***</span> <span class="o">[</span>yes-test-all] Error 1
</code></pre>
<p>To fix this</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="p">@@ -597,8 +597,7 @@</span> get_event_id(rb_event_flag_t event)
C(thread_begin, THREAD_BEGIN);
C(thread_end, THREAD_END);
C(fiber_switch, FIBER_SWITCH);
<span class="gd">- C(specified_line, SPECIFIED_LINE);
- case RUBY_EVENT_LINE | RUBY_EVENT_SPECIFIED_LINE: CONST_ID(id, "line"); return id;
</span><span class="gi">+ C(line, SPECIFIED_LINE);
</span> #undef C
default:
return 0;
</code></pre>
Ruby master - Bug #12271 (Closed): `Time#to_time` removes timezone information
https://bugs.ruby-lang.org/issues/12271
2016-04-12T09:35:33Z
yui-knk (Kaneko Yuichiro)
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">001</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="no">RUBY_VERSION</span>
<span class="o">=></span> <span class="s2">"2.3.0"</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">002</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="nb">require</span> <span class="s1">'date'</span>
<span class="o">=></span> <span class="kp">true</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">003</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="no">ENV</span><span class="p">[</span><span class="s1">'TZ'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'US/Eastern'</span>
<span class="o">=></span> <span class="s2">"US/Eastern"</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">004</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="n">time</span> <span class="o">=</span> <span class="no">Time</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2005</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">21</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="s1">'+09:00'</span><span class="p">)</span>
<span class="o">=></span> <span class="mi">2005</span><span class="o">-</span><span class="mo">02</span><span class="o">-</span><span class="mi">21</span> <span class="mi">10</span><span class="p">:</span><span class="mi">11</span><span class="p">:</span><span class="mi">12</span> <span class="o">+</span><span class="mi">0900</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">005</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="n">time</span><span class="p">.</span><span class="nf">to_time</span>
<span class="o">=></span> <span class="mi">2005</span><span class="o">-</span><span class="mo">02</span><span class="o">-</span><span class="mi">20</span> <span class="mi">20</span><span class="p">:</span><span class="mi">11</span><span class="p">:</span><span class="mi">12</span> <span class="o">-</span><span class="mo">0500</span>
</code></pre>
<p>Same as <a href="https://bugs.ruby-lang.org/issues/12189" class="external">https://bugs.ruby-lang.org/issues/12189</a>, <code>Time#to_time</code> does not use self timezone.<br>
I think it is better to make it to match with <code>DateTime#to_time</code> behavior.</p>
Ruby master - Bug #11842 (Closed): r53123 breaks some gems which use erb
https://bugs.ruby-lang.org/issues/11842
2015-12-19T07:03:25Z
yui-knk (Kaneko Yuichiro)
<p>r53123 breaks some gems which use erb.</p>
<p>Thor gem for example.<br>
They set an instance variable <code>"@output_buffer"</code> to 4th argument (<code>eoutvar</code>) of <code>ERB.new</code> (<a href="https://github.com/erikhuda/thor/blob/f0c2166534e122636f5ce04d61885736ef605617/lib/thor/actions/file_manipulation.rb#L116" class="external">here</a>).<br>
And change this instance variable from outside erb (<a href="https://github.com/erikhuda/thor/blob/f0c2166534e122636f5ce04d61885736ef605617/lib/thor/actions/file_manipulation.rb#L308" class="external">here</a>).</p>
<p><a href="https://github.com/ruby/ruby/blob/ec7a964dca57821d2d7a36f168c2355a46a76ca2/lib/erb.rb#L751" class="external">Example code of erb</a> shows this usage of <code>eoutvar</code>.<br>
I think we should revert r53123 and add a test case for this usage.</p>
<pre><code>Failures:
1) Thor::Actions#template allows using block helpers in the template
Failure/Error: concat(result.strip + " world!")
NoMethodError:
undefined method `strip' for ["Hello\n"]:Array
# ./spec/fixtures/group.thor:58:in `world'
# (erb):1:in `template'
# ./lib/thor/actions/file_manipulation.rb:116:in `block in template'
# ./lib/thor/actions/create_file.rb:53:in `render'
# ./lib/thor/actions/create_file.rb:62:in `block (2 levels) in invoke!'
# ./lib/thor/actions/create_file.rb:62:in `open'
# ./lib/thor/actions/create_file.rb:62:in `block in invoke!'
# ./lib/thor/actions/empty_directory.rb:116:in `invoke_with_conflict_check'
# ./lib/thor/actions/create_file.rb:60:in `invoke!'
# ./lib/thor/actions.rb:94:in `action'
# ./lib/thor/actions/create_file.rb:25:in `create_file'
# ./lib/thor/actions/file_manipulation.rb:115:in `template'
# ./spec/actions/file_manipulation_spec.rb:11:in `block in action'
# ./spec/helper.rb:55:in `capture'
# ./spec/actions/file_manipulation_spec.rb:11:in `action'
# ./spec/actions/file_manipulation_spec.rb:160:in `block (3 levels) in <top (required)>'
</code></pre>
Ruby master - Bug #11804 (Closed): 52931 以降、caseでInfinityを使用するとFloatDomainErrorが発生する
https://bugs.ruby-lang.org/issues/11804
2015-12-11T08:24:38Z
yui-knk (Kaneko Yuichiro)
<p>以下のようなケースです。</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="k">def</span> <span class="nf">test_infinity</span>
<span class="n">inf</span> <span class="o">=</span> <span class="mf">1.0</span><span class="o">/</span><span class="mf">0.0</span>
<span class="n">result</span> <span class="o">=</span> <span class="k">case</span> <span class="n">inf</span>
<span class="k">when</span> <span class="kp">true</span> <span class="k">then</span> <span class="mi">1</span>
<span class="k">when</span> <span class="kp">false</span> <span class="k">then</span> <span class="mi">0</span>
<span class="k">else</span>
<span class="n">inf</span><span class="p">.</span><span class="nf">to_i</span> <span class="k">rescue</span> <span class="kp">nil</span>
<span class="k">end</span>
<span class="n">assert_nil</span> <span class="n">result</span>
<span class="k">end</span>
</code></pre>
<p>52930の場合</p>
<pre><code># Running tests:
Finished tests in 0.136572s, 51.2550 tests/s, 314.8522 assertions/s.
7 tests, 43 assertions, 0 failures, 0 errors, 0 skips
</code></pre>
<p>52931の場合</p>
<pre><code>[4/7] TestCase#test_infinity = 0.00 s
1) Error:
TestCase#test_infinity:
FloatDomainError: Infinity
ruby/test/ruby/test_case.rb:156:in `test_infinity'
Finished tests in 0.135196s, 51.7767 tests/s, 310.6601 assertions/s.
7 tests, 42 assertions, 0 failures, 1 errors, 0 skips
</code></pre>
<p>なお<code>when</code>のあとがStringのみのケースだと2.2.3でも例外が発生します。</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">001</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="no">RUBY_VERSION</span>
<span class="o">=></span> <span class="s2">"2.2.3"</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">002</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="n">inf</span> <span class="o">=</span> <span class="mf">1.0</span><span class="o">/</span><span class="mf">0.0</span>
<span class="o">=></span> <span class="no">Infinity</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">003</span><span class="p">:</span><span class="mi">0</span><span class="o">></span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">004</span><span class="p">:</span><span class="mi">0</span><span class="o">*</span> <span class="n">result</span> <span class="o">=</span> <span class="k">case</span> <span class="n">inf</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">005</span><span class="p">:</span><span class="mi">1</span><span class="o">></span> <span class="k">when</span> <span class="s1">'str'</span> <span class="k">then</span> <span class="ss">:string</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">006</span><span class="p">:</span><span class="mi">1</span><span class="o">></span> <span class="k">else</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">007</span><span class="p">:</span><span class="mi">1</span><span class="o">*</span> <span class="n">inf</span><span class="p">.</span><span class="nf">to_i</span> <span class="k">rescue</span> <span class="kp">nil</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">00</span><span class="mi">8</span><span class="p">:</span><span class="mi">1</span><span class="o">></span> <span class="k">end</span>
<span class="no">FloatDomainError</span><span class="p">:</span> <span class="no">Infinity</span>
<span class="n">from</span> <span class="p">(</span><span class="n">irb</span><span class="p">):</span><span class="mi">4</span>
<span class="n">from</span> <span class="p">.</span><span class="nf">rbenv</span><span class="o">/</span><span class="n">versions</span><span class="o">/</span><span class="mf">2.2</span><span class="o">.</span><span class="mi">3</span><span class="o">/</span><span class="n">bin</span><span class="o">/</span><span class="n">irb</span><span class="p">:</span><span class="mi">11</span><span class="ss">:in</span> <span class="sb">`<main>'
</span></code></pre>
Ruby master - Misc #11770 (Closed): [PATCH] $KCODEへの代入時にwarningが発生することのテストを追加
https://bugs.ruby-lang.org/issues/11770
2015-12-04T02:11:05Z
yui-knk (Kaneko Yuichiro)
<p>testケースがなかったので、追加します。</p>
Ruby master - Misc #11757 (Closed): test_string.rbから不要なコードを削除する
https://bugs.ruby-lang.org/issues/11757
2015-12-01T12:58:56Z
yui-knk (Kaneko Yuichiro)
<p>テストでは<code>pre_1_7_1</code>に渡したブロックは実行されていないので、削除します</p>
Ruby master - Misc #11732 (Closed): [PATCH] Coverage restart に関するテストケースの追加
https://bugs.ruby-lang.org/issues/11732
2015-11-23T11:03:55Z
yui-knk (Kaneko Yuichiro)
<p>Coverageのrestart後に新しいファイルをrequireしたときの挙動がテストに記述されていなかったので、<code>test_restarting_coverage</code>に追記しました。</p>
Ruby master - Misc #11726 (Closed): [PATCH] Add a test case for `Coverage.peek_result`
https://bugs.ruby-lang.org/issues/11726
2015-11-21T05:06:27Z
yui-knk (Kaneko Yuichiro)
<p>Assert <code>Coverage.peek_result</code> raises Error if <code>Coverage.start</code> was not called before.</p>
Ruby master - Feature #11689 (Open): Add methods allow us to get visibility from Method and Unbou...
https://bugs.ruby-lang.org/issues/11689
2015-11-15T04:53:31Z
yui-knk (Kaneko Yuichiro)
<p>Add <code>Method#visibility</code> and <code>UnboundMethod#visibility</code> for getting visibility from Method and UnboundMethod object.<br>
In GitHub <a href="https://github.com/ruby/ruby/pull/1098" class="external">https://github.com/ruby/ruby/pull/1098</a>.</p>
Ruby master - Bug #11677 (Closed): 52530の変更により、sprintfの引数のhashにkeyが存在していてもvalueがnilのときにKeyErrorがで...
https://bugs.ruby-lang.org/issues/11677
2015-11-11T08:14:47Z
yui-knk (Kaneko Yuichiro)
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="k">def</span> <span class="nf">test_named_with_nil</span>
<span class="n">h</span> <span class="o">=</span> <span class="p">{</span> <span class="ss">key: </span><span class="kp">nil</span><span class="p">,</span> <span class="ss">key2: </span><span class="s2">"key2_val"</span> <span class="p">}</span>
<span class="n">assert_equal</span><span class="p">(</span><span class="s2">"key is , key2 is key2_val"</span><span class="p">,</span> <span class="s2">"key is %{key}, key2 is %{key2}"</span> <span class="o">%</span> <span class="n">h</span><span class="p">)</span>
<span class="k">end</span>
</code></pre>
<p>のようなテストが2.2.3では通るのですが、trunkでは</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">KeyError</span><span class="p">:</span> <span class="n">key</span><span class="p">{</span><span class="n">key</span><span class="p">}</span> <span class="ow">not</span> <span class="n">found</span>
</code></pre>
<p>となります。</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="s2">"a.hoge is %{a}, b.fuga is %{b}"</span> <span class="o">%</span> <span class="p">{</span> <span class="ss">a: </span><span class="n">a</span><span class="p">.</span><span class="nf">hoge</span><span class="p">,</span> <span class="ss">b: </span><span class="n">b</span><span class="p">.</span><span class="nf">fuga</span> <span class="p">}</span>
</code></pre>
<p>のように書きたいときにvalueがnilでないことのチェックする必要がでるため、<br>
今まで通りkeyが存在するときは例外が発生しないように修正したいです。</p>
Ruby master - Misc #11649 (Closed): [Refactor] Use `rb_method_visibility_t` instead of `int` in `...
https://bugs.ruby-lang.org/issues/11649
2015-11-03T08:17:50Z
yui-knk (Kaneko Yuichiro)
<p>See also <a href="https://github.com/ruby/ruby/pull/1078" class="external">https://github.com/ruby/ruby/pull/1078</a>.</p>
<p>Same as <code>rb_print_inaccessible</code>, change <code>rb_print_undef</code> to use <code>rb_method_visibility_t</code>.</p>
<p>Please let me merge this patch.</p>
Ruby master - Bug #11640 (Closed): [PATHC] Sometime `NameError#message` raises `ArgumentError: ma...
https://bugs.ruby-lang.org/issues/11640
2015-10-30T16:22:08Z
yui-knk (Kaneko Yuichiro)
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="k">def</span> <span class="nf">test_message_of_name_error</span>
<span class="k">begin</span>
<span class="no">Module</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="kp">module_function</span> <span class="ss">:foo</span>
<span class="k">end</span>
<span class="k">rescue</span> <span class="o">=></span> <span class="n">e</span>
<span class="n">error</span> <span class="o">=</span> <span class="n">e</span>
<span class="k">end</span>
<span class="n">assert_match</span> <span class="sr">/\Aundefined method `foo' for module `#<Module:.*>'\z/</span><span class="p">,</span> <span class="n">error</span><span class="p">.</span><span class="nf">message</span>
<span class="k">end</span>
<span class="c1"># =></span>
<span class="no">TestException</span><span class="c1">#test_name_error:</span>
<span class="no">ArgumentError</span><span class="p">:</span> <span class="n">malformed</span> <span class="nb">format</span> <span class="n">string</span> <span class="o">-</span> <span class="sx">%$
/Users/yuichirokaneko/ruby/ruby/test/ruby/test_exception.rb:734:in `to_str'
/Users/yuichirokaneko/ruby/ruby/test/ruby/test_exception.rb:734:in `to_s'
/Users/yuichirokaneko/ruby/ruby/test/ruby/test_exception.rb:734:in `message'
/Users/yuichirokaneko/ruby/ruby/test/ruby/test_exception.rb:734:in `test_name_error'
</span></code></pre>
<p>I send <a href="https://github.com/ruby/ruby/pull/1077" class="external">PR</a>.</p>
Ruby master - Bug #11618 (Rejected): Safe call syntax with aref or aset is
https://bugs.ruby-lang.org/issues/11618
2015-10-24T07:21:21Z
yui-knk (Kaneko Yuichiro)
<p>This test pass</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># ruby -v: ruby 2.3.0dev (2015-10-24 trunk 52128) [x86_64-darwin14]</span>
<span class="c1"># test/ruby/test_call.rb</span>
<span class="k">def</span> <span class="nf">test_safe_call_aref_aset</span>
<span class="n">s</span> <span class="o">=</span> <span class="no">Struct</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">:x</span><span class="p">,</span> <span class="ss">:y</span><span class="p">)</span>
<span class="n">o</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="nf">new</span><span class="p">({</span><span class="ss">a: </span><span class="mi">10</span><span class="p">})</span>
<span class="n">assert_equal</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">o</span><span class="p">.</span><span class="nf">x</span><span class="o">.</span><span class="p">?</span><span class="nb">send</span><span class="p">(</span><span class="ss">:[]</span><span class="p">,</span> <span class="p">:</span><span class="n">a</span><span class="p">))</span>
<span class="n">o</span><span class="p">.</span><span class="nf">x</span><span class="o">.</span><span class="p">?</span><span class="nb">send</span><span class="p">(</span><span class="ss">:[]=</span><span class="p">,</span> <span class="p">:</span><span class="n">a</span><span class="p">,</span> <span class="mi">11</span><span class="p">)</span>
<span class="n">assert_equal</span><span class="p">(</span><span class="mi">11</span><span class="p">,</span> <span class="n">o</span><span class="p">.</span><span class="nf">x</span><span class="o">.</span><span class="p">?</span><span class="nb">send</span><span class="p">(</span><span class="ss">:[]</span><span class="p">,</span> <span class="p">:</span><span class="n">a</span><span class="p">))</span>
<span class="n">assert_nil</span><span class="p">(</span><span class="n">o</span><span class="p">.</span><span class="nf">y</span><span class="o">.</span><span class="p">?</span><span class="nb">send</span><span class="p">(</span><span class="ss">:[]</span><span class="p">,</span> <span class="p">:</span><span class="n">a</span><span class="p">))</span>
<span class="n">o</span><span class="p">.</span><span class="nf">y</span><span class="o">.</span><span class="p">?</span><span class="nb">send</span><span class="p">(</span><span class="ss">:[]=</span><span class="p">,</span> <span class="p">:</span><span class="n">a</span><span class="p">,</span> <span class="mi">11</span><span class="p">)</span>
<span class="n">assert_nil</span><span class="p">(</span><span class="n">o</span><span class="p">.</span><span class="nf">y</span><span class="o">.</span><span class="p">?</span><span class="nb">send</span><span class="p">(</span><span class="ss">:[]</span><span class="p">,</span> <span class="p">:</span><span class="n">a</span><span class="p">))</span>
<span class="k">end</span>
</code></pre>
<p>This is invalid syntax</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># ruby -v: ruby 2.3.0dev (2015-10-24 trunk 52128) [x86_64-darwin14]</span>
<span class="c1"># test/ruby/test_call.rb</span>
<span class="k">def</span> <span class="nf">test_safe_call_aref_aset</span>
<span class="n">s</span> <span class="o">=</span> <span class="no">Struct</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">:x</span><span class="p">,</span> <span class="ss">:y</span><span class="p">)</span>
<span class="n">o</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="nf">new</span><span class="p">({</span><span class="ss">a: </span><span class="mi">10</span><span class="p">})</span>
<span class="n">assert_equal</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="n">o</span><span class="p">.</span><span class="nf">x</span><span class="o">.</span><span class="sc">?[</span><span class="ss">:a</span><span class="p">])</span>
<span class="n">o</span><span class="p">.</span><span class="nf">x</span><span class="o">.</span><span class="sc">?[</span><span class="ss">:a</span><span class="p">]</span> <span class="o">=</span> <span class="mi">11</span>
<span class="n">assert_equal</span><span class="p">(</span><span class="mi">11</span><span class="p">,</span> <span class="n">o</span><span class="p">.</span><span class="nf">x</span><span class="o">.</span><span class="sc">?[</span><span class="ss">:a</span><span class="p">])</span>
<span class="n">assert_nil</span><span class="p">(</span><span class="n">o</span><span class="p">.</span><span class="nf">y</span><span class="o">.</span><span class="sc">?[</span><span class="ss">:a</span><span class="p">])</span>
<span class="n">o</span><span class="p">.</span><span class="nf">y</span><span class="o">.</span><span class="sc">?[</span><span class="ss">:a</span><span class="p">]</span> <span class="o">=</span> <span class="mi">11</span>
<span class="n">assert_nil</span><span class="p">(</span><span class="n">o</span><span class="p">.</span><span class="nf">y</span><span class="o">.</span><span class="sc">?[</span><span class="ss">:a</span><span class="p">])</span>
<span class="k">end</span>
</code></pre>
<pre><code>./test/runner.rb: ruby/ruby/test/ruby/test_call.rb:60: syntax error, unexpected '[', expecting '(' (SyntaxError)
assert_equal(10, o.x.?[:a])
^
ruby/ruby/test/ruby/test_call.rb:61: syntax error, unexpected '[', expecting '('
o.x.?[:a] = 11
^
ruby/ruby/test/ruby/test_call.rb:62: syntax error, unexpected '[', expecting '('
assert_equal(11, o.x.?[:a])
^
ruby/ruby/test/ruby/test_call.rb:64: syntax error, unexpected '[', expecting '('
assert_nil(o.y.?[:a])
^
ruby/ruby/test/ruby/test_call.rb:65: syntax error, unexpected '[', expecting '('
o.y.?[:a] = 11
^
ruby/ruby/test/ruby/test_call.rb:66: syntax error, unexpected '[', expecting '('
assert_nil(o.y.?[:a])
^
make: *** [yes-test-all] Error 1
</code></pre>
Ruby master - Bug #9619 (Closed): Fix README.EXT
https://bugs.ruby-lang.org/issues/9619
2014-03-10T13:29:11Z
yui-knk (Kaneko Yuichiro)
<p>Update contents of <code>ruby_options</code> and replace <code>ruby_run</code> to <code>ruby_run_node</code>.</p>
<p>README.EXTの<code>ruby_options</code>を更新し、<code>ruby_run</code>を<code>ruby_run_node</code>に変えました。</p>
Ruby master - Bug #9615 (Closed): fix typo in comments of eval.c
https://bugs.ruby-lang.org/issues/9615
2014-03-09T02:36:35Z
yui-knk (Kaneko Yuichiro)
<p>Delete unnecessary space from comments of eval.c .<br>
不要に思われるスペースを削除しました。</p>
Ruby master - Bug #9526 (Rejected): Method#owner returns wrong owner if using prepend.
https://bugs.ruby-lang.org/issues/9526
2014-02-17T14:24:50Z
yui-knk (Kaneko Yuichiro)
<p>rdoc indicates that Method#owner will return a class or module that defines a method.<br>
<a href="http://www.ruby-doc.org/core-2.0/Method.html#method-i-owner" class="external">http://www.ruby-doc.org/core-2.0/Method.html#method-i-owner</a></p>
<hr>
<p>module MyMod<br>
def x(y)<br>
super(y*y)<br>
end<br>
end</p>
<p>class Blah<br>
def x(y)<br>
y + 1<br>
end<br>
prepend MyMod<br>
end</p>
<p>Blah.new.method(:x).owner<br>
# => MyMod</p>
<hr>
<p>In this case, a class or module that defines a method is Blah.<br>
So I think Blah.new.method(:x).owner should return Blah.</p>