Blame lib/Sub/Uplevel.pm

Packit cde0b4
package Sub::Uplevel;
Packit cde0b4
use 5.006;
Packit cde0b4
use strict;
Packit cde0b4
# ABSTRACT: apparently run a function in a higher stack frame
Packit cde0b4
Packit cde0b4
our $VERSION = '0.2800';
Packit cde0b4
Packit cde0b4
# Frame check global constant
Packit cde0b4
our $CHECK_FRAMES;
Packit cde0b4
BEGIN {
Packit cde0b4
  $CHECK_FRAMES = !! $CHECK_FRAMES;
Packit cde0b4
}
Packit cde0b4
use constant CHECK_FRAMES => $CHECK_FRAMES;
Packit cde0b4
Packit cde0b4
# We must override *CORE::GLOBAL::caller if it hasn't already been 
Packit cde0b4
# overridden or else Perl won't see our local override later.
Packit cde0b4
Packit cde0b4
if ( not defined *CORE::GLOBAL::caller{CODE} ) {
Packit cde0b4
  *CORE::GLOBAL::caller = \&_normal_caller;
Packit cde0b4
}
Packit cde0b4
Packit cde0b4
# modules to force reload if ":aggressive" is specified
Packit cde0b4
my @reload_list = qw/Exporter Exporter::Heavy/;
Packit cde0b4
Packit cde0b4
sub import {
Packit cde0b4
  no strict 'refs'; ## no critic
Packit cde0b4
  my ($class, @args) = @_;
Packit cde0b4
  for my $tag ( @args, 'uplevel' ) {
Packit cde0b4
    if ( $tag eq 'uplevel' ) {
Packit cde0b4
      my $caller = caller(0);
Packit cde0b4
      *{"$caller\::uplevel"} = \&uplevel;
Packit cde0b4
    }
Packit cde0b4
    elsif( $tag eq ':aggressive' ) {
Packit cde0b4
      _force_reload( @reload_list );
Packit cde0b4
    }
Packit cde0b4
    else {
Packit cde0b4
      die qq{"$tag" is not exported by the $class module\n}
Packit cde0b4
    }
Packit cde0b4
  }
Packit cde0b4
  return;
Packit cde0b4
}
Packit cde0b4
Packit cde0b4
sub _force_reload {
Packit cde0b4
  no warnings 'redefine';
Packit cde0b4
  local $^W = 0;
Packit cde0b4
  for my $m ( @_ ) {
Packit cde0b4
    $m =~ s{::}{/}g;
Packit cde0b4
    $m .= ".pm";
Packit cde0b4
    require $m if delete $INC{$m};
Packit cde0b4
  }
Packit cde0b4
}
Packit cde0b4
Packit cde0b4
#pod =head1 SYNOPSIS
Packit cde0b4
#pod
Packit cde0b4
#pod   use Sub::Uplevel;
Packit cde0b4
#pod
Packit cde0b4
#pod   sub foo {
Packit cde0b4
#pod       print join " - ", caller;
Packit cde0b4
#pod   }
Packit cde0b4
#pod
Packit cde0b4
#pod   sub bar {
Packit cde0b4
#pod       uplevel 1, \&foo;
Packit cde0b4
#pod   }
Packit cde0b4
#pod
Packit cde0b4
#pod   #line 11
Packit cde0b4
#pod   bar();    # main - foo.plx - 11
Packit cde0b4
#pod
Packit cde0b4
#pod =head1 DESCRIPTION
Packit cde0b4
#pod
Packit cde0b4
#pod Like Tcl's uplevel() function, but not quite so dangerous.  The idea
Packit cde0b4
#pod is just to fool caller().  All the really naughty bits of Tcl's
Packit cde0b4
#pod uplevel() are avoided.
Packit cde0b4
#pod
Packit cde0b4
#pod B<THIS IS NOT THE SORT OF THING YOU WANT TO DO EVERYDAY>
Packit cde0b4
#pod
Packit cde0b4
#pod =over 4
Packit cde0b4
#pod
Packit cde0b4
#pod =item B<uplevel>
Packit cde0b4
#pod
Packit cde0b4
#pod   uplevel $num_frames, \&func, @args;
Packit cde0b4
#pod
Packit cde0b4
#pod Makes the given function think it's being executed $num_frames higher
Packit cde0b4
#pod than the current stack level.  So when they use caller($frames) it
Packit cde0b4
#pod will actually give caller($frames + $num_frames) for them.
Packit cde0b4
#pod
Packit cde0b4
#pod C<uplevel(1, \&some_func, @_)> is effectively C<goto &some_func> but
Packit cde0b4
#pod you don't immediately exit the current subroutine.  So while you can't
Packit cde0b4
#pod do this:
Packit cde0b4
#pod
Packit cde0b4
#pod     sub wrapper {
Packit cde0b4
#pod         print "Before\n";
Packit cde0b4
#pod         goto &some_func;
Packit cde0b4
#pod         print "After\n";
Packit cde0b4
#pod     }
Packit cde0b4
#pod
Packit cde0b4
#pod you can do this:
Packit cde0b4
#pod
Packit cde0b4
#pod     sub wrapper {
Packit cde0b4
#pod         print "Before\n";
Packit cde0b4
#pod         my @out = uplevel 1, &some_func;
Packit cde0b4
#pod         print "After\n";
Packit cde0b4
#pod         return @out;
Packit cde0b4
#pod     }
Packit cde0b4
#pod
Packit cde0b4
#pod C<uplevel> has the ability to issue a warning if C<$num_frames> is more than
Packit cde0b4
#pod the current call stack depth, although this warning is disabled and compiled
Packit cde0b4
#pod out by default as the check is relatively expensive.
Packit cde0b4
#pod
Packit cde0b4
#pod To enable the check for debugging or testing, you should set the global
Packit cde0b4
#pod C<$Sub::Uplevel::CHECK_FRAMES> to true before loading Sub::Uplevel for the
Packit cde0b4
#pod first time as follows:
Packit cde0b4
#pod
Packit cde0b4
#pod     #!/usr/bin/perl
Packit cde0b4
#pod     
Packit cde0b4
#pod     BEGIN {
Packit cde0b4
#pod         $Sub::Uplevel::CHECK_FRAMES = 1;
Packit cde0b4
#pod     }
Packit cde0b4
#pod     use Sub::Uplevel;
Packit cde0b4
#pod
Packit cde0b4
#pod Setting or changing the global after the module has been loaded will have
Packit cde0b4
#pod no effect.
Packit cde0b4
#pod
Packit cde0b4
#pod =cut
Packit cde0b4
Packit cde0b4
# @Up_Frames -- uplevel stack
Packit cde0b4
# $Caller_Proxy -- whatever caller() override was in effect before uplevel
Packit cde0b4
our (@Up_Frames, $Caller_Proxy);
Packit cde0b4
Packit cde0b4
sub _apparent_stack_height {
Packit cde0b4
    my $height = 1; # start above this function 
Packit cde0b4
    while ( 1 ) {
Packit cde0b4
        last if ! defined scalar $Caller_Proxy->($height);
Packit cde0b4
        $height++;
Packit cde0b4
    }
Packit cde0b4
    return $height - 1; # subtract 1 for this function
Packit cde0b4
}
Packit cde0b4
Packit cde0b4
sub uplevel {
Packit cde0b4
    # Backwards compatible version of "no warnings 'redefine'"
Packit cde0b4
    my $old_W = $^W;
Packit cde0b4
    $^W = 0;
Packit cde0b4
Packit cde0b4
    # Update the caller proxy if the uplevel override isn't in effect
Packit cde0b4
    local $Caller_Proxy = *CORE::GLOBAL::caller{CODE}
Packit cde0b4
        if *CORE::GLOBAL::caller{CODE} != \&_uplevel_caller;
Packit cde0b4
    local *CORE::GLOBAL::caller = \&_uplevel_caller;
Packit cde0b4
Packit cde0b4
    # Restore old warnings state
Packit cde0b4
    $^W = $old_W;
Packit cde0b4
Packit cde0b4
    if ( CHECK_FRAMES and $_[0] >= _apparent_stack_height() ) {
Packit cde0b4
      require Carp;
Packit cde0b4
      Carp::carp("uplevel $_[0] is more than the caller stack");
Packit cde0b4
    }
Packit cde0b4
Packit cde0b4
    local @Up_Frames = (shift, @Up_Frames );
Packit cde0b4
Packit cde0b4
    my $function = shift;
Packit cde0b4
    return $function->(@_);
Packit cde0b4
}
Packit cde0b4
Packit cde0b4
sub _normal_caller (;$) { ## no critic Prototypes
Packit cde0b4
    my ($height) = @_;
Packit cde0b4
    $height++;
Packit cde0b4
    my @caller = CORE::caller($height);
Packit cde0b4
    if ( CORE::caller() eq 'DB' ) {
Packit cde0b4
        # Oops, redo picking up @DB::args
Packit cde0b4
        package DB;
Packit cde0b4
        @caller = CORE::caller($height);
Packit cde0b4
    }
Packit cde0b4
Packit cde0b4
    return if ! @caller;                  # empty
Packit cde0b4
    return $caller[0] if ! wantarray;     # scalar context
Packit cde0b4
    return @_ ? @caller : @caller[0..2];  # extra info or regular
Packit cde0b4
}
Packit cde0b4
Packit cde0b4
sub _uplevel_caller (;$) { ## no critic Prototypes
Packit cde0b4
    my $height = $_[0] || 0;
Packit cde0b4
Packit cde0b4
    # shortcut if no uplevels have been called
Packit cde0b4
    # always add +1 to CORE::caller (proxy caller function)
Packit cde0b4
    # to skip this function's caller
Packit cde0b4
    return $Caller_Proxy->( $height + 1 ) if ! @Up_Frames;
Packit cde0b4
Packit cde0b4
#pod =begin _private
Packit cde0b4
#pod
Packit cde0b4
#pod So it has to work like this:
Packit cde0b4
#pod
Packit cde0b4
#pod     Call stack               Actual     uplevel 1
Packit cde0b4
#pod CORE::GLOBAL::caller
Packit cde0b4
#pod Carp::short_error_loc           0
Packit cde0b4
#pod Carp::shortmess_heavy           1           0
Packit cde0b4
#pod Carp::croak                     2           1
Packit cde0b4
#pod try_croak                       3           2
Packit cde0b4
#pod uplevel                         4            
Packit cde0b4
#pod function_that_called_uplevel    5            
Packit cde0b4
#pod caller_we_want_to_see           6           3
Packit cde0b4
#pod its_caller                      7           4
Packit cde0b4
#pod
Packit cde0b4
#pod So when caller(X) winds up below uplevel(), it only has to use  
Packit cde0b4
#pod CORE::caller(X+1) (to skip CORE::GLOBAL::caller).  But when caller(X)
Packit cde0b4
#pod winds up no or above uplevel(), it's CORE::caller(X+1+uplevel+1).
Packit cde0b4
#pod
Packit cde0b4
#pod Which means I'm probably going to have to do something nasty like walk
Packit cde0b4
#pod up the call stack on each caller() to see if I'm going to wind up   
Packit cde0b4
#pod before or after Sub::Uplevel::uplevel().
Packit cde0b4
#pod
Packit cde0b4
#pod =end _private
Packit cde0b4
#pod
Packit cde0b4
#pod =begin _dagolden
Packit cde0b4
#pod
Packit cde0b4
#pod I found the description above a bit confusing.  Instead, this is the logic
Packit cde0b4
#pod that I found clearer when CORE::GLOBAL::caller is invoked and we have to
Packit cde0b4
#pod walk up the call stack:
Packit cde0b4
#pod
Packit cde0b4
#pod * if searching up to the requested height in the real call stack doesn't find
Packit cde0b4
#pod a call to uplevel, then we can return the result at that height in the
Packit cde0b4
#pod call stack
Packit cde0b4
#pod
Packit cde0b4
#pod * if we find a call to uplevel, we need to keep searching upwards beyond the
Packit cde0b4
#pod requested height at least by the amount of upleveling requested for that
Packit cde0b4
#pod call to uplevel (from the Up_Frames stack set during the uplevel call)
Packit cde0b4
#pod
Packit cde0b4
#pod * additionally, we need to hide the uplevel subroutine call, too, so we search
Packit cde0b4
#pod upwards one more level for each call to uplevel
Packit cde0b4
#pod
Packit cde0b4
#pod * when we've reached the top of the search, we want to return that frame
Packit cde0b4
#pod in the call stack, i.e. the requested height plus any uplevel adjustments
Packit cde0b4
#pod found during the search
Packit cde0b4
#pod
Packit cde0b4
#pod =end _dagolden
Packit cde0b4
#pod
Packit cde0b4
#pod =cut
Packit cde0b4
Packit cde0b4
    my $saw_uplevel = 0;
Packit cde0b4
    my $adjust = 0;
Packit cde0b4
Packit cde0b4
    # walk up the call stack to fight the right package level to return;
Packit cde0b4
    # look one higher than requested for each call to uplevel found
Packit cde0b4
    # and adjust by the amount found in the Up_Frames stack for that call.
Packit cde0b4
    # We *must* use CORE::caller here since we need the real stack not what 
Packit cde0b4
    # some other override says the stack looks like, just in case that other
Packit cde0b4
    # override breaks things in some horrible way
Packit cde0b4
    my $test_caller;
Packit cde0b4
    for ( my $up = 0; $up <= $height + $adjust; $up++ ) {
Packit cde0b4
        $test_caller = scalar CORE::caller($up + 1);
Packit cde0b4
        if( $test_caller && $test_caller eq __PACKAGE__ ) {
Packit cde0b4
            # add one for each uplevel call seen
Packit cde0b4
            # and look into the uplevel stack for the offset
Packit cde0b4
            $adjust += 1 + $Up_Frames[$saw_uplevel];
Packit cde0b4
            $saw_uplevel++;
Packit cde0b4
        }
Packit cde0b4
    }
Packit cde0b4
Packit cde0b4
    # For returning values, we pass through the call to the proxy caller
Packit cde0b4
    # function, just at a higher stack level
Packit cde0b4
    my @caller = $Caller_Proxy->($height + $adjust + 1);
Packit cde0b4
    if ( CORE::caller() eq 'DB' ) {
Packit cde0b4
        # Oops, redo picking up @DB::args
Packit cde0b4
        package DB;
Packit cde0b4
        @caller = $Sub::Uplevel::Caller_Proxy->($height + $adjust + 1);
Packit cde0b4
    }
Packit cde0b4
Packit cde0b4
    return if ! @caller;                  # empty
Packit cde0b4
    return $caller[0] if ! wantarray;     # scalar context
Packit cde0b4
    return @_ ? @caller : @caller[0..2];  # extra info or regular
Packit cde0b4
}
Packit cde0b4
Packit cde0b4
#pod =back
Packit cde0b4
#pod
Packit cde0b4
#pod =head1 EXAMPLE
Packit cde0b4
#pod
Packit cde0b4
#pod The main reason I wrote this module is so I could write wrappers
Packit cde0b4
#pod around functions and they wouldn't be aware they've been wrapped.
Packit cde0b4
#pod
Packit cde0b4
#pod     use Sub::Uplevel;
Packit cde0b4
#pod
Packit cde0b4
#pod     my $original_foo = \&foo;
Packit cde0b4
#pod
Packit cde0b4
#pod     *foo = sub {
Packit cde0b4
#pod         my @output = uplevel 1, $original_foo;
Packit cde0b4
#pod         print "foo() returned:  @output";
Packit cde0b4
#pod         return @output;
Packit cde0b4
#pod     };
Packit cde0b4
#pod
Packit cde0b4
#pod If this code frightens you B<you should not use this module.>
Packit cde0b4
#pod
Packit cde0b4
#pod
Packit cde0b4
#pod =head1 BUGS and CAVEATS
Packit cde0b4
#pod
Packit cde0b4
#pod Well, the bad news is uplevel() is about 5 times slower than a normal
Packit cde0b4
#pod function call.  XS implementation anyone?  It also slows down every invocation
Packit cde0b4
#pod of caller(), regardless of whether uplevel() is in effect.
Packit cde0b4
#pod
Packit cde0b4
#pod Sub::Uplevel overrides CORE::GLOBAL::caller temporarily for the scope of
Packit cde0b4
#pod each uplevel call.  It does its best to work with any previously existing
Packit cde0b4
#pod CORE::GLOBAL::caller (both when Sub::Uplevel is first loaded and within 
Packit cde0b4
#pod each uplevel call) such as from Contextual::Return or Hook::LexWrap.  
Packit cde0b4
#pod
Packit cde0b4
#pod However, if you are routinely using multiple modules that override 
Packit cde0b4
#pod CORE::GLOBAL::caller, you are probably asking for trouble.
Packit cde0b4
#pod
Packit cde0b4
#pod You B<should> load Sub::Uplevel as early as possible within your program.  As
Packit cde0b4
#pod with all CORE::GLOBAL overloading, the overload will not affect modules that
Packit cde0b4
#pod have already been compiled prior to the overload.  One module that often is
Packit cde0b4
#pod unavoidably loaded prior to Sub::Uplevel is Exporter.  To forcibly recompile
Packit cde0b4
#pod Exporter (and Exporter::Heavy) after loading Sub::Uplevel, use it with the
Packit cde0b4
#pod ":aggressive" tag:
Packit cde0b4
#pod
Packit cde0b4
#pod     use Sub::Uplevel qw/:aggressive/;
Packit cde0b4
#pod
Packit cde0b4
#pod The private function C<Sub::Uplevel::_force_reload()> may be passed a list of
Packit cde0b4
#pod additional modules to reload if ":aggressive" is not aggressive enough.  
Packit cde0b4
#pod Reloading modules may break things, so only use this as a last resort.
Packit cde0b4
#pod
Packit cde0b4
#pod As of version 0.20, Sub::Uplevel requires Perl 5.6 or greater.
Packit cde0b4
#pod
Packit cde0b4
#pod =head1 HISTORY
Packit cde0b4
#pod
Packit cde0b4
#pod Those who do not learn from HISTORY are doomed to repeat it.
Packit cde0b4
#pod
Packit cde0b4
#pod The lesson here is simple:  Don't sit next to a Tcl programmer at the
Packit cde0b4
#pod dinner table.
Packit cde0b4
#pod
Packit cde0b4
#pod =head1 THANKS
Packit cde0b4
#pod
Packit cde0b4
#pod Thanks to Brent Welch, Damian Conway and Robin Houston.
Packit cde0b4
#pod
Packit cde0b4
#pod See http://www.perl.com/perl/misc/Artistic.html
Packit cde0b4
#pod
Packit cde0b4
#pod =head1 SEE ALSO
Packit cde0b4
#pod
Packit cde0b4
#pod PadWalker (for the similar idea with lexicals), Hook::LexWrap, 
Packit cde0b4
#pod Tcl's uplevel() at http://www.scriptics.com/man/tcl8.4/TclCmd/uplevel.htm
Packit cde0b4
#pod
Packit cde0b4
#pod =cut
Packit cde0b4
Packit cde0b4
1;
Packit cde0b4
Packit cde0b4
__END__
Packit cde0b4
Packit cde0b4
=pod
Packit cde0b4
Packit cde0b4
=encoding UTF-8
Packit cde0b4
Packit cde0b4
=head1 NAME
Packit cde0b4
Packit cde0b4
Sub::Uplevel - apparently run a function in a higher stack frame
Packit cde0b4
Packit cde0b4
=head1 VERSION
Packit cde0b4
Packit cde0b4
version 0.2800
Packit cde0b4
Packit cde0b4
=head1 SYNOPSIS
Packit cde0b4
Packit cde0b4
  use Sub::Uplevel;
Packit cde0b4
Packit cde0b4
  sub foo {
Packit cde0b4
      print join " - ", caller;
Packit cde0b4
  }
Packit cde0b4
Packit cde0b4
  sub bar {
Packit cde0b4
      uplevel 1, \&foo;
Packit cde0b4
  }
Packit cde0b4
Packit cde0b4
  #line 11
Packit cde0b4
  bar();    # main - foo.plx - 11
Packit cde0b4
Packit cde0b4
=head1 DESCRIPTION
Packit cde0b4
Packit cde0b4
Like Tcl's uplevel() function, but not quite so dangerous.  The idea
Packit cde0b4
is just to fool caller().  All the really naughty bits of Tcl's
Packit cde0b4
uplevel() are avoided.
Packit cde0b4
Packit cde0b4
B<THIS IS NOT THE SORT OF THING YOU WANT TO DO EVERYDAY>
Packit cde0b4
Packit cde0b4
=over 4
Packit cde0b4
Packit cde0b4
=item B<uplevel>
Packit cde0b4
Packit cde0b4
  uplevel $num_frames, \&func, @args;
Packit cde0b4
Packit cde0b4
Makes the given function think it's being executed $num_frames higher
Packit cde0b4
than the current stack level.  So when they use caller($frames) it
Packit cde0b4
will actually give caller($frames + $num_frames) for them.
Packit cde0b4
Packit cde0b4
C<uplevel(1, \&some_func, @_)> is effectively C<goto &some_func> but
Packit cde0b4
you don't immediately exit the current subroutine.  So while you can't
Packit cde0b4
do this:
Packit cde0b4
Packit cde0b4
    sub wrapper {
Packit cde0b4
        print "Before\n";
Packit cde0b4
        goto &some_func;
Packit cde0b4
        print "After\n";
Packit cde0b4
    }
Packit cde0b4
Packit cde0b4
you can do this:
Packit cde0b4
Packit cde0b4
    sub wrapper {
Packit cde0b4
        print "Before\n";
Packit cde0b4
        my @out = uplevel 1, &some_func;
Packit cde0b4
        print "After\n";
Packit cde0b4
        return @out;
Packit cde0b4
    }
Packit cde0b4
Packit cde0b4
C<uplevel> has the ability to issue a warning if C<$num_frames> is more than
Packit cde0b4
the current call stack depth, although this warning is disabled and compiled
Packit cde0b4
out by default as the check is relatively expensive.
Packit cde0b4
Packit cde0b4
To enable the check for debugging or testing, you should set the global
Packit cde0b4
C<$Sub::Uplevel::CHECK_FRAMES> to true before loading Sub::Uplevel for the
Packit cde0b4
first time as follows:
Packit cde0b4
Packit cde0b4
    #!/usr/bin/perl
Packit cde0b4
    
Packit cde0b4
    BEGIN {
Packit cde0b4
        $Sub::Uplevel::CHECK_FRAMES = 1;
Packit cde0b4
    }
Packit cde0b4
    use Sub::Uplevel;
Packit cde0b4
Packit cde0b4
Setting or changing the global after the module has been loaded will have
Packit cde0b4
no effect.
Packit cde0b4
Packit cde0b4
=begin _private
Packit cde0b4
Packit cde0b4
So it has to work like this:
Packit cde0b4
Packit cde0b4
    Call stack               Actual     uplevel 1
Packit cde0b4
CORE::GLOBAL::caller
Packit cde0b4
Carp::short_error_loc           0
Packit cde0b4
Carp::shortmess_heavy           1           0
Packit cde0b4
Carp::croak                     2           1
Packit cde0b4
try_croak                       3           2
Packit cde0b4
uplevel                         4            
Packit cde0b4
function_that_called_uplevel    5            
Packit cde0b4
caller_we_want_to_see           6           3
Packit cde0b4
its_caller                      7           4
Packit cde0b4
Packit cde0b4
So when caller(X) winds up below uplevel(), it only has to use  
Packit cde0b4
CORE::caller(X+1) (to skip CORE::GLOBAL::caller).  But when caller(X)
Packit cde0b4
winds up no or above uplevel(), it's CORE::caller(X+1+uplevel+1).
Packit cde0b4
Packit cde0b4
Which means I'm probably going to have to do something nasty like walk
Packit cde0b4
up the call stack on each caller() to see if I'm going to wind up   
Packit cde0b4
before or after Sub::Uplevel::uplevel().
Packit cde0b4
Packit cde0b4
=end _private
Packit cde0b4
Packit cde0b4
=begin _dagolden
Packit cde0b4
Packit cde0b4
I found the description above a bit confusing.  Instead, this is the logic
Packit cde0b4
that I found clearer when CORE::GLOBAL::caller is invoked and we have to
Packit cde0b4
walk up the call stack:
Packit cde0b4
Packit cde0b4
* if searching up to the requested height in the real call stack doesn't find
Packit cde0b4
a call to uplevel, then we can return the result at that height in the
Packit cde0b4
call stack
Packit cde0b4
Packit cde0b4
* if we find a call to uplevel, we need to keep searching upwards beyond the
Packit cde0b4
requested height at least by the amount of upleveling requested for that
Packit cde0b4
call to uplevel (from the Up_Frames stack set during the uplevel call)
Packit cde0b4
Packit cde0b4
* additionally, we need to hide the uplevel subroutine call, too, so we search
Packit cde0b4
upwards one more level for each call to uplevel
Packit cde0b4
Packit cde0b4
* when we've reached the top of the search, we want to return that frame
Packit cde0b4
in the call stack, i.e. the requested height plus any uplevel adjustments
Packit cde0b4
found during the search
Packit cde0b4
Packit cde0b4
=end _dagolden
Packit cde0b4
Packit cde0b4
=back
Packit cde0b4
Packit cde0b4
=head1 EXAMPLE
Packit cde0b4
Packit cde0b4
The main reason I wrote this module is so I could write wrappers
Packit cde0b4
around functions and they wouldn't be aware they've been wrapped.
Packit cde0b4
Packit cde0b4
    use Sub::Uplevel;
Packit cde0b4
Packit cde0b4
    my $original_foo = \&foo;
Packit cde0b4
Packit cde0b4
    *foo = sub {
Packit cde0b4
        my @output = uplevel 1, $original_foo;
Packit cde0b4
        print "foo() returned:  @output";
Packit cde0b4
        return @output;
Packit cde0b4
    };
Packit cde0b4
Packit cde0b4
If this code frightens you B<you should not use this module.>
Packit cde0b4
Packit cde0b4
=head1 BUGS and CAVEATS
Packit cde0b4
Packit cde0b4
Well, the bad news is uplevel() is about 5 times slower than a normal
Packit cde0b4
function call.  XS implementation anyone?  It also slows down every invocation
Packit cde0b4
of caller(), regardless of whether uplevel() is in effect.
Packit cde0b4
Packit cde0b4
Sub::Uplevel overrides CORE::GLOBAL::caller temporarily for the scope of
Packit cde0b4
each uplevel call.  It does its best to work with any previously existing
Packit cde0b4
CORE::GLOBAL::caller (both when Sub::Uplevel is first loaded and within 
Packit cde0b4
each uplevel call) such as from Contextual::Return or Hook::LexWrap.  
Packit cde0b4
Packit cde0b4
However, if you are routinely using multiple modules that override 
Packit cde0b4
CORE::GLOBAL::caller, you are probably asking for trouble.
Packit cde0b4
Packit cde0b4
You B<should> load Sub::Uplevel as early as possible within your program.  As
Packit cde0b4
with all CORE::GLOBAL overloading, the overload will not affect modules that
Packit cde0b4
have already been compiled prior to the overload.  One module that often is
Packit cde0b4
unavoidably loaded prior to Sub::Uplevel is Exporter.  To forcibly recompile
Packit cde0b4
Exporter (and Exporter::Heavy) after loading Sub::Uplevel, use it with the
Packit cde0b4
":aggressive" tag:
Packit cde0b4
Packit cde0b4
    use Sub::Uplevel qw/:aggressive/;
Packit cde0b4
Packit cde0b4
The private function C<Sub::Uplevel::_force_reload()> may be passed a list of
Packit cde0b4
additional modules to reload if ":aggressive" is not aggressive enough.  
Packit cde0b4
Reloading modules may break things, so only use this as a last resort.
Packit cde0b4
Packit cde0b4
As of version 0.20, Sub::Uplevel requires Perl 5.6 or greater.
Packit cde0b4
Packit cde0b4
=head1 HISTORY
Packit cde0b4
Packit cde0b4
Those who do not learn from HISTORY are doomed to repeat it.
Packit cde0b4
Packit cde0b4
The lesson here is simple:  Don't sit next to a Tcl programmer at the
Packit cde0b4
dinner table.
Packit cde0b4
Packit cde0b4
=head1 THANKS
Packit cde0b4
Packit cde0b4
Thanks to Brent Welch, Damian Conway and Robin Houston.
Packit cde0b4
Packit cde0b4
See http://www.perl.com/perl/misc/Artistic.html
Packit cde0b4
Packit cde0b4
=head1 SEE ALSO
Packit cde0b4
Packit cde0b4
PadWalker (for the similar idea with lexicals), Hook::LexWrap, 
Packit cde0b4
Tcl's uplevel() at http://www.scriptics.com/man/tcl8.4/TclCmd/uplevel.htm
Packit cde0b4
Packit cde0b4
=for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan
Packit cde0b4
Packit cde0b4
=head1 SUPPORT
Packit cde0b4
Packit cde0b4
=head2 Bugs / Feature Requests
Packit cde0b4
Packit cde0b4
Please report any bugs or feature requests through the issue tracker
Packit cde0b4
at L<https://github.com/Perl-Toolchain-Gang/Sub-Uplevel/issues>.
Packit cde0b4
You will be notified automatically of any progress on your issue.
Packit cde0b4
Packit cde0b4
=head2 Source Code
Packit cde0b4
Packit cde0b4
This is open source software.  The code repository is available for
Packit cde0b4
public review and contribution under the terms of the license.
Packit cde0b4
Packit cde0b4
L<https://github.com/Perl-Toolchain-Gang/Sub-Uplevel>
Packit cde0b4
Packit cde0b4
  git clone https://github.com/Perl-Toolchain-Gang/Sub-Uplevel.git
Packit cde0b4
Packit cde0b4
=head1 AUTHORS
Packit cde0b4
Packit cde0b4
=over 4
Packit cde0b4
Packit cde0b4
=item *
Packit cde0b4
Packit cde0b4
Michael Schwern <mschwern@cpan.org>
Packit cde0b4
Packit cde0b4
=item *
Packit cde0b4
Packit cde0b4
David Golden <dagolden@cpan.org>
Packit cde0b4
Packit cde0b4
=back
Packit cde0b4
Packit cde0b4
=head1 CONTRIBUTORS
Packit cde0b4
Packit cde0b4
=for stopwords Adam Kennedy Alexandr Ciornii David Golden Graham Ollis J. Nick Koston Michael Gray
Packit cde0b4
Packit cde0b4
=over 4
Packit cde0b4
Packit cde0b4
=item *
Packit cde0b4
Packit cde0b4
Adam Kennedy <adamk@cpan.org>
Packit cde0b4
Packit cde0b4
=item *
Packit cde0b4
Packit cde0b4
Alexandr Ciornii <alexchorny@gmail.com>
Packit cde0b4
Packit cde0b4
=item *
Packit cde0b4
Packit cde0b4
David Golden <xdg@xdg.me>
Packit cde0b4
Packit cde0b4
=item *
Packit cde0b4
Packit cde0b4
Graham Ollis <plicease@cpan.org>
Packit cde0b4
Packit cde0b4
=item *
Packit cde0b4
Packit cde0b4
J. Nick Koston <nick@cpanel.net>
Packit cde0b4
Packit cde0b4
=item *
Packit cde0b4
Packit cde0b4
Michael Gray <mg13@sanger.ac.uk>
Packit cde0b4
Packit cde0b4
=back
Packit cde0b4
Packit cde0b4
=head1 COPYRIGHT AND LICENSE
Packit cde0b4
Packit cde0b4
This software is copyright (c) 2017 by Michael Schwern and David Golden.
Packit cde0b4
Packit cde0b4
This is free software; you can redistribute it and/or modify it under
Packit cde0b4
the same terms as the Perl 5 programming language system itself.
Packit cde0b4
Packit cde0b4
=cut