-
Notifications
You must be signed in to change notification settings - Fork 602
Improvements to B::Deparse handling of signatured subs #23710
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
Conversation
|
I really appreciate the (best) effort put into this. I only use I don't think this kind of usage will trigger the behaviour described with regard to "ambient pragmas", though. |
|
Indeed so. In the usual |
bram-perl
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How are you planning to merge this?
- Branch as is?
- Squashing some commits and fast-forward merge (i.e. no merge commit)
- With a merge commit?
My personal view: there are definitely some commits that I would keep separate (i.e. the tidying up) .
| warning_bits => $warning_bits, | ||
| '%^H' => $hinthash, | ||
| ); | ||
| $deparse->ambient_pragmas_from_caller; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commit tests for ->ambient_pragmas_from_caller
This commit is slightly confusing; that it: when seeing the commit title I would've expected tests for the ambient_pragmas_from_caller function but what it is doing is using it inside the tests.
(If that is all that was intended then fine; I'm not asking for explicit tests for the ambient_pragmas_from_caller it's just what I expected to see in the commit)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yeah that was more of a note to myself to remind me. I'll just squash it in to the previous commit.
lib/B/Deparse.pm
Outdated
| foreach my $parami ( 0 .. $#param_padix ) { | ||
| my $argix = $parami; | ||
|
|
||
| $code .= "my $param_padname[$parami] = "; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commit Best-effort deparse of OP_MULTIPARAM when feature 'signatures' is disabled
Reading up a bit on signatures, in perlsub, it contains:
An optional parameter can be nameless just like a mandatory parameter. For example,
sub foo ($thing, $ = 1) { print $thing; }The parameter's default value will still be evaluated if the corresponding argument isn't supplied, even though the value won't be stored anywhere. This is in case evaluating it has important side effects. However, it will be evaluated in void context, ...
It's not yet clear to me how/if this is handled.
(But I'm not that familiar yet with this code and/or signatures so I might be overlooking something)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not yet clear to me how/if this is handled.
Ooh, good catch. I don't have a test for that yet, and in fact I'm not sure the code will even handle it. Looks like more work to do there.
lib/B/Deparse.pm
Outdated
| as possible. This is performed on a B<best-effort> basis. It is not | ||
| guaranteed to perfectly capture the semantics of the signature's behaviour, | ||
| only to offer a human-readable suggestion as to what it might do. | ||
| Furthermore. it is not guaranteed to be able to reproduce every possible |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commit Add docs to B::Deparse about signatures pure-perl fallback
Furthermore. --> Furthermore, ?
Yeah I'll squash some of them out and preserve the identity of others. I'll have a hack at that now. |
|
Rebased, squashed some commits, fixed a few more little docs issues, added code + tests for anonymous signature params. PTAL. |
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commit Unit tests for B::Deparse coderef2text on signatured sub with signatures feature enabled
Slightly wondering: should $deparse->ambient_pragmas_from_caller; be called after the test(s) to reset the state?
In the earlier block of code (line 96) it does happen explicitely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's probably no huge need to reset it after some tests, as any newly-added test block that gets added after this may want to set it back to something else for its own purposes anyway.
| else { | ||
| # anonymous params without defaulting expressions can be entirely ignored | ||
| $param_padix[$parami] or next; | ||
|
|
||
| $stmt .= "\$_[$argix]"; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commit Best-effort deparse of OP_MULTIPARAM when feature 'signatures' is disabled
While the code works it was a bit confusing at first.
I would probably write this as:
if (my $defmode = $param_defmode[$parami]) {
...
}
elsif (not $param_padix[$parami]) {
# anonymous params without defaulting expressions can be entirely ignored
next;
}
else {
$stmt .= "\$_[$argix]";
}The check is also inconsistent with the earlier check. Earlier check (on line 1130):
if( length $param_padname[$parami] > 1 ) {while here it just checks for a true value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While the code works it was a bit confusing at first. I would probably write this as:
...
I wanted to structure it in two branches, for optional vs. mandatory params, and within each branch then have a condition for anonymous versions of those. It's two binary choices, not a threeway split.
The check is also inconsistent with the earlier check. Earlier check (on line 1130):
...
while here it just checks for a true value.
Ohyes, hmm. That's quite subtle.
Anonymous mandatory params don't even get allocate a pad slot, so their padname is undefined. Anonymous optional params need a pad slot to detect if it's been set or not, and therefore have a name that is simply '$'. So the conditions for detecting named vs. anonymous params are different depending if they're optional or mandatory.
I have explained further in some more comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While the code works it was a bit confusing at first. I would probably write this as:
...I wanted to structure it in two branches, for optional vs. mandatory params, and within each branch then have a condition for anonymous versions of those. It's two binary choices, not a threeway split.
The thing that bothers me most with:
else {
# Mandatory anonymous params can be entirely ignored. Their pad
# index will be zero.
$param_padix[$parami] or next;
$stmt .= "\$_[$argix]";
}
is that the comment is at the beginning of the block and it can easily be read as applying to the entire block but it only applies to the next line.
(I think my initial thought was something like: the comment says they can be ignored but it still does $stmt .= ... which felt conflicting)
Alternative (untested):
if (my $defmode = $param_defmode[$parami]) {
...
}
else {
if (not $param_padix[$parami]) {
# Mandatory anonymous params can be entirely ignored. Their pad
# index will be zero.
next;
}
$stmt .= "\$_[$argix]";
}or (untested):
if (my $defmode = $param_defmode[$parami]) {
...
}
else {
$param_padix[$parami] or next; # Mandatory anonymous params can be entirely ignored. Their pad
# index will be zero.
$stmt .= "\$_[$argix]";
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahyes, I see how the positioning of some of the comments is rather misleading. I've had a go at adjusting it somewhat more, see new push.
| foreach my $parami ( 0 .. $#param_padix ) { | ||
| my $argix = $parami; | ||
|
|
||
| my $stmt = "my $param_padname[$parami] = "; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commit Best-effort deparse of OP_MULTIPARAM when feature 'signatures' is disabled
Can $param_padname[$parami] be undef? (If so then it will trigger a warning)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the name is always at least '$'
lib/B/Deparse.pm
Outdated
|
|
||
| # anonymous params with defaults don't create or assign a variable but | ||
| # still evaluate the defaulting expression for side-effects | ||
| if( length $param_padname[$parami] > 1 ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commit Best-effort deparse of OP_MULTIPARAM when feature 'signatures' is disabled
nit-picking: style seems appears inconsistent?
Earlier if-blocks are all if (...) { while this is if( ... ) {
(if/when intentional then feel free to ignore)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahyes, fixed.
4868d81 to
94d4a7e
Compare
Add C<...> wrapping around the name of the module, also a few other places. Also add L<...> wrapping around names of other modules.
…res feature enabled
->ambient_pragmas_from_callermethod for simplicityOP_MULTIPARAMto prior pure-perl behavioursCurrently no perldelta, but I could be convinced to add one if considered significant. Do we normally include changes to bundled modules in perldelta?