diff options
author | Ruslan Zakirov <ruz@bestpractical.com> | 2013-03-02 16:57:41 +0400 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2013-09-13 01:25:34 -0700 |
commit | 6dd3e0f2449b60948d1ae2a8377afcea1fb88000 (patch) | |
tree | 7bb1d7d0fa55961d739a7b240953b5805d0fb866 /pp.c | |
parent | ace8699dea8a8f004662f49f5587ba134fee9da1 (diff) | |
download | perl-6dd3e0f2449b60948d1ae2a8377afcea1fb88000.tar.gz |
index/value array slice operation
kvaslice operator that imlements %a[0,2,4] syntax which
result in list of index/value pairs. Implemented in
consistency with "key/value hash slice" operator.
Diffstat (limited to 'pp.c')
-rw-r--r-- | pp.c | 44 |
1 files changed, 44 insertions, 0 deletions
@@ -4350,6 +4350,50 @@ PP(pp_aslice) RETURN; } +PP(pp_kvaslice) +{ + dVAR; dSP; dMARK; + AV *const av = MUTABLE_AV(POPs); + I32 lval = (PL_op->op_flags & OPf_MOD); + I32 items = SP - MARK; + + if (PL_op->op_private & OPpMAYBE_LVSUB) { + const I32 flags = is_lvalue_sub(); + if (flags) { + if (!(flags & OPpENTERSUB_INARGS)) + Perl_croak(aTHX_ "Can't modify index/value array slice in list assignment"); + lval = flags; + } + } + + MEXTEND(SP,items); + while (items > 1) { + *(MARK+items*2-1) = *(MARK+items); + items--; + } + items = SP-MARK; + SP += items; + + while (++MARK <= SP) { + SV **svp; + + svp = av_fetch(av, SvIV(*MARK), lval); + if (lval) { + if (!svp || !*svp || *svp == &PL_sv_undef) { + DIE(aTHX_ PL_no_aelem, SvIV(*MARK)); + } + *MARK = sv_mortalcopy(*MARK); + } + *++MARK = svp ? *svp : &PL_sv_undef; + } + if (GIMME != G_ARRAY) { + MARK = SP - items*2; + *++MARK = items > 0 ? *SP : &PL_sv_undef; + SP = MARK; + } + RETURN; +} + /* Smart dereferencing for keys, values and each */ PP(pp_rkeys) { |