[svn:parrot] r38785 - trunk/docs/book

allison at svn.parrot.org allison at svn.parrot.org
Fri May 15 03:08:22 UTC 2009


Author: allison
Date: Fri May 15 03:08:21 2009
New Revision: 38785
URL: https://trac.parrot.org/parrot/changeset/38785

Log:
[book] More section restructuring in PIR chapter.

Modified:
   trunk/docs/book/ch03_pir.pod

Modified: trunk/docs/book/ch03_pir.pod
==============================================================================
--- trunk/docs/book/ch03_pir.pod	Fri May 15 01:25:41 2009	(r38784)
+++ trunk/docs/book/ch03_pir.pod	Fri May 15 03:08:21 2009	(r38785)
@@ -48,7 +48,7 @@
 
   =cut
 
-=head2 Labels
+=head3 Labels
 
 Z<CHP-3-SECT-4>
 
@@ -240,7 +240,7 @@
 account for all the complexity of human-readable (and computer-representable)
 textual data.
 
-=head3 Strings: Encodings and Charsets
+=head3 Encodings and Charsets
 
 X<charset>
 A modern string system must manage several character encodings and charsets in
@@ -321,6 +321,26 @@
 custom methods to perform various operations, may be passed to subroutines that
 expect PMC arguments, and can be subclassed by a user-defined type.
 
+
+PMCs are are polymorphic data items that
+can be one of a large variety of predefined types. As we have seen briefly,
+and as we will see in more depth later, PMCs have a standard interface called
+the VTABLE interface. VTABLEs are a standard list of functions that all PMCs
+implement N<or, PMCs can choose not to implement each interface explicitly and
+instead let Parrot call the default implementations>.
+
+VTABLEs are very strict: There are a fixed number with fixed names and
+fixed argument lists. You can't just create any random VTABLE interface that
+you want to create, you can only make use of the ones that Parrot supplies
+and expects. To circumvent this limitation, PMCs may have METHODS in
+addition to VTABLEs. METHODs are arbitrary code functions that can be
+written in C, may have any name, and may implement any behavior.
+
+=head2 VTABLE Interfaces
+
+Internally, all operations on PMCs are performed by calling various VTABLE
+interfaces.
+
 =head3 Type Conversion
 
 The C<=> operator is very powerful.  Its simplest form stores a value into one
@@ -363,14 +383,14 @@
   $I2 = $P2      # Intify. 3
   $N2 = $P2      # Unbox. $N2 = 3.14
 
-=head2 Flow Control
+=head2 Control Flow
 
 Z<CHP-3-SECT-5>
 
-X<PIR (Parrot intermediate representation);flow control>
-X<flow control;in PIR>
+X<PIR (Parrot intermediate representation);control flow>
+X<control flow;in PIR>
 
-Flow control in PIR occurs entirely with conditional and unconditional branches
+Control flow in PIR occurs entirely with conditional and unconditional branches
 to labels. This may seem simplistic and primitive, but here PIR shows its roots
 as a thin overlay on the assembly language of a virtual processor.  PIR does
 not support high-level looping structures such as C<while> or C<for> loops. PIR
@@ -630,8 +650,6 @@
 call to the appropriate integer register. This is all in addition to the
 computation the subroutine itself performs.
 
-=head3 Expanded Subroutine Syntax
-
 The single line subroutine call is incredibly convenient, but it isn't always
 flexible enough. PIR also has a more verbose call syntax that is still more
 convenient than manual calls. This example looks up the subroutine C<fact> out
@@ -710,7 +728,9 @@
 
 As usual, execution of the program starts at the C<:main> subroutine.
 
-=head3 Named Arguments
+=head3 Parameters and Arguments
+
+=head4 Named Parameters
 
 =for author
 
@@ -759,7 +779,7 @@
 Named arguments can be a big help because you don't have to worry about the
 exact order of variables, especially as argument lists get very long.
 
-=head3 Optional Arguments
+=head4 Optional Parameters
 
 X<optional arguments>
 Some functions have arguments with appropriate default values, so that callers
@@ -819,116 +839,75 @@
   'MySub'("answer" => 42)  # with a value
   'MySub'()                # without
 
-=head3 Sub PMCs
-
-Subroutines are a PMC type in Parrot. You can store them in PMC registers and
-manipulate them just as you do the other PMC types.  Look up a subroutine in
-the current namespace with the C<get_global> opcode:
-
-  $P0 = get_global "MySubName"
-
-To find a subroutine in a different namespace, first look up the appropriate
-the namespace PMC, then use that with C<get_global>:
-
-  $P0 = get_namespace "MyNamespace"
-  $P1 = get_global $P0, "MySubName"
-
-You can obviously invoke a Sub PMC:
-
-  $P0(1, 2, 3)
-
-You can get or even I<change> its name:
-
-  $S0 = $P0               # Get the current name
-  $P0 = "MyNewSubName"    # Set a new name
-
-You can get a hash of the complete metadata for the subroutine:
-
-  $P1 = inspect $P0
-
-The metadata fields in this hash are
-
-=over 4
-
-=item * pos_required
-
-The number of required positional parameters to the Sub
-
-=item * pos_optional
-
-The number of optional positional parameters to the Sub
+=head4 Commandline Arguments
 
-=item * named_required
+Programs written in Parrot have access to arguments passed on the command
+line:
 
-The number of required named parameters to the Sub
+  .sub 'MyMain' :main
+    .param pmc all_args :slurpy
+    ...
+  .end
 
-=item * named_optional
+=for author
 
-The number of optional named parameters to the Sub
+Please verify and expand.
 
-=item * pos_slurpy
+=end for
 
-Returns true if the sub has a slurpy parameter to eat up extra positional args
+The C<all_args> PMC is a ResizableStringArray PMC, which means you can loop
+over the results, access them individually, or even modify them.
 
-=item * named_slurpy
+=head3 Continuations
 
-Returns true if the sub has a slurpy parameter to eat up extra named args
+X<continuations>
 
-=back
+Continuations are a kind of subroutine that take a snapshots of control flow. They are frozen images of the current
+execution state of the VM. Once you have a continuation, you can invoke it to
+return to the point where the continuation was first created. It's like a
+magical timewarp that allows the developer to arbitrarily move control flow
+back to any previous point in the program.
 
-Instead of getting the whole inspection hash, you ask about individual pieces
-of metadata:
+Continuations are like any other PMC; you can create one with the C<new> opcode:
 
-  $I0 = inspect $P0, "pos_required"
+  $P0 = new 'Continuation'
 
-To discover to get the total number of defined parameters to the Sub, call the
-C<arity> method:
+The new continuation starts off in an undefined state. If you attempt to invoke
+a new continuation without initializing it, Parrot will throw an exception.  To
+prepare the continuation for use, assign it a destination label with the
+C<set_addr> opcode:
 
-  $I0 = $P0.'arity'()
+    $P0 = new 'Continuation'
+    set_addr $P0, my_label
 
-To fetch the namespace PMC that the Sub was defined into, call the
-C<get_namespace> method:
+  my_label:
+    ...
 
-  $P1 = $P0.'get_namespace'()
+To jump to the continuation's stored label and return the context to the state
+it was in I<at the point of its creation>, invoke the continuation:
 
-=head2 The Commandline
+  invoke $P0  # Explicit using "invoke" opcode
+  $P0()       # Same, but nicer syntax
 
-Programs written in Parrot have access to arguments passed on the command
-line like any other program would:
+Even though you can use the subroutine notation C<$P0()> to invoke the
+continuation, it doesn't make any sense to pass arguments or obtain return
+values:
 
-  .sub 'MyMain' :main
-    .param pmc all_args :slurpy
-    ...
-  .end
+  $P0 = new 'Continuation'
+  set_addr $P0, my_label
 
-=for author
+  $P0(1, 2)      # WRONG!
 
-Please verify and expand.
+  $P1 = $P0()    # WRONG!
 
-=end for
 
-The C<all_args> PMC is a ResizableStringArray PMC, which means you can loop
-over the results, access them individually, or even modify them.
 
-=head2 Continuation Passing Style
+=head4 Continuation Passing Style
 
-X<continuations>
 X<continuation passing style>
 X<CPS>
-Continuations are snapshots of control flow: frozen images of the current
-execution state of the VM. Once you have a continuation, you can invoke it to
-return to the point where the continuation was first created. It's like a
-magical timewarp that allows the developer to arbitrarily move control flow
-back to any previous point in the program.
 
-Continuations are not a new concept; they've boggled the minds of new Lisp and
-Scheme programmers for many years.  Despite their power and heritage, they're
-not visible to most other modern programming languages or their runtimes.
-Parrot aims to change that: it performs almost all control flow through the use
-of continuations.  PIR and PCT hide most of this complexity from developers,
-but the full power of continuations is available.
-
-When Parrot invokes a function, it creates a continuation representing the
+Parrot uses continuations internally for control flow. When Parrot invokes a function, it creates a continuation representing the
 current point in the program.  It passes this continuation as an invisible
 parameter to the function call.  When that function returns, it invokes the
 continuation -- in effect, it performs a goto to the point of creation of that
@@ -937,10 +916,10 @@
 
 This type of flow control -- invoking continuations instead of performing bare
 jumps -- is X<Continuation Passing Style;CPS> Continuation Passing Style (CPS).
-CPS allows parrot to offer all sorts of neat features, such as tail-call
-optimizations and lexical subroutines.
 
-=head3 Tailcalls
+
+
+=head4 Tailcalls
 
 In many cases, a subroutine will set up and call another subroutine, and then
 return the result of the second call directly. This is a X<tailcall> tailcall,
@@ -996,88 +975,320 @@
 
 This example above will print out the correct value "7".
 
-=head3 Creating and Using Continuations
 
-While Parrot's use of continuations and CPS is invisible to most code, you can
-create and use them explicitly if you like.  Continuations are like any other
-PMC; create one with the C<new> opcode:
 
-  $P0 = new 'Continuation'
 
-The new continuation starts off in an undefined state. If you attempt to invoke
-a new continuation without initializing it, Parrot will raise an exception.  To
-prepare the continuation for use, assign it a destination label with the
-C<set_addr> opcode:
+=head3 Coroutines
 
-    $P0 = new 'Continuation'
-    set_addr $P0, my_label
+X<PIR;Coroutines>
+X<Coroutines>
+We've mentioned coroutines several times before, and we're finally going
+to explain what they are. Coroutines are similar to subroutines except
+that they have an internal notion of I<state> N<And the cool new name!>.
+Coroutines, in addition to performing a normal C<.return> to return
+control flow back to the caller and destroy the lexical environment of
+the subroutine, may also perform a C<.yield> operation. C<.yield> returns
+a value to the caller like C<.return> can, but it does not destroy the
+lexical state of the coroutine. The next time the coroutine is called, it
+continues execution from the point of the last C<.yield>, not at the
+beginning of the coroutine.
 
-  my_label:
-    ...
+In a Coroutine, when we continue from a C<.yield>, the entire lexical
+environment is the same as it was when C<.yield> was called. This
+means that the parameter values don't change, even if we call the
+coroutine with different arguments later.
 
-To jump to the continuation's stored label and return the context to the state
-it was in I<at the point of its creation>, invoke the continuation:
+Coroutines are defined like any ordinary subroutine. They do not require
+any special flag or any special syntax to mark them as being a
+coroutine. However, what sets them apart is the use of the C<.yield>
+directive. C<.yield> plays several roles:
 
-  invoke $P0  # Explicit using "invoke" opcode
-  $P0()       # Same, but nicer syntax
+=over 4
 
-Even though you can use the subroutine notation C<$P0()> to invoke the
-continuation, it doesn't make any sense to pass arguments or obtain return
-values:
+=item * Identifies coroutines
 
-  $P0 = new 'Continuation'
-  set_addr $P0, my_label
+When Parrot sees a yield, it knows to create a Coroutine PMC object
+instead of a Sub PMC.
 
-  $P0(1, 2)      # WRONG!
+=item * Creates a continuation
 
-  $P1 = $P0()    # WRONG!
+Continuations, as we have already seen, allow us to continue
+execution at the point of the continuation later. It's like a snapshot of
+the current execution environment. C<.yield> creates a continuation in
+the coroutine and stores the continuation object in the coroutine object
+or later resuming from the point of the C<.yield>.
 
-=head3 Lexical Variables
+=item * Returns a value
 
-As we have seen above, we can declare a new subroutine to be a nested inner
-subroutine of an existing outer subroutine using the C<:outer> flag. The
-outer flag is used to specify the name of the outer subroutine. Where there
-may be multiple subroutines with the same name N<such is the case with
-multisubs, which we will discuss soon>, we can use the C<:subid> flag on the
-outer subroutine to give it a different--and unique--name that the lexical
-subroutines can reference in their C<:outer> declarations. Within lexical
-subroutines, the C<.lex> command defines a local variable that follows these
-scoping rules.
+C<.yield> can return a value N<or many values, or no values> to the caller.
+It is basically the same as a C<.return> in this regard.
 
-=head3 LexPad and LexInfo PMCs
+=back
 
-Information about lexical variables in a subroutine is stored in two different
-types of PMCs: The LexPad PMC that we already mentioned briefly, and the
-LexInfo PMCs which we haven't. Neither of these PMC types are really usable
-from PIR code, but are instead used by Parrot internally to store information
-about lexical variables.
+Here is a quick example of a simple coroutine:
 
-C<LexInfo> PMCs are used to store information about lexical variables at
-compile time. This is read-only information that is generated during
-compilation to represent what is known about lexical variables. Not all
-subroutines get a LexInfo PMC by default, you need to indicate to Parrot
-somehow that you require a LexInfo PMC to be created. One way to do this is
-with the C<.lex> directive that we looked at above. Of course, the C<.lex>
-directive only works for languages where the names of lexical variables are
-all known at compile time. For languages where this information isn't known,
-the subroutine can be flagged with C<:lex> instead.
+  .sub 'MyCoro'
+    .yield(1)
+    .yield(2)
+    .yield(3)
+    .return(4)
+  .end
 
-C<LexPad> PMCs are used to store run-time information about lexical variables.
-This includes their current values and their type information. LexPad PMCs are
-created at runtime for subs that have a C<LexInfo> PMC already. These are
-created each time the subroutine is invoked, which allows for recursive
-subroutine calls without overwriting variable names.
+  .sub 'main' :main
+    $I0 = MyCoro()    # 1
+    $I0 = MyCoro()    # 2
+    $I0 = MyCoro()    # 3
+    $I0 = MyCoro()    # 4
+    $I0 = MyCoro()    # 1
+    $I0 = MyCoro()    # 2
+    $I0 = MyCoro()    # 3
+    $I0 = MyCoro()    # 4
+    $I0 = MyCoro()    # 1
+    $I0 = MyCoro()    # 2
+    $I0 = MyCoro()    # 3
+    $I0 = MyCoro()    # 4
+  .end
 
-With a Subroutine PMC, you can get access to the associated LexInfo PMC by
-calling the C<'get_lexinfo'> method:
+This is obviously a contrived example, but it demonstrates how the coroutine
+stores it's state. The coroutine stores it's state when we reach a C<.yield>
+directive, and when the coroutine is called again it picks up where it last
+left off. Coroutines also handle parameters in a way that might not be
+intuitive. Here's an example of this:
 
-  $P0 = find_global "MySubroutine"
-  $P1 = $P0.'get_lexinfo'()
+  .sub 'StoredConstant'
+    .param int x
+    .yield(x)
+    .yield(x)
+    .yield(x)
+  .end
 
-Once you have the LexInfo PMC, there are a limited number of operations that
-you can call with it:
+  .sub 'main' :main
+    $I0 = StoredConstant(5)       # $I0 = 5
+    $I0 = StoredConstant(6)       # $I0 = 5
+    $I0 = StoredConstant(7)       # $I0 = 5
+    $I0 = StoredConstant(8)       # $I0 = 8
+  .end
 
-  $I0 = elements $P1    # Get the number of lexical variables from it
+Notice how even though we are calling the C<StoredConstant> coroutine with
+different arguments each time, the value of parameter C<x> doesn't change
+until the coroutine's state resets after the last C<.yield>. Remember that
+a continuation takes a snapshot of the current state, and the C<.yield>
+directive takes a continuation. The next time we call the coroutine, it
+invokes the continuation internally, and returns us to the exact same place in
+the exact same condition as we were when we called the C<.yield>. In order
+to reset the coroutine and enable it to take a new parameter, we must either
+execute a C<.return> directive or reach the end of the coroutine.
+
+=head3 Multiple Dispatch
+
+Multiple dispatch is when there are multiple subroutines in a single
+namespace with the same name. These functions must differ, however, in
+their parameter list, or "signature". All subs with the same name get
+put into a single PMC called a MultiSub. The MultiSub is like a list
+of subroutines. When the multisub is invoked, the MultiSub PMC object
+searches through the list of subroutines and searches for the one with
+the closest matching signature. The best match is the sub that gets
+invoked.
+
+MultiSubs are subroutines with the C<:multi> flag applied to them.
+MultiSubs (also called "Multis") must all differ from one another in
+the number and/or type of arguments passed to the function. Having
+two multisubs with the same function signature could result in a
+parsing error, or the later function could overwrite the former one
+in the multi.
+
+Multisubs are defined like this:
+
+  .sub 'MyMulti' :multi
+      # does whatever a MyMulti does
+  .end
+
+Multis belong to a specific namespace. Functions in different namespaces
+with the same name do not conflict with each other N<this is one of the
+reasons for having multisubs in the first place!>. It's only when
+multiple functions in a single namespace need to have the same name that
+a multi is used.
+
+Multisubs take a special designator called a I<multi signature>. The multi
+signature tells Parrot what particular combination of input parameters the
+multi accepts. Each multi will have a different signature, and Parrot will
+be able to dispatch to each one depending on the arguments passed. The
+multi signature is specified in the C<:multi> directive:
+
+  .sub 'Add' :multi(I, I)
+    .param int x
+    .param int y
+    .return(x + y)
+  .end
+
+  .sub 'Add' :multi(N, N)
+    .param num x
+    .param num y
+    .return(x + y)
+  .end
+
+  .sub 'Start' :main
+    $I0 = Add(1, 2)      # 3
+    $N0 = Add(3.14, 2.0) # 5.14
+    $S0 = Add("a", "b")  # ERROR! No (S, S) variant!
+  .end
+
+Multis can take I, N, S, and P types, but they can also use C<_> (underscore)
+to denote a wildcard, and a string that can be the name of a particular PMC
+type:
+
+  .sub 'Add' :multi(I, I)  # Two integers
+    ...
+
+  .sub 'Add' :multi(I, 'Float')  # An integer and Float PMC
+    ...
+
+                           # Two Integer PMCs
+  .sub 'Add' :multi('Integer', _)
+    ...
+
+When we call a multi PMC, Parrot will try to take the most specific
+best-match variant, and will fall back to more general variants if a perfect
+best-match cannot be found. So if we call C<'Add'(1, 2)>, Parrot will dispatch
+to the C<(I, I)> variant. If we call C<'Add'(1, "hi")>, Parrot will match the
+C<(I, _)> variant, since the string in the second argument doesn't match C<I>
+or C<'Float'>. Parrot can also choose to automatically promote one of the I,
+N, or S values to an Integer, Float, or String PMC.
+
+To make the decision about which multi variant to call, Parrot takes a
+I<Manhattan Distance> between the two. Parrot calculates the I<distance>
+between the multi signatures and the argument signature. Every difference
+counts as one step. A difference can be an autobox from a primitive type
+to a PMC, or the conversion from one primitive type to another, or the
+matching of an argument to a C<_> wildcard. After Parrot calculates the
+distance to each variant, it calls the function with the lowest distance.
+Notice that it's possible to define a variant that is impossible to call:
+for every potential combination of arguments there is a better match. This
+isn't necessarily a common occurrence, but it's something to watch out for
+in systems with a lot of multis and a limited number of data types in use.
+
+=head3 Sub PMCs
+
+Subroutines are a PMC type in Parrot. You can store them in PMC registers and
+manipulate them just as you do the other PMC types.  Look up a subroutine in
+the current namespace with the C<get_global> opcode:
+
+  $P0 = get_global "MySubName"
+
+To find a subroutine in a different namespace, first look up the appropriate
+the namespace PMC, then use that with C<get_global>:
+
+  $P0 = get_namespace "MyNamespace"
+  $P1 = get_global $P0, "MySubName"
+
+You can obviously invoke a Sub PMC:
+
+  $P0(1, 2, 3)
+
+You can get or even I<change> its name:
+
+  $S0 = $P0               # Get the current name
+  $P0 = "MyNewSubName"    # Set a new name
+
+You can get a hash of the complete metadata for the subroutine:
+
+  $P1 = inspect $P0
+
+The metadata fields in this hash are
+
+=over 4
+
+=item * pos_required
+
+The number of required positional parameters to the Sub
+
+=item * pos_optional
+
+The number of optional positional parameters to the Sub
+
+=item * named_required
+
+The number of required named parameters to the Sub
+
+=item * named_optional
+
+The number of optional named parameters to the Sub
+
+=item * pos_slurpy
+
+Returns true if the sub has a slurpy parameter to eat up extra positional args
+
+=item * named_slurpy
+
+Returns true if the sub has a slurpy parameter to eat up extra named args
+
+=back
+
+Instead of getting the whole inspection hash, you ask about individual pieces
+of metadata:
+
+  $I0 = inspect $P0, "pos_required"
+
+To discover to get the total number of defined parameters to the Sub, call the
+C<arity> method:
+
+  $I0 = $P0.'arity'()
+
+To fetch the namespace PMC that the Sub was defined into, call the
+C<get_namespace> method:
+
+  $P1 = $P0.'get_namespace'()
+
+
+
+
+
+=head2 Lexical Variables
+
+As we have seen above, we can declare a new subroutine to be a nested inner
+subroutine of an existing outer subroutine using the C<:outer> flag. The
+outer flag is used to specify the name of the outer subroutine. Where there
+may be multiple subroutines with the same name N<such is the case with
+multisubs, which we will discuss soon>, we can use the C<:subid> flag on the
+outer subroutine to give it a different--and unique--name that the lexical
+subroutines can reference in their C<:outer> declarations. Within lexical
+subroutines, the C<.lex> command defines a local variable that follows these
+scoping rules.
+
+=head3 LexPad and LexInfo PMCs
+
+Information about lexical variables in a subroutine is stored in two different
+types of PMCs: The LexPad PMC that we already mentioned briefly, and the
+LexInfo PMCs which we haven't. Neither of these PMC types are really usable
+from PIR code, but are instead used by Parrot internally to store information
+about lexical variables.
+
+C<LexInfo> PMCs are used to store information about lexical variables at
+compile time. This is read-only information that is generated during
+compilation to represent what is known about lexical variables. Not all
+subroutines get a LexInfo PMC by default, you need to indicate to Parrot
+somehow that you require a LexInfo PMC to be created. One way to do this is
+with the C<.lex> directive that we looked at above. Of course, the C<.lex>
+directive only works for languages where the names of lexical variables are
+all known at compile time. For languages where this information isn't known,
+the subroutine can be flagged with C<:lex> instead.
+
+C<LexPad> PMCs are used to store run-time information about lexical variables.
+This includes their current values and their type information. LexPad PMCs are
+created at runtime for subs that have a C<LexInfo> PMC already. These are
+created each time the subroutine is invoked, which allows for recursive
+subroutine calls without overwriting variable names.
+
+With a Subroutine PMC, you can get access to the associated LexInfo PMC by
+calling the C<'get_lexinfo'> method:
+
+  $P0 = find_global "MySubroutine"
+  $P1 = $P0.'get_lexinfo'()
+
+Once you have the LexInfo PMC, there are a limited number of operations that
+you can call with it:
+
+  $I0 = elements $P1    # Get the number of lexical variables from it
   $P0 = $P1["name"]     # Get the entry for lexical variable "name"
 
 There really isn't much else useful to do with LexInfo PMCs, they're mostly
@@ -1181,43 +1392,7 @@
 isn't properly stored in the LexPad, then they won't be available in nested
 inner subroutines, or available from C<:outer> subroutines either.
 
-=head2 Namespaces, Methods, and VTABLES
-
-Z<CHP-4-SECT-2>
-
-X<PIR (Parrot intermediate representation);methods>
-X<methods;in PIR>
-X<classes;methods>
-X<. (dot);. (method call);instruction (PIR)>
-PIR provides syntax to simplify writing methods and method calls for
-object-oriented programming. We've seen some method calls in the examples
-above, especially when we were talking about the interfaces to certain PMC
-types. We've also seen a little bit of information about classes and objects
-in the previous chapter. PIR allows you to define your own classes, and with
-those classes you can define method interfaces to them. Method calls follow
-the same Parrot calling conventions that we have seen above, including all the
-various parameter configurations, lexical scoping, and other aspects we have
-already talked about.
-
-Classes can be defined in two ways: in C and compiled to machine code, and
-in PIR. The former is how the built-in PMC types are defined, like
-C<ResizablePMCArray>, or C<Integer>. These PMC types are either built with
-Parrot at compile time, or are compiled into a shared library called a
-I<dynpmc> and loaded into Parrot at runtime. We will talk about writing PMCs
-in C, and dealing with dynpmcs in chapter 11.
-
-The second type of class can be defined in PIR at runtime. We saw some
-examples of this in the last chapter using the C<newclass> and C<subclass>
-opcodes. We also talked about class attribute values. Now, we're going to talk
-about associating subroutines with these classes, and they're called
-I<methods>. Methods are just like other normal subroutines with two major
-changes: they are marked with the C<:method> flag, and they exist in a
-I<namespace>. Before we can talk about methods, we need to discuss
-namespaces first.
-
-=head3 Namespaces
-
-Z<CHP-4-SECT-2.1>
+=head2 Namespaces
 
 X<Namespaces>
 X<.namespace>
@@ -1230,400 +1405,125 @@
 will describe later. Namespaces are also vital for defining classes and their
 methods, which we already mentioned. We'll talk about all those uses here.
 
-Namespaces are specified with the C<.namespace []> directive. The brackets
-are not optional, but the keys inside them are. Here are some examples:
-
-  .namespace [ ]               # The root namespace
-  .namespace [ "Foo" ]         # The namespace "Foo"
-  .namespace [ "Foo" ; "Bar" ] # Namespace Foo::Bar
-  .namespace                   # WRONG! The [] are needed
-
-Using semicolons, namespaces can be nested to any arbitrary depth.
-Namespaces are special types of PMC, so we can access them and manipulate
-them just like other data objects. We can get the PMC for the root
-namespace using the C<get_root_namespace> opcode:
-
-  $P0 = get_root_namespace
-
-The current namespace, which might be different from the root namespace
-can be retrieved with the C<get_namespace> opcode:
-
-  $P0 = get_namespace             # get current namespace PMC
-  $P0 = get_namespace ["Foo"]     # get PMC for namespace "Foo"
-
-Namespaces are arranged into a large n-ary tree. There is the root namespace
-at the top of the tree, and in the root namespace are various special HLL
-namespaces. Each HLL compiler gets its own HLL namespace where it can store
-its data during compilation and runtime. Each HLL namespace may have a large
-hierarchy of other namespaces. We'll talk more about HLL namespaces and their
-significance in chapter 10.
-
-The root namespace is a busy place. Everybody could be lazy and use it to store
-all their subroutines and global variables, and then we would run into all
-sorts of collisions. One library would define a function "Foo", and then
-another library could try to create another subroutine with the same name.
-This is called I<namespace pollution>, because everybody is trying to put
-things into the root namespace, and those things are all unrelated to each
-other. Best practices requires that namespaces be used to hold private
-information away from public information, and to keep like things together.
-
-As an example, the namespace C<Integers> could be used to store subroutines
-that deal with integers. The namespace C<images> could be used to store
-subroutines that deal with creating and manipulating images. That way, when
-we have a subroutine that adds two numbers together, and a subroutine that
-performs additive image composition, we can name them both C<add> without any
-conflict or confusion. And within the C<image> namespace we could have sub
-namespaces for C<jpeg> and C<MRI> and C<schematics>, and each of these could
-have a C<add> method without getting into each other's way.
-
-The short version is this: use namespaces. There aren't any penalties to them,
-and they do a lot of work to keep things organized and separated.
-
-=head3 Namespace PMC
-
-The C<.namespace> directive that we've seen sets the current namespace. In
-PIR code, we have multiple ways to address a namespace:
-
-  # Get namespace "a/b/c" starting at the root namespace
-  $P0 = get_root_namespace ["a" ; "b" ; "c"]
-
-  # Get namespace "a/b/c" starting in the current HLL namespace.
-  $P0 = get_hll_namespace ["a" ; "b" ; "c"]
-  # Same
-  $P0 = get_root_namespace ["hll" ; "a" ; "b" ; "c"]
-
-  # Get namespace "a/b/c" starting in the current namespace
-  $P0 = get_namespace ["a" ; "b" ; "c"]
-
-Once we have a namespace PMC we can retrieve global variables and
-subroutine PMCs from it using the following functions:
-
-  $P1 = get_global $S0            # Get global in current namespace
-  $P1 = get_global ["Foo"], $S0   # Get global in namespace "Foo"
-  $P1 = get_global $P0, $S0       # Get global in $P0 namespace PMC
-
-=head3 Operations on the Namespace PMC
-
-We've seen above how to find a Namespace PMC. Once you have it, there are a
-few things you can do with it. You can find methods and variables that are
-stored in the namespace, or you can add new ones:
-
-  $P0 = get_namespace
-  $P0.'add_namespace'($P1)      # Add Namespace $P1 to $P0
-  $P1 = $P0.'find_namespace'("MyOtherNamespace")
-
-  # Find namespace "MyNamespace" in $P0, create it if it
-  #    doesn't exist
-  $P1 = $P0.'make_namespace'("MyNamespace")
-
-  $P0.'add_sub'("MySub", $P2)   # Add Sub PMC $P2 to the namespace
-  $P1 = $P0.'find_sub'("MySub") # Find it
-
-  $P0.'add_var'("MyVar", $P3)   # Add variable "MyVar" in $P3
-  $P1 = $P0.'find_var'("MyVar") # Find it
-
-  # Return the name of Namespace $P0 as a ResizableStringArray
-  $P3 = $P0.'get_name'()
-
-  # Find the parent namespace that contains this one:
-  $P5 = $P0.'get_parent'()
-
-  # Get the Class PMC associated with this namespace:
-  $P6 = $P0.'get_class'()
-
-There are a few other operations that can be done on Namespaces, but none
-as interesting as these. We'll talk about Namespaces throughout the rest
-of this chapter.
-
-
-
-
-=head2 Coroutines
-
-X<PIR;Coroutines>
-X<Coroutines>
-We've mentioned coroutines several times before, and we're finally going
-to explain what they are. Coroutines are similar to subroutines except
-that they have an internal notion of I<state> N<And the cool new name!>.
-Coroutines, in addition to performing a normal C<.return> to return
-control flow back to the caller and destroy the lexical environment of
-the subroutine, may also perform a C<.yield> operation. C<.yield> returns
-a value to the caller like C<.return> can, but it does not destroy the
-lexical state of the coroutine. The next time the coroutine is called, it
-continues execution from the point of the last C<.yield>, not at the
-beginning of the coroutine.
-
-In a Coroutine, when we continue from a C<.yield>, the entire lexical
-environment is the same as it was when C<.yield> was called. This
-means that the parameter values don't change, even if we call the
-coroutine with different arguments later.
-
-=head3 Defining Coroutines
-
-Coroutines are defined like any ordinary subroutine. They do not require
-any special flag or any special syntax to mark them as being a
-coroutine. However, what sets them apart is the use of the C<.yield>
-directive. C<.yield> plays several roles:
-
-=over 4
-
-=item * Identifies coroutines
-
-When Parrot sees a yield, it knows to create a Coroutine PMC object
-instead of a Sub PMC.
-
-=item * Creates a continuation
-
-Continuations, as we have already seen, allow us to continue
-execution at the point of the continuation later. It's like a snapshot of
-the current execution environment. C<.yield> creates a continuation in
-the coroutine and stores the continuation object in the coroutine object
-or later resuming from the point of the C<.yield>.
-
-=item * Returns a value
-
-C<.yield> can return a value N<or many values, or no values> to the caller.
-It is basically the same as a C<.return> in this regard.
-
-=back
-
-Here is a quick example of a simple coroutine:
-
-  .sub 'MyCoro'
-    .yield(1)
-    .yield(2)
-    .yield(3)
-    .return(4)
-  .end
-
-  .sub 'main' :main
-    $I0 = MyCoro()    # 1
-    $I0 = MyCoro()    # 2
-    $I0 = MyCoro()    # 3
-    $I0 = MyCoro()    # 4
-    $I0 = MyCoro()    # 1
-    $I0 = MyCoro()    # 2
-    $I0 = MyCoro()    # 3
-    $I0 = MyCoro()    # 4
-    $I0 = MyCoro()    # 1
-    $I0 = MyCoro()    # 2
-    $I0 = MyCoro()    # 3
-    $I0 = MyCoro()    # 4
-  .end
-
-This is obviously a contrived example, but it demonstrates how the coroutine
-stores it's state. The coroutine stores it's state when we reach a C<.yield>
-directive, and when the coroutine is called again it picks up where it last
-left off. Coroutines also handle parameters in a way that might not be
-intuitive. Here's an example of this:
-
-  .sub 'StoredConstant'
-    .param int x
-    .yield(x)
-    .yield(x)
-    .yield(x)
-  .end
-
-  .sub 'main' :main
-    $I0 = StoredConstant(5)       # $I0 = 5
-    $I0 = StoredConstant(6)       # $I0 = 5
-    $I0 = StoredConstant(7)       # $I0 = 5
-    $I0 = StoredConstant(8)       # $I0 = 8
-  .end
-
-Notice how even though we are calling the C<StoredConstant> coroutine with
-different arguments each time, the value of parameter C<x> doesn't change
-until the coroutine's state resets after the last C<.yield>. Remember that
-a continuation takes a snapshot of the current state, and the C<.yield>
-directive takes a continuation. The next time we call the coroutine, it
-invokes the continuation internally, and returns us to the exact same place in
-the exact same condition as we were when we called the C<.yield>. In order
-to reset the coroutine and enable it to take a new parameter, we must either
-execute a C<.return> directive or reach the end of the coroutine.
-
-=head2 Multiple Dispatch
-
-Multiple dispatch is when there are multiple subroutines in a single
-namespace with the same name. These functions must differ, however, in
-their parameter list, or "signature". All subs with the same name get
-put into a single PMC called a MultiSub. The MultiSub is like a list
-of subroutines. When the multisub is invoked, the MultiSub PMC object
-searches through the list of subroutines and searches for the one with
-the closest matching signature. The best match is the sub that gets
-invoked.
-
-=head3 Defining MultiSubs
-
-MultiSubs are subroutines with the C<:multi> flag applied to them.
-MultiSubs (also called "Multis") must all differ from one another in
-the number and/or type of arguments passed to the function. Having
-two multisubs with the same function signature could result in a
-parsing error, or the later function could overwrite the former one
-in the multi.
-
-Multisubs are defined like this:
-
-  .sub 'MyMulti' :multi
-      # does whatever a MyMulti does
-  .end
-
-Multis belong to a specific namespace. Functions in different namespaces
-with the same name do not conflict with each other N<this is one of the
-reasons for having multisubs in the first place!>. It's only when
-multiple functions in a single namespace need to have the same name that
-a multi is used.
-
-Multisubs take a special designator called a I<multi signature>. The multi
-signature tells Parrot what particular combination of input parameters the
-multi accepts. Each multi will have a different signature, and Parrot will
-be able to dispatch to each one depending on the arguments passed. The
-multi signature is specified in the C<:multi> directive:
-
-  .sub 'Add' :multi(I, I)
-    .param int x
-    .param int y
-    .return(x + y)
-  .end
-
-  .sub 'Add' :multi(N, N)
-    .param num x
-    .param num y
-    .return(x + y)
-  .end
-
-  .sub 'Start' :main
-    $I0 = Add(1, 2)      # 3
-    $N0 = Add(3.14, 2.0) # 5.14
-    $S0 = Add("a", "b")  # ERROR! No (S, S) variant!
-  .end
-
-Multis can take I, N, S, and P types, but they can also use C<_> (underscore)
-to denote a wildcard, and a string that can be the name of a particular PMC
-type:
+Namespaces are specified with the C<.namespace []> directive. The brackets
+are not optional, but the keys inside them are. Here are some examples:
 
-  .sub 'Add' :multi(I, I)  # Two integers
-    ...
+  .namespace [ ]               # The root namespace
+  .namespace [ "Foo" ]         # The namespace "Foo"
+  .namespace [ "Foo" ; "Bar" ] # Namespace Foo::Bar
+  .namespace                   # WRONG! The [] are needed
 
-  .sub 'Add' :multi(I, 'Float')  # An integer and Float PMC
-    ...
+Using semicolons, namespaces can be nested to any arbitrary depth.
+Namespaces are special types of PMC, so we can access them and manipulate
+them just like other data objects. We can get the PMC for the root
+namespace using the C<get_root_namespace> opcode:
 
-                           # Two Integer PMCs
-  .sub 'Add' :multi('Integer', _)
-    ...
+  $P0 = get_root_namespace
 
-When we call a multi PMC, Parrot will try to take the most specific
-best-match variant, and will fall back to more general variants if a perfect
-best-match cannot be found. So if we call C<'Add'(1, 2)>, Parrot will dispatch
-to the C<(I, I)> variant. If we call C<'Add'(1, "hi")>, Parrot will match the
-C<(I, _)> variant, since the string in the second argument doesn't match C<I>
-or C<'Float'>. Parrot can also choose to automatically promote one of the I,
-N, or S values to an Integer, Float, or String PMC.
+The current namespace, which might be different from the root namespace
+can be retrieved with the C<get_namespace> opcode:
 
-To make the decision about which multi variant to call, Parrot takes a
-I<Manhattan Distance> between the two. Parrot calculates the I<distance>
-between the multi signatures and the argument signature. Every difference
-counts as one step. A difference can be an autobox from a primitive type
-to a PMC, or the conversion from one primitive type to another, or the
-matching of an argument to a C<_> wildcard. After Parrot calculates the
-distance to each variant, it calls the function with the lowest distance.
-Notice that it's possible to define a variant that is impossible to call:
-for every potential combination of arguments there is a better match. This
-isn't necessarily a common occurrence, but it's something to watch out for
-in systems with a lot of multis and a limited number of data types in use.
+  $P0 = get_namespace             # get current namespace PMC
+  $P0 = get_namespace ["Foo"]     # get PMC for namespace "Foo"
 
+Namespaces are arranged into a large n-ary tree. There is the root namespace
+at the top of the tree, and in the root namespace are various special HLL
+namespaces. Each HLL compiler gets its own HLL namespace where it can store
+its data during compilation and runtime. Each HLL namespace may have a large
+hierarchy of other namespaces. We'll talk more about HLL namespaces and their
+significance in chapter 10.
 
-=head2 Classes and Objects
+The root namespace is a busy place. Everybody could be lazy and use it to store
+all their subroutines and global variables, and then we would run into all
+sorts of collisions. One library would define a function "Foo", and then
+another library could try to create another subroutine with the same name.
+This is called I<namespace pollution>, because everybody is trying to put
+things into the root namespace, and those things are all unrelated to each
+other. Best practices requires that namespaces be used to hold private
+information away from public information, and to keep like things together.
 
-It may seem more appropriate for a discussion of PIR's support for classes
-and objects to reside in its own chapter, instead of appearing in a generic
-chapter about PIR programming "basics". However, part of PIR's core
-functionality is its support for object-oriented programming. PIR doesn't
-use all the fancy syntax as other OO languages, and it doesn't even support
-all the features that most modern OO languages have. What PIR does have is
-support for some of the basic structures and abilities, the necessary subset
-to construct richer and higher-level object systems.
+As an example, the namespace C<Integers> could be used to store subroutines
+that deal with integers. The namespace C<images> could be used to store
+subroutines that deal with creating and manipulating images. That way, when
+we have a subroutine that adds two numbers together, and a subroutine that
+performs additive image composition, we can name them both C<add> without any
+conflict or confusion. And within the C<image> namespace we could have sub
+namespaces for C<jpeg> and C<MRI> and C<schematics>, and each of these could
+have a C<add> method without getting into each other's way.
 
-=head2 PMCs as Classes
+The short version is this: use namespaces. There aren't any penalties to them,
+and they do a lot of work to keep things organized and separated.
 
-PMCs aren't exactly "classes" in the way that this term is normally used in
-object-oriented programming languages. They are polymorphic data items that
-can be one of a large variety of predefined types. As we have seen briefly,
-and as we will see in more depth later, PMCs have a standard interface called
-the VTABLE interface. VTABLEs are a standard list of functions that all PMCs
-implement N<or, PMCs can choose not to implement each interface explicitly and
-instead let Parrot call the default implementations>.
+=head3 Namespace PMC
 
-VTABLEs are very strict: There are a fixed number with fixed names and
-fixed argument lists. You can't just create any random VTABLE interface that
-you want to create, you can only make use of the ones that Parrot supplies
-and expects. To circumvent this limitation, PMCs may have METHODS in
-addition to VTABLEs. METHODs are arbitrary code functions that can be
-written in C, may have any name, and may implement any behavior.
+The C<.namespace> directive that we've seen sets the current namespace. In
+PIR code, we have multiple ways to address a namespace:
 
-=head2 VTABLE Interfaces
+  # Get namespace "a/b/c" starting at the root namespace
+  $P0 = get_root_namespace ["a" ; "b" ; "c"]
 
-Internally, all operations on PMCs are performed by calling various VTABLE
-interfaces.
+  # Get namespace "a/b/c" starting in the current HLL namespace.
+  $P0 = get_hll_namespace ["a" ; "b" ; "c"]
+  # Same
+  $P0 = get_root_namespace ["hll" ; "a" ; "b" ; "c"]
 
+  # Get namespace "a/b/c" starting in the current namespace
+  $P0 = get_namespace ["a" ; "b" ; "c"]
 
+Once we have a namespace PMC we can retrieve global variables and
+subroutine PMCs from it using the following functions:
 
-=head2 Class and Object PMCs
+  $P1 = get_global $S0            # Get global in current namespace
+  $P1 = get_global ["Foo"], $S0   # Get global in namespace "Foo"
+  $P1 = get_global $P0, $S0       # Get global in $P0 namespace PMC
 
-The details about various PMC classes are managed by the Class PMC. Class PMCs
-contain information about the class, available methods, the inheritance
-hierarchy of the class, and various other details. Classes can be created
-with the C<newclass> opcode:
+=head3 Operations on the Namespace PMC
 
-  $P0 = newclass "MyClass"
+We've seen above how to find a Namespace PMC. Once you have it, there are a
+few things you can do with it. You can find methods and variables that are
+stored in the namespace, or you can add new ones:
 
-Once we have created the class PMC, we can instantiate objects of that class
-using the C<new> opcode. The C<new> opcode takes either the class name or the
-Class PMC as an argument:
+  $P0 = get_namespace
+  $P0.'add_namespace'($P1)      # Add Namespace $P1 to $P0
+  $P1 = $P0.'find_namespace'("MyOtherNamespace")
 
-  $P1 = new $P0        # $P0 is the Class PMC
-  $P2 = new "MyClass"  # Same
+  # Find namespace "MyNamespace" in $P0, create it if it
+  #    doesn't exist
+  $P1 = $P0.'make_namespace'("MyNamespace")
 
-The C<new> opcode can create two different types of PMC. The first type are
-the built-in core PMC classes. The built-in PMCs are written in C and cannot
-be extended from PIR without subclassing. However, you can also create
-user-defined PMC types in PIR. User-defined PMCs use the Object PMC type for
-instantiation. Object PMCs are used for all user-defined type and keep track
-of the methods and VTABLE override definitions. We're going to talk about
-methods and VTABLE overrides in the next chapter.
+  $P0.'add_sub'("MySub", $P2)   # Add Sub PMC $P2 to the namespace
+  $P1 = $P0.'find_sub'("MySub") # Find it
 
-=head2 Subclassing PMCs
+  $P0.'add_var'("MyVar", $P3)   # Add variable "MyVar" in $P3
+  $P1 = $P0.'find_var'("MyVar") # Find it
 
-Existing built-in PMC types can be subclassed to associate additional data
-and methods with that PMC type. Subclassed PMC types act like their PMC
-base types, by sharing the same VTABLE methods and underlying data types.
-However, the subclass can define additional methods and attribute data
-storage. If necessary new VTABLE interfaces can be defined in PIR and old
-VTABLE methods can be overridden using PIR. We'll talk about defining
-methods and VTABLE interface overrides in the next chapter.
+  # Return the name of Namespace $P0 as a ResizableStringArray
+  $P3 = $P0.'get_name'()
 
-Creating a new subclass of an existing PMC class is done using the
-C<subclass> keyword:
+  # Find the parent namespace that contains this one:
+  $P5 = $P0.'get_parent'()
 
-  # create an anonymous subclass
-  $P0 = subclass 'ResizablePMCArray'
+  # Get the Class PMC associated with this namespace:
+  $P6 = $P0.'get_class'()
 
-  # create a subclass named "MyArray"
-  $P0 = subclass 'ResizablePMCArray', 'MyArray'
+There are a few other operations that can be done on Namespaces, but none
+as interesting as these. We'll talk about Namespaces throughout the rest
+of this chapter.
 
-This returns a C<Class> PMC which can be used to create and modify the
-class by adding attributes or creating objects of that class. You can also
-use the new class PMC to create additional subclasses:
 
-  $P0 = subclass 'ResizablePMCArray', 'MyArray'
-  $P1 = subclass $P0, 'MyOtherArray'
+=head2 Classes and Objects
 
-Once you have created these classes, you can create them like normal with
-the C<new> keyword:
+It may seem more appropriate for a discussion of PIR's support for classes
+and objects to reside in its own chapter, instead of appearing in a generic
+chapter about PIR programming "basics". However, part of PIR's core
+functionality is its support for object-oriented programming. PIR doesn't
+use all the fancy syntax as other OO languages, and it doesn't even support
+all the features that most modern OO languages have. What PIR does have is
+support for some of the basic structures and abilities, the necessary subset
+to construct richer and higher-level object systems.
 
-  $P0 = new 'MyArray'
-  $P1 = new 'MyOtherArray'
 
-=head2 Attributes
+=head3 Attributes
 
 Classes and subclasses can be given attributes N<in addition to methods,
 which we will talk about in the next chapter> which are named data fields.
@@ -1651,7 +1551,26 @@
 both of the ones in the example are. They can be integers, numbers
 or PMCs too.
 
-=head3 Calling Methods
+=head3 Methods
+
+PIR provides syntax to simplify writing methods and method calls for
+object-oriented programming. We've seen some method calls in the examples
+above, especially when we were talking about the interfaces to certain PMC
+types. We've also seen a little bit of information about classes and objects
+in the previous chapter. PIR allows you to define your own classes, and with
+those classes you can define method interfaces to them. Method calls follow
+the same Parrot calling conventions that we have seen above, including all the
+various parameter configurations, lexical scoping, and other aspects we have
+already talked about.
+
+The second type of class can be defined in PIR at runtime. We saw some
+examples of this in the last chapter using the C<newclass> and C<subclass>
+opcodes. We also talked about class attribute values. Now, we're going to talk
+about associating subroutines with these classes, and they're called
+I<methods>. Methods are just like other normal subroutines with two major
+changes: they are marked with the C<:method> flag, and they exist in a
+I<namespace>. Before we can talk about methods, we need to discuss
+namespaces first.
 
 Z<CHP-4-SECT-2.2>
 
@@ -1753,6 +1672,65 @@
 
   (res1, res2) = obj."method"(arg1, arg2)
 
+
+=head3 Introspection
+
+The details about various PMC classes are managed by the Class PMC. Class PMCs
+contain information about the class, available methods, the inheritance
+hierarchy of the class, and various other details. Classes can be created
+with the C<newclass> opcode:
+
+  $P0 = newclass "MyClass"
+
+Once we have created the class PMC, we can instantiate objects of that class
+using the C<new> opcode. The C<new> opcode takes either the class name or the
+Class PMC as an argument:
+
+  $P1 = new $P0        # $P0 is the Class PMC
+  $P2 = new "MyClass"  # Same
+
+The C<new> opcode can create two different types of PMC. The first type are
+the built-in core PMC classes. The built-in PMCs are written in C and cannot
+be extended from PIR without subclassing. However, you can also create
+user-defined PMC types in PIR. User-defined PMCs use the Object PMC type for
+instantiation. Object PMCs are used for all user-defined type and keep track
+of the methods and VTABLE override definitions. We're going to talk about
+methods and VTABLE overrides in the next chapter.
+
+=head2 Subclassing PMCs
+
+Existing built-in PMC types can be subclassed to associate additional data
+and methods with that PMC type. Subclassed PMC types act like their PMC
+base types, by sharing the same VTABLE methods and underlying data types.
+However, the subclass can define additional methods and attribute data
+storage. If necessary new VTABLE interfaces can be defined in PIR and old
+VTABLE methods can be overridden using PIR. We'll talk about defining
+methods and VTABLE interface overrides in the next chapter.
+
+Creating a new subclass of an existing PMC class is done using the
+C<subclass> keyword:
+
+  # create an anonymous subclass
+  $P0 = subclass 'ResizablePMCArray'
+
+  # create a subclass named "MyArray"
+  $P0 = subclass 'ResizablePMCArray', 'MyArray'
+
+This returns a C<Class> PMC which can be used to create and modify the
+class by adding attributes or creating objects of that class. You can also
+use the new class PMC to create additional subclasses:
+
+  $P0 = subclass 'ResizablePMCArray', 'MyArray'
+  $P1 = subclass $P0, 'MyOtherArray'
+
+Once you have created these classes, you can create them like normal with
+the C<new> keyword:
+
+  $P0 = new 'MyArray'
+  $P1 = new 'MyOtherArray'
+
+
+
 =head3 Vtable Overrides
 
 PMCs all subscribe to a common interface of functions called X<VTABLE>
@@ -1760,9 +1738,7 @@
 perform very specific low-level tasks on the PMC. The term VTABLE was
 originally a shortened form of the name "virtual function table",
 although that name isn't used any more by the developers, or in any of
-the documentation N<In fact, if you say "virtual function table" to
-one of the developers, they probably won't know what you are talking
-about>. The virtual functions in the VTABLE, called X<VTABLE
+the documentation. The virtual functions in the VTABLE, called X<VTABLE
 interfaces> VTABLE interfaces, are similar to ordinary functions and
 methods in many respects. VTABLE interfaces are occasionally called
 "VTABLE functions", or "VTABLE methods" or even "VTABLE entries" in
@@ -1840,7 +1816,7 @@
 declaration.
 
 
-=head2 Roles
+=head3 Roles
 
 As we've seen above and in the previous chapter, Class PMCs and NameSpace
 PMCs work to keep classes and methods together in a logical way. There is
@@ -1879,18 +1855,11 @@
 interface.  
 
 
-=head2 Input and Output
+=head2 Filehandles
 
 Like almost everything else in Parrot, input and output are handled by PMCs.
-Using the C<print> opcode or the C<say> opcode like we've already seen in
-some examples does this internally without your knowledge. However, we can
-do it explicitly too. First we'll talk about basic I/O, and then we will talk
-about using PMC-based filehandles for more advanced operations.
-
-=head2 Basic I/O Opcodes
 
-We've seen C<print> and C<say>. These are carry-over artifacts from Perl, when
-Parrot was simply the VM backend to the Perl 6 language. C<print> prints
+We've seen C<print> and C<say>. C<print> prints
 the given string argument, or the stringified form of the argument, if it's
 not a string, to standard output. C<say> does the same thing but also appends
 a trailing newline to it. Another opcode worth mentioning is the C<printerr>
@@ -1914,8 +1883,6 @@
 
 =end PIR
 
-=head2 Filehandles
-
 The ops we have seen so far are useful if all your I/O operations are limited
 to the standard streams. However, there are plenty of other places where
 you might want to get data from and send data to. Things like files, sockets,
@@ -2210,7 +2177,7 @@
   my_handler:
     ...
 
-=head3 Rethrowing and Exception Propagation
+=head3 Rethrowing Exceptions
 
 Exception handlers are nested and are stored in a stack. This is because not
 all handlers are intended to handle all exceptions. If a handler cannot deal


More information about the parrot-commits mailing list