зеркало из https://github.com/github/ruby.git
[Bug #19175] p_rest should be `assignable'
It should also check for duplicate names.
This commit is contained in:
Родитель
2f916812a9
Коммит
6c0925ba70
59
parse.y
59
parse.y
|
@ -761,9 +761,9 @@ static bool args_info_empty_p(struct rb_args_info *args);
|
|||
static NODE *new_args(struct parser_params*,NODE*,NODE*,ID,NODE*,NODE*,const YYLTYPE*);
|
||||
static NODE *new_args_tail(struct parser_params*,NODE*,ID,ID,const YYLTYPE*);
|
||||
static NODE *new_array_pattern(struct parser_params *p, NODE *constant, NODE *pre_arg, NODE *aryptn, const YYLTYPE *loc);
|
||||
static NODE *new_array_pattern_tail(struct parser_params *p, NODE *pre_args, int has_rest, ID rest_arg, NODE *post_args, const YYLTYPE *loc);
|
||||
static NODE *new_array_pattern_tail(struct parser_params *p, NODE *pre_args, int has_rest, NODE *rest_arg, NODE *post_args, const YYLTYPE *loc);
|
||||
static NODE *new_find_pattern(struct parser_params *p, NODE *constant, NODE *fndptn, const YYLTYPE *loc);
|
||||
static NODE *new_find_pattern_tail(struct parser_params *p, ID pre_rest_arg, NODE *args, ID post_rest_arg, const YYLTYPE *loc);
|
||||
static NODE *new_find_pattern_tail(struct parser_params *p, NODE *pre_rest_arg, NODE *args, NODE *post_rest_arg, const YYLTYPE *loc);
|
||||
static NODE *new_hash_pattern(struct parser_params *p, NODE *constant, NODE *hshptn, const YYLTYPE *loc);
|
||||
static NODE *new_hash_pattern_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, const YYLTYPE *loc);
|
||||
|
||||
|
@ -1116,12 +1116,6 @@ new_array_pattern_tail(struct parser_params *p, VALUE pre_args, VALUE has_rest,
|
|||
{
|
||||
NODE *t;
|
||||
|
||||
if (has_rest) {
|
||||
rest_arg = dispatch1(var_field, rest_arg ? rest_arg : Qnil);
|
||||
}
|
||||
else {
|
||||
rest_arg = Qnil;
|
||||
}
|
||||
|
||||
t = rb_node_newnode(NODE_ARYPTN, pre_args, rest_arg, post_args, &NULL_LOC);
|
||||
add_mark_object(p, pre_args);
|
||||
|
@ -1144,9 +1138,6 @@ new_find_pattern_tail(struct parser_params *p, VALUE pre_rest_arg, VALUE args, V
|
|||
{
|
||||
NODE *t;
|
||||
|
||||
pre_rest_arg = dispatch1(var_field, pre_rest_arg ? pre_rest_arg : Qnil);
|
||||
post_rest_arg = dispatch1(var_field, post_rest_arg ? post_rest_arg : Qnil);
|
||||
|
||||
t = rb_node_newnode(NODE_FNDPTN, pre_rest_arg, args, post_rest_arg, &NULL_LOC);
|
||||
add_mark_object(p, pre_rest_arg);
|
||||
add_mark_object(p, args);
|
||||
|
@ -1485,13 +1476,13 @@ static int looking_at_eol_p(struct parser_params *p);
|
|||
%type <node> mlhs mlhs_head mlhs_basic mlhs_item mlhs_node mlhs_post mlhs_inner
|
||||
%type <node> p_case_body p_cases p_top_expr p_top_expr_body
|
||||
%type <node> p_expr p_as p_alt p_expr_basic p_find
|
||||
%type <node> p_args p_args_head p_args_tail p_args_post p_arg
|
||||
%type <node> p_args p_args_head p_args_tail p_args_post p_arg p_rest
|
||||
%type <node> p_value p_primitive p_variable p_var_ref p_expr_ref p_const
|
||||
%type <node> p_kwargs p_kwarg p_kw
|
||||
%type <id> keyword_variable user_variable sym operation operation2 operation3
|
||||
%type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg f_bad_arg
|
||||
%type <id> f_kwrest f_label f_arg_asgn call_op call_op2 reswords relop dot_or_colon
|
||||
%type <id> p_rest p_kwrest p_kwnorest p_any_kwrest p_kw_label
|
||||
%type <id> p_kwrest p_kwnorest p_any_kwrest p_kw_label
|
||||
%type <id> f_no_kwarg f_any_kwrest args_forward excessed_comma nonlocal_var
|
||||
%type <ctxt> lex_ctxt /* keep <ctxt> in ripper */
|
||||
%token END_OF_INPUT 0 "end-of-input"
|
||||
|
@ -4439,7 +4430,7 @@ p_top_expr : p_top_expr_body
|
|||
p_top_expr_body : p_expr
|
||||
| p_expr ','
|
||||
{
|
||||
$$ = new_array_pattern_tail(p, Qnone, 1, 0, Qnone, &@$);
|
||||
$$ = new_array_pattern_tail(p, Qnone, 1, Qnone, Qnone, &@$);
|
||||
$$ = new_array_pattern(p, Qnone, get_value($1), $$, &@$);
|
||||
}
|
||||
| p_expr ',' p_args
|
||||
|
@ -4523,7 +4514,7 @@ p_expr_basic : p_value
|
|||
}
|
||||
| p_const '(' rparen
|
||||
{
|
||||
$$ = new_array_pattern_tail(p, Qnone, 0, 0, Qnone, &@$);
|
||||
$$ = new_array_pattern_tail(p, Qnone, 0, Qnone, Qnone, &@$);
|
||||
$$ = new_array_pattern(p, $1, Qnone, $$, &@$);
|
||||
}
|
||||
| p_const p_lbracket p_args rbracket
|
||||
|
@ -4555,7 +4546,7 @@ p_expr_basic : p_value
|
|||
}
|
||||
| p_const '[' rbracket
|
||||
{
|
||||
$$ = new_array_pattern_tail(p, Qnone, 0, 0, Qnone, &@$);
|
||||
$$ = new_array_pattern_tail(p, Qnone, 0, Qnone, Qnone, &@$);
|
||||
$$ = new_array_pattern(p, $1, Qnone, $$, &@$);
|
||||
}
|
||||
| tLBRACK p_args rbracket
|
||||
|
@ -4568,7 +4559,7 @@ p_expr_basic : p_value
|
|||
}
|
||||
| tLBRACK rbracket
|
||||
{
|
||||
$$ = new_array_pattern_tail(p, Qnone, 0, 0, Qnone, &@$);
|
||||
$$ = new_array_pattern_tail(p, Qnone, 0, Qnone, Qnone, &@$);
|
||||
$$ = new_array_pattern(p, Qnone, Qnone, $$, &@$);
|
||||
}
|
||||
| tLBRACE
|
||||
|
@ -4599,22 +4590,22 @@ p_args : p_expr
|
|||
{
|
||||
/*%%%*/
|
||||
NODE *pre_args = NEW_LIST($1, &@$);
|
||||
$$ = new_array_pattern_tail(p, pre_args, 0, 0, Qnone, &@$);
|
||||
$$ = new_array_pattern_tail(p, pre_args, 0, Qnone, Qnone, &@$);
|
||||
/*%
|
||||
$$ = new_array_pattern_tail(p, rb_ary_new_from_args(1, get_value($1)), 0, 0, Qnone, &@$);
|
||||
$$ = new_array_pattern_tail(p, rb_ary_new_from_args(1, get_value($1)), 0, Qnone, Qnone, &@$);
|
||||
%*/
|
||||
}
|
||||
| p_args_head
|
||||
{
|
||||
$$ = new_array_pattern_tail(p, $1, 1, 0, Qnone, &@$);
|
||||
$$ = new_array_pattern_tail(p, $1, 1, Qnone, Qnone, &@$);
|
||||
}
|
||||
| p_args_head p_arg
|
||||
{
|
||||
/*%%%*/
|
||||
$$ = new_array_pattern_tail(p, list_concat($1, $2), 0, 0, Qnone, &@$);
|
||||
$$ = new_array_pattern_tail(p, list_concat($1, $2), 0, Qnone, Qnone, &@$);
|
||||
/*%
|
||||
VALUE pre_args = rb_ary_concat($1, get_value($2));
|
||||
$$ = new_array_pattern_tail(p, pre_args, 0, 0, Qnone, &@$);
|
||||
$$ = new_array_pattern_tail(p, pre_args, 0, Qnone, Qnone, &@$);
|
||||
%*/
|
||||
}
|
||||
| p_args_head p_rest
|
||||
|
@ -4660,11 +4651,18 @@ p_find : p_rest ',' p_args_post ',' p_rest
|
|||
|
||||
p_rest : tSTAR tIDENTIFIER
|
||||
{
|
||||
$$ = $2;
|
||||
/*%%%*/
|
||||
error_duplicate_pattern_variable(p, $2, &@2);
|
||||
$$ = assignable(p, $2, 0, &@$);
|
||||
/*% %*/
|
||||
/*% ripper: assignable(p, var_field(p, $2)) %*/
|
||||
}
|
||||
| tSTAR
|
||||
{
|
||||
/*%%%*/
|
||||
$$ = 0;
|
||||
/*% %*/
|
||||
/*% ripper: Qnil %*/
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -12687,7 +12685,7 @@ new_array_pattern(struct parser_params *p, NODE *constant, NODE *pre_arg, NODE *
|
|||
}
|
||||
|
||||
static NODE*
|
||||
new_array_pattern_tail(struct parser_params *p, NODE *pre_args, int has_rest, ID rest_arg, NODE *post_args, const YYLTYPE *loc)
|
||||
new_array_pattern_tail(struct parser_params *p, NODE *pre_args, int has_rest, NODE *rest_arg, NODE *post_args, const YYLTYPE *loc)
|
||||
{
|
||||
int saved_line = p->ruby_sourceline;
|
||||
NODE *node;
|
||||
|
@ -12700,12 +12698,7 @@ new_array_pattern_tail(struct parser_params *p, NODE *pre_args, int has_rest, ID
|
|||
apinfo->pre_args = pre_args;
|
||||
|
||||
if (has_rest) {
|
||||
if (rest_arg) {
|
||||
apinfo->rest_arg = assignable(p, rest_arg, 0, loc);
|
||||
}
|
||||
else {
|
||||
apinfo->rest_arg = NODE_SPECIAL_NO_NAME_REST;
|
||||
}
|
||||
apinfo->rest_arg = rest_arg ? rest_arg : NODE_SPECIAL_NO_NAME_REST;
|
||||
}
|
||||
else {
|
||||
apinfo->rest_arg = NULL;
|
||||
|
@ -12726,7 +12719,7 @@ new_find_pattern(struct parser_params *p, NODE *constant, NODE *fndptn, const YY
|
|||
}
|
||||
|
||||
static NODE*
|
||||
new_find_pattern_tail(struct parser_params *p, ID pre_rest_arg, NODE *args, ID post_rest_arg, const YYLTYPE *loc)
|
||||
new_find_pattern_tail(struct parser_params *p, NODE *pre_rest_arg, NODE *args, NODE *post_rest_arg, const YYLTYPE *loc)
|
||||
{
|
||||
int saved_line = p->ruby_sourceline;
|
||||
NODE *node;
|
||||
|
@ -12736,9 +12729,9 @@ new_find_pattern_tail(struct parser_params *p, ID pre_rest_arg, NODE *args, ID p
|
|||
node = NEW_NODE(NODE_FNDPTN, 0, tmpbuf, fpinfo, loc);
|
||||
RB_OBJ_WRITTEN(p->ast, Qnil, tmpbuf);
|
||||
|
||||
fpinfo->pre_rest_arg = pre_rest_arg ? assignable(p, pre_rest_arg, 0, loc) : NODE_SPECIAL_NO_NAME_REST;
|
||||
fpinfo->pre_rest_arg = pre_rest_arg ? pre_rest_arg : NODE_SPECIAL_NO_NAME_REST;
|
||||
fpinfo->args = args;
|
||||
fpinfo->post_rest_arg = post_rest_arg ? assignable(p, post_rest_arg, 0, loc) : NODE_SPECIAL_NO_NAME_REST;
|
||||
fpinfo->post_rest_arg = post_rest_arg ? post_rest_arg : NODE_SPECIAL_NO_NAME_REST;
|
||||
|
||||
p->ruby_sourceline = saved_line;
|
||||
return node;
|
||||
|
|
|
@ -175,7 +175,7 @@ eot
|
|||
[:aryptn,
|
||||
nil,
|
||||
[[:var_field, [:@ident, "a", [1, 11]]]],
|
||||
[:var_field, nil],
|
||||
nil,
|
||||
nil],
|
||||
[[:void_stmt]],
|
||||
nil]],
|
||||
|
@ -229,7 +229,7 @@ eot
|
|||
[__LINE__, %q{ case 0; in *; end }] =>
|
||||
[:case,
|
||||
[:@int, "0", [1, 5]],
|
||||
[:in, [:aryptn, nil, nil, [:var_field, nil], nil], [[:void_stmt]], nil]],
|
||||
[:in, [:aryptn, nil, nil, nil, nil], [[:void_stmt]], nil]],
|
||||
|
||||
[__LINE__, %q{ case 0; in *,a; end }] =>
|
||||
[:case,
|
||||
|
@ -238,7 +238,7 @@ eot
|
|||
[:aryptn,
|
||||
nil,
|
||||
nil,
|
||||
[:var_field, nil],
|
||||
nil,
|
||||
[[:var_field, [:@ident, "a", [1, 13]]]]],
|
||||
[[:void_stmt]],
|
||||
nil]],
|
||||
|
@ -407,6 +407,14 @@ eot
|
|||
[[:void_stmt]],
|
||||
nil]],
|
||||
|
||||
[__LINE__, %q{ case 0; in [a,]; end }] =>
|
||||
[:case,
|
||||
[:@int, "0", [1, 5]],
|
||||
[:in,
|
||||
[:aryptn, nil, [[:var_field, [:@ident, "a", [1, 12]]]], nil, nil],
|
||||
[[:void_stmt]],
|
||||
nil]],
|
||||
|
||||
[__LINE__, %q{ case 0; in []; end }] =>
|
||||
[:case,
|
||||
[:@int, "0", [1, 5]],
|
||||
|
@ -418,9 +426,9 @@ eot
|
|||
[:in,
|
||||
[:fndptn,
|
||||
nil,
|
||||
[:var_field, nil],
|
||||
nil,
|
||||
[[:var_field, [:@ident, "a", [1, 9]]]],
|
||||
[:var_field, nil]],
|
||||
nil],
|
||||
nil,
|
||||
nil]],
|
||||
|
||||
|
@ -486,6 +494,14 @@ eot
|
|||
[:begin, [:binary, [:@int, "0", [1, 13]], :+, [:@int, "0", [1, 15]]]],
|
||||
[[:void_stmt]],
|
||||
nil]],
|
||||
|
||||
[__LINE__, %q{ case 0; in [*a]; a; end } ] =>
|
||||
[:case,
|
||||
[:@int, "0", [1, 5]],
|
||||
[:in,
|
||||
[:aryptn, nil, nil, [:var_field, [:@ident, "a", [1, 13]]], nil],
|
||||
[[:var_ref, [:@ident, "a", [1, 17]]]],
|
||||
nil]],
|
||||
}
|
||||
pattern_matching_data.each do |(i, src), expected|
|
||||
define_method(:"test_pattern_matching_#{i}") do
|
||||
|
|
|
@ -800,6 +800,10 @@ END
|
|||
true
|
||||
end
|
||||
end
|
||||
|
||||
assert_syntax_error(%q{
|
||||
0 => [a, *a]
|
||||
}, /duplicated variable name/)
|
||||
end
|
||||
|
||||
def test_find_pattern
|
||||
|
@ -868,6 +872,10 @@ END
|
|||
false
|
||||
end
|
||||
end
|
||||
|
||||
assert_syntax_error(%q{
|
||||
0 => [*a, a, b, *b]
|
||||
}, /duplicated variable name/)
|
||||
end
|
||||
|
||||
def test_hash_pattern
|
||||
|
|
Загрузка…
Ссылка в новой задаче