Skip to content

Commit 081331e

Browse files
author
Brock Wilcox
committed
Initial phaser doc, from S04
1 parent cc397c0 commit 081331e

File tree

1 file changed

+249
-0
lines changed

1 file changed

+249
-0
lines changed

doc/Language/phasers.pod

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
=begin pod
2+
3+
=TITLE Phasers
4+
5+
=SUBTITLE Execution phases
6+
7+
The lifetime (execution timeline) of a program is broken up into phases. A
8+
I<phaser> is a block of code called during a specific execution phase.
9+
10+
=head1 Phasers
11+
12+
A phaser block is just a trait of the closure containing it, and is
13+
automatically called at the appropriate moment. These auto-called blocks are
14+
known as I<phasers>, since they generally mark the transition from one phase of
15+
computing to another. For instance, a C<CHECK> block is called at the end of
16+
compiling a compilation unit. Other kinds of phasers can be installed as well;
17+
these are automatically called at various times as appropriate, and some of
18+
them respond to various control exceptions and exit values.
19+
20+
Here is a summary:
21+
22+
BEGIN {...} # * at compile time, ASAP, only ever runs once
23+
CHECK {...} # * at compile time, ALAP, only ever runs once
24+
LINK {...} # * at link time, ALAP, only ever runs once
25+
INIT {...} # * at run time, ASAP, only ever runs once
26+
END {...} # at run time, ALAP, only ever runs once
27+
28+
ENTER {...} # * at every block entry time, repeats on loop blocks.
29+
LEAVE {...} # at every block exit time (even stack unwinds from exceptions)
30+
KEEP {...} # at every successful block exit, part of LEAVE queue
31+
UNDO {...} # at every unsuccessful block exit, part of LEAVE queue
32+
33+
FIRST {...} # * at loop initialization time, before any ENTER
34+
NEXT {...} # at loop continuation time, before any LEAVE
35+
LAST {...} # at loop termination time, after any LEAVE
36+
37+
PRE {...} # assert precondition at every block entry, before ENTER
38+
POST {...} # assert postcondition at every block exit, after LEAVE
39+
40+
CATCH {...} # catch exceptions, before LEAVE
41+
CONTROL {...} # catch control exceptions, before LEAVE
42+
43+
COMPOSE {...} # when a role is composed into a class
44+
45+
Constructs marked with a C<*> have a run-time value, and if evaluated
46+
earlier than their surrounding expression, they simply save their result for
47+
use in the expression later when the rest of the expression is evaluated:
48+
49+
my $compiletime = BEGIN { now };
50+
our $temphandle = ENTER { maketemp() };
51+
52+
As with other statement prefixes, these value-producing constructs may be
53+
placed in front of either a block or a statement:
54+
55+
my $compiletime = BEGIN now;
56+
our $temphandle = ENTER maketemp();
57+
58+
Most of these phasers will take either a block or a function reference. The
59+
statement form can be particularly useful to expose a lexically scoped
60+
declaration to the surrounding lexical scope without "trapping" it inside a
61+
block.
62+
63+
Hence these declare the same variables with the same scope as the preceding
64+
example, but run the statements as a whole at the indicated time:
65+
66+
BEGIN my $compiletime = now;
67+
ENTER our $temphandle = maketemp();
68+
69+
(Note, however, that the value of a variable calculated at compile time may
70+
not persist under run-time cloning of any surrounding closure.)
71+
72+
Most of the non-value-producing phasers may also be so used:
73+
74+
END say my $accumulator;
75+
76+
Note, however, that
77+
78+
END say my $accumulator = 0;
79+
80+
sets the variable to 0 at C<END> time, since that is when the "my"
81+
declaration is actually executed. Only argumentless phasers may use the
82+
statement form. This means that C<CATCH> and C<CONTROL> always require a
83+
block, since they take an argument that sets C<$_> to the current topic, so
84+
that the innards are able to behave as a switch statement. (If bare
85+
statements were allowed, the temporary binding of C<$_> would leak out past
86+
the end of the C<CATCH> or C<CONTROL>, with unpredictable and quite possibly
87+
dire consequences. Exception handlers are supposed to reduce uncertainty,
88+
not increase it.)
89+
90+
Code that is generated at run time can still fire off C<CHECK> and C<INIT>
91+
phasers, though of course those phasers can't do things that would require
92+
travel back in time. You need a wormhole for that.
93+
94+
The compiler is free to ignore C<LINK> phasers compiled at run time since
95+
they're too late for the application-wide linking decisions.
96+
97+
Some of these phasers also have corresponding traits that can be set on
98+
variables. These have the advantage of passing the variable in question
99+
into the closure as its topic:
100+
101+
our $h will enter { .rememberit() } will undo { .forgetit() };
102+
103+
Only phasers that can occur multiple times within a block are eligible for
104+
this per-variable form.
105+
106+
Apart from C<CATCH> and C<CONTROL>, which can only occur once, most of these
107+
can occur multiple times within the block. So they aren't really traits,
108+
exactly--they add themselves onto a list stored in the actual trait. So if
109+
you examine the C<ENTER> trait of a block, you'll find that it's really a
110+
list of phasers rather than a single phaser.
111+
112+
When multiple phasers are scheduled to run at the same moment, the general
113+
tiebreaking principle is that initializing phasers execute in order
114+
declared, while finalizing phasers execute in the opposite order, because
115+
setup and teardown usually want to happen in the opposite order from each
116+
other. When phasers are in different modules, the C<INIT> and C<END>
117+
phasers are treated as if declared at C<use> time in the using module. (It
118+
is erroneous to depend on this order if the module is used more than once,
119+
however, since the phasers are only installed the first time they're
120+
noticed.)
121+
122+
The semantics of C<INIT> and C<once> are not equivalent to each other in the
123+
case of cloned closures. An C<INIT> only runs once for all copies of a
124+
cloned closure. A C<once> runs separately for each clone, so separate
125+
clones can keep separate state variables:
126+
127+
our $i = 0;
128+
...
129+
$func = once { state $x { $x = $i++ }; dostuff($i) };
130+
131+
But C<state> automatically applies "once" semantics to any initializer, so
132+
this also works:
133+
134+
$func = { state $x = $i++; dostuff($i) }
135+
136+
Each subsequent clone gets an initial state that is one higher than the
137+
previous, and each clone maintains its own state of C<$x>, because that's
138+
what C<state> variables do.
139+
140+
Even in the absence of closure cloning, C<INIT> runs before the mainline
141+
code, while C<once> puts off the initialization till the last possible
142+
moment, then runs exactly once, and caches its value for all subsequent
143+
calls (assuming it wasn't called in sink context, in which case the C<once>
144+
is evaluated once only for its side effects). In particular, this means
145+
that C<once> can make use of any parameters passed in on the first call,
146+
whereas C<INIT> cannot.
147+
148+
All of these phaser blocks can see any previously declared lexical
149+
variables, even if those variables have not been elaborated yet when the
150+
closure is invoked (in which case the variables evaluate to an undefined
151+
value.)
152+
153+
Note: Apocalypse 4 confused the notions of C<PRE>/C<POST> with
154+
C<ENTER>/C<LEAVE>. These are now separate notions. C<ENTER> and C<LEAVE>
155+
are used only for their side effects. C<PRE> and C<POST> return boolean
156+
values which, if false, trigger a runtime exception. C<KEEP> and C<UNDO>
157+
are just variants of C<LEAVE>, and for execution order are treated as part
158+
of the queue of C<LEAVE> phasers.
159+
160+
It is conjectured that C<PRE> and C<POST> submethods in a class could be
161+
made to run as if they were phasers in any public method of the class. This
162+
feature is awaiting further exploration by means of a C<ClassHOW> extension.
163+
164+
C<FIRST>, C<NEXT>, and C<LAST> are meaningful only within the lexical scope
165+
of a loop, and may occur only at the top level of such a loop block. A
166+
C<NEXT> executes only if the end of the loop block is reached normally, or
167+
an explicit C<next> is executed. In distinction to C<LEAVE> phasers, a
168+
C<NEXT> phaser is not executed if the loop block is exited via any exception
169+
other than the control exception thrown by C<next>. In particular, a
170+
C<last> bypasses evaluation of C<NEXT> phasers.
171+
172+
[Note: the name C<FIRST> used to be associated with C<state> declarations.
173+
Now it is associated only with loops. See the C<once> above for C<state>
174+
semantics.]
175+
176+
Except for C<CATCH> and C<CONTROL> phasers, which run while an exception is
177+
looking for a place to handle it, all block-leaving phasers wait until the
178+
call stack is actually unwound to run. Unwinding happens only after some
179+
exception handler decides to handle the exception that way. That is, just
180+
because an exception is thrown past a stack frame does not mean we have
181+
officially left the block yet, since the exception might be resumable. In
182+
any case, exception handlers are specified to run within the dynamic scope
183+
of the failing code, whether or not the exception is resumable. The stack
184+
is unwound and the phasers are called only if an exception is not resumed.
185+
186+
So C<LEAVE> phasers for a given block are necessarily evaluated after any
187+
C<CATCH> and C<CONTROL> phasers. This includes the C<LEAVE> variants,
188+
C<KEEP> and C<UNDO>. C<POST> phasers are evaluated after everything else,
189+
to guarantee that even C<LEAVE> phasers can't violate postconditions.
190+
Likewise C<PRE> phasers fire off before any C<ENTER> or C<FIRST> (though not
191+
before C<BEGIN>, C<CHECK>, C<LINK>, or C<INIT>, since those are done at
192+
compile or process initialization time).
193+
194+
The C<POST> block can be defined in one of two ways. Either the
195+
corresponding C<POST> is defined as a separate phaser, in which case C<PRE>
196+
and C<POST> share no lexical scope. Alternately, any C<PRE> phaser may
197+
define its corresponding C<POST> as an embedded phaser block that closes
198+
over the lexical scope of the C<PRE>.
199+
200+
If exit phasers are running as a result of a stack unwind initiated by an
201+
exception, this information needs to be made available. In any case, the
202+
information as to whether the block is being exited successfully or
203+
unsuccessfully needs to be available to decide whether to run C<KEEP> or
204+
C<UNDO> blocks (also see L</"Definition of Success">). How this information
205+
is made available is implementation dependent.
206+
207+
An exception thrown from an C<ENTER> phaser will abort the C<ENTER> queue,
208+
but one thrown from a C<LEAVE> phaser will not. The exceptions thrown by
209+
failing C<PRE> and C<POST> phasers cannot be caught by a C<CATCH> in the
210+
same block, which implies that C<POST> phaser are not run if a C<PRE> phaser
211+
fails.
212+
213+
If a C<POST> fails or any kind of C<LEAVE> block throws an exception while
214+
the stack is unwinding, the unwinding continues and collects exceptions to
215+
be handled. When the unwinding is completed all new exceptions are thrown
216+
from that point.
217+
218+
For phasers such as C<KEEP> and C<POST> that are run when exiting a scope
219+
normally, the return value (if any) from that scope is available as the
220+
current topic within the phaser.
221+
222+
The topic of the block outside a phaser is still available as C<<
223+
OUTER::<$_> >>. Whether the return value is modifiable may be a policy of
224+
the phaser in question. In particular, the return value should not be
225+
modified within a C<POST> phaser, but a C<LEAVE> phaser could be more
226+
liberal.
227+
228+
Any phaser defined in the lexical scope of a method is a closure that closes
229+
over C<self> as well as normal lexicals. (Or equivalently, an
230+
implementation may simply turn all such phasers into submethods whose primed
231+
invocant is the current object.)
232+
233+
=head2 BEGIN
234+
=head2 CHECK
235+
=head2 LINK
236+
=head2 INIT
237+
=head2 END
238+
=head2 ENTER
239+
=head2 LEAVE
240+
=head2 KEEP
241+
=head2 UNDO
242+
=head2 FIRST
243+
=head2 NEXT
244+
=head2 LAST
245+
=head2 PRE
246+
=head2 POST
247+
=head2 CATCH
248+
=head2 CONTROL
249+
=head2 COMPOSE

0 commit comments

Comments
 (0)