Project

General

Profile

Misc #15723 ยป implicit-param.diff

jeremyevans0 (Jeremy Evans), 04/24/2019 05:42 AM

View differences:

bootstraptest/test_syntax.rb
532 532
assert_syntax_error "unterminated string meets end of file", '().."', '[ruby-dev:29732]'
533 533
assert_equal %q{[]}, %q{$&;[]}, '[ruby-dev:31068]'
534 534
assert_syntax_error "syntax error, unexpected *, expecting '}'", %q{{*0}}, '[ruby-dev:31072]'
535
assert_syntax_error "leading zero is not allowed as a numbered parameter", %q{@0..0}, '[ruby-dev:31095]'
535
assert_syntax_error "`@0' is not allowed as an instance variable name", %q{@0..0}, '[ruby-dev:31095]'
536 536
assert_syntax_error "identifier $00 is not valid to get", %q{$00..0}, '[ruby-dev:31100]'
537 537
assert_syntax_error "identifier $00 is not valid to set", %q{0..$00=1}
538 538
assert_equal %q{0}, %q{[*0];0}, '[ruby-dev:31102]'
ext/ripper/eventids2.c
51 51
    ID ripper_id_label_end;
52 52
    ID ripper_id_tlambda;
53 53
    ID ripper_id_tlambeg;
54
    ID ripper_id_tnumparam;
54
    ID ripper_id_timplicitparam;
55 55

  
56 56
    ID ripper_id_ignored_nl;
57 57
    ID ripper_id_comment;
......
114 114
    set_id2(label_end);
115 115
    set_id2(tlambda);
116 116
    set_id2(tlambeg);
117
    set_id2(tnumparam);
117
    set_id2(timplicitparam);
118 118

  
119 119
    set_id2(ignored_nl);
120 120
    set_id2(comment);
......
278 278
    {tLABEL_END,		O(label_end)},
279 279
    {tLAMBDA,			O(tlambda)},
280 280
    {tLAMBEG,			O(tlambeg)},
281
    {tNUMPARAM, 		O(tnumparam)},
281
    {tIMPLICITPARAM, 		O(timplicitparam)},
282 282

  
283 283
    /* ripper specific tokens */
284 284
    {tIGNORED_NL,		O(ignored_nl)},
parse.y
167 167
    struct local_vars *prev;
168 168
};
169 169

  
170
#define NUMPARAM_MAX 100 /* INT_MAX */
171

  
172 170
#define DVARS_INHERIT ((void*)1)
173 171
#define DVARS_TOPSCOPE NULL
174 172
#define DVARS_TERMINAL_P(tbl) ((tbl) == DVARS_INHERIT || (tbl) == DVARS_TOPSCOPE)
......
246 244
    rb_ast_t *ast;
247 245
    int node_id;
248 246

  
249
    int max_numparam;
250

  
251 247
    unsigned int command_start:1;
252 248
    unsigned int eofp: 1;
253 249
    unsigned int ruby__end__seen: 1;
......
265 261
# endif
266 262
    unsigned int error_p: 1;
267 263
    unsigned int cr_seen: 1;
264
    unsigned int has_explicit_params: 1;
265
    unsigned int has_implicit_param: 1;
268 266

  
269 267
#ifndef RIPPER
270 268
    /* Ruby core only */
......
423 421
static NODE *new_hash_pattern_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, const YYLTYPE *loc);
424 422

  
425 423
static NODE *new_kw_arg(struct parser_params *p, NODE *k, const YYLTYPE *loc);
426
static NODE *args_with_numbered(struct parser_params*,NODE*,int);
424
static NODE *args_with_implicit(struct parser_params*,NODE*);
427 425

  
428 426
static VALUE negate_lit(struct parser_params*, VALUE);
429 427
static NODE *ret_args(struct parser_params*,NODE*);
......
540 538
YYLTYPE *rb_parser_set_location_from_strterm_heredoc(struct parser_params *p, rb_strterm_heredoc_t *here, YYLTYPE *yylloc);
541 539
YYLTYPE *rb_parser_set_location_of_none(struct parser_params *p, YYLTYPE *yylloc);
542 540
YYLTYPE *rb_parser_set_location(struct parser_params *p, YYLTYPE *yylloc);
543
ID rb_parser_numparam_id(struct parser_params *p, int num);
541
ID rb_parser_implicit_param_id(struct parser_params *p);
544 542
RUBY_SYMBOL_EXPORT_END
545 543

  
546
#define numparam_id rb_parser_numparam_id
544
#define implicit_param_id rb_parser_implicit_param_id
547 545

  
548 546
static void parser_token_value_print(struct parser_params *p, enum yytokentype type, const YYSTYPE *valp);
549 547
static ID formal_argument(struct parser_params*, ID);
......
704 702
}
705 703

  
706 704
static inline VALUE
707
args_with_numbered(struct parser_params *p, VALUE args, int max_numparam)
705
args_with_implicit(struct parser_params *p, VALUE args)
708 706
{
709 707
    return args;
710 708
}
......
967 965
%token <id>   tCONSTANT      "constant"
968 966
%token <id>   tCVAR          "class variable"
969 967
%token <id>   tLABEL
970
%token <id>   tNUMPARAM      "numbered parameter"
968
%token <id>   tIMPLICITPARAM "implicit parameter"
971 969
%token <node> tINTEGER       "integer literal"
972 970
%token <node> tFLOAT         "float literal"
973 971
%token <node> tRATIONAL      "rational literal"
......
3284 3282
		    }
3285 3283
		| tOROP
3286 3284
		    {
3287
			p->max_numparam = -1;
3285
			p->has_explicit_params = 1;
3288 3286
		    /*%%%*/
3289 3287
			$$ = 0;
3290 3288
		    /*% %*/
......
3293 3291
		| '|' block_param opt_bv_decl '|'
3294 3292
		    {
3295 3293
			p->cur_arg = 0;
3296
			p->max_numparam = -1;
3294
			p->has_explicit_params = 1;
3297 3295
		    /*%%%*/
3298 3296
			$$ = $2;
3299 3297
		    /*% %*/
......
3339 3337
			$<num>$ = p->lex.lpar_beg;
3340 3338
			p->lex.lpar_beg = p->lex.paren_nest;
3341 3339
		    }
3342
		    {
3343
			$<num>$ = p->max_numparam;
3344
		    }
3345 3340
		  f_larglist
3346 3341
		    {
3347 3342
			CMDARG_PUSH(0);
3348 3343
		    }
3349 3344
		  lambda_body
3350 3345
		    {
3351
			int max_numparam = p->max_numparam;
3352 3346
			p->lex.lpar_beg = $<num>2;
3353
			p->max_numparam = $<num>3;
3354 3347
			CMDARG_POP();
3355
			$4 = args_with_numbered(p, $4, max_numparam);
3348
			$3 = args_with_implicit(p, $3);
3356 3349
		    /*%%%*/
3357 3350
                        {
3358
                            YYLTYPE loc = code_loc_gen(&@4, &@6);
3359
                            $$ = NEW_LAMBDA($4, $6, &loc);
3360
                            nd_set_line($$->nd_body, @6.end_pos.lineno);
3361
                            nd_set_line($$, @4.end_pos.lineno);
3351
                            YYLTYPE loc = code_loc_gen(&@3, &@5);
3352
                            $$ = NEW_LAMBDA($3, $5, &loc);
3353
                            nd_set_line($$->nd_body, @5.end_pos.lineno);
3354
                            nd_set_line($$, @3.end_pos.lineno);
3362 3355
                        }
3363 3356
		    /*% %*/
3364
		    /*% ripper: lambda!($4, $6) %*/
3357
		    /*% ripper: lambda!($3, $5) %*/
3365 3358
			dyna_pop(p, $<vars>1);
3366 3359
		    }
3367 3360
		;
......
3370 3363
		    {
3371 3364
		    /*%%%*/
3372 3365
			$$ = $2;
3373
			p->max_numparam = -1;
3366
			p->has_explicit_params = 1;
3374 3367
		    /*% %*/
3375 3368
		    /*% ripper: paren!($2) %*/
3376 3369
		    }
......
3378 3371
		    {
3379 3372
		    /*%%%*/
3380 3373
			if (!args_info_empty_p($1->nd_ainfo))
3381
			    p->max_numparam = -1;
3374
			    p->has_explicit_params = 1;
3382 3375
		    /*% %*/
3383 3376
			$$ = $1;
3384 3377
		    }
......
3537 3530

  
3538 3531
brace_body	: {$<vars>$ = dyna_push(p);}
3539 3532
		    {
3540
			$<num>$ = p->max_numparam;
3541
			p->max_numparam = 0;
3533
			p->has_explicit_params = 0;
3542 3534
		    }
3543 3535
		  opt_block_param compstmt
3544 3536
		    {
3545
			int max_numparam = p->max_numparam;
3546
			p->max_numparam = $<num>2;
3547
			$3 = args_with_numbered(p, $3, max_numparam);
3537
			$3 = args_with_implicit(p, $3);
3548 3538
		    /*%%%*/
3549 3539
			$$ = NEW_ITER($3, $4, &@$);
3550 3540
		    /*% %*/
......
3555 3545

  
3556 3546
do_body 	: {$<vars>$ = dyna_push(p);}
3557 3547
		    {
3558
			$<num>$ = p->max_numparam;
3559
			p->max_numparam = 0;
3548
			p->has_explicit_params = 0;
3560 3549
			CMDARG_PUSH(0);
3561 3550
		    }
3562 3551
		  opt_block_param bodystmt
3563 3552
		    {
3564
			int max_numparam = p->max_numparam;
3565
			p->max_numparam = $<num>2;
3566
			$3 = args_with_numbered(p, $3, max_numparam);
3553
			$3 = args_with_implicit(p, $3);
3567 3554
		    /*%%%*/
3568 3555
			$$ = NEW_ITER($3, $4, &@$);
3569 3556
		    /*% %*/
......
4449 4436
		    /*% %*/
4450 4437
		    /*% ripper: var_ref!($1) %*/
4451 4438
		    }
4452
		| tNUMPARAM
4453
		    {
4454
		    /*%%%*/
4455
			$$ = NEW_DVAR($1, &@1);
4456
		    /*% %*/
4457
		    /*% ripper: var_ref!($1) %*/
4458
		    }
4459 4439
		| backref
4460 4440
		;
4461 4441

  
......
4511 4491
		| tGVAR
4512 4492
		| tCONSTANT
4513 4493
		| tCVAR
4514
		| tNUMPARAM
4494
		| tIMPLICITPARAM
4515 4495
		;
4516 4496

  
4517 4497
keyword_variable: keyword_nil {$$ = KWD2EID(nil, $1);}
......
4735 4715
		| tIDENTIFIER
4736 4716
		    {
4737 4717
			formal_argument(p, get_id($1));
4738
			p->max_numparam = -1;
4718
			p->has_explicit_params = 1;
4739 4719
			$$ = $1;
4740 4720
		    }
4741 4721
		;
......
4800 4780
			ID id = get_id($1);
4801 4781
			arg_var(p, formal_argument(p, id));
4802 4782
			p->cur_arg = id;
4803
			p->max_numparam = -1;
4783
			p->has_explicit_params = 1;
4804 4784
			$$ = $1;
4805 4785
		    }
4806 4786
		;
......
6651 6631
	    if (++ptr >= p->lex.pend) return 0;
6652 6632
	    c = *ptr;
6653 6633
	}
6654
	else if (ISDIGIT(c)) {
6655
	    return tSTRING_DVAR;
6656
	}
6657 6634
	break;
6658 6635
      case '{':
6659 6636
	p->lex.pcur = ptr;
......
8272 8249
}
8273 8250

  
8274 8251
static bool
8275
parser_numbered_param(struct parser_params *p, unsigned long n)
8252
parser_implicit_param(struct parser_params *p)
8276 8253
{
8277 8254
    if (DVARS_TERMINAL_P(p->lvtbl->args) || DVARS_TERMINAL_P(p->lvtbl->args->prev)) {
8278
	compile_error(p, "numbered parameter outside block");
8255
	compile_error(p, "implicit parameter outside block");
8279 8256
	return false;
8280 8257
    }
8281
    if (p->max_numparam < 0) {
8258
    if (p->has_explicit_params) {
8282 8259
	compile_error(p, "ordinary parameter is defined");
8283 8260
	return false;
8284 8261
    }
8285
    set_yylval_name(numparam_id(p, (int)n));
8262
    p->has_implicit_param = 1;
8263
    set_yylval_name(implicit_param_id(p));
8286 8264
    SET_LEX_STATE(EXPR_ARG);
8287 8265
    return true;
8288 8266
}
......
8303 8281
	tokadd(p, '@');
8304 8282
	c = nextc(p);
8305 8283
    }
8306
    if (c == -1 || !parser_is_identchar(p)) {
8284
    if ((c == -1 || !parser_is_identchar(p)) && !ISDIGIT(c)) {
8307 8285
	pushback(p, c);
8308 8286
	RUBY_SET_YYLLOC(loc);
8309 8287
	if (result == tIVAR) {
8310
	    compile_error(p, "`@' without identifiers is not allowed as an instance variable name");
8288
	    if (parser_implicit_param(p)) {
8289
		return tIMPLICITPARAM;
8290
	    }
8311 8291
	}
8312 8292
	else {
8313 8293
	    compile_error(p, "`@@' without identifiers is not allowed as a class variable name");
......
8317 8297
	return result;
8318 8298
    }
8319 8299
    else if (ISDIGIT(c)) {
8300
	RUBY_SET_YYLLOC(loc);
8301
	pushback(p, c);
8320 8302
	if (result == tIVAR) {
8321
	    const char *ptr = p->lex.pcur - 1;
8322
	    size_t len = p->lex.pend - ptr;
8323
	    int overflow;
8324
	    unsigned long n = ruby_scan_digits(ptr, len, 10, &len, &overflow);
8325
	    p->lex.pcur = ptr + len;
8326
	    RUBY_SET_YYLLOC(loc);
8327
	    if (ptr[0] == '0') {
8328
		compile_error(p, "leading zero is not allowed as a numbered parameter");
8329
	    }
8330
	    else if (overflow || n > NUMPARAM_MAX) {
8331
		compile_error(p, "too large numbered parameter");
8332
	    }
8333
	    else if (parser_numbered_param(p, n)) {
8334
		return tNUMPARAM;
8335
	    }
8303
	    compile_error(p, "`@%c' is not allowed as an instance variable name", c);
8336 8304
	}
8337 8305
	else {
8338
	    RUBY_SET_YYLLOC(loc);
8339
	    pushback(p, c);
8340 8306
	    compile_error(p, "`@@%c' is not allowed as a class variable name", c);
8341 8307
	}
8342 8308
	parser_show_error_line(p, &loc);
......
10065 10031
	{
10066 10032
	    int idx = vtable_included(p->lvtbl->args, id);
10067 10033
	    if (idx) {
10068
		compile_error(p, "Can't assign to numbered parameter @%d", idx);
10034
		compile_error(p, "Can't assign to implicit parameter @");
10069 10035
		break;
10070 10036
	    }
10071 10037
	}
......
10979 10945
}
10980 10946

  
10981 10947
static NODE *
10982
args_with_numbered(struct parser_params *p, NODE *args, int max_numparam)
10948
args_with_implicit(struct parser_params *p, NODE *args)
10983 10949
{
10984
    if (max_numparam > 0) {
10950
    if (p->has_implicit_param) {
10985 10951
	if (!args) args = new_args_tail(p, 0, 0, 0, 0);
10986
	args->nd_ainfo->pre_args_num = max_numparam;
10987
	args->nd_ainfo->rest_arg = excessed_comma;
10952
	args->nd_ainfo->pre_args_num = 1;
10988 10953
    }
10989 10954
    return args;
10990 10955
}
10991 10956

  
10992 10957
ID
10993
rb_parser_numparam_id(struct parser_params *p, int idx)
10958
rb_parser_implicit_param_id(struct parser_params *p)
10994 10959
{
10995 10960
    struct vtable *args;
10996
    if (idx <= 0) return (ID)0;
10997
    if (p->max_numparam < idx) {
10998
	p->max_numparam = idx;
10999
    }
11000 10961
    args = p->lvtbl->args;
11001
    while (idx > args->pos) {
10962
    if (args->pos == 0) {
11002 10963
	vtable_add(args, internal_id(p));
11003 10964
    }
11004
    return args->tbl[idx-1];
10965
    return args->tbl[0];
11005 10966
}
11006 10967

  
11007 10968
static NODE*
test/ripper/test_parser_events.rb
58 58
    assert_equal '[assign(var_field(a),ref(a))]', parse('a=a')
59 59
    assert_equal '[ref(nil)]', parse('nil')
60 60
    assert_equal '[ref(true)]', parse('true')
61
    assert_include parse('proc{@1}'), '[ref(@1)]'
61
    assert_include parse('proc{@}'), '[ref(@)]'
62 62
  end
63 63

  
64 64
  def test_vcall
......
1478 1478
    assert_equal("unterminated regexp meets end of file", compile_error('/'))
1479 1479
  end
1480 1480

  
1481
  def test_invalid_numbered_parameter_name
1482
    assert_equal("leading zero is not allowed as a numbered parameter", compile_error('proc{@0}'))
1483
  end
1484

  
1485 1481
  def test_invalid_instance_variable_name
1486
    assert_equal("`@' without identifiers is not allowed as an instance variable name", compile_error('@%'))
1487
    assert_equal("`@' without identifiers is not allowed as an instance variable name", compile_error('@'))
1482
    assert_equal("`@1' is not allowed as an instance variable name", compile_error('@1'))
1483
    assert_equal("implicit parameter outside block", compile_error('@%'))
1484
    assert_equal("implicit parameter outside block", compile_error('@'))
1488 1485
  end
1489 1486

  
1490 1487
  def test_invalid_class_variable_name
test/ripper/test_scanner_events.rb
259 259
                 scan('embvar', '"#@ivar"')
260 260
    assert_equal ['#'],
261 261
                 scan('embvar', '"#@@cvar"')
262
    assert_equal ['#'],
263
                 scan('embvar', '"#@1"')
264 262
    assert_equal [],
265 263
                 scan('embvar', '"#lvar"')
266 264
    assert_equal [],
......
350 348
                 scan('ivar', 'm(lvar, @ivar, @@cvar, $gvar)')
351 349
  end
352 350

  
353
  def test_tnumparam
354
    assert_equal [],
355
                 scan('tnumparam', '')
356
    assert_equal ['@1'],
357
                 scan('tnumparam', 'proc {@1}')
351
  def test_timplicitparam
352
    assert_equal ['@'],
353
                 scan('timplicitparam', 'proc {@}')
358 354
  end
359 355

  
360 356
  def test_kw
......
751 747
    assert_equal [" E\n\n"],
752 748
                 scan('tstring_content', "<<""'E'\n E\n\n"),
753 749
                 bug10392
754
                 scan('tstring_content', "tap{<<""EOS}\n""there\n""heredoc\#@1xxx\nEOS")
750
                 scan('tstring_content', "tap{<<""EOS}\n""there\n""heredoc\#{@}xxx\nEOS")
755 751
  end
756 752

  
757 753
  def test_heredoc_end
test/ruby/test_parse.rb
378 378

  
379 379
  def assert_disallowed_variable(type, noname, invalid)
380 380
    noname.each do |name|
381
      assert_syntax_error("proc{a = #{name} }", "`#{noname[0]}' without identifiers is not allowed as #{type} variable name")
381
      assert_syntax_error("a = #{name}", "`#{noname[0]}' without identifiers is not allowed as #{type} variable name")
382 382
    end
383 383
    invalid.each do |name|
384
      assert_syntax_error("proc {a = #{name} }", "`#{name}' is not allowed as #{type} variable name")
384
      assert_syntax_error("a = #{name}", "`#{name}' is not allowed as #{type} variable name")
385 385
    end
386 386
  end
387 387

  
388 388
  def test_disallowed_instance_variable
389
    assert_disallowed_variable("an instance", %w[@ @.], %w[])
389
    assert_syntax_error("a = @", "implicit parameter outside block")
390
    assert_syntax_error("a = @.to_f", "implicit parameter outside block")
391
    assert_syntax_error("a = @1", "`@1' is not allowed as an instance variable name")
390 392
  end
391 393

  
392 394
  def test_disallowed_class_variable
......
720 722
  end
721 723

  
722 724
  def test_invalid_instance_variable
723
    pattern = /without identifiers is not allowed as an instance variable name/
724
    assert_raise_with_message(SyntaxError, pattern) { eval('@%') }
725
    assert_raise_with_message(SyntaxError, pattern) { eval('@') }
725
    assert_raise_with_message(SyntaxError, /implicit parameter outside block.*unterminated quoted string meets end of file/m) { eval('@%') }
726
    assert_raise_with_message(SyntaxError, /implicit parameter outside block/) { eval('@') }
726 727
  end
727 728

  
728 729
  def test_invalid_class_variable
test/ruby/test_syntax.rb
1291 1291
    assert_valid_syntax('obj::foo (1) {}')
1292 1292
  end
1293 1293

  
1294
  def test_numbered_parameter
1295
    assert_valid_syntax('proc {@1}')
1296
    assert_equal(3, eval('[1,2].then {@1+@2}'))
1297
    assert_equal("12", eval('[1,2].then {"#@1#@2"}'))
1298
    assert_equal(3, eval('->{@1+@2}.call(1,2)'))
1299
    assert_syntax_error('proc {|| @1}', /ordinary parameter is defined/)
1300
    assert_syntax_error('proc {|x| @1}', /ordinary parameter is defined/)
1301
    assert_syntax_error('->(){@1}', /ordinary parameter is defined/)
1302
    assert_syntax_error('->(x){@1}', /ordinary parameter is defined/)
1303
    assert_syntax_error('->x{@1}', /ordinary parameter is defined/)
1304
    assert_syntax_error('->x:@2{}', /ordinary parameter is defined/)
1305
    assert_syntax_error('->x=@1{}', /ordinary parameter is defined/)
1306
    assert_syntax_error('proc {@1 = nil}', /Can't assign to numbered parameter @1/)
1307
    assert_syntax_error('proc {@01}', /leading zero/)
1308
    assert_syntax_error('proc {@1_}', /unexpected/)
1309
    assert_syntax_error('proc {@9999999999999999}', /too large/)
1310
    assert_syntax_error('@1', /outside block/)
1294
  def test_implicit_parameter
1295
    assert_valid_syntax('proc {@}')
1296
    assert_equal(3, eval('[1,2].then {@[0]+@[1]}'))
1297
    assert_equal("12", eval('[1,2].then {"#{@[0]}#{@[1]}"}'))
1298
    assert_equal(3, eval('->{@[0]+@[1]}.call([1,2])'))
1299
    assert_syntax_error('proc {|| @}', /ordinary parameter is defined/)
1300
    assert_syntax_error('proc {|x| @}', /ordinary parameter is defined/)
1301
    assert_syntax_error('proc {|x=@|}', /ordinary parameter is defined/)
1302
    assert_syntax_error('->(){@}', /ordinary parameter is defined/)
1303
    assert_syntax_error('->(x){@}', /ordinary parameter is defined/)
1304
    assert_syntax_error('->x{@}', /ordinary parameter is defined/)
1305
    assert_syntax_error('->x:@{}', /ordinary parameter is defined/)
1306
    assert_syntax_error('->x=@{}', /ordinary parameter is defined/)
1307
    assert_syntax_error('proc {@ = nil}', /Can't assign to implicit parameter @/)
1308
    assert_syntax_error('proc {@01}', /not allowed as an instance variable name/)
1309
    assert_syntax_error('proc {@1_}', /not allowed as an instance variable name/)
1310
    assert_syntax_error('proc {@9999999999999999}', /not allowed as an instance variable name/)
1311
    assert_syntax_error('@', /outside block/)
1311 1312
  end
1312 1313

  
1313 1314
  private
1314
-