summaryrefslogtreecommitdiff
path: root/pp.c
diff options
context:
space:
mode:
authorRuslan Zakirov <ruz@bestpractical.com>2013-03-02 16:57:41 +0400
committerFather Chrysostomos <sprout@cpan.org>2013-09-13 01:25:34 -0700
commit6dd3e0f2449b60948d1ae2a8377afcea1fb88000 (patch)
tree7bb1d7d0fa55961d739a7b240953b5805d0fb866 /pp.c
parentace8699dea8a8f004662f49f5587ba134fee9da1 (diff)
downloadperl-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.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/pp.c b/pp.c
index 470ebd1681..2dd0fe8d9a 100644
--- a/pp.c
+++ b/pp.c
@@ -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)
{