Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
ruby
提交
e8f53692
R
ruby
项目概览
张重言
/
ruby
通知
3
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
ruby
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
e8f53692
编写于
4月 01, 2020
作者:
N
Nobuyoshi Nakada
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Endless method definition [Feature #16746]
上级
878e21c6
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
132 addition
and
38 deletion
+132
-38
NEWS.md
NEWS.md
+7
-0
parse.y
parse.y
+105
-38
spec/ruby/language/method_spec.rb
spec/ruby/language/method_spec.rb
+13
-0
test/ruby/test_syntax.rb
test/ruby/test_syntax.rb
+7
-0
未找到文件。
NEWS.md
浏览文件 @
e8f53692
...
...
@@ -45,6 +45,13 @@ sufficient information, see the ChangeLog file or Redmine
fib(10) => x
```
*
Endless method definition is added. [EXPERIMENTAL]
[[Feature #16746]]
```ruby
def square(x) = x * x
```
## Command line options
## Core classes updates
...
...
parse.y
浏览文件 @
e8f53692
...
...
@@ -59,6 +59,8 @@ struct lex_context {
#include "ruby/util.h"
#include "symbol.h"
#define AREF(ary, i) RARRAY_AREF(ary, i)
#ifndef WARN_PAST_SCOPE
# define WARN_PAST_SCOPE 0
#endif
...
...
@@ -906,8 +908,27 @@ static VALUE heredoc_dedent(struct parser_params*,VALUE);
#define ID2VAL(id) (id)
#define TOKEN2VAL(t) ID2VAL(t)
#define KWD2EID(t, v) keyword_##t
static NODE *
set_defun_body(struct parser_params *p, NODE *n, NODE *args, NODE *body, const YYLTYPE *loc)
{
body = remove_begin(body);
reduce_nodes(p, &body);
n->nd_defn = NEW_SCOPE(args, body, loc);
n->nd_loc = *loc;
nd_set_line(n->nd_defn, loc->end_pos.lineno);
set_line_body(body, loc->beg_pos.lineno);
return n;
}
#endif /* RIPPER */
static void
restore_defun(struct parser_params *p, NODE *name)
{
p->cur_arg = name->nd_vid;
p->ctxt.in_def = name->nd_state & 1;
}
#ifndef RIPPER
# define Qnone 0
# define Qnull 0
...
...
@@ -1082,7 +1103,7 @@ static int looking_at_eol_p(struct parser_params *p);
%type <node> singleton strings string string1 xstring regexp
%type <node> string_contents xstring_contents regexp_contents string_content
%type <node> words symbols symbol_list qwords qsymbols word_list qword_list qsym_list word
%type <node> literal numeric simple_numeric ssym dsym symbol cpath
%type <node> literal numeric simple_numeric ssym dsym symbol cpath
def_name defn_head defs_head
%type <node> top_compstmt top_stmts top_stmt begin_block rassign
%type <node> bodystmt compstmt stmts stmt_or_begin stmt expr arg primary command command_call method_call
%type <node> expr_value expr_value_do arg_value primary_value fcall rel_expr
...
...
@@ -1093,7 +1114,7 @@ static int looking_at_eol_p(struct parser_params *p);
%type <node> command_rhs arg_rhs
%type <node> command_asgn mrhs mrhs_arg superclass block_call block_command
%type <node> f_block_optarg f_block_opt
%type <node> f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs f_rest_marg
%type <node> f_arglist f_arg
list_opt f_arg
s f_arg f_arg_item f_optarg f_marg f_marg_list f_margs f_rest_marg
%type <node> assoc_list assocs assoc undef_list backref string_dvar for_var
%type <node> block_param opt_block_param block_param_def f_opt
%type <node> f_kwarg f_kw f_block_kwarg f_block_kw
...
...
@@ -1635,6 +1656,46 @@ expr : command_call
| arg %prec tLBRACE_ARG
;
def_name : fname
{
ID fname = get_id($1);
ID cur_arg = p->cur_arg;
int in_def = p->ctxt.in_def;
numparam_name(p, fname);
local_push(p, 0);
p->cur_arg = 0;
p->ctxt.in_def = 1;
$<node>$ = NEW_NODE(NODE_SELF, /*vid*/cur_arg, /*mid*/fname, /*state*/in_def, &@$);
/*%%%*/
/*%
$$ = NEW_RIPPER(fname, get_value($1), $$, &NULL_LOC);
%*/
}
;
defn_head : k_def def_name
{
$$ = $2;
/*%%%*/
$$ = NEW_NODE(NODE_DEFN, 0, $$->nd_mid, $$, &@$);
/*% %*/
}
;
defs_head : k_def singleton dot_or_colon {SET_LEX_STATE(EXPR_FNAME);} def_name
{
SET_LEX_STATE(EXPR_ENDFN|EXPR_LABEL); /* force for args */
$$ = $5;
/*%%%*/
$$ = NEW_NODE(NODE_DEFS, $2, $$->nd_mid, $$, &@$);
/*%
VALUE ary = rb_ary_new_from_args(3, $2, $3, get_value($$));
add_mark_object(p, ary);
$<node>$->nd_rval = ary;
%*/
}
;
expr_value : expr
{
value_expr($1);
...
...
@@ -2392,6 +2453,26 @@ arg : lhs '=' arg_rhs
/*% %*/
/*% ripper: ifop!($1, $3, $6) %*/
}
| defn_head f_arglist_opt '=' arg
{
restore_defun(p, $<node>1->nd_defn);
/*%%%*/
$$ = set_defun_body(p, $1, $2, $4, &@$);
/*% %*/
/*% ripper: def!(get_value($1), $2, $4) %*/
local_pop(p);
}
| defs_head f_arglist_opt '=' arg
{
restore_defun(p, $<node>1->nd_defn);
/*%%%*/
$$ = set_defun_body(p, $1, $2, $4, &@$);
/*%
$1 = get_value($1);
%*/
/*% ripper: defs!(AREF($1, 0), AREF($1, 1), AREF($1, 2), $2, $4) %*/
local_pop(p);
}
| primary
{
$$ = $1;
...
...
@@ -3018,56 +3099,31 @@ primary : literal
local_pop(p);
p->ctxt.in_class = $<ctxt>1.in_class;
}
| k_def fname
{
numparam_name(p, get_id($2));
local_push(p, 0);
$<id>$ = p->cur_arg;
p->cur_arg = 0;
$<ctxt>1 = p->ctxt;
p->ctxt.in_def = 1;
}
| defn_head
f_arglist
bodystmt
k_end
{
restore_defun(p, $<node>1->nd_defn);
/*%%%*/
NODE *body = remove_begin($5);
reduce_nodes(p, &body);
$$ = NEW_DEFN($2, $4, body, &@$);
nd_set_line($$->nd_defn, @6.end_pos.lineno);
set_line_body(body, @1.beg_pos.lineno);
$$ = set_defun_body(p, $1, $2, $3, &@$);
/*% %*/
/*% ripper: def!(
$2, $4, $5
) %*/
/*% ripper: def!(
get_value($1), $2, $3
) %*/
local_pop(p);
p->ctxt.in_def = $<ctxt>1.in_def;
p->cur_arg = $<id>3;
}
| k_def singleton dot_or_colon {SET_LEX_STATE(EXPR_FNAME);} fname
{
numparam_name(p, get_id($5));
$<ctxt>1 = p->ctxt;
p->ctxt.in_def = 1;
SET_LEX_STATE(EXPR_ENDFN|EXPR_LABEL); /* force for args */
local_push(p, 0);
$<id>$ = p->cur_arg;
p->cur_arg = 0;
}
| defs_head
f_arglist
bodystmt
k_end
{
restore_defun(p, $<node>1->nd_defn);
/*%%%*/
NODE *body = remove_begin($8);
reduce_nodes(p, &body);
$$ = NEW_DEFS($2, $5, $7, body, &@$);
nd_set_line($$->nd_defn, @9.end_pos.lineno);
set_line_body(body, @1.beg_pos.lineno);
/*% %*/
/*% ripper: defs!($2, $3, $5, $7, $8) %*/
$$ = set_defun_body(p, $1, $2, $3, &@$);
/*%
$1 = get_value($1);
%*/
/*% ripper: defs!(AREF($1, 0), AREF($1, 1), AREF($1, 2), $2, $3) %*/
local_pop(p);
p->ctxt.in_def = $<ctxt>1.in_def;
p->cur_arg = $<id>6;
}
| keyword_break
{
...
...
@@ -4840,6 +4896,17 @@ superclass : '<'
}
;
f_arglist_opt : f_arglist
| /* none */
{
/*%%%*/
$$ = new_args_tail(p, Qnone, Qnone, Qnone, &@0);
$$ = new_args(p, Qnone, Qnone, Qnone, Qnone, $$, &@0);
/*% %*/
/*% ripper: Qnil %*/
}
;
f_arglist : '(' f_args rparen
{
/*%%%*/
...
...
spec/ruby/language/method_spec.rb
浏览文件 @
e8f53692
...
...
@@ -1766,3 +1766,16 @@ def [](*)
end
end
end
ruby_version_is
'2.8'
do
describe
"An endless method definition"
do
evaluate
<<-
ruby
do
def m(a) = a
ruby
a
=
b
=
m
1
a
.
should
==
1
b
.
should
==
1
end
end
end
test/ruby/test_syntax.rb
浏览文件 @
e8f53692
...
...
@@ -1414,6 +1414,13 @@ def test_method_call_location
assert_equal
(
line
,
e
.
backtrace_locations
[
0
].
lineno
)
end
def
test_methoddef_endless
assert_valid_syntax
(
'private def foo = 42'
)
assert_valid_syntax
(
'private def inc(x) = x + 1'
)
assert_valid_syntax
(
'private def obj.foo = 42'
)
assert_valid_syntax
(
'private def obj.inc(x) = x + 1'
)
end
def
test_methoddef_in_cond
assert_valid_syntax
(
'while def foo; tap do end; end; break; end'
)
assert_valid_syntax
(
'while def foo a = tap do end; end; break; end'
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录