Add a "repeated flag" to parameter nodes#2144
Conversation
It's possible to repeat parameters in method definitions like so: ```ruby def foo(_a, _a) end ``` The compiler needs to know to adjust the local table size to account for these duplicate names. We'll use the repeated parameter flag to account for the extra stack space required Co-Authored-By: Kevin Newton <kddnewton@gmail.com> Co-Authored-By: Jemma Issroff <jemmaissroff@gmail.com>
kddnewton
left a comment
There was a problem hiding this comment.
Two small optional things, otherwise looks good
| pm_node_flag_set(node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER); | ||
| break; | ||
| default: | ||
| fprintf(stderr, "unhandled type %d\n", PM_NODE_TYPE(node)); |
There was a problem hiding this comment.
We could potentially change this function to do an assertion at the top of the function on the type and then just set the flag. But I doubt this is a very common path so I'm fine with leaving it as is.
There was a problem hiding this comment.
I think using assert rather than the printf / abort is better. I'll change it.
| * parameter is unique or not. | ||
| */ | ||
| static void | ||
| static bool |
There was a problem hiding this comment.
Could you document the return type in the description of the function?
|
@kddnewton mind reviewing again? I think I addressed the feedback. |
|
I wonder what is the right approach here. class P
def m(*a) = p a
end
class C<P
def m(_,_,_)
_ = 4
super
end
end
C.new.m(1,2,3) # => [4, 2, 3]So the 1st Notably The JRuby parser defines multiple variables in that case: So I'm thinking it would be nice if Prism would really consider these Regarding naming, one trick is to use an invalid local variable name like I think the repeated flag in this PR is harder to process and error-prone, i.e., if anything uses the Prism AST and see two As a note, while the added flag on |
|
For comparison to the JRuby AST above, this is the current Prism AST for Looking at it it all seems too clear that there is a single |
|
It is funny because I was discussing this variable to someone this weekend and it appears '' as a user visible variable is the first '' encountered while parsing. So: def foo(,); p _; end; foo(1, 2); # "1" def foo(_, (a, _); p _; end; foo(1, [2,3]) # "3" For this second case either first That aside the semantics are only one /* '_' can be seen as a variable only by its first assignment as a local variable. For any additional
* '_' we create temporary variables in the case the scope has a zsuper in it. If so, then the zsuper
* call will slurp those temps up as it's parameters so it can properly set up the call.
*/
Variable argumentResult(RubySymbol name) {
// |a,| case
if (name == null) return temp();
boolean isUnderscore = name.getBytes().realSize() == 1 && name.getBytes().charAt(0) == '_';
if (isUnderscore && underscoreVariableSeen) {
return temp();
} else {
if (isUnderscore) underscoreVariableSeen = true;
return getNewLocalVariable(name, 0);
}
}In this new parsing world we just assign a temp and do not pollute the variable table (obviously JRuby using register based design makes this simple). The main point here though is there is no semantic reason why Marking the real
@kddnewton I think we should consider annotating the real @eregon I don't see value in adding these extra |
Wow that is nasty.
That's the part we disagree. They are semantics because they affect the behavior of Ruby and it is observable (an implementation detail OTOH would not be observable from Ruby code). I wish multiple |
|
AFAIK matz says that assignments to repeated For example: def foo(a, _a, _a); end
foo(0, 1, 2)The caller will push 3 items on the stack, but if we only look at the local table provided by prism, then we'll assume the stack size is only 2. This flag just helps CRuby do stack size book keeping, it's not a statement about actual behavior in the language. |
|
@eregon wrote:
I think some people use variable names that start with '_' to indicate that these are ignored. That would suggest that such variables are not accessible at all. This would solve the problem with duplication automatically. |
Right, it's very similar to the issue enebo and I are mentioning.
I think that's the part we could fix, we could have Prism list all the semantically-different variables in its local tables (by renaming duplicates as suggested above). I can see the renaming is not ideal (introducing variables with a different name than in the source) but I think it's the cleanest solution here. It is possible to workaround this issue with the new flag, but it's less convenient and I think every semantic usage of Prism will have to manually workaround this. |
|
In #2124 FWIW we have adopted the repeated flag in TruffleRuby, it's convenient. Not as good as if we didn't even have to think about it because it would already be separate variables, but simple enough in practice. |
It's possible to repeat parameters in method definitions like so:
The compiler needs to know to adjust the local table size to account for these duplicate names. We'll use the repeated parameter flag to account for the extra stack space required