Author: lwall
Date: 2010-07-10 00:55:41 +0200 (Sat, 10 Jul 2010)
New Revision: 31609
Modified:
docs/Perl6/Spec/S04-control.pod
docs/Perl6/Spec/S06-routines.pod
Log:
[S04,6] more refinement of how scoping works under DBC
note that all phasers in methods to have access to self via closure
Modified: docs/Perl6/Spec/S04-control.pod
===================================================================
--- docs/Perl6/Spec/S04-control.pod 2010-07-09 22:39:12 UTC (rev 31608)
+++ docs/Perl6/Spec/S04-control.pod 2010-07-09 22:55:41 UTC (rev 31609)
@@ -14,7 +14,7 @@
Created: 19 Aug 2004
Last Modified: 9 Jul 2010
- Version: 99
+ Version: 100
This document summarizes Apocalypse 4, which covers the block and
statement syntax of Perl.
@@ -1379,17 +1379,31 @@
before C<BEGIN>, C<CHECK>, or C<INIT>, since those are done at compile or
process initialization time). Much like C<BUILD> and C<DESTROY> are implicitly
called in the correct order by C<BUILDALL> and C<DESTROYALL>, the
C<PRE>/C<POST>
-calls are via an implicit C<ENFORCEALL> method that runs
+calls are via an implicit C<CALL-VIA-DBC> method that runs
outside the actual call to the method in question. Class-level C<PRE>/C<POST>
submethods are notionally outside of the method-level C<PRE>/C<POST> blocks.
-At each submethod level, C<ENFORCEALL> calls (in the normal course of things):
+In the normal course of things, C<CALL-VIA-DBC> follows these steps:
- 1. class's C<PRE> submethod
- 2. method's C<PRE> phaser
- 3. method call
- 4. method's C<POST> phaser
- 5. class's C<POST> submethod
+ 1. create an empty stack for scheduling postcalls.
+ 2. call all the appropriate per-class C<PRE> submethods,
+ pushing any corresponding C<POST> onto the postcall stack.
+ 3. call all the appropriate per-method C<PRE> phasers,
+ pushing any corresponding C<POST> onto the postcall stack.
+ 4. enforce DBC logic of C<PRE> calls
+ 5. call the method call itself, capturing return/unwind status.
+ 6. pop and call every C<POST> on the postcall stack.
+ 7. enforce DBC logic of C<POST> calls
+ 8. continue with the return or unwind.
+Note that in steps 2 and 3, the C<POST> block can be defined in
+one of two ways. Either the corresponding C<POST> is defined as a
+separate declaration (submethod for 2, phaser for 3), in which case
+C<PRE> and C<POST> share no lexical scope. Alternately, any C<PRE>
+(either submethod or phaser) may define its corresponding C<POST>
+as an embedded phaser block that closes over the lexical scope of
+the C<PRE>. In either case, the code is pushed onto the postphaser
+stack to be run at the appropriate moment.
+
If exit phasers are running as a result of a stack unwind initiated
by an exception, C<$!> contains the exception that caused it, though
it will be marked as handled by then. In any case, the information
@@ -1416,15 +1430,22 @@
world in raw form, so that the phaser doesn't accidentally impose
context prematurely.)
-The topic of the outer block of a phaser is still available as C<< OUTER::<$_>
>>.
+The topic of the block outside a phaser is still available as C<< OUTER::<$_>
>>.
Whether the return value is modifiable may be a policy of the phaser
in question. In particular, the return value should not be modified
within a C<POST> phaser, but a C<LEAVE> phaser could be more liberal.
-Class-level C<PRE> and C<POST> submethods are not in the lexical
-scope of a method, and are not run in the dynamic scope of the method,
-so cannot see the method's C<$_> at all.
+Class-level C<PRE> and C<POST> submethods are not in the lexical scope
+of a method (and are not run in the dynamic scope of the method),
+so they cannot see the method's C<$_> at all. As methods, they
+do have access to the current C<self>, of course. And the C<POST>
+submethod gets the return value as the topic, just as exit phasers do.
+Any phaser defined in the lexical scope of a method is a closure that
+closes over C<self> as well as normal lexicals. (Or equivalently,
+an implementation may simply turn all such phasers into submethods
+whose curried invocant is the current object.)
+
=head1 Statement parsing
In this statement:
Modified: docs/Perl6/Spec/S06-routines.pod
===================================================================
--- docs/Perl6/Spec/S06-routines.pod 2010-07-09 22:39:12 UTC (rev 31608)
+++ docs/Perl6/Spec/S06-routines.pod 2010-07-09 22:55:41 UTC (rev 31609)
@@ -17,7 +17,7 @@
Created: 21 Mar 2003
Last Modified: 9 Jul 2010
- Version: 137
+ Version: 138
This document summarizes Apocalypse 6, which covers subroutines and the
new type system.
@@ -2093,7 +2093,8 @@
or C<ENTER> block are automatically hoisted outward to be called at the
same time as other C<POST> phasers. This conveniently gives "circum"
semantics by virtue of wrapping the post lexical scope within the pre
-lexical scope.
+lexical scope. That is, the C<POST> closes over its outer scope, even
+if that scope is gone by the time the C<POST> is run.
method push ($new_item) {
ENTER {
@@ -2113,13 +2114,20 @@
return pop @.items;
}
-[Conjecture: class and module invariants can similarly be supplied
-by embedding C<POST>/C<post> declarations in a C<FOREIGN> block that
-only runs when any routine of this module is called from "outside"
-the current module or type, however that's defined. The C<FOREIGN> block
-itself could perhaps refine the concept of what is foreign, much like
-an exception handler.]
+Note that C<self> is available in phasers defined within methods.
+Class invariants are declared with C<PRE>/C<POST> submethods instead of
phasers.
+
+Module invariants are declared with C<PRE>/C<POST> subs or protos.
+
+[Conjecture: class and module invariants can applied more selectively
+by marking C<PRE>/C<POST> declarations with a C<selective> trait that
+stops it from running on internal calls (which might allow temporary
+violations of invariants), but enforces the invariants when any routine
+of this module is called from "outside" the current module or type,
+however that's defined. There could be arguments to this trait that
+could refine the concept of what is foreign.]
+
=item C<ENTER>/C<LEAVE>/C<KEEP>/C<UNDO>/etc.
These phasers supply code that is to be conditionally executed before or