Project

General

Profile

Bug #17015

Updated by nobu (Nobuyoshi Nakada) 2 months ago

## Summary 

 `RubyVM::AbstractSyntaxTree.parse("proc { |a| }")` and `RubyVM::AbstractSyntaxTree.parse("proc { |a,| }")` have the same result. 
 Since `proc { |a| }` and `proc { |a,| }` have different meanings, I think we need a way to distinguish them. 

 ```ruby 
 node1 = RubyVM::AbstractSyntaxTree.parse("proc { |a| }") 
 body1 = node1.children.last 
 pp body1 
 # => (ITER@1:0-1:12 (FCALL@1:0-1:4 :proc nil) 
 #         (SCOPE@1:5-1:12 
 #          tbl: [:a] 
 #          args: 
 #            (ARGS@1:8-1:9 
 #             pre_num: 1 
 #             pre_init: nil 
 #             opt: nil 
 #             first_post: nil 
 #             post_num: 0 
 #             post_init: nil 
 #             rest: nil 
 #             kw: nil 
 #             kwrest: nil 
 #             block: nil) 
 #          body: (BEGIN@1:10-1:10 nil))) 


 # returns the same result as proc { |a| } 
 node2 = RubyVM::AbstractSyntaxTree.parse("proc { |a,| }") 
 body2 = node2.children.last 
 pp body2 
 # => (ITER@1:0-1:13 (FCALL@1:0-1:4 :proc nil) 
 #         (SCOPE@1:5-1:13 
 #          tbl: [:a] 
 #          args: 
 #            (ARGS@1:8-1:10 
 #             pre_num: 1 
 #             pre_init: nil 
 #             opt: nil 
 #             first_post: nil 
 #             post_num: 0 
 #             post_init: nil 
 #             rest: nil 
 #             kw: nil 
 #             kwrest: nil 
 #             block: nil) 
 #          body: (BEGIN@1:11-1:11 nil))) 
 ``` 

 ## Proposal 

 In case of `proc { |a,| }`, `rest: :NODE_SPECIAL_EXCESSIVE_COMMA` is added. 

 ```ruby 
 # no change 
 node1 = RubyVM::AbstractSyntaxTree.parse("proc { |a| }") 
 body1 = node1.children.last 
 pp body1 
 # => (ITER@1:0-1:12 (FCALL@1:0-1:4 :proc nil) 
 #         (SCOPE@1:5-1:12 
 #          tbl: [:a] 
 #          args: 
 #            (ARGS@1:8-1:9 
 #             pre_num: 1 
 #             pre_init: nil 
 #             opt: nil 
 #             first_post: nil 
 #             post_num: 0 
 #             post_init: nil 
 #             rest: nil 
 #             kw: nil 
 #             kwrest: nil 
 #             block: nil) 
 #          body: (BEGIN@1:10-1:10 nil))) 


 # rest: :NODE_SPECIAL_EXCESSIVE_COMMA is added 
 node2 = RubyVM::AbstractSyntaxTree.parse("proc { |a,| }") 
 body2 = node2.children.last 
 pp body2 
 # => (ITER@1:0-1:13 (FCALL@1:0-1:4 :proc nil) 
 #         (SCOPE@1:5-1:13 
 #          tbl: [:a] 
 #          args: 
 #            (ARGS@1:8-1:10 
 #             pre_num: 1 
 #             pre_init: nil 
 #             opt: nil 
 #             first_post: nil 
 #             post_num: 0 
 #             post_init: nil 
 #             rest: :NODE_SPECIAL_EXCESSIVE_COMMA 
 #             kw: nil 
 #             kwrest: nil 
 #             block: nil) 
 #          body: (BEGIN@1:11-1:11 nil))) 
 ``` 

 This correspondence is similar to `:NODE_SPECIAL_NO_NAME_REST` for `MASGN`. 

 ```ruby 
 node = RubyVM::AbstractSyntaxTree.parse("*a = foo") 
 body = node.children.last 
 pp body 
 # => (MASGN@1:0-1:8 (VCALL@1:5-1:8 :foo) nil (LASGN@1:1-1:2 :a nil)) 

 # :NODE_SPECIAL_NO_NAME_REST is added if the variable name is not defined 
 node = RubyVM::AbstractSyntaxTree.parse("* = foo") 
 body = node.children.last 
 pp body 
 # => (MASGN@1:0-1:7 (VCALL@1:4-1:7 :foo) nil :NODE_SPECIAL_NO_NAME_REST) 
 ``` 

 ## NOTE 

 `NODE_SPECIAL_EXCESSIVE_COMMA` was implemented in [0872ea5](https://github.com/ruby/ruby/commit/0872ea53303499caf3584e40f2a5438e86eb4fed) and renamed in [f258137](https://github.com/ruby/ruby/commit/f258137083051a7fc2412c62e3fb239f93d1fdf8). で実装され、[f258137](https://github.com/ruby/ruby/commit/f258137083051a7fc2412c62e3fb239f93d1fdf8). 
 So backport to 2.6 can be difficult. 

 ## Versions 

 * `ruby 2.6.6p146 (2020-03-31 revision 67876) [x86_64-linux]` 
 * `ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]` 
 * `ruby 2.8.0dev (2020-07-05T16:15:47Z master efe851a0df) [x86_64-linux]` 

 ## Patch 

 * PR:https://github.com/ruby/ruby/pull/3298 

Back