Project

General

Profile

Actions

Bug #19877

closed

Non intuitive behavior of syntax only applied to literal value

Added by tompng (tomoya ishida) about 1 year ago. Updated 11 months ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 3.3.0dev (2023-09-08T23:08:32Z master b635a66e95) [x86_64-linux]
[ruby-core:114722]

Description

Non intuitive behavior of syntax only applied to literal value

Some ruby syntax is only applied to literal value.

def 1.foo; end # receiver is a literal, it is Syntax Error
/(?<a>)/ =~ s # receiver is regexp literal, it will assign to local variable
if cond1..cond2; end # range-like syntax appears in condition, it is flipflop

If it is wrapped with parenthesis, the behavior seems not intuitive for me, and YARP parses it differently.

def (1).foo; end # Syntax Error
def ((1;1)).foo; end # Syntax Error
def ((;1)).foo; end # Syntax OK
def ((1+1;1)).foo; end # Syntax OK
def ((%s();1)).foo; end # Syntax Error
def ((%w();1)).foo; end # Syntax OK
def ("#{42}").foo; end # Syntax Error
def (:"#{42}").foo; end # Syntax OK

(/(?<a>)/) =~ s # assigns to a
(;/(?<a>)/) =~ s # does not assigns
(%s();/(?<a>)/) =~ s # assigns to a
(%w();/(?<a>)/) =~ s # does not assigns
(1; (2; 3; (4; /(?<a>)/))) =~ s # assigns to a
(1+1; /(?<a>)/) =~ s # does not assign

if ((cond1..cond2)); end # flipflop
if (; cond1..cond2); end # range
if (1; cond1..cond2); end # flipflop
if (%s(); cond1..cond2); end # flipflop
if (%w(); cond1..cond2); end # range
if (1; (2; (3; 4; cond1..cond2))); end # flipflop
if (1+1; cond1..cond2); end # range

I expect YARP and parse.y parses same.
I expect all parenthesis-wrapped result same.
I think it is simple and intuitive if parenthesis-wrapped code always behaves different from non-wrapped code because there are more complex variation like this

def (class A; 1; end).foo; end
(break; /?<a>/) =~ s
class A; /?<a>/; end =~ s
Actions #1

Updated by nobu (Nobuyoshi Nakada) about 1 year ago

  • Status changed from Open to Closed

Applied in changeset git|e8896a31d48e5797df3878696dcb50aed85b87c2.


[Bug #19877] Literals cannot have singleton methods even in blocks

Updated by kddnewton (Kevin Newton) 11 months ago

We need an answer on this in order to properly understand what we need to support. In particular,

(1; /(?<foo>)/) =~ s

assigning to the local seems incorrect. It would mean the only way for a parser (prism or any other) to be correct would be to mirror CRuby dropping literal nodes from the tree. In the meantime I know @yui-knk (Kaneko Yuichiro) has been working on adding those nodes back in for the universal parser.

So either way, we need to know what is "correct" in this case.

Updated by kddnewton (Kevin Newton) 11 months ago

Thank you @nobu (Nobuyoshi Nakada) that fixes the regex, but we still need it for flip-flops:

https://github.com/ruby/prism/issues/1923

RubyVM::AbstractSyntaxTree.parse 'if (1; a..b); end'
# => 
(SCOPE@1:0-1:17
 tbl: []
 args: nil
 body: (IF@1:0-1:17 (FLIP2@1:7-1:11 (VCALL@1:7-1:8 :a) (VCALL@1:10-1:11 :b)) (BEGIN@1:13-1:13 nil) nil))

Updated by tompng (tomoya ishida) 11 months ago

I found a similar behavior for MATCH node (Prism::MatchLastLineNode)

RubyVM::AbstractSyntaxTree.parse 'if (1; //); end'
(none):1: warning: regex literal in condition
=> 
(SCOPE@1:0-1:15
 tbl: []
 args: nil
 body:
   (IF@1:0-1:15
      (BEGIN@1:3-1:10
         (BLOCK@1:4-1:9 (LIT@1:4-1:5 1) (MATCH@1:7-1:9 //)))
      (BEGIN@1:11-1:11 nil) nil))

Updated by mame (Yusuke Endoh) 11 months ago

In today's dev meeting, @matz (Yukihiro Matsumoto) said:

expr if (cond1..cond2)                # This should be a flip-flop
expr if (((cond1..cond2)))            # This should be a flip-flop
expr if begin cond1..cond2; end       # This should be a flip-flop
expr if (;;; cond1..cond2)            # Don't care. Either is ok
expr if (1; cond1..cond2)             # This should NOT be a flip-flop
expr if (method; cond1..cond2)        # This should NOT be a flip-flop

(111; /(?<a>)/) =~ s; # a should NOT be defined
(foo; /(?<a>)/) =~ s; # a should NOT be defined
(/(?<a>)/) =~ s       # a should NOT be defined
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0