PPCODE:
SU_DOPOPTOCX(CXt_EVAL);
+void
+CALLER(...)
+PROTOTYPE: ;$
+PREINIT:
+ I32 cxix = cxstack_ix, caller = 0, level = 0;
+PPCODE:
+ if (items) {
+ SV *csv = ST(0);
+ if (SvOK(csv))
+ caller = SvIV(csv);
+ }
+ cxix = cxstack_ix;
+ while (cxix > 0) {
+ PERL_CONTEXT *cx = cxstack + cxix--;
+ switch (CxTYPE(cx)) {
+ case CXt_SUB:
+ case CXt_EVAL:
+ case CXt_FORMAT:
+ --caller;
+ if (caller < 0)
+ goto done;
+ break;
+ }
+ ++level;
+ }
+done:
+ ST(0) = sv_2mortal(newSViv(level));
+ XSRETURN(1);
+
void
reap(SV *hook, ...)
PROTOTYPE: &;$
If C<$from> is omitted in any of those functions, the current level is used as the reference level.
+=head2 C<CALLER $stack>
+
+The level corresponding to the stack referenced by C<caller $stack>.
+
=head1 EXPORT
The functions L</reap>, L</localize>, L</localize_elem>, L</localize_delete> and L</unwind> are only exported on request, either individually or by the tags C<':funcs'> and C<':all'>.
-Same goes for the words L</TOP>, L</HERE>, L</UP>, L</DOWN>, L</SUB> and L</EVAL> that are only exported on request, individually or by the tags C<':words'> and C<':all'>.
+Same goes for the words L</TOP>, L</HERE>, L</UP>, L</DOWN>, L</SUB>, L</EVAL> and L</CALLER> that are only exported on request, individually or by the tags C<':words'> and C<':all'>.
=cut
our @EXPORT = ();
our %EXPORT_TAGS = (
funcs => [ qw/reap localize localize_elem localize_delete unwind/ ],
- words => [ qw/TOP HERE UP DOWN SUB EVAL/ ],
+ words => [ qw/TOP HERE UP DOWN SUB EVAL CALLER/ ],
);
our @EXPORT_OK = map { @$_ } values %EXPORT_TAGS;
$EXPORT_TAGS{'all'} = [ @EXPORT_OK ];
use strict;
use warnings;
-use Test::More tests => 11;
+use Test::More tests => 12;
require Scope::Upper;
-for (qw/reap localize localize_elem localize_delete unwind TOP HERE UP DOWN SUB EVAL/) {
+for (qw/reap localize localize_elem localize_delete unwind TOP HERE UP DOWN SUB EVAL CALLER/) {
eval { Scope::Upper->import($_) };
is($@, '', 'import ' . $_);
}
use strict;
use warnings;
-use Test::More tests => 33;
+use Test::More tests => 46;
use Scope::Upper qw/:words/;
}
};
} while (0);
+
+{
+ is CALLER, 1, '{ } : caller';
+ is CALLER(0), 1, '{ } : caller 0';
+ is CALLER(1), 1, '{ } : caller 1';
+ sub {
+ is CALLER, 0, '{ sub { } } : caller';
+ is CALLER(0), 0, '{ sub { } } : caller 0';
+ is CALLER(1), 2, '{ sub { } } : caller 1';
+ for (1) {
+ is CALLER, 1, '{ sub { for { } } } : caller';
+ is CALLER(0), 1, '{ sub { for { } } } : caller 0';
+ is CALLER(1), 3, '{ sub { for { } } } : caller 1';
+ eval {
+ is CALLER, 0, '{ sub { for { eval { } } } } : caller';
+ is CALLER(0), 0, '{ sub { for { eval { } } } } : caller 0';
+ is CALLER(1), 2, '{ sub { for { eval { } } } } : caller 1';
+ is CALLER(2), 4, '{ sub { for { eval { } } } } : caller 2';
+ }
+ }
+ }->();
+}