📄 deparse.pm
字号:
sub pp_complement { maybe_targmy(@_, \&pfixop, "~", 21) }sub pp_negate { maybe_targmy(@_, \&real_negate) }sub real_negate { my $self = shift; my($op, $cx) = @_; if ($op->first->name =~ /^(i_)?negate$/) { # avoid --$x $self->pfixop($op, $cx, "-", 21.5); } else { $self->pfixop($op, $cx, "-", 21); }}sub pp_i_negate { pp_negate(@_) }sub pp_not { my $self = shift; my($op, $cx) = @_; if ($cx <= 4) { $self->pfixop($op, $cx, "not ", 4); } else { $self->pfixop($op, $cx, "!", 21); }}sub unop { my $self = shift; my($op, $cx, $name) = @_; my $kid; if ($op->flags & OPf_KIDS) { $kid = $op->first; return $self->maybe_parens_unop($name, $kid, $cx); } else { return $name . ($op->flags & OPf_SPECIAL ? "()" : ""); }}sub pp_chop { maybe_targmy(@_, \&unop, "chop") }sub pp_chomp { maybe_targmy(@_, \&unop, "chomp") }sub pp_schop { maybe_targmy(@_, \&unop, "chop") }sub pp_schomp { maybe_targmy(@_, \&unop, "chomp") }sub pp_defined { unop(@_, "defined") }sub pp_undef { unop(@_, "undef") }sub pp_study { unop(@_, "study") }sub pp_ref { unop(@_, "ref") }sub pp_pos { maybe_local(@_, unop(@_, "pos")) }sub pp_sin { maybe_targmy(@_, \&unop, "sin") }sub pp_cos { maybe_targmy(@_, \&unop, "cos") }sub pp_rand { maybe_targmy(@_, \&unop, "rand") }sub pp_srand { unop(@_, "srand") }sub pp_exp { maybe_targmy(@_, \&unop, "exp") }sub pp_log { maybe_targmy(@_, \&unop, "log") }sub pp_sqrt { maybe_targmy(@_, \&unop, "sqrt") }sub pp_int { maybe_targmy(@_, \&unop, "int") }sub pp_hex { maybe_targmy(@_, \&unop, "hex") }sub pp_oct { maybe_targmy(@_, \&unop, "oct") }sub pp_abs { maybe_targmy(@_, \&unop, "abs") }sub pp_length { maybe_targmy(@_, \&unop, "length") }sub pp_ord { maybe_targmy(@_, \&unop, "ord") }sub pp_chr { maybe_targmy(@_, \&unop, "chr") }sub pp_each { unop(@_, "each") }sub pp_values { unop(@_, "values") }sub pp_keys { unop(@_, "keys") }sub pp_pop { unop(@_, "pop") }sub pp_shift { unop(@_, "shift") }sub pp_caller { unop(@_, "caller") }sub pp_reset { unop(@_, "reset") }sub pp_exit { unop(@_, "exit") }sub pp_prototype { unop(@_, "prototype") }sub pp_close { unop(@_, "close") }sub pp_fileno { unop(@_, "fileno") }sub pp_umask { unop(@_, "umask") }sub pp_untie { unop(@_, "untie") }sub pp_tied { unop(@_, "tied") }sub pp_dbmclose { unop(@_, "dbmclose") }sub pp_getc { unop(@_, "getc") }sub pp_eof { unop(@_, "eof") }sub pp_tell { unop(@_, "tell") }sub pp_getsockname { unop(@_, "getsockname") }sub pp_getpeername { unop(@_, "getpeername") }sub pp_chdir { maybe_targmy(@_, \&unop, "chdir") }sub pp_chroot { maybe_targmy(@_, \&unop, "chroot") }sub pp_readlink { unop(@_, "readlink") }sub pp_rmdir { maybe_targmy(@_, \&unop, "rmdir") }sub pp_readdir { unop(@_, "readdir") }sub pp_telldir { unop(@_, "telldir") }sub pp_rewinddir { unop(@_, "rewinddir") }sub pp_closedir { unop(@_, "closedir") }sub pp_getpgrp { maybe_targmy(@_, \&unop, "getpgrp") }sub pp_localtime { unop(@_, "localtime") }sub pp_gmtime { unop(@_, "gmtime") }sub pp_alarm { unop(@_, "alarm") }sub pp_sleep { maybe_targmy(@_, \&unop, "sleep") }sub pp_dofile { unop(@_, "do") }sub pp_entereval { unop(@_, "eval") }sub pp_ghbyname { unop(@_, "gethostbyname") }sub pp_gnbyname { unop(@_, "getnetbyname") }sub pp_gpbyname { unop(@_, "getprotobyname") }sub pp_shostent { unop(@_, "sethostent") }sub pp_snetent { unop(@_, "setnetent") }sub pp_sprotoent { unop(@_, "setprotoent") }sub pp_sservent { unop(@_, "setservent") }sub pp_gpwnam { unop(@_, "getpwnam") }sub pp_gpwuid { unop(@_, "getpwuid") }sub pp_ggrnam { unop(@_, "getgrnam") }sub pp_ggrgid { unop(@_, "getgrgid") }sub pp_lock { unop(@_, "lock") }sub pp_exists { my $self = shift; my($op, $cx) = @_; return $self->maybe_parens_func("exists", $self->pp_helem($op->first, 16), $cx, 16);}sub pp_delete { my $self = shift; my($op, $cx) = @_; my $arg; if ($op->private & OPpSLICE) { return $self->maybe_parens_func("delete", $self->pp_hslice($op->first, 16), $cx, 16); } else { return $self->maybe_parens_func("delete", $self->pp_helem($op->first, 16), $cx, 16); }}sub pp_require { my $self = shift; my($op, $cx) = @_; if (class($op) eq "UNOP" and $op->first->name eq "const" and $op->first->private & OPpCONST_BARE) { my $name = $self->const_sv($op->first)->PV; $name =~ s[/][::]g; $name =~ s/\.pm//g; return "require($name)"; } else { $self->unop($op, $cx, "require"); }}sub pp_scalar { my $self = shift; my($op, $cv) = @_; my $kid = $op->first; if (not null $kid->sibling) { # XXX Was a here-doc return $self->dquote($op); } $self->unop(@_, "scalar");}sub padval { my $self = shift; my $targ = shift; #cluck "curcv was undef" unless $self->{curcv}; return (($self->{'curcv'}->PADLIST->ARRAY)[1]->ARRAY)[$targ];}sub pp_refgen { my $self = shift; my($op, $cx) = @_; my $kid = $op->first; if ($kid->name eq "null") { $kid = $kid->first; if ($kid->name eq "anonlist" || $kid->name eq "anonhash") { my($pre, $post) = @{{"anonlist" => ["[","]"], "anonhash" => ["{","}"]}->{$kid->name}}; my($expr, @exprs); $kid = $kid->first->sibling; # skip pushmark for (; !null($kid); $kid = $kid->sibling) { $expr = $self->deparse($kid, 6); push @exprs, $expr; } return $pre . join(", ", @exprs) . $post; } elsif (!null($kid->sibling) and $kid->sibling->name eq "anoncode") { return "sub " . $self->deparse_sub($self->padval($kid->sibling->targ)); } elsif ($kid->name eq "pushmark") { my $sib_name = $kid->sibling->name; if ($sib_name =~ /^(pad|rv2)[ah]v$/ and not $kid->sibling->flags & OPf_REF) { # The @a in \(@a) isn't in ref context, but only when the # parens are there. return "\\(" . $self->deparse($kid->sibling, 1) . ")"; } elsif ($sib_name eq 'entersub') { my $text = $self->deparse($kid->sibling, 1); # Always show parens for \(&func()), but only with -p otherwise $text = "($text)" if $self->{'parens'} or $kid->sibling->private & OPpENTERSUB_AMPER; return "\\$text"; } } } $self->pfixop($op, $cx, "\\", 20);}sub pp_srefgen { pp_refgen(@_) }sub pp_readline { my $self = shift; my($op, $cx) = @_; my $kid = $op->first; $kid = $kid->first if $kid->name eq "rv2gv"; # <$fh> return "<" . $self->deparse($kid, 1) . ">";}# Unary operators that can occur as pseudo-listops inside double quotessub dq_unop { my $self = shift; my($op, $cx, $name, $prec, $flags) = (@_, 0, 0); my $kid; if ($op->flags & OPf_KIDS) { $kid = $op->first; # If there's more than one kid, the first is an ex-pushmark. $kid = $kid->sibling if not null $kid->sibling; return $self->maybe_parens_unop($name, $kid, $cx); } else { return $name . ($op->flags & OPf_SPECIAL ? "()" : ""); }}sub pp_ucfirst { dq_unop(@_, "ucfirst") }sub pp_lcfirst { dq_unop(@_, "lcfirst") }sub pp_uc { dq_unop(@_, "uc") }sub pp_lc { dq_unop(@_, "lc") }sub pp_quotemeta { maybe_targmy(@_, \&dq_unop, "quotemeta") }sub loopex { my $self = shift; my ($op, $cx, $name) = @_; if (class($op) eq "PVOP") { return "$name " . $op->pv; } elsif (class($op) eq "OP") { return $name; } elsif (class($op) eq "UNOP") { # Note -- loop exits are actually exempt from the # looks-like-a-func rule, but a few extra parens won't hurt return $self->maybe_parens_unop($name, $op->first, $cx); }}sub pp_last { loopex(@_, "last") }sub pp_next { loopex(@_, "next") }sub pp_redo { loopex(@_, "redo") }sub pp_goto { loopex(@_, "goto") }sub pp_dump { loopex(@_, "dump") }sub ftst { my $self = shift; my($op, $cx, $name) = @_; if (class($op) eq "UNOP") { # Genuine `-X' filetests are exempt from the LLAFR, but not # l?stat(); for the sake of clarity, give'em all parens return $self->maybe_parens_unop($name, $op->first, $cx); } elsif (class($op) eq "SVOP") { return $self->maybe_parens_func($name, $self->pp_gv($op, 1), $cx, 16); } else { # I don't think baseop filetests ever survive ck_ftst, but... return $name; }}sub pp_lstat { ftst(@_, "lstat") }sub pp_stat { ftst(@_, "stat") }sub pp_ftrread { ftst(@_, "-R") }sub pp_ftrwrite { ftst(@_, "-W") }sub pp_ftrexec { ftst(@_, "-X") }sub pp_fteread { ftst(@_, "-r") }sub pp_ftewrite { ftst(@_, "-r") }sub pp_fteexec { ftst(@_, "-r") }sub pp_ftis { ftst(@_, "-e") }sub pp_fteowned { ftst(@_, "-O") }sub pp_ftrowned { ftst(@_, "-o") }sub pp_ftzero { ftst(@_, "-z") }sub pp_ftsize { ftst(@_, "-s") }sub pp_ftmtime { ftst(@_, "-M") }sub pp_ftatime { ftst(@_, "-A") }sub pp_ftctime { ftst(@_, "-C") }sub pp_ftsock { ftst(@_, "-S") }sub pp_ftchr { ftst(@_, "-c") }sub pp_ftblk { ftst(@_, "-b") }sub pp_ftfile { ftst(@_, "-f") }sub pp_ftdir { ftst(@_, "-d") }sub pp_ftpipe { ftst(@_, "-p") }sub pp_ftlink { ftst(@_, "-l") }sub pp_ftsuid { ftst(@_, "-u") }sub pp_ftsgid { ftst(@_, "-g") }sub pp_ftsvtx { ftst(@_, "-k") }sub pp_fttty { ftst(@_, "-t") }sub pp_fttext { ftst(@_, "-T") }sub pp_ftbinary { ftst(@_, "-B") }sub SWAP_CHILDREN () { 1 }sub ASSIGN () { 2 } # has OP= variantmy(%left, %right);sub assoc_class { my $op = shift; my $name = $op->name; if ($name eq "concat" and $op->first->name eq "concat") { # avoid spurious `=' -- see comment in pp_concat return "concat"; } if ($name eq "null" and class($op) eq "UNOP" and $op->first->name =~ /^(and|x?or)$/ and null $op->first->sibling) { # Like all conditional constructs, OP_ANDs and OP_ORs are topped # with a null that's used as the common end point of the two # flows of control. For precedence purposes, ignore it. # (COND_EXPRs have these too, but we don't bother with # their associativity). return assoc_class($op->first); } return $name . ($op->flags & OPf_STACKED ? "=" : "");}# Left associative operators, like `+', for which# $a + $b + $c is equivalent to ($a + $b) + $cBEGIN { %left = ('multiply' => 19, 'i_multiply' => 19, 'divide' => 19, 'i_divide' => 19, 'modulo' => 19, 'i_modulo' => 19, 'repeat' => 19, 'add' => 18, 'i_add' => 18, 'subtract' => 18, 'i_subtract' => 18, 'concat' => 18, 'left_shift' => 17, 'right_shift' => 17, 'bit_and' => 13, 'bit_or' => 12, 'bit_xor' => 12, 'and' => 3, 'or' => 2, 'xor' => 2, );}sub deparse_binop_left { my $self = shift; my($op, $left, $prec) = @_; if ($left{assoc_class($op)} && $left{assoc_class($left)} and $left{assoc_class($op)} == $left{assoc_class($left)}) { return $self->deparse($left, $prec - .00001); } else { return $self->deparse($left, $prec); }}# Right associative operators, like `=', for which# $a = $b = $c is equivalent to $a = ($b = $c)BEGIN { %right = ('pow' => 22, 'sassign=' => 7, 'aassign=' => 7, 'multiply=' => 7, 'i_multiply=' => 7, 'divide=' => 7, 'i_divide=' => 7, 'modulo=' => 7, 'i_modulo=' => 7, 'repeat=' => 7, 'add=' => 7, 'i_add=' => 7, 'subtract=' => 7, 'i_subtract=' => 7, 'concat=' => 7, 'left_shift=' => 7, 'right_shift=' => 7, 'bit_and=' => 7, 'bit_or=' => 7, 'bit_xor=' => 7, 'andassign' => 7, 'orassign' => 7, );}sub deparse_binop_right { my $self = shift; my($op, $right, $prec) = @_; if ($right{assoc_class($op)} && $right{assoc_class($right)} and $right{assoc_class($op)} == $right{assoc_class($right)}) { return $self->deparse($right, $prec - .00001); } else { return $self->deparse($right, $prec); }}sub binop { my $self = shift; my ($op, $cx, $opname, $prec, $flags) = (@_, 0); my $left = $op->first; my $right = $op->last; my $eq = ""; if ($op->flags & OPf_STACKED && $flags & ASSIGN) { $eq = "="; $prec = 7; } if ($flags & SWAP_CHILDREN) { ($left, $right) = ($right, $left); } $left = $self->deparse_binop_left($op, $left, $prec); $right = $self->deparse_binop_right($op, $right, $prec); return $self->maybe_parens("$left $opname$eq $right", $cx, $prec);}sub pp_add { maybe_targmy(@_, \&binop, "+", 18, ASSIGN) }sub pp_multiply { maybe_targmy(@_, \&binop, "*", 19, ASSIGN) }sub pp_subtract { maybe_targmy(@_, \&binop, "-",18, ASSIGN) }sub pp_divide { maybe_targmy(@_, \&binop, "/", 19, ASSIGN) }sub pp_modulo { maybe_targmy(@_, \&binop, "%", 19, ASSIGN) }sub pp_i_add { maybe_targmy(@_, \&binop, "+", 18, ASSIGN) }sub pp_i_multiply { maybe_targmy(@_, \&binop, "*", 19, ASSIGN) }sub pp_i_subtract { maybe_targmy(@_, \&binop, "-", 18, ASSIGN) }sub pp_i_divide { maybe_targmy(@_, \&binop, "/", 19, ASSIGN) }sub pp_i_modulo { maybe_targmy(@_, \&binop, "%", 19, ASSIGN) }sub pp_pow { maybe_targmy(@_, \&binop, "**", 22, ASSIGN) }sub pp_left_shift { maybe_targmy(@_, \&binop, "<<", 17, ASSIGN) }sub pp_right_shift { maybe_targmy(@_, \&binop, ">>", 17, ASSIGN) }sub pp_bit_and { maybe_targmy(@_, \&binop, "&", 13, ASSIGN) }sub pp_bit_or { maybe_targmy(@_, \&binop, "|", 12, ASSIGN) }sub pp_bit_xor { maybe_targmy(@_, \&binop, "^", 12, ASSIGN) }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -