+ Executes the code reference $callback with arguments @args as if it were
+ located at the subroutine stack frame pointed by $context, effectively
+ fooling "caller" and "die" into believing that the call actually
+ happened higher in the stack. The code is executed in the context of the
+ "uplevel" call, and what it returns is returned as-is by "uplevel".
+
+ sub target {
+ faker(@_);
+ }
+
+ sub faker {
+ uplevel {
+ map { 1 / $_ } @_;
+ } @_ => CALLER(1);
+ }
+
+ my @inverses = target(1, 2, 4); # @inverses contains (0, 0.5, 0.25)
+ my $count = target(1, 2, 4); # $count is 3
+
+ Note that if @args is empty, then the $context parameter is optional and
+ defaults to the current context ; otherwise it is mandatory.
+
+ Sub::Uplevel also implements a pure-Perl version of "uplevel". Both are
+ identical, with the following caveats :
+
+ * The Sub::Uplevel implementation of "uplevel" may execute a code
+ reference in the context of any upper stack frame. The Scope::Upper
+ version can only uplevel to a subroutine stack frame, and will croak
+ if you try to target an "eval" or a format.
+
+ * Exceptions thrown from the code called by this version of "uplevel"
+ will not be caught by "eval" blocks between the target frame and the
+ uplevel call, while they will for Sub::Uplevel's version. This means
+ that :
+
+ eval {
+ sub {
+ local $@;
+ eval {
+ sub {
+ uplevel { die 'wut' } CALLER(2); # for Scope::Upper
+ # uplevel(3, sub { die 'wut' }) # for Sub::Uplevel
+ }->();
+ };
+ print "inner block: $@";
+ $@ and exit;
+ }->();
+ };
+ print "outer block: $@";
+
+ will print "inner block: wut..." with Sub::Uplevel and "outer block:
+ wut..." with Scope::Upper.
+
+ * Sub::Uplevel globally overrides the Perl keyword "caller", while
+ Scope::Upper does not.
+
+ A simple wrapper lets you mimic the interface of "uplevel" in
+ Sub::Uplevel :
+
+ use Scope::Upper;
+
+ sub uplevel {
+ my $frame = shift;
+ my $code = shift;
+ my $cxt = Scope::Upper::CALLER($frame);
+ &Scope::Upper::uplevel($code => @_ => $cxt);
+ }
+
+ Albeit the three exceptions listed above, it passes all the tests of
+ Sub::Uplevel.
+
+ "uid"
+ my $uid = uid;
+ my $uid = uid $context;
+
+ Returns an unique identifier (UID) for the context (or dynamic scope)
+ pointed by $context, or for the current context if $context is omitted.
+ This UID will only be valid for the life time of the context it
+ represents, and another UID will be generated next time the same scope
+ is executed.
+
+ my $uid;
+
+ {
+ $uid = uid;
+ if ($uid eq uid()) { # yes, this is the same context
+ ...
+ }
+ {
+ if ($uid eq uid()) { # no, we are one scope below
+ ...
+ }
+ if ($uid eq uid(UP)) { # yes, UP points to the same scope as $uid
+ ...
+ }
+ }
+ }
+
+ # $uid is now invalid
+
+ {
+ if ($uid eq uid()) { # no, this is another block
+ ...
+ }
+ }
+
+ For example, each loop iteration gets its own UID :
+
+ my %uids;
+
+ for (1 .. 5) {
+ my $uid = uid;
+ $uids{$uid} = $_;
+ }
+
+ # %uids has 5 entries
+
+ The UIDs are not guaranteed to be numbers, so you must use the "eq"
+ operator to compare them.
+
+ To check whether a given UID is valid, you can use the "validate_uid"
+ function.
+
+ "validate_uid"
+ my $is_valid = validate_uid $uid;
+
+ Returns true if and only if $uid is the UID of a currently valid context
+ (that is, it designates a scope that is higher than the current one in
+ the call stack).
+
+ my $uid;
+
+ {
+ $uid = uid();
+ if (validate_uid($uid)) { # yes
+ ...
+ }
+ {
+ if (validate_uid($uid)) { # yes
+ ...
+ }
+ }
+ }
+
+ if (validate_uid($uid)) { # no
+ ...
+ }
+
+CONSTANTS
+ "SU_THREADSAFE"
+ True iff the module could have been built when thread-safety features.
+
+WORDS
+ Constants
+ "TOP"
+ my $top_context = TOP;
+
+ Returns the context that currently represents the highest scope.
+
+ "HERE"
+ my $current_context = HERE;
+
+ The context of the current scope.
+
+ Getting a context from a context
+ For any of those functions, $from is expected to be a context. When
+ omitted, it defaults to the current context.
+
+ "UP"
+ my $upper_context = UP;
+ my $upper_context = UP $from;
+
+ The context of the scope just above $from. If $from points to the
+ top-level scope in the current stack, then a warning is emitted and
+ $from is returned (see "DIAGNOSTICS" for details).
+
+ "SUB"
+ my $sub_context = SUB;
+ my $sub_context = SUB $from;
+
+ The context of the closest subroutine above $from. If $from already
+ designates a subroutine context, then it is returned as-is ; hence "SUB
+ SUB == SUB". If no subroutine context is present in the call stack, then
+ a warning is emitted and the current context is returned (see
+ "DIAGNOSTICS" for details).
+
+ "EVAL"
+ my $eval_context = EVAL;
+ my $eval_context = EVAL $from;
+
+ The context of the closest eval above $from. If $from already designates
+ an eval context, then it is returned as-is ; hence "EVAL EVAL == EVAL".
+ If no eval context is present in the call stack, then a warning is
+ emitted and the current context is returned (see "DIAGNOSTICS" for
+ details).
+
+ Getting a context from a level
+ Here, $level should denote a number of scopes above the current one.
+ When omitted, it defaults to 0 and those functions return the same
+ context as "HERE".
+
+ "SCOPE"
+ my $context = SCOPE;
+ my $context = SCOPE $level;
+
+ The $level-th upper context, regardless of its type. If $level points
+ above the top-level scope in the current stack, then a warning is
+ emitted and the top-level context is returned (see "DIAGNOSTICS" for
+ details).
+
+ "CALLER"
+ my $context = CALLER;
+ my $context = CALLER $level;
+
+ The context of the $level-th upper subroutine/eval/format. It kind of
+ corresponds to the context represented by "caller $level", but while
+ e.g. "caller 0" refers to the caller context, "CALLER 0" will refer to
+ the top scope in the current context. If $level points above the
+ top-level scope in the current stack, then a warning is emitted and the
+ top-level context is returned (see "DIAGNOSTICS" for details).
+
+ Examples
+ Where "reap" fires depending on the $cxt :
+
+ sub {
+ eval {
+ sub {
+ {
+ reap \&cleanup => $cxt;
+ ...
+ } # $cxt = SCOPE(0) = HERE
+ ...
+ }->(); # $cxt = SCOPE(1) = UP = SUB = CALLER(0)
+ ...
+ }; # $cxt = SCOPE(2) = UP UP = UP SUB = EVAL = CALLER(1)
+ ...
+ }->(); # $cxt = SCOPE(3) = SUB UP SUB = SUB EVAL = CALLER(2)
+ ...
+
+ Where "localize", "localize_elem" and "localize_delete" act depending on
+ the $cxt :
+
+ sub {
+ eval {
+ sub {
+ {
+ localize '$x' => 1 => $cxt;
+ # $cxt = SCOPE(0) = HERE
+ ...
+ }
+ # $cxt = SCOPE(1) = UP = SUB = CALLER(0)
+ ...
+ }->();
+ # $cxt = SCOPE(2) = UP UP = UP SUB = EVAL = CALLER(1)
+ ...
+ };
+ # $cxt = SCOPE(3) = SUB UP SUB = SUB EVAL = CALLER(2)
+ ...
+ }->();
+ # $cxt = SCOPE(4), UP SUB UP SUB = UP SUB EVAL = UP CALLER(2) = TOP
+ ...
+
+ Where "unwind", "yield", "want_at", "context_info" and "uplevel" point
+ to depending on the $cxt:
+
+ sub {
+ eval {
+ sub {
+ {
+ unwind @things => $cxt; # or yield @things => $cxt
+ # or uplevel { ... } $cxt
+ ...
+ }
+ ...
+ }->(); # $cxt = SCOPE(0) = SCOPE(1) = HERE = UP = SUB = CALLER(0)
+ ...
+ }; # $cxt = SCOPE(2) = UP UP = UP SUB = EVAL = CALLER(1) (*)
+ ...
+ }->(); # $cxt = SCOPE(3) = SUB UP SUB = SUB EVAL = CALLER(2)
+ ...
+
+ # (*) Note that uplevel() will croak if you pass that scope frame,
+ # because it cannot target eval scopes.
+
+DIAGNOSTICS
+ "Cannot target a scope outside of the current stack"
+ This warning is emitted when "UP", "SCOPE" or "CALLER" end up pointing
+ to a context that is above the top-level context of the current stack.
+ It indicates that you tried to go higher than the main scope, or to
+ point across a "DESTROY" method, a signal handler, an overloaded or tied
+ method call, a "require" statement or a "sort" callback. In this case,
+ the resulting context is the highest reachable one.
+
+ "No targetable %s scope in the current stack"
+ This warning is emitted when you ask for an "EVAL" or "SUB" context and
+ no such scope can be found in the call stack. The resulting context is
+ the current one.