[svn:parrot] r37484 - trunk/docs/pdds

pmichaud at svn.parrot.org pmichaud at svn.parrot.org
Mon Mar 16 15:57:08 UTC 2009


Author: pmichaud
Date: Mon Mar 16 15:57:07 2009
New Revision: 37484
URL: https://trac.parrot.org/parrot/changeset/37484

Log:
Update pdd20 -- resolves TT #243

Modified:
   trunk/docs/pdds/pdd20_lexical_vars.pod

Modified: trunk/docs/pdds/pdd20_lexical_vars.pod
==============================================================================
--- trunk/docs/pdds/pdd20_lexical_vars.pod	Mon Mar 16 15:24:24 2009	(r37483)
+++ trunk/docs/pdds/pdd20_lexical_vars.pod	Mon Mar 16 15:57:07 2009	(r37484)
@@ -14,25 +14,25 @@
 
 =head2 Synopsis
 
-    .sub foo
-        .lex "$a", P0
-        P1 = new Integer
-        P1 = 13013
-        store_lex "$a", P1
-        print P0            # prints 13013
+    .sub 'foo'
+        .lex "$a", $P0
+        $P1 = new Integer
+        $P1 = 13013
+        store_lex "$a", $P1
+        print $P0            # prints 13013
     .end
 
-    .sub bar :outer(foo)
-        P0 = find_lex "$a"  # may succeed; depends on closure creation
+    .sub 'bar' :outer('foo')
+        $P0 = find_lex "$a"
     .end
 
-    .sub baz
-        P0 = find_lex "$a"  # guaranteed to fail: no .lex, no :outer()
+    .sub 'baz'
+        $P0 = find_lex "$a"  # guaranteed to fail: no .lex, no :outer()
     .end
 
-    .sub corge
+    .sub 'corge'
         print "hi"
-    .end                    # no .lex and no :lex, thus: no LexInfo, no LexPad
+    .end                     # no .lex and no :lex, thus: no LexInfo, no LexPad
 
 
     # Lexical behavior varies by HLL.  For example,
@@ -41,14 +41,14 @@
     .HLL "Tcl"
     .loadlib 'tcl_group'
 
-    .sub grault :lex        # without ":lex", Tcl subs have no lexicals
-        P0 = find_lex "x"   # FAILS
+    .sub grault :lex         # without ":lex", Tcl subs have no lexicals
+        $P0 = find_lex "x"   # FAILS
 
-        P0 = new Integer    # really TclInteger
-        P0 = 42
-        store_lex "x", P0   # creates lexical "x"
+        $P0 = new Integer    # really TclInteger
+        $P0 = 42
+        store_lex "x", $P0   # creates lexical "x"
 
-        P0 = find_lex "x"   # SUCCEEDS
+        $P0 = find_lex "x"   # SUCCEEDS
     .end
 
 =head2 Description
@@ -78,7 +78,7 @@
 languages (e.g. Tcl) their names.  They are the interface through which the
 Parrot runtime stores and fetches lexical variables.
 
-At run time, each call frame for a Subroutine (or Subroutine derivative) that
+At run time, each call frame for a Sub (or Sub derivative) that
 uses lexical variables will be populated with a PMC of HLL-mapped
 type LexPad.  Note that call frames for subroutines without lexical
 variables will omit the LexPad.
@@ -98,30 +98,102 @@
 so a single LexPad reference wouldn't be as useful as one might expect.  And,
 of course, opcodes can cheat ... er, can be written in optimized C.  :-)
 
-TODO: Describe how lexical naming system interacts with non-ASCII character
-      sets.
+=head4 Nested Subroutines Have Outies; the ":outer" attribute
 
-=head4 Lexical Lookup Algorithm
+For HLLs that support nested subroutines, Parrot provides a way to denote that
+a given subroutine is conceptually "inside" another.  Lookup for lexical
+variables starts at the current call frame and proceeds through call frames
+of the "outer" subroutines.  The specific meaning of "outer" is defined
+below, but it's designed to support the common linguistic structure of nested
+subroutines where inner subs refer to lexical variables contained in outer
+blocks.
 
-If Parrot is asked to access a lexical variable named $var, Parrot
-follows the following strategy.  Note that fetch and store use the
-exact same approach.
+Note that "outer" and "caller" are very different concepts!  For example,
+given the Perl 6 code:
 
-Parrot starts with the currently executing subroutine $sub, then loops
-through these steps:
+   sub foo {
+      my $a = 1;
+      my sub a { eval '$a' }
+      return &a;
+   }
 
-  1. Starting at the current call frame, walk back until an active frame is
-     found that is executing $sub.  Call it $frame.
+The C<&foo> subroutine is the outer subroutine of C<&a>, but it is not the
+caller of C<&a>.
 
-     (NOTE: The first time through, $sub is the current subroutine and $frame
-     is the currently live frame.)
+In the above example, the definition of the Parrot subroutine implementing
+&a must include a notation that it is textually enclosed within C<&foo>.
+This is normally a static attribute of a Sub, but can be changed
+dynamically using the C<set_outer> method.
 
-  2. Look for $var in $frame.get_lexpad using standard Hash methods.
+    .sub 'a' :outer('foo')
 
-  3. If the given pad contains $var, fetch/store it and REPORT SUCCESS.
+The value of C<:outer> identifies a subroutine by its C<:subid>
+flag; subroutine definitions that do not have an explicit C<:subid>
+flag have the name of the Sub as the C<:subid>.
+
+Note that the outer sub B<must> be compiled first; in other words, 
+"foo" must appear before "a" in the source text.  Compilers can 
+easily do this via preorder traversal of lexically-nested subs.
+
+=head4 Capturing the lexical environment
+
+The C<capture_lex> opcode is used to attach the current lexical
+environment to any subroutines that are lexically nested within
+the current sub.  This is normally done either when the outer
+sub is entered or just prior to invoking the inner sub.
+
+    .sub 'a'
+        .lex '$a', $P0
+        ...
+        # capture current lexical environment for inner sub 'foo'
+        .const 'Sub' $P0 = 'foo'
+        capture_lex $P0
+        # invoke inner sub 'foo'
+        'foo'()
+    .end
+
+The C<newclosure> opcode will clone a subroutine and then perform
+C<capture_lex> on the newly cloned sub.
 
-  4. Set $sub to $sub.outer.  (That is, the textually enclosing subroutine.)
-     But if $sub has no outer sub, REPORT FAILURE.
+    .sub 'a'
+        .lex '$a', $P0
+
+        # invoke inner sub 'foo'
+        .const 'Sub' $P0 = 'foo'
+        $P1 = newclosure $P0
+        $P1()
+    .end
+
+=head4 Lexical Lookup Algorithm
+
+When a subroutine is invoked, its newly created call frame
+points to the outer sub's context that was established for
+the sub by the C<capture_lex> opcode above.  When Parrot 
+is asked to access a lexical variable named '$a'  (e.g., 
+via the C<find_lex> opcode), Parrot starts with the current 
+call frame and follows the chain of outer lexical call
+frames until it finds one containing the requested lexical.
+If none of the outer lexical environments define such a
+variable, an exception is thrown.
+
+=head4 Autoclose semantics
+
+If an inner subroutine is invoked that hasn't had a
+C<capture_lex> operation performed on it, then Parrot
+will attempt to dynamically perform the lexical capture
+using the call from from its outer sub.  If the outer sub 
+doesn't have a call frame, as might occur when jumping 
+directly to the inner sub without previously invoking the 
+outer, then Parrot creates a dummy call frame for the 
+outer sub to be used for its inner lexical sub captures
+(until the outer sub is invoked, at which point it receives
+a new call frame).
+
+Note that the dummy call frame created for the outer sub will
+be attached to its outer call frame, which may require creating
+dummy call frames for additional outer contexts (until an
+invoked outer sub is located, or the top-level outer lexical
+context is reached).
 
 =head4 LexPad and LexInfo are optional; the ":lex" attribute
 
@@ -137,55 +209,6 @@
 languages, the additional Subroutine attribute ":lex" should be specified.  It
 forces Parrot to create LexInfo and LexPads.
 
-=head4 Closures
-
-NOTE: This section should be taken using the "as-if" rule: Parrot behaves as
-if this section were literally true.  As always, short cuts (development and
-runtime) may be taken.
-
-Closures are specialized Subroutines that carry their I<lexical environment>
-along with them.  A lexical environment, which we will call a "LexEnv" for
-brevity, is a list of LexPads to be searched when looking for lexical
-variables.  Its implementation may be as simple as a basic PMC array, but any
-ordered integer-indexed collection will do.
-
-=head4 Closure creation: Capturing the lexical environment
-
-The C<newclosure> op creates a Closure from a Subroutine and gives that
-Closure a new LexEnv attribute.  The LexEnv is then populated with pointers to
-the current I<enclosing> LexPads.  The definition of "enclosing" is not
-obvious, though.
-
-The algorithm used to find "enclosing" LexPads is a loop of the following
-steps, starting with $sub set to the running Subroutine (which is a Closure):
-
-  1. Starting at the current call frame, walk back until an active frame is
-     found that is executing $sub.  Call it $frame.
-
-     (NOTE: The first time through, $sub is the current subroutine and $frame
-            is the currently live frame.)
-
-  2. Append $frame's LexPad to the LexEnv.
-
-  3. If $sub has a LexEnv, append $sub's LexEnv to the LexEnv being built,
-     and END LOOP.  Otherwise:
-
-  4. Set $sub to $sub.outer.  (That is, the textually enclosing subroutine.)
-     But if $sub has no outer sub, END LOOP.
-
-NOTE: The C<newclosure> opcode should check to make sure that the target
-Subroutine has an C<:outer()> attribute that points back to the currently
-running Subroutine.  This is a requirement for closures.
-
-=head4 Closure runtime: Using the lexical environment
-
-At runtime, the C<find_lex> opcode behaves differently in closures.  It has no
-need to walk the call stack finding LexPads - they have all already been
-collected conveniently together in the LexEnv.  Therefore, in a Closure,
-C<find_lex> I<ignores> the call stack, and instead searches (1) the current
-call frame's LexPad - i.e. the Closure's own lexicals -- and then (2) the
-LexPads in the LexEnv.
-
 =head4 HLL Type Mapping
 
 The implementation of lexical variables in the PIR compiler depends on two new
@@ -203,41 +226,8 @@
 information to store, there's no need for TclLexInfo to do anything
 interesting.
 
-=head4 Nested Subroutines Have Outies; the ":outer" attribute
 
-For HLLs that support nested subroutines, Parrot provides a way to denote that
-a given subroutine is conceptually "inside" another.  Lookup for lexical
-variables starts at the current call frame and proceeds through call frames
-that invoke "outer" subroutines.  The specific meaning of "outer" is defined
-below, but it's designed to support the common linguistic structure of nested
-subroutines where inner subs refer to lexical variables contained in outer
-blocks.
-
-Note that "outer" and "caller" are very different concepts!  For example,
-given the Perl 6 code:
-
-   sub foo {
-      my $a = 1;
-      my sub a { eval '$a' }
-      return &a;
-   }
-
-The C<&foo> subroutine is the outer subroutine of C<&a>, but it is not the
-caller of C<&a>.
-
-In the above example, the definition of the Parrot subroutine implementing
-&a must include a notation that it is textually enclosed within C<&foo>.
-This is a static attribute of a Subroutine, set at compile time and never
-changed thereafter.  (Unless you're evil, or Damian.  But I repeat myself.)
-This information is given through an C<:outer()> subroutine attribute, e.g.:
-
-    .sub a :outer(foo)
-
-Note that the "foo" sub B<must> be compiled first; in other words, "foo" must
-appear before "a" in the source text.  Compilers can easily do this via
-preorder traversal of lexically-nested subs.
-
-=head3 Required Interfaces: LexPad, LexInfo, Closure
+=head3 Required Interfaces: LexPad, LexInfo
 
 =head4 LexInfo
 
@@ -303,19 +293,6 @@
 
 =back
 
-=head4 Closure
-
-For debugging and introspection, the Closure PMC should support:
-
-=over 4
-
-=item B<PMC *get_lexenv()>
-
-Return the associated LexEnv, an ordered integer-index collection (e.g. an
-Array) of LexPads captured at C<newclosure> time.
-
-=back
-
 =head3 Default Parrot LexPad and LexInfo
 
 The default LexInfo supports lexicals only as aliases for PMC registers.  It
@@ -372,8 +349,6 @@
 It's likely that this interface will continue to be available even once call
 frames become visible as PMCs.
 
-TODO: Full interpreter introspection interface.
-
 =head2 Implementation
 
 TK.


More information about the parrot-commits mailing list