This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
mk_PL_charclass.pl: Accept Unicode 6.1 syntax
[perl5.git] / dist / B-Deparse / Deparse.pm
index 81c918c..28da808 100644 (file)
@@ -14,7 +14,7 @@ use B qw(class main_root main_start main_cv svref_2object opnumber perlstring
         OPf_KIDS OPf_REF OPf_STACKED OPf_SPECIAL OPf_MOD
         OPpLVAL_INTRO OPpOUR_INTRO OPpENTERSUB_AMPER OPpSLICE OPpCONST_BARE
         OPpTRANS_SQUASH OPpTRANS_DELETE OPpTRANS_COMPLEMENT OPpTARGET_MY
-        OPpCONST_ARYBASE OPpEXISTS_SUB OPpSORT_NUMERIC OPpSORT_INTEGER
+        OPpEXISTS_SUB OPpSORT_NUMERIC OPpSORT_INTEGER
         OPpSORT_REVERSE
         SVf_IOK SVf_NOK SVf_ROK SVf_POK SVpad_OUR SVf_FAKE SVs_RMG SVs_SMG
          CVf_METHOD CVf_LVALUE
@@ -25,8 +25,16 @@ use B qw(class main_root main_start main_cv svref_2object opnumber perlstring
         ($] < 5.008009 ? () : qw(OPpCONST_NOVER OPpPAD_STATE)),
         ($] < 5.009 ? 'PMf_SKIPWHITE' : qw(RXf_SKIPWHITE)),
         ($] < 5.011 ? 'CVf_LOCKED' : 'OPpREVERSE_INPLACE'),
-        ($] < 5.013 ? () : 'PMf_NONDESTRUCT');
-$VERSION = "1.04";
+        ($] < 5.013 ? () : 'PMf_NONDESTRUCT'),
+        ($] < 5.015003 &&
+            # This empirical feature test is required during the
+            # transitional phase where blead still identifies itself
+            # as 5.15.2 but has had $[ removed.  After blead has its
+            # version number bumped to 5.15.3, this can be reduced to
+            # just test $] < 5.015003.
+            ($] < 5.015002 || do { require B; exists(&B::OPpCONST_ARYBASE) })
+            ? qw(OPpCONST_ARYBASE) : ());
+$VERSION = "1.08";
 use strict;
 use vars qw/$AUTOLOAD/;
 use warnings ();
@@ -36,7 +44,7 @@ BEGIN {
     # be to fake up a dummy constant that will never actually be true.
     foreach (qw(OPpSORT_INPLACE OPpSORT_DESCEND OPpITER_REVERSED OPpCONST_NOVER
                OPpPAD_STATE RXf_SKIPWHITE CVf_LOCKED OPpREVERSE_INPLACE
-               PMf_NONDESTRUCT)) {
+               PMf_NONDESTRUCT OPpCONST_ARYBASE)) {
        no strict 'refs';
        *{$_} = sub () {0} unless *{$_}{CODE};
     }
@@ -481,7 +489,7 @@ sub stash_subs {
     else {
        $pack =~ s/(::)?$/::/;
        no strict 'refs';
-       $stash = \%$pack;
+       $stash = \%{"main::$pack"};
     }
     my %stash = svref_2object($stash)->ARRAY;
     while (my ($key, $val) = each %stash) {
@@ -737,7 +745,11 @@ sub ambient_pragmas {
        }
 
        elsif ($name eq '$[') {
-           $arybase = $val;
+           if (OPpCONST_ARYBASE) {
+               $arybase = $val;
+           } else {
+               croak "\$[ can't be non-zero on this perl" unless $val == 0;
+           }
        }
 
        elsif ($name eq 'integer'
@@ -1095,7 +1107,9 @@ sub maybe_my {
     my $self = shift;
     my($op, $cx, $text) = @_;
     if ($op->private & OPpLVAL_INTRO and not $self->{'avoid_local'}{$$op}) {
-       my $my = $op->private & OPpPAD_STATE ? "state" : "my";
+       my $my = $op->private & OPpPAD_STATE
+           ? $self->keyword("state")
+           : "my";
        if (want_scalar($op)) {
            return "$my $text";
        } else {
@@ -1274,7 +1288,7 @@ Carp::confess() unless ref($gv) eq "B::GV";
 # If a lexical with the same name is in scope, it may need to be
 # fully-qualified.
 sub stash_variable {
-    my ($self, $prefix, $name) = @_;
+    my ($self, $prefix, $name, $cx) = @_;
 
     return "$prefix$name" if $name =~ /::/;
 
@@ -1283,6 +1297,18 @@ sub stash_variable {
        return "$prefix$name";
     }
 
+    if ($name =~ /^[^\w+-]$/) {
+      if (defined $cx && $cx == 26) {
+       if ($prefix eq '@') {
+           return "$prefix\{$name}";
+       }
+       elsif ($name eq '#') { return '${#}' } #  "${#}a" vs "$#a"
+      }
+      if ($prefix eq '$#') {
+       return "\$#{$name}";
+      }
+    }
+
     my $v = ($prefix eq '$#' ? '@' : $prefix) . $name;
     return $prefix .$self->{'curstash'}.'::'. $name if $self->lex_in_scope($v);
     return "$prefix$name";
@@ -1404,7 +1430,7 @@ sub pp_nextstate {
        $self->{'curstash'} = $stash;
     }
 
-    if ($self->{'arybase'} != $op->arybase) {
+    if (OPpCONST_ARYBASE && $self->{'arybase'} != $op->arybase) {
        push @text, '$[ = '. $op->arybase .";\n";
        $self->{'arybase'} = $op->arybase;
     }
@@ -1523,12 +1549,29 @@ sub pp_setstate { pp_nextstate(@_) }
 
 sub pp_unstack { return "" } # see also leaveloop
 
+my %feature_keywords = (
+  # keyword => 'feature',
+    state   => 'state',
+    say     => 'say',
+    given   => 'switch',
+    when    => 'switch',
+    default => 'switch',
+    break   => 'switch',
+);
+
 sub keyword {
     my $self = shift;
     my $name = shift;
     return $name if $name =~ /^CORE::/; # just in case
+    if (exists $feature_keywords{$name}) {
+       return
+         $self->{'hinthash'}
+          && $self->{'hinthash'}{"feature_$feature_keywords{$name}"}
+           ? $name
+           : "CORE::$name";
+    }
     if (
-      $name !~ /^(?:chom?p|exec|system)\z/
+      $name !~ /^(?:chom?p|exec|s(?:elect|ystem))\z/
        && !defined eval{prototype "CORE::$name"}
     ) { return $name }
     if (
@@ -1740,11 +1783,7 @@ sub pp_ggrgid { unop(@_, "getgrgid") }
 sub pp_lock { unop(@_, "lock") }
 
 sub pp_continue { unop(@_, "continue"); }
-sub pp_break {
-    my ($self, $op) = @_;
-    return "" if $op->flags & OPf_SPECIAL;
-    unop(@_, "break");
-}
+sub pp_break { unop(@_, "break"); }
 
 sub givwhen {
     my $self = shift;
@@ -1753,7 +1792,7 @@ sub givwhen {
     my $enterop = $op->first;
     my ($head, $block);
     if ($enterop->flags & OPf_SPECIAL) {
-       $head = "default";
+       $head = $self->keyword("default");
        $block = $self->deparse($enterop->first, 0);
     }
     else {
@@ -1768,8 +1807,8 @@ sub givwhen {
        "\b}\cK";
 }
 
-sub pp_leavegiven { givwhen(@_, "given"); }
-sub pp_leavewhen  { givwhen(@_, "when"); }
+sub pp_leavegiven { givwhen(@_, $_[0]->keyword("given")); }
+sub pp_leavewhen  { givwhen(@_, $_[0]->keyword("when")); }
 
 sub pp_exists {
     my $self = shift;
@@ -2428,9 +2467,6 @@ sub pp_syscall { listop(@_, "syscall") }
 sub pp_glob {
     my $self = shift;
     my($op, $cx) = @_;
-    if ($op->flags & OPf_SPECIAL) {
-       return $self->deparse($op->first->sibling);
-    }
     my $text = $self->dq($op->first->sibling);  # skip pushmark
     if ($text =~ /^\$?(\w|::|\`)+$/ # could look like a readline
        or $text =~ /[<>]/) {
@@ -2812,10 +2848,9 @@ sub pp_leavetry {
     return "eval {\n\t" . $self->pp_leave(@_) . "\n\b}";
 }
 
-BEGIN { eval "sub OP_CONST () {" . opnumber("const") . "}" }
-BEGIN { eval "sub OP_STRINGIFY () {" . opnumber("stringify") . "}" }
-BEGIN { eval "sub OP_RV2SV () {" . opnumber("rv2sv") . "}" }
-BEGIN { eval "sub OP_LIST () {" . opnumber("list") . "}" }
+BEGIN { for (qw[ const stringify rv2sv list glob ]) {
+    eval "sub OP_\U$_ () { " . opnumber($_) . "}"
+}}
 
 sub pp_null {
     my $self = shift;
@@ -2833,6 +2868,14 @@ sub pp_null {
        return $self->pp_scope($op->first, $cx);
     } elsif ($op->targ == OP_STRINGIFY) {
        return $self->dquote($op, $cx);
+    } elsif ($op->targ == OP_GLOB) {
+       return $self->pp_glob(
+                $op->first    # entersub
+                   ->first    # ex-list
+                   ->first    # pushmark
+                   ->sibling, # glob
+                $cx
+              );
     } elsif (!null($op->first->sibling) and
             $op->first->sibling->name eq "readline" and
             $op->first->sibling->flags & OPf_STACKED) {
@@ -2903,7 +2946,7 @@ sub pp_gvsv {
     my($op, $cx) = @_;
     my $gv = $self->gv_or_padgv($op);
     return $self->maybe_local($op, $cx, $self->stash_variable("\$",
-                                $self->gv_name($gv)));
+                                $self->gv_name($gv), $cx));
 }
 
 sub pp_gv {
@@ -2913,22 +2956,25 @@ sub pp_gv {
     return $self->gv_name($gv);
 }
 
+sub pp_aelemfast_lex {
+    my $self = shift;
+    my($op, $cx) = @_;
+    my $name = $self->padname($op->targ);
+    $name =~ s/^@/\$/;
+    return $name . "[" .  ($op->private + $self->{'arybase'}) . "]";
+}
+
 sub pp_aelemfast {
     my $self = shift;
     my($op, $cx) = @_;
-    my $name;
-    if ($op->flags & OPf_SPECIAL) { # optimised PADAV
-       $name = $self->padname($op->targ);
-       $name =~ s/^@/\$/;
-    }
-    else {
-       my $gv = $self->gv_or_padgv($op);
-       $name = $self->gv_name($gv);
-       $name = $self->{'curstash'}."::$name"
-           if $name !~ /::/ && $self->lex_in_scope('@'.$name);
-       $name = '$' . $name;
-    }
+    # optimised PADAV, pre 5.15
+    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;
     return $name . "[" .  ($op->private + $self->{'arybase'}) . "]";
 }
 
@@ -2942,7 +2988,7 @@ sub rv2x {
     }
     my $kid = $op->first;
     if ($kid->name eq "gv") {
-       return $self->stash_variable($type, $self->deparse($kid, 0));
+       return $self->stash_variable($type, $self->deparse($kid, 0), $cx);
     } elsif (is_scalar $kid) {
        my $str = $self->deparse($kid, 0);
        if ($str =~ /^\$([^\w\d])\z/) {
@@ -3218,7 +3264,7 @@ sub _method {
     } else {
        $obj = $kid;
        $kid = $kid->sibling;
-       for (; !null ($kid->sibling) && $kid->name ne "method_named";
+       for (; !null ($kid->sibling) && $kid->name!~/^method(?:_named)?\z/;
              $kid = $kid->sibling) {
            push @exprs, $kid
        }
@@ -4330,7 +4376,7 @@ sub pp_split {
     } elsif (!ref($replroot) and $replroot > 0) {
        $gv = $self->padval($replroot);
     }
-    $ary = $self->stash_variable('@', $self->gv_name($gv)) if $gv;
+    $ary = $self->stash_variable('@', $self->gv_name($gv), $cx) if $gv;
 
     for (; !null($kid); $kid = $kid->sibling) {
        push @exprs, $self->deparse($kid, 6);
@@ -4758,6 +4804,7 @@ expect.
 =item $[
 
 Takes a number, the value of the array base $[.
+Cannot be non-zero on Perl 5.15.3 or later.
 
 =item bytes