|
| 1 | +=begin pod |
| 2 | +
|
| 3 | +=TITLE class CallFrame |
| 4 | +
|
| 5 | +=SUBTITLE Capturing current frame state |
| 6 | +
|
| 7 | + class CallFrame { ... } |
| 8 | +
|
| 9 | +There's no way to instantiate a C<CallFrame>. Instead, it is captured from the current state of a program using the L<callframe> subroutine. |
| 10 | +
|
| 11 | + my $frame = callframe; |
| 12 | + say "The above line of code ran at {$frame.file}:{$frame.line}."; |
| 13 | +
|
| 14 | +With no arguments the callframe will give you frame information for the line calling C<callframe>. The file and line annotations will be identical to those in L<$?FILE> and L<$?LINE>. |
| 15 | +
|
| 16 | +You may, however, pass a number to C<callframe> to specify a different frame level. The current frame is level 0 (though level of the frame may be different, see L<level> for more information). A positive number will move upward through the levels of frame. A negative number will move downward into the C<callframe> method and class itself at the point at which they are running to construct this information for you. |
| 17 | +
|
| 18 | +The frames themselves do not necessarily match to method or subroutine calls. Perl constructs a frames for blocks and such as well, so if you need a callframe for a particular method call, do not assume it is a fixed number of levels up. |
| 19 | +
|
| 20 | +Each frame stores L<annotations>, including the L<file> and L<line> annotations, which have convenience methods for accessing those directly. You can also retrieve a reference to the code block of the currently executing frame using the L<code> method. The frame also captures all lexical variables stored with the frame, which are available by calling L<my> on the frame object. |
| 21 | +
|
| 22 | +Here's a short example that will find the calling routine and prints the package of the caller using the C<callframe> interface. |
| 23 | +
|
| 24 | + for 1..* -> $level { |
| 25 | + given callframe($level) { |
| 26 | + when CallFrame { |
| 27 | + next unless $frame.code ~~ Routine; |
| 28 | + say $frame.code.package; |
| 29 | + last; |
| 30 | + } |
| 31 | + default { |
| 32 | + say "no calling routine or method found"; |
| 33 | + last; |
| 34 | + } |
| 35 | + } |
| 36 | + } |
| 37 | +
|
| 38 | +If you just need to trace caller information, L<Backtrace> may provide a better means of getting information. L<CallFrame> contains more information about a specific frame, but provides a tedious interface for enumerating a call stack. |
| 39 | +
|
| 40 | +=head1 Methods |
| 41 | +
|
| 42 | +=head2 method code |
| 43 | +
|
| 44 | + method code(CallFrame:D:) |
| 45 | +
|
| 46 | +Return the callable code for the current block. When called on the object returned by C<callframe(0)>, this will be the same value found in L<&?BLOCK>. |
| 47 | +
|
| 48 | +=head2 method file |
| 49 | +
|
| 50 | + method file(CallFrame:D:) |
| 51 | +
|
| 52 | +This is a shortcut for looking up the C<file> annotation. Therefore, the following code prints C<True>. |
| 53 | +
|
| 54 | + my $frame = callframe(0); |
| 55 | + say $frame.file eq $frame.annotations<file>; |
| 56 | +
|
| 57 | +head2 method level |
| 58 | +
|
| 59 | + method level(CallFrame:D:) |
| 60 | +
|
| 61 | +Return the absolute level of the frame in the stack. This will usually be higher than 0 when calling C<callframe(0)>. Using a negative number to retrieve a frame less than 0 will result in an exception. |
| 62 | +
|
| 63 | +=head2 method line |
| 64 | +
|
| 65 | + method line(CallFrame:D:) |
| 66 | +
|
| 67 | +This is a shortcut for looking up the C<line> annotation. For example, the following two calls are identical. |
| 68 | +
|
| 69 | + say callframe(1).line; |
| 70 | + say callframe(1).annotations<line>; |
| 71 | +
|
| 72 | +=head2 method my |
| 73 | +
|
| 74 | + method my(CallFrame:D:) |
| 75 | +
|
| 76 | +Return a L<Hash> that names all the variables and their values associated with the lexical scope of the frame. |
| 77 | +
|
| 78 | + sub some-value { |
| 79 | + my $the-answer = 42; |
| 80 | + callframe(0); |
| 81 | + } |
| 82 | +
|
| 83 | + my $frame = some-value(); |
| 84 | + say $frame.my<$the-answer>; # 42 |
| 85 | +
|
| 86 | +=head1 Routines |
| 87 | +
|
| 88 | +=head2 sub callframe |
| 89 | +
|
| 90 | + sub callframe(Int $level = 0) |
| 91 | +
|
| 92 | +Returns a L<CallFrame> object for the given level. If no level is given, the default level is 0. Positive levels move up the frame stack and negative levels move down (into the call to C<callframe> and deeper). |
| 93 | +
|
| 94 | +Returns L<Mu> if there is no call information for the given level. (Negative levels may result in an exception.) |
| 95 | +
|
| 96 | +=end pod |
| 97 | + |
| 98 | +# vim: expandtab shiftwidth=4 ft=perl6 |
0 commit comments