From: "Eregon (Benoit Daloze) via ruby-core" Date: 2023-12-08T19:23:35+00:00 Subject: [ruby-core:115664] [Ruby master Bug#19392] Endless method and parsing priorities Issue #19392 has been updated by Eregon (Benoit Daloze). > indirectly affecting the reputation of the language. I can share the feeling. The current parsing of endless methods feels like the old PHP parser, i.e., very buggy and counterintuitive (e.g. wouldn't accept an arbitrary exception inside `[]` for indexing IIRC). I think it is a reasonable expectation that if one has a single-line method (without `;`) they can transform it into an endless method. That's not true due to this issue and there are many confusing cases as shown in the description. Maybe we should reconsider how we parse/handle endless methods, i.e., maybe "desugar" them at lexer time like `def m(args) = ...\n` into `def m(args); ...; end\n`? It does feel hacky, but I think at least that expresses the desired and intuitive semantics clearly. ---------------------------------------- Bug #19392: Endless method and parsing priorities https://bugs.ruby-lang.org/issues/19392#change-105601 * Author: zverok (Victor Shepelev) * Status: Closed * Priority: Normal * Backport: 2.7: DONTNEED, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- **Initial description** [Discovered](https://twitter.com/lucianghinda/status/1617783952353406977) by Lucian Ghinda: ```ruby def test = puts("foo") and puts("bar") # prints "bar" immediately test # prints "foo" ``` It seems that it is a parser error, right?.. ```ruby RubyVM::AbstractSyntaxTree.parse('def test = puts("foo") and puts("bar")') # => # (SCOPE@1:0-1:38 # tbl: [] # args: nil # body: # (AND@1:0-1:38 # (DEFN@1:0-1:22 # mid: :test # body: # (SCOPE@1:0-1:22 # tbl: [] # args: # (ARGS@1:0-1:8 pre_num: 0 pre_init: nil opt: nil first_post: nil post_num: 0 post_init: nil rest: nil kw: nil kwrest: nil block: nil) # body: (FCALL@1:11-1:22 :puts (LIST@1:16-1:21 (STR@1:16-1:21 "foo") nil)))) # (FCALL@1:27-1:38 :puts (LIST@1:32-1:37 (STR@1:32-1:37 "bar") nil)))) ``` E.g. it is parsed as ```ruby (def test = puts("foo")) and (puts("bar")) ``` ...which is hardly intentional or have any practical use. The rightly parsed code in this case _can_ have practical use, like ```ruby def write(data) = File.write(@filename, data) == data.size or raise "Something went wrong" ``` **Additional cases of what seems to be the same problem** ```ruby def save = File.write(name, self.to_yaml) unless invalid? # Parsed as: (def save = File.write(name, self.to_yaml)) unless invalid? ``` ...which makes it very hard for the users to diagnose the real reason, see #19731 ```ruby def initialize(a, b) = @a, b = a, b # syntax error, unexpected ',', expecting end-of-input (SyntaxError) # def initialize(a, b) = @a, b = a, b # ^ # Again, parsed as (def initialize(a, b) = @a), b = a, b ``` While this one is at least diagnosed early, in pathological cases, it might lead to very subtle bugs: ```ruby private def start = @operation, @conversion = :print, :to_s ``` This code doesn't throw a syntax error, but its effect is very far from expected. Again, it is parsed as ```ruby private( (def start = @operation), @conversion = :print, :to_s ) ``` ...and ends up in: * defining a private method `start` * making private methods `:print` and `:to_s` -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/