Project

General

Profile

Actions

Bug #20467

closed

Prism creates a wrong ConstantReadNode for `Bar::Foo = 42`

Added by mame (Yusuke Endoh) 15 days ago. Updated 15 days ago.

Status:
Closed
Target version:
-
[ruby-core:117754]

Description

Currently, Prism creates the following AST for Bar::Foo = 42

irb(main):001> Prism.parse(%q(Bar::Foo = 42)).value
=>
@ ProgramNode (location: (1,0)-(1,13))
├── locals: []
└── statements:
    @ StatementsNode (location: (1,0)-(1,13))
    └── body: (length: 1)
        └── @ ConstantPathWriteNode (location: (1,0)-(1,13))
            ├── target:
            │   @ ConstantPathNode (location: (1,0)-(1,8))
            │   ├── parent:
            │   │   @ ConstantReadNode (location: (1,0)-(1,3))
            │   │   └── name: :Bar
            │   ├── child:
            │   │   @ ConstantReadNode (location: (1,5)-(1,8))
            │   │   └── name: :Foo
            │   └── delimiter_loc: (1,3)-(1,5) = "::"
            ├── operator_loc: (1,9)-(1,10) = "="
            └── value:
                @ IntegerNode (location: (1,11)-(1,13))
                ├── flags: decimal
                └── value: 42

Note that it includes ConstantReadNode(name: :Foo). I believe this is a bug because Bar::Foo = 42 does not read a constant Foo.

Also, Foo and Bar::Foo generates the followings.

irb(main):002> Prism.parse(%q(Foo)).value
=>
@ ProgramNode (location: (1,0)-(1,3))
├── locals: []
└── statements:
    @ StatementsNode (location: (1,0)-(1,3))
    └── body: (length: 1)
        └── @ ConstantReadNode (location: (1,0)-(1,3))
            └── name: :Foo
irb(main):003> Prism.parse(%q(Bar::Foo)).value
=>
@ ProgramNode (location: (1,0)-(1,8))
├── locals: []
└── statements:
    @ StatementsNode (location: (1,0)-(1,8))
    └── body: (length: 1)
        └── @ ConstantPathNode (location: (1,0)-(1,8))
            ├── parent:
            │   @ ConstantReadNode (location: (1,0)-(1,3))
            │   └── name: :Bar
            ├── child:
            │   @ ConstantReadNode (location: (1,5)-(1,8))
            │   └── name: :Foo
            └── delimiter_loc: (1,3)-(1,5) = "::"

Note that both have the same subtree of ConstantReadNode(name: :Foo). It is very confusing because Foo (non-scoped read of Foo) and Bar::Foo (scoped read of Foo) have very different meanings.

I think the following design would be desirable.

# Foo::Bar=42

ConstantPathWriteNode(
  base: ConstantReadNode(name: ConstantNameNode(:Foo)),
  name: ConstantNameNode(:Bar),
  value: 42
)

# Foo

ConstantReadNode(name: ConstantNameNode(:Foo))

# Foo::Bar

ConstantPathReadNode(
  base: ConstantReadNode(name: ConstantNameNode(:Foo)),
  name: ConstantNameNode(:Bar),
)

Updated by kddnewton (Kevin Newton) 15 days ago

I've changed it to be the following since https://github.com/ruby/ruby/pull/10716.

irb(main):001> Prism.parse(%q(Bar::Foo)).value
=> 
@ ProgramNode (location: (1,0)-(1,8))
├── locals: []
└── statements:
    @ StatementsNode (location: (1,0)-(1,8))
    └── body: (length: 1)
        └── @ ConstantPathNode (location: (1,0)-(1,8))
            ├── parent:
            │   @ ConstantReadNode (location: (1,0)-(1,3))
            │   └── name: :Bar
            ├── name: :Foo
            ├── delimiter_loc: (1,3)-(1,5) = "::"
            └── name_loc: (1,5)-(1,8) = "Foo"
Actions #2

Updated by kddnewton (Kevin Newton) 15 days ago

  • Status changed from Open to Closed
Actions

Also available in: Atom PDF

Like0
Like0Like0