Skip to content

Commit

Permalink
\@array[@slice] assignment
Browse files Browse the repository at this point in the history
plus changes to the aelem tests to check rhs context.

I did \local @A[@s] at the same time, since I was practically copying
and pasting code from aslice (ok, not quite).
  • Loading branch information
Father Chrysostomos committed Oct 11, 2014
1 parent 1199b01 commit 0ca7b7f
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 6 deletions.
5 changes: 5 additions & 0 deletions op.c
Original file line number Diff line number Diff line change
Expand Up @@ -2649,6 +2649,11 @@ Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags)
kid->op_private |= OPpLVREF_ELEM;
kid->op_flags |= OPf_STACKED;
break;
case OP_ASLICE:
kid->op_type = OP_LVREFSLICE;
kid->op_ppaddr = PL_ppaddr[OP_LVREFSLICE];
kid->op_private &= OPpLVAL_INTRO|OPpLVREF_ELEM;
continue;
default:
badref:
/* diag_listed_as: Can't modify %s in %s */
Expand Down
47 changes: 46 additions & 1 deletion pp.c
Original file line number Diff line number Diff line change
Expand Up @@ -6223,7 +6223,52 @@ PP(pp_lvref)

PP(pp_lvrefslice)
{
DIE(aTHX_ "Unimplemented");
dSP; dMARK; dORIGMARK;
AV * const av = (AV *)POPs;
const bool localizing = PL_op->op_private & OPpLVAL_INTRO;
bool can_preserve = FALSE;

if (localizing) {
MAGIC *mg;
HV *stash;
SV **svp;

can_preserve = SvCANEXISTDELETE(av);

if (SvTYPE(av) == SVt_PVAV) {
SSize_t max = -1;

for (svp = MARK + 1; svp <= SP; svp++) {
const SSize_t elem = SvIV(*svp);
if (elem > max)
max = elem;
}
if (max > AvMAX(av))
av_extend(av, max);
}
}

while (++MARK <= SP) {
SV * const elemsv = *MARK;
const SSize_t elem = SvIV(elemsv);
bool existent = TRUE;

if (localizing && can_preserve)
existent = av_exists(av, elem);

if (localizing && existent) {
SV ** const svp = av_fetch(av, elem, 1);
if (!svp || !*svp)
DIE(aTHX_ PL_no_aelem, elem);
save_aelem(av, elem, svp);
}
else
SAVEADELETE(av, elem);

*MARK = sv_2mortal(newSV_type(SVt_PVMG));
sv_magic(*MARK,(SV *)av,PERL_MAGIC_lvref,(char *)elemsv,HEf_SVKEY);
}
RETURN;
}

/*
Expand Down
25 changes: 20 additions & 5 deletions t/op/lvref.t
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ BEGIN {
set_up_inc("../lib");
}

plan 48;
plan 52;

sub on { $::TODO = ' ' }
sub off{ $::TODO = '' }
Expand Down Expand Up @@ -76,17 +76,32 @@ is *foo{SCALAR}, *bar{GLOB}, 'globref-to-scalarref assignment';

# Array Elements

\$a[0] = \$_;
sub expect_scalar_cx { wantarray ? 0 : \$_ }
sub expect_list_cx { wantarray ? (\$_,\$_) : 0 }
\$a[0] = expect_scalar_cx;
is \$a[0], \$_, '\$array[0]';
\($a[1]) = \$_;
\($a[1]) = expect_list_cx;
is \$a[1], \$_, '\($array[0])';
{
my @a;
\$a[0] = \$_;
\$a[0] = expect_scalar_cx;
is \$a[0], \$_, '\$lexical_array[0]';
\($a[1]) = \$_;
\($a[1]) = expect_list_cx;
is \$a[1], \$_, '\($lexical_array[0])';
}
{
my @a;
\@a[0,1] = expect_list_cx;
is \$a[0].\$a[1], \$_.\$_, '\@array[indices]';
\(@a[2,3]) = expect_list_cx;
is \$a[0].\$a[1], \$_.\$_, '\(@array[indices])';
my $tmp;
{
\local @a[0,1] = (\$tmp)x2;
is \$a[0].\$a[1], \$tmp.\$tmp, '\local @a[indices]';
}
is \$a[0].\$a[1], \$_.\$_, '\local @a[indices] unwound';
}

# Hash Elements

Expand Down

0 comments on commit 0ca7b7f

Please sign in to comment.