📄 deparse.pm
字号:
sub pp_eq { binop(@_, "==", 14) }sub pp_ne { binop(@_, "!=", 14) }sub pp_lt { binop(@_, "<", 15) }sub pp_gt { binop(@_, ">", 15) }sub pp_ge { binop(@_, ">=", 15) }sub pp_le { binop(@_, "<=", 15) }sub pp_ncmp { binop(@_, "<=>", 14) }sub pp_i_eq { binop(@_, "==", 14) }sub pp_i_ne { binop(@_, "!=", 14) }sub pp_i_lt { binop(@_, "<", 15) }sub pp_i_gt { binop(@_, ">", 15) }sub pp_i_ge { binop(@_, ">=", 15) }sub pp_i_le { binop(@_, "<=", 15) }sub pp_i_ncmp { binop(@_, "<=>", 14) }sub pp_seq { binop(@_, "eq", 14) }sub pp_sne { binop(@_, "ne", 14) }sub pp_slt { binop(@_, "lt", 15) }sub pp_sgt { binop(@_, "gt", 15) }sub pp_sge { binop(@_, "ge", 15) }sub pp_sle { binop(@_, "le", 15) }sub pp_scmp { binop(@_, "cmp", 14) }sub pp_sassign { binop(@_, "=", 7, SWAP_CHILDREN) }sub pp_aassign { binop(@_, "=", 7, SWAP_CHILDREN) }# `.' is special because concats-of-concats are optimized to save copying# by making all but the first concat stacked. The effect is as if the# programmer had written `($a . $b) .= $c', except legal.sub pp_concat { maybe_targmy(@_, \&real_concat) }sub real_concat { my $self = shift; my($op, $cx) = @_; my $left = $op->first; my $right = $op->last; my $eq = ""; my $prec = 18; if ($op->flags & OPf_STACKED and $op->first->name ne "concat") { $eq = "="; $prec = 7; } $left = $self->deparse_binop_left($op, $left, $prec); $right = $self->deparse_binop_right($op, $right, $prec); return $self->maybe_parens("$left .$eq $right", $cx, $prec);}# `x' is weird when the left arg is a listsub pp_repeat { my $self = shift; my($op, $cx) = @_; my $left = $op->first; my $right = $op->last; my $eq = ""; my $prec = 19; if ($op->flags & OPf_STACKED) { $eq = "="; $prec = 7; } if (null($right)) { # list repeat; count is inside left-side ex-list my $kid = $left->first->sibling; # skip pushmark my @exprs; for (; !null($kid->sibling); $kid = $kid->sibling) { push @exprs, $self->deparse($kid, 6); } $right = $kid; $left = "(" . join(", ", @exprs). ")"; } else { $left = $self->deparse_binop_left($op, $left, $prec); } $right = $self->deparse_binop_right($op, $right, $prec); return $self->maybe_parens("$left x$eq $right", $cx, $prec);}sub range { my $self = shift; my ($op, $cx, $type) = @_; my $left = $op->first; my $right = $left->sibling; $left = $self->deparse($left, 9); $right = $self->deparse($right, 9); return $self->maybe_parens("$left $type $right", $cx, 9);}sub pp_flop { my $self = shift; my($op, $cx) = @_; my $flip = $op->first; my $type = ($flip->flags & OPf_SPECIAL) ? "..." : ".."; return $self->range($flip->first, $cx, $type);}# one-line while/until is handled in pp_leavesub logop { my $self = shift; my ($op, $cx, $lowop, $lowprec, $highop, $highprec, $blockname) = @_; my $left = $op->first; my $right = $op->first->sibling; if ($cx == 0 and is_scope($right) and $blockname and $self->{'expand'} < 7) { # if ($a) {$b} $left = $self->deparse($left, 1); $right = $self->deparse($right, 0); return "$blockname ($left) {\n\t$right\n\b}\cK"; } elsif ($cx == 0 and $blockname and not $self->{'parens'} and $self->{'expand'} < 7) { # $b if $a $right = $self->deparse($right, 1); $left = $self->deparse($left, 1); return "$right $blockname $left"; } elsif ($cx > $lowprec and $highop) { # $a && $b $left = $self->deparse_binop_left($op, $left, $highprec); $right = $self->deparse_binop_right($op, $right, $highprec); return $self->maybe_parens("$left $highop $right", $cx, $highprec); } else { # $a and $b $left = $self->deparse_binop_left($op, $left, $lowprec); $right = $self->deparse_binop_right($op, $right, $lowprec); return $self->maybe_parens("$left $lowop $right", $cx, $lowprec); }}sub pp_and { logop(@_, "and", 3, "&&", 11, "if") }sub pp_or { logop(@_, "or", 2, "||", 10, "unless") }# xor is syntactically a logop, but it's really a binop (contrary to# old versions of opcode.pl). Syntax is what matters here.sub pp_xor { logop(@_, "xor", 2, "", 0, "") }sub logassignop { my $self = shift; my ($op, $cx, $opname) = @_; my $left = $op->first; my $right = $op->first->sibling->first; # skip sassign $left = $self->deparse($left, 7); $right = $self->deparse($right, 7); return $self->maybe_parens("$left $opname $right", $cx, 7);}sub pp_andassign { logassignop(@_, "&&=") }sub pp_orassign { logassignop(@_, "||=") }sub listop { my $self = shift; my($op, $cx, $name) = @_; my(@exprs); my $parens = ($cx >= 5) || $self->{'parens'}; my $kid = $op->first->sibling; return $name if null $kid; my $first = $self->deparse($kid, 6); $first = "+$first" if not $parens and substr($first, 0, 1) eq "("; push @exprs, $first; $kid = $kid->sibling; for (; !null($kid); $kid = $kid->sibling) { push @exprs, $self->deparse($kid, 6); } if ($parens) { return "$name(" . join(", ", @exprs) . ")"; } else { return "$name " . join(", ", @exprs); }}sub pp_bless { listop(@_, "bless") }sub pp_atan2 { maybe_targmy(@_, \&listop, "atan2") }sub pp_substr { maybe_local(@_, listop(@_, "substr")) }sub pp_vec { maybe_local(@_, listop(@_, "vec")) }sub pp_index { maybe_targmy(@_, \&listop, "index") }sub pp_rindex { maybe_targmy(@_, \&listop, "rindex") }sub pp_sprintf { maybe_targmy(@_, \&listop, "sprintf") }sub pp_formline { listop(@_, "formline") } # see also deparse_formatsub pp_crypt { maybe_targmy(@_, \&listop, "crypt") }sub pp_unpack { listop(@_, "unpack") }sub pp_pack { listop(@_, "pack") }sub pp_join { maybe_targmy(@_, \&listop, "join") }sub pp_splice { listop(@_, "splice") }sub pp_push { maybe_targmy(@_, \&listop, "push") }sub pp_unshift { maybe_targmy(@_, \&listop, "unshift") }sub pp_reverse { listop(@_, "reverse") }sub pp_warn { listop(@_, "warn") }sub pp_die { listop(@_, "die") }# Actually, return is exempt from the LLAFR (see examples in this very# module!), but for consistency's sake, ignore that factsub pp_return { listop(@_, "return") }sub pp_open { listop(@_, "open") }sub pp_pipe_op { listop(@_, "pipe") }sub pp_tie { listop(@_, "tie") }sub pp_binmode { listop(@_, "binmode") }sub pp_dbmopen { listop(@_, "dbmopen") }sub pp_sselect { listop(@_, "select") }sub pp_select { listop(@_, "select") }sub pp_read { listop(@_, "read") }sub pp_sysopen { listop(@_, "sysopen") }sub pp_sysseek { listop(@_, "sysseek") }sub pp_sysread { listop(@_, "sysread") }sub pp_syswrite { listop(@_, "syswrite") }sub pp_send { listop(@_, "send") }sub pp_recv { listop(@_, "recv") }sub pp_seek { listop(@_, "seek") }sub pp_fcntl { listop(@_, "fcntl") }sub pp_ioctl { listop(@_, "ioctl") }sub pp_flock { maybe_targmy(@_, \&listop, "flock") }sub pp_socket { listop(@_, "socket") }sub pp_sockpair { listop(@_, "sockpair") }sub pp_bind { listop(@_, "bind") }sub pp_connect { listop(@_, "connect") }sub pp_listen { listop(@_, "listen") }sub pp_accept { listop(@_, "accept") }sub pp_shutdown { listop(@_, "shutdown") }sub pp_gsockopt { listop(@_, "getsockopt") }sub pp_ssockopt { listop(@_, "setsockopt") }sub pp_chown { maybe_targmy(@_, \&listop, "chown") }sub pp_unlink { maybe_targmy(@_, \&listop, "unlink") }sub pp_chmod { maybe_targmy(@_, \&listop, "chmod") }sub pp_utime { maybe_targmy(@_, \&listop, "utime") }sub pp_rename { maybe_targmy(@_, \&listop, "rename") }sub pp_link { maybe_targmy(@_, \&listop, "link") }sub pp_symlink { maybe_targmy(@_, \&listop, "symlink") }sub pp_mkdir { maybe_targmy(@_, \&listop, "mkdir") }sub pp_open_dir { listop(@_, "opendir") }sub pp_seekdir { listop(@_, "seekdir") }sub pp_waitpid { maybe_targmy(@_, \&listop, "waitpid") }sub pp_system { maybe_targmy(@_, \&listop, "system") }sub pp_exec { maybe_targmy(@_, \&listop, "exec") }sub pp_kill { maybe_targmy(@_, \&listop, "kill") }sub pp_setpgrp { maybe_targmy(@_, \&listop, "setpgrp") }sub pp_getpriority { maybe_targmy(@_, \&listop, "getpriority") }sub pp_setpriority { maybe_targmy(@_, \&listop, "setpriority") }sub pp_shmget { listop(@_, "shmget") }sub pp_shmctl { listop(@_, "shmctl") }sub pp_shmread { listop(@_, "shmread") }sub pp_shmwrite { listop(@_, "shmwrite") }sub pp_msgget { listop(@_, "msgget") }sub pp_msgctl { listop(@_, "msgctl") }sub pp_msgsnd { listop(@_, "msgsnd") }sub pp_msgrcv { listop(@_, "msgrcv") }sub pp_semget { listop(@_, "semget") }sub pp_semctl { listop(@_, "semctl") }sub pp_semop { listop(@_, "semop") }sub pp_ghbyaddr { listop(@_, "gethostbyaddr") }sub pp_gnbyaddr { listop(@_, "getnetbyaddr") }sub pp_gpbynumber { listop(@_, "getprotobynumber") }sub pp_gsbyname { listop(@_, "getservbyname") }sub pp_gsbyport { listop(@_, "getservbyport") }sub pp_syscall { listop(@_, "syscall") }sub pp_glob { my $self = shift; my($op, $cx) = @_; my $text = $self->dq($op->first->sibling); # skip pushmark if ($text =~ /^\$?(\w|::|\`)+$/ # could look like a readline or $text =~ /[<>]/) { return 'glob(' . single_delim('qq', '"', $text) . ')'; } else { return '<' . $text . '>'; }}# Truncate is special because OPf_SPECIAL makes a bareword first arg# be a filehandle. This could probably be better fixed in the core# by moving the GV lookup into ck_truc.sub pp_truncate { my $self = shift; my($op, $cx) = @_; my(@exprs); my $parens = ($cx >= 5) || $self->{'parens'}; my $kid = $op->first->sibling; my $fh; if ($op->flags & OPf_SPECIAL) { # $kid is an OP_CONST $fh = $self->const_sv($kid)->PV; } else { $fh = $self->deparse($kid, 6); $fh = "+$fh" if not $parens and substr($fh, 0, 1) eq "("; } my $len = $self->deparse($kid->sibling, 6); if ($parens) { return "truncate($fh, $len)"; } else { return "truncate $fh, $len"; }}sub indirop { my $self = shift; my($op, $cx, $name) = @_; my($expr, @exprs); my $kid = $op->first->sibling; my $indir = ""; if ($op->flags & OPf_STACKED) { $indir = $kid; $indir = $indir->first; # skip rv2gv if (is_scope($indir)) { $indir = "{" . $self->deparse($indir, 0) . "}"; } else { $indir = $self->deparse($indir, 24); } $indir = $indir . " "; $kid = $kid->sibling; } for (; !null($kid); $kid = $kid->sibling) { $expr = $self->deparse($kid, 6); push @exprs, $expr; } return $self->maybe_parens_func($name, $indir . join(", ", @exprs), $cx, 5);}sub pp_prtf { indirop(@_, "printf") }sub pp_print { indirop(@_, "print") }sub pp_sort { indirop(@_, "sort") }sub mapop { my $self = shift; my($op, $cx, $name) = @_; my($expr, @exprs); my $kid = $op->first; # this is the (map|grep)start $kid = $kid->first->sibling; # skip a pushmark my $code = $kid->first; # skip a null if (is_scope $code) { $code = "{" . $self->deparse($code, 0) . "} "; } else { $code = $self->deparse($code, 24) . ", "; } $kid = $kid->sibling; for (; !null($kid); $kid = $kid->sibling) { $expr = $self->deparse($kid, 6); push @exprs, $expr if $expr; } return $self->maybe_parens_func($name, $code . join(", ", @exprs), $cx, 5);}sub pp_mapwhile { mapop(@_, "map") } sub pp_grepwhile { mapop(@_, "grep") } sub pp_list { my $self = shift; my($op, $cx) = @_; my($expr, @exprs); my $kid = $op->first->sibling; # skip pushmark my $lop; my $local = "either"; # could be local(...) or my(...) for ($lop = $kid; !null($lop); $lop = $lop->sibling) { # This assumes that no other private flags equal 128, and that # OPs that store things other than flags in their op_private, # like OP_AELEMFAST, won't be immediate children of a list. unless ($lop->private & OPpLVAL_INTRO or $lop->name eq "undef") { $local = ""; # or not last; } if ($lop->name =~ /^pad[ash]v$/) { # my() ($local = "", last) if $local eq "local"; $local = "my"; } elsif ($lop->name ne "undef") { # local() ($local = "", last) if $local eq "my"; $local = "local"; } } $local = "" if $local eq "either"; # no point if it's all undefs return $self->deparse($kid, $cx) if null $kid->sibling and not $local; for (; !null($kid); $kid = $kid->sibling) { if ($local) { if (class($kid) eq "UNOP" and $kid->first->name eq "gvsv") { $lop = $kid->first; } else { $lop = $kid; } $self->{'avoid_local'}{$$lop}++; $expr = $self->deparse($kid, 6); delete $self->{'avoid_local'}{$$lop}; } else { $expr = $self->deparse($kid, 6); } push @exprs, $expr; } if ($local) { return "$local(" . join(", ", @exprs) . ")"; } else { return $self->maybe_parens( join(", ", @exprs), $cx, 6); }}sub is_ifelse_cont { my $op = shift; return ($op->name eq "null" and class($op) eq "UNOP" and $op->first->name =~ /^(and|cond_expr)$/ and is_scope($op->first->first->sibling));}sub pp_cond_expr { my $self = shift; my($op, $cx) = @_; my $cond = $op->first; my $true = $cond->sibling; my $false = $true->sibling; my $cuddle = $self->{'cuddle'}; unless ($cx == 0 and (is_scope($true) and $true->name ne "null") and (is_scope($false) || is_ifelse_cont($false)) and $self->{'expand'} < 7) { $cond = $self->deparse($cond, 8); $true = $self->deparse($true, 8); $false = $self->deparse($false, 8); return $self->maybe_parens("$cond ? $true : $false", $cx, 8); } $cond = $self->deparse($cond, 1); $true = $self->deparse($true, 0); my $head = "if ($cond) {\n\t$true\n\b}"; my @elsifs; while (!null($false) and is_ifelse_cont($false)) { my $newop = $false->first; my $newcond = $newop->first; my $newtrue = $newcond->sibling; $false = $newtrue->sibling; # last in chain is OP_AND => no else $newcond = $self->deparse($newcond, 1); $newtrue = $self->deparse($newtrue, 0); push @elsifs, "elsif ($newcond) {\n\t$newtrue\n\b}"; } if (!null($false)) { $false = $cuddle . "else {\n\t" . $self->deparse($false, 0) . "\n\b}\cK"; } else { $false = "\cK"; } return $head . join($cuddle, "", @elsifs) . $false; }sub loop_common { my $self = shift; my($op, $cx, $init) = @_; my $enter = $op->first; my $kid = $enter->sibling; local($self->{'curstash'}) = $self->{'curstash'}; my $head = "";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -