[#104004] [Ruby master Feature#17883] Load bundler/setup earlier to make `bundle exec ruby -r` respect Gemfile — mame@...
Issue #17883 has been reported by mame (Yusuke Endoh).
21 messages
2021/05/24
[ruby-core:103890] [Ruby master Bug#17869] `Ripper.sexp`'s S-expression when using endless method definition
From:
koic.ito@...
Date:
2021-05-19 16:32:48 UTC
List:
ruby-core #103890
Issue #17869 has been reported by koic (Koichi ITO).
----------------------------------------
Bug #17869: `Ripper.sexp`'s S-expression when using endless method definition
https://bugs.ruby-lang.org/issues/17869
* Author: koic (Koichi ITO)
* Status: Open
* Priority: Normal
* ruby -v: ruby 3.1.0dev (2021-05-17T10:51:51Z master ee611341c9) [x86_64-darwin19]
* Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN
----------------------------------------
## Summary
The result of `Ripper.sexp` differs between normal method definition and endless method definition.
### Normal method definition
```ruby
% ruby -rripper -e "pp Ripper.sexp('def m(a) foo end')"
[:program,
[[:def,
[:@ident, "m", [1, 4]],
[:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil, nil, nil, nil]],
[:bodystmt, [[:vcall, [:@ident, "foo", [1, 9]]]], nil, nil, nil]]]]
```
### Endless method definition
```ruby
% ruby -rripper -e "pp Ripper.sexp('def m(a) = foo')"
[:program,
[[:def,
[:@ident, "m", [1, 4]],
[:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil, nil, nil, nil]],
[:vcall, [:@ident, "foo", [1, 11]]]]]]
```
Endless method definition does not have `bodystmt`. Is it an expected behavior that these results differ?
This is reproduced in Ruby 3.1.0-dev and Ruby 3.0.1.
## Additional Information
Their results are the same when using `RubyVM::AbstractSyntaxTree.parse` and `ruby --dump=p`.
### `RubyVM::AbstractSyntaxTree.parse`
The following returns the same AST.
```console
% ruby -e "pp RubyVM::AbstractSyntaxTree.parse('def m(a) foo end')"
(SCOPE@1:0-1:16
tbl: []
args: nil
body:
(DEFN@1:0-1:16
mid: :m
body:
(SCOPE@1:0-1:16
tbl: [:a]
args:
(ARGS@1:6-1:7
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: (VCALL@1:9-1:12 :foo))))
% ruby -e "pp RubyVM::AbstractSyntaxTree.parse('def m(a) = foo')"
(SCOPE@1:0-1:14
tbl: []
args: nil
body:
(DEFN@1:0-1:14
mid: :m
body:
(SCOPE@1:0-1:14
tbl: [:a]
args:
(ARGS@1:6-1:7
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: (VCALL@1:11-1:14 :foo))))
```
### `ruby --dump=p`
The following returns the same parsetree.
```console
% ruby --dump=p -e 'def m(a) foo end'
###########################################################
## Do NOT use this node dump for any purpose other than #
## debug and research. ompatibility is not guaranteed. ##
###########################################################
# @ NODE_SCOPE (line: 1, location: (1,0)-(1,16))
# +- nd_tbl: (empty)
# +- nd_args:
# | (null node)
# +- nd_body:
# @ NODE_DEFN (line: 1, location: (1,0)-(1,16))*
# +- nd_mid: :m
# +- nd_defn:
# @ NODE_SCOPE (line: 1, location: (1,0)-(1,16))
# +- nd_tbl: :a
# +- nd_args:
# | @ NODE_ARGS (line: 1, location: (1,6)-(1,7))
# | +- nd_ainfo->pre_args_num: 1
# | +- nd_ainfo->pre_init:
# | | (null node)
# | +- nd_ainfo->post_args_num: 0
# | +- nd_ainfo->post_init:
# | | (null node)
# | +- nd_ainfo->first_post_arg: (null)
# | +- nd_ainfo->rest_arg: (null)
# | +- nd_ainfo->block_arg: (null)
# | +- nd_ainfo->opt_args:
# | | (null node)
# | +- nd_ainfo->kw_args:
# | | (null node)
# | +- nd_ainfo->kw_rest_arg:
# | (null node)
# +- nd_body:
# @ NODE_VCALL (line: 1, location: (1,9)-(1,12))*
# +- nd_mid: :foo
% ruby --dump=p -e 'def m(a) = foo'
###########################################################
## Do NOT use this node dump for any purpose other than ##
## debug and research. Compatibility is not guaranteed. ##
###########################################################
# @ NODE_SCOPE (line: 1, location: (1,0)-(1,14))
# +- nd_tbl: (empty)
# +- nd_args:
# | (null node)
# +- nd_body:
# @ NODE_DEFN (line: 1, location: (1,0)-(1,14))*
# +- nd_mid: :m
# +- nd_defn:
# @ NODE_SCOPE (line: 1, location: (1,0)-(1,14))
# +- nd_tbl: :a
# +- nd_args:
# | @ NODE_ARGS (line: 1, location: (1,6)-(1,7))
# | +- nd_ainfo->pre_args_num: 1
# | +- nd_ainfo->pre_init:
# | | (null node)
# | +- nd_ainfo->post_args_num: 0
# | +- nd_ainfo->post_init:
# | | (null node)
# | +- nd_ainfo->first_post_arg: (null)
# | +- nd_ainfo->rest_arg: (null)
# | +- nd_ainfo->block_arg: (null)
# | +- nd_ainfo->opt_args:
# | | (null node)
# | +- nd_ainfo->kw_args:
# | | (null node)
# | +- nd_ainfo->kw_rest_arg:
# | (null node)
# +- nd_body:
# @ NODE_VCALL (line: 1, location: (1,11)-(1,14))
# +- nd_mid: :foo
```
I noticed the issue because a 3rd party parser builds the same AST.
```ruby
% ruby-parse -e 'def m(a) = foo'
warning: parser/current is loading parser/ruby31, which recognizes
warning: 3.1.0-dev-compliant syntax, but you are running 3.1.0.
warning: please see https://github.com/whitequark/parser#compatibility-with-ruby-mri.
(def :m
(args
(arg :a))
(send nil :foo))
% ruby-parse -e 'def m(a) foo end'
warning: parser/current is loading parser/ruby31, which recognizes
warning: 3.1.0-dev-compliant syntax, but you are running 3.1.0.
warning: please see https://github.com/whitequark/parser#compatibility-with-ruby-mri.
(def :m
(args
(arg :a))
(send nil :foo))
```
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>