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