[#5563] Non-overridable and non-redefinable methods — Eric Mahurin <eric_mahurin@...>

Lately, I've been thinking about the future of ruby

44 messages 2005/08/19
[#5564] Re: Non-overridable and non-redefinable methods — Austin Ziegler <halostatue@...> 2005/08/19

On 8/19/05, Eric Mahurin <eric_mahurin@yahoo.com> wrote:

[#5571] Re: Non-overridable and non-redefinable methods — Eric Mahurin <eric_mahurin@...> 2005/08/19

--- Austin Ziegler <halostatue@gmail.com> wrote:

[#5574] Re: Non-overridable and non-redefinable methods — TRANS <transfire@...> 2005/08/20

Just wanted to add a few things.

[#5581] Re: Non-overridable and non-redefinable methods — Austin Ziegler <halostatue@...> 2005/08/20

On 8/19/05, TRANS <transfire@gmail.com> wrote:

[#5583] Re: Non-overridable and non-redefinable methods — "David A. Black" <dblack@...> 2005/08/20

Hi --

[#5585] Re: Non-overridable and non-redefinable methods — Eric Mahurin <eric_mahurin@...> 2005/08/20

--- "David A. Black" <dblack@wobblini.net> wrote:

[#5609] Pathname#walk for traversing path nodes (patch) — ES <ruby-ml@...>

Here is a small addition to Pathname against 1.9, probably suited

20 messages 2005/08/22

Re: [BUG] bug in variable assignment

From: Mauricio Fernandez <mfp@...>
Date: 2005-08-09 22:14:37 UTC
List: ruby-core #5543
hi,

On Tue, Aug 09, 2005 at 07:26:11AM +0900, Mauricio Fernandez wrote:
> On Mon, Aug 08, 2005 at 11:36:22AM +0900, nobuyoshi nakada wrote:
> > Does this fix it?
> Not quite:
> 
> $ ./ruby -v -e "->(&b){b.call(1)}.call{|x| puts x}"
> ruby 1.9.0 (2005-08-08) [i686-linux]
> -e:1: warning: multiple values for a block parameter (0 for 1)
>         from -e:1
> -e:1: wrong number of arguments (1 for 0) (ArgumentError)
>         from -e:1


I've found another problem with the other formal parameters:

$ ./ruby -ve "a = 0; ->(a){}.call(2); p a"
ruby 1.9.0 (2005-08-09) [i686-linux]
0

The patch is somewhat larger this time: I also updated the unit tests
you added under test/ruby/test_lambda.rb.


Index: node.h
===================================================================
RCS file: /src/ruby/node.h,v
retrieving revision 1.68
diff -p -u -r1.68 node.h
--- node.h	27 Jul 2005 07:27:18 -0000	1.68
+++ node.h	9 Aug 2005 22:01:34 -0000
@@ -208,7 +208,7 @@ typedef struct RNode {
 
 #define nd_lit   u1.value
 
-#define nd_frml  u3.value
+#define nd_frml  u3.node
 #define nd_rest  u2.node
 #define nd_opt   u1.node
 
Index: eval.c
===================================================================
RCS file: /src/ruby/eval.c,v
retrieving revision 1.814
diff -p -u -r1.814 eval.c
--- eval.c	9 Aug 2005 12:53:38 -0000	1.814
+++ eval.c	9 Aug 2005 22:01:41 -0000
@@ -5737,7 +5737,7 @@ formal_assign(recv, node, argc, argv, lo
 	rb_bug("no argument-node");
     }
 
-    i = node->nd_frml ? RARRAY(node->nd_frml)->len : 0;
+    i = node->nd_frml ? node->nd_frml->nd_alen : 0;
     if (i > argc) {
 	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, i);
     }
@@ -5761,10 +5761,11 @@ formal_assign(recv, node, argc, argv, lo
     }
     else {
 	int j;
-	VALUE a = node->nd_frml;
+	NODE *a = node->nd_frml;
 
 	for (j=0; j<i; j++) {
-	    dvar_asgn_curr(SYM2ID(RARRAY(a)->ptr[j]), argv[j]);
+	    assign(recv, a->nd_head, argv[j], 1);
+	    a = a->nd_next;
 	}
     }
     argv += i; argc -= i;
@@ -9339,7 +9340,7 @@ rb_node_arity(body)
 	if (nd_type(body) == NODE_BLOCK)
 	    body = body->nd_head;
 	if (!body) return 0;
-	n = body->nd_frml ? RARRAY(body->nd_frml)->len : 0;
+	n = body->nd_frml ? body->nd_frml->nd_alen : 0;
 	if (body->nd_opt || body->nd_rest)
 	    n = -n-1;
 	return n;
Index: parse.y
===================================================================
RCS file: /src/ruby/parse.y,v
retrieving revision 1.401
diff -p -u -r1.401 parse.y
--- parse.y	8 Aug 2005 23:24:23 -0000	1.401
+++ parse.y	9 Aug 2005 22:01:44 -0000
@@ -245,7 +245,7 @@ static NODE *evstr2dstr _((NODE*));
 static NODE *call_op_gen _((struct parser_params*,NODE*,ID,int,NODE*));
 #define call_op(recv,id,narg,arg1) call_op_gen(parser, recv,id,narg,arg1)
 
-static NODE *new_args_gen _((struct parser_params*,VALUE,NODE*,NODE*,NODE*));
+static NODE *new_args_gen _((struct parser_params*,NODE*,NODE*,NODE*,NODE*));
 #define new_args(f,o,r,b) new_args_gen(parser, f,o,r,b)
 
 static NODE *negate_lit _((NODE*));
@@ -519,7 +519,7 @@ static void ripper_compile_error _((stru
 %type <node> mlhs mlhs_head mlhs_basic mlhs_entry mlhs_item mlhs_node
 %type <id>   fsym variable sym symbol operation operation2 operation3
 %type <id>   cname fname op f_norm_arg
-%type <val>  f_arg
+%type <node> f_arg
 /*%%%*/
 /*%
 %type <val> program reswords then do dot_or_colon
@@ -4097,7 +4097,9 @@ f_norm_arg	: tCONSTANT
 			if (!is_local_id($1))
 			    yyerror("formal argument must be local variable");
 			if (dyna_in_block()) {
-			    dyna_var($1);
+			    if (!local_id($1) && !rb_dvar_defined($1)) {
+				dyna_var($1);
+			    }
 			}
 			else {
 			    local_cnt($1);
@@ -4110,14 +4112,31 @@ f_norm_arg	: tCONSTANT
 		;
 
 f_arg		: f_norm_arg
-		    { $$ = rb_ary_new3(1, ID2SYM($1)); }
+		    { $$ = NEW_LIST(assignable($1, 0)); }
 		| f_arg ',' f_norm_arg
 		    {
-			$$ = $1;
-			if (rb_ary_includes($$, ID2SYM($3))) {
-			    yyerror("duplicated argument name");
+			{
+			    NODE *n = $1;
+			    $$ = $1;
+			    
+			    while (n) {
+				switch (nd_type(n->nd_head)) {
+				  case NODE_DASGN:
+				  case NODE_DASGN_CURR:
+				  case NODE_LASGN:
+				    if (n->nd_head->nd_vid == $3) {
+					yyerror("duplicated argument name");
+				    }
+				    break;
+				  default:
+				    rb_bug("invalid formal argument nodetype(%d)",
+					   nd_type(n->nd_head));
+				    break;
+				}
+				n = n->nd_next;
+			    }
 			}
-			rb_ary_push($$, ID2SYM($3));
+			list_append($$, assignable($3, 0));
 		    }
 		;
 
@@ -7988,46 +8007,52 @@ arg_prepend(node1, node2)
 static int
 arg_dup_check(vid, m, list, node)
     ID vid;
-    VALUE m, list;
-    NODE *node;
+    NODE *m, **list, *node;
 {
-    VALUE sym = ID2SYM(vid);
-    if ((m && rb_ary_includes(m, sym)) || rb_ary_includes(list, sym)) {
-	ruby_sourceline = nd_line(node);
-	return 1;
+    NODE *n1, *n2;
+
+    n1 = m;
+    n2 = *list;
+    while (n1 || n2) {
+	if ((n1 && n1->nd_head->nd_vid == vid) || 
+	    (n2 && n2->nd_head->nd_vid == vid)) {
+	    ruby_sourceline = nd_line(node);
+	    return 1;
+	}
+	n1 = n1 ? n1->nd_next : n1;
+	n2 = n2 ? n2->nd_next : n2;
     }
-    rb_ary_push(list, sym);		  
+    
+    *list = list_append(*list, NEW_DASGN(vid, 0));
     return 0;
 }
 
 static NODE*
 new_args_gen(parser, m, o, r, b)
     struct parser_params *parser;
-    VALUE m;
-    NODE *o, *r, *b;
+    NODE *m, *o, *r, *b;
 {
     int saved_line = ruby_sourceline;
-    NODE *tmp;
-    VALUE list;
+    NODE *tmp, *list;
 
-    list = rb_ary_new();
+    list = 0;
     tmp = o;
     while (tmp) {
 	if (!tmp->nd_head) break;
-	if (arg_dup_check(tmp->nd_head->nd_vid, m, list, tmp)) {
+	if (arg_dup_check(tmp->nd_head->nd_vid, m, &list, tmp)) {
 	    yyerror("duplicated optional argument name");
 	    return 0;	
 	}
 	tmp = tmp->nd_next;
     }
     if (RTEST(r)) {
-	if (arg_dup_check(r->nd_vid, m, list, r)) {
+	if (arg_dup_check(r->nd_vid, m, &list, r)) {
 	    yyerror("duplicated rest argument name");
 	    return 0;
 	}
     }
     if (b) {
-	if (arg_dup_check(b->nd_vid, m, list, b)) {
+	if (arg_dup_check(b->nd_vid, m, &list, b)) {
 	    yyerror("duplicated block argument name");
 	    return 0;
 	}
Index: test/ruby/test_lambda.rb
===================================================================
RCS file: /src/ruby/test/ruby/test_lambda.rb,v
retrieving revision 1.1
diff -p -u -r1.1 test_lambda.rb
--- test/ruby/test_lambda.rb	8 Aug 2005 23:24:29 -0000	1.1
+++ test/ruby/test_lambda.rb	9 Aug 2005 22:01:44 -0000
@@ -50,4 +50,42 @@ class TestLambdaParameters < Test::Unit:
     2.times ->(_){ a += 1 }
     assert_equal(a, 2)
   end
+
+  def test_formal_args_with_lvars
+    a = b = c = 0
+    ->(a){}.call(1)
+    ->(b,c){}.call(2,3)
+
+    assert_equal([1,2,3], [a,b,c])
+
+    a = nil
+    ->(&a){}.call{ }
+    assert_instance_of(Proc, a)
+  end
+  
+  def test_lambda_with_dvars
+    w, x, y, z = lambda do
+      a = b = c = 0
+      [->(){a}, ->(){b}, ->(){c}, ->(a,b,&c){ }]
+    end.call
+    
+    assert_equal([0,0,0], [w[], x[], y[]])
+    z.call(1,2){ }
+    assert_instance_of(Proc, y[])
+    assert_equal([1,2], [w[], x[]])
+  end
+  
+  def test_formal_args_with_mixed_vars
+    a = b = c = x = 0
+    _a, _b, _c, _d, _e, _f = lambda do
+      d = e = 0
+      [->(){a}, ->(){b}, ->(){c}, ->(){d}, ->(){e}, ->(a,b,_,c=0,*d,&e){ e.call }]
+    end.call
+    
+    assert_equal([0,0,0,0,0,0], [_a[], _b[], _c[], _d[], _e[], x])
+    _f.call(1,2,2,3,4,5){ x = 10 }
+    assert_equal([1,2,3,[4,5], 10], [_a[], _b[], _c[], _d[], x])
+    _f.call(1,2,2){ x = 20 }
+    assert_equal([1,2,0,[],20], [_a[], _b[], _c[], _d[], x])
+  end
 end


$ ./ruby -e "a = 0; ->(a){}.call(2); p a"
2
$ ./ruby test/ruby/test_lambda.rb
Loaded suite test/ruby/test_lambda
Started
.........
Finished in 0.009704 seconds.

9 tests, 32 assertions, 0 failures, 0 errors
$ make test
rbconfig.rb unchanged
test succeeded


-- 
Mauricio Fernandez

In This Thread