@@ -681,8 +681,8 @@ static VALUE rb_yield_0 _((VALUE, VALUE, VALUE));
681
681
static VALUE rb_call _ ((VALUE ,VALUE ,ID ,int ,VALUE * ,int ));
682
682
static VALUE module_setup _ ((VALUE ,NODE * ));
683
683
684
- static VALUE massign _ ((VALUE ,NODE * ,VALUE ));
685
- static void assign _ ((VALUE ,NODE * ,VALUE ));
684
+ static VALUE massign _ ((VALUE ,NODE * ,VALUE , int ));
685
+ static void assign _ ((VALUE ,NODE * ,VALUE , int ));
686
686
687
687
static int safe_level = 0 ;
688
688
/* safe-level:
@@ -2314,7 +2314,7 @@ rb_eval(self, node)
2314
2314
break ;
2315
2315
2316
2316
case NODE_MASGN :
2317
- result = massign (self , node , rb_eval (self , node -> nd_value ));
2317
+ result = massign (self , node , rb_eval (self , node -> nd_value ), 0 );
2318
2318
break ;
2319
2319
2320
2320
case NODE_LASGN :
@@ -3162,10 +3162,15 @@ rb_yield_0(val, self, klass)
3162
3162
if (!self ) self = block -> self ;
3163
3163
node = block -> body ;
3164
3164
if (block -> var ) {
3165
- if (nd_type (block -> var ) == NODE_MASGN )
3166
- massign (self , block -> var , val );
3167
- else
3168
- assign (self , block -> var , val );
3165
+ PUSH_TAG (PROT_NONE );
3166
+ if ((state = EXEC_TAG ()) == 0 ) {
3167
+ if (nd_type (block -> var ) == NODE_MASGN )
3168
+ massign (self , block -> var , val , 1 );
3169
+ else
3170
+ assign (self , block -> var , val , 1 );
3171
+ }
3172
+ POP_TAG ();
3173
+ if (state ) goto pop_state ;
3169
3174
}
3170
3175
PUSH_ITER (block -> iter );
3171
3176
PUSH_TAG (PROT_NONE );
@@ -3201,6 +3206,7 @@ rb_yield_0(val, self, klass)
3201
3206
}
3202
3207
}
3203
3208
POP_TAG ();
3209
+ pop_state :
3204
3210
POP_ITER ();
3205
3211
POP_CLASS ();
3206
3212
POP_VARS ();
@@ -3227,13 +3233,14 @@ rb_f_loop()
3227
3233
}
3228
3234
3229
3235
static VALUE
3230
- massign (self , node , val )
3236
+ massign (self , node , val , check )
3231
3237
VALUE self ;
3232
3238
NODE * node ;
3233
3239
VALUE val ;
3240
+ int check ;
3234
3241
{
3235
3242
NODE * list ;
3236
- int i , len ;
3243
+ int i = 0 , len ;
3237
3244
3238
3245
list = node -> nd_head ;
3239
3246
@@ -3243,33 +3250,46 @@ massign(self, node, val)
3243
3250
}
3244
3251
len = RARRAY (val )-> len ;
3245
3252
for (i = 0 ; list && i < len ; i ++ ) {
3246
- assign (self , list -> nd_head , RARRAY (val )-> ptr [i ]);
3253
+ assign (self , list -> nd_head , RARRAY (val )-> ptr [i ], check );
3247
3254
list = list -> nd_next ;
3248
3255
}
3256
+ if (check && list ) goto arg_error ;
3249
3257
if (node -> nd_args ) {
3250
3258
if (!list && i < len ) {
3251
- assign (self , node -> nd_args , rb_ary_new4 (len - i , RARRAY (val )-> ptr + i ));
3259
+ assign (self , node -> nd_args , rb_ary_new4 (len - i , RARRAY (val )-> ptr + i ), check );
3252
3260
}
3253
3261
else {
3254
- assign (self , node -> nd_args , rb_ary_new2 (0 ));
3262
+ assign (self , node -> nd_args , rb_ary_new2 (0 ), check );
3255
3263
}
3256
3264
}
3265
+ else if (check && i < len ) goto arg_error ;
3257
3266
}
3258
3267
else if (node -> nd_args ) {
3259
- assign (self , node -> nd_args , Qnil );
3268
+ assign (self , node -> nd_args , Qnil , check );
3260
3269
}
3270
+
3271
+ if (check && list ) goto arg_error ;
3261
3272
while (list ) {
3262
- assign (self , list -> nd_head , Qnil );
3273
+ i ++ ;
3274
+ assign (self , list -> nd_head , Qnil , check );
3263
3275
list = list -> nd_next ;
3264
3276
}
3265
3277
return val ;
3278
+
3279
+ arg_error :
3280
+ while (list ) {
3281
+ i ++ ;
3282
+ list = list -> nd_next ;
3283
+ }
3284
+ rb_raise (rb_eArgError , "wrong # of arguments (%d for %d)" , len , i );
3266
3285
}
3267
3286
3268
3287
static void
3269
- assign (self , lhs , val )
3288
+ assign (self , lhs , val , check )
3270
3289
VALUE self ;
3271
3290
NODE * lhs ;
3272
3291
VALUE val ;
3292
+ int check ;
3273
3293
{
3274
3294
switch (nd_type (lhs )) {
3275
3295
case NODE_GASGN :
@@ -3299,7 +3319,7 @@ assign(self, lhs, val)
3299
3319
break ;
3300
3320
3301
3321
case NODE_MASGN :
3302
- massign (self , lhs , val );
3322
+ massign (self , lhs , val , check );
3303
3323
break ;
3304
3324
3305
3325
case NODE_CALL :
@@ -3852,7 +3872,7 @@ rb_call0(klass, recv, id, argc, argv, body, nosuper)
3852
3872
NODE * opt = node -> nd_opt ;
3853
3873
3854
3874
while (opt && argc ) {
3855
- assign (recv , opt -> nd_head , * argv );
3875
+ assign (recv , opt -> nd_head , * argv , 1 );
3856
3876
argv ++ ; argc -- ;
3857
3877
opt = opt -> nd_next ;
3858
3878
}
@@ -5427,10 +5447,19 @@ proc_call(proc, args)
5427
5447
struct BLOCK * volatile old_block ;
5428
5448
struct BLOCK * data ;
5429
5449
volatile VALUE result = Qnil ;
5430
- int state ;
5450
+ int state , n ;
5431
5451
volatile int orphan ;
5432
5452
volatile int safe = safe_level ;
5433
5453
5454
+ Data_Get_Struct (proc , struct BLOCK , data );
5455
+ orphan = blk_orphan (data );
5456
+
5457
+ /* PUSH BLOCK from data */
5458
+ old_block = ruby_block ;
5459
+ ruby_block = data ;
5460
+ PUSH_ITER (ITER_CUR );
5461
+ ruby_frame -> iter = ITER_CUR ;
5462
+
5434
5463
if (TYPE (args ) == T_ARRAY ) {
5435
5464
switch (RARRAY (args )-> len ) {
5436
5465
case 0 :
@@ -5442,15 +5471,6 @@ proc_call(proc, args)
5442
5471
}
5443
5472
}
5444
5473
5445
- Data_Get_Struct (proc , struct BLOCK , data );
5446
- orphan = blk_orphan (data );
5447
-
5448
- /* PUSH BLOCK from data */
5449
- old_block = ruby_block ;
5450
- ruby_block = data ;
5451
- PUSH_ITER (ITER_CUR );
5452
- ruby_frame -> iter = ITER_CUR ;
5453
-
5454
5474
if (orphan ) {/* orphan procedure */
5455
5475
if (rb_iterator_p ()) {
5456
5476
ruby_block -> frame .iter = ITER_CUR ;
@@ -5494,6 +5514,31 @@ proc_call(proc, args)
5494
5514
return result ;
5495
5515
}
5496
5516
5517
+ static VALUE
5518
+ proc_arity (proc )
5519
+ VALUE proc ;
5520
+ {
5521
+ struct BLOCK * data ;
5522
+ NODE * list ;
5523
+ int n ;
5524
+
5525
+ Data_Get_Struct (proc , struct BLOCK , data );
5526
+ if (data -> var == 0 ) return 0 ;
5527
+ switch (nd_type (data -> var )) {
5528
+ default :
5529
+ return INT2FIX (-1 );
5530
+ case NODE_MASGN :
5531
+ list = data -> var -> nd_head ;
5532
+ n = 0 ;
5533
+ while (list ) {
5534
+ n ++ ;
5535
+ list = list -> nd_next ;
5536
+ }
5537
+ if (data -> var -> nd_args ) return INT2FIX (- n );
5538
+ return INT2FIX (n );
5539
+ }
5540
+ }
5541
+
5497
5542
static VALUE
5498
5543
block_pass (self , node )
5499
5544
VALUE self ;
@@ -5645,6 +5690,38 @@ method_call(argc, argv, method)
5645
5690
return result ;
5646
5691
}
5647
5692
5693
+ static VALUE
5694
+ method_arity (method )
5695
+ VALUE method ;
5696
+ {
5697
+ struct METHOD * data ;
5698
+ NODE * body ;
5699
+ int n ;
5700
+
5701
+ Data_Get_Struct (method , struct METHOD , data );
5702
+
5703
+ body = data -> body ;
5704
+ switch (nd_type (body )) {
5705
+ case NODE_CFUNC :
5706
+ if (body -> nd_argc < 0 ) return INT2FIX (-1 );
5707
+ return INT2FIX (body -> nd_argc );
5708
+ case NODE_ZSUPER :
5709
+ return INT2FIX (-1 );
5710
+ case NODE_ATTRSET :
5711
+ return INT2FIX (1 );
5712
+ case NODE_IVAR :
5713
+ return INT2FIX (0 );
5714
+ default :
5715
+ body = body -> nd_next ; /* skip NODE_SCOPE */
5716
+ if (nd_type (body ) == NODE_BLOCK )
5717
+ body = body -> nd_head ;
5718
+ if (!body ) return INT2FIX (0 );
5719
+ n = body -> nd_cnt ;
5720
+ if (body -> nd_rest ) n = - n ;
5721
+ return INT2FIX (n );
5722
+ }
5723
+ }
5724
+
5648
5725
static VALUE
5649
5726
method_inspect (method )
5650
5727
VALUE method ;
@@ -5710,6 +5787,7 @@ Init_Proc()
5710
5787
rb_define_singleton_method (rb_cProc , "new" , proc_s_new , 0 );
5711
5788
5712
5789
rb_define_method (rb_cProc , "call" , proc_call , -2 );
5790
+ rb_define_method (rb_cProc , "arity" , proc_arity , 0 );
5713
5791
rb_define_method (rb_cProc , "[]" , proc_call , -2 );
5714
5792
rb_define_global_function ("proc" , rb_f_lambda , 0 );
5715
5793
rb_define_global_function ("lambda" , rb_f_lambda , 0 );
@@ -5722,6 +5800,7 @@ Init_Proc()
5722
5800
rb_undef_method (CLASS_OF (rb_cMethod ), "new" );
5723
5801
rb_define_method (rb_cMethod , "call" , method_call , -1 );
5724
5802
rb_define_method (rb_cMethod , "[]" , method_call , -1 );
5803
+ rb_define_method (rb_cMethod , "arity" , method_arity , 0 );
5725
5804
rb_define_method (rb_cMethod , "inspect" , method_inspect , 0 );
5726
5805
rb_define_method (rb_cMethod , "to_s" , method_inspect , 0 );
5727
5806
rb_define_method (rb_cMethod , "to_proc" , method_proc , 0 );
0 commit comments