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

allison at svn.parrot.org allison at svn.parrot.org
Fri May 15 04:08:38 UTC 2009


Author: allison
Date: Fri May 15 04:08:26 2009
New Revision: 38787
URL: https://trac.parrot.org/parrot/changeset/38787

Log:
[book] Gutting the PASM chapter for the PIR chapter (a better place to
teach the introductory stuff).

Modified:
   trunk/docs/book/ch03_pir.pod
   trunk/docs/book/ch09_pasm.pod

Modified: trunk/docs/book/ch03_pir.pod
==============================================================================
--- trunk/docs/book/ch03_pir.pod	Fri May 15 03:09:05 2009	(r38786)
+++ trunk/docs/book/ch03_pir.pod	Fri May 15 04:08:26 2009	(r38787)
@@ -170,6 +170,7 @@
 
 =head3 Control Flow
 
+
 =head3 Subroutines
 
 A PIR subroutine starts with the C<.sub> directive and ends with the C<.end> directive. Parameter declarations use the C<.param> directive, and look a lot like named variable declarations. The following example declares a subroutined named C<greeting>, that takes a single string parameter named C<hello>:
@@ -181,13 +182,136 @@
 
 =head2 Working with Numbers
 
-Integers and numbers use platform-dependent sizes and
-limitationsN<There are a few exceptions to this; Parrot smooths out some of the
-bumps and inconsistencies so that PIR code behaves the same way on all
-supported platforms>. Parrot treats both I and N registers as
-signed quantities internally for the purposes of arithmetic. Parrot's floating
-point values and operations all comply with the IEEE 754 standard.
+X<PASM (Parrot assembly language);math operations>
+PIR has a full set of math instructions. These work with integers,
+floating-point numbers, and numeric PMCs. Most of the major math instructions have two- and
+three-argument forms:
+
+=begin PIR
+
+  $I10 = $I11 + $I2
+  $I0 += $I1
+
+=end PASM
+
+The three-argument form of C<+> stores the sum
+of the two arguments in the result variable. The two-argument form
+adds the first variable to the second and stores the result back in
+the first variable.
+
+The arguments can be Parrot variables or constants, but they
+must be compatible with the type of the result.
+Generally, "compatible" means that the result and arguments have to
+be the same type, but there are a few exceptions:
+
+=begin PASM
+
+  $P0 = $P1 - 2
+  $P0 = $P1 - 1.5
+
+=end PASM
+
+If the result is an integer type, like C<$I0>, the arguments must be integer variables or constants. A
+floating-point result, like C<$N0>, usually requires
+floating-point arguments, but many math instructions also allow the final
+argument to be an integer. Instructions with a PMC result may
+accept an integer, floating-point, or PMC final argument:
+
+=begin PASM
+
+  mul P0, P1             # P0 *= P1
+  mul P0, I1
+  mul P0, N1
+  mul P0, P1, P2         # P0 = P1 * P2
+  mul P0, P1, I2
+  mul P0, P1, N2
+
+=end PASM
+
+
+
+We won't list every math opcode here, but we'll list some of the most common
+ones. You can get a complete list in "PASM Opcodes" in Chapter 11.
+
+=head4 Unary math opcodes
+
+Z<CHP-9-SECT-2.3.1>
+
+The unary opcodes have either a destination argument and a source
+argument, or a single argument as destination and source. Some of the
+most common unary math opcodes are C<inc> (increment), C<dec>
+(decrement), C<abs> (absolute value), C<neg> (negate), and C<fact>
+(factorial):
+
+=begin PASM
+
+  abs N0, -5.0  # the absolute value of -5.0 is 5.0
+  fact I1, 5    # the factorial of 5 is 120
+  inc I1        # 120 incremented by 1 is 121
+
+=end PASM
+
+=head4 Binary math opcodes
+
+Z<CHP-9-SECT-2.3.2>
+
+X<PASM (Parrot assembly language);math operations;binary>
+Binary opcodes have two source arguments and a destination argument, and we
+saw examples of these types above. As we mentioned before, most binary math
+opcodes have a two-argument form in which the first argument is both a source
+and the destination. Parrot provides C<add>X<add opcode (PASM)> (addition),
+C<sub>X<sub opcode (PASM)> (subtraction), C<mul>X<mul opcode (PASM)>
+(multiplication), C<div>X<div opcode (PASM)> (division), and C<pow>X<pow
+opcode (PASM)> (exponent) opcodes, as well as two different modulus
+operations. C<mod>X<mod opcode (PASM)> is Parrot's implementation of modulus,
+and C<cmod>X<cmod opcode (PASM)> performs an operation equivalent the C<%>
+operator from the C programming language. It also provides C<gcd>X<gcd opcode
+(PASM)> (greatest common divisor) and C<lcm>X<lcm opcode (PASM)> (least common
+multiple).
+
+=begin PASM
+
+  div I0, 12, 5   # I0 = 12 / 5
+  mod I0, 12, 5   # I0 = 12 % 5
+
+=end PASM
+
+=head4 Floating-point operations
+
+Z<CHP-9-SECT-2.3.3>
+
+X<PASM (Parrot assembly language);math operations;floating-point>
+Although most of the math operations work with both floating-point numbers
+and integers, a few require floating-point destination registers. Among these
+are C<ln> (natural log), C<log2> (log base 2), C<log10> (log base 10), and
+C<exp> (I<e>G<x>), as well as a full set of trigonometric opcodes such as
+C<sin> (sine), C<cos> (cosine), C<tan> (tangent), C<sec> (secant), C<cosh>
+(hyperbolic cosine), C<tanh> (hyperbolic tangent), C<sech> (hyperbolic secant),
+C<asin> (arc sine), C<acos> (arc cosine), C<atan> (arc tangent), C<asec> (arc
+secant), C<exsec> (exsecant), C<hav> (haversine), and C<vers> (versine). All
+angle arguments for the X<trigonometric functions (PASM)> trigonometric
+functions are in radians:
 
+=begin PASM
+
+  sin N1, N0
+  exp N1, 2
+
+=end PASM
+
+The majority of the floating-point operations have a single source argument
+and a single destination argument. Even though the destination must be a
+floating-point register, the source can be either an integer or floating-point
+number.
+
+The C<atan>X<atan opcode (PASM)> opcode also has a three-argument variant that
+implements C's C<atan2()>:
+
+=begin PASM
+
+  atan N0, 1, 1
+
+=end PASM
 
 
 
@@ -231,110 +355,1317 @@
   This is a multi-line string literal. Notice that
   it doesn't use quotation marks.
 
-  End_Token
+  End_Token
+
+Strings are buffers of variable-sized data. The most common use of string
+registers and variables is to store textual data. String registers I<may> also be
+buffers for binary or other non-textual data, though this is rareN<In general,
+a custom PMC is more useful>.  Parrot strings are flexible and powerful, to
+account for all the complexity of human-readable (and computer-representable)
+textual data.
+
+X<PASM (Parrot assembly language);string operations>
+String operations work with string registers and string-like PMCs. String operations on PMC registers require all their string
+arguments to be String PMCs.
+
+=head4 Concatenating strings
+
+Z<CHP-9-SECT-2.4.1>
+
+X<PASM (Parrot assembly language);string operations;concatenation>
+Use the C<concat>X<concat opcode (PASM)> opcode to concatenate
+strings. With string register or string constant arguments, C<concat>
+has both a two-argument and a three-argument form. The first argument
+is a source and a destination in the two-argument form:
+
+=begin PASM
+
+  set S0, "ab"
+  concat S0, "cd"     # S0 has "cd" appended
+  print S0            # prints "abcd"
+  print "\n"
+
+  concat S1, S0, "xy" # S1 is the string S0 with "xy" appended
+  print S1            # prints "abcdxy"
+  print "\n"
+  end
+
+=end PASM
+
+The first C<concat> concatenates the string "cd" onto the string "ab" in
+C<S0>. It generates a new string "abcd" and changes C<S0> to point to the
+new string. The second C<concat> concatenates "xy" onto the string "abcd"
+in C<S0> and stores the new string in C<S1>.
+
+X<PMCs (Polymorphic Containers);concatenation>
+For PMC registers, C<concat> has only a three-argument form with
+separate registers for source and destination:
+
+=begin PASM
+
+  new P0, "String"
+  new P1, "String"
+  new P2, "String"
+  set P0, "ab"
+  set P1, "cd"
+  concat P2, P0, P1
+  print P2            # prints abcd
+  print "\n"
+  end
+
+=end PASM
+
+Here, C<concat> concatenates the strings in C<P0> and C<P1> and stores
+the result in C<P2>.
+
+=head4 Repeating strings
+
+Z<CHP-9-SECT-2.4.2>
+
+X<PASM (Parrot assembly language);string operations;repeating strings>
+The C<repeat>X<repeat opcode (PASM)> opcode repeats a string a certain
+number of times:
+
+=begin PASM
+
+  set S0, "x"
+  repeat S1, S0, 5  # S1 = S0 x 5
+  print S1          # prints "xxxxx"
+  print "\n"
+  end
+
+=end PASM
+
+In this example, C<repeat> generates a new string with "x" repeated
+five times and stores a pointer to it in C<S1>.
+
+=head4 Length of a string
+
+Z<CHP-9-SECT-2.4.3>
+
+X<PASM (Parrot assembly language);string operations;length>
+The C<length>X<length opcode (PASM)> opcode returns the length of a
+string in characters. This won't be the same as the length in bytes
+for multibyte encoded strings:
+
+=begin PASM
+
+  set S0, "abcd"
+  length I0, S0                # the length is 4
+  print I0
+  print "\n"
+  end
+
+=end PASM
+
+C<length> doesn't have an equivalent for PMC strings.
+
+=head4 Substrings
+
+Z<CHP-9-SECT-2.4.4>
+
+X<PASM (Parrot assembly language);string operations;substrings>
+The simplest version of the C<substr>X<substr opcode (PASM)> opcode
+takes four arguments: a destination register, a string, an offset
+position, and a length. It returns a substring of the original string,
+starting from the offset position (0 is the first character) and
+spanning the length:
+
+=begin PASM
+
+  substr S0, "abcde", 1, 2        # S0 is "bc"
+
+=end PASM
+
+This example extracts a two-character string from "abcde" at a
+one-character offset from the beginning of the string (starting with
+the second character). It generates a new string, "bc", in the
+destination register C<S0>.
+
+When the offset position is negative, it counts backward from the end
+of the string. So an offset of -1 starts at the last character of the
+string.
+
+C<substr> also has a five-argument form, where the fifth argument is a
+string to replace the substring. This modifies the second argument and
+returns the removed substring in the destination register.
+
+=begin PASM
+
+  set S1, "abcde"
+  substr S0, S1, 1, 2, "XYZ"
+  print S0                        # prints "bc"
+  print "\n"
+  print S1                        # prints "aXYZde"
+  print "\n"
+  end
+
+=end PASM
+
+This replaces the substring "bc" in C<S1> with the string "XYZ", and
+returns "bc" in C<S0>.
+
+When the offset position in a replacing C<substr> is one character
+beyond the original string length, C<substr> appends the replacement
+string just like the C<concat> opcode. If the replacement string is an
+empty string, the characters are just removed from the original
+string.
+
+When you don't need to capture the replaced string, there's an
+optimized version of C<substr> that just does a replace without
+returning the removed substring.
+
+=begin PASM
+
+  set S1, "abcde"
+  substr S1, 1, 2, "XYZ"
+  print S1                        # prints "aXYZde"
+  print "\n"
+  end
+
+=end PASM
+
+The PMC versions of C<substr> are not yet implemented.
+
+=head4 Chopping strings
+
+Z<CHP-9-SECT-2.4.5>
+
+X<PASM (Parrot assembly language);string operations;chopping strings>
+The C<chopn>X<chopn opcode (PASM)> opcode removes characters from the
+end of a string. It takes two arguments: the string to modify and the
+count of characters to remove.
+
+=begin PASM
+
+  set S0, "abcde"
+  chopn S0, 2
+  print S0         # prints "abc"
+  print "\n"
+  end
+
+=end PASM
+
+This example removes two characters from the end of C<S0>. If the
+count is negative, that many characters are kept in the string:
+
+=begin PASM
+
+  set S0, "abcde"
+  chopn S0, -2
+  print S0         # prints "ab"
+  print "\n"
+  end
+
+=end PASM
+
+This keeps the first two characters in C<S0> and removes the rest.
+C<chopn> also has a three-argument version that stores the chopped
+string in a separate destination register, leaving the original string
+untouched:
+
+=begin PASM
+
+  set S0, "abcde"
+  chopn S1, S0, 1
+  print S1         # prints "abcd"
+  print "\n"
+  end
+
+=end PASM
+
+=head4 Copying and Cloning
+
+Z<CHP-9-SECT-2.4.6>
+
+X<PASM (Parrot assembly language);string operations;copying> The C<clone>
+X<clone opcode (PASM)> opcode makes a deep copy of a string or PMC. Earlier
+in this chapter we saw that PMC and String values used with the C<set> opcode
+didn't create a copy of the underlying data structure, it only created
+a copy of the reference to that structure. With strings, this doesn't cause
+a problem because strings use Copy On Write (COW) semantics to automatically
+create a copy of the string when one reference is modified. However, as we
+saw, PMCs don't have this same behavior and so making a change to one PMC
+reference would modify the data that all the other references to that same
+PMC pointed to.
+
+Instead of just copying the pointer like C<set> would do, we can use the
+C<clone> opcode to create a I<deep copy> of the PMC, not just a I<shallow
+copy> of the reference.
+
+=begin PASM
+
+  new P0, "String"
+  set P0, "Ford"
+  clone P1, P0
+  set P0, "Zaphod"
+  print P0        # prints "Zaphod"
+  print P1        # prints "Ford"
+  end
+
+=end PASM
+
+This example creates an identical, independent clone of the PMC in
+C<P0> and puts a pointer to it in C<P1>. Later changes to C<P0> have
+no effect on the PMC referenced in C<P1>.
+
+With simple strings, the copes created by C<clone> are COW exactly the same
+as the copy created by C<set>, so there is no difference between these two
+opcodes for strings. By convention, C<set> is used with strings more often
+then C<clone>, but there is no rule about this.
+
+=head4 Converting characters
+
+Z<CHP-9-SECT-2.4.7>
+
+X<PASM (Parrot assembly language);string operations;converting strings>
+The C<chr>X<chr opcode (PASM)> opcode takes an integer value and returns the
+corresponding character in the ASCII character set as a one-character string,
+while the C<ord>X<ord opcode (PASM)> opcode takes a single character string
+and returns the integer value of the character at the first position in the
+string. Notice that the integer value of the character will differ depending
+on the current encoding of the string:
+
+=begin PASM
+
+  chr S0, 65                # S0 is "A"
+  ord I0, S0                # I0 is 65, if S0 is ASCII or UTF-8
+
+=end PASM
+
+C<ord> has a three-argument variant that takes a character offset to select
+a single character from a multicharacter string. The offset must be within
+the length of the string:
+
+=begin PASM
+
+  ord I0, "ABC", 2        # I0 is 67
+
+=end PASM
+
+A negative offset counts backward from the end of the string, so -1 is
+the last character.
+
+=begin PASM
+
+  ord I0, "ABC", -1        # I0 is 67
+
+=end PASM
+
+=head4 Formatting strings
+
+Z<CHP-9-SECT-2.4.8>
+
+X<PASM (Parrot assembly language);string operations;formatting strings>
+The C<sprintf>X<sprintf opcode (PASM)> opcode generates a formatted string
+from a series of values. It takes three arguments: the destination register,
+a string specifying the format, and an ordered aggregate PMC (like an
+C<Array> PMC) containing the values to be formatted. The format string and
+the destination register can be either strings or PMCs:
+
+=begin PASM
+
+  sprintf S0, S1, P2
+  sprintf P0, P1, P2
+
+=end PASM
+
+The format string is similar to the one for C's C<sprintf> function,
+but with some extensions for Parrot data types. Each format field in
+the string starts with a C<%>
+X<% (percent sign);% format strings for sprintf opcode (PASM)> and
+ends with a character specifying the output format. The output format
+characters are listed in Table 9-1.
+
+=begin table picture Format characters
+
+Z<CHP-9-TABLE-1>
+
+=headrow
+
+=row
+
+=cell Format
+
+=cell Meaning
+
+=bodyrows
+
+=row
+
+=cell C<%c>
+
+=cell A single character.
+
+=row
+
+=cell C<%d>
+
+=cell A decimal integer.
+
+=row
+
+=cell C<%i>
+
+=cell A decimal integer.
+
+=row
+
+=cell C<%u>
+
+=cell An unsigned integer.
+
+=row
+
+=cell C<%o>
+
+=cell An octal integer.
+
+=row
+
+=cell C<%x>
+
+=cell A hex integer, preceded by 0x when # is specified.
+
+=row
+
+=cell C<%X>
+
+=cell A hex integer with a capital X (when # is specified).
+
+=row
+
+=cell C<%b>
+
+=cell A binary integer, preceded by 0b when # is specified.
+
+=row
+
+=cell C<%B>
+
+=cell A binary integer with a capital B (when # is specified).
+
+=row
+
+=cell C<%p>
+
+=cell A pointer address in hex.
+
+=row
+
+=cell C<%f>
+
+=cell A floating-point number.
+
+=row
+
+=cell C<%e>
+
+=cell A floating-point number in scientific notation (displayed with a
+lowercase "e").
+
+=row
+
+=cell C<%E>
+
+=cell The same as C<%e>, but displayed with an uppercase E.
+
+=row
+
+=cell C<%g>
+
+=cell The same as either C<%e> or C<%f>, whichever fits best.
+
+=row
+
+=cell C<%G>
+
+=cell The same as C<%g>, but displayed with an uppercase E.
+
+=row
+
+=cell C<%s>
+
+=cell A string.
+
+=end table
+
+Each format field can be specified with several options: R<flags>,
+R<width>, R<precision>, and R<size>. The format flags are listed in
+Table 9-2.
+
+=begin table picture Format flags
+
+Z<CHP-9-TABLE-2>
+
+=headrow
+
+=row
+
+=cell Flag
+
+=cell Meaning
+
+=bodyrows
+
+=row
+
+=cell 0
+
+=cell Pad with zeros.
+
+=row
+
+=cell E<lt>spaceE<gt>
+
+=cell Pad with spaces.
+
+=row
+
+=cell C<+>
+
+=cell Prefix numbers with a sign.
+
+=row
+
+=cell C<->
+
+=cell Align left.
+
+=row
+
+=cell C<#>
+
+=cell Prefix a leading 0 for octal, 0x for hex, or force a decimal point.
+
+=end table
+
+The R<width> is a number defining the minimum width of the output from
+a field. The R<precision> is the maximum width for strings or
+integers, and the number of decimal places for floating-point fields.
+If either R<width> or R<precision> is an asterisk (C<*>), it takes its
+value from the next argument in the PMC.
+
+The R<size> modifier defines the type of the argument the field takes.
+The flags are listed in Table 9-3.
+
+=begin table picture Size flags
+
+Z<CHP-9-TABLE-3>
+
+=headrow
+
+=row
+
+=cell Character
+
+=cell Meaning
+
+=bodyrows
+
+=row
+
+=cell C<h>
+
+=cell short integer or single-precision float
+
+=row
+
+=cell C<l>
+
+=cell long
+
+=row
+
+=cell C<H>
+
+=cell huge value (long long or long double)
+
+=row
+
+=cell C<v>
+
+=cell Parrot INTVAL or FLOATVAL
+
+=row
+
+=cell C<O>
+
+=cell opcode_t pointer
+
+=row
+
+=cell C<P>
+
+=cell C<PMC>
+
+=row
+
+=cell C<S>
+
+=cell String
+
+=end table
+
+The values in the aggregate PMC must have a type compatible with the
+specified R<size>.
+
+Here's a short illustration of string formats:
+
+=begin PASM
+
+  new P2, "Array"
+  new P0, "Int"
+  set P0, 42
+  push P2, P0
+  new P1, "Num"
+  set P1, 10
+  push P2, P1
+  sprintf S0, "int %#Px num %+2.3Pf\n", P2
+  print S0     # prints "int 0x2a num +10.000"
+  print "\n"
+  end
+
+=end PASM
+
+The first eight lines create a C<Array> with two elements: a
+C<Int> and a C<Num>. The format string of the C<sprintf> has
+two format fields. The first, C<%#Px>, takes a PMC argument from the
+aggregate (C<P>) and formats it as a hexadecimal integer (C<x>), with
+a leading 0x (C<#>). The second format field, C<%+2.3Pf>, takes a PMC
+argument (C<P>) and formats it as a floating-point number (C<f>), with
+a minimum of two whole digits and a maximum of three decimal places
+(C<2.3>) and a leading sign (C<+>).
+
+The test files F<t/op/string.t> and F<t/src/sprintf.t> have many more
+examples of format strings.
+
+=head4 Testing for substrings
+
+Z<CHP-9-SECT-2.4.9>
+
+X<PASM (Parrot assembly language);string operations;testing for substrings>
+The C<index>X<index opcode (PASM)> opcode searches for a substring
+within a string. If it finds the substring, it returns the position
+where the substring was found as a character offset from the beginning
+of the string. If it fails to find the substring, it returns -1:
+
+=begin PASM
+
+  index I0, "Beeblebrox", "eb"
+  print I0                       # prints 2
+  print "\n"
+  index I0, "Beeblebrox", "Ford"
+  print I0                       # prints -1
+  print "\n"
+  end
+
+=end PASM
+
+C<index> also has a four-argument version, where the fourth argument
+defines an offset position for starting the search:
+
+=begin PASM
+
+  index I0, "Beeblebrox", "eb", 3
+  print I0                         # prints 5
+  print "\n"
+  end
+
+=end PASM
+
+This finds the second "eb" in "Beeblebrox" instead of the first,
+because the search skips the first three characters in the
+string.
+
+=head4 Joining strings
+
+The C<join> opcode joins the elements of an array PMC into a single
+string. The second argument separates the individual elements of the
+PMC in the final string result.
+
+=begin PASM
+
+  new P0, "Array"
+  push P0, "hi"
+  push P0, 0
+  push P0, 1
+  push P0, 0
+  push P0, "parrot"
+  join S0, "__", P0
+  print S0              # prints "hi__0__1__0__parrot"
+  end
+
+=end PASM
+
+This example builds a C<Array> in C<P0> with the values C<"hi">,
+C<0>, C<1>, C<0>, and C<"parrot">. It then joins those values (separated
+by the string C<"__">) into a single string, and stores it in C<S0>.
+
+=head4 Splitting strings
+
+Splitting a string yields a new array containing the resulting
+substrings of the original string.
+
+=begin PASM
+
+  split P0, "", "abc"
+  set P1, P0[0]
+  print P1              # 'a'
+  set P1, P0[2]
+  print P1              # 'c'
+  end
+
+=end PASM
+
+This example splits the string "abc" into individual characters and
+stores them in an array in C<P0>. It then prints out the first and
+third elements of the array. For now, the split pattern (the second
+argument to the opcode) is ignored except for a test to make sure that
+its length is zero.
+
+=head3 Logical and Bitwise Operations
+
+Z<CHP-9-SECT-2.6>
+
+X<PASM (Parrot assembly language);bitwise operations>
+X<PASM (Parrot assembly language);logical operations>
+The X<logical opcodes> logical opcodes evaluate the truth of their
+arguments. They're often used to make decisions on control flow.
+Logical operations are implemented for integers and PMCs. Numeric
+values are false if they're 0, and true otherwise. Strings are false
+if they're the empty string or a single character "0", and true
+otherwise. PMCs are true when their
+C<get_bool>X<get_bool vtable method (PASM)> vtable method returns a
+nonzero value.
+
+The C<and>X<and opcode (PASM)> opcode returns the second argument if
+it's false and the third argument otherwise:
+
+=begin PASM
+
+  and I0, 0, 1  # returns 0
+  and I0, 1, 2  # returns 2
+
+=end PASM
+
+The C<or>X<or opcode (PASM)> opcode returns the second argument if
+it's true and the third argument otherwise:
+
+=begin PASM
+
+  or I0, 1, 0  # returns 1
+  or I0, 0, 2  # returns 2
+
+  or P0, P1, P2
+
+=end PASM
+
+Both C<and> and C<or> are short-circuiting. If they can determine what
+value to return from the second argument, they'll never evaluate the
+third.  This is significant only for PMCs, as they might have side
+effects on evaluation.
+
+The C<xor>X<xor opcode (PASM)> opcode returns the second argument if
+it is the only true value, returns the third argument if it is the
+only true value, and returns false if both values are true or both are
+false:
+
+=begin PASM
+
+  xor I0, 1, 0  # returns 1
+  xor I0, 0, 1  # returns 1
+  xor I0, 1, 1  # returns 0
+  xor I0, 0, 0  # returns 0
+
+=end PASM
+
+The C<not>X<not opcode (PASM)> opcode returns a true value when the
+second argument is false, and a false value if the second argument is
+true:
+
+=begin PASM
+
+  not I0, I1
+  not P0, P1
+
+=end PASM
+
+The X<bitwise;opcodes (PASM)> bitwise opcodes operate on their values
+a single bit at a time. C<band>X<band opcode (PASM)>,
+C<bor>X<bor opcode (PASM)>, and C<bxor>X<bxor opcode (PASM)> return a
+value that is the logical AND, OR, or XOR of each bit in the source
+arguments. They each take a destination register and two source
+registers. They also have two-argument forms where the destination is
+also a source.  C<bnot>X<bnot opcode (PASM)> is the logical NOT of
+each bit in a single source argument.
+
+=begin PASM
+
+  bnot I0, I1
+  band P0, P1
+  bor I0, I1, I2
+  bxor P0, P1, I2
+
+=end PASM
+
+X<bitwise;string opcodes>
+The bitwise opcodes also have string variants for AND, OR, and XOR:
+C<bors>X<bors opcode (PASM)>, C<bands>X<bands opcode (PASM)>, and
+C<bxors>X<bxors opcode (PASM)>. These take string register or PMC
+string source arguments and perform the logical operation on each byte
+of the strings to produce the final string.
+
+=begin PASM
+
+  bors S0, S1
+  bands P0, P1
+  bors S0, S1, S2
+  bxors P0, P1, S2
+
+=end PASM
+
+The bitwise string opcodes only have meaningful results when they're
+used with simple ASCII strings because the bitwise operation is done
+per byte.
+
+The logical and arithmetic shift operations shift their values by a
+specified number of bits:
+
+=begin PASM
+
+  shl  I0, I1, I2        # shift I1 left by count I2 giving I0
+  shr  I0, I1, I2        # arithmetic shift right
+  lsr  P0, P1, P2        # logical shift right
+
+=end PASM
+
+=head3 Encodings and Charsets
+
+X<charset>
+A modern string system must manage several character encodings and charsets in
+order to make sense out of all the string data in the world.  Parrot does this.
+Every string has an associated encoding and an associated character set.  The
+default charset is 8-bit ASCII, which is simple to use and is almost
+universally supported.
+
+Double-quoted string constants can have an optional prefix specifying the the
+string's encoding and charsetN<As you might suspect, single-quoted strings do
+not support this.>. Parrot will maintain these values internally, and will
+automatically convert strings when necessary to preserve the information.
+String prefixes are specified as C<encoding:charset:> at the front of the
+string. Here are some examples:
+
+  $S0 = utf8:unicode:"Hello UTF8 Unicode World!"
+  $S1 = utf16:unicode:"Hello UTF16 Unicode World!"
+  $S2 = ascii:"This is 8-bit ASCII"
+  $S3 = binary:"This is raw, unformatted binary data"
+
+The C<binary:> charset treats the string as a buffer of raw unformatted binary
+data. It isn't really a string per se, because binary data contains no readable
+characters.  As mentioned earlier, this exists to support libraries which
+manipulate binary data that doesn't easily fit into any other primitive data
+type.
+
+When Parrot combines two strings (such as through concatenation), they must
+both use the same character set and encoding.  Parrot will automatically
+upgrade one or both of the strings to use the next highest compatible format as
+necessary. ASCII strings will automatically upgrade to UTF-8 strings if needed,
+and UTF-8 will upgrade to UTF-16. All of these conversions happen inside
+Parrot; you the programmer don't need to worry about the details.
+
+=head2 Working with PMCs
+
+Polymorphic Containers (PMCs) are the basis for complex data types and
+object-oriented behavior in Parrot. In PIR, any variable that isn't a
+low-level integer, number, or string is a PMC
+
+Operations on a PMC are implemented by vtable functions. The result of an operation is entirely determined by the behavior of
+the PMCs vtable. Since PMCs define their own behavior for these vtable functions, it's important to familiarize yourself with the behavior
+of the particular PMC before you start performing a lot of operations on it.
+
+=head4 PMC object types
+
+Z<CHP-9-SECT-2.2.2>
+
+X<PMCs (Polymorphic Containers);object types>
+Every PMC has a distinct type that determines its behavior through the
+vtable interface. In the chapter on PIR, we've seen a number of these vtable
+functions already, and seen how they implement the behaviors found inside
+the various opcodes. The vtable interface is standard, and all PMCs implement
+the exact same set of vtables. We've seen some of the vtables and their uses,
+and more of them will be discussed in this chapter and later in the various
+reference chapters.
+
+The C<typeof> opcode can be used to determine the type of a PMC. When
+the source argument is a PMC and the destination is a string register,
+C<typeof> returns the name of the type:
+
+=begin PASM
+
+  new P0, "String"
+  typeof S0, P0               # S0 is "String"
+  print S0
+  print "\n"
+  end
+
+=end PASM
+
+Using C<typeof> with a PMC output parameter instead, it returns the Class
+PMC for that type.
+
+
+
+=head3 Scalars
+
+Parrot provides a set of
+
+In most of the examples we've shown so far, X<PMCs (Polymorphic
+Containers);working with> PMCs just duplicate the functionality of integers,
+numbers, and strings.
+
+PMCs act much like any integer, floating-point
+number, or string register or variable, but you have to instantiate a
+new PMC object into a type before you use it. The C<new> instruction creates
+a new PMC of the specified type:
+
+  $P0 = new 'String'
+  $P0 = "That's a bollard and not a parrot."
+  say $P0
+
+This example creates a C<String> object, stores it in the PMC register variable C<$P0>,
+assigns it the value "Hello, Polly.", and prints it:
+
+  .local String hello    # or .local pmc hello
+  hello = new 'String'
+  hello = "Hello, Polly."
+  say hello
+
+PIR is a dynamic language; that dynamicism is evident in how Parrot handles PMC
+values. Primitive registers like strings, numbers, and integers perform a
+special action called X<autoboxing> when assigned to a PMC. Autoboxing is the
+process of converting a primitive type to a PMC object.  PMC classes exist for
+String, Number, and Integer; notice that the primitive types are in lower-case,
+while the PMC classes are capitalized. If you want to box a value explicitly,
+use the C<box> opcode:
+
+  $P0 = new 'Integer'       # The boxed form of int
+  $P0 = box 42
+  $P1 = new 'Number'        # The boxed form of num
+  $P1 = box 3.14
+  $P2 = new 'String'        # The boxed form of string
+  $P2 = "This is a string!"
+
+The PMC classes C<Integer>, C<Number>, and C<String> are thin overlays on the
+primitive types they represent. These PMC types have the benefit of the
+X<PMC;VTABLE Interface> VTABLE interface. VTABLEs are a standard API that all
+PMCs conform to for performing standard operations. These PMC types support
+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.
+
+=head4 Boxing and Unboxing
+
+Z<CHP-9-SECT-2.2.3>
+
+As we've seen in the previous chapters about PIR, we can convert between
+primitive string, integer, and number types and PMCs. PIR used the C<=>
+operator to make these conversions. PASM uses the C<set> opcode to do the
+same thing. C<set> will perform the type conversions for us automatically,
+in a process called I<autoboxing>.
+
+Assigning a primitive data type to a PMC of a String, Integer, or Float type
+converts that PMC to the new type. So, assigning a string to a Number PMC
+converts it into a String PMC. Assigning an integer value converts it to a
+C<Integer>, and assigning C<undef> converts it to an C<Undef> PMC:
+
+=begin PASM
+
+  new P0, "String"
+  set P0, "Ford\n"
+  print P0           # prints "Ford\n"
+  set P0, 42
+  print P0           # prints 42
+  print "\n"
+  typeof S0, P0
+  print S0           # prints "Integer"
+  print "\n"
+  end
+
+=end PASM
+
+C<P0> starts as a C<String>, but when C<set> assigns it an integer
+value 42 (replacing the old string value C<"Ford">), it changes type
+to C<Integer>. This behavior only works for the wrapper PMC types for the
+primitive values string, int, and num. Other PMC classes will have different
+behaviors when you try to assign a primitive value to them.
+
+We can also use the C<box> opcode to explicitly convert an integer, a float,
+or a string into an appropriate PMC type.
+
+=begin PASM
+
+  box P0, 3
+  typeof S0, P0         # P0 is an "Integer"
+  box P1, "hello"
+  typeof S0, P1         # P1 is a "String"
+  box P2, 3.14
+  typeof S0, P2         # P2 is a "Number"
+
+=end PASM
+
+
+=head3 Aggregates
+
+Z<CHP-9-SECT-3.1>
+
+PMCs can define complex types that hold multiple values. These are
+commonly called "X<PMCs (Polymorphic Containers);aggregate>
+X<aggregate PMCs> aggregates." The most important feature added for
+aggregates is keyed access. Elements within an aggregate PMC can be
+stored and retrieved by a numeric or string key. PASM also offers a
+full set of operations for manipulating aggregate data types.
+
+Two of the most basic aggregate types are arrays and hashes. The primary
+difference between these two is that arrays are indexed using integer keys,
+and hashes are indexed with string keys. The term "hash" in this context is
+derived from the data type in Perl 5 of the same name. Other programming
+languages might refer to the same concept using different terms such as
+"dictionary" or "hash table" or "associative array".
+
+Arrays and hashes are not the only types of aggregates available, although
+they are the most simple demonstrations of using integer and strings as
+keys in an aggregate, respectively.
+
+=head4 Arrays
+
+Z<CHP-9-SECT-3.1.1>
+
+X<arrays>
+The C<Array>X<Array PMC> PMC is an ordered aggregate with zero-based integer
+keys. The syntax for X<keyed access to PMCs> keyed access to a PMC puts the
+key in square brackets after the register name:
+
+=begin PASM
+
+  new P0, "Array"     # obtain a new array object
+  set P0, 2           # set its length
+  set P0[0], 10       # set first element to 10
+  set P0[1], I31      # set second element to I31
+  set I0, P0[0]       # get the first element
+  set I1, P0          # get array length
+
+=end PASM
+
+A key on the destination register of a C<set> operation sets a value
+for that key in the aggregate. A key on the source register of a
+C<set> returns the value for that key. If you set C<P0> without a key,
+you set the length of the array, not one of its values.N<C<Array>
+is an autoextending array, so you never need to set its length. Other
+array types may require the length to be set explicitly.> And if you
+assign the C<Array> to an integer, you get the length of the
+array.
+
+We mention "other array types" above, not as a vague suggestion that there may
+be other types of arrays eventually, but as an indication that we actually
+have several types of array PMCs in Parrot's core. Parrot comes with
+C<FixedPMCArray>, C<ResizablePMCArray>, C<FixedIntegerArray>,
+C<ResizableIntegerArray>, C<FixedFloatArray>, C<ResizableFloatArray>,
+C<FixedStringArray>, C<ResizableStringArray>, C<FixedBooleanArray>,
+and C<ResizableBooleanArray> types. These various types of arrays use
+various packing methods to create higher memory efficiency for their contents
+then using a single generic array type would be able to. The trade-off for
+higher memory efficiency is that these array PMCs can only hold a single type
+of data.
+
+The array PMC types that start with "Fixed" have a fixed size and do not
+automatically extend themselves if you attempt to add data to a higher index
+then the array contains. The "Resizable" variants will automatically extend
+themselves as more data are added, but the cost is in algorithmic complexity
+of checking array bounds and reallocating array memory.
+
+To retrieve the number of items currently in an array, you can use the
+C<elements> opcode.
+
+=begin PASM
+
+  set P0, 100         # allocate store for 100 elements
+  set I0, P0          # obtain current allocation size
+  elements I0, P0     # get element count
+
+=end PASM
+
+Some other useful instructions for working with arrays are C<push>,
+C<pop>, C<shift>, and C<unshift> (you'll find them in
+"PASM Opcodes" in Chapter 11).
+
+=head4 Hashes
+
+Z<CHP-9-SECT-3.1.2>
+
+X<PMCs (Polymorphic Containers);hashes>
+The C<Hash>X<Hash PMC> PMC is an unordered aggregate which uses string keys
+to identify elements within it.
+
+=begin PASM
+
+  new P1, "Hash"      # generate a new hash object
+  set P1["key"], 10   # set key and value
+  set I0, P1["key"]   # obtain value for key
+  set I1, P1          # number of entries in hash
+
+=end PASM
+
+The C<exists>X<exists opcode (PASM)> opcode tests whether a keyed
+value exists in an aggregate. It returns 1 if it finds the key in the
+aggregate, and returns 0 if it doesn't. It doesn't care if the value
+itself is true or false, only that the key has been set:
+
+=begin PASM
+
+  new P0, "Hash"
+  set P0["key"], 0
+  exists I0, P0["key"] # does a value exist at "key"
+  print I0             # prints 1
+  print "\n"
+  end
+
+=end PASM
+
+The C<delete>X<delete opcode (PASM)> opcode is also useful for working
+with hashes: it removes a key/value pair.
+
+=head4 Iterators
+
+Z<CHP-9-SECT-3.1.3>
+
+Iterators extract values from an aggregate PMC one at a time and without
+extracting duplicates. Iterators are most useful in loops where an action
+needs to be performed on every element in an aggregate. You create an
+iterator by creating a new C<Iterator> PMC, and passing the aggregate PMC
+to C<new> as an additional parameter:
+
+=begin PASM
+
+  new P1, "Iterator", P2
+
+=end PASM
+
+Alternatively, you can use the C<iter> opcode to do the same thing:
+
+=begin PASM
+
+  iter P1, P2     # Same!
+
+=end PASM
+
+The include file F<iterator.pasm> defines some constants for working
+with iterators. The C<.ITERATE_FROM_START> and C<.ITERATE_FROM_END>
+constants are used to select whether an array iterator starts from the
+beginning or end of the array. Since Hash PMCs are unordered, these two
+constants do not have any affect on Hash iterators.
+
+A value can be extracted from the iterator using the C<shift> opcode.
+Evaluating the iterator PMC as a boolean returns whether the iterator has
+reached the end of the aggregate or not.
+
+=begin PASM
+
+  .include "iterator.pasm"
+      new P2, "Array"
+      push P2, "a"
+      push P2, "b"
+      push P2, "c"
+      new P1, "Iterator", P2
+      set P1, .ITERATE_FROM_START
+
+  iter_loop:
+      unless P1, iter_end
+      shift P5, P1
+      print P5                        # prints "a", "b", "c"
+      branch iter_loop
+  iter_end:
+      end
+
+=end PASM
+
+Hash iterators work similarly to array iterators, but they extract keys
+only. With the key, you can find it's value from the original hash PMC.
+With hashes it's only meaningful to iterate in one direction since they
+don't define any order for their keys.
+
+=begin PASM
+
+  .include "iterator.pasm"
+      new P2, "Hash"
+      set P2["a"], 10
+      set P2["b"], 20
+      set P2["c"], 30
+      new P1, "Iterator", P2
+      set P1, .ITERATE_FROM_START_KEYS
+
+  iter_loop:
+      unless P1, iter_end
+      shift S5, P1                    # one of the keys "a", "b", "c"
+      set I9, P2[S5]
+      print I9                        # prints e.g. 20, 10, 30
+      branch iter_loop
+  iter_end:
+      end
+
+=end PASM
+
+=head4 Data structures
+
+Z<CHP-9-SECT-3.1.4>
+
+X<PMCs (Polymorphic Containers);data structures>
+Arrays and hashes can hold any data type, including other aggregates.
+Accessing elements deep within nested data structures is a common
+operation, so PASM provides a way to do it in a single instruction.
+Complex keys specify a series of nested data structures, with each
+individual key separated by a semicolon:
+
+=begin PASM
+
+  new P0, "Hash"
+  new P1, "Array"
+  set P1[2], 42
+  set P0["answer"], P1
+  set I1, 2
+  set I0, P0["answer";I1]        # $i = %hash{"answer"}[2]
+  print I0
+  print "\n"
+  end
+
+=end PASM
+
+This example builds up a data structure of a hash containing an array.
+The complex key C<P0["answer";I1]> retrieves an element of the array
+within the hash. You can also set a value using a complex key:
+
+=begin PASM
+
+  set P0["answer";0], 5   # %hash{"answer"}[0] = 5
+
+=end PASM
+
+The individual keys are integers or strings, or registers with integer
+or string values.
+
+=head3 PMC Assignment
+
+Z<CHP-9-SECT-3.2>
+
+We mentioned before that C<set> on two X<PMCs (Polymorphic
+Containers);assignment> PMCs simply aliases them both to the same object,
+and that C<clone> creates a complete duplicate object. But if you just
+want to assign the value of one PMC to another PMC, you need the
+C<assign>X<assign opcode (PASM)> opcode:
+
+=begin PASM
 
-Strings are buffers of variable-sized data. The most common use of string
-registers and variables is to store textual data. String registers I<may> also be
-buffers for binary or other non-textual data, though this is rareN<In general,
-a custom PMC is more useful>.  Parrot strings are flexible and powerful, to
-account for all the complexity of human-readable (and computer-representable)
-textual data.
+  new P0, "Int"
+  new P1, "Int"
+  set P0, 42
+  set P2, P0
+  assign P1, P0     # note: P1 has to exist already
+  inc P0
+  print P0          # prints 43
+  print "\n"
+  print P1          # prints 42
+  print "\n"
+  print P2          # prints 43
+  print "\n"
+  end
 
-=head3 Encodings and Charsets
+=end PASM
 
-X<charset>
-A modern string system must manage several character encodings and charsets in
-order to make sense out of all the string data in the world.  Parrot does this.
-Every string has an associated encoding and an associated character set.  The
-default charset is 8-bit ASCII, which is simple to use and is almost
-universally supported.
+This example creates two C<Int> PMCs: C<P0> and C<P1>. It gives
+C<P0> a value of 42. It then uses C<set> to give the same value to
+C<P2>, but uses C<assign> to give the value to C<P1>. When C<P0> is
+incremented, C<P2> also changes, but C<P1> doesn't. The destination
+register for C<assign> must have an existing object of the right type
+in it, since C<assign> doesn't create a new object (as with C<clone>)
+or reuse the source object (as with C<set>).
 
-Double-quoted string constants can have an optional prefix specifying the the
-string's encoding and charsetN<As you might suspect, single-quoted strings do
-not support this.>. Parrot will maintain these values internally, and will
-automatically convert strings when necessary to preserve the information.
-String prefixes are specified as C<encoding:charset:> at the front of the
-string. Here are some examples:
+=head3 Properties
 
-  $S0 = utf8:unicode:"Hello UTF8 Unicode World!"
-  $S1 = utf16:unicode:"Hello UTF16 Unicode World!"
-  $S2 = ascii:"This is 8-bit ASCII"
-  $S3 = binary:"This is raw, unformatted binary data"
+Z<CHP-9-SECT-3.3>
 
-The C<binary:> charset treats the string as a buffer of raw unformatted binary
-data. It isn't really a string per se, because binary data contains no readable
-characters.  As mentioned earlier, this exists to support libraries which
-manipulate binary data that doesn't easily fit into any other primitive data
-type.
+X<PMCs (Polymorphic Containers);properties>
+PMCs can have additional values attached to them as "properties" of
+the PMC. What these properties do is entirely up to the language being
+implemented. Most usually properties are used to hold extra metadata about
+the PMC that is used by the high-level language (HLL).
 
-When Parrot combines two strings (such as through concatenation), they must
-both use the same character set and encoding.  Parrot will automatically
-upgrade one or both of the strings to use the next highest compatible format as
-necessary. ASCII strings will automatically upgrade to UTF-8 strings if needed,
-and UTF-8 will upgrade to UTF-16. All of these conversions happen inside
-Parrot; you the programmer don't need to worry about the details.
+The C<setprop>X<setprop opcode (PASM)> opcode sets the value of a
+named property on a PMC. It takes three arguments: the PMC to be set
+with a property, the name of the property, and a PMC containing the
+value of the property. The C<getprop>X<getprop opcode (PASM)> opcode
+returns the value of a property. It also takes three arguments: the
+PMC to store the property's value, the name of the property, and the
+PMC from which the property value is to be retrieved. Internally a PMCs
+properties are stored in a Hash structure, where the name of the property
+is stored in a special properties Hash.
 
-=head2 Working with PMCs
+=begin PASM
 
-Polymorphic Containers (PMCs) are the basis for complex data types and
-object-oriented behavior in Parrot. In PIR, any variable that isn't a low-level integer, number, or string is a PMC. Parrot provides a set of
+  new P0, "String"
+  set P0, "Zaphod"
+  new P1, "Int"
+  set P1, 1
+  setprop P0, "constant", P1        # set a property on P0
+  getprop P3, "constant", P0        # retrieve a property on P0
+  print P3                          # prints 1
+  print "\n"
+  end
 
-resemble classes and objects are in
-object-oriented languages. They are 
+=end PASM
 
-PMCs act much like any integer, floating-point
-number, or string register or variable, but you have to instantiate a
-new PMC object into a type before you use it. The C<new> instruction creates
-a new PMC of the specified type:
+This example creates a C<String> object in C<P0>, and a C<Int>
+object with the value 1 in C<P1>. C<setprop> sets a property named
+"constant" on the object in C<P0> and gives the property the value in
+C<P1>.N<The "constant" property is ignored by PASM, but may be significant
+to the HLL that set it.> C<getprop> retrieves the value of the property
+"constant" on C<P0> and stores it in C<P3>.
 
-  $P0 = new 'String'
-  $P0 = "That's a bollard and not a parrot."
-  say $P0
+Properties are kept in a separate hash for each PMC. Property values
+are always PMCs, but only references to the actual PMCs. Trying to
+fetch the value of a property that doesn't exist returns a
+C<Undef>.
 
-This example creates a C<String> object, stores it in the PMC register variable C<$P0>,
-assigns it the value "Hello, Polly.", and prints it:
+C<delprop>X<delprop opcode (PASM)> deletes a property from a PMC.
 
-  .local String hello    # or .local pmc hello
-  hello = new 'String'
-  hello = "Hello, Polly."
-  say hello
+=begin PASM
 
-PIR is a dynamic language; that dynamicism is evident in how Parrot handles PMC
-values. Primitive registers like strings, numbers, and integers perform a
-special action called X<autoboxing> when assigned to a PMC. Autoboxing is the
-process of converting a primitive type to a PMC object.  PMC classes exist for
-String, Number, and Integer; notice that the primitive types are in lower-case,
-while the PMC classes are capitalized. If you want to box a value explicitly,
-use the C<box> opcode:
+  delprop P1, "constant"  # delete property
 
-  $P0 = new 'Integer'       # The boxed form of int
-  $P0 = box 42
-  $P1 = new 'Number'        # The boxed form of num
-  $P1 = box 3.14
-  $P2 = new 'String'        # The boxed form of string
-  $P2 = "This is a string!"
+=end PASM
 
-The PMC classes C<Integer>, C<Number>, and C<String> are thin overlays on the
-primitive types they represent. These PMC types have the benefit of the
-X<PMC;VTABLE Interface> VTABLE interface. VTABLEs are a standard API that all
-PMCs conform to for performing standard operations. These PMC types support
-custom methods to perform various operations, may be passed to subroutines that
-expect PMC arguments, and can be subclassed by a user-defined type.
+You can also return a complete hash of all properties on a PMC with
+C<prophash>X<prophash opcode (PASM)>.
 
+=begin PASM
 
-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>.
+  prophash P0, P1         # set P0 to the property hash of P1
+
+=end PASM
 
-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
 
@@ -535,6 +1866,214 @@
 All modern programming languages use branching constructs to implement their
 most complex flow control devices.
 
+Although it has many advanced features, at heart PASM is an assembly
+language. All flow control in PASM--as in most assembly languages--is
+done with branches and jumps.
+
+Branch instructions transfer control to a relative offset from the
+current instruction. The rightmost argument to every branch opcode is
+a label, which the assembler converts to the integer value of the
+offset. You can also branch on a literal integer value, but there's
+rarely any need to do so. The simplest branch instruction is
+C<branch>:
+
+=begin PASM
+
+    branch L1                # branch 4
+    print "skipped\n"
+  L1:
+    print "after branch\n"
+    end
+
+=end PASM
+
+This example unconditionally branches to the location of the label
+C<L1>, skipping over the first C<print> statement.
+
+Jump instructions transfer control to an absolute address. The C<jump>
+opcode doesn't calculate an address from a label, so it's used
+together with C<set_addr>:
+
+=begin PASM
+
+    set_addr I0, L1
+    jump I0
+    print "skipped\n"
+    end
+  L1:
+    print "after jump\n"
+    end
+
+=end PASM
+
+The C<set_addr>X<set_addr opcode (PASM)> opcode takes a label or an
+integer offset and returns an absolute address.
+
+You've probably noticed the C<end>X<end opcode (PASM)> opcode as the
+last statement in many examples above. This terminates the execution
+of the current run loop. Terminating the main bytecode segment (the
+first run loop) stops the interpreter. Without the C<end> statement,
+execution just falls off the end of the bytecode segment, with a good
+chance of crashing the interpreter.
+
+=head3 Conditional Branches
+
+Z<CHP-9-SECT-4.1>
+
+X<PASM (Parrot assembly language);conditional branches>
+X<conditional branches in PASM>
+Unconditional jumps and branches aren't really enough for flow
+control. What you need to implement the control structures of
+high-level languages is the ability to select different actions based
+on a set of conditions. PASM has opcodes that conditionally branch
+based on the truth of a single value or the comparison of two values.
+The following example has C<if>X<if (conditional);opcode (PASM)> and
+C<unless>X<unless (conditional);opcode (PASM)> conditional branches:
+
+=begin PASM
+
+    set I0, 0
+    if I0, TRUE
+    unless I0, FALSE
+    print "skipped\n"
+    end
+  TRUE:
+    print "shouldn't happen\n"
+    end
+  FALSE:
+    print "the value was false\n"
+    end
+
+=end PASM
+
+C<if> branches if its first argument is a true value, and C<unless>
+branches if its first argument is a false value. In this case, the
+C<if> doesn't branch because C<I0> is false, but the C<unless> does
+branch.
+The comparison branching opcodes compare two values and branch if the
+stated relation holds true. These are
+C<eq>X<eq (equal);opcode (PASM)> (branch when equal),
+C<ne>X<ne (not equal);opcode (PASM)> (when not equal),
+C<lt>X<lt (less than);opcode (PASM)> (when less than),
+C<gt>X<gt (greater than);opcode (PASM)> (when greater than),
+C<le>X<le (less than or equal);opcode (PASM)> (when less than or
+equal), and C<ge>X<ge (greater than or equal);opcode (PASM)> (when
+greater than or equal). The two compared arguments must be the same
+register type:
+
+=begin PASM
+
+    set I0, 4
+    set I1, 4
+    eq I0, I1, EQUAL
+    print "skipped\n"
+    end
+  EQUAL:
+    print "the two values are equal\n"
+    end
+
+=end PASM
+
+This compares two integers, C<I0> and C<I1>, and branches if they're
+equal. Strings of different character sets or encodings are converted
+to Unicode before they're compared. PMCs have a C<cmp> vtable method.
+This gets called on the left argument to perform the comparison of the
+two objects.
+
+The comparison opcodes don't specify if a numeric or string comparison
+is intended. The type of the register selects for integers, floats,
+and strings. With PMCs, the vtable method C<cmp> or C<is_equal> of the
+first argument is responsible for comparing the PMC meaningfully with
+the other operand. If you need to force a numeric or string comparison
+on two PMCs, use the alternate comparison opcodes that end in the
+C<_num> and C<_str> suffixes.
+
+=begin PASM
+
+  eq_str P0, P1, label     # always a string compare
+  gt_num P0, P1, label     # always numerically
+
+=end PASM
+
+Finally, the C<eq_addr> opcode branches if two PMCs or strings are
+actually the same object (have the same address):
+
+=begin PASM
+
+  eq_addr P0, P1, same_pmcs_found
+
+=end PASM
+
+=head3 Iteration
+
+Z<CHP-9-SECT-4.2>
+
+X<iteration;in PASM>
+X<PASM (Parrot assembly language);iteration>
+PASM doesn't define high-level loop constructs. These are built up
+from a combination of conditional and unconditional branches. A
+I<do-while>X<do-while style loop;(PASM)> style loop can be constructed
+with a single conditional branch:
+
+=begin PASM
+
+    set I0, 0
+    set I1, 10
+  REDO:
+    inc I0
+    print I0
+    print "\n"
+    lt I0, I1, REDO
+    end
+
+=end PASM
+
+This example prints out the numbers 1 to 10. The first time through,
+it executes all statements up to the C<lt> statement.  If the
+condition evaluates as true (C<I0> is less than C<I1>) it branches to
+the C<REDO> label and runs the three statements in the loop body
+again. The loop ends when the condition evaluates as false.
+
+Conditional and unconditional branches can build up quite complex
+looping constructs, as follows:
+
+=begin PASM
+
+    # loop ($i=1; $i<=10; $i++) {
+    #    print "$i\n";
+    # }
+  loop_init:
+    set I0, 1
+    branch loop_test
+  loop_body:
+    print I0
+    print "\n"
+    branch loop_continue
+  loop_test:
+    le I0, 10, loop_body
+    branch out
+  loop_continue:
+    inc I0
+    branch loop_test
+  out:
+    end
+
+=end PASM
+
+X<loops;PASM>
+X<PASM (Parrot assembly language);loops>
+This example emulates a X<counter-controlled loop> counter-controlled
+loop like Perl 6's C<loop> keyword or C's C<for>. The first time
+through the loop it sets the initial value of the counter in
+C<loop_init>, tests that the loop condition is met in C<loop_test>,
+and then executes the body of the loop in C<loop_body>. If the test
+fails on the first iteration, the loop body will never execute. The
+end of C<loop_body> branches to C<loop_continue>, which increments the
+counter and then goes to C<loop_test> again. The loop ends when the
+condition fails, and it branches to C<out>. The example is more
+complex than it needs to be just to count to 10, but it nicely shows
+the major components of a
+loop.
 
 =head2 Macros
 
@@ -624,6 +2163,21 @@
 X<PIR (Parrot intermediate representation);subroutines;Parrot calling conventions>
 X<subroutines;Parrot calling conventions;in PIR>
 
+The C<.sub> directive defines globally accessible subroutine
+objects.
+
+Subroutine objects of all kinds can be called with the
+C<invoke>X<invoke opcode (PASM)> opcode. There is also an C<invoke>
+C<PR<x>> instruction for calling objects held in a different register.
+
+The C<invokecc>X<invokecc opcode (PASM)> opcode is like C<invoke>, but it
+also creates and stores a new return continuation. When the
+called subroutine invokes this return continuation, it returns control
+to the instruction after the function call. This kind of call is known
+as Continuation Passing Style (CPS).
+X<CPS (Continuation Passing Style)>
+X<Continuation Passing Style (CPS)>
+
 The way that Parrot calls a subroutine -- passing arguments, altering control
 flow, and returning results -- is the "Parrot Calling Conventions" (PCC).
 Parrot generally hides the details of PCC from the programmer.  PIR has several
@@ -862,6 +2416,38 @@
 
 X<continuations>
 
+A continuation is a subroutine that captures a complete copy of the
+caller's context. Invoking a
+continuation starts or restarts it at the entry point:
+
+=begin PASM
+
+    new P1, "Int"
+    set P1, 5
+
+    newsub P0, .Continuation, _con
+  _con:
+    print "in cont "
+    print P1
+    print "\n"
+    dec P1
+    unless P1, done
+    invoke                        # P0
+  done:
+    print "done\n"
+    end
+
+=end PASM
+
+This prints:
+
+  in cont 5
+  in cont 4
+  in cont 3
+  in cont 2
+  in cont 1
+  done
+
 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
@@ -904,77 +2490,254 @@
 
 =head4 Continuation Passing Style
 
-X<continuation passing style>
-X<CPS>
+X<continuation passing style>
+X<CPS>
+
+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
+continuation.  If you have a continuation, you can invoke it to return to its
+point of creation any time you want.
+
+This type of flow control -- invoking continuations instead of performing bare
+jumps -- is X<Continuation Passing Style;CPS> Continuation Passing Style (CPS).
+
+
+
+=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,
+and is an important opportunity for optimization.  Here's a contrived example
+in pseudocode:
+
+  call add_two(5)
+
+  subroutine add_two(value)
+    value = add_one(value)
+    return add_one(value)
+
+In this example, the subroutine C<add_two> makes two calls to c<add_one>. The
+second call to C<add_one> is the return value. C<add_one> gets called; its
+result gets returned to the caller of C<add_two>.  Nothing in C<add_two> uses
+that return value directly.
+
+A simple optimization is available for this type of code.  The second call to
+C<add_one> can return to the same place that C<add_two> returns; therefore,
+it's perfectly safe and correct to use the same return continuation that
+C<add_two> uses. The two subroutine calls can share a return continuation,
+instead of having to create a new continuation for each call.
+
+X<.tailcall directive>
+
+PIR provides the C<.tailcall> directive to identify similar situations.  Use it
+in place of the C<.return> directive. C<.tailcall> performs this optimization
+by reusing the return continuation of the parent function to make the tailcall:
+
+=begin PIR
+
+  .sub 'main' :main
+      .local int value
+      value = add_two(5)
+      say value
+  .end
+
+  .sub 'add_two'
+      .param int value
+      .local int val2
+      val2 = add_one(value)
+      .tailcall add_one(val2)
+  .end
+
+  .sub 'add_one'
+      .param int a
+      .local int b
+      b = a + 1
+      .return (b)
+  .end
+
+=end PIR
+
+This example above will print out the correct value "7".
+
+=head3 Native Call Interface
+
+Z<CHP-9-SECT-7.2>
+
+X<subroutines;calling conventions;NCI>
+A special version of the Parrot calling conventions are used by the
+X<NCI (Native Call Interface)> Native Call Interface (NCI) for calling
+subroutines with a known prototype in shared libraries. This is not
+really portable across all libraries, but it's worth a short example.
+This is a simplified version of the first test in F<t/pmc/nci.t>:
+
+=begin PASM
+
+    loadlib P1, "libnci_test"     # get library object for a shared lib
+    print "loaded\n"
+    dlfunc P0, P1, "nci_dd", "dd" # obtain the function object
+    print "dlfunced\n"
+    set I0, 1                     # prototype used - unchecked
+    set_args "0", 4.0             # set the argument
+    get_results "0", N5           # prepare to store the return value
+    invokecc P0                   # call nci_dd
+    ne N5, 8.0, nok_1             # the test functions returns 2*arg
+    print "ok 1\n"
+    end
+    nok_1:
+    #...
+
+=end PASM
+
+This example shows two new instructions: C<loadlib> and C<dlfunc>. The
+C<loadlib>X<loadlib opcode (PASM)> opcode obtains a handle for a shared
+library. It searches for the shared library in the current directory,
+in F<runtime/parrot/dynext>, and in a few other configured
+directories. It also tries to load the provided filename unaltered and
+with appended extensions like C<.so> or C<.dll>. Which extensions it
+tries depends on the OS Parrot is running on.
+
+The C<dlfunc>X<dlfunc opcode (PASM)> opcode gets a function object from a
+previously loaded library (second argument) of a specified name (third
+argument) with a known function signature (fourth argument). The
+function signature is a string where the first character is the return
+value and the rest of the parameters are the function parameters. The
+characters used in X<NCI (Native Call Interface);function signatures>
+NCI function signatures are listed in Table 9-5.
+
+=begin table picture Function signature letters
+
+Z<CHP-9-TABLE-5>
+
+=headrow
+
+=row
+
+=cell Character
+
+=cell Register set
+
+=cell C type
+
+=bodyrows
+
+=row
+
+=cell C<v>
+
+=cell -
+
+=cell void (no return value)
+
+=row
+
+=cell C<c>
+
+=cell C<I>
+
+=cell char
+
+=row
+
+=cell C<s>
+
+=cell C<I>
+
+=cell short
+
+=row
+
+=cell C<i>
+
+=cell C<I>
+
+=cell int
+
+=row
+
+=cell C<l>
+
+=cell C<I>
+
+=cell long
+
+=row
+
+=cell C<f>
+
+=cell C<N>
+
+=cell float
+
+=row
+
+=cell C<d>
+
+=cell C<N>
+
+=cell double
+
+=row
+
+=cell C<t>
+
+=cell C<S>
+
+=cell char *
+
+=row
+
+=cell C<p>
+
+=cell C<P>
+
+=cell void * (or other pointer)
+
+=row
+
+=cell C<I>
+
+=cell -
 
-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
-continuation.  If you have a continuation, you can invoke it to return to its
-point of creation any time you want.
+=cell Parrot_Interp *interpreter
 
-This type of flow control -- invoking continuations instead of performing bare
-jumps -- is X<Continuation Passing Style;CPS> Continuation Passing Style (CPS).
+=row
 
+=cell C<C>
 
+=cell -
 
-=head4 Tailcalls
+=cell a callback function pointer
 
-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,
-and is an important opportunity for optimization.  Here's a contrived example
-in pseudocode:
+=row
 
-  call add_two(5)
+=cell C<D>
 
-  subroutine add_two(value)
-    value = add_one(value)
-    return add_one(value)
+=cell -
 
-In this example, the subroutine C<add_two> makes two calls to c<add_one>. The
-second call to C<add_one> is the return value. C<add_one> gets called; its
-result gets returned to the caller of C<add_two>.  Nothing in C<add_two> uses
-that return value directly.
+=cell a callback function pointer
 
-A simple optimization is available for this type of code.  The second call to
-C<add_one> can return to the same place that C<add_two> returns; therefore,
-it's perfectly safe and correct to use the same return continuation that
-C<add_two> uses. The two subroutine calls can share a return continuation,
-instead of having to create a new continuation for each call.
+=row
 
-X<.tailcall directive>
+=cell C<Y>
 
-PIR provides the C<.tailcall> directive to identify similar situations.  Use it
-in place of the C<.return> directive. C<.tailcall> performs this optimization
-by reusing the return continuation of the parent function to make the tailcall:
+=cell C<P>
 
-=begin PIR
+=cell the subroutine C<C> or C<D> calls into
 
-  .sub 'main' :main
-      .local int value
-      value = add_two(5)
-      say value
-  .end
+=row
 
-  .sub 'add_two'
-      .param int value
-      .local int val2
-      val2 = add_one(value)
-      .tailcall add_one(val2)
-  .end
+=cell C<Z>
 
-  .sub 'add_one'
-      .param int a
-      .local int b
-      b = a + 1
-      .return (b)
-  .end
+=cell C<P>
 
-=end PIR
+=cell the argument for C<Y>
 
-This example above will print out the correct value "7".
+=end table
 
+For more information on callback functions, read the documentation in
+F<docs/pdds/pdd16_native_call.pod> and F<docs/pmc/struct.pod>.
 
 
 
@@ -982,6 +2745,84 @@
 
 X<PIR;Coroutines>
 X<Coroutines>
+
+As we mentioned in the previous chapter, coroutines are
+X<subroutines;coroutines> subroutines that
+can suspend themselves and return control to the caller--and then pick
+up where they left off the next time they're called, as if they never
+left.
+
+X<coroutines>
+In PASM, coroutines are subroutine-like objects:
+
+=begin PASM
+
+  newsub P0, .Coroutine, _co_entry
+
+=end PASM
+
+The C<Coroutine> object has its own user stack, register frame stacks,
+control stack, and pad stack. The pad stack is inherited from the
+caller. The coroutine's control stack has the caller's control stack
+prepended, but is still distinct. When the coroutine invokes itself,
+it returns to the caller and restores the caller's context (basically
+swapping all stacks). The next time the coroutine is invoked, it
+continues to execute from the point at which it previously returned:
+
+=begin PASM
+
+    new_pad 0                # push a new lexical pad on stack
+    new P0, "Int"            # save one variable in it
+    set P0, 10
+    store_lex -1, "var", P0
+
+    newsub P0, .Coroutine, _cor
+                             # make a new coroutine object
+    saveall                  # preserve environment
+    invoke                   # invoke the coroutine
+    restoreall
+    print "back\n"
+    saveall
+    invoke                   # invoke coroutine again
+    restoreall
+    print "done\n"
+    pop_pad
+    end
+
+  _cor:
+    find_lex P1, "var"       # inherited pad from caller
+    print "in cor "
+    print P1
+    print "\n"
+    inc P1                   # var++
+    saveall
+    invoke                   # yield(  )
+    restoreall
+    print "again "
+    branch _cor              # next invocation of the coroutine
+
+=end PASM
+
+This prints out the result:
+
+  in cor 10
+  back
+  again in cor 11
+  done
+
+X<invoke opcode (PASM);coroutines and>
+The C<invoke> inside the coroutine is commonly referred to as
+I<yield>. The coroutine never ends. When it reaches the bottom, it
+branches back up to C<_cor> and executes until it hits C<invoke>
+again.
+
+The interesting part about this example is that the coroutine yields
+in the same way that a subroutine is called. This means that the
+coroutine has to preserve its own register values. This example uses
+C<saveall> but it could have only stored the registers the coroutine
+actually used. Saving off the registers like this works because
+coroutines have their own register frame stacks.
+
 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!>.
@@ -1239,11 +3080,178 @@
 
   $P1 = $P0.'get_namespace'()
 
+=head3 Evaluating a Code String
+
+Z<CHP-9-SECT-7.6>
+
+X<code strings, evaluating>
+This isn't really a subroutine operation, but it does produce a code
+object that can be invoked. In this case, it's a X<bytecode segment
+object> bytecode segment object.
+
+The first step is to get an assembler or compiler for the target
+language:
+
+=begin PASM
+
+  compreg P1, "PASM"
+
+=end PASM
+
+Within the Parrot interpreter there are currently three registered
+languages: C<PASM>, C<PIR>, and C<PASM1>. The first two are for parrot
+assembly language and parrot intermediate representation code. The third
+is for evaluating single statements in PASM. Parrot automatically adds
+an C<end> opcode at the end of C<PASM1> strings before they're
+compiled.
+
+This example places a bytecode segment object into the destination
+register C<P0> and then invokes it with C<invoke>:
 
+=begin PASM
 
+  compreg P1, "PASM1"                # get compiler
+  set S1, "in eval\n"
+  compile P0, P1, "print S1"
+  invoke                             # eval code P0
+  print "back again\n"
+  end
 
+=end PASM
 
-=head2 Lexical Variables
+You can register a compiler or assembler for any language inside the
+Parrot core and use it to compile and invoke code from that language.
+These compilers may be written in PASM or reside in shared libraries.
+
+=begin PASM
+
+  compreg "MyLanguage", P10
+
+=end PASM
+
+In this example the C<compreg> opcode registers the subroutine-like
+object C<P10> as a compiler for the language "MyLanguage". See
+F<examples/compilers> and F<examples/japh/japh16.pasm> for an external
+compiler in a shared library.
+
+
+
+=head2 Lexicals and Globals
+
+So far, we've been treating Parrot registers like the variables of a
+high-level language. This is fine, as far as it goes, but it isn't the
+full picture. The dynamic nature and introspective features of
+languages like Perl make it desirable to manipulate variables by name,
+instead of just by register or stack location. These languages also
+have global variables, which are visible throughout the entire
+program. Storing a global variable in a register would either tie up
+that register for the lifetime of the program or require some unwieldy way
+to shuffle the data into and out of registers.
+
+Parrot provides structures for storing both global and lexically
+scoped named variables. Lexical and global variables must be PMC
+values. PASM provides instructions for storing and retrieving
+variables from these structures so the PASM opcodes can operate on
+their values.
+
+=head3 Globals
+
+Z<CHP-9-SECT-6.1>
+
+X<PASM (Parrot assembly language);global variables>
+Global variables are stored in a C<Hash>, so every variable name
+must be unique.  PASM has two opcodes for globals, C<set_global> and
+C<get_global>:
+
+=begin PASM
+
+  new P10, "Int"
+  set P10, 42
+  set_global "$foo", P10
+  # ...
+  get_global P0, "$foo"
+  print P0                        # prints 42
+  end
+
+=end PASM
+
+The first two statements create a C<Int> in the PMC register
+C<P10> and give it the value 42. In the third statement,
+C<set_global> stores that PMC as the named global variable C<$foo>.
+At some later point in the program, C<get_global> retrieves the PMC
+from the global variable by name, and stores it in C<P0> so it can be
+printed.
+
+The C<set_global> opcode only stores a reference to the object. If
+we add an increment statement:
+
+=begin PASM
+
+  inc P10
+
+=end PASM
+
+after the C<set_global> it increments the stored global, printing 43.
+If that's not what you want, you can C<clone> the PMC before you store
+it. Leaving the global variable as an alias does have advantages,
+though. If you retrieve a stored global into a register and modify it
+as follows:
+
+=begin PASM
+
+  get_global P0, "varname"
+  inc P0
+
+=end PASM
+
+the value of the stored global is directly modified, so you don't need
+to call C<set_global> again.
+
+The two-argument forms of C<set_global> and C<get_global> store or
+retrieve globals from the outermost namespace (what Perl users will
+know as the "main" namespace). A simple flat global namespace isn't
+enough for most languages, so Parrot also needs to support
+hierarchical namespaces for separating packages (classes and modules
+in Perl 6). Use C<set_rootglobal> and
+C<get_root_global> add an argument to select a nested namespace:
+
+=begin PASM
+
+  set_root_global ["Foo"], "var", P0 # store P0 as var in the Foo namespace
+  get_root_global P1, ["Foo"], "var"  # get Foo::var
+
+=end PASM
+
+Eventually the global opcodes will have variants that take a PMC to
+specify the namespace, but the design and implementation of these
+aren't finished yet.
+
+=head3 Lexicals
+
+X<PASM (Parrot assembly language);lexical variables>
+Lexical variables are stored in a lexical scratchpad. There's one pad
+for each lexical scope. Every pad has both a hash and an array, so
+elements can be stored either by name or by numeric index.
+
+=head4 Basic instructions
+
+Z<CHP-9-SECT-6.2.1>
+
+To store a lexical variable in the current scope pad, use C<store_lex>.
+Likewise, use C<find_lex> to retrieve a variable from the current pad.
+
+=begin PASM
+
+  new P0, "Int"            # create a variable
+  set P0, 10               # assign value to it
+  store_lex "foo", P0      # store the var with the variable name "foo"
+  # ...
+  find_lex P1, "foo"       # get the var "foo" into P1
+  print P1
+  print "\n"               # prints 10
+  end
+
+=end PASM
 
 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
@@ -1513,6 +3521,367 @@
 
 =head2 Classes and Objects
 
+This section revolves around one complete example that defines a
+class, instantiates objects, and uses them. The whole example is
+included at the end of the section.
+
+=head3 Class declaration
+
+Z<CHP-9-SECT-12.1>
+
+X<classes;in PASM>
+The C<newclass>X<newclass opcode (PASM)> opcode defines a new class.
+It takes two arguments, the name of the class and the destination
+register for the class PMC. All classes (and objects) inherit from the
+C<ParrotClass> PMCX<ParrotClass PMC>, which is the core of the Parrot
+object system.
+
+=begin PASM
+
+    newclass P1, "Foo"
+
+=end PASM
+
+To instantiate a new object of a particular class, you first look up
+the integer value for the class type with the C<find_type> opcode,
+then create an object of that type with the C<new> opcode:
+
+=begin PASM
+
+    find_type I1, "Foo"
+    new P3I I1
+
+=end PASM
+
+The C<new> opcode also checks to see if the class defines a
+method named "__init" and calls it if it exists.
+
+=head3 Attributes
+
+Z<CHP-9-SECT-12.2>
+
+X<attributes;in PASM>
+X<classes;attributes>
+The C<addattribute> opcode creates a slot in the class for an
+attribute (sometimes known as an I<instance variable>) and associates
+it with a name:
+
+=begin PASM
+
+    addattribute P1, ".i"                # Foo.i
+
+=end PASM
+
+This chunk of code
+from the C<__init> method looks up the position of the first
+attribute, creates a C<Int> PMC, and stores it as the first
+attribute:
+
+=begin PASM
+
+    classoffset I0, P2, "Foo"     # first "Foo" attribute of object P2
+    new P6, "Int"                 # create storage for the attribute
+    setattribute P2, I0, P6       # store the first attribute
+
+=end PASM
+
+The C<classoffset> opcodeX<classoffset opcode (PASM)> takes a PMC
+containing an object and the name of its class, and returns an integer
+index for the position of the first attribute. The C<setattribute>
+opcode uses the integer index to store a PMC value in one of the
+object's attribute slots. This example initializes the first
+attribute. The second attribute would be at C<I0 + 1>, the third
+attribute at C<I0 + 2>, etc:
+
+=begin PASM
+
+    inc I0
+    setattribute P2, I0, P7       # store next attribute
+    #...
+
+=end PASM
+
+There is also support for named parameters with fully qualified
+parameter names (although this is a little bit slower than getting
+the class offset once and accessing several attributes by index):
+
+=begin PASM
+
+    new P6, "Int"
+    setattribute P2, "Foo\x0.i", P6   # store the attribute
+
+=end PASM
+
+You use the same integer index to retrieve the value of an attribute.
+The C<getattribute>X<getattribute opcode (PASM)> opcode takes an object and
+an index as arguments and returns the attribute PMC at that position:
+
+=begin PASM
+
+    classoffset I0, P2, "Foo"         # first "Foo" attribute of object P2
+    getattribute P10, P2, I0          # indexed get of attribute
+
+=end PASM
+
+or
+
+=begin PASM
+
+    getattribute P10, P2, "Foo\x0.i"  # named get
+
+=end PASM
+
+To set the value of an attribute PMC, first retrieve it with
+C<getattribute> and then assign to the returned PMC. Because PMC
+registers are only pointers to values, you don't need to store the PMC
+again after you modify its value:
+
+=begin PASM
+
+    getattribute P10, P2, I0
+    set P10, I5
+
+=end PASM
+
+=head3 Methods
+
+Z<CHP-9-SECT-12.3>
+
+X<methods;in PASM>
+X<classes;methods>
+X<classes;namespaces>
+Methods in PASM are just subroutines installed in the namespace of the
+class. You define a method with the C<.pcc_sub> directive before the
+label:
+
+=begin PASM
+
+  .pcc_sub _half:                 # I5 = self."_half"()
+    classoffset I0, P2, "Foo"
+    getattribute P10, P2, I0
+    set I5, P10                   # get value
+    div I5, 2
+    invoke P1
+
+=end PASM
+
+This routine returns half of the value of the first attribute of the
+object. Method calls use the Parrot calling conventions so they always
+pass the I<invocant> object (often called I<self>) in C<P2>. Invoking
+the return continuation in C<P1> returns control to the caller.
+
+The C<.pcc_sub> directive automatically stores the subroutine as a
+global in the current namespace. The C<.namespace> directive sets the
+current namespace:
+
+=begin PASM
+
+  .namespace [ "Foo" ]
+
+=end PASM
+
+If the namespace is explicitly set to an empty string or key, then the
+subroutine is stored in the outermost namespace.
+
+The C<callmethodcc>X<callmethodcc opcode (PASM)> opcode makes a method
+call. It follows the Parrot calling conventions, so it expects to
+find the invocant object in C<P2>, the method object in C<P0>, etc. It
+adds one bit of magic, though. If you pass the name of the method in
+C<S0>, C<callmethodcc> looks up that method name in the invocant
+object and stores the method object in C<P0> for you:
+
+=begin PASM
+
+    set S0, "_half"             # set method name
+    set P2, P3                  # the object
+    callmethodcc                # create return continuation, call
+    print I5                    # result of method call
+    print "\n"
+
+=end PASM
+
+The C<callmethodcc> opcode also generates a return continuation and
+stores it in C<P1>. The C<callmethod> opcode doesn't generate a return
+continuation, but is otherwise identical to C<callmethodcc>. Just like
+ordinary subroutine calls, you have to preserve and restore any
+registers you want to keep after a method call. Whether you store
+individual registers, register frames, or half register frames is up
+to you.
+
+=head4 Overriding vtable functions
+
+Z<CHP-9-SECT-12.3.1>
+
+Every object inherits a default set of I<vtable> functions from the
+C<ParrotObject> PMC, but you can also override them with your own
+methods. The vtable functions have predefined names that start with a
+double underscore "__". The following code defines a method named
+C<__init> in the C<Foo> class that initializes the first attribute of
+the object with an integer:
+
+=begin PASM
+
+  .sub __init:
+    classoffset I0, P2, "Foo"     # lookup first attribute position
+    new P6, "Int"                 # create storage for the attribute
+    setattribute P2, I0, P6       # store the first attribute
+    invoke P1                     # return
+
+=end PASM
+
+Ordinary methods have to be called explicitly, but the vtable
+functions are called implicitly in many different contexts. Parrot
+saves and restores registers for you in these calls. The C<__init>
+method is called whenever a new object is constructed:
+
+=begin PASM
+
+    find_type I1, "Foo"
+    new P3, I1          # call __init if it exists
+
+=end PASM
+
+A few other vtable functions in the complete code example for this
+section are C<__set_integer_native>, C<__add>, C<__get_integer>,
+C<__get_string>, and C<__increment>. The C<set> opcode calls Foo's
+C<__set_integer_native> vtable function when its destination register
+is a C<Foo> object and the source register is a native integer:
+
+=begin PASM
+
+    set P3, 30          # call __set_integer_native method
+
+=end PASM
+
+The C<add> opcode calls Foo's C<__add> vtable function when it adds
+two C<Foo> objects:
+
+=begin PASM
+
+    new P4, I1          # same with P4
+    set P4, 12
+    new P5, I1          # create a new store for add
+
+    add P5, P3, P4      # __add method
+
+=end PASM
+
+The C<inc> opcode calls Foo's C<__increment> vtable function when it
+increments a C<Foo> object:
+
+=begin PASM
+
+    inc P3              # __increment
+
+=end PASM
+
+Foo's C<__get_integer> and C<__get_string> vtable functions are called
+whenever an integer or string value is retrieved from a C<Foo> object:
+
+=begin PASM
+
+    set I10, P5         # __get_integer
+    #...
+    print P5            # calls __get_string, prints 'fortytwo'
+
+=end PASM
+
+
+=head3 Inheritance
+
+Z<CHP-9-SECT-12.4>
+
+X<inheritance;in PASM>
+X<classes;inheritance>
+The C<subclass>X<subclass opcode (PASM)> opcode creates a new class that
+inherits methods and attributes from another class. It takes 3
+arguments: the destination register for the new class, a register
+containing the parent class, and the name of the new class:
+
+=begin PASM
+
+    subclass P3, P1, "Bar"
+
+=end PASM
+
+X<multiple inheritance; in PASM>
+For multiple inheritance, the C<addparent>X<addparent opcode (PASM)>
+opcode adds additional parents to a subclass.
+
+=begin PASM
+
+  newclass P4, "Baz"
+  addparent P3, P4
+
+=end PASM
+
+To override an inherited method, define a method with the same name in
+the namespace of the subclass. The following code overrides Bar's
+C<__increment> method so it decrements the value instead of
+incrementing it:
+
+=begin PASM
+
+  .namespace [ "Bar" ]
+
+  .sub __increment:
+    classoffset I0, P2, "Foo"     # get Foo's attribute slot offset
+    getattribute P10, P2, I0      # get the first Foo attribute
+    dec P10                       # the evil line
+    invoke P1
+
+=end PASM
+
+Notice that the attribute inherited from C<Foo> can only be looked up
+with the C<Foo> class name, not the C<Bar> class name. This preserves
+the distinction between attributes that belong to the class and
+inherited attributes.
+
+Object creation for subclasses is the same as for ordinary classes:
+
+=begin PASM
+
+    find_type I1, "Bar"
+    new P5, I1
+
+=end PASM
+
+Calls to inherited methods are just like calls to methods defined in
+the class:
+
+=begin PASM
+
+    set P5, 42                  # inherited __set_integer_native
+    inc P5                      # overridden __increment
+    print P5                    # prints 41 as Bar's __increment decrements
+    print "\n"
+
+    set S0, "_half"             # set method name
+    set P2, P5                  # the object
+    callmethodcc                # create return continuation, call
+    print I5
+    print "\n"
+
+=end PASM
+
+=head3 Additional Object Opcodes
+
+Z<CHP-9-SECT-12.5>
+
+The C<isa> and C<can> instructuions are also useful when working with
+objects. C<isa> checks whether an object belongs to or
+inherits from a particular class. C<can> checks whether
+an object has a particular method. Both return a true or false value.
+
+=begin PASM
+
+    $I0 = isa $P3, "Foo"           # 1
+    $I0 = isa $P3, "Bar"           # 1
+    $I0 = can $P3, "add"         # 1
+
+=end PASM
+
+
 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
@@ -2085,6 +4454,101 @@
 
 =head2 Exceptions
 
+=head2 Exceptions and Exception Handlers
+
+Z<CHP-9-SECT-8>
+
+X<exceptions>
+X<exception handlers>
+Exceptions provide a way of calling a piece of code outside the normal
+flow of control. They are mainly used for error reporting or cleanup
+tasks, but sometimes exceptions are just a funny way to branch from
+one code location to another one. The design and implementation of
+exceptions in Parrot isn't complete yet, but this section will give
+you an idea where we're headed.
+
+Exceptions are objects that hold all the information needed to handle
+the exception: the error message, the severity and type of the error,
+etc. The class of an exception object indicates the kind of exception
+it is.
+
+Exception handlers are derived from continuations. They are ordinary
+subroutines that follow the Parrot calling conventions, but are never
+explicitly called from within user code. User code pushes an exception
+handler onto the control stack with the C<set_eh>X<set_eh opcode (PASM)>
+opcode. The system calls the installed exception handler only when an
+exception is thrown (perhaps because of code that does division by
+zero or attempts to retrieve a global that wasn't stored.)
+
+=begin PASM
+
+    newsub P20, .ExceptionHandler, _handler
+    set_eh P20                  # push handler on control stack
+    null P10                    # set register to null
+    get_global P10, "none"     # may throw exception
+    clear_eh                    # pop the handler off the stack
+    #...
+
+  _handler:                     # if not, execution continues here
+    is_null P10, not_found      # test P10
+    #...
+
+=end PASM
+
+This example creates a new exception handler subroutine with the
+C<newsub> opcode and installs it on the control stack with the
+C<set_eh> opcode. It sets the C<P10> register to a null value (so it
+can be checked later) and attempts to retrieve the global variable
+named C<none>. If the global variable is found, the next statement
+(C<clear_eh>) pops the exception handler off the control stack and
+normal execution continues. If the C<get_global> call doesn't find
+C<none> it throws an exception by pushing an exception object onto the
+control stack. When Parrot sees that it has an exception, it pops it
+off the control stack and calls the exception handler C<_handler>.
+
+The first exception handler in the control stack sees every exception
+thrown. The handler has to examine the exception object and decide
+whether it can handle it (or discard it) or whether it should
+C<rethrow> the exception to pass it along to an exception handler
+deeper in the stack. The C<rethrow>X<rethrow opcode (PASM)> opcode is only
+valid in exception handlers. It pushes the exception object back onto
+the control stack so Parrot knows to search for the next exception
+handler in the stack. The process continues until some exception
+handler deals with the exception and returns normally, or until there
+are no more exception handlers on the control stack. When the system
+finds no installed exception handlers it defaults to a final action,
+which normally means it prints an appropriate message and terminates
+the program.
+
+When the system installs an exception handler, it creates a return
+continuation with a snapshot of the current interpreter context. If
+the exception handler just returns (that is, if the exception is
+cleanly caught) the return continuation restores the control stack
+back to its state when the exception handler was called, cleaning up
+the exception handler and any other changes that were made in the
+process of handling the exception.
+
+Exceptions thrown by standard Parrot opcodes (like the one thrown by
+C<get_global> above or by the C<throw> opcode) are always resumable,
+so when the exception handler function returns normally it continues
+execution at the opcode immediately after the one that threw the
+exception. Other exceptions at the run-loop level are also generally
+resumable.
+
+=begin PASM
+
+  new P10, 'Exception'    # create new Exception object
+  set P10, 'I die'        # set message attribute
+  throw P10               # throw it
+
+=end PASM
+
+Exceptions are designed to work with the Parrot calling conventions.
+Since the return addresses of C<bsr> subroutine calls and exception
+handlers are both pushed onto the control stack, it's generally a bad
+idea to combine the two.
+
+
 Parrot includes a robust exception mechanism that is not only used internally
 to implement a variety of control flow constructs, but is also available for
 use directly from PIR code. Exceptions, in as few words as possible, are
@@ -2233,6 +4697,334 @@
 C<'annotation'> which is the hash of annotations that were in effect at that
 point, and C<'sub'> which is the Sub PMC of that function.
 
+=head2 Events
+
+Z<CHP-9-SECT-9>
+
+An event is a notification that something has happened: a timer
+expired, an IO operation finished, a thread sent a message to
+another thread, or the user pressed C<Ctrl-C> to interrupt program
+execution.
+
+What all of these events have in common is that they arrive
+asynchronously. It's generally not safe to interrupt program flow at an
+arbitrary point and continue at a different position, so the event is
+placed in the
+interpreter's task queue. The run loops code regularly checks whether
+an event needs to be handled. Event handlers may be an internal piece
+of code or a user-defined event handler subroutine.
+
+Events are still experimental in Parrot, so the implementation and
+design is subject to change.
+
+=head3 Timers
+
+Z<CHP-9-SECT-9.1>
+
+C<Timer> objects are the replacement for Perl 5's C<alarm> handlers.
+They are also a significant improvement. Timers can fire once or
+repeatedly, and multiple timers can run independently. The precision
+of a timer is limited by the OS Parrot runs on, but it is always more
+fine-grained then a whole second. The final syntax isn't yet fixed, so
+please consult the documentation for examples.
+
+=head3 Signals
+
+Z<CHP-9-SECT-9.2>
+
+Signal handling is related to events. When Parrot gets a signal it
+needs to handle from the OS, it converts that signal into an event and
+broadcasts it to all running threads. Each thread independently
+decides if it's interested in this signal and, if so, how to respond to it.
+
+=begin PASM
+
+    newsub P20, .ExceptionHandler, _handler
+    set_eh P20                  # establish signal handler
+    print "send SIGINT:\n"
+    sleep 2                     # press ^C after you saw start
+    print "no SIGINT\n"
+    end
+  _handler:
+    .include "signal.pasm"      # get signal definitions
+    print "caught "
+    set I0, P5["type"]         # if _type is negative, the ...
+    neg I0, I0                  # ... negated type is the signal
+    ne I0, .SIGINT, nok
+    print "SIGINT\n"
+  nok:
+    end
+
+=end PASM
+
+This example creates a signal handler and pushes it on to the control
+stack. It then prompts the user to send a C<SIGINT> from the shell
+(this is usually C<Ctrl-C>, but it varies in different shells), and
+waits for 2 seconds. If the user doesn't send a SIGINT in 2 seconds
+the example just prints "no SIGINT" and ends. If the user does send a
+SIGINT, the signal handler catches it, prints out "caught SIGINT" and
+ends.N<Currently, only Linux installs a C<SIGINT> C<sigaction>
+handler, so this example won't work on other platforms.>
+
+=head2 Threads
+
+Z<CHP-9-SECT-10>
+
+Threads allow multiple pieces of code to run in parallel. This is
+useful when you have multiple physical CPUs to share the load of
+running individual threads. With a single processor, threads still
+provide the feeling of parallelism, but without any improvement in
+execution time. Even worse, sometimes using threads on a single
+processor will actually slow down your program.
+
+Still, many algorithms can be expressed more easily in terms of
+parallel running pieces of code and many applications profit from
+taking advantage of multiple CPUs. Threads can vastly simplify
+asynchronous programs like internet servers: a thread splits off,
+waits for some IO to happen, handles it, and relinquishes the
+processor again when it's done.
+
+Parrot compiles in thread support by default (at least, if the
+platform provides some kind of support for it). Unlike Perl 5,
+compiling with threading support doesn't impose any execution time
+penalty for a non-threaded program. Like exceptions and events,
+threads are still under development, so you can expect significant
+changes in the near future.
+
+As outlined in the previous chapter, Parrot implements three different
+threading models. (B<Note>:  As of version 1.0, the C<TQueue> PMC will be
+deprecated, rendering the following discussion obsolete.) The following
+example uses the third model, which takes advantage of shared data. It uses a
+C<TQueue> (thread-safe queue) object to synchronize the two parallel running
+threads. This is only a simple example to illustrate threads, not a typical
+usage of threads (no-one really wants to spawn two threads just to print out a
+simple string).
+
+=begin PASM
+
+    get_global P5, "_th1"              # locate thread function
+    new P2, "ParrotThread"              # create a new thread
+    find_method P0, P2, "thread3"       # a shared thread's entry
+    new P7, "TQueue"                    # create a Queue object
+    new P8, "Int"                       # and a Int
+    push P7, P8                         # push the Int onto queue
+    new P6, "String"                    # create new string
+    set P6, "Js nte artHce\n"
+    set I3, 3                           # thread function gets 3 args
+    invoke                              # _th1.run(P5,P6,P7)
+    new P2, "ParrotThread"              # same for a second thread
+    get_global P5, "_th2"
+    set P6, "utaohrPro akr"             # set string to 2nd thread's
+    invoke                              # ... data, run 2nd thread too
+    end                                 # Parrot joins both
+
+  .pcc_sub _th1:                        # 1st thread function
+  w1: sleep 0.001                       # wait a bit and schedule
+    defined I1, P7                      # check if queue entry is ...
+    unless I1, w1                       # ... defined, yes: it's ours
+    set S5, P6                          # get string param
+    substr S0, S5, I0, 1                # extract next char
+    print S0                            # and print it
+    inc I0                              # increment char pointer
+    shift P8, P7                        # pull item off from queue
+    if S0, w1                           # then wait again, if todo
+    invoke P1                           # done with string
+
+  .pcc_sub _th2:                        # 2nd thread function
+  w2: sleep 0.001
+    defined I1, P7                      # if queue entry is defined
+    if I1, w2                           # then wait
+    set S5, P6
+    substr S0, S5, I0, 1                # if not print next char
+    print S0
+    inc I0
+    new P8, "Int"                       # and put a defined entry
+    push P7, P8                         # onto the queue so that
+    if S0, w2                           # the other thread will run
+    invoke P1                           # done with string
+
+=end PASM
+
+This example creates a C<ParrotThread> object and calls its C<thread3>
+method, passing three arguments: a PMC for the C<_th1> subroutine in
+C<P5>, a string argument in C<P6>, and a C<TQueue> object in C<P7>
+containing a single integer. Remember from the earlier section
+"Parrot calling conventions" that registers 5-15
+hold the arguments for a subroutine or method call and C<I3> stores
+the number of arguments. The thread object is passed in C<P2>.
+
+This call to the C<thread3> method spawns a new thread to run the
+C<_th1> subroutine. The main body of the code then creates a second
+C<ParrotThread> object in C<P2>, stores a different subroutine in
+C<P5>, sets C<P6> to a new string value, and then calls the C<thread3>
+method again, passing it the same C<TQueue> object as the first
+thread. This method call spawns a second thread. The main body of code
+then ends, leaving the two threads to do the work.
+
+At this point the two threads have already started running. The first
+thread (C<_th1>) starts off by sleeping for a 1000th of a second. It
+then checks if the C<TQueue> object contains a value. Since it
+contains a value when the thread is first called, it goes ahead and
+runs the body of the subroutine. The first thing this does is shift
+the element off the C<TQueue>. It then pulls one character off a copy
+of the string parameter using C<substr>, prints the character,
+increments the current position (C<I0>) in the string, and loops back
+to the C<w1> label and sleeps. Since the queue doesn't have any
+elements now, the subroutine keeps sleeping.
+
+Meanwhile, the second thread (C<_th2>) also starts off by sleeping for
+a 1000th of a second. It checks if the shared C<TQueue> object
+contains a defined value but unlike the first thread it only continues
+sleeping if the queue does contain a value. Since the queue contains a
+value when the second thread is first called, the subroutine loops
+back to the C<w2> label and continues sleeping. It keeps sleeping
+until the first thread shifts the integer off the queue, then runs the
+body of the subroutine. The body pulls one character off a copy of the
+string parameter using C<substr>, prints the character, and increments
+the current position in the string. It then creates a new
+C<Int>, pushes it onto the shared queue, and loops back to the
+C<w2> label again to sleep. The queue has an element now, so the
+second thread keeps sleeping, but the first thread runs through its
+loop again.
+
+The two threads alternate like this, printing a character and marking
+the queue so the next thread can run, until there are no more
+characters in either string. At the end, each subroutine invokes the
+return continuation in C<P1> which terminates the thread. The
+interpreter waits for all threads to terminate in the cleanup phase
+after the C<end> in the main body of code.
+
+The final printed result (as you might have guessed) is:
+
+  Just another Parrot Hacker
+
+The syntax for threads isn't carved in stone and the implementation
+still isn't finished but as this example shows, threads are working
+now and already useful.
+
+Several methods are useful when working with threads. The C<join>
+method belongs to the C<ParrotThread> class. When it's called on a
+C<ParrotThread> object, the calling code waits until the thread
+terminates.
+
+=begin PASM
+
+    new P2, "ParrotThread"      # create a new thread
+    set I5, P2                  # get thread ID
+
+    find_method P0, P2, "join"  # get the join method...
+    invoke                      # ...and join (wait for) the thread
+    set P16, P5                 # the return result of the thread
+
+=end PASM
+
+C<kill> and C<detach> are interpreter methods, so you have to grab the
+current interpreter object before you can look up the method object.
+
+=begin PASM
+
+    set I5, P2                  # get thread ID of thread P2
+    getinterp P3                # get this interpreter object
+    find_method P0, P3, "kill"  # get kill method
+    invoke                      # kill thread with ID I5
+
+    find_method P0, P3, "detach"
+    invoke                      # detach thread with ID I5
+
+=end PASM
+
+By the time you read this, some of these combinations of statements
+and much of the threading syntax above may be reduced to a simpler set
+of opcodes.
+
+=head2 Loading Bytecode
+
+Z<CHP-9-SECT-11>
+
+In addition to running Parrot bytecode on the command-line, you can
+also load pre-compiled bytecode directly into your PASM source file.
+The C<load_bytecode>X<load_bytecode opcode (PASM)> opcode takes a single
+argument: the name of the bytecode file to load. So, if you create a
+file named F<file.pasm> containing a single subroutine:
+
+=begin PASM
+
+  # file.pasm
+  .sub _sub2:               # .sub stores a global sub
+     print "in sub2\n"
+     invoke P1
+
+=end PASM
+
+and compile it to bytecode using the C<-o> command-line switch:
+
+  $ parrot -o file.pbc file.pasm
+
+You can then load the compiled bytecode into F<main.pasm> and directly
+call the subroutine defined in F<file.pasm>:
+
+=begin PASM
+
+  # main.pasm
+  main:
+    load_bytecode "file.pbc"    # compiled file.pasm
+    get_global P0, "_sub2"
+    invokecc
+    end
+
+=end PASM
+
+The C<load_bytecode> opcode also works with source files, as long as
+Parrot has a compiler registered for that type of file:
+
+=begin PASM
+
+  # main2.pasm
+  main:
+    load_bytecode "file.pasm"  # PASM source code
+    set_global P0, "_sub2"
+    invokecc
+    end
+
+=end PASM
+
+Subroutines marked with C<:load> run as soon as they're loaded (before
+C<load_bytecode> returns), rather than waiting to be called. A
+subroutine marked with C<:main> will always run first, no matter what
+name you give it or where you define it in the file.
+
+=begin PASM
+
+  # file3.pasm
+  .sub :load                    # mark the sub as to be run
+    print "file3\n"
+    invoke P1                   # return
+
+  # main3.pasm
+  first:                        # first is never invoked
+    print "never\n"
+    invoke P1
+
+  .sub :main                    # because _main is marked as the
+    print "main\n"              # MAIN entry of program execution
+    load_bytecode "file3.pasm"
+    print "back\n"
+    end
+
+=end PASM
+
+This example uses both C<:load> and C<:main>. Because the C<main>
+subroutine is defined with C<:main> it will execute first even though
+another subroutine comes before it in the file. C<main> prints a
+line, loads the PASM source file, and then prints another line.
+Because C<_entry> in F<file3.pasm> is marked with C<:load> it runs
+before C<load_bytecode> returns, so the final output is:
+
+  main
+  file3
+  back
+
+
 =cut
 
 # Local variables:

Modified: trunk/docs/book/ch09_pasm.pod
==============================================================================
--- trunk/docs/book/ch09_pasm.pod	Fri May 15 03:09:05 2009	(r38786)
+++ trunk/docs/book/ch09_pasm.pod	Fri May 15 04:08:26 2009	(r38787)
@@ -117,58 +117,6 @@
 
 =end PASM
 
-=head3 Constants
-
-Z<CHP-9-SECT-2.1>
-
-X<PASM (Parrot assembly language);constants>
-We've already seen constants in PIR, and for the most part the syntax
-is the same in PASM. We will give a brief refresher here, but see the
-chapter on PIR for a more in-depth discussion of constants and datatypes.
-
-Integer constants in Parrot are signed integers.N<The sizes of integers
-and all other data values like floats are defined when Parrot is
-configured and built. Integers are typically 32 bits wide on 32-bit
-computers (a range of -2G<31> to +2G<31>-1) and twice that size on
-64-bit processors.> Decimal integer constants can have a positive (C<+>) or
-negative (C<->) sign in front. Binary integers are preceded by C<0b>
-or C<0B>, and hexadecimal integers are preceded by C<0x> or C<0X>:
-
-=begin PASM
-
-  print 42         # Decimalinteger constant
-  print +144       # integer constant
-  print 0x2A       # hexadecimal integer
-  print 0b1101     # binary integer
-
-=end PASM
-
-Floating-point constants can also be positive or negative. Scientific
-notation provides an exponent, marked with C<e> or C<E> (the sign of
-the exponent is optional):
-
-=begin PASM
-
-  print 3.14159    # floating point constant
-  print 1.e6       # scientific notation
-  print -1.23e+45
-
-=end PASM
-
-String constants are wrapped in single or double quotation marks.
-Quotation marks inside the string must be escaped by a backslash.
-Other special characters also have escape sequences. These are the
-same as for Perl 5's C<qq()> operator: C<\t> (tab), C<\n> (newline),
-C<\r> (return), C<\f> (form feed), C<\\> (literal slash), C<\">
-(literal double quote), etc.
-
-=begin PASM
-
-  print "string\n"    # string constant with escaped newline
-  print "\\"          # a literal backslash
-  print 'a\n'         # three chars: 'a', a backslash, and a 'n'
-
-=end PASM
 
 =head3 Working with Registers
 
@@ -305,3047 +253,11 @@
 yet mature enough to support these kinds of semantics. One day in the future,
 Parrot might change this, but it hasn't changed yet.
 
-=head4 PMC object types
-
-Z<CHP-9-SECT-2.2.2>
-
-X<PMCs (Polymorphic Containers);object types>
-Every PMC has a distinct type that determines its behavior through the
-vtable interface. In the chapter on PIR, we've seen a number of these vtable
-functions already, and seen how they implement the behaviors found inside
-the various opcodes. The vtable interface is standard, and all PMCs implement
-the exact same set of vtables. We've seen some of the vtables and their uses,
-and more of them will be discussed in this chapter and later in the various
-reference chapters.
-
-The C<typeof> opcode can be used to determine the type of a PMC. When
-the source argument is a PMC and the destination is a string register,
-C<typeof> returns the name of the type:
-
-=begin PASM
-
-  new P0, "String"
-  typeof S0, P0               # S0 is "String"
-  print S0
-  print "\n"
-  end
-
-=end PASM
-
-Using C<typeof> with a PMC output parameter instead, it returns the Class
-PMC for that type.
-
-=head4 Autoboxing
-
-Z<CHP-9-SECT-2.2.3>
-
-X<Autoboxing>
-As we've seen in the previous chapters about PIR, we can convert between
-primitive string, integer, and number types and PMCs. PIR used the C<=>
-operator to make these conversions. PASM uses the C<set> opcode to do the
-same thing. C<set> will perform the type conversions for us automatically,
-in a process called I<autoboxing>.
-
-Assigning a primitive data type to a PMC of a String, Integer, or Float type
-converts that PMC to the new type. So, assigning a string to a Number PMC
-converts it into a String PMC. Assigning an integer value converts it to a
-C<Integer>, and assigning C<undef> converts it to an C<Undef> PMC:
-
-=begin PASM
-
-  new P0, "String"
-  set P0, "Ford\n"
-  print P0           # prints "Ford\n"
-  set P0, 42
-  print P0           # prints 42
-  print "\n"
-  typeof S0, P0
-  print S0           # prints "Integer"
-  print "\n"
-  end
-
-=end PASM
-
-C<P0> starts as a C<String>, but when C<set> assigns it an integer
-value 42 (replacing the old string value C<"Ford">), it changes type
-to C<Integer>. This behavior only works for the wrapper PMC types for the
-primitive values string, int, and num. Other PMC classes will have different
-behaviors when you try to assign a primitive value to them.
-
-We can also use the C<box> opcode to explicitly convert an integer, a float,
-or a string into an appropriate PMC type.
-
-=begin PASM
-
-  box P0, 3
-  typeof S0, P0         # P0 is an "Integer"
-  box P1, "hello"
-  typeof S0, P1         # P1 is a "String"
-  box P2, 3.14
-  typeof S0, P2         # P2 is a "Number"
-
-=end PASM
-
-=head3 Math Operations
-
-Z<CHP-9-SECT-2.3>
-
-X<PASM (Parrot assembly language);math operations>
-PASM has a full set of math instructions. These work with integers,
-floating-point numbers, and PMCs that implement the vtable methods of
-a numeric object. Most of the major math opcodes have two- and
-three-argument forms:
-
-=begin PASM
-
-  add I10, I11, I2        # I10 = I11 + I2
-  add I0, I1              # I0 += I1
-  add I0, I0, I1          # Same!
-
-=end PASM
-
-The three-argument form of C<add>X<add opcode (PASM)> stores the sum
-of the last two registers in the first register. The two-argument form
-adds the first register to the second and stores the result back in
-the first register.
-
-The source arguments can be Parrot registers or constants, but they
-must be compatible with the type of the destination register.
-Generally, "compatible" means that the source and destination have to
-be the same type, but there are a few exceptions:
-
-=begin PASM
-
-  sub P0, P1, 2          # P0 = P1 - 2
-  sub P0, P1, 1.5        # P0 = P1 - 1.5
-
-=end PASM
-
-If the destination register is an integer register, like C<I0>, the
-other arguments must be integer registers or integer constants. A
-floating-point destination, like C<N0>, usually requires
-floating-point arguments, but many math opcodes also allow the final
-argument to be an integer. Opcodes with a PMC destination register may
-take an integer, floating-point, or PMC final argument:
-
-=begin PASM
-
-  mul P0, P1             # P0 *= P1
-  mul P0, I1
-  mul P0, N1
-  mul P0, P1, P2         # P0 = P1 * P2
-  mul P0, P1, I2
-  mul P0, P1, N2
-
-=end PASM
-
-X<PMCs (Polymorphic Containers);operations on>
-Operations on a PMC are implemented by the vtable method of the destination
-(in the two-argument form) or the left source argument (in the three argument
-form). The result of an operation is entirely determined by the behavior of
-the PMCs vtable. For some types of PMC the results may be very idiosyncratic
-and not intuitive, so it's important to familiarize yourself with the behavior
-of the particular PMC before you start performing a lot of operations on it.
-
-We won't list every math opcode here, but we'll list some of the most common
-ones. You can get a complete list in "PASM Opcodes" in Chapter 11.
-
-=head4 Unary math opcodes
-
-Z<CHP-9-SECT-2.3.1>
-
-The unary opcodes have either a destination argument and a source
-argument, or a single argument as destination and source. Some of the
-most common unary math opcodes are C<inc> (increment), C<dec>
-(decrement), C<abs> (absolute value), C<neg> (negate), and C<fact>
-(factorial):
-
-=begin PASM
-
-  abs N0, -5.0  # the absolute value of -5.0 is 5.0
-  fact I1, 5    # the factorial of 5 is 120
-  inc I1        # 120 incremented by 1 is 121
-
-=end PASM
-
-=head4 Binary math opcodes
-
-Z<CHP-9-SECT-2.3.2>
-
-X<PASM (Parrot assembly language);math operations;binary>
-Binary opcodes have two source arguments and a destination argument, and we
-saw examples of these types above. As we mentioned before, most binary math
-opcodes have a two-argument form in which the first argument is both a source
-and the destination. Parrot provides C<add>X<add opcode (PASM)> (addition),
-C<sub>X<sub opcode (PASM)> (subtraction), C<mul>X<mul opcode (PASM)>
-(multiplication), C<div>X<div opcode (PASM)> (division), and C<pow>X<pow
-opcode (PASM)> (exponent) opcodes, as well as two different modulus
-operations. C<mod>X<mod opcode (PASM)> is Parrot's implementation of modulus,
-and C<cmod>X<cmod opcode (PASM)> performs an operation equivalent the C<%>
-operator from the C programming language. It also provides C<gcd>X<gcd opcode
-(PASM)> (greatest common divisor) and C<lcm>X<lcm opcode (PASM)> (least common
-multiple).
-
-=begin PASM
-
-  div I0, 12, 5   # I0 = 12 / 5
-  mod I0, 12, 5   # I0 = 12 % 5
-
-=end PASM
-
-=head4 Floating-point operations
-
-Z<CHP-9-SECT-2.3.3>
-
-X<PASM (Parrot assembly language);math operations;floating-point>
-Although most of the math operations work with both floating-point numbers
-and integers, a few require floating-point destination registers. Among these
-are C<ln> (natural log), C<log2> (log base 2), C<log10> (log base 10), and
-C<exp> (I<e>G<x>), as well as a full set of trigonometric opcodes such as
-C<sin> (sine), C<cos> (cosine), C<tan> (tangent), C<sec> (secant), C<cosh>
-(hyperbolic cosine), C<tanh> (hyperbolic tangent), C<sech> (hyperbolic secant),
-C<asin> (arc sine), C<acos> (arc cosine), C<atan> (arc tangent), C<asec> (arc
-secant), C<exsec> (exsecant), C<hav> (haversine), and C<vers> (versine). All
-angle arguments for the X<trigonometric functions (PASM)> trigonometric
-functions are in radians:
-
-=begin PASM
-
-  sin N1, N0
-  exp N1, 2
-
-=end PASM
-
-The majority of the floating-point operations have a single source argument
-and a single destination argument. Even though the destination must be a
-floating-point register, the source can be either an integer or floating-point
-number.
-
-The C<atan>X<atan opcode (PASM)> opcode also has a three-argument variant that
-implements C's C<atan2()>:
-
-=begin PASM
-
-  atan N0, 1, 1
-
-=end PASM
-
-=head3 Working with Strings
-
-Z<CHP-9-SECT-2.4>
-
-X<PASM (Parrot assembly language);string operations>
-String operations work with string registers and with PMCs that implement a
-string class. String operations on PMC registers require all their string
-arguments to be String PMCs.
-
-=head4 Concatenating strings
-
-Z<CHP-9-SECT-2.4.1>
-
-X<PASM (Parrot assembly language);string operations;concatenation>
-Use the C<concat>X<concat opcode (PASM)> opcode to concatenate
-strings. With string register or string constant arguments, C<concat>
-has both a two-argument and a three-argument form. The first argument
-is a source and a destination in the two-argument form:
-
-=begin PASM
-
-  set S0, "ab"
-  concat S0, "cd"     # S0 has "cd" appended
-  print S0            # prints "abcd"
-  print "\n"
-
-  concat S1, S0, "xy" # S1 is the string S0 with "xy" appended
-  print S1            # prints "abcdxy"
-  print "\n"
-  end
-
-=end PASM
-
-The first C<concat> concatenates the string "cd" onto the string "ab" in
-C<S0>. It generates a new string "abcd" and changes C<S0> to point to the
-new string. The second C<concat> concatenates "xy" onto the string "abcd"
-in C<S0> and stores the new string in C<S1>.
-
-X<PMCs (Polymorphic Containers);concatenation>
-For PMC registers, C<concat> has only a three-argument form with
-separate registers for source and destination:
-
-=begin PASM
-
-  new P0, "String"
-  new P1, "String"
-  new P2, "String"
-  set P0, "ab"
-  set P1, "cd"
-  concat P2, P0, P1
-  print P2            # prints abcd
-  print "\n"
-  end
-
-=end PASM
-
-Here, C<concat> concatenates the strings in C<P0> and C<P1> and stores
-the result in C<P2>.
-
-=head4 Repeating strings
-
-Z<CHP-9-SECT-2.4.2>
-
-X<PASM (Parrot assembly language);string operations;repeating strings>
-The C<repeat>X<repeat opcode (PASM)> opcode repeats a string a certain
-number of times:
-
-=begin PASM
-
-  set S0, "x"
-  repeat S1, S0, 5  # S1 = S0 x 5
-  print S1          # prints "xxxxx"
-  print "\n"
-  end
-
-=end PASM
-
-In this example, C<repeat> generates a new string with "x" repeated
-five times and stores a pointer to it in C<S1>.
-
-=head4 Length of a string
-
-Z<CHP-9-SECT-2.4.3>
-
-X<PASM (Parrot assembly language);string operations;length>
-The C<length>X<length opcode (PASM)> opcode returns the length of a
-string in characters. This won't be the same as the length in bytes
-for multibyte encoded strings:
-
-=begin PASM
-
-  set S0, "abcd"
-  length I0, S0                # the length is 4
-  print I0
-  print "\n"
-  end
-
-=end PASM
-
-C<length> doesn't have an equivalent for PMC strings.
-
-=head4 Substrings
-
-Z<CHP-9-SECT-2.4.4>
-
-X<PASM (Parrot assembly language);string operations;substrings>
-The simplest version of the C<substr>X<substr opcode (PASM)> opcode
-takes four arguments: a destination register, a string, an offset
-position, and a length. It returns a substring of the original string,
-starting from the offset position (0 is the first character) and
-spanning the length:
-
-=begin PASM
-
-  substr S0, "abcde", 1, 2        # S0 is "bc"
-
-=end PASM
-
-This example extracts a two-character string from "abcde" at a
-one-character offset from the beginning of the string (starting with
-the second character). It generates a new string, "bc", in the
-destination register C<S0>.
-
-When the offset position is negative, it counts backward from the end
-of the string. So an offset of -1 starts at the last character of the
-string.
-
-C<substr> also has a five-argument form, where the fifth argument is a
-string to replace the substring. This modifies the second argument and
-returns the removed substring in the destination register.
-
-=begin PASM
-
-  set S1, "abcde"
-  substr S0, S1, 1, 2, "XYZ"
-  print S0                        # prints "bc"
-  print "\n"
-  print S1                        # prints "aXYZde"
-  print "\n"
-  end
-
-=end PASM
-
-This replaces the substring "bc" in C<S1> with the string "XYZ", and
-returns "bc" in C<S0>.
-
-When the offset position in a replacing C<substr> is one character
-beyond the original string length, C<substr> appends the replacement
-string just like the C<concat> opcode. If the replacement string is an
-empty string, the characters are just removed from the original
-string.
-
-When you don't need to capture the replaced string, there's an
-optimized version of C<substr> that just does a replace without
-returning the removed substring.
-
-=begin PASM
-
-  set S1, "abcde"
-  substr S1, 1, 2, "XYZ"
-  print S1                        # prints "aXYZde"
-  print "\n"
-  end
-
-=end PASM
-
-The PMC versions of C<substr> are not yet implemented.
-
-=head4 Chopping strings
-
-Z<CHP-9-SECT-2.4.5>
-
-X<PASM (Parrot assembly language);string operations;chopping strings>
-The C<chopn>X<chopn opcode (PASM)> opcode removes characters from the
-end of a string. It takes two arguments: the string to modify and the
-count of characters to remove.
-
-=begin PASM
-
-  set S0, "abcde"
-  chopn S0, 2
-  print S0         # prints "abc"
-  print "\n"
-  end
-
-=end PASM
-
-This example removes two characters from the end of C<S0>. If the
-count is negative, that many characters are kept in the string:
-
-=begin PASM
-
-  set S0, "abcde"
-  chopn S0, -2
-  print S0         # prints "ab"
-  print "\n"
-  end
-
-=end PASM
-
-This keeps the first two characters in C<S0> and removes the rest.
-C<chopn> also has a three-argument version that stores the chopped
-string in a separate destination register, leaving the original string
-untouched:
-
-=begin PASM
-
-  set S0, "abcde"
-  chopn S1, S0, 1
-  print S1         # prints "abcd"
-  print "\n"
-  end
-
-=end PASM
-
-=head4 Copying and Cloning
-
-Z<CHP-9-SECT-2.4.6>
-
-X<PASM (Parrot assembly language);string operations;copying> The C<clone>
-X<clone opcode (PASM)> opcode makes a deep copy of a string or PMC. Earlier
-in this chapter we saw that PMC and String values used with the C<set> opcode
-didn't create a copy of the underlying data structure, it only created
-a copy of the reference to that structure. With strings, this doesn't cause
-a problem because strings use Copy On Write (COW) semantics to automatically
-create a copy of the string when one reference is modified. However, as we
-saw, PMCs don't have this same behavior and so making a change to one PMC
-reference would modify the data that all the other references to that same
-PMC pointed to.
-
-Instead of just copying the pointer like C<set> would do, we can use the
-C<clone> opcode to create a I<deep copy> of the PMC, not just a I<shallow
-copy> of the reference.
-
-=begin PASM
-
-  new P0, "String"
-  set P0, "Ford"
-  clone P1, P0
-  set P0, "Zaphod"
-  print P0        # prints "Zaphod"
-  print P1        # prints "Ford"
-  end
-
-=end PASM
-
-This example creates an identical, independent clone of the PMC in
-C<P0> and puts a pointer to it in C<P1>. Later changes to C<P0> have
-no effect on the PMC referenced in C<P1>.
-
-With simple strings, the copes created by C<clone> are COW exactly the same
-as the copy created by C<set>, so there is no difference between these two
-opcodes for strings. By convention, C<set> is used with strings more often
-then C<clone>, but there is no rule about this.
-
-=head4 Converting characters
-
-Z<CHP-9-SECT-2.4.7>
-
-X<PASM (Parrot assembly language);string operations;converting strings>
-The C<chr>X<chr opcode (PASM)> opcode takes an integer value and returns the
-corresponding character in the ASCII character set as a one-character string,
-while the C<ord>X<ord opcode (PASM)> opcode takes a single character string
-and returns the integer value of the character at the first position in the
-string. Notice that the integer value of the character will differ depending
-on the current encoding of the string:
-
-=begin PASM
-
-  chr S0, 65                # S0 is "A"
-  ord I0, S0                # I0 is 65, if S0 is ASCII or UTF-8
-
-=end PASM
-
-C<ord> has a three-argument variant that takes a character offset to select
-a single character from a multicharacter string. The offset must be within
-the length of the string:
-
-=begin PASM
-
-  ord I0, "ABC", 2        # I0 is 67
-
-=end PASM
-
-A negative offset counts backward from the end of the string, so -1 is
-the last character.
-
-=begin PASM
-
-  ord I0, "ABC", -1        # I0 is 67
-
-=end PASM
-
-=head4 Formatting strings
-
-Z<CHP-9-SECT-2.4.8>
-
-X<PASM (Parrot assembly language);string operations;formatting strings>
-The C<sprintf>X<sprintf opcode (PASM)> opcode generates a formatted string
-from a series of values. It takes three arguments: the destination register,
-a string specifying the format, and an ordered aggregate PMC (like an
-C<Array> PMC) containing the values to be formatted. The format string and
-the destination register can be either strings or PMCs:
-
-=begin PASM
-
-  sprintf S0, S1, P2
-  sprintf P0, P1, P2
-
-=end PASM
-
-The format string is similar to the one for C's C<sprintf> function,
-but with some extensions for Parrot data types. Each format field in
-the string starts with a C<%>
-X<% (percent sign);% format strings for sprintf opcode (PASM)> and
-ends with a character specifying the output format. The output format
-characters are listed in Table 9-1.
-
-=begin table picture Format characters
-
-Z<CHP-9-TABLE-1>
-
-=headrow
-
-=row
-
-=cell Format
-
-=cell Meaning
-
-=bodyrows
-
-=row
-
-=cell C<%c>
-
-=cell A single character.
-
-=row
-
-=cell C<%d>
-
-=cell A decimal integer.
-
-=row
-
-=cell C<%i>
-
-=cell A decimal integer.
-
-=row
-
-=cell C<%u>
-
-=cell An unsigned integer.
-
-=row
-
-=cell C<%o>
-
-=cell An octal integer.
-
-=row
-
-=cell C<%x>
-
-=cell A hex integer, preceded by 0x when # is specified.
-
-=row
-
-=cell C<%X>
-
-=cell A hex integer with a capital X (when # is specified).
-
-=row
-
-=cell C<%b>
-
-=cell A binary integer, preceded by 0b when # is specified.
-
-=row
-
-=cell C<%B>
-
-=cell A binary integer with a capital B (when # is specified).
-
-=row
 
-=cell C<%p>
 
-=cell A pointer address in hex.
 
-=row
-
-=cell C<%f>
-
-=cell A floating-point number.
-
-=row
-
-=cell C<%e>
-
-=cell A floating-point number in scientific notation (displayed with a
-lowercase "e").
-
-=row
-
-=cell C<%E>
-
-=cell The same as C<%e>, but displayed with an uppercase E.
-
-=row
-
-=cell C<%g>
-
-=cell The same as either C<%e> or C<%f>, whichever fits best.
-
-=row
-
-=cell C<%G>
-
-=cell The same as C<%g>, but displayed with an uppercase E.
-
-=row
-
-=cell C<%s>
-
-=cell A string.
-
-=end table
-
-Each format field can be specified with several options: R<flags>,
-R<width>, R<precision>, and R<size>. The format flags are listed in
-Table 9-2.
-
-=begin table picture Format flags
-
-Z<CHP-9-TABLE-2>
-
-=headrow
-
-=row
-
-=cell Flag
-
-=cell Meaning
-
-=bodyrows
-
-=row
-
-=cell 0
-
-=cell Pad with zeros.
-
-=row
-
-=cell E<lt>spaceE<gt>
-
-=cell Pad with spaces.
-
-=row
-
-=cell C<+>
-
-=cell Prefix numbers with a sign.
-
-=row
-
-=cell C<->
-
-=cell Align left.
-
-=row
-
-=cell C<#>
-
-=cell Prefix a leading 0 for octal, 0x for hex, or force a decimal point.
-
-=end table
-
-The R<width> is a number defining the minimum width of the output from
-a field. The R<precision> is the maximum width for strings or
-integers, and the number of decimal places for floating-point fields.
-If either R<width> or R<precision> is an asterisk (C<*>), it takes its
-value from the next argument in the PMC.
-
-The R<size> modifier defines the type of the argument the field takes.
-The flags are listed in Table 9-3.
-
-=begin table picture Size flags
-
-Z<CHP-9-TABLE-3>
-
-=headrow
-
-=row
-
-=cell Character
-
-=cell Meaning
-
-=bodyrows
-
-=row
-
-=cell C<h>
-
-=cell short integer or single-precision float
-
-=row
-
-=cell C<l>
-
-=cell long
-
-=row
-
-=cell C<H>
-
-=cell huge value (long long or long double)
-
-=row
-
-=cell C<v>
-
-=cell Parrot INTVAL or FLOATVAL
-
-=row
-
-=cell C<O>
-
-=cell opcode_t pointer
-
-=row
-
-=cell C<P>
-
-=cell C<PMC>
-
-=row
-
-=cell C<S>
-
-=cell String
-
-=end table
-
-The values in the aggregate PMC must have a type compatible with the
-specified R<size>.
-
-Here's a short illustration of string formats:
-
-=begin PASM
-
-  new P2, "Array"
-  new P0, "Int"
-  set P0, 42
-  push P2, P0
-  new P1, "Num"
-  set P1, 10
-  push P2, P1
-  sprintf S0, "int %#Px num %+2.3Pf\n", P2
-  print S0     # prints "int 0x2a num +10.000"
-  print "\n"
-  end
-
-=end PASM
-
-The first eight lines create a C<Array> with two elements: a
-C<Int> and a C<Num>. The format string of the C<sprintf> has
-two format fields. The first, C<%#Px>, takes a PMC argument from the
-aggregate (C<P>) and formats it as a hexadecimal integer (C<x>), with
-a leading 0x (C<#>). The second format field, C<%+2.3Pf>, takes a PMC
-argument (C<P>) and formats it as a floating-point number (C<f>), with
-a minimum of two whole digits and a maximum of three decimal places
-(C<2.3>) and a leading sign (C<+>).
-
-The test files F<t/op/string.t> and F<t/src/sprintf.t> have many more
-examples of format strings.
-
-=head4 Testing for substrings
-
-Z<CHP-9-SECT-2.4.9>
-
-X<PASM (Parrot assembly language);string operations;testing for substrings>
-The C<index>X<index opcode (PASM)> opcode searches for a substring
-within a string. If it finds the substring, it returns the position
-where the substring was found as a character offset from the beginning
-of the string. If it fails to find the substring, it returns -1:
-
-=begin PASM
-
-  index I0, "Beeblebrox", "eb"
-  print I0                       # prints 2
-  print "\n"
-  index I0, "Beeblebrox", "Ford"
-  print I0                       # prints -1
-  print "\n"
-  end
-
-=end PASM
-
-C<index> also has a four-argument version, where the fourth argument
-defines an offset position for starting the search:
-
-=begin PASM
-
-  index I0, "Beeblebrox", "eb", 3
-  print I0                         # prints 5
-  print "\n"
-  end
-
-=end PASM
-
-This finds the second "eb" in "Beeblebrox" instead of the first,
-because the search skips the first three characters in the
-string.
-
-=head4 Joining strings
-
-The C<join> opcode joins the elements of an array PMC into a single
-string. The second argument separates the individual elements of the
-PMC in the final string result.
-
-=begin PASM
-
-  new P0, "Array"
-  push P0, "hi"
-  push P0, 0
-  push P0, 1
-  push P0, 0
-  push P0, "parrot"
-  join S0, "__", P0
-  print S0              # prints "hi__0__1__0__parrot"
-  end
-
-=end PASM
-
-This example builds a C<Array> in C<P0> with the values C<"hi">,
-C<0>, C<1>, C<0>, and C<"parrot">. It then joins those values (separated
-by the string C<"__">) into a single string, and stores it in C<S0>.
-
-=head4 Splitting strings
-
-Splitting a string yields a new array containing the resulting
-substrings of the original string.
-
-=begin PASM
-
-  split P0, "", "abc"
-  set P1, P0[0]
-  print P1              # 'a'
-  set P1, P0[2]
-  print P1              # 'c'
-  end
-
-=end PASM
-
-This example splits the string "abc" into individual characters and
-stores them in an array in C<P0>. It then prints out the first and
-third elements of the array. For now, the split pattern (the second
-argument to the opcode) is ignored except for a test to make sure that
-its length is zero.
-
-=head3 Logical and Bitwise Operations
-
-Z<CHP-9-SECT-2.6>
-
-X<PASM (Parrot assembly language);bitwise operations>
-X<PASM (Parrot assembly language);logical operations>
-The X<logical opcodes> logical opcodes evaluate the truth of their
-arguments. They're often used to make decisions on control flow.
-Logical operations are implemented for integers and PMCs. Numeric
-values are false if they're 0, and true otherwise. Strings are false
-if they're the empty string or a single character "0", and true
-otherwise. PMCs are true when their
-C<get_bool>X<get_bool vtable method (PASM)> vtable method returns a
-nonzero value.
-
-The C<and>X<and opcode (PASM)> opcode returns the second argument if
-it's false and the third argument otherwise:
-
-=begin PASM
-
-  and I0, 0, 1  # returns 0
-  and I0, 1, 2  # returns 2
-
-=end PASM
-
-The C<or>X<or opcode (PASM)> opcode returns the second argument if
-it's true and the third argument otherwise:
-
-=begin PASM
-
-  or I0, 1, 0  # returns 1
-  or I0, 0, 2  # returns 2
-
-  or P0, P1, P2
-
-=end PASM
-
-Both C<and> and C<or> are short-circuiting. If they can determine what
-value to return from the second argument, they'll never evaluate the
-third.  This is significant only for PMCs, as they might have side
-effects on evaluation.
-
-The C<xor>X<xor opcode (PASM)> opcode returns the second argument if
-it is the only true value, returns the third argument if it is the
-only true value, and returns false if both values are true or both are
-false:
-
-=begin PASM
-
-  xor I0, 1, 0  # returns 1
-  xor I0, 0, 1  # returns 1
-  xor I0, 1, 1  # returns 0
-  xor I0, 0, 0  # returns 0
-
-=end PASM
-
-The C<not>X<not opcode (PASM)> opcode returns a true value when the
-second argument is false, and a false value if the second argument is
-true:
-
-=begin PASM
-
-  not I0, I1
-  not P0, P1
-
-=end PASM
-
-The X<bitwise;opcodes (PASM)> bitwise opcodes operate on their values
-a single bit at a time. C<band>X<band opcode (PASM)>,
-C<bor>X<bor opcode (PASM)>, and C<bxor>X<bxor opcode (PASM)> return a
-value that is the logical AND, OR, or XOR of each bit in the source
-arguments. They each take a destination register and two source
-registers. They also have two-argument forms where the destination is
-also a source.  C<bnot>X<bnot opcode (PASM)> is the logical NOT of
-each bit in a single source argument.
-
-=begin PASM
-
-  bnot I0, I1
-  band P0, P1
-  bor I0, I1, I2
-  bxor P0, P1, I2
-
-=end PASM
-
-X<bitwise;string opcodes>
-The bitwise opcodes also have string variants for AND, OR, and XOR:
-C<bors>X<bors opcode (PASM)>, C<bands>X<bands opcode (PASM)>, and
-C<bxors>X<bxors opcode (PASM)>. These take string register or PMC
-string source arguments and perform the logical operation on each byte
-of the strings to produce the final string.
-
-=begin PASM
-
-  bors S0, S1
-  bands P0, P1
-  bors S0, S1, S2
-  bxors P0, P1, S2
-
-=end PASM
-
-The bitwise string opcodes only have meaningful results when they're
-used with simple ASCII strings because the bitwise operation is done
-per byte.
-
-The logical and arithmetic shift operations shift their values by a
-specified number of bits:
-
-=begin PASM
-
-  shl  I0, I1, I2        # shift I1 left by count I2 giving I0
-  shr  I0, I1, I2        # arithmetic shift right
-  lsr  P0, P1, P2        # logical shift right
-
-=end PASM
-
-=head2 Working with PMCs
-
-Z<CHP-9-SECT-3>
-
-In most of the examples we've shown so far, X<PMCs (Polymorphic
-Containers);working with> PMCs just duplicate the functionality of integers,
-numbers, and strings. They wouldn't be terribly useful if that's all they did,
-though. PMCs offer several advanced features that we will look at in the next
-few sections.
-
-=head3 Aggregates
-
-Z<CHP-9-SECT-3.1>
-
-PMCs can define complex types that hold multiple values. These are
-commonly called "X<PMCs (Polymorphic Containers);aggregate>
-X<aggregate PMCs> aggregates." The most important feature added for
-aggregates is keyed access. Elements within an aggregate PMC can be
-stored and retrieved by a numeric or string key. PASM also offers a
-full set of operations for manipulating aggregate data types.
-
-Two of the most basic aggregate types are arrays and hashes. The primary
-difference between these two is that arrays are indexed using integer keys,
-and hashes are indexed with string keys. The term "hash" in this context is
-derived from the data type in Perl 5 of the same name. Other programming
-languages might refer to the same concept using different terms such as
-"dictionary" or "hash table" or "associative array".
-
-Arrays and hashes are not the only types of aggregates available, although
-they are the most simple demonstrations of using integer and strings as
-keys in an aggregate, respectively.
-
-=head4 Arrays
-
-Z<CHP-9-SECT-3.1.1>
-
-X<PMCs (Polymorphic Containers);arrays>
-The C<Array>X<Array PMC> PMC is an ordered aggregate with zero-based integer
-keys. The syntax for X<keyed access to PMCs> keyed access to a PMC puts the
-key in square brackets after the register name:
-
-=begin PASM
-
-  new P0, "Array"     # obtain a new array object
-  set P0, 2           # set its length
-  set P0[0], 10       # set first element to 10
-  set P0[1], I31      # set second element to I31
-  set I0, P0[0]       # get the first element
-  set I1, P0          # get array length
-
-=end PASM
-
-A key on the destination register of a C<set> operation sets a value
-for that key in the aggregate. A key on the source register of a
-C<set> returns the value for that key. If you set C<P0> without a key,
-you set the length of the array, not one of its values.N<C<Array>
-is an autoextending array, so you never need to set its length. Other
-array types may require the length to be set explicitly.> And if you
-assign the C<Array> to an integer, you get the length of the
-array.
-
-We mention "other array types" above, not as a vague suggestion that there may
-be other types of arrays eventually, but as an indication that we actually
-have several types of array PMCs in Parrot's core. Parrot comes with
-C<FixedPMCArray>, C<ResizablePMCArray>, C<FixedIntegerArray>,
-C<ResizableIntegerArray>, C<FixedFloatArray>, C<ResizableFloatArray>,
-C<FixedStringArray>, C<ResizableStringArray>, C<FixedBooleanArray>,
-and C<ResizableBooleanArray> types. These various types of arrays use
-various packing methods to create higher memory efficiency for their contents
-then using a single generic array type would be able to. The trade-off for
-higher memory efficiency is that these array PMCs can only hold a single type
-of data.
-
-The array PMC types that start with "Fixed" have a fixed size and do not
-automatically extend themselves if you attempt to add data to a higher index
-then the array contains. The "Resizable" variants will automatically extend
-themselves as more data are added, but the cost is in algorithmic complexity
-of checking array bounds and reallocating array memory.
-
-To retrieve the number of items currently in an array, you can use the
-C<elements> opcode.
-
-=begin PASM
-
-  set P0, 100         # allocate store for 100 elements
-  set I0, P0          # obtain current allocation size
-  elements I0, P0     # get element count
-
-=end PASM
-
-Some other useful instructions for working with arrays are C<push>,
-C<pop>, C<shift>, and C<unshift> (you'll find them in
-"PASM Opcodes" in Chapter 11).
-
-=head4 Hashes
-
-Z<CHP-9-SECT-3.1.2>
-
-X<PMCs (Polymorphic Containers);hashes>
-The C<Hash>X<Hash PMC> PMC is an unordered aggregate which uses string keys
-to identify elements within it.
-
-=begin PASM
-
-  new P1, "Hash"      # generate a new hash object
-  set P1["key"], 10   # set key and value
-  set I0, P1["key"]   # obtain value for key
-  set I1, P1          # number of entries in hash
-
-=end PASM
-
-The C<exists>X<exists opcode (PASM)> opcode tests whether a keyed
-value exists in an aggregate. It returns 1 if it finds the key in the
-aggregate, and returns 0 if it doesn't. It doesn't care if the value
-itself is true or false, only that the key has been set:
-
-=begin PASM
-
-  new P0, "Hash"
-  set P0["key"], 0
-  exists I0, P0["key"] # does a value exist at "key"
-  print I0             # prints 1
-  print "\n"
-  end
-
-=end PASM
-
-The C<delete>X<delete opcode (PASM)> opcode is also useful for working
-with hashes: it removes a key/value pair.
-
-=head4 Iterators
-
-Z<CHP-9-SECT-3.1.3>
-
-Iterators extract values from an aggregate PMC one at a time and without
-extracting duplicates. Iterators are most useful in loops where an action
-needs to be performed on every element in an aggregate. You create an
-iterator by creating a new C<Iterator> PMC, and passing the aggregate PMC
-to C<new> as an additional parameter:
-
-=begin PASM
-
-  new P1, "Iterator", P2
-
-=end PASM
-
-Alternatively, you can use the C<iter> opcode to do the same thing:
-
-=begin PASM
-
-  iter P1, P2     # Same!
-
-=end PASM
-
-The include file F<iterator.pasm> defines some constants for working
-with iterators. The C<.ITERATE_FROM_START> and C<.ITERATE_FROM_END>
-constants are used to select whether an array iterator starts from the
-beginning or end of the array. Since Hash PMCs are unordered, these two
-constants do not have any affect on Hash iterators.
-
-A value can be extracted from the iterator using the C<shift> opcode.
-Evaluating the iterator PMC as a boolean returns whether the iterator has
-reached the end of the aggregate or not.
-
-=begin PASM
-
-  .include "iterator.pasm"
-      new P2, "Array"
-      push P2, "a"
-      push P2, "b"
-      push P2, "c"
-      new P1, "Iterator", P2
-      set P1, .ITERATE_FROM_START
-
-  iter_loop:
-      unless P1, iter_end
-      shift P5, P1
-      print P5                        # prints "a", "b", "c"
-      branch iter_loop
-  iter_end:
-      end
-
-=end PASM
-
-Hash iterators work similarly to array iterators, but they extract keys
-only. With the key, you can find it's value from the original hash PMC.
-With hashes it's only meaningful to iterate in one direction since they
-don't define any order for their keys.
-
-=begin PASM
-
-  .include "iterator.pasm"
-      new P2, "Hash"
-      set P2["a"], 10
-      set P2["b"], 20
-      set P2["c"], 30
-      new P1, "Iterator", P2
-      set P1, .ITERATE_FROM_START_KEYS
-
-  iter_loop:
-      unless P1, iter_end
-      shift S5, P1                    # one of the keys "a", "b", "c"
-      set I9, P2[S5]
-      print I9                        # prints e.g. 20, 10, 30
-      branch iter_loop
-  iter_end:
-      end
-
-=end PASM
-
-=head4 Data structures
-
-Z<CHP-9-SECT-3.1.4>
-
-X<PMCs (Polymorphic Containers);data structures>
-Arrays and hashes can hold any data type, including other aggregates.
-Accessing elements deep within nested data structures is a common
-operation, so PASM provides a way to do it in a single instruction.
-Complex keys specify a series of nested data structures, with each
-individual key separated by a semicolon:
-
-=begin PASM
-
-  new P0, "Hash"
-  new P1, "Array"
-  set P1[2], 42
-  set P0["answer"], P1
-  set I1, 2
-  set I0, P0["answer";I1]        # $i = %hash{"answer"}[2]
-  print I0
-  print "\n"
-  end
-
-=end PASM
-
-This example builds up a data structure of a hash containing an array.
-The complex key C<P0["answer";I1]> retrieves an element of the array
-within the hash. You can also set a value using a complex key:
-
-=begin PASM
-
-  set P0["answer";0], 5   # %hash{"answer"}[0] = 5
-
-=end PASM
-
-The individual keys are integers or strings, or registers with integer
-or string values.
-
-=head3 PMC Assignment
-
-Z<CHP-9-SECT-3.2>
-
-We mentioned before that C<set> on two X<PMCs (Polymorphic
-Containers);assignment> PMCs simply aliases them both to the same object,
-and that C<clone> creates a complete duplicate object. But if you just
-want to assign the value of one PMC to another PMC, you need the
-C<assign>X<assign opcode (PASM)> opcode:
-
-=begin PASM
-
-  new P0, "Int"
-  new P1, "Int"
-  set P0, 42
-  set P2, P0
-  assign P1, P0     # note: P1 has to exist already
-  inc P0
-  print P0          # prints 43
-  print "\n"
-  print P1          # prints 42
-  print "\n"
-  print P2          # prints 43
-  print "\n"
-  end
-
-=end PASM
-
-This example creates two C<Int> PMCs: C<P0> and C<P1>. It gives
-C<P0> a value of 42. It then uses C<set> to give the same value to
-C<P2>, but uses C<assign> to give the value to C<P1>. When C<P0> is
-incremented, C<P2> also changes, but C<P1> doesn't. The destination
-register for C<assign> must have an existing object of the right type
-in it, since C<assign> doesn't create a new object (as with C<clone>)
-or reuse the source object (as with C<set>).
-
-=head3 Properties
-
-Z<CHP-9-SECT-3.3>
-
-X<PMCs (Polymorphic Containers);properties>
-PMCs can have additional values attached to them as "properties" of
-the PMC. What these properties do is entirely up to the language being
-implemented. Most usually properties are used to hold extra metadata about
-the PMC that is used by the high-level language (HLL).
-
-The C<setprop>X<setprop opcode (PASM)> opcode sets the value of a
-named property on a PMC. It takes three arguments: the PMC to be set
-with a property, the name of the property, and a PMC containing the
-value of the property. The C<getprop>X<getprop opcode (PASM)> opcode
-returns the value of a property. It also takes three arguments: the
-PMC to store the property's value, the name of the property, and the
-PMC from which the property value is to be retrieved. Internally a PMCs
-properties are stored in a Hash structure, where the name of the property
-is stored in a special properties Hash.
-
-=begin PASM
-
-  new P0, "String"
-  set P0, "Zaphod"
-  new P1, "Int"
-  set P1, 1
-  setprop P0, "constant", P1        # set a property on P0
-  getprop P3, "constant", P0        # retrieve a property on P0
-  print P3                          # prints 1
-  print "\n"
-  end
-
-=end PASM
-
-This example creates a C<String> object in C<P0>, and a C<Int>
-object with the value 1 in C<P1>. C<setprop> sets a property named
-"constant" on the object in C<P0> and gives the property the value in
-C<P1>.N<The "constant" property is ignored by PASM, but may be significant
-to the HLL that set it.> C<getprop> retrieves the value of the property
-"constant" on C<P0> and stores it in C<P3>.
-
-Properties are kept in a separate hash for each PMC. Property values
-are always PMCs, but only references to the actual PMCs. Trying to
-fetch the value of a property that doesn't exist returns a
-C<Undef>.
-
-C<delprop>X<delprop opcode (PASM)> deletes a property from a PMC.
-
-=begin PASM
-
-  delprop P1, "constant"  # delete property
-
-=end PASM
-
-You can also return a complete hash of all properties on a PMC with
-C<prophash>X<prophash opcode (PASM)>.
-
-=begin PASM
-
-  prophash P0, P1         # set P0 to the property hash of P1
-
-=end PASM
-
-=head2 Flow Control
-
-Z<CHP-9-SECT-4>
-
-X<PASM (Parrot assembly language);flow control>
-Although it has many advanced features, at heart PASM is an assembly
-language. All flow control in PASM--as in most assembly languages--is
-done with branches and jumps.
-
-Branch instructions transfer control to a relative offset from the
-current instruction. The rightmost argument to every branch opcode is
-a label, which the assembler converts to the integer value of the
-offset. You can also branch on a literal integer value, but there's
-rarely any need to do so. The simplest branch instruction is
-C<branch>:
-
-=begin PASM
-
-    branch L1                # branch 4
-    print "skipped\n"
-  L1:
-    print "after branch\n"
-    end
-
-=end PASM
-
-This example unconditionally branches to the location of the label
-C<L1>, skipping over the first C<print> statement.
-
-Jump instructions transfer control to an absolute address. The C<jump>
-opcode doesn't calculate an address from a label, so it's used
-together with C<set_addr>:
-
-=begin PASM
-
-    set_addr I0, L1
-    jump I0
-    print "skipped\n"
-    end
-  L1:
-    print "after jump\n"
-    end
-
-=end PASM
-
-The C<set_addr>X<set_addr opcode (PASM)> opcode takes a label or an
-integer offset and returns an absolute address.
-
-You've probably noticed the C<end>X<end opcode (PASM)> opcode as the
-last statement in many examples above. This terminates the execution
-of the current run loop. Terminating the main bytecode segment (the
-first run loop) stops the interpreter. Without the C<end> statement,
-execution just falls off the end of the bytecode segment, with a good
-chance of crashing the interpreter.
-
-=head3 Conditional Branches
-
-Z<CHP-9-SECT-4.1>
-
-X<PASM (Parrot assembly language);conditional branches>
-X<conditional branches in PASM>
-Unconditional jumps and branches aren't really enough for flow
-control. What you need to implement the control structures of
-high-level languages is the ability to select different actions based
-on a set of conditions. PASM has opcodes that conditionally branch
-based on the truth of a single value or the comparison of two values.
-The following example has C<if>X<if (conditional);opcode (PASM)> and
-C<unless>X<unless (conditional);opcode (PASM)> conditional branches:
-
-=begin PASM
-
-    set I0, 0
-    if I0, TRUE
-    unless I0, FALSE
-    print "skipped\n"
-    end
-  TRUE:
-    print "shouldn't happen\n"
-    end
-  FALSE:
-    print "the value was false\n"
-    end
-
-=end PASM
-
-C<if> branches if its first argument is a true value, and C<unless>
-branches if its first argument is a false value. In this case, the
-C<if> doesn't branch because C<I0> is false, but the C<unless> does
-branch.
-The comparison branching opcodes compare two values and branch if the
-stated relation holds true. These are
-C<eq>X<eq (equal);opcode (PASM)> (branch when equal),
-C<ne>X<ne (not equal);opcode (PASM)> (when not equal),
-C<lt>X<lt (less than);opcode (PASM)> (when less than),
-C<gt>X<gt (greater than);opcode (PASM)> (when greater than),
-C<le>X<le (less than or equal);opcode (PASM)> (when less than or
-equal), and C<ge>X<ge (greater than or equal);opcode (PASM)> (when
-greater than or equal). The two compared arguments must be the same
-register type:
-
-=begin PASM
-
-    set I0, 4
-    set I1, 4
-    eq I0, I1, EQUAL
-    print "skipped\n"
-    end
-  EQUAL:
-    print "the two values are equal\n"
-    end
-
-=end PASM
-
-This compares two integers, C<I0> and C<I1>, and branches if they're
-equal. Strings of different character sets or encodings are converted
-to Unicode before they're compared. PMCs have a C<cmp> vtable method.
-This gets called on the left argument to perform the comparison of the
-two objects.
-
-The comparison opcodes don't specify if a numeric or string comparison
-is intended. The type of the register selects for integers, floats,
-and strings. With PMCs, the vtable method C<cmp> or C<is_equal> of the
-first argument is responsible for comparing the PMC meaningfully with
-the other operand. If you need to force a numeric or string comparison
-on two PMCs, use the alternate comparison opcodes that end in the
-C<_num> and C<_str> suffixes.
-
-=begin PASM
-
-  eq_str P0, P1, label     # always a string compare
-  gt_num P0, P1, label     # always numerically
-
-=end PASM
-
-Finally, the C<eq_addr> opcode branches if two PMCs or strings are
-actually the same object (have the same address):
-
-=begin PASM
-
-  eq_addr P0, P1, same_pmcs_found
-
-=end PASM
-
-=head3 Iteration
-
-Z<CHP-9-SECT-4.2>
-
-X<iteration;in PASM>
-X<PASM (Parrot assembly language);iteration>
-PASM doesn't define high-level loop constructs. These are built up
-from a combination of conditional and unconditional branches. A
-I<do-while>X<do-while style loop;(PASM)> style loop can be constructed
-with a single conditional branch:
-
-=begin PASM
-
-    set I0, 0
-    set I1, 10
-  REDO:
-    inc I0
-    print I0
-    print "\n"
-    lt I0, I1, REDO
-    end
-
-=end PASM
-
-This example prints out the numbers 1 to 10. The first time through,
-it executes all statements up to the C<lt> statement.  If the
-condition evaluates as true (C<I0> is less than C<I1>) it branches to
-the C<REDO> label and runs the three statements in the loop body
-again. The loop ends when the condition evaluates as false.
-
-Conditional and unconditional branches can build up quite complex
-looping constructs, as follows:
-
-=begin PASM
-
-    # loop ($i=1; $i<=10; $i++) {
-    #    print "$i\n";
-    # }
-  loop_init:
-    set I0, 1
-    branch loop_test
-  loop_body:
-    print I0
-    print "\n"
-    branch loop_continue
-  loop_test:
-    le I0, 10, loop_body
-    branch out
-  loop_continue:
-    inc I0
-    branch loop_test
-  out:
-    end
-
-=end PASM
-
-X<loops;PASM>
-X<PASM (Parrot assembly language);loops>
-This example emulates a X<counter-controlled loop> counter-controlled
-loop like Perl 6's C<loop> keyword or C's C<for>. The first time
-through the loop it sets the initial value of the counter in
-C<loop_init>, tests that the loop condition is met in C<loop_test>,
-and then executes the body of the loop in C<loop_body>. If the test
-fails on the first iteration, the loop body will never execute. The
-end of C<loop_body> branches to C<loop_continue>, which increments the
-counter and then goes to C<loop_test> again. The loop ends when the
-condition fails, and it branches to C<out>. The example is more
-complex than it needs to be just to count to 10, but it nicely shows
-the major components of a
-loop.
-
-=head2 Lexicals and Globals
-
-Z<CHP-9-SECT-6>
-
-So far, we've been treating Parrot registers like the variables of a
-high-level language. This is fine, as far as it goes, but it isn't the
-full picture. The dynamic nature and introspective features of
-languages like Perl make it desirable to manipulate variables by name,
-instead of just by register or stack location. These languages also
-have global variables, which are visible throughout the entire
-program. Storing a global variable in a register would either tie up
-that register for the lifetime of the program or require some unwieldy way
-to shuffle the data into and out of registers.
-
-Parrot provides structures for storing both global and lexically
-scoped named variables. Lexical and global variables must be PMC
-values. PASM provides instructions for storing and retrieving
-variables from these structures so the PASM opcodes can operate on
-their values.
-
-=head3 Globals
-
-Z<CHP-9-SECT-6.1>
-
-X<PASM (Parrot assembly language);global variables>
-Global variables are stored in a C<Hash>, so every variable name
-must be unique.  PASM has two opcodes for globals, C<set_global> and
-C<get_global>:
-
-=begin PASM
-
-  new P10, "Int"
-  set P10, 42
-  set_global "$foo", P10
-  # ...
-  get_global P0, "$foo"
-  print P0                        # prints 42
-  end
-
-=end PASM
-
-The first two statements create a C<Int> in the PMC register
-C<P10> and give it the value 42. In the third statement,
-C<set_global> stores that PMC as the named global variable C<$foo>.
-At some later point in the program, C<get_global> retrieves the PMC
-from the global variable by name, and stores it in C<P0> so it can be
-printed.
-
-The C<set_global> opcode only stores a reference to the object. If
-we add an increment statement:
-
-=begin PASM
-
-  inc P10
-
-=end PASM
-
-after the C<set_global> it increments the stored global, printing 43.
-If that's not what you want, you can C<clone> the PMC before you store
-it. Leaving the global variable as an alias does have advantages,
-though. If you retrieve a stored global into a register and modify it
-as follows:
-
-=begin PASM
-
-  get_global P0, "varname"
-  inc P0
-
-=end PASM
-
-the value of the stored global is directly modified, so you don't need
-to call C<set_global> again.
-
-The two-argument forms of C<set_global> and C<get_global> store or
-retrieve globals from the outermost namespace (what Perl users will
-know as the "main" namespace). A simple flat global namespace isn't
-enough for most languages, so Parrot also needs to support
-hierarchical namespaces for separating packages (classes and modules
-in Perl 6). Use C<set_rootglobal> and
-C<get_root_global> add an argument to select a nested namespace:
-
-=begin PASM
-
-  set_root_global ["Foo"], "var", P0 # store P0 as var in the Foo namespace
-  get_root_global P1, ["Foo"], "var"  # get Foo::var
-
-=end PASM
-
-Eventually the global opcodes will have variants that take a PMC to
-specify the namespace, but the design and implementation of these
-aren't finished yet.
-
-=head3 Lexicals
-
-Z<CHP-9-SECT-6.2>
-
-X<PASM (Parrot assembly language);lexical variables>
-Lexical variables are stored in a lexical scratchpad. There's one pad
-for each lexical scope. Every pad has both a hash and an array, so
-elements can be stored either by name or by numeric index.
-
-=head4 Basic instructions
-
-Z<CHP-9-SECT-6.2.1>
-
-To store a lexical variable in the current scope pad, use C<store_lex>.
-Likewise, use C<find_lex> to retrieve a variable from the current pad.
-
-=begin PASM
-
-  new P0, "Int"            # create a variable
-  set P0, 10               # assign value to it
-  store_lex "foo", P0      # store the var with the variable name "foo"
-  # ...
-  find_lex P1, "foo"       # get the var "foo" into P1
-  print P1
-  print "\n"               # prints 10
-  end
-
-=end PASM
-
-=head2 Subroutines
-
-Z<CHP-9-SECT-7>
-
-X<subroutines>
-Subroutines and methods are the basic building blocks of larger
-programs. At the heart of every subroutine call are two fundamental
-actions: it has to store the current location so it can come back to
-it, and it has to transfer control to the subroutine. The
-C<bsr>X<bsr opcode (PASM)> opcode does both. It pushes the address of the
-next instruction onto the control stack, and then branches to a label
-that marks the subroutine:
-
-=begin PASM
-
-    print "in main\n"
-    bsr _sub
-    print "and back\n"
-    end
-  _sub:
-    print "in sub\n"
-    ret
-
-=end PASM
-
-At the end of the subroutine, the C<ret> instruction pops a location
-back off the control stack and goes there, returning control to the
-caller. The C<jsr>X<jsr opcode (PASM)> opcode pushes the current location
-onto the call stack and jumps to a subroutine. Just like the C<jump>
-opcode, it takes an absolute address in an integer register, so the
-address has to be calculated first with the C<set_addr>X<set_addr
-opcode (PASM)> opcode:
-
-=begin PASM
-
-    print "in main\n"
-    set_addr I0, _sub
-    jsr I0
-    print "and back\n"
-    end
-  _sub:
-    print "in sub\n"
-    ret
-
-=end PASM
-
-=head3 Calling Conventions
-
-Z<CHP-9-SECT-7.1>
-
-X<registers;usage for subroutine calls>
-X<subroutines;register usage>
-X<subroutines;calling conventions>
-A C<bsr> or C<jsr> is fine for a simple subroutine call, but few
-subroutines are quite that simple. Who is responsible for saving and
-restoring the registers, however, so that they don't get overwritten when
-we perform a c<bsr> or C<jsr>? How are arguments passed? Where are the
-subroutine's return values stored? A number of different answers are
-possible. You've seen how many ways Parrot has of storing values. The
-critical point is that the caller and the called subroutine have to
-agree on all the answers.
-
-=head4 Parrot calling conventions
-
-Z<CHP-9-SECT-7.1.2>
-
-Internal subroutines can use whatever calling convention serves them
-best. Externally visible subroutines and methods need stricter rules.
-Since these routines may be called as part of an included library or
-module and even from a different high level language, it's important
-to have a consistent interface.
-
-The C<.sub> directive defines globally accessible subroutine
-objects.
-
-Subroutine objects of all kinds can be called with the
-C<invoke>X<invoke opcode (PASM)> opcode. There is also an C<invoke>
-C<PR<x>> instruction for calling objects held in a different register.
-
-The C<invokecc>X<invokecc opcode (PASM)> opcode is like C<invoke>, but it
-also creates and stores a new return continuation. When the
-called subroutine invokes this return continuation, it returns control
-to the instruction after the function call. This kind of call is known
-as Continuation Passing Style (CPS).
-X<CPS (Continuation Passing Style)>
-X<Continuation Passing Style (CPS)>
-
-=head3 Native Call Interface
-
-Z<CHP-9-SECT-7.2>
-
-X<subroutines;calling conventions;NCI>
-A special version of the Parrot calling conventions are used by the
-X<NCI (Native Call Interface)> Native Call Interface (NCI) for calling
-subroutines with a known prototype in shared libraries. This is not
-really portable across all libraries, but it's worth a short example.
-This is a simplified version of the first test in F<t/pmc/nci.t>:
-
-=begin PASM
-
-    loadlib P1, "libnci_test"     # get library object for a shared lib
-    print "loaded\n"
-    dlfunc P0, P1, "nci_dd", "dd" # obtain the function object
-    print "dlfunced\n"
-    set I0, 1                     # prototype used - unchecked
-    set_args "0", 4.0             # set the argument
-    get_results "0", N5           # prepare to store the return value
-    invokecc P0                   # call nci_dd
-    ne N5, 8.0, nok_1             # the test functions returns 2*arg
-    print "ok 1\n"
-    end
-    nok_1:
-    #...
-
-=end PASM
-
-This example shows two new instructions: C<loadlib> and C<dlfunc>. The
-C<loadlib>X<loadlib opcode (PASM)> opcode obtains a handle for a shared
-library. It searches for the shared library in the current directory,
-in F<runtime/parrot/dynext>, and in a few other configured
-directories. It also tries to load the provided filename unaltered and
-with appended extensions like C<.so> or C<.dll>. Which extensions it
-tries depends on the OS Parrot is running on.
-
-The C<dlfunc>X<dlfunc opcode (PASM)> opcode gets a function object from a
-previously loaded library (second argument) of a specified name (third
-argument) with a known function signature (fourth argument). The
-function signature is a string where the first character is the return
-value and the rest of the parameters are the function parameters. The
-characters used in X<NCI (Native Call Interface);function signatures>
-NCI function signatures are listed in Table 9-5.
-
-=begin table picture Function signature letters
-
-Z<CHP-9-TABLE-5>
-
-=headrow
-
-=row
-
-=cell Character
-
-=cell Register set
-
-=cell C type
-
-=bodyrows
-
-=row
-
-=cell C<v>
-
-=cell -
-
-=cell void (no return value)
-
-=row
-
-=cell C<c>
-
-=cell C<I>
-
-=cell char
-
-=row
-
-=cell C<s>
-
-=cell C<I>
-
-=cell short
-
-=row
-
-=cell C<i>
-
-=cell C<I>
-
-=cell int
-
-=row
-
-=cell C<l>
-
-=cell C<I>
-
-=cell long
-
-=row
-
-=cell C<f>
-
-=cell C<N>
-
-=cell float
-
-=row
-
-=cell C<d>
-
-=cell C<N>
-
-=cell double
-
-=row
-
-=cell C<t>
-
-=cell C<S>
-
-=cell char *
-
-=row
-
-=cell C<p>
-
-=cell C<P>
-
-=cell void * (or other pointer)
-
-=row
-
-=cell C<I>
-
-=cell -
-
-=cell Parrot_Interp *interpreter
-
-=row
-
-=cell C<C>
-
-=cell -
-
-=cell a callback function pointer
-
-=row
-
-=cell C<D>
-
-=cell -
-
-=cell a callback function pointer
-
-=row
-
-=cell C<Y>
-
-=cell C<P>
-
-=cell the subroutine C<C> or C<D> calls into
-
-=row
-
-=cell C<Z>
-
-=cell C<P>
-
-=cell the argument for C<Y>
-
-=end table
-
-For more information on callback functions, read the documentation in
-F<docs/pdds/pdd16_native_call.pod> and F<docs/pmc/struct.pod>.
-
-=head3 Coroutines
-
-Z<CHP-9-SECT-7.4>
-
-As we mentioned in the previous chapter, coroutines are
-X<subroutines;coroutines> subroutines that
-can suspend themselves and return control to the caller--and then pick
-up where they left off the next time they're called, as if they never
-left.
-
-X<coroutines>
-In PASM, coroutines are subroutine-like objects:
-
-=begin PASM
-
-  newsub P0, .Coroutine, _co_entry
-
-=end PASM
-
-The C<Coroutine> object has its own user stack, register frame stacks,
-control stack, and pad stack. The pad stack is inherited from the
-caller. The coroutine's control stack has the caller's control stack
-prepended, but is still distinct. When the coroutine invokes itself,
-it returns to the caller and restores the caller's context (basically
-swapping all stacks). The next time the coroutine is invoked, it
-continues to execute from the point at which it previously returned:
-
-=begin PASM
-
-    new_pad 0                # push a new lexical pad on stack
-    new P0, "Int"            # save one variable in it
-    set P0, 10
-    store_lex -1, "var", P0
-
-    newsub P0, .Coroutine, _cor
-                             # make a new coroutine object
-    saveall                  # preserve environment
-    invoke                   # invoke the coroutine
-    restoreall
-    print "back\n"
-    saveall
-    invoke                   # invoke coroutine again
-    restoreall
-    print "done\n"
-    pop_pad
-    end
-
-  _cor:
-    find_lex P1, "var"       # inherited pad from caller
-    print "in cor "
-    print P1
-    print "\n"
-    inc P1                   # var++
-    saveall
-    invoke                   # yield(  )
-    restoreall
-    print "again "
-    branch _cor              # next invocation of the coroutine
-
-=end PASM
-
-This prints out the result:
-
-  in cor 10
-  back
-  again in cor 11
-  done
-
-X<invoke opcode (PASM);coroutines and>
-The C<invoke> inside the coroutine is commonly referred to as
-I<yield>. The coroutine never ends. When it reaches the bottom, it
-branches back up to C<_cor> and executes until it hits C<invoke>
-again.
-
-The interesting part about this example is that the coroutine yields
-in the same way that a subroutine is called. This means that the
-coroutine has to preserve its own register values. This example uses
-C<saveall> but it could have only stored the registers the coroutine
-actually used. Saving off the registers like this works because
-coroutines have their own register frame stacks.
-
-=head3 Continuations
-
-Z<CHP-9-SECT-7.5>
-
-X<continuations>
-X<subroutines;continuations>
-A continuation is a subroutine that gets a complete copy of the
-caller's context, including its own copy of the call stack. Invoking a
-continuation starts or restarts it at the entry point:
-
-=begin PASM
-
-    new P1, "Int"
-    set P1, 5
-
-    newsub P0, .Continuation, _con
-  _con:
-    print "in cont "
-    print P1
-    print "\n"
-    dec P1
-    unless P1, done
-    invoke                        # P0
-  done:
-    print "done\n"
-    end
-
-=end PASM
-
-This prints:
-
-  in cont 5
-  in cont 4
-  in cont 3
-  in cont 2
-  in cont 1
-  done
-
-=head3 Evaluating a Code String
-
-Z<CHP-9-SECT-7.6>
-
-X<code strings, evaluating>
-This isn't really a subroutine operation, but it does produce a code
-object that can be invoked. In this case, it's a X<bytecode segment
-object> bytecode segment object.
-
-The first step is to get an assembler or compiler for the target
-language:
-
-=begin PASM
-
-  compreg P1, "PASM"
-
-=end PASM
-
-Within the Parrot interpreter there are currently three registered
-languages: C<PASM>, C<PIR>, and C<PASM1>. The first two are for parrot
-assembly language and parrot intermediate representation code. The third
-is for evaluating single statements in PASM. Parrot automatically adds
-an C<end> opcode at the end of C<PASM1> strings before they're
-compiled.
-
-This example places a bytecode segment object into the destination
-register C<P0> and then invokes it with C<invoke>:
-
-=begin PASM
-
-  compreg P1, "PASM1"                # get compiler
-  set S1, "in eval\n"
-  compile P0, P1, "print S1"
-  invoke                             # eval code P0
-  print "back again\n"
-  end
-
-=end PASM
-
-You can register a compiler or assembler for any language inside the
-Parrot core and use it to compile and invoke code from that language.
-These compilers may be written in PASM or reside in shared libraries.
-
-=begin PASM
-
-  compreg "MyLanguage", P10
-
-=end PASM
-
-In this example the C<compreg> opcode registers the subroutine-like
-object C<P10> as a compiler for the language "MyLanguage". See
-F<examples/compilers> and F<examples/japh/japh16.pasm> for an external
-compiler in a shared library.
-
-=head2 Exceptions and Exception Handlers
-
-Z<CHP-9-SECT-8>
-
-X<exceptions>
-X<exception handlers>
-Exceptions provide a way of calling a piece of code outside the normal
-flow of control. They are mainly used for error reporting or cleanup
-tasks, but sometimes exceptions are just a funny way to branch from
-one code location to another one. The design and implementation of
-exceptions in Parrot isn't complete yet, but this section will give
-you an idea where we're headed.
-
-Exceptions are objects that hold all the information needed to handle
-the exception: the error message, the severity and type of the error,
-etc. The class of an exception object indicates the kind of exception
-it is.
-
-Exception handlers are derived from continuations. They are ordinary
-subroutines that follow the Parrot calling conventions, but are never
-explicitly called from within user code. User code pushes an exception
-handler onto the control stack with the C<set_eh>X<set_eh opcode (PASM)>
-opcode. The system calls the installed exception handler only when an
-exception is thrown (perhaps because of code that does division by
-zero or attempts to retrieve a global that wasn't stored.)
-
-=begin PASM
-
-    newsub P20, .ExceptionHandler, _handler
-    set_eh P20                  # push handler on control stack
-    null P10                    # set register to null
-    get_global P10, "none"     # may throw exception
-    clear_eh                    # pop the handler off the stack
-    #...
-
-  _handler:                     # if not, execution continues here
-    is_null P10, not_found      # test P10
-    #...
-
-=end PASM
-
-This example creates a new exception handler subroutine with the
-C<newsub> opcode and installs it on the control stack with the
-C<set_eh> opcode. It sets the C<P10> register to a null value (so it
-can be checked later) and attempts to retrieve the global variable
-named C<none>. If the global variable is found, the next statement
-(C<clear_eh>) pops the exception handler off the control stack and
-normal execution continues. If the C<get_global> call doesn't find
-C<none> it throws an exception by pushing an exception object onto the
-control stack. When Parrot sees that it has an exception, it pops it
-off the control stack and calls the exception handler C<_handler>.
-
-The first exception handler in the control stack sees every exception
-thrown. The handler has to examine the exception object and decide
-whether it can handle it (or discard it) or whether it should
-C<rethrow> the exception to pass it along to an exception handler
-deeper in the stack. The C<rethrow>X<rethrow opcode (PASM)> opcode is only
-valid in exception handlers. It pushes the exception object back onto
-the control stack so Parrot knows to search for the next exception
-handler in the stack. The process continues until some exception
-handler deals with the exception and returns normally, or until there
-are no more exception handlers on the control stack. When the system
-finds no installed exception handlers it defaults to a final action,
-which normally means it prints an appropriate message and terminates
-the program.
-
-When the system installs an exception handler, it creates a return
-continuation with a snapshot of the current interpreter context. If
-the exception handler just returns (that is, if the exception is
-cleanly caught) the return continuation restores the control stack
-back to its state when the exception handler was called, cleaning up
-the exception handler and any other changes that were made in the
-process of handling the exception.
-
-Exceptions thrown by standard Parrot opcodes (like the one thrown by
-C<get_global> above or by the C<throw> opcode) are always resumable,
-so when the exception handler function returns normally it continues
-execution at the opcode immediately after the one that threw the
-exception. Other exceptions at the run-loop level are also generally
-resumable.
-
-=begin PASM
-
-  new P10, 'Exception'    # create new Exception object
-  set P10, 'I die'        # set message attribute
-  throw P10               # throw it
-
-=end PASM
-
-Exceptions are designed to work with the Parrot calling conventions.
-Since the return addresses of C<bsr> subroutine calls and exception
-handlers are both pushed onto the control stack, it's generally a bad
-idea to combine the two.
-
-=head2 Events
-
-Z<CHP-9-SECT-9>
-
-An event is a notification that something has happened: a timer
-expired, an IO operation finished, a thread sent a message to
-another thread, or the user pressed C<Ctrl-C> to interrupt program
-execution.
-
-What all of these events have in common is that they arrive
-asynchronously. It's generally not safe to interrupt program flow at an
-arbitrary point and continue at a different position, so the event is
-placed in the
-interpreter's task queue. The run loops code regularly checks whether
-an event needs to be handled. Event handlers may be an internal piece
-of code or a user-defined event handler subroutine.
-
-Events are still experimental in Parrot, so the implementation and
-design is subject to change.
-
-=head3 Timers
-
-Z<CHP-9-SECT-9.1>
-
-C<Timer> objects are the replacement for Perl 5's C<alarm> handlers.
-They are also a significant improvement. Timers can fire once or
-repeatedly, and multiple timers can run independently. The precision
-of a timer is limited by the OS Parrot runs on, but it is always more
-fine-grained then a whole second. The final syntax isn't yet fixed, so
-please consult the documentation for examples.
-
-=head3 Signals
-
-Z<CHP-9-SECT-9.2>
-
-Signal handling is related to events. When Parrot gets a signal it
-needs to handle from the OS, it converts that signal into an event and
-broadcasts it to all running threads. Each thread independently
-decides if it's interested in this signal and, if so, how to respond to it.
-
-=begin PASM
-
-    newsub P20, .ExceptionHandler, _handler
-    set_eh P20                  # establish signal handler
-    print "send SIGINT:\n"
-    sleep 2                     # press ^C after you saw start
-    print "no SIGINT\n"
-    end
-  _handler:
-    .include "signal.pasm"      # get signal definitions
-    print "caught "
-    set I0, P5["type"]         # if _type is negative, the ...
-    neg I0, I0                  # ... negated type is the signal
-    ne I0, .SIGINT, nok
-    print "SIGINT\n"
-  nok:
-    end
-
-=end PASM
-
-This example creates a signal handler and pushes it on to the control
-stack. It then prompts the user to send a C<SIGINT> from the shell
-(this is usually C<Ctrl-C>, but it varies in different shells), and
-waits for 2 seconds. If the user doesn't send a SIGINT in 2 seconds
-the example just prints "no SIGINT" and ends. If the user does send a
-SIGINT, the signal handler catches it, prints out "caught SIGINT" and
-ends.N<Currently, only Linux installs a C<SIGINT> C<sigaction>
-handler, so this example won't work on other platforms.>
-
-=head2 Threads
-
-Z<CHP-9-SECT-10>
-
-Threads allow multiple pieces of code to run in parallel. This is
-useful when you have multiple physical CPUs to share the load of
-running individual threads. With a single processor, threads still
-provide the feeling of parallelism, but without any improvement in
-execution time. Even worse, sometimes using threads on a single
-processor will actually slow down your program.
-
-Still, many algorithms can be expressed more easily in terms of
-parallel running pieces of code and many applications profit from
-taking advantage of multiple CPUs. Threads can vastly simplify
-asynchronous programs like internet servers: a thread splits off,
-waits for some IO to happen, handles it, and relinquishes the
-processor again when it's done.
-
-Parrot compiles in thread support by default (at least, if the
-platform provides some kind of support for it). Unlike Perl 5,
-compiling with threading support doesn't impose any execution time
-penalty for a non-threaded program. Like exceptions and events,
-threads are still under development, so you can expect significant
-changes in the near future.
-
-As outlined in the previous chapter, Parrot implements three different
-threading models. (B<Note>:  As of version 1.0, the C<TQueue> PMC will be
-deprecated, rendering the following discussion obsolete.) The following
-example uses the third model, which takes advantage of shared data. It uses a
-C<TQueue> (thread-safe queue) object to synchronize the two parallel running
-threads. This is only a simple example to illustrate threads, not a typical
-usage of threads (no-one really wants to spawn two threads just to print out a
-simple string).
-
-=begin PASM
-
-    get_global P5, "_th1"              # locate thread function
-    new P2, "ParrotThread"              # create a new thread
-    find_method P0, P2, "thread3"       # a shared thread's entry
-    new P7, "TQueue"                    # create a Queue object
-    new P8, "Int"                       # and a Int
-    push P7, P8                         # push the Int onto queue
-    new P6, "String"                    # create new string
-    set P6, "Js nte artHce\n"
-    set I3, 3                           # thread function gets 3 args
-    invoke                              # _th1.run(P5,P6,P7)
-    new P2, "ParrotThread"              # same for a second thread
-    get_global P5, "_th2"
-    set P6, "utaohrPro akr"             # set string to 2nd thread's
-    invoke                              # ... data, run 2nd thread too
-    end                                 # Parrot joins both
-
-  .pcc_sub _th1:                        # 1st thread function
-  w1: sleep 0.001                       # wait a bit and schedule
-    defined I1, P7                      # check if queue entry is ...
-    unless I1, w1                       # ... defined, yes: it's ours
-    set S5, P6                          # get string param
-    substr S0, S5, I0, 1                # extract next char
-    print S0                            # and print it
-    inc I0                              # increment char pointer
-    shift P8, P7                        # pull item off from queue
-    if S0, w1                           # then wait again, if todo
-    invoke P1                           # done with string
-
-  .pcc_sub _th2:                        # 2nd thread function
-  w2: sleep 0.001
-    defined I1, P7                      # if queue entry is defined
-    if I1, w2                           # then wait
-    set S5, P6
-    substr S0, S5, I0, 1                # if not print next char
-    print S0
-    inc I0
-    new P8, "Int"                       # and put a defined entry
-    push P7, P8                         # onto the queue so that
-    if S0, w2                           # the other thread will run
-    invoke P1                           # done with string
-
-=end PASM
-
-This example creates a C<ParrotThread> object and calls its C<thread3>
-method, passing three arguments: a PMC for the C<_th1> subroutine in
-C<P5>, a string argument in C<P6>, and a C<TQueue> object in C<P7>
-containing a single integer. Remember from the earlier section
-"Parrot calling conventions" that registers 5-15
-hold the arguments for a subroutine or method call and C<I3> stores
-the number of arguments. The thread object is passed in C<P2>.
-
-This call to the C<thread3> method spawns a new thread to run the
-C<_th1> subroutine. The main body of the code then creates a second
-C<ParrotThread> object in C<P2>, stores a different subroutine in
-C<P5>, sets C<P6> to a new string value, and then calls the C<thread3>
-method again, passing it the same C<TQueue> object as the first
-thread. This method call spawns a second thread. The main body of code
-then ends, leaving the two threads to do the work.
-
-At this point the two threads have already started running. The first
-thread (C<_th1>) starts off by sleeping for a 1000th of a second. It
-then checks if the C<TQueue> object contains a value. Since it
-contains a value when the thread is first called, it goes ahead and
-runs the body of the subroutine. The first thing this does is shift
-the element off the C<TQueue>. It then pulls one character off a copy
-of the string parameter using C<substr>, prints the character,
-increments the current position (C<I0>) in the string, and loops back
-to the C<w1> label and sleeps. Since the queue doesn't have any
-elements now, the subroutine keeps sleeping.
-
-Meanwhile, the second thread (C<_th2>) also starts off by sleeping for
-a 1000th of a second. It checks if the shared C<TQueue> object
-contains a defined value but unlike the first thread it only continues
-sleeping if the queue does contain a value. Since the queue contains a
-value when the second thread is first called, the subroutine loops
-back to the C<w2> label and continues sleeping. It keeps sleeping
-until the first thread shifts the integer off the queue, then runs the
-body of the subroutine. The body pulls one character off a copy of the
-string parameter using C<substr>, prints the character, and increments
-the current position in the string. It then creates a new
-C<Int>, pushes it onto the shared queue, and loops back to the
-C<w2> label again to sleep. The queue has an element now, so the
-second thread keeps sleeping, but the first thread runs through its
-loop again.
-
-The two threads alternate like this, printing a character and marking
-the queue so the next thread can run, until there are no more
-characters in either string. At the end, each subroutine invokes the
-return continuation in C<P1> which terminates the thread. The
-interpreter waits for all threads to terminate in the cleanup phase
-after the C<end> in the main body of code.
-
-The final printed result (as you might have guessed) is:
-
-  Just another Parrot Hacker
-
-The syntax for threads isn't carved in stone and the implementation
-still isn't finished but as this example shows, threads are working
-now and already useful.
-
-Several methods are useful when working with threads. The C<join>
-method belongs to the C<ParrotThread> class. When it's called on a
-C<ParrotThread> object, the calling code waits until the thread
-terminates.
-
-=begin PASM
-
-    new P2, "ParrotThread"      # create a new thread
-    set I5, P2                  # get thread ID
-
-    find_method P0, P2, "join"  # get the join method...
-    invoke                      # ...and join (wait for) the thread
-    set P16, P5                 # the return result of the thread
-
-=end PASM
-
-C<kill> and C<detach> are interpreter methods, so you have to grab the
-current interpreter object before you can look up the method object.
-
-=begin PASM
-
-    set I5, P2                  # get thread ID of thread P2
-    getinterp P3                # get this interpreter object
-    find_method P0, P3, "kill"  # get kill method
-    invoke                      # kill thread with ID I5
-
-    find_method P0, P3, "detach"
-    invoke                      # detach thread with ID I5
-
-=end PASM
-
-By the time you read this, some of these combinations of statements
-and much of the threading syntax above may be reduced to a simpler set
-of opcodes.
-
-=head2 Loading Bytecode
-
-Z<CHP-9-SECT-11>
-
-In addition to running Parrot bytecode on the command-line, you can
-also load pre-compiled bytecode directly into your PASM source file.
-The C<load_bytecode>X<load_bytecode opcode (PASM)> opcode takes a single
-argument: the name of the bytecode file to load. So, if you create a
-file named F<file.pasm> containing a single subroutine:
-
-=begin PASM
-
-  # file.pasm
-  .sub _sub2:               # .sub stores a global sub
-     print "in sub2\n"
-     invoke P1
-
-=end PASM
-
-and compile it to bytecode using the C<-o> command-line switch:
-
-  $ parrot -o file.pbc file.pasm
-
-You can then load the compiled bytecode into F<main.pasm> and directly
-call the subroutine defined in F<file.pasm>:
-
-=begin PASM
-
-  # main.pasm
-  main:
-    load_bytecode "file.pbc"    # compiled file.pasm
-    get_global P0, "_sub2"
-    invokecc
-    end
-
-=end PASM
-
-The C<load_bytecode> opcode also works with source files, as long as
-Parrot has a compiler registered for that type of file:
-
-=begin PASM
-
-  # main2.pasm
-  main:
-    load_bytecode "file.pasm"  # PASM source code
-    set_global P0, "_sub2"
-    invokecc
-    end
-
-=end PASM
-
-Subroutines marked with C<:load> run as soon as they're loaded (before
-C<load_bytecode> returns), rather than waiting to be called. A
-subroutine marked with C<:main> will always run first, no matter what
-name you give it or where you define it in the file.
-
-=begin PASM
-
-  # file3.pasm
-  .sub :load                    # mark the sub as to be run
-    print "file3\n"
-    invoke P1                   # return
-
-  # main3.pasm
-  first:                        # first is never invoked
-    print "never\n"
-    invoke P1
-
-  .sub :main                    # because _main is marked as the
-    print "main\n"              # MAIN entry of program execution
-    load_bytecode "file3.pasm"
-    print "back\n"
-    end
-
-=end PASM
-
-This example uses both C<:load> and C<:main>. Because the C<main>
-subroutine is defined with C<:main> it will execute first even though
-another subroutine comes before it in the file. C<main> prints a
-line, loads the PASM source file, and then prints another line.
-Because C<_entry> in F<file3.pasm> is marked with C<:load> it runs
-before C<load_bytecode> returns, so the final output is:
-
-  main
-  file3
-  back
-
-=head2 Classes and Objects
-
-Z<CHP-9-SECT-12>
-
-This section revolves around one complete example that defines a
-class, instantiates objects, and uses them. The whole example is
-included at the end of the section.
-
-=head3 Class declaration
-
-Z<CHP-9-SECT-12.1>
-
-X<classes;in PASM>
-The C<newclass>X<newclass opcode (PASM)> opcode defines a new class.
-It takes two arguments, the name of the class and the destination
-register for the class PMC. All classes (and objects) inherit from the
-C<ParrotClass> PMCX<ParrotClass PMC>, which is the core of the Parrot
-object system.
-
-=begin PASM
-
-    newclass P1, "Foo"
-
-=end PASM
-
-To instantiate a new object of a particular class, you first look up
-the integer value for the class type with the C<find_type> opcode,
-then create an object of that type with the C<new> opcode:
-
-=begin PASM
-
-    find_type I1, "Foo"
-    new P3I I1
-
-=end PASM
-
-The C<new> opcode also checks to see if the class defines a
-method named "__init" and calls it if it exists.
-
-=head3 Attributes
-
-Z<CHP-9-SECT-12.2>
-
-X<attributes;in PASM>
-X<classes;attributes>
-The C<addattribute> opcode creates a slot in the class for an
-attribute (sometimes known as an I<instance variable>) and associates
-it with a name:
-
-=begin PASM
-
-    addattribute P1, ".i"                # Foo.i
-
-=end PASM
-
-This chunk of code
-from the C<__init> method looks up the position of the first
-attribute, creates a C<Int> PMC, and stores it as the first
-attribute:
-
-=begin PASM
-
-    classoffset I0, P2, "Foo"     # first "Foo" attribute of object P2
-    new P6, "Int"                 # create storage for the attribute
-    setattribute P2, I0, P6       # store the first attribute
-
-=end PASM
-
-The C<classoffset> opcodeX<classoffset opcode (PASM)> takes a PMC
-containing an object and the name of its class, and returns an integer
-index for the position of the first attribute. The C<setattribute>
-opcode uses the integer index to store a PMC value in one of the
-object's attribute slots. This example initializes the first
-attribute. The second attribute would be at C<I0 + 1>, the third
-attribute at C<I0 + 2>, etc:
-
-=begin PASM
-
-    inc I0
-    setattribute P2, I0, P7       # store next attribute
-    #...
-
-=end PASM
-
-There is also support for named parameters with fully qualified
-parameter names (although this is a little bit slower than getting
-the class offset once and accessing several attributes by index):
-
-=begin PASM
-
-    new P6, "Int"
-    setattribute P2, "Foo\x0.i", P6   # store the attribute
-
-=end PASM
-
-You use the same integer index to retrieve the value of an attribute.
-The C<getattribute>X<getattribute opcode (PASM)> opcode takes an object and
-an index as arguments and returns the attribute PMC at that position:
-
-=begin PASM
-
-    classoffset I0, P2, "Foo"         # first "Foo" attribute of object P2
-    getattribute P10, P2, I0          # indexed get of attribute
-
-=end PASM
-
-or
-
-=begin PASM
-
-    getattribute P10, P2, "Foo\x0.i"  # named get
-
-=end PASM
-
-To set the value of an attribute PMC, first retrieve it with
-C<getattribute> and then assign to the returned PMC. Because PMC
-registers are only pointers to values, you don't need to store the PMC
-again after you modify its value:
-
-=begin PASM
-
-    getattribute P10, P2, I0
-    set P10, I5
-
-=end PASM
-
-=head3 Methods
-
-Z<CHP-9-SECT-12.3>
-
-X<methods;in PASM>
-X<classes;methods>
-X<classes;namespaces>
-Methods in PASM are just subroutines installed in the namespace of the
-class. You define a method with the C<.pcc_sub> directive before the
-label:
-
-=begin PASM
-
-  .pcc_sub _half:                 # I5 = self."_half"()
-    classoffset I0, P2, "Foo"
-    getattribute P10, P2, I0
-    set I5, P10                   # get value
-    div I5, 2
-    invoke P1
-
-=end PASM
-
-This routine returns half of the value of the first attribute of the
-object. Method calls use the Parrot calling conventions so they always
-pass the I<invocant> object (often called I<self>) in C<P2>. Invoking
-the return continuation in C<P1> returns control to the caller.
-
-The C<.pcc_sub> directive automatically stores the subroutine as a
-global in the current namespace. The C<.namespace> directive sets the
-current namespace:
-
-=begin PASM
-
-  .namespace [ "Foo" ]
-
-=end PASM
-
-If the namespace is explicitly set to an empty string or key, then the
-subroutine is stored in the outermost namespace.
-
-The C<callmethodcc>X<callmethodcc opcode (PASM)> opcode makes a method
-call. It follows the Parrot calling conventions, so it expects to
-find the invocant object in C<P2>, the method object in C<P0>, etc. It
-adds one bit of magic, though. If you pass the name of the method in
-C<S0>, C<callmethodcc> looks up that method name in the invocant
-object and stores the method object in C<P0> for you:
-
-=begin PASM
-
-    set S0, "_half"             # set method name
-    set P2, P3                  # the object
-    callmethodcc                # create return continuation, call
-    print I5                    # result of method call
-    print "\n"
-
-=end PASM
-
-The C<callmethodcc> opcode also generates a return continuation and
-stores it in C<P1>. The C<callmethod> opcode doesn't generate a return
-continuation, but is otherwise identical to C<callmethodcc>. Just like
-ordinary subroutine calls, you have to preserve and restore any
-registers you want to keep after a method call. Whether you store
-individual registers, register frames, or half register frames is up
-to you.
-
-=head4 Overriding vtable functions
-
-Z<CHP-9-SECT-12.3.1>
-
-Every object inherits a default set of I<vtable> functions from the
-C<ParrotObject> PMC, but you can also override them with your own
-methods. The vtable functions have predefined names that start with a
-double underscore "__". The following code defines a method named
-C<__init> in the C<Foo> class that initializes the first attribute of
-the object with an integer:
-
-=begin PASM
-
-  .sub __init:
-    classoffset I0, P2, "Foo"     # lookup first attribute position
-    new P6, "Int"                 # create storage for the attribute
-    setattribute P2, I0, P6       # store the first attribute
-    invoke P1                     # return
-
-=end PASM
-
-Ordinary methods have to be called explicitly, but the vtable
-functions are called implicitly in many different contexts. Parrot
-saves and restores registers for you in these calls. The C<__init>
-method is called whenever a new object is constructed:
-
-=begin PASM
-
-    find_type I1, "Foo"
-    new P3, I1          # call __init if it exists
-
-=end PASM
-
-A few other vtable functions in the complete code example for this
-section are C<__set_integer_native>, C<__add>, C<__get_integer>,
-C<__get_string>, and C<__increment>. The C<set> opcode calls Foo's
-C<__set_integer_native> vtable function when its destination register
-is a C<Foo> object and the source register is a native integer:
-
-=begin PASM
-
-    set P3, 30          # call __set_integer_native method
-
-=end PASM
-
-The C<add> opcode calls Foo's C<__add> vtable function when it adds
-two C<Foo> objects:
-
-=begin PASM
-
-    new P4, I1          # same with P4
-    set P4, 12
-    new P5, I1          # create a new store for add
-
-    add P5, P3, P4      # __add method
-
-=end PASM
-
-The C<inc> opcode calls Foo's C<__increment> vtable function when it
-increments a C<Foo> object:
-
-=begin PASM
-
-    inc P3              # __increment
-
-=end PASM
-
-Foo's C<__get_integer> and C<__get_string> vtable functions are called
-whenever an integer or string value is retrieved from a C<Foo> object:
-
-=begin PASM
-
-    set I10, P5         # __get_integer
-    #...
-    print P5            # calls __get_string, prints 'fortytwo'
-
-=end PASM
-
-
-=head3 Inheritance
-
-Z<CHP-9-SECT-12.4>
-
-X<inheritance;in PASM>
-X<classes;inheritance>
-The C<subclass>X<subclass opcode (PASM)> opcode creates a new class that
-inherits methods and attributes from another class. It takes 3
-arguments: the destination register for the new class, a register
-containing the parent class, and the name of the new class:
-
-=begin PASM
-
-    subclass P3, P1, "Bar"
-
-=end PASM
-
-X<multiple inheritance; in PASM>
-For multiple inheritance, the C<addparent>X<addparent opcode (PASM)>
-opcode adds additional parents to a subclass.
-
-=begin PASM
-
-  newclass P4, "Baz"
-  addparent P3, P4
-
-=end PASM
-
-To override an inherited method, define a method with the same name in
-the namespace of the subclass. The following code overrides Bar's
-C<__increment> method so it decrements the value instead of
-incrementing it:
-
-=begin PASM
-
-  .namespace [ "Bar" ]
-
-  .sub __increment:
-    classoffset I0, P2, "Foo"     # get Foo's attribute slot offset
-    getattribute P10, P2, I0      # get the first Foo attribute
-    dec P10                       # the evil line
-    invoke P1
-
-=end PASM
-
-Notice that the attribute inherited from C<Foo> can only be looked up
-with the C<Foo> class name, not the C<Bar> class name. This preserves
-the distinction between attributes that belong to the class and
-inherited attributes.
-
-Object creation for subclasses is the same as for ordinary classes:
-
-=begin PASM
-
-    find_type I1, "Bar"
-    new P5, I1
-
-=end PASM
-
-Calls to inherited methods are just like calls to methods defined in
-the class:
-
-=begin PASM
-
-    set P5, 42                  # inherited __set_integer_native
-    inc P5                      # overridden __increment
-    print P5                    # prints 41 as Bar's __increment decrements
-    print "\n"
-
-    set S0, "_half"             # set method name
-    set P2, P5                  # the object
-    callmethodcc                # create return continuation, call
-    print I5
-    print "\n"
-
-=end PASM
-
-=head3 Additional Object Opcodes
-
-Z<CHP-9-SECT-12.5>
-
-The C<isa> and C<can> opcodes are also useful when working with
-objects. C<isa>X<isa opcode (PASM)> checks whether an object belongs to or
-inherits from a particular class. C<can>X<can opcode (PASM)> checks whether
-an object has a particular method. Both return a true or false value.
-
-=begin PASM
-
-    isa I0, P3, "Foo"           # 1
-    isa I0, P3, "Bar"           # 1
-    can I0, P3, "__add"         # 1
-
-=end PASM
-
-=head3 Complete Example
-
-Z<CHP-9-SECT-12.6>
-
-=begin PASM
-
-    newclass P1, "Foo"
-    addattribute P1, "$.i"                # Foo.i
-
-    find_type I1, "Foo"
-    new P3, I1          # call __init if it exists
-    set P3, 30          # call __set_integer_native method
-
-    new P4, I1          # same with P4
-    set P4, 12
-    new P5, I1          # create a new LHS for add
-
-    add P5, P3, P4      # __add method
-    set I10, P5         # __get_integer
-    print I10
-    print "\n"
-    print P5            # calls __get_string prints 'fortytwo'
-    print "\n"
-
-    inc P3              # __increment
-    add P5, P3, P4
-    print P5            # calls __get_string prints '43'
-    print "\n"
-
-    subclass P3, P1, "Bar"
-
-    find_type I1, "Bar"
-    new P3, I1
-
-    set P3, 100
-    new P4, I1
-    set P4, 200
-    new P5, I1
-
-    add P5, P3, P4
-    print P5                    # prints 300
-    print "\n"
-
-    set P5, 42
-    print P5                    # prints 'fortytwo'
-    print "\n"
-
-    inc P5
-    print P5                    # prints 41 as Bar's
-    print "\n"                  # __increment decrements
-
-    set S0, "_half"             # set method name
-    set P2, P3                  # the object
-    callmethodcc                # create return continuation, call
-    print I5                    # prints 50
-    print "\n"
-
-    end
-
-  .namespace [ "Foo" ]
-
-  .sub __init:
-    classoffset I0, P2, "Foo"     # lookup first attribute position
-    new P6, "Int"                 # create a store for the attribute
-    setattribute P2, I0, P6       # store the first attribute
-    invoke P1                     # return
-
-  .sub __set_integer_native:
-    classoffset I0, P2, "Foo"
-    getattribute P10, P2, I0
-    set P10, I5                   # assign passed in value
-    invoke P1
-
-  .sub __get_integer:
-    classoffset I0, P2, "Foo"
-    getattribute P10, P2, I0
-    set I5, P10                   # return value
-    invoke P1
-
-  .sub __get_string:
-    classoffset I0, P2, "Foo"
-    getattribute P10, P2, I0
-    set I5, P10
-    set S5, P10                   # get stringified value
-    ne I5, 42, ok
-    set S5, "fortytwo"            # or return modified one
-  ok:
-    invoke P1
-
-  .sub __increment:
-    classoffset I0, P2, "Foo"
-    getattribute P10, P2, I0      # as with all aggregates, this
-    inc P10                       # has reference semantics - no
-    invoke P1                     # setattribute needed
-
-  .sub __add:
-    classoffset I0, P2, "Foo"
-    getattribute P10, P2, I0      # object
-    getattribute P11, P5, I0      # argument
-    getattribute P12, P6, I0      # destination
-    add P12, P10, P11
-    invoke P1
-
-  .sub _half:                 # I5 = _half(self)
-    classoffset I0, P2, "Foo"
-    getattribute P10, P2, I0
-    set I5, P10                   # get value
-    div I5, 2
-    invoke P1
-
-
-  .namespace [ "Bar" ]
-
-  .sub __increment:
-    classoffset I0, P2, "Foo"     # get Foo's attribute slot offset
-    getattribute P10, P2, I0      # get the first Foo attribute
-    dec P10                       # the evil line
-    invoke P1
-
-=end PASM
 
-This example prints out:
 
-  42
-  fortytwo
-  43
-  300
-  fortytwo
-  41
-  50
 
 =cut
 


More information about the parrot-commits mailing list