Alt-Lexical-Var-ButSupportModernPerl
view release on metacpan or search on metacpan
# if PERL_VERSION_GE(5,9,5)
# define COP_SEQ_RANGE_LOW(sv) ((XPVNV*)SvANY(sv))->xnv_u.xpad_cop_seq.xlow
# define COP_SEQ_RANGE_HIGH(sv) ((XPVNV*)SvANY(sv))->xnv_u.xpad_cop_seq.xhigh
# else /* <5.9.5 */
# define COP_SEQ_RANGE_LOW(sv) ((U32)SvNVX(sv))
# define COP_SEQ_RANGE_HIGH(sv) ((U32)SvIVX(sv))
# endif /* <5.9.5 */
#endif /* !COP_SEQ_RANGE_LOW */
#ifndef COP_SEQ_RANGE_LOW_set
# ifdef newPADNAMEpvn
# define COP_SEQ_RANGE_LOW_set(sv,val) \
do { (sv)->xpadn_low = (val); } while(0)
# define COP_SEQ_RANGE_HIGH_set(sv,val) \
do { (sv)->xpadn_high = (val); } while(0)
# elif PERL_VERSION_GE(5,9,5)
# define COP_SEQ_RANGE_LOW_set(sv,val) \
do { ((XPVNV*)SvANY(sv))->xnv_u.xpad_cop_seq.xlow = val; } while(0)
# define COP_SEQ_RANGE_HIGH_set(sv,val) \
do { ((XPVNV*)SvANY(sv))->xnv_u.xpad_cop_seq.xhigh = val; } while(0)
# else /* <5.9.5 */
# define COP_SEQ_RANGE_LOW_set(sv,val) SvNV_set(sv, val)
# define COP_SEQ_RANGE_HIGH_set(sv,val) SvIV_set(sv, val)
# endif /* <5.9.5 */
#endif /* !COP_SEQ_RANGE_LOW_set */
#ifndef SvRV_set
# define SvRV_set(SV, VAL) (SvRV(SV) = (VAL))
#endif /* !SvRV_set */
#ifndef newSV_type
# define newSV_type(type) THX_newSV_type(aTHX_ type)
static SV *THX_newSV_type(pTHX_ svtype type)
{
SV *sv = newSV(0);
(void) SvUPGRADE(sv, type);
return sv;
}
#endif /* !newSV_type */
#ifndef SVfARG
# define SVfARG(p) ((void *)p)
#endif /* !SVfARG */
#ifndef GV_NOTQUAL
# define GV_NOTQUAL 0
#endif /* !GV_NOTQUAL */
#ifndef padnamelist_store
/* Note that the return values are different. If we ever call it in non-
void context, we would have to change it to *av_store. */
# define padnamelist_store av_store
#endif
/*
* scalar classification
*
* Logic borrowed from Params::Classify.
*/
#define sv_is_glob(sv) (SvTYPE(sv) == SVt_PVGV)
#if PERL_VERSION_GE(5,11,0)
# define sv_is_regexp(sv) (SvTYPE(sv) == SVt_REGEXP)
#else /* <5.11.0 */
# define sv_is_regexp(sv) 0
#endif /* <5.11.0 */
#define sv_is_string(sv) \
(!sv_is_glob(sv) && !sv_is_regexp(sv) && \
(SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK|SVp_IOK|SVp_NOK|SVp_POK)))
/*
* gen_const_identity_op()
*
* This function generate op that evaluates to a fixed object identity
* and can also participate in constant folding.
*
* Lexical::Var generally needs to make ops that evaluate to fixed
* identities, that being what a name that it handles represents.
* Normally it can do this by means of an rv2xv op applied to a const op,
* where the const op holds an RV that references the object of interest.
* However, rv2xv can't undergo constant folding. Where the object is
* a readonly scalar, we'd like it to take part in constant folding.
* The obvious way to make it work as a constant for folding is to use a
* const op that directly holds the object. However, in a Perl built for
* ithreads, the value in a const op gets moved into the pad to achieve
* clonability, and in the process the value may be copied rather than the
* object merely rereferenced. Generally, the const op only guarantees
* to provide a fixed *value*, not a fixed object identity.
*
* Where a const op might not preserve object identity, we can achieve
* preservation by means of a customised variant of the const op. The op
* directly holds an RV that references the object of interest, and its
* variant pp function dereferences it (as rv2sv would). The pad logic
* operates on the op structure as normal, and may copy the RV without
* preserving its identity, which is OK because the RV isn't what we
* need to preserve. Being labelled as a const op, it is eligible for
* constant folding. When actually executed, it evaluates to the object
* of interest, providing both fixed value and fixed identity.
*/
#ifdef USE_ITHREADS
# define Q_USE_ITHREADS 1
#else /* !USE_ITHREADS */
# define Q_USE_ITHREADS 0
#endif /* !USE_ITHREADS */
#define Q_CONST_COPIES Q_USE_ITHREADS
#if Q_CONST_COPIES
static OP *pp_const_via_ref(pTHX)
{
dSP;
SV *reference_sv = cSVOPx_sv(PL_op);
SV *referent_sv = SvRV(reference_sv);
PUSHs(referent_sv);
RETURN;
}
#endif /* Q_CONST_COPIES */
#define gen_const_identity_op(sv) THX_gen_const_identity_op(aTHX_ sv)
static OP *THX_gen_const_identity_op(pTHX_ SV *sv)
{
#if Q_CONST_COPIES
OP *op = newSVOP(OP_CONST, 0, newRV_noinc(sv));
op->op_ppaddr = pp_const_via_ref;
return op;
#else /* !Q_CONST_COPIES */
return newSVOP(OP_CONST, 0, sv);
if(!sv_is_string(name)) croak("%s name is not a string", vari_word);
key = name_key(base_sigil, name);
if(!key) croak("malformed %s name", vari_word);
he = hv_fetch_ent(GvHV(PL_hintgv), key, 0, 0);
return he ? SvREFCNT_inc(HeVAL(he)) : &PL_sv_undef;
}
static int svt_scalar(svtype t)
{
switch(t) {
case SVt_NULL: case SVt_IV: case SVt_NV:
#if !PERL_VERSION_GE(5,11,0)
case SVt_RV:
#endif /* <5.11.0 */
case SVt_PV: case SVt_PVIV: case SVt_PVNV:
case SVt_PVMG: case SVt_PVLV: case SVt_PVGV:
#if PERL_VERSION_GE(5,11,0)
case SVt_REGEXP:
#endif /* >=5.11.0 */
return 1;
default:
return 0;
}
}
#define import(base_sigil, vari_word) THX_import(aTHX_ base_sigil, vari_word)
static void THX_import(pTHX_ char base_sigil, char const *vari_word)
{
dXSARGS;
CV *compcv;
int i;
SP -= items;
if(items < 1)
croak("too few arguments for import");
if(items == 1)
croak("%"SVf" does no default importation", SVfARG(ST(0)));
if(!(items & 1))
croak("import list for %"SVf
" must alternate name and reference", SVfARG(ST(0)));
compcv = find_compcv(vari_word);
PL_hints |= HINT_LOCALIZE_HH;
gv_HVadd(PL_hintgv);
for(i = 1; i != items; i += 2) {
SV *name = ST(i), *ref = ST(i+1), *key, *val;
svtype rt;
bool rok;
char const *vt;
char sigil;
HE *he;
if(!sv_is_string(name))
croak("%s name is not a string", vari_word);
key = name_key(base_sigil, name);
if(!key) croak("malformed %s name", vari_word);
sigil = SvPVX(key)[KEYPREFIXLEN];
rt = SvROK(ref) ? SvTYPE(SvRV(ref)) : SVt_LAST;
switch(sigil) {
case '$': rok = svt_scalar(rt); vt="scalar"; break;
case '@': rok = rt == SVt_PVAV; vt="array"; break;
case '%': rok = rt == SVt_PVHV; vt="hash"; break;
case '&': rok = rt == SVt_PVCV; vt="code"; break;
case '*': rok = rt == SVt_PVGV; vt="glob"; break;
default: rok = 0; vt = "wibble"; break;
}
if(!rok) croak("%s is not %s reference", vari_word, vt);
val = newRV_inc(SvRV(ref));
he = hv_store_ent(GvHV(PL_hintgv), key, val, 0);
if(he) {
val = HeVAL(he);
SvSETMAGIC(val);
} else {
SvREFCNT_dec(val);
}
if(char_attr[(U8)sigil] & CHAR_USEPAD)
setup_pad(compcv, SvPVX(key)+KEYPREFIXLEN);
}
PUTBACK;
}
#define unimport(base_sigil, vari_word) \
THX_unimport(aTHX_ base_sigil, vari_word)
static void THX_unimport(pTHX_ char base_sigil, char const *vari_word)
{
dXSARGS;
CV *compcv;
int i;
SP -= items;
if(items < 1)
croak("too few arguments for unimport");
if(items == 1)
croak("%"SVf" does no default unimportation", SVfARG(ST(0)));
compcv = find_compcv(vari_word);
PL_hints |= HINT_LOCALIZE_HH;
gv_HVadd(PL_hintgv);
for(i = 1; i != items; i++) {
SV *name = ST(i), *ref, *key;
char sigil;
if(!sv_is_string(name))
croak("%s name is not a string", vari_word);
key = name_key(base_sigil, name);
if(!key) croak("malformed %s name", vari_word);
sigil = SvPVX(key)[KEYPREFIXLEN];
if(i != items && (ref = ST(i+1), SvROK(ref))) {
HE *he;
SV *cref;
i++;
he = hv_fetch_ent(GvHV(PL_hintgv), key, 0, 0);
cref = he ? HeVAL(he) : &PL_sv_undef;
if(SvROK(cref) && SvRV(cref) != SvRV(ref))
continue;
}
(void) hv_delete_ent(GvHV(PL_hintgv), key, G_DISCARD, 0);
if(char_attr[(U8)sigil] & CHAR_USEPAD)
setup_pad(compcv, SvPVX(key)+KEYPREFIXLEN);
}
}
MODULE = Lexical::Var PACKAGE = Lexical::Var
PROTOTYPES: DISABLE
BOOT:
( run in 1.648 second using v1.01-cache-2.11-cpan-39bf76dae61 )