summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2011-12-21 08:17:01 -0800
committerFather Chrysostomos <sprout@cpan.org>2011-12-21 10:37:51 -0800
commitbe6cf5cf0a864ce5ef586bff8ef592ed0485d201 (patch)
treeb08367dba1946f80aa99c3c7454b812be874bbdf
parent86c08a2ca2546ef08513c65dabf686423cade2f3 (diff)
downloadperl-be6cf5cf0a864ce5ef586bff8ef592ed0485d201.tar.gz
Deparse "string"->[0] correctly
"foo"->[0] and $foo[0] compile down to the same thing. B::Deparse was assuming that an rv2gv with a gv kid would have to be $foo[0] syntax, so it didn’t take things like '!@T#$'->[0] into account. This commit only fixes aelemfast. It is related to b89b7257.
-rw-r--r--dist/B-Deparse/Deparse.pm34
-rw-r--r--dist/B-Deparse/t/deparse.t12
2 files changed, 34 insertions, 12 deletions
diff --git a/dist/B-Deparse/Deparse.pm b/dist/B-Deparse/Deparse.pm
index 6a4d8cb78a..d99080aa03 100644
--- a/dist/B-Deparse/Deparse.pm
+++ b/dist/B-Deparse/Deparse.pm
@@ -1304,6 +1304,23 @@ sub stash_variable {
return "$prefix$name";
}
+# Return just the name, without the prefix. It may be returned as a quoted
+# string. The second return value is a boolean indicating that.
+sub stash_variable_name {
+ my($self, $prefix, $gv) = @_;
+ my $name = $self->gv_name($gv, 1);
+ $name = $self->{'curstash'}.'::'. $name
+ if $prefix and $self->lex_in_scope("$prefix$name");
+ if ($name =~ /^(?:\S|(?!\d)[\ca-\cz]?(?:\w|::)*|\d+)\z/) {
+ $name =~ s/^([\ca-\cz])/'^'.($1|'@')/e;
+ $name =~ /^(\^..|{)/ and $name = "{$name}";
+ return $name, 0; # not quoted
+ }
+ else {
+ single_delim("q", "'", $name), 1;
+ }
+}
+
sub lex_in_scope {
my ($self, $name) = @_;
$self->populate_curcvlex() if !defined $self->{'curcvlex'};
@@ -2373,14 +2390,9 @@ sub pp_dorassign { logassignop(@_, "//=") }
sub rv2gv_or_string {
my($self,$op) = @_;
if ($op->name eq "gv") { # could be open("open") or open("###")
- my $name = $self->gv_name($self->gv_or_padgv($op), 1);
- if ($name =~ /^(?:\S|(?!\d)[\ca-\cz]?\w*|\d+)\z/) {
- $name =~ s/^([\ca-\cz])/'^'.($1|'@')/e;
- $name =~ /^(\^..|{)/ ? "*{$name}" : "*$name";
- }
- else {
- single_delim("q", "'", $name);
- }
+ my($name,$quoted) =
+ $self->stash_variable_name(undef,$self->gv_or_padgv($op));
+ $quoted ? $name : "*$name";
}
else {
$self->deparse($op, 6);
@@ -3050,10 +3062,8 @@ sub pp_aelemfast {
return $self->pp_aelemfast_lex(@_) if ($op->flags & OPf_SPECIAL);
my $gv = $self->gv_or_padgv($op);
- my $name = $self->gv_name($gv);
- $name = $self->{'curstash'}."::$name"
- if $name !~ /::/ && $self->lex_in_scope('@'.$name);
- $name = '$' . $name;
+ my($name,$quoted) = $self->stash_variable_name('@',$gv);
+ $name = $quoted ? "$name->" : '$' . $name;
return $name . "[" . ($op->private + $self->{'arybase'}) . "]";
}
diff --git a/dist/B-Deparse/t/deparse.t b/dist/B-Deparse/t/deparse.t
index be9cbb6d29..2baef66027 100644
--- a/dist/B-Deparse/t/deparse.t
+++ b/dist/B-Deparse/t/deparse.t
@@ -902,6 +902,18 @@ open '####';
open '^A';
open *^A;
####
+# "string"->[] ->{}
+no strict 'vars';
+() = 'open'->[0]; #aelemfast
+() = '####'->[0];
+() = '^A'->[0];
+() = "\ca"->[0];
+>>>>
+() = $open[0];
+() = '####'->[0];
+() = '^A'->[0];
+() = $^A[0];
+####
# [perl #74740] -(f()) vs -f()
$_ = -(f());
####