------art_4908_25005344.1211700664123
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

This patch is an independent but related one to my previous one.  It can be
combined to allow for normal block syntax lambdas with default arguments.
This patch allows you to make lambda's more concisely by simply removing the
"lambda":

plus   |a,b| a+b }  # |'s are required to disambiguate with a Hash
plus[1, 2] # 3

f  o 42 end   # || not required
f[] # 42

def my_while(cond)
    yield while cond[]
end
i
my_while({ || (i-.nonzero?}) { p i }

9
8
7
6
5
4
3
2
1


I wasn't able to get rid of some reduce/reduce conflict warnings (at
yacc/compile time).  They are come from the do/end, not the {}.  I tried
putting in some %prec attributes to help, but didn't get anywhere.  A yacc
expert may have better luck.  It looks like the default precedence is
correct though.  I assume the problem occurs between the first argument of a
no parens call arg list and a block for that call.  It looks to treat it as
a block in this case (instead of a lambda for the first argument), which
will maintain compatibility?

Here would be a ChangeLog entry:

* parse.y (primary) : allow for a <block_lambda>.  The <block_lambda>
grammar is almost identical to a normal block except |'s are required in the
{} form (to disambiguate from a Hash).  The semantics are equivalent to
preceding the block with "lambda".
* sample/test.rb : tests for the above.


Index: sample/test.rb
--- sample/test.rb    (revision 16585)
+++ sample/test.rb    (working copy)
@@ -1027,6 +1027,20 @@
 call_argument_test(false, lambda{|a,|})
 call_argument_test(false, lambda{|a,|}, 1,2)

+call_argument_test(true, {||})
+call_argument_test(false, {||}, 1)
+call_argument_test(true, {|a,|}, 1)
+call_argument_test(false, {|a,|})
+call_argument_test(false, {|a,|}, 1,2)
+
+call_argument_test(true, do end)
+call_argument_test(false, do end, 1)
+call_argument_test(true, do || end)
+call_argument_test(false, do || end, 1)
+call_argument_test(true, do |a,| end, 1)
+call_argument_test(false, do |a,| end)
+call_argument_test(false, do |a,| end, 1,2)
+
 call_argument_test(true, Proc.new{||})
 call_argument_test(true, Proc.new{||}, 1)
 call_argument_test(true, Proc.new{|a,|}, 1)
Index: parse.y
--- parse.y    (revision 16585)
+++ parse.y    (working copy)
@@ -670,6 +670,7 @@
 %type <node> assoc_list assocs assoc undef_list backref string_dvar for_var
 %type <node> block_param opt_block_param block_param_def f_opt
 %type <node> bv_decls opt_bv_decl bvar
+%type <node> block_lambda
 %type <node> lambda f_larglist lambda_body
 %type <node> brace_block cmd_brace_block do_block lhs none fitem
 %type <node> mlhs mlhs_head mlhs_basic mlhs_item mlhs_node mlhs_post
mlhs_inner
@@ -2641,6 +2642,10 @@
             $$  ispatch1(hash, escape_Qundef($2));
             %*/
             }
+                | block_lambda
+            {
+            $$  1;
+            }
         | keyword_return
             {
             /*%%%*/
@@ -3327,6 +3332,56 @@
             }
         ;

+block_lambda    : tLBRACE
+            {
+            /*%%%*/
+            dyna_push();
+            $<num>$  uby_sourceline;
+            /*%
+                    %*/
+            }
+                  block_param_def compstmt '}'
+            {
+            /*%%%*/
+                        $$  EW_ITER($3, $4);
+            nd_set_line($$, $<num>2);
+            dyna_pop();
+            $$->nd_iter  EW_FCALL(rb_intern("lambda"), 0);
+            fixpos($$->nd_iter, $$);
+            /*%
+            $$  ethod_arg(
+                            dispatch1(fcall, rb_intern("lambda")),
+                            arg_new());
+            $$  ethod_add_block($$,
+                            dispatch2(brace_block, escape_Qundef($3), $4));
+            %*/
+            }
+        | keyword_do_block
+            {
+            /*%%%*/
+            dyna_push();
+            $<num>$  uby_sourceline;
+            /*%
+                    %*/
+            }
+                  opt_block_param compstmt keyword_end
+            {
+            /*%%%*/
+                        $$  EW_ITER($3, $4);
+            nd_set_line($$, $<num>2);
+            dyna_pop();
+            $$->nd_iter  EW_FCALL(rb_intern("lambda"), 0);
+            fixpos($$->nd_iter, $$);
+            /*%
+            $$  ethod_arg(
+                            dispatch1(fcall, rb_intern("lambda")),
+                            arg_new());
+            $$  ethod_add_block($$,
+                            dispatch2(do_block, escape_Qundef($3), $4));
+            %*/
+            }
+                ;
+
 f_larglist    : '(' f_args opt_bv_decl rparen
             {
             /*%%%*/

------art_4908_25005344.1211700664123
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

This patch is an independent but related one to my previous one.&nbsp; It can be combined to allow for normal block syntax lambdas with default arguments.&nbsp; This patch allows you to make lambda&#39;s more concisely by simply removing the &quot;lambda&quot;:<br>
<br>plus   |a,b| a+b }&nbsp; # |&#39;s are required to disambiguate with a Hash<br>plus[1, 2] # t; 3<br><br>f  o 42 end&nbsp;&nbsp; # || not required<br>f[] # t; 42<br><br>def my_while(cond)<br>&nbsp;&nbsp;&nbsp; yield while cond[]<br>end<br>
i<br>my_while({ || (i-.nonzero?}) { p i }<br><br>9<br>8<br>7<br>6<br>5<br>4<br>3<br>2<br>1<br><br><br>I wasn&#39;t able to get rid of some reduce/reduce conflict warnings (at yacc/compile time).&nbsp; They are come from the do/end, not the {}.&nbsp; I tried putting in some %prec attributes to help, but didn&#39;t get anywhere.&nbsp; A yacc expert may have better luck.&nbsp; It looks like the default precedence is correct though.&nbsp; I assume the problem occurs between the first argument of a no parens call arg list and a block for that call.&nbsp; It looks to treat it as a block in this case (instead of a lambda for the first argument), which will maintain compatibility?<br>
<br>Here would be a ChangeLog entry:<br><br>* parse.y (primary) : allow for a &lt;block_lambda&gt;.&nbsp; The &lt;block_lambda&gt; grammar is almost identical to a normal block except |&#39;s are required in the {} form (to disambiguate from a Hash).&nbsp; The semantics are equivalent to preceding the block with &quot;lambda&quot;.<br>
* sample/test.rb : tests for the above.<br><br><br>Index: sample/test.rb<br>r>--- sample/test.rb&nbsp;&nbsp;&nbsp; (revision 16585)<br>+++ sample/test.rb&nbsp;&nbsp;&nbsp; (working copy)<br>
@@ -1027,6 +1027,20 @@<br>&nbsp;call_argument_test(false, lambda{|a,|})<br>&nbsp;call_argument_test(false, lambda{|a,|}, 1,2)<br>&nbsp;<br>+call_argument_test(true, {||})<br>+call_argument_test(false, {||}, 1)<br>+call_argument_test(true, {|a,|}, 1)<br>
+call_argument_test(false, {|a,|})<br>+call_argument_test(false, {|a,|}, 1,2)<br>+<br>+call_argument_test(true, do end)<br>+call_argument_test(false, do end, 1)<br>+call_argument_test(true, do || end)<br>+call_argument_test(false, do || end, 1)<br>
+call_argument_test(true, do |a,| end, 1)<br>+call_argument_test(false, do |a,| end)<br>+call_argument_test(false, do |a,| end, 1,2)<br>+<br>&nbsp;call_argument_test(true, Proc.new{||})<br>&nbsp;call_argument_test(true, Proc.new{||}, 1)<br>
&nbsp;call_argument_test(true, Proc.new{|a,|}, 1)<br>Index: parse.y<br>r>--- parse.y&nbsp;&nbsp;&nbsp; (revision 16585)<br>+++ parse.y&nbsp;&nbsp;&nbsp; (working copy)<br>@@ -670,6 +670,7 @@<br>
&nbsp;%type &lt;node&gt; assoc_list assocs assoc undef_list backref string_dvar for_var<br>&nbsp;%type &lt;node&gt; block_param opt_block_param block_param_def f_opt<br>&nbsp;%type &lt;node&gt; bv_decls opt_bv_decl bvar<br>+%type &lt;node&gt; block_lambda<br>
&nbsp;%type &lt;node&gt; lambda f_larglist lambda_body<br>&nbsp;%type &lt;node&gt; brace_block cmd_brace_block do_block lhs none fitem<br>&nbsp;%type &lt;node&gt; mlhs mlhs_head mlhs_basic mlhs_item mlhs_node mlhs_post mlhs_inner<br>@@ -2641,6 +2642,10 @@<br>
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $$  ispatch1(hash, escape_Qundef($2));<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; %*/<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | block_lambda<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $$  1;<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; | keyword_return<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /*%%%*/<br>@@ -3327,6 +3332,56 @@<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ;<br>&nbsp;<br>+block_lambda&nbsp;&nbsp;&nbsp; : tLBRACE<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /*%%%*/<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dyna_push();<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $&lt;num&gt;$  uby_sourceline;<br>
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /*%<br>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %*/<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; block_param_def compstmt &#39;}&#39;<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /*%%%*/<br>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $$  EW_ITER($3, $4);<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; nd_set_line($$, $&lt;num&gt;2);<br>
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dyna_pop();<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $$-&gt;nd_iter  EW_FCALL(rb_intern(&quot;lambda&quot;), 0);<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fixpos($$-&gt;nd_iter, $$);<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /*%<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $$  ethod_arg(<br>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dispatch1(fcall, rb_intern(&quot;lambda&quot;)),<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arg_new());<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $$  ethod_add_block($$,<br>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dispatch2(brace_block, escape_Qundef($3), $4));<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; %*/<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; | keyword_do_block<br>
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /*%%%*/<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dyna_push();<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $&lt;num&gt;$  uby_sourceline;<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /*%<br>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %*/<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; opt_block_param compstmt keyword_end<br>
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /*%%%*/<br>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $$  EW_ITER($3, $4);<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; nd_set_line($$, $&lt;num&gt;2);<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dyna_pop();<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $$-&gt;nd_iter  EW_FCALL(rb_intern(&quot;lambda&quot;), 0);<br>
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fixpos($$-&gt;nd_iter, $$);<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /*%<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $$  ethod_arg(<br>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dispatch1(fcall, rb_intern(&quot;lambda&quot;)),<br>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arg_new());<br>
+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $$  ethod_add_block($$,<br>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dispatch2(do_block, escape_Qundef($3), $4));<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; %*/<br>+&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;<br>+<br>&nbsp;f_larglist&nbsp;&nbsp;&nbsp; : &#39;(&#39; f_args opt_bv_decl rparen<br>
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /*%%%*/<br>

------art_4908_25005344.1211700664123--