-
Notifications
You must be signed in to change notification settings - Fork 140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ClassNodes and ModuleNodes now always have ConstantPathNode children #1304
Conversation
If a ClassNode has a simple path, like "Foo", it will be represented as a ConstantPathNode with a ConstantReadNode parent, and a nil child. This is so that all ClassNodes and ModuleNodes have consistent path nodes, and not path nodes which could be either ConstantReadNodes or ConstantPathNodes.
A constant path node with a nil parent is supposed to represent |
There is also an opportunity here to have something turn up red after this change since this PR was still green. |
I guess lex-100 did fail but it is unclear it caught ::Foo case from that assertion. |
I thought about this - that's why I made it a nil child (not parent) for the |
Sorry to ask this question here but since you are both looking at this code here. For the ConstantPath I should be looking to see if parent is Nil and not null here right? Operand getContainerFromCPath(Node node) {
if (node instanceof ConstantReadNode) {
return findContainerModule();
} else if (node instanceof ConstantPathNode) {
ConstantPathNode path = (ConstantPathNode) node;
if (path.parent == null) { // ::Foo
return getManager().getObjectClass();
} else {
return build(path.parent);
}
}
// FIXME: We may not need these based on whether there are more possible nodes.
throw notCompilable("Unsupported node in module path", node);
} I am mildly surprised I have not been tripped up by this but I am only loading like the first 100 files of JRuby booting up. |
What is the difference between |
I don't know either. I guess I am confused by this statement "nil parent is supposed to represent ::Foo". Is that just a null field? I was unclear if @kddnewton had meant an actual nil value as special value holder or just no value at all. |
I think he means no value at all here. |
@jemmaissroff thanks. I guess I found it strange I could execute so much Ruby and not handle ::Foo if it had been a special nil holding value. |
Sorry, here's the mapping today: Foo # ConstantReadNode("Foo")
::Foo # ConstantPathNode(nil, ConstantReadNode("Foo"))
Foo::Bar # ConstantPathNode(ConstantReadNode("Foo"), ConstantReadNode("Bar))
::Foo::Bar # ConstantPathNode(ConstantPathNode(nil, ConstantReadNode("Foo")), ConstantReadNode("Bar"))
foo::Bar # ConstantPathNode(CallNode("foo"), ConstantReadNode("Bar")) The Sorry I didn't understand before that you had changed the parent. To me that's kind of confusing, because now you can't compile it in the same way as other I understand that you're trying to simplify this for consistency's sake. Is there another solution we could come to? For me it is very confusing to have a non-null parent but a null child, but also because it allocates a lot memory for every class and module definition now. |
I think a ConstantPathNode with I think the logic to handle all 3 cases (Foo, Foo::Bar, ::Foo) can be extracted in a small helper method like here and here, where it doesn't matter much that there is 2 different node types. We could have a common trait/interface for ConstantPathNode & ConstantReadNode to have a slightly more precise type, but I'm not sure it would give us much here, besides making it clearer when reading that this field can only be one of those two. |
Actually I noticed the JRuby AST has that and uses it to define |
I think null as first value is not that confusing. I echo @kddnewton that universally using constantpath would significantly increase the memory of class/module definitions. |
What about having a required class name (ConstantReadNode) and optional class path (ConstantPathNode)? CRuby needs the class name isolated anyways. The class path could just have parents of the required class name. The only case I haven't figured out is Agreed, it is possible for each Ruby implementation using YARP to make helpers that do the same thing. Or YARP can expose those helpers (slightly better). But to me, either of these indicate a case where YARP's node structure is not reflecting what's helpful to consumers. |
Yes, agreed, I think that's fine, for
I like that idea. I think either a flag or a special node (like in #1143) to differentiate |
As you say we have to always do this split in processing anyways so I like that part of this. I don't really have strong feelings on how to differentiate As a special object then for modules/classes |
Also if these end up being fields for class/module node I think you can omit the ConstantReadNode and just use Location since we know the rhs of the cpath has to be a constant identifier already. |
By this you mean the RHS of a ConstantReadNode could use the constant pool, right? Pretty sure we agree we don't want to rely on location fields for compilation. |
@eregon yeah constant pool entry. |
Closing this. Discussed with Kevin, he implemented adding a name in #1325, and will implement another PR to add a new node type for the |
If a ClassNode has a simple path, like "Foo", it will be represented as a ConstantPathNode with a ConstantReadNode parent, and a nil child. This is so that all ClassNodes and ModuleNodes have consistent path nodes, and not path nodes which could be either ConstantReadNodes or ConstantPathNodes.
This PR simplifies how any consumer of YARP has to handle ClassNodes or ModuleNodes. Before this, the logic for splitting on path / read node had to be both in the ConstantPathNode and in the ClassNode / ModuleNode. This commit minimizes the places where this splitting is duplicated, and makes the compiler (or any consumer of YARP) slightly simpler.