whitequark / parser

A Ruby parser.
Other
1.59k stars 199 forks source link

multi-level mlhs treated as single level #825

Open hmdne opened 3 years ago

hmdne commented 3 years ago

This bug was found in opal/opal#1703

$ ruby-parse -e '((x, y)) = [[1,2]]'
(masgn
  (mlhs             # <- shouldn't this be (mlhs (mlhs ... ))?
    (lvasgn :x)
    (lvasgn :y))
  (array
    (array
      (int 1)
      (int 2))))
$ ruby-parse -e '(x, y) = [[1,2]]'
(masgn
  (mlhs            # <- the same as above, can't differentiate
    (lvasgn :x)
    (lvasgn :y))
  (array
    (array
      (int 1)
      (int 2))))
$ ruby-parse -V
ruby-parse based on parser version 3.0.2.0
$

This also happens in all legacy modes. This works correctly for ((x,y),) and for ((x,y),z)

iliabylich commented 3 years ago

Thanks for reporting, yes, looks like a bug

3.0.0 :004 > (x, y) = [[1,2]]; [x, y]
 => [[1, 2], nil]
3.0.0 :005 > ((x, y)) = [[1,2]]; [x, y]
 => [1, 2]
hmdne commented 3 years ago

There's another issue that I encountered and may be a similar problem:

$ ruby-parse -e 'proc { |a| }'
(block
  (send nil :proc)
  (args
    (procarg0
      (arg :a))) nil)
$ ruby-parse -e 'proc { |(a)| }'
(block
  (send nil :proc)
  (args
    (procarg0              # <- It's the same! But why?
      (arg :a))) nil)
$ ruby-parse --legacy -e 'proc { |a| }'
(block
  (send nil :proc)
  (args                      # <- In this example Opal (running in legacy mode) checks source for "," to check if procarg0
    (arg :a)) nil)
$ ruby-parse --legacy -e 'proc { |(a)| }'
(block
  (send nil :proc)
  (args                      # <- But this is denoted clearly!
    (mlhs
      (arg :a))) nil)
$

Yet:

$ ruby -e 'p proc { |i| i }.([1,2,3])'
[1, 2, 3]
$ ruby -e 'p proc { |(i)| i }.([1,2,3])'
1
$
hmdne commented 3 years ago

Ref: #550