diff options
author | Father Chrysostomos <sprout@cpan.org> | 2011-07-09 19:18:45 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2011-07-09 19:19:51 -0700 |
commit | 777d9014444bb88a98ccd6c09ebb520cdc4c0d8b (patch) | |
tree | add55b04929f0bc1462315c6aa167b4bfa2c641e /op.h | |
parent | fe57f3b7598666107c5e6e9c9ffd844da47ea527 (diff) | |
download | perl-777d9014444bb88a98ccd6c09ebb520cdc4c0d8b.tar.gz |
Propagate (non-)lvalue context through nested calls
Before this commit, this code would fail:
$foo = "foo";
sub foo :lvalue{ return index "foo","o" }
sub bar :lvalue { foo }
$x = bar;
(It would fail for ‘return $]’ as well. Whether it’s a PADTMP or a
read-only scalar makes no difference.)
foo would think it was being called in true lvalue context, because
the entersub op that called it (in bar) was marked that way, bar being
an lvalue sub as well.
The PUSHSUB macro in cop.h needed to be modified to account for
dynamic, or indetermine, context (i.e., indeterminable at compile
time). This happens when an entersub op is an argument to return or
the last statement in a subroutine. In those cases it has to propa-
gate the context from the caller.
So what we now do is this: Both lvalue and in-args flags are turned on
for an entersub op when op_lvalue is called with OP_LEAVESUBLV as the
type. Then PUSHSUB copies into the context stack only those flags
that are set both on the current entersub op and in the context stack
for the previous sub call.
Diffstat (limited to 'op.h')
-rw-r--r-- | op.h | 5 |
1 files changed, 5 insertions, 0 deletions
@@ -196,12 +196,17 @@ Deprecated. Use C<GIMME_V> instead. #define OPpDEREF_SV (32|64) /* Want ref to SV. */ /* Private for OP_RV2SV, OP_RV2AV, OP_RV2AV */ #define OPpDEREFed 4 /* prev op was OPpDEREF */ + /* OP_ENTERSUB only */ #define OPpENTERSUB_DB 16 /* Debug subroutine. */ #define OPpENTERSUB_HASTARG 32 /* Called from OP tree. */ #define OPpENTERSUB_NOMOD 64 /* Immune to op_lvalue() for :attrlist. */ #define OPpENTERSUB_INARGS 4 /* Lval used as arg to a sub. */ #define OPpENTERSUB_DEREF 1 /* Lval call that autovivifies. */ + /* Mask for OP_ENTERSUB flags, the absence of which must be propagated + in dynamic context */ +#define OPpENTERSUB_LVAL_MASK (OPpLVAL_INTRO|OPpENTERSUB_INARGS) + /* OP_RV2CV only */ #define OPpENTERSUB_AMPER 8 /* Used & form to call. */ #define OPpENTERSUB_NOPAREN 128 /* bare sub call (without parens) */ |