Array-Base
view release on metacpan or search on metacpan
lib/Array/Base.xs view on Meta::CPAN
#endif /* OPpGREP_LEX */
return mop;
}
static OP *THX_myck_aelem(pTHX_ OP *op)
{
IV base;
if((base = current_base()) != 0) {
OP *aop, *iop;
if(!(op->op_flags & OPf_KIDS)) {
bad_ops:
croak("strange op tree prevents applying array base");
}
aop = cBINOPx(op)->op_first;
iop = OpSIBLING(aop);
if(!iop || OpHAS_SIBLING(iop)) goto bad_ops;
OpLASTSIB_set(aop, op);
cBINOPx(op)->op_last = NULL;
OpLASTSIB_set(iop, NULL);
iop = op_contextualize(
newBINOP(OP_I_SUBTRACT, 0, iop,
newSVOP(OP_CONST, 0, newSViv(base))),
G_SCALAR);
OpMORESIB_set(aop, iop);
OpLASTSIB_set(iop, op);
cBINOPx(op)->op_last = iop;
}
return THX_nxck_aelem(aTHX_ op);
}
static OP *THX_myck_aslice(pTHX_ OP *op)
{
IV base;
if((base = current_base()) != 0) {
OP *iop, *aop;
if(!(op->op_flags & OPf_KIDS)) {
bad_ops:
croak("strange op tree prevents applying array base");
}
iop = cLISTOPx(op)->op_first;
aop = OpSIBLING(iop);
if(!aop || OpHAS_SIBLING(aop)) goto bad_ops;
OpLASTSIB_set(iop, NULL);
cLISTOPx(op)->op_first = aop;
iop = op_contextualize(mapify_op(iop, base, OP_I_SUBTRACT),
G_ARRAY);
OpMORESIB_set(iop, aop);
cLISTOPx(op)->op_first = iop;
}
return THX_nxck_aslice(aTHX_ op);
}
#if QHAVE_OP_KVASLICE
static OP *THX_pp_munge_kvaslice(pTHX)
{
dSP; dMARK;
if(SP != MARK) {
SV **kp;
IV base = POPi;
PUTBACK;
if(MARK+1 != SP) {
for(kp = MARK; kp != SP; kp += 2) {
SV *k = kp[1];
if(SvOK(k))
kp[1] = sv_2mortal(
newSViv(SvIV(k) + base));
}
}
}
return PL_op->op_next;
}
#define newUNOP_munge_kvaslice(f, l) THX_newUNOP_munge_kvaslice(aTHX_ f, l)
static OP *THX_newUNOP_munge_kvaslice(pTHX_ OP *kvasliceop, OP *baseop)
{
OP *mungeop, *pushop;
pushop = newOP(OP_PUSHMARK, 0);
NewOpSz(0, mungeop, sizeof(UNOP));
#ifdef XopENTRY_set
mungeop->op_type = OP_CUSTOM;
#else /* !XopENTRY_set */
mungeop->op_type = OP_DOFILE;
#endif /* !XopENTRY_set */
mungeop->op_ppaddr = THX_pp_munge_kvaslice;
mungeop->op_flags = OPf_KIDS;
cUNOPx(mungeop)->op_first = pushop;
OpMORESIB_set(pushop, kvasliceop);
OpMORESIB_set(kvasliceop, baseop);
OpLASTSIB_set(baseop, mungeop);
return mungeop;
}
static OP *THX_myck_kvaslice(pTHX_ OP *op)
{
IV base;
if((base = current_base()) != 0) {
OP *iop, *aop;
if(!(op->op_flags & OPf_KIDS)) {
bad_ops:
croak("strange op tree prevents applying array base");
}
iop = cLISTOPx(op)->op_first;
aop = OpSIBLING(iop);
if(!aop || OpHAS_SIBLING(aop)) goto bad_ops;
/*
* A kvaslice op is built in a nasty way that interferes
* with munging it through a checker. It's first built
* containing the interesting operands, but missing a
* necessary pushmark op. The checker gets invoked on
* this incomplete op. Then the pushmark gets inserted,
* without invoking any checker, provided that the op is
* still of type kvaslice. If the checker changed the op
* type, then instead a new kvaslice gets built containing
* the pushmark and whatever the checker returned,
* and the checker gets invoked a second time on that.
*
* The incomplete structure the first time round
* means we can't very well wrap the op at that point.
* We can munge the operands, but the wrapping needs to
* be postponed until after the pushmark gets inserted.
lib/Array/Base.xs view on Meta::CPAN
if((base = current_base()) != 0) {
OP *pop, *aop, *iop;
if(!(op->op_flags & OPf_KIDS)) {
bad_ops:
croak("strange op tree prevents applying array base");
}
pop = cLISTOPx(op)->op_first;
if(pop->op_type != OP_PUSHMARK) goto bad_ops;
aop = OpSIBLING(pop);
if(!aop) goto bad_ops;
iop = OpSIBLING(aop);
if(iop) {
OP *rest = OpSIBLING(iop);
OpMAYBESIB_set(aop, rest, op);
OpLASTSIB_set(iop, NULL);
if(!rest) cLISTOPx(op)->op_last = aop;
iop = newBINOP(OP_I_SUBTRACT, 0,
op_contextualize(iop, G_SCALAR),
newSVOP(OP_CONST, 0, newSViv(base)));
OpMAYBESIB_set(iop, rest, op);
OpMORESIB_set(aop, iop);
if(!rest) cLISTOPx(op)->op_last = iop;
}
}
return THX_nxck_splice(aTHX_ op);
}
#if QHAVE_OP_AKEYS
static OP *THX_myck_keys(pTHX_ OP *op)
{
/*
* Annoyingly, keys(@array) ops don't go through the nominal
* checker for OP_AKEYS. Instead they start out as OP_KEYS,
* and get mutated to OP_AKEYS by the OP_KEYS checker. This
* is therefore what we have to hook.
*/
OP *aop;
IV base;
if((op->op_flags & OPf_KIDS) && (aop = cUNOPx(op)->op_first, 1) &&
(aop->op_type == OP_PADAV ||
aop->op_type == OP_RV2AV) &&
(base = current_base()) != 0) {
return mapify_op(
op_contextualize(THX_nxck_keys(aTHX_ op), G_ARRAY),
base, OP_I_ADD);
} else {
return THX_nxck_keys(aTHX_ op);
}
}
#endif /* QHAVE_OP_AKEYS */
#if QHAVE_OP_AEACH
static OP *THX_pp_munge_aeach(pTHX)
{
dSP; dMARK;
if(SP != MARK) {
IV base = POPi;
if(SP != MARK && SvOK(MARK[1]))
MARK[1] = sv_2mortal(newSViv(SvIV(MARK[1]) + base));
PUTBACK;
}
return PL_op->op_next;
}
#define newUNOP_munge_aeach(f, l) THX_newUNOP_munge_aeach(aTHX_ f, l)
static OP *THX_newUNOP_munge_aeach(pTHX_ OP *aeachop, OP *baseop)
{
OP *mungeop, *pushop;
pushop = newOP(OP_PUSHMARK, 0);
NewOpSz(0, mungeop, sizeof(UNOP));
#ifdef XopENTRY_set
mungeop->op_type = OP_CUSTOM;
#else /* !XopENTRY_set */
mungeop->op_type = OP_DOFILE;
#endif /* !XopENTRY_set */
mungeop->op_ppaddr = THX_pp_munge_aeach;
mungeop->op_flags = OPf_KIDS;
cUNOPx(mungeop)->op_first = pushop;
OpMORESIB_set(pushop, aeachop);
OpMORESIB_set(aeachop, baseop);
OpLASTSIB_set(baseop, mungeop);
return mungeop;
}
static OP *THX_myck_each(pTHX_ OP *op)
{
/*
* Annoyingly, each(@array) ops don't go through the nominal
* checker for OP_AEACH. Instead they start out as OP_EACH,
* and get mutated to OP_AEACH by the OP_EACH checker. This
* is therefore what we have to hook.
*/
OP *aop;
IV base;
if((op->op_flags & OPf_KIDS) && (aop = cUNOPx(op)->op_first, 1) &&
(aop->op_type == OP_PADAV ||
aop->op_type == OP_RV2AV) &&
(base = current_base()) != 0) {
return newUNOP_munge_aeach(THX_nxck_each(aTHX_ op),
newSVOP(OP_CONST, 0, newSViv(base)));
} else {
return THX_nxck_each(aTHX_ op);
}
}
#endif /* QHAVE_OP_AEACH */
MODULE = Array::Base PACKAGE = Array::Base
PROTOTYPES: DISABLE
BOOT:
{
#ifdef XopENTRY_set
XOP *xop;
Newxz(xop, 1, XOP);
XopENTRY_set(xop, xop_name, "munge_aeach");
XopENTRY_set(xop, xop_desc, "fixup following each on array");
XopENTRY_set(xop, xop_class, OA_UNOP);
Perl_custom_op_register(aTHX_ THX_pp_munge_aeach, xop);
( run in 1.351 second using v1.01-cache-2.11-cpan-39bf76dae61 )