Alt-Lexical-Var-ButSupportModernPerl
view release on metacpan or search on metacpan
if(p[0] != ':' || p[1] != ':') return NULL;
p += 2;
}
if(!(char_attr[(U8)*p] & CHAR_IDSTART)) return NULL;
for(q = p+1; q != end; q++) {
if(!(char_attr[(U8)*q] & CHAR_IDCONT)) return NULL;
}
key = sv_2mortal(newSV(KEYPREFIXLEN + 1 + (end-p)));
sv_setpvs(key, KEYPREFIX"?");
SvPVX(key)[KEYPREFIXLEN] = sigil;
sv_catpvn(key, p, end-p);
return key;
}
/*
* compiling code that uses lexical variables
*/
#define gv_mark_multi(name) THX_gv_mark_multi(aTHX_ name)
static void THX_gv_mark_multi(pTHX_ SV *name)
{
GV *gv;
#ifdef gv_fetchsv
gv = gv_fetchsv(name, GV_NOADD_NOINIT|GV_NOEXPAND|GV_NOTQUAL,
SVt_PVGV);
#else /* !gv_fetchsv */
gv = gv_fetchpv(SvPVX(name), 0, SVt_PVGV);
#endif /* !gv_fetchsv */
if(gv && SvTYPE(gv) == SVt_PVGV) GvMULTI_on(gv);
}
static SV *fake_sv, *fake_av, *fake_hv;
#define ck_rv2xv(o, sigil, nxck) THX_ck_rv2xv(aTHX_ o, sigil, nxck)
static OP *THX_ck_rv2xv(pTHX_ OP *o, char sigil, OP *(*nxck)(pTHX_ OP *o))
{
OP *c;
SV *ref, *key;
HE *he;
if((o->op_flags & OPf_KIDS) && (c = cUNOPx(o)->op_first) &&
c->op_type == OP_CONST &&
(c->op_private & (OPpCONST_ENTERED|OPpCONST_BARE)) &&
(ref = cSVOPx(c)->op_sv) && SvPOK(ref) &&
(key = name_key(sigil, ref))) {
if((he = hv_fetch_ent(GvHV(PL_hintgv), key, 0, 0))) {
SV *hintref, *referent, *fake_referent, *newref;
OP *newop;
U16 type, flags;
#if !PERL_VERSION_GE(5,11,2)
if(sigil == '&' && (c->op_private & OPpCONST_BARE))
croak("can't reference lexical subroutine "
"without & sigil on this perl");
#endif /* <5.11.2 */
if(sigil != 'P' || !PERL_VERSION_GE(5,8,0)) {
/*
* A bogus symbol lookup has already been
* done (by the tokeniser) based on the name
* we're using, to support the package-based
* interpretation that we're about to
* replace. This can cause bogus "used only
* once" warnings. The best we can do here
* is to flag the symbol as multiply-used to
* suppress that warning, though this is at
* the risk of muffling an accurate warning.
*/
gv_mark_multi(ref);
}
/*
* The base checker for rv2Xv checks that the
* item being pointed to by the constant ref is of
* an appropriate type. There are two problems with
* this check. Firstly, it rejects GVs as a scalar
* target, whereas they are in fact valid. (This
* is in RT as bug #69456 so may be fixed.) Second,
* and more serious, sometimes a reference is being
* constructed through the wrong op type. An array
* indexing expression "$foo[0]" gets constructed as
* an rv2sv op, because of the "$" sigil, and then
* gets munged later. We have to detect the real
* intended type through the pad entry, which the
* tokeniser has worked out in advance, and then
* work through the wrong op. So it's a bit cheeky
* for perl to complain about the wrong type here.
* We work around it by making the constant ref
* initially point to an innocuous item to pass the
* type check, then changing it to the real
* reference later.
*/
hintref = HeVAL(he);
if(!SvROK(hintref))
croak("non-reference hint for Lexical::Var");
referent = SvREFCNT_inc(SvRV(hintref));
type = o->op_type;
flags = o->op_flags | (((U16)o->op_private) << 8);
if(type == OP_RV2SV && sigil == 'P' &&
SvPVX(ref)[LEXPADPREFIXLEN] == '$' &&
SvREADONLY(referent)) {
op_free(o);
return gen_const_identity_op(referent);
}
switch(type) {
case OP_RV2SV: fake_referent = fake_sv; break;
case OP_RV2AV: fake_referent = fake_av; break;
case OP_RV2HV: fake_referent = fake_hv; break;
default: fake_referent = referent; break;
}
newref = newRV_noinc(fake_referent);
if(referent != fake_referent) {
SvREFCNT_inc(fake_referent);
SvREFCNT_inc(newref);
}
newop = newUNOP(type, flags,
newSVOP(OP_CONST, 0, newref));
if(referent != fake_referent) {
fake_referent = SvRV(newref);
SvREADONLY_off(newref);
SvRV_set(newref, referent);
SvREADONLY_on(newref);
SvREFCNT_dec(fake_referent);
SvREFCNT_dec(newref);
}
( run in 2.053 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )