diff options
author | Father Chrysostomos <sprout@cpan.org> | 2013-06-02 00:54:09 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2013-06-02 11:54:55 -0700 |
commit | 9a5e6f3cd84e6eaf40dad034fb9d25cb3361accc (patch) | |
tree | f1d67840ba7992a9ccbdbbe75a7f32162ae0427b /embed.h | |
parent | 83a72a15a3e8908c9fea8334e083e9329d425feb (diff) | |
download | perl-9a5e6f3cd84e6eaf40dad034fb9d25cb3361accc.tar.gz |
[perl #116735] Honour lexical prototypes when no parens are used
As Peter Martini noted in ticket #116735, lexical subs produce dif-
ferent op trees for ‘foo 1’ and ‘foo(1)’. foo(1) produces an rv2cv
op with a padcv kid. The unparenthetical version produces just
a padcv op.
And the difference in op trees caused lexical sub calls to honour
prototypes only in the presence of parentheses, because rv2cv_op_cv
(which searches for the cv in order to check its prototype) was
expecting rv2cv+padcv.
Not realising there was a discrepancy between the two forms, and
noticing that foo() produces *two* newCVREF ops, in commit 279d09bf893
I made newCVREF return just a padcv op for lexical subs. At the time
I couldn’t figure out why there were two rv2cv ops, and punted on
researching it.
This is how it works for package subs:
When a sub call is compiled, if there are parentheses, an implicit '&'
is fed to the parser. The token that follows is a WORD token with a
constant op attached to it, containing the name of the subroutine.
When the parser sees '&', it calls newCVREF on the const op to create
an rv2cv op.
For sub calls without parentheses, the token passed to the parser is
already an rv2cv op.
The resulting op tree is the same either way.
For lexical subs, I had the lexer emitting an rv2cv op in both paths,
which was why we got the double rv2cv when newCVREF was returning an
rv2cv for lexical subs.
The real solution is to call newCVREF in the lexer only when there
are no parentheses, since in that case the lexer is not going to call
newCVREF itself. That avoids a redundant newCVREF call. Hence, we
can have newCVREF always return an rv2cv op.
The result is that ‘foo(1)’ and ‘foo 1’ produce identical op trees for
a lexical sub.
One more thing needed to change: The lexer was not looking at the
lexical prototype CV but simply the stub to be autovivified, so it
couldn’t see the parameter prototype attached to the CV (the stub
doesn’t have one).
The lexer needs to see the parameter prototype too, in order to deter-
mine precedence.
The logic for digging through pads to find the CV has been extracted
out of rv2cv_op_cv into a separate (non-API!) routine.
Diffstat (limited to 'embed.h')
-rw-r--r-- | embed.h | 1 |
1 files changed, 1 insertions, 0 deletions
@@ -1090,6 +1090,7 @@ #define dump_packsubs_perl(a,b) Perl_dump_packsubs_perl(aTHX_ a,b) #define dump_sub_perl(a,b) Perl_dump_sub_perl(aTHX_ a,b) #define finalize_optree(a) Perl_finalize_optree(aTHX_ a) +#define find_lexical_cv(a) Perl_find_lexical_cv(aTHX_ a) #define find_runcv_where(a,b,c) Perl_find_runcv_where(aTHX_ a,b,c) #define find_rundefsv2(a,b) Perl_find_rundefsv2(aTHX_ a,b) #define find_script(a,b,c,d) Perl_find_script(aTHX_ a,b,c,d) |