зеркало из https://github.com/github/ruby.git
Make pattern matching support **nil syntax
This commit is contained in:
Родитель
cda5745c1b
Коммит
94d6ec1d90
5
ast.c
5
ast.c
|
@ -652,10 +652,13 @@ node_children(rb_ast_t *ast, NODE *node)
|
||||||
}
|
}
|
||||||
case NODE_HSHPTN:
|
case NODE_HSHPTN:
|
||||||
{
|
{
|
||||||
|
VALUE kwrest = node->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD ? ID2SYM(rb_intern("NODE_SPECIAL_NO_REST_KEYWORD")) :
|
||||||
|
NEW_CHILD(ast, node->nd_pkwrestarg);
|
||||||
|
|
||||||
return rb_ary_new_from_args(3,
|
return rb_ary_new_from_args(3,
|
||||||
NEW_CHILD(ast, node->nd_pconst),
|
NEW_CHILD(ast, node->nd_pconst),
|
||||||
NEW_CHILD(ast, node->nd_pkwargs),
|
NEW_CHILD(ast, node->nd_pkwargs),
|
||||||
NEW_CHILD(ast, node->nd_pkwrestarg));
|
kwrest);
|
||||||
}
|
}
|
||||||
case NODE_ARGS_AUX:
|
case NODE_ARGS_AUX:
|
||||||
case NODE_LAST:
|
case NODE_LAST:
|
||||||
|
|
23
compile.c
23
compile.c
|
@ -5467,7 +5467,15 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
|
||||||
* end
|
* end
|
||||||
* end
|
* end
|
||||||
* if pattern.has_kw_rest_arg_node?
|
* if pattern.has_kw_rest_arg_node?
|
||||||
* pattern.kw_rest_arg_node.match?(d)
|
* if pattern.no_rest_keyword?
|
||||||
|
* unless d.empty?
|
||||||
|
* goto match_failed
|
||||||
|
* end
|
||||||
|
* else
|
||||||
|
* unless pattern.kw_rest_arg_node.match?(d)
|
||||||
|
* goto match_failed
|
||||||
|
* end
|
||||||
|
* end
|
||||||
* end
|
* end
|
||||||
* true
|
* true
|
||||||
* goto fin
|
* goto fin
|
||||||
|
@ -5563,9 +5571,16 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->nd_pkwrestarg) {
|
if (node->nd_pkwrestarg) {
|
||||||
ADD_INSN(ret, line, dup);
|
if (node->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD) {
|
||||||
iseq_compile_pattern_each(iseq, ret, node->nd_pkwrestarg, in_alt_pattern);
|
ADD_INSN(ret, line, dup);
|
||||||
ADD_INSNL(ret, line, branchunless, match_failed);
|
ADD_SEND(ret, line, idEmptyP, INT2FIX(0));
|
||||||
|
ADD_INSNL(ret, line, branchunless, match_failed);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ADD_INSN(ret, line, dup);
|
||||||
|
iseq_compile_pattern_each(iseq, ret, node->nd_pkwrestarg, in_alt_pattern);
|
||||||
|
ADD_INSNL(ret, line, branchunless, match_failed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ADD_INSN(ret, line, pop);
|
ADD_INSN(ret, line, pop);
|
||||||
|
|
7
node.c
7
node.c
|
@ -1065,7 +1065,12 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
|
||||||
F_NODE(nd_pconst, "constant");
|
F_NODE(nd_pconst, "constant");
|
||||||
F_NODE(nd_pkwargs, "keyword arguments");
|
F_NODE(nd_pkwargs, "keyword arguments");
|
||||||
LAST_NODE;
|
LAST_NODE;
|
||||||
F_NODE(nd_pkwrestarg, "keyword rest argument");
|
if (node->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD) {
|
||||||
|
F_MSG(nd_pkwrestarg, "keyword rest argument", "NODE_SPECIAL_NO_REST_KEYWORD (**nil)");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
F_NODE(nd_pkwrestarg, "keyword rest argument");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case NODE_ARGS_AUX:
|
case NODE_ARGS_AUX:
|
||||||
|
|
1
node.h
1
node.h
|
@ -385,6 +385,7 @@ typedef struct RNode {
|
||||||
#define NODE_SPECIAL_NO_NAME_REST ((NODE *)-1)
|
#define NODE_SPECIAL_NO_NAME_REST ((NODE *)-1)
|
||||||
#define NODE_NAMED_REST_P(node) ((node) != NODE_SPECIAL_NO_NAME_REST)
|
#define NODE_NAMED_REST_P(node) ((node) != NODE_SPECIAL_NO_NAME_REST)
|
||||||
#define NODE_SPECIAL_EXCESSIVE_COMMA ((ID)1)
|
#define NODE_SPECIAL_EXCESSIVE_COMMA ((ID)1)
|
||||||
|
#define NODE_SPECIAL_NO_REST_KEYWORD ((NODE *)-1)
|
||||||
|
|
||||||
VALUE rb_node_case_when_optimizable_literal(const NODE *const node);
|
VALUE rb_node_case_when_optimizable_literal(const NODE *const node);
|
||||||
|
|
||||||
|
|
21
parse.y
21
parse.y
|
@ -1033,7 +1033,7 @@ static void token_info_warn(struct parser_params *p, const char *token, token_in
|
||||||
%type <id> keyword_variable user_variable sym operation operation2 operation3
|
%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> 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> f_kwrest f_label f_arg_asgn call_op call_op2 reswords relop dot_or_colon
|
||||||
%type <id> p_kwrest
|
%type <id> p_kwrest p_kwnorest
|
||||||
%type <id> f_no_kwarg
|
%type <id> f_no_kwarg
|
||||||
%token END_OF_INPUT 0 "end-of-input"
|
%token END_OF_INPUT 0 "end-of-input"
|
||||||
%token <id> '.'
|
%token <id> '.'
|
||||||
|
@ -3950,6 +3950,14 @@ p_kwargs : p_kwarg ',' p_kwrest
|
||||||
{
|
{
|
||||||
$$ = new_hash_pattern_tail(p, new_hash(p, Qnone, &@$), $1, &@$);
|
$$ = new_hash_pattern_tail(p, new_hash(p, Qnone, &@$), $1, &@$);
|
||||||
}
|
}
|
||||||
|
| p_kwarg ',' p_kwnorest
|
||||||
|
{
|
||||||
|
$$ = new_hash_pattern_tail(p, new_unique_key_hash(p, $1, &@$), ID2SYM(idNil), &@$);
|
||||||
|
}
|
||||||
|
| p_kwnorest
|
||||||
|
{
|
||||||
|
$$ = new_hash_pattern_tail(p, new_hash(p, Qnone, &@$), ID2SYM(idNil), &@$);
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
p_kwarg : p_kw
|
p_kwarg : p_kw
|
||||||
|
@ -4026,6 +4034,12 @@ p_kwrest : kwrest_mark tIDENTIFIER
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
p_kwnorest : kwrest_mark keyword_nil
|
||||||
|
{
|
||||||
|
$$ = 0;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
p_value : p_primitive
|
p_value : p_primitive
|
||||||
| p_primitive tDOT2 p_primitive
|
| p_primitive tDOT2 p_primitive
|
||||||
{
|
{
|
||||||
|
@ -11253,7 +11267,10 @@ new_hash_pattern_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, co
|
||||||
int saved_line = p->ruby_sourceline;
|
int saved_line = p->ruby_sourceline;
|
||||||
NODE *node, *kw_rest_arg_node;
|
NODE *node, *kw_rest_arg_node;
|
||||||
|
|
||||||
if (kw_rest_arg) {
|
if (kw_rest_arg == ID2SYM(idNil)) {
|
||||||
|
kw_rest_arg_node = NODE_SPECIAL_NO_REST_KEYWORD;
|
||||||
|
}
|
||||||
|
else if (kw_rest_arg) {
|
||||||
kw_rest_arg_node = assignable(p, kw_rest_arg, 0, loc);
|
kw_rest_arg_node = assignable(p, kw_rest_arg, 0, loc);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -846,6 +846,44 @@ END
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert_block do
|
||||||
|
[{}, C.new({})].all? do |i|
|
||||||
|
case i
|
||||||
|
in **nil
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_block do
|
||||||
|
[{a: 0}, C.new({a: 0})].all? do |i|
|
||||||
|
case i
|
||||||
|
in **nil
|
||||||
|
else
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_block do
|
||||||
|
[{a: 0}, C.new({a: 0})].all? do |i|
|
||||||
|
case i
|
||||||
|
in a:, **nil
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_block do
|
||||||
|
[{a: 0, b: 1}, C.new({a: 0, b: 1})].all? do |i|
|
||||||
|
case i
|
||||||
|
in a:, **nil
|
||||||
|
else
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
assert_block do
|
assert_block do
|
||||||
case C.new({a: 0})
|
case C.new({a: 0})
|
||||||
in C(a: 0)
|
in C(a: 0)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче