[svn:parrot] r37501 - in trunk: . docs/user/pir

allison at svn.parrot.org allison at svn.parrot.org
Mon Mar 16 21:06:50 UTC 2009


Author: allison
Date: Mon Mar 16 21:06:48 2009
New Revision: 37501
URL: https://trac.parrot.org/parrot/changeset/37501

Log:
[doc] Renaming some introductory files.

Added:
   trunk/docs/user/pir/intro.pod
      - copied unchanged from r37497, trunk/docs/user/pir/pp001-intro.pod
   trunk/docs/user/pir/objects.pod
      - copied unchanged from r37497, trunk/docs/user/pir/pp003-oop.pod
   trunk/docs/user/pir/pmcs.pod
      - copied unchanged from r37497, trunk/docs/user/pir/pp002-pmc.pod
Deleted:
   trunk/docs/user/pir/pp001-intro.pod
   trunk/docs/user/pir/pp002-pmc.pod
   trunk/docs/user/pir/pp003-oop.pod
Modified:
   trunk/MANIFEST

Modified: trunk/MANIFEST
==============================================================================
--- trunk/MANIFEST	Mon Mar 16 20:56:37 2009	(r37500)
+++ trunk/MANIFEST	Mon Mar 16 21:06:48 2009	(r37501)
@@ -1,7 +1,7 @@
 # ex: set ro:
 # $Id$
 #
-# generated by tools/dev/mk_manifest_and_skip.pl Mon Mar 16 17:06:35 2009 UT
+# generated by tools/dev/mk_manifest_and_skip.pl Mon Mar 16 21:02:26 2009 UT
 #
 # See tools/dev/install_files.pl for documentation on the
 # format of this file.
@@ -528,9 +528,9 @@
 docs/submissions.pod                                        []
 docs/tests.pod                                              []
 docs/user/pir/exceptions.pod                                [main]doc
-docs/user/pir/pp001-intro.pod                               [main]doc
-docs/user/pir/pp002-pmc.pod                                 [main]doc
-docs/user/pir/pp003-oop.pod                                 [main]doc
+docs/user/pir/intro.pod                                     [main]doc
+docs/user/pir/objects.pod                                   [main]doc
+docs/user/pir/pmcs.pod                                      [main]doc
 docs/vtables.pod                                            [devel]doc
 editor/README.pod                                           []doc
 editor/filetype_parrot.vim                                  []

Copied: trunk/docs/user/pir/intro.pod (from r37497, trunk/docs/user/pir/pp001-intro.pod)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/docs/user/pir/intro.pod	Mon Mar 16 21:06:48 2009	(r37501, copy of r37497, trunk/docs/user/pir/pp001-intro.pod)
@@ -0,0 +1,347 @@
+# $Id$
+
+# One first version of this article was published on TPR 2.3
+#
+# Please feel free to edit it to suit latest parrot developments,
+# and to be a good starting point for beginners.
+
+=head1 Writing PIR
+
+PIR (Parrot Intermediate Representation) is a way to program the
+parrot virtual machine that is easier to use than PASM (Parrot
+Assembler). PASM notation is like any other assembler-like format and
+can be used directly, but it is more verbose and gives too much power
+to the user. PIR abstracts common operations and conventions into a
+syntax that more closely resembles a high-level language. PIR allows
+the programmer to write code that more naturally expresses their
+intent without worrying about setting up the exact details that PASM
+requires to function properly.
+
+This article will show the basics on programming in PIR. More advanced
+topics will appear in later articles.
+
+=head2 Getting Parrot
+
+In order to test the PIR and PASM code in this article, a parrot virtual
+machine is needed (henceforth just "parrot"). Parrot is available from
+L<http://parrot.org>. Just download the latest release, or checkout
+the current development version from the SVN tree. The programs in this
+article were tested with Parrot 0.8.1.
+
+Parrot is very easy to compile on unix-like and Microsoft Windows
+operating systems: just run C<perl Configure.pl && make> in the root
+directory of the parrot source and, if everything works correctly, a
+C<parrot> executable should appear. At the moment of writing, the
+C<make install> target does not work properly, so in this and other
+articles it is assumed that the parrot executable is invoked from the
+parrot root directory.
+
+If you do not want to compile your own Parrot you can download a pre-compiled
+binary from http://www.parrot.org/source.html.
+
+=head2 Parrot Virtual Machine overview
+
+Before we get started with the examples, here's a quick overview of
+parrot's architecture.
+
+Parrot is a register-based virtual machine. It provides 4 types of
+registers. The register types are:
+
+=over 4
+
+=item I - integer
+
+=item N - floating point
+
+=item S - string
+
+=item P - polymorphic container (PMC)
+
+=back
+
+In order to designate a register in PASM, use the character indicating
+the type (C<I>, C<N>, C<S> or C<P>) and the register number. For instance,
+in order to use register 10 of type integer, you'd write C<I10>. In this
+series of articles, we will mainly focus on programming PIR.
+
+In PIR, you would type the C<$> character in front of the register, to
+indicate a I<virtual> register. For instance, the integer registers are
+C<$I0>, C<$I1> and so on. The PMC registers hold arbitrary data objects
+and are parrot's mechanism for implementing more complex behavior than the
+ones that can be expressed using the other 3 register types alone.
+
+A virtual register is mapped to an actual register by the register allocator.
+You can use as many registers as you want, and the register allocator will
+allocate them as needed.
+
+PMCs will be covered in more detail in a future article. Examples in
+this article will focus on the first 3 register types.
+
+=head2 Simple Operators
+
+Let me start with a simple and typical example:
+
+  .sub main :main
+       print "hello world\n"
+  .end
+
+To run it, save the code in a C<hello.pir> file and pass it to the
+parrot virtual machine:
+
+   ./parrot hello.pir
+
+Note that I am using a relative path to parrot given that I didn't
+install it into the system.
+
+The keywords starting with a dot (C<.sub> and C<.end>) are PIR directives.
+They are used together to define subroutines. After the C<.sub> keyword
+I use the name of the subroutine. The keyword that starts with a colon
+(C<:main>) is a pragma that tells parrot that this is the main body of the
+program and that it should start by executing this subroutine.
+By the way, I could use C<.sub foo :main> and Parrot will use the C<foo>
+subroutine as the main body of the program. The actual name of the
+subroutine does not matter as long as it has the C<:main> pragma. If you
+don't specify the <:main> pragma on any subroutine, then parrot will start
+executing the first subroutine in the source file.
+The full set of pragmas are defined in L<docs/pdds/pdd19_pir.pod>.
+
+Before going into more details about subroutines and calling
+conventions, let's compare some PIR syntax to the equivalent PASM.
+
+If I want to add two integer registers using PASM I would use the
+Parrot C<set> opcode to put values into registers, and the C<add>
+opcode to add them, like this:
+
+   set $I1, 5
+   set $I2, 3
+   add $I0, $I1, $I2   # $I0 yields 5+3
+
+PIR includes infix operators for these common opcodes. I could write
+this same code as
+
+   $I1 = 5
+   $I2 = 3
+   $I0 = $I1 + $I2
+
+There are the four arithmetic operators as you should be expecting, as
+well as the six different comparison operators, which return a boolean
+value:
+
+   $I1 = 5
+   $I2 = 3
+   $I0 = $I1 <= $I2   # $I0 yields 0 (false)
+
+I can also use the short accumulation-like operators, like C<+=>.
+
+Another PIR perk is that local variable names may be declared and used
+instead of register names. For that I just need to declare the
+variable using the C<.local> keyword with any of the four data
+types available on PIR: C<int>, C<string>, C<num> and C<pmc>:
+
+   .local int size
+   size = 5
+
+Note that all registers, both numbered and named, are consolidated by
+the Parrot register allocator, assigning these "virtual registers" to
+actual registers as needed.  The register allocator even coalesces two
+virtual names onto the same physical register when it can
+prove that they have non-overlapping lifetimes, so there is no need to
+be stingy with register names.  To see the actual registers used, use
+C<pbc_disassemble> on the C<*.pbc> output. You can generate a Parrot
+Byte Code (PBC) file as follows:
+
+   ./parrot -o foo.pbc --output-pbc foo.pir
+
+Then, use C<pbc_disassemble> in order to disassemble it:
+
+   ./pbc_disassemble foo.pbc
+
+=head2 Branching
+
+Another simplification of PASM are branches. Basically, when I want to
+test a condition and jump to another place in the code, I would write
+the following PASM code:
+
+   le $I1, $I2, LESS_EQ
+
+Meaning, if C<$I1> is less or equal than C<$I2>, jump to label
+C<LESS_EQ>. In PIR I would write it in a more legible way:
+
+   if $I1 <= $I2 goto LESS_EQ
+
+PIR includes the C<unless> keyword as well.
+
+=head2 Calling Functions
+
+Subroutines can easily be created using the C<.sub> keyword shown
+before. If you do not need parameters, it is just as simple as I show in
+the following code:
+
+  .sub main :main
+     hello()
+  .end
+
+  .sub hello
+    print "Hello World\n"
+  .end
+
+Now, I want to make my C<hello> subroutine a little more useful, such
+that I can greet other people. For that I will use the C<.param>
+keyword to define the parameters C<hello> can handle:
+
+  .sub main :main
+     hello("leo")
+     hello("chip")
+  .end
+
+  .sub hello
+     .param string person
+     print "Hello "
+     print person
+     print "\n"
+  .end
+
+If I need more parameters I just need to add more C<.param> lines.
+
+To return values from PIR subroutines I use the C<.return> keyword,
+followed by one or more arguments, just like this:
+
+  .return (10, 20, 30)
+
+The calling subroutine can accept these values. If you want to retrieve
+only one value (or only the first value, in case multiple values are
+returned), write this:
+
+  $I0 = compute_it($I8, $I9)
+
+To accept multiple values from such a function, use a parenthesized
+results list:
+
+  ($I1, $I2, $I3) = compute_it($I8, $I9)
+
+=head2 Factorial Example
+
+Now, for a little more complicated example, let me show how I would
+code Factorial subroutine:
+
+  .sub main :main
+     $I1 = factorial(5)
+     print $I1
+     print "\n"
+  .end
+
+  .sub factorial
+     .param int i
+     if i > 1 goto recur
+     .return (1)
+  recur:
+     $I1 = i - 1
+     $I2 = factorial($I1)
+     $I2 *= i
+     .return ($I2)
+  .end
+
+This example also shows that PIR subroutines may be recursive just as in
+a high-level language.
+
+=head2 Named Arguments
+
+As some other languages as Python and Perl support named arguments,
+PIR supports them as well.
+
+As before, I need to use C<.param> for each named argument, but you need to
+specify a flag indicating the parameter is named:
+
+  .sub func
+    .param int a :named("foo")
+
+The subroutine will receive an integer named "foo", and inside of the
+subroutine that integer will be known as "a".
+
+When calling the function, I need to pass the names of the
+arguments. For that there are two syntaxes:
+
+  func( 10 :named("foo") )    # or
+  func( "foo" => 10 )
+
+Note that with named arguments, you may rearrange the order of your
+parameters at will.
+
+  .sub foo
+    .param string "name"    => a
+    .param int    "age"     => b
+    .param string "gender"  => c
+    # ...
+  .end
+
+This subroutine may be called in any of the following ways:
+
+  foo( "Fred", 35, "m" )
+  foo( "gender" => "m", "name" => "Fred", "age" => 35 )
+  foo( "age" => 35, "gender" => "m", "name" => "Fred" )
+  foo( "m" :named("gender"), 35 :named("age"), "name" => "Fred" )
+
+and any other permutation you can think of as long as you use the named
+argument syntax. Note that any positional parameters must be passed
+before the named parameters. So, the following is allowed:
+
+  .sub main
+    .param int a
+    .param int b :named("age")
+    # ...
+  .end
+
+Whereas the following is not:
+
+  .sub main
+    .param int a :named("name")
+    .param int b # cannot declare positional parameter after a named parameter
+    # ...
+  .end
+
+It's also possible to use named syntax when returning values from
+subroutines. Into the C<.return> command I'll use:
+
+  .return ( "bar" => 20, "foo" => 10)
+
+and when calling the function, I will do:
+
+  ("foo" => $I0, "bar" => $I1) = func()
+
+And C<$I0> will yield 10, and C<$I1> will yield 20, as expected.
+
+=head2 Concluding
+
+To conclude this first article on PIR and to let you test what you
+learned, let me show you how to do input on PASM (hence, also in
+PIR). There is a C<read> opcode to read from standard input.  Just
+pass it a string register or variable where you wish the characters
+read to be placed and the number of characters you wish to read:
+
+  read $S1, 100
+
+This line will read 100 characters (or until the end of the line) and
+put the read string into C<$S1>. In case you need a number, just
+assign the string to the correct register type:
+
+  read $S1, 100
+  $I1 = $S1
+
+With the PIR syntax shown in this article you should be able to start
+writing simple programs. Next article we will look into available
+Polymorphic Containers (PMCs), and how they can be used.
+
+=head2 Author
+
+Alberto Simões
+
+=head2 Thanks
+
+=over 4
+
+=item * Jonathan Scott Duff
+
+=back
+
+=cut
+

Copied: trunk/docs/user/pir/objects.pod (from r37497, trunk/docs/user/pir/pp003-oop.pod)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/docs/user/pir/objects.pod	Mon Mar 16 21:06:48 2009	(r37501, copy of r37497, trunk/docs/user/pir/pp003-oop.pod)
@@ -0,0 +1,404 @@
+# $Id$
+
+=head1 Programming Parrot -- Using objects
+
+Yes, you've read correctly. Parrot has the ability to create
+and manipulate objects (aka, object oriented programming).
+While it may seem strange for a low-level language like
+PIR to have the facility for object oriented programming,
+it makes perfect sense in this particular case. Remember,
+the original goal of Parrot was to be the underlying
+implementation for Perl6, which has object oriented
+features. Parrot's secondary goal is to provide a good
+platform for other dynamic languages such as Python, Ruby,
+PHP, Javascript, etc. and those languages too have the
+ability (if not the requirement) to be object oriented. Thus
+Parrot contains facilities for a manipulating objects so
+that language implementors can easily express the
+appropriate object semantics for their language of interest.
+
+=head2 Namespaces
+
+Before I begin talking about how to create classes and
+instantiate objects, I first need to talk about an
+intimately related subject: namespaces. Namespaces serve a
+twofold purpose, they allow you to group related routines
+together and they allow you to give several subroutines the
+same name but different, domain specific, implementations.
+These characteristics are, oddly enough, similar to the
+basic requirements for a class.
+
+For instance, you may put all of your subroutines dealing
+with people in a C<Person> namespace and all of your
+subroutines dealing with computer programs in the C<Process>
+namespace. Both namespaces may have a subroutine called
+C<run()> but with radically different implementations. Below
+is some code to illustrate this example:
+
+=head3 Example 1:
+
+    .namespace [ "Person" ]
+
+    .sub run
+        say "Run Forrest, Run!"
+    .end
+
+    .namespace [ "Process" ]
+
+    .sub run
+        say "Running process #53"
+    .end
+
+As you might guess, the C<.namespace> directive tells Parrot
+what namespace to group subroutines under.  A namespace ends when
+another C<.namespace> directive changes the namespace or when
+the end of the file is reached. A C<.namespace> directive
+with no names in the brackets changes back to the root namespace.
+
+Perl programmers will recognize that Parrot
+C<.namespace> declarations are just like Perl C<package>
+declarations, albeit with different syntax.
+But there are a few other differences. I'll
+talk more about how Parrot uses namespaces and classes
+together in just a minute.
+
+=head2 PIR with class
+
+Creating classes in Parrot is relatively easy. There are
+opcodes for it. The easiest to start with is C<newclass>;
+just say C<$P0 = newclass 'Foo'> where $P0 is a PMC
+register, and 'Foo' is the name of the class you want to create.
+
+When you wish to instantiate objects that belong to the class
+you've created, it's equally simple.  Just say C<myobj = new
+"Foo"> where C<myobj> is a PMC and "Foo" is the classname you've
+created with C<newclass>.  Here's a simple example:
+
+=head3 Example 2: A classic Dog
+
+    .sub _ :main
+        $P0 = newclass 'Dog'
+        .local pmc spot
+        spot = new 'Dog'
+    .end
+
+You may notice that I didn't use the return value of
+C<newclass>.  That's only because this is a simple example.  :-)
+I'll talk about what to do with the return value of C<newclass>
+a little later. Right now, let's talk about methods.
+
+=head2 Madness ... er, Methods
+
+So now that I've created a C<Dog> class, how do I add methods
+to it?  Remember before when I talked about namespaces?  Well,
+that's the answer. To add methods to a class, you create a
+namespace with the same name as the class and then put your
+subroutines in that namespace. PIR also provides a syntactic
+marker to let everyone know these subroutines are methods. When
+declaring the subroutine, add the C<:method> modifier after the
+subroutine name. Here's a familiar example to anyone who has
+read L<perlboot>.
+
+=head3 Example 3: Barnyard animals
+
+    .namespace [ "Cow" ]
+
+    .sub speak :method
+        print "Moo\n"
+    .end
+
+    .namespace [ "Dog" ]
+
+    .sub speak :method
+        print "Woof\n"
+    .end
+
+    .namespace [ "Pig" ]
+
+    .sub speak :method
+        print "Oink\n"
+    .end
+
+    .namespace []
+
+    .sub _ :main
+        $P0 = newclass "Cow"
+        $P0 = newclass "Dog"
+        $P0 = newclass "Pig"
+
+        .local pmc elsie, fido, porky
+
+        elsie   = new "Cow"
+        fido    = new "Dog"
+        porky   = new "Pig"
+
+        elsie.'speak'()
+        fido.'speak'()
+        porky.'speak'()
+    .end
+
+It's important to note that even though I've declared the
+namespaces and put subroutines in them, this does not
+automatically create classes. The C<newclass> declarations
+tell Parrot to create a class and as a side effect,
+namespaces with the same name as the class may be used to
+store methods for that class.
+
+One thing you may notice about method calls is that the
+method names are quoted. Why is that? If you would have left out
+the quotes, then the identifier is assumed to be a declared
+C<.local> symbol. So, instead of writing:
+
+    elsie.'speak'()
+
+you could also have written:
+
+    .local string speak
+    speak = 'speak'
+    elsie.speak()
+
+Another example of this is shown below.
+
+=head3 Example 4: variable methods
+
+    .namespace [ 'Foo' ]
+
+    .sub foo :method
+        print "foo\n"
+    .end
+
+    .sub bar :method
+        print "bar\n"
+    .end
+
+    .namespace []
+
+    .sub _ :main
+        $P0 = newclass "Foo"
+        .local pmc f
+        f = new "Foo"
+
+        .local string m
+        m = "foo"
+        f.m()
+        m = "bar"
+        f.m()
+    .end
+
+=head2 But where do I store my stuff?
+
+So far I've talked about namespaces and creating classes
+and associating methods with those classes, but what about
+storing data in the class? Remember how the C<newclass>
+opcode returned a PMC that I didn't do anything to/with?
+Well, here's where it's used. The PMC returned from
+C<newclass> is the handle by which you manipulate the class.
+One such manipulation involves class "attributes".  Attributes
+are where you store your class-specific data.
+
+Parrot has several opcodes for manipulating attributes; they
+are: C<addattribute>, C<setattribute>, and C<getattribute>.
+The C<addattribute> opcode lets you add a spot in the class
+for storing a particular value which may be get and set with
+C<getattribute> and C<setattribute> respectively.  The only
+restriction on these values is that currently all
+attributes must be PMCs.
+
+So, say I wanted to give my barnyard animals names (I'll
+illustrate with just one animal and you can infer how to do the
+same for the rest):
+
+=head3 Example 5: Naming my animals
+
+    .namespace [ "Dog" ]
+
+    .sub name :method
+        .local pmc name
+        name = getattribute self, "name"
+        print name
+    .end
+
+    .sub speak :method
+        print "woof"
+    .end
+
+    .namespace []
+
+    .sub _ :main
+        $P0 = newclass "Dog"
+        addattribute $P0, "name"
+
+        .local pmc dog
+        dog = new "Dog"
+        $P0 = new "String"
+        $P0 = "Phideaux"
+        setattribute dog, "name", $P0
+
+        dog.'name'()
+        print " says "
+        dog.'speak'()
+        print "!\n"
+    .end
+
+Whew! There's a lot of new stuff in this code. I'll take them
+starting from the top of the program and working towards the
+bottom.
+
+One of the benefits of tagging your subroutines as methods
+is that they get a PMC named C<self> that represents the
+object they are acting on behalf of. The C<name> method
+takes advantage of this to retrieve the attribute called
+"name" from the C<self> PMC and print it.
+
+Immediately after I create the class called "Dog", I use the
+PMC handle returned from C<newclass> to add an attribute called
+"name" to the class. This just allocates a slot in the class for
+the value, it does nothing more.
+
+Next, I create a new Dog and give it a name. Because
+attributes may only be PMCs, in order to give the Dog a
+name, I first have to create a new String PMC (this is one
+of the PMCs builtin to Parrot) and assign the name I wish
+to give the dog to this PMC. Then I can pass this PMC as a
+parameter to C<setattribute> to give my Dog a name.
+
+Seems kind of complicated, doesn't it? Especially when you think
+about doing this for each animal. Each animal namespace
+would have an identical version of the C<name> method.  For each
+call to C<newclass> I'd need to also call C<addattribute> so
+that all of the animals may have a name.  Each time I wish to
+assign a name to an animal, I'd first need to create a
+C<String> and call C<setattribute> on it. Et cetera.
+
+Surely there's a better way?!?  There is ...
+
+=head2 Inheritance
+
+You saw it coming didn't you? What's object oriented
+programming without inheritance? Parrot has an opcode
+C<subclass> that lets you inherit data and methods from an
+existing class. We can use this ability to create a base
+class called "Animal" that contains the "name" attribute and
+two methods that are common to all animals: C<setname> and
+C<getname> Then, to create new animals, I just inherit from
+the Animal base class like so:
+
+=head3 Example 6: inheriting
+
+    ...
+    $P0 = newclass "Animal"
+    addattribute $P0, "name"
+    $P0 = subclass "Animal", "Cow"
+    $P0 = subclass "Animal", "Dog"
+    $P0 = subclass "Animal", "Pig"
+    ...
+    cow = new 'Cow'
+    cow.'setname'("Elsie")
+    ...
+    cow.'getname'()
+
+Each subclass will contain an attribute called "name" that can be
+used to store the name of the animal.  The C<setname> method
+abstracts out the process of creating a C<String> PMC and
+calling C<setattribute> on it. And finally the C<getname> method
+becomes a wrapper around C<getattribute>.
+
+=head2 Wrapup
+
+I hope this gives you an idea of how to do object oriented
+programming using Parrot. The opcodes illustrated here are what
+any language implementor that targets Parrot would use to
+implement object oriented features in their language. Of course
+there are more opcodes for richer object oriented behavior
+available in Parrot.  This article only covers the basics.  For
+more information see parrot/docs/pdds/pdd15_objects.pod.
+
+At the end of this article is a more complete listing of the
+program that gives my barnyard animals voices. There are
+many improvements that can be made to this code so take this
+opportunity to read and experiment and learn more about OOP
+in Parrot.
+
+=head2 Acknowledgements
+
+=over 4
+
+* Thanks to Randal Schwartz for providing a neat set of
+  examples in L<perlboot> from which this article
+  shamelessly borrows.
+* Thanks to the Parrot people for feedback
+
+=back
+
+=head2 Author
+
+Jonathan Scott Duff
+
+=head3 Example 6: Full barnyard listing
+
+    .namespace [ "Animal" ]
+
+    .sub setname :method
+        .param string name
+        $P0 = new 'String'
+        $P0 = name
+        setattribute self, "name", $P0
+    .end
+
+    .sub getname :method
+        $P0 = getattribute self, "name"
+        print $P0
+    .end
+
+    .sub speak :method
+        .local string name, sound
+        name = self.'getname'()
+        sound = self.'sound'()
+        print name
+        print " says "
+        print sound
+        print "\n"
+    .end
+
+    .namespace [ "Cow" ]
+
+    .sub sound :method
+        .return( "moo" )
+    .end
+
+    .namespace [ "Dog" ]
+
+    .sub sound :method
+        .return( "woof" )
+    .end
+
+    .namespace [ "Pig" ]
+
+    .sub sound :method
+        .return( "oink" )
+    .end
+
+    .namespace []
+
+    .sub _ :main
+        $P0 = newclass "Animal"
+        addattribute $P0, "name"
+        $P0 = subclass "Animal", "Cow"
+        $P0 = subclass "Animal", "Dog"
+        $P0 = subclass "Animal", "Pig"
+
+        .local pmc cow, dog, pig
+
+        cow   = new "Cow"
+        cow.'setname'("Elsie")
+        dog    = new "Dog"
+        dog.'setname'("Snoopy")
+        pig   = new "Pig"
+        pig.'setname'("Porky")
+
+        cow.'speak'()
+        dog.'speak'()
+        pig.'speak'()
+    .end
+
+=cut

Copied: trunk/docs/user/pir/pmcs.pod (from r37497, trunk/docs/user/pir/pp002-pmc.pod)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/docs/user/pir/pmcs.pod	Mon Mar 16 21:06:48 2009	(r37501, copy of r37497, trunk/docs/user/pir/pp002-pmc.pod)
@@ -0,0 +1,348 @@
+# $Id$
+
+=head1 Programming Parrot -- PMCs
+
+=head2 Preliminaries
+
+To run the example code in this article, you'll need to
+obtain a copy of Parrot and build it for your system. For
+information on obtaining Parrot, see
+L<http://www.parrot.org/>. Instructions for compiling
+Parrot are available in the Parrot distribution itself. All
+code examples in this article were tested with Parrot 0.8.1
+
+=head2 A quick review of Parrot
+
+As mentioned by Alberto Manuel Simões in TPR 2.3, Parrot is
+a register-based virtual machine with 4 register types:
+Integer, String, Number and PMC. PIR registers are
+referenced by a C<$> character, a capital letter signifying
+the register type followed by the register number (C<$S15> is
+String register number 15). Parrot programs consist of lines of
+text where each line contains one opcode and its arguments.
+
+Each subroutine will have as many registers
+available as necessary; a simple subroutine will only need
+a few whereas complex subroutines with many calculations will
+need a larger number of registers. This is a fundamental
+difference from the original design of Parrot, in which there
+were 32 registers for each of the built-in types (int, num,
+pmc, string).
+PIR also provides for a more "natural" syntax for opcodes.
+Rather than saying C<set $I1, 0> to assign a zero to the $I1
+register, you may say instead C<$I1 = 0>.
+PIR also provides syntax for easily creating named variables
+and constants, subroutines, passing parameters to subroutines,
+accessing parameters by name, etc.
+
+Now, on to business ...
+
+=head2 What's a PMC?
+
+Integers, strings, and arbitrary floating point numbers are
+common data types in most programming languages, but what's
+a PMC? PMC stands for "Polymorphic Container". PMCs are how
+Parrot handles more complicated structures and behaviors
+(hence the magic :) Some examples of PMC usage would be for
+arrays, hashes, data structures, objects, etc. Anything that
+can't be expressed using just integers, floating point
+numbers and strings can be expressed with a PMC.
+
+Parrot comes with many types of PMC that encapsulate common,
+useful behavior.
+
+Many of the PMC type names give clues as to how they are
+used. Here's a table that gives a short description of
+several interesting and useful PMC types:
+
+    PMC type        Description of PMC
+    --------        ------------------
+    Env             access environment variables
+    Iterator        iterate over aggregates such as arrays or hashes
+    Array           A generic, resizable array
+    Hash            A generic, resizable hash
+    Random          Obtain a random number
+    String          Similar to a string register but in PMC form
+    Integer         Similar to an integer register but in PMC form
+    Float           Similar to a number register but in PMC form
+    Exception       The standard exception mechanism
+    Timer           A timer of course :)
+
+=head2 Your wish is my command line
+
+Before I take a closer look at some of these PMC types,
+let's look at a common thing that people want to know how to
+do -- read command line arguments. The subroutine designated
+as the main program (by the C<:main> pragma) has an
+implicit parameter passed to it that is the command line
+arguments. Since previous examples never had such a
+parameter to the main program, Parrot simply ignored
+whatever was passed on the command line. Now I want Parrot
+to capture the command line so that I can manipulate it. So,
+let's write a program that reads the command line arguments
+and outputs them one per line:
+
+=head3 Example 2: reading command line arguments, take 1
+
+    .sub _ :main
+        .param pmc args
+      loop:
+        unless args goto end_loop           # line 4
+        $S0 = shift args
+        print $S0
+        print "\n"
+        goto loop
+      end_loop:
+    .end
+
+The C<.param> directive tells parrot that I want this
+subroutine to accept a single parameter and that parameter
+is some sort of PMC that I've named C<args>. Since this is
+the main subroutine of my program (as designated by the
+C<:main> modifier to the subroutine), Parrot arranges for
+the C<args> PMC to be an aggregate of some sort that
+contains the command line arguments. We then repeatedly use
+the C<shift> opcode to remove an element from the front of
+C<args> and place it into a string register which I then
+output. When the C<args> PMC is empty, it will evaluate as a
+boolean false and the conditional on line 4 will cause the
+program to end.
+
+One problem with my program is that it's destructive to the
+C<args> PMC. What if I wanted to use the C<args> PMC later
+in the program? One way to do that is to use an integer to
+keep an index into the aggregate and then just print out
+each indexed value.
+
+=head3 Example 3: reading command line arguments, take 2
+
+    .sub _ :main
+        .param pmc args
+        .local int argc
+        argc = args                         # line 4
+        $I0 = 0
+      loop:
+        unless $I0 < argc goto end_loop
+        print $I0
+        print "\t"
+        $S0 = args[$I0]                     # line 10
+        print $S0
+        print "\n"
+        inc $I0
+        goto loop
+      end_loop:
+    .end
+
+Line 4 shows something interesting about aggregates. Similar
+to perl, when you assign an aggregate to an integer thing
+(whether it be a register or local variable, but as was explained
+before, a local variable is in fact just a symbol indicating that
+is mapped to a register), Parrot puts the number of elements in
+the aggregate into the integer thing. (e.g., if you had a PMC that
+held 5 things in C<$P0>, the statement C<$I0 = $P0> assigns 5 to
+the register C<$I0>)
+
+Since I know how many things are in the aggregate, I can
+make a loop that increments a value until it reaches that
+number. Line 10 shows that to index an aggregate, you use
+square brackets just like you would in Perl and many other
+programming languages. Also note that I'm assigning to a
+string register and then printing that register. Why didn't
+I just do C<print args[$I0]> instead? Because this isn't a
+high level language. PIR provides a nicer syntax but it's
+still really low level. Each line of PIR still essentially
+corresponds to one opcode (there are cases in which this is not
+the case, but those will be discussed later).
+So, while there's an opcode to index into an aggregate and
+an opcode to print a string, there is no opcode to do I<both>
+of those things.
+
+BTW, what type of aggregate is the C<args> PMC anyway?
+Another way to use the C<typeof> opcode is to pass it an
+actual PMC:
+
+=head3 Example 4: Typing the C<args> PMC
+
+    .sub _ :main
+        .param pmc args
+        $S0 = typeof args
+        print $S0
+        print "\n"
+    .end
+
+When you run this program it should output
+"ResizableStringArray". If you assign the result of the
+C<typeof> opcode to a string thing, you get the name of the
+PMC type.
+
+=head2 "You are standing in a field of PMCs"
+
+Now, let's get back to that table above. The C<Env> PMC can
+be thought of as a hash where the keys are environment
+variable names and the values are the corresponding
+environment variable values. But where does the actual PMC
+come from? For the command line, the PMC showed up as an
+implicit parameter to the main subroutine. Does C<Env> do
+something similar?
+
+Nope. If you want to access environment variables I<you>
+need to create a PMC of type C<Env>. This is accomplished by
+the C<new> opcode like so: C<$P0 = new 'Env'> After that
+statement, C<$P0> will contain a hash consisting of all of
+the environment variables at that time.
+
+But, both the keys and values the C<Env> hash are strings,
+so how do I iterate over them as I did for the command
+line? We can't do the same as I did with the command line
+and use an integer index into the PMC because the keys are
+strings, not integers. So, how do I do it? The answer is
+another PMC type--C<Iterator>
+
+An C<Iterator> PMC is used, as its name implies, to iterate
+over aggregates. It doesn't care if they are arrays or
+hashes or something else entirely, it just gives you a way
+to walk from one end of the aggregate to the other.
+
+Here's a program that outputs the name and value of all
+environment variables:
+
+=head3 Example 5: output environment
+
+    .sub _ :main
+        .local pmc env, iter
+        .local string key, value
+
+        env  = new 'Env'                    # line 3
+        iter = new 'Iterator', env          # line 4
+      iterloop:
+        unless iter goto iterend
+        key = shift iter                    # line 8
+        value = env[key]
+        print key
+        print ":"
+        print value
+        print "\n"
+        goto iterloop
+      iterend:
+    .end
+
+Lines 3 and 4 create my new PMCs. Line 3 creates a new
+C<Env> PMC which at the moment of its existence contains a
+hash of all of the environment variables currently in the
+environment. Line 4 creates a new C<Iterator> PMC and
+initializes it with the PMC that I wish to iterate over
+(my newly created C<Env> PMC in this case). From that point
+on, I treat the C<Iterator> much the same way I first
+treated the PMC of command line arguments. Test if it's
+"empty" (the iterator has been exhausted) and shift elements
+from the C<Iterator> in order to walk from one end of the
+aggregate to the other. A key difference is however, I'm
+not modifying the original aggregate, just the C<Iterator>
+which can be thrown away or reset so that I can iterate the
+aggregate over and over again or even have two iterators
+iterating the same aggregate simultaneously. For more
+information on iterators, see
+L<parrot/docs/pmc/iterator.pod>
+
+So, to output the environment variables, I use the
+C<Iterator> to walk the keys, and then index each key into
+the C<Env> PMC to get the value associated with that key and
+then output it. Simple. Say ... couldn't I have iterated
+over the command line this same way? Sure!
+
+=head3 Example 6: reading command line arguments, take 3
+
+    .sub _ :main
+        .param pmc args
+        .local pmc cmdline
+        cmdline = new 'Iterator', args
+      loop:
+        unless cmdline goto end_loop
+        $S0 = shift cmdline
+        print $S0
+        print "\n"
+        goto loop
+      end_loop:
+    .end
+
+Notice how this code approaches the simplicity of the
+original that destructively iterated the C<args> PMC. Using
+indexes can quickly become complicated by comparison.
+
+=head2 How do I create my own PMC type?
+
+That's really beyond the scope of this article, but if
+you're really interested in doing so, get a copy of the
+Parrot source and read the file C<docs/vtables.pod>.
+This file outlines the steps you need to take to create
+a new PMC type.
+
+=head2 A few more PMC examples
+
+I'll conclude with a few examples without explanation. I
+encourage you to explore the Parrot source code and
+documentation to find out more about these (and other) PMCs.
+A good place to start is the docs directory in the Parrot
+distribution (parrot/docs)
+
+=head3 Example 7: Output random numbers
+
+    .sub _ :main
+        $P0 = new 'Random'
+        $N0 = $P0
+        print $N0
+        print "\n"
+        $N0 = $P0
+        print $N0
+        print "\n"
+    .end
+
+=head3 Example 8: Triggering an exception
+
+    .sub _ :main
+        $P0 = new 'Exception'
+        $P0 = "The sky is falling!"
+        throw $P0
+    .end
+
+=head3 Example 9: Setting a timer
+
+    .include "timer.pasm"                   # for the timer constants
+
+    .sub expired
+       print "Timer has expired!\n"
+    .end
+
+    .sub _ :main
+       $P0 = new 'Timer'
+       $P1 = global "expired"
+
+       $P0[.PARROT_TIMER_HANDLER] = $P1    # call sub in $P1 when timer goes off
+       $P0[.PARROT_TIMER_SEC] = 2          # trigger every 2 seconds
+       $P0[.PARROT_TIMER_REPEAT] = -1      # repeat indefinitely
+       $P0[.PARROT_TIMER_RUNNING] = 1      # start timer immediately
+       global "timer" = $P0                # keep the timer around
+
+       $I0 = 0
+      loop:
+       print $I0
+       print ": running...\n"
+       inc $I0
+       sleep 1                             # wait a second
+       goto loop
+    .end
+
+
+=head2 Author
+
+Jonathan Scott Duff <duff at pobox.com>
+
+=head2 Thanks
+
+=over 4
+
+* Alberto Simões
+
+=back
+
+=cut

Deleted: trunk/docs/user/pir/pp001-intro.pod
==============================================================================
--- trunk/docs/user/pir/pp001-intro.pod	Mon Mar 16 21:06:48 2009	(r37500)
+++ /dev/null	00:00:00 1970	(deleted)
@@ -1,347 +0,0 @@
-# $Id$
-
-# One first version of this article was published on TPR 2.3
-#
-# Please feel free to edit it to suit latest parrot developments,
-# and to be a good starting point for beginners.
-
-=head1 Writing PIR
-
-PIR (Parrot Intermediate Representation) is a way to program the
-parrot virtual machine that is easier to use than PASM (Parrot
-Assembler). PASM notation is like any other assembler-like format and
-can be used directly, but it is more verbose and gives too much power
-to the user. PIR abstracts common operations and conventions into a
-syntax that more closely resembles a high-level language. PIR allows
-the programmer to write code that more naturally expresses their
-intent without worrying about setting up the exact details that PASM
-requires to function properly.
-
-This article will show the basics on programming in PIR. More advanced
-topics will appear in later articles.
-
-=head2 Getting Parrot
-
-In order to test the PIR and PASM code in this article, a parrot virtual
-machine is needed (henceforth just "parrot"). Parrot is available from
-L<http://parrot.org>. Just download the latest release, or checkout
-the current development version from the SVN tree. The programs in this
-article were tested with Parrot 0.8.1.
-
-Parrot is very easy to compile on unix-like and Microsoft Windows
-operating systems: just run C<perl Configure.pl && make> in the root
-directory of the parrot source and, if everything works correctly, a
-C<parrot> executable should appear. At the moment of writing, the
-C<make install> target does not work properly, so in this and other
-articles it is assumed that the parrot executable is invoked from the
-parrot root directory.
-
-If you do not want to compile your own Parrot you can download a pre-compiled
-binary from http://www.parrot.org/source.html.
-
-=head2 Parrot Virtual Machine overview
-
-Before we get started with the examples, here's a quick overview of
-parrot's architecture.
-
-Parrot is a register-based virtual machine. It provides 4 types of
-registers. The register types are:
-
-=over 4
-
-=item I - integer
-
-=item N - floating point
-
-=item S - string
-
-=item P - polymorphic container (PMC)
-
-=back
-
-In order to designate a register in PASM, use the character indicating
-the type (C<I>, C<N>, C<S> or C<P>) and the register number. For instance,
-in order to use register 10 of type integer, you'd write C<I10>. In this
-series of articles, we will mainly focus on programming PIR.
-
-In PIR, you would type the C<$> character in front of the register, to
-indicate a I<virtual> register. For instance, the integer registers are
-C<$I0>, C<$I1> and so on. The PMC registers hold arbitrary data objects
-and are parrot's mechanism for implementing more complex behavior than the
-ones that can be expressed using the other 3 register types alone.
-
-A virtual register is mapped to an actual register by the register allocator.
-You can use as many registers as you want, and the register allocator will
-allocate them as needed.
-
-PMCs will be covered in more detail in a future article. Examples in
-this article will focus on the first 3 register types.
-
-=head2 Simple Operators
-
-Let me start with a simple and typical example:
-
-  .sub main :main
-       print "hello world\n"
-  .end
-
-To run it, save the code in a C<hello.pir> file and pass it to the
-parrot virtual machine:
-
-   ./parrot hello.pir
-
-Note that I am using a relative path to parrot given that I didn't
-install it into the system.
-
-The keywords starting with a dot (C<.sub> and C<.end>) are PIR directives.
-They are used together to define subroutines. After the C<.sub> keyword
-I use the name of the subroutine. The keyword that starts with a colon
-(C<:main>) is a pragma that tells parrot that this is the main body of the
-program and that it should start by executing this subroutine.
-By the way, I could use C<.sub foo :main> and Parrot will use the C<foo>
-subroutine as the main body of the program. The actual name of the
-subroutine does not matter as long as it has the C<:main> pragma. If you
-don't specify the <:main> pragma on any subroutine, then parrot will start
-executing the first subroutine in the source file.
-The full set of pragmas are defined in L<docs/pdds/pdd19_pir.pod>.
-
-Before going into more details about subroutines and calling
-conventions, let's compare some PIR syntax to the equivalent PASM.
-
-If I want to add two integer registers using PASM I would use the
-Parrot C<set> opcode to put values into registers, and the C<add>
-opcode to add them, like this:
-
-   set $I1, 5
-   set $I2, 3
-   add $I0, $I1, $I2   # $I0 yields 5+3
-
-PIR includes infix operators for these common opcodes. I could write
-this same code as
-
-   $I1 = 5
-   $I2 = 3
-   $I0 = $I1 + $I2
-
-There are the four arithmetic operators as you should be expecting, as
-well as the six different comparison operators, which return a boolean
-value:
-
-   $I1 = 5
-   $I2 = 3
-   $I0 = $I1 <= $I2   # $I0 yields 0 (false)
-
-I can also use the short accumulation-like operators, like C<+=>.
-
-Another PIR perk is that local variable names may be declared and used
-instead of register names. For that I just need to declare the
-variable using the C<.local> keyword with any of the four data
-types available on PIR: C<int>, C<string>, C<num> and C<pmc>:
-
-   .local int size
-   size = 5
-
-Note that all registers, both numbered and named, are consolidated by
-the Parrot register allocator, assigning these "virtual registers" to
-actual registers as needed.  The register allocator even coalesces two
-virtual names onto the same physical register when it can
-prove that they have non-overlapping lifetimes, so there is no need to
-be stingy with register names.  To see the actual registers used, use
-C<pbc_disassemble> on the C<*.pbc> output. You can generate a Parrot
-Byte Code (PBC) file as follows:
-
-   ./parrot -o foo.pbc --output-pbc foo.pir
-
-Then, use C<pbc_disassemble> in order to disassemble it:
-
-   ./pbc_disassemble foo.pbc
-
-=head2 Branching
-
-Another simplification of PASM are branches. Basically, when I want to
-test a condition and jump to another place in the code, I would write
-the following PASM code:
-
-   le $I1, $I2, LESS_EQ
-
-Meaning, if C<$I1> is less or equal than C<$I2>, jump to label
-C<LESS_EQ>. In PIR I would write it in a more legible way:
-
-   if $I1 <= $I2 goto LESS_EQ
-
-PIR includes the C<unless> keyword as well.
-
-=head2 Calling Functions
-
-Subroutines can easily be created using the C<.sub> keyword shown
-before. If you do not need parameters, it is just as simple as I show in
-the following code:
-
-  .sub main :main
-     hello()
-  .end
-
-  .sub hello
-    print "Hello World\n"
-  .end
-
-Now, I want to make my C<hello> subroutine a little more useful, such
-that I can greet other people. For that I will use the C<.param>
-keyword to define the parameters C<hello> can handle:
-
-  .sub main :main
-     hello("leo")
-     hello("chip")
-  .end
-
-  .sub hello
-     .param string person
-     print "Hello "
-     print person
-     print "\n"
-  .end
-
-If I need more parameters I just need to add more C<.param> lines.
-
-To return values from PIR subroutines I use the C<.return> keyword,
-followed by one or more arguments, just like this:
-
-  .return (10, 20, 30)
-
-The calling subroutine can accept these values. If you want to retrieve
-only one value (or only the first value, in case multiple values are
-returned), write this:
-
-  $I0 = compute_it($I8, $I9)
-
-To accept multiple values from such a function, use a parenthesized
-results list:
-
-  ($I1, $I2, $I3) = compute_it($I8, $I9)
-
-=head2 Factorial Example
-
-Now, for a little more complicated example, let me show how I would
-code Factorial subroutine:
-
-  .sub main :main
-     $I1 = factorial(5)
-     print $I1
-     print "\n"
-  .end
-
-  .sub factorial
-     .param int i
-     if i > 1 goto recur
-     .return (1)
-  recur:
-     $I1 = i - 1
-     $I2 = factorial($I1)
-     $I2 *= i
-     .return ($I2)
-  .end
-
-This example also shows that PIR subroutines may be recursive just as in
-a high-level language.
-
-=head2 Named Arguments
-
-As some other languages as Python and Perl support named arguments,
-PIR supports them as well.
-
-As before, I need to use C<.param> for each named argument, but you need to
-specify a flag indicating the parameter is named:
-
-  .sub func
-    .param int a :named("foo")
-
-The subroutine will receive an integer named "foo", and inside of the
-subroutine that integer will be known as "a".
-
-When calling the function, I need to pass the names of the
-arguments. For that there are two syntaxes:
-
-  func( 10 :named("foo") )    # or
-  func( "foo" => 10 )
-
-Note that with named arguments, you may rearrange the order of your
-parameters at will.
-
-  .sub foo
-    .param string "name"    => a
-    .param int    "age"     => b
-    .param string "gender"  => c
-    # ...
-  .end
-
-This subroutine may be called in any of the following ways:
-
-  foo( "Fred", 35, "m" )
-  foo( "gender" => "m", "name" => "Fred", "age" => 35 )
-  foo( "age" => 35, "gender" => "m", "name" => "Fred" )
-  foo( "m" :named("gender"), 35 :named("age"), "name" => "Fred" )
-
-and any other permutation you can think of as long as you use the named
-argument syntax. Note that any positional parameters must be passed
-before the named parameters. So, the following is allowed:
-
-  .sub main
-    .param int a
-    .param int b :named("age")
-    # ...
-  .end
-
-Whereas the following is not:
-
-  .sub main
-    .param int a :named("name")
-    .param int b # cannot declare positional parameter after a named parameter
-    # ...
-  .end
-
-It's also possible to use named syntax when returning values from
-subroutines. Into the C<.return> command I'll use:
-
-  .return ( "bar" => 20, "foo" => 10)
-
-and when calling the function, I will do:
-
-  ("foo" => $I0, "bar" => $I1) = func()
-
-And C<$I0> will yield 10, and C<$I1> will yield 20, as expected.
-
-=head2 Concluding
-
-To conclude this first article on PIR and to let you test what you
-learned, let me show you how to do input on PASM (hence, also in
-PIR). There is a C<read> opcode to read from standard input.  Just
-pass it a string register or variable where you wish the characters
-read to be placed and the number of characters you wish to read:
-
-  read $S1, 100
-
-This line will read 100 characters (or until the end of the line) and
-put the read string into C<$S1>. In case you need a number, just
-assign the string to the correct register type:
-
-  read $S1, 100
-  $I1 = $S1
-
-With the PIR syntax shown in this article you should be able to start
-writing simple programs. Next article we will look into available
-Polymorphic Containers (PMCs), and how they can be used.
-
-=head2 Author
-
-Alberto Simões
-
-=head2 Thanks
-
-=over 4
-
-=item * Jonathan Scott Duff
-
-=back
-
-=cut
-

Deleted: trunk/docs/user/pir/pp002-pmc.pod
==============================================================================
--- trunk/docs/user/pir/pp002-pmc.pod	Mon Mar 16 21:06:48 2009	(r37500)
+++ /dev/null	00:00:00 1970	(deleted)
@@ -1,348 +0,0 @@
-# $Id$
-
-=head1 Programming Parrot -- PMCs
-
-=head2 Preliminaries
-
-To run the example code in this article, you'll need to
-obtain a copy of Parrot and build it for your system. For
-information on obtaining Parrot, see
-L<http://www.parrot.org/>. Instructions for compiling
-Parrot are available in the Parrot distribution itself. All
-code examples in this article were tested with Parrot 0.8.1
-
-=head2 A quick review of Parrot
-
-As mentioned by Alberto Manuel Simões in TPR 2.3, Parrot is
-a register-based virtual machine with 4 register types:
-Integer, String, Number and PMC. PIR registers are
-referenced by a C<$> character, a capital letter signifying
-the register type followed by the register number (C<$S15> is
-String register number 15). Parrot programs consist of lines of
-text where each line contains one opcode and its arguments.
-
-Each subroutine will have as many registers
-available as necessary; a simple subroutine will only need
-a few whereas complex subroutines with many calculations will
-need a larger number of registers. This is a fundamental
-difference from the original design of Parrot, in which there
-were 32 registers for each of the built-in types (int, num,
-pmc, string).
-PIR also provides for a more "natural" syntax for opcodes.
-Rather than saying C<set $I1, 0> to assign a zero to the $I1
-register, you may say instead C<$I1 = 0>.
-PIR also provides syntax for easily creating named variables
-and constants, subroutines, passing parameters to subroutines,
-accessing parameters by name, etc.
-
-Now, on to business ...
-
-=head2 What's a PMC?
-
-Integers, strings, and arbitrary floating point numbers are
-common data types in most programming languages, but what's
-a PMC? PMC stands for "Polymorphic Container". PMCs are how
-Parrot handles more complicated structures and behaviors
-(hence the magic :) Some examples of PMC usage would be for
-arrays, hashes, data structures, objects, etc. Anything that
-can't be expressed using just integers, floating point
-numbers and strings can be expressed with a PMC.
-
-Parrot comes with many types of PMC that encapsulate common,
-useful behavior.
-
-Many of the PMC type names give clues as to how they are
-used. Here's a table that gives a short description of
-several interesting and useful PMC types:
-
-    PMC type        Description of PMC
-    --------        ------------------
-    Env             access environment variables
-    Iterator        iterate over aggregates such as arrays or hashes
-    Array           A generic, resizable array
-    Hash            A generic, resizable hash
-    Random          Obtain a random number
-    String          Similar to a string register but in PMC form
-    Integer         Similar to an integer register but in PMC form
-    Float           Similar to a number register but in PMC form
-    Exception       The standard exception mechanism
-    Timer           A timer of course :)
-
-=head2 Your wish is my command line
-
-Before I take a closer look at some of these PMC types,
-let's look at a common thing that people want to know how to
-do -- read command line arguments. The subroutine designated
-as the main program (by the C<:main> pragma) has an
-implicit parameter passed to it that is the command line
-arguments. Since previous examples never had such a
-parameter to the main program, Parrot simply ignored
-whatever was passed on the command line. Now I want Parrot
-to capture the command line so that I can manipulate it. So,
-let's write a program that reads the command line arguments
-and outputs them one per line:
-
-=head3 Example 2: reading command line arguments, take 1
-
-    .sub _ :main
-        .param pmc args
-      loop:
-        unless args goto end_loop           # line 4
-        $S0 = shift args
-        print $S0
-        print "\n"
-        goto loop
-      end_loop:
-    .end
-
-The C<.param> directive tells parrot that I want this
-subroutine to accept a single parameter and that parameter
-is some sort of PMC that I've named C<args>. Since this is
-the main subroutine of my program (as designated by the
-C<:main> modifier to the subroutine), Parrot arranges for
-the C<args> PMC to be an aggregate of some sort that
-contains the command line arguments. We then repeatedly use
-the C<shift> opcode to remove an element from the front of
-C<args> and place it into a string register which I then
-output. When the C<args> PMC is empty, it will evaluate as a
-boolean false and the conditional on line 4 will cause the
-program to end.
-
-One problem with my program is that it's destructive to the
-C<args> PMC. What if I wanted to use the C<args> PMC later
-in the program? One way to do that is to use an integer to
-keep an index into the aggregate and then just print out
-each indexed value.
-
-=head3 Example 3: reading command line arguments, take 2
-
-    .sub _ :main
-        .param pmc args
-        .local int argc
-        argc = args                         # line 4
-        $I0 = 0
-      loop:
-        unless $I0 < argc goto end_loop
-        print $I0
-        print "\t"
-        $S0 = args[$I0]                     # line 10
-        print $S0
-        print "\n"
-        inc $I0
-        goto loop
-      end_loop:
-    .end
-
-Line 4 shows something interesting about aggregates. Similar
-to perl, when you assign an aggregate to an integer thing
-(whether it be a register or local variable, but as was explained
-before, a local variable is in fact just a symbol indicating that
-is mapped to a register), Parrot puts the number of elements in
-the aggregate into the integer thing. (e.g., if you had a PMC that
-held 5 things in C<$P0>, the statement C<$I0 = $P0> assigns 5 to
-the register C<$I0>)
-
-Since I know how many things are in the aggregate, I can
-make a loop that increments a value until it reaches that
-number. Line 10 shows that to index an aggregate, you use
-square brackets just like you would in Perl and many other
-programming languages. Also note that I'm assigning to a
-string register and then printing that register. Why didn't
-I just do C<print args[$I0]> instead? Because this isn't a
-high level language. PIR provides a nicer syntax but it's
-still really low level. Each line of PIR still essentially
-corresponds to one opcode (there are cases in which this is not
-the case, but those will be discussed later).
-So, while there's an opcode to index into an aggregate and
-an opcode to print a string, there is no opcode to do I<both>
-of those things.
-
-BTW, what type of aggregate is the C<args> PMC anyway?
-Another way to use the C<typeof> opcode is to pass it an
-actual PMC:
-
-=head3 Example 4: Typing the C<args> PMC
-
-    .sub _ :main
-        .param pmc args
-        $S0 = typeof args
-        print $S0
-        print "\n"
-    .end
-
-When you run this program it should output
-"ResizableStringArray". If you assign the result of the
-C<typeof> opcode to a string thing, you get the name of the
-PMC type.
-
-=head2 "You are standing in a field of PMCs"
-
-Now, let's get back to that table above. The C<Env> PMC can
-be thought of as a hash where the keys are environment
-variable names and the values are the corresponding
-environment variable values. But where does the actual PMC
-come from? For the command line, the PMC showed up as an
-implicit parameter to the main subroutine. Does C<Env> do
-something similar?
-
-Nope. If you want to access environment variables I<you>
-need to create a PMC of type C<Env>. This is accomplished by
-the C<new> opcode like so: C<$P0 = new 'Env'> After that
-statement, C<$P0> will contain a hash consisting of all of
-the environment variables at that time.
-
-But, both the keys and values the C<Env> hash are strings,
-so how do I iterate over them as I did for the command
-line? We can't do the same as I did with the command line
-and use an integer index into the PMC because the keys are
-strings, not integers. So, how do I do it? The answer is
-another PMC type--C<Iterator>
-
-An C<Iterator> PMC is used, as its name implies, to iterate
-over aggregates. It doesn't care if they are arrays or
-hashes or something else entirely, it just gives you a way
-to walk from one end of the aggregate to the other.
-
-Here's a program that outputs the name and value of all
-environment variables:
-
-=head3 Example 5: output environment
-
-    .sub _ :main
-        .local pmc env, iter
-        .local string key, value
-
-        env  = new 'Env'                    # line 3
-        iter = new 'Iterator', env          # line 4
-      iterloop:
-        unless iter goto iterend
-        key = shift iter                    # line 8
-        value = env[key]
-        print key
-        print ":"
-        print value
-        print "\n"
-        goto iterloop
-      iterend:
-    .end
-
-Lines 3 and 4 create my new PMCs. Line 3 creates a new
-C<Env> PMC which at the moment of its existence contains a
-hash of all of the environment variables currently in the
-environment. Line 4 creates a new C<Iterator> PMC and
-initializes it with the PMC that I wish to iterate over
-(my newly created C<Env> PMC in this case). From that point
-on, I treat the C<Iterator> much the same way I first
-treated the PMC of command line arguments. Test if it's
-"empty" (the iterator has been exhausted) and shift elements
-from the C<Iterator> in order to walk from one end of the
-aggregate to the other. A key difference is however, I'm
-not modifying the original aggregate, just the C<Iterator>
-which can be thrown away or reset so that I can iterate the
-aggregate over and over again or even have two iterators
-iterating the same aggregate simultaneously. For more
-information on iterators, see
-L<parrot/docs/pmc/iterator.pod>
-
-So, to output the environment variables, I use the
-C<Iterator> to walk the keys, and then index each key into
-the C<Env> PMC to get the value associated with that key and
-then output it. Simple. Say ... couldn't I have iterated
-over the command line this same way? Sure!
-
-=head3 Example 6: reading command line arguments, take 3
-
-    .sub _ :main
-        .param pmc args
-        .local pmc cmdline
-        cmdline = new 'Iterator', args
-      loop:
-        unless cmdline goto end_loop
-        $S0 = shift cmdline
-        print $S0
-        print "\n"
-        goto loop
-      end_loop:
-    .end
-
-Notice how this code approaches the simplicity of the
-original that destructively iterated the C<args> PMC. Using
-indexes can quickly become complicated by comparison.
-
-=head2 How do I create my own PMC type?
-
-That's really beyond the scope of this article, but if
-you're really interested in doing so, get a copy of the
-Parrot source and read the file C<docs/vtables.pod>.
-This file outlines the steps you need to take to create
-a new PMC type.
-
-=head2 A few more PMC examples
-
-I'll conclude with a few examples without explanation. I
-encourage you to explore the Parrot source code and
-documentation to find out more about these (and other) PMCs.
-A good place to start is the docs directory in the Parrot
-distribution (parrot/docs)
-
-=head3 Example 7: Output random numbers
-
-    .sub _ :main
-        $P0 = new 'Random'
-        $N0 = $P0
-        print $N0
-        print "\n"
-        $N0 = $P0
-        print $N0
-        print "\n"
-    .end
-
-=head3 Example 8: Triggering an exception
-
-    .sub _ :main
-        $P0 = new 'Exception'
-        $P0 = "The sky is falling!"
-        throw $P0
-    .end
-
-=head3 Example 9: Setting a timer
-
-    .include "timer.pasm"                   # for the timer constants
-
-    .sub expired
-       print "Timer has expired!\n"
-    .end
-
-    .sub _ :main
-       $P0 = new 'Timer'
-       $P1 = global "expired"
-
-       $P0[.PARROT_TIMER_HANDLER] = $P1    # call sub in $P1 when timer goes off
-       $P0[.PARROT_TIMER_SEC] = 2          # trigger every 2 seconds
-       $P0[.PARROT_TIMER_REPEAT] = -1      # repeat indefinitely
-       $P0[.PARROT_TIMER_RUNNING] = 1      # start timer immediately
-       global "timer" = $P0                # keep the timer around
-
-       $I0 = 0
-      loop:
-       print $I0
-       print ": running...\n"
-       inc $I0
-       sleep 1                             # wait a second
-       goto loop
-    .end
-
-
-=head2 Author
-
-Jonathan Scott Duff <duff at pobox.com>
-
-=head2 Thanks
-
-=over 4
-
-* Alberto Simões
-
-=back
-
-=cut

Deleted: trunk/docs/user/pir/pp003-oop.pod
==============================================================================
--- trunk/docs/user/pir/pp003-oop.pod	Mon Mar 16 21:06:48 2009	(r37500)
+++ /dev/null	00:00:00 1970	(deleted)
@@ -1,404 +0,0 @@
-# $Id$
-
-=head1 Programming Parrot -- Using objects
-
-Yes, you've read correctly. Parrot has the ability to create
-and manipulate objects (aka, object oriented programming).
-While it may seem strange for a low-level language like
-PIR to have the facility for object oriented programming,
-it makes perfect sense in this particular case. Remember,
-the original goal of Parrot was to be the underlying
-implementation for Perl6, which has object oriented
-features. Parrot's secondary goal is to provide a good
-platform for other dynamic languages such as Python, Ruby,
-PHP, Javascript, etc. and those languages too have the
-ability (if not the requirement) to be object oriented. Thus
-Parrot contains facilities for a manipulating objects so
-that language implementors can easily express the
-appropriate object semantics for their language of interest.
-
-=head2 Namespaces
-
-Before I begin talking about how to create classes and
-instantiate objects, I first need to talk about an
-intimately related subject: namespaces. Namespaces serve a
-twofold purpose, they allow you to group related routines
-together and they allow you to give several subroutines the
-same name but different, domain specific, implementations.
-These characteristics are, oddly enough, similar to the
-basic requirements for a class.
-
-For instance, you may put all of your subroutines dealing
-with people in a C<Person> namespace and all of your
-subroutines dealing with computer programs in the C<Process>
-namespace. Both namespaces may have a subroutine called
-C<run()> but with radically different implementations. Below
-is some code to illustrate this example:
-
-=head3 Example 1:
-
-    .namespace [ "Person" ]
-
-    .sub run
-        say "Run Forrest, Run!"
-    .end
-
-    .namespace [ "Process" ]
-
-    .sub run
-        say "Running process #53"
-    .end
-
-As you might guess, the C<.namespace> directive tells Parrot
-what namespace to group subroutines under.  A namespace ends when
-another C<.namespace> directive changes the namespace or when
-the end of the file is reached. A C<.namespace> directive
-with no names in the brackets changes back to the root namespace.
-
-Perl programmers will recognize that Parrot
-C<.namespace> declarations are just like Perl C<package>
-declarations, albeit with different syntax.
-But there are a few other differences. I'll
-talk more about how Parrot uses namespaces and classes
-together in just a minute.
-
-=head2 PIR with class
-
-Creating classes in Parrot is relatively easy. There are
-opcodes for it. The easiest to start with is C<newclass>;
-just say C<$P0 = newclass 'Foo'> where $P0 is a PMC
-register, and 'Foo' is the name of the class you want to create.
-
-When you wish to instantiate objects that belong to the class
-you've created, it's equally simple.  Just say C<myobj = new
-"Foo"> where C<myobj> is a PMC and "Foo" is the classname you've
-created with C<newclass>.  Here's a simple example:
-
-=head3 Example 2: A classic Dog
-
-    .sub _ :main
-        $P0 = newclass 'Dog'
-        .local pmc spot
-        spot = new 'Dog'
-    .end
-
-You may notice that I didn't use the return value of
-C<newclass>.  That's only because this is a simple example.  :-)
-I'll talk about what to do with the return value of C<newclass>
-a little later. Right now, let's talk about methods.
-
-=head2 Madness ... er, Methods
-
-So now that I've created a C<Dog> class, how do I add methods
-to it?  Remember before when I talked about namespaces?  Well,
-that's the answer. To add methods to a class, you create a
-namespace with the same name as the class and then put your
-subroutines in that namespace. PIR also provides a syntactic
-marker to let everyone know these subroutines are methods. When
-declaring the subroutine, add the C<:method> modifier after the
-subroutine name. Here's a familiar example to anyone who has
-read L<perlboot>.
-
-=head3 Example 3: Barnyard animals
-
-    .namespace [ "Cow" ]
-
-    .sub speak :method
-        print "Moo\n"
-    .end
-
-    .namespace [ "Dog" ]
-
-    .sub speak :method
-        print "Woof\n"
-    .end
-
-    .namespace [ "Pig" ]
-
-    .sub speak :method
-        print "Oink\n"
-    .end
-
-    .namespace []
-
-    .sub _ :main
-        $P0 = newclass "Cow"
-        $P0 = newclass "Dog"
-        $P0 = newclass "Pig"
-
-        .local pmc elsie, fido, porky
-
-        elsie   = new "Cow"
-        fido    = new "Dog"
-        porky   = new "Pig"
-
-        elsie.'speak'()
-        fido.'speak'()
-        porky.'speak'()
-    .end
-
-It's important to note that even though I've declared the
-namespaces and put subroutines in them, this does not
-automatically create classes. The C<newclass> declarations
-tell Parrot to create a class and as a side effect,
-namespaces with the same name as the class may be used to
-store methods for that class.
-
-One thing you may notice about method calls is that the
-method names are quoted. Why is that? If you would have left out
-the quotes, then the identifier is assumed to be a declared
-C<.local> symbol. So, instead of writing:
-
-    elsie.'speak'()
-
-you could also have written:
-
-    .local string speak
-    speak = 'speak'
-    elsie.speak()
-
-Another example of this is shown below.
-
-=head3 Example 4: variable methods
-
-    .namespace [ 'Foo' ]
-
-    .sub foo :method
-        print "foo\n"
-    .end
-
-    .sub bar :method
-        print "bar\n"
-    .end
-
-    .namespace []
-
-    .sub _ :main
-        $P0 = newclass "Foo"
-        .local pmc f
-        f = new "Foo"
-
-        .local string m
-        m = "foo"
-        f.m()
-        m = "bar"
-        f.m()
-    .end
-
-=head2 But where do I store my stuff?
-
-So far I've talked about namespaces and creating classes
-and associating methods with those classes, but what about
-storing data in the class? Remember how the C<newclass>
-opcode returned a PMC that I didn't do anything to/with?
-Well, here's where it's used. The PMC returned from
-C<newclass> is the handle by which you manipulate the class.
-One such manipulation involves class "attributes".  Attributes
-are where you store your class-specific data.
-
-Parrot has several opcodes for manipulating attributes; they
-are: C<addattribute>, C<setattribute>, and C<getattribute>.
-The C<addattribute> opcode lets you add a spot in the class
-for storing a particular value which may be get and set with
-C<getattribute> and C<setattribute> respectively.  The only
-restriction on these values is that currently all
-attributes must be PMCs.
-
-So, say I wanted to give my barnyard animals names (I'll
-illustrate with just one animal and you can infer how to do the
-same for the rest):
-
-=head3 Example 5: Naming my animals
-
-    .namespace [ "Dog" ]
-
-    .sub name :method
-        .local pmc name
-        name = getattribute self, "name"
-        print name
-    .end
-
-    .sub speak :method
-        print "woof"
-    .end
-
-    .namespace []
-
-    .sub _ :main
-        $P0 = newclass "Dog"
-        addattribute $P0, "name"
-
-        .local pmc dog
-        dog = new "Dog"
-        $P0 = new "String"
-        $P0 = "Phideaux"
-        setattribute dog, "name", $P0
-
-        dog.'name'()
-        print " says "
-        dog.'speak'()
-        print "!\n"
-    .end
-
-Whew! There's a lot of new stuff in this code. I'll take them
-starting from the top of the program and working towards the
-bottom.
-
-One of the benefits of tagging your subroutines as methods
-is that they get a PMC named C<self> that represents the
-object they are acting on behalf of. The C<name> method
-takes advantage of this to retrieve the attribute called
-"name" from the C<self> PMC and print it.
-
-Immediately after I create the class called "Dog", I use the
-PMC handle returned from C<newclass> to add an attribute called
-"name" to the class. This just allocates a slot in the class for
-the value, it does nothing more.
-
-Next, I create a new Dog and give it a name. Because
-attributes may only be PMCs, in order to give the Dog a
-name, I first have to create a new String PMC (this is one
-of the PMCs builtin to Parrot) and assign the name I wish
-to give the dog to this PMC. Then I can pass this PMC as a
-parameter to C<setattribute> to give my Dog a name.
-
-Seems kind of complicated, doesn't it? Especially when you think
-about doing this for each animal. Each animal namespace
-would have an identical version of the C<name> method.  For each
-call to C<newclass> I'd need to also call C<addattribute> so
-that all of the animals may have a name.  Each time I wish to
-assign a name to an animal, I'd first need to create a
-C<String> and call C<setattribute> on it. Et cetera.
-
-Surely there's a better way?!?  There is ...
-
-=head2 Inheritance
-
-You saw it coming didn't you? What's object oriented
-programming without inheritance? Parrot has an opcode
-C<subclass> that lets you inherit data and methods from an
-existing class. We can use this ability to create a base
-class called "Animal" that contains the "name" attribute and
-two methods that are common to all animals: C<setname> and
-C<getname> Then, to create new animals, I just inherit from
-the Animal base class like so:
-
-=head3 Example 6: inheriting
-
-    ...
-    $P0 = newclass "Animal"
-    addattribute $P0, "name"
-    $P0 = subclass "Animal", "Cow"
-    $P0 = subclass "Animal", "Dog"
-    $P0 = subclass "Animal", "Pig"
-    ...
-    cow = new 'Cow'
-    cow.'setname'("Elsie")
-    ...
-    cow.'getname'()
-
-Each subclass will contain an attribute called "name" that can be
-used to store the name of the animal.  The C<setname> method
-abstracts out the process of creating a C<String> PMC and
-calling C<setattribute> on it. And finally the C<getname> method
-becomes a wrapper around C<getattribute>.
-
-=head2 Wrapup
-
-I hope this gives you an idea of how to do object oriented
-programming using Parrot. The opcodes illustrated here are what
-any language implementor that targets Parrot would use to
-implement object oriented features in their language. Of course
-there are more opcodes for richer object oriented behavior
-available in Parrot.  This article only covers the basics.  For
-more information see parrot/docs/pdds/pdd15_objects.pod.
-
-At the end of this article is a more complete listing of the
-program that gives my barnyard animals voices. There are
-many improvements that can be made to this code so take this
-opportunity to read and experiment and learn more about OOP
-in Parrot.
-
-=head2 Acknowledgements
-
-=over 4
-
-* Thanks to Randal Schwartz for providing a neat set of
-  examples in L<perlboot> from which this article
-  shamelessly borrows.
-* Thanks to the Parrot people for feedback
-
-=back
-
-=head2 Author
-
-Jonathan Scott Duff
-
-=head3 Example 6: Full barnyard listing
-
-    .namespace [ "Animal" ]
-
-    .sub setname :method
-        .param string name
-        $P0 = new 'String'
-        $P0 = name
-        setattribute self, "name", $P0
-    .end
-
-    .sub getname :method
-        $P0 = getattribute self, "name"
-        print $P0
-    .end
-
-    .sub speak :method
-        .local string name, sound
-        name = self.'getname'()
-        sound = self.'sound'()
-        print name
-        print " says "
-        print sound
-        print "\n"
-    .end
-
-    .namespace [ "Cow" ]
-
-    .sub sound :method
-        .return( "moo" )
-    .end
-
-    .namespace [ "Dog" ]
-
-    .sub sound :method
-        .return( "woof" )
-    .end
-
-    .namespace [ "Pig" ]
-
-    .sub sound :method
-        .return( "oink" )
-    .end
-
-    .namespace []
-
-    .sub _ :main
-        $P0 = newclass "Animal"
-        addattribute $P0, "name"
-        $P0 = subclass "Animal", "Cow"
-        $P0 = subclass "Animal", "Dog"
-        $P0 = subclass "Animal", "Pig"
-
-        .local pmc cow, dog, pig
-
-        cow   = new "Cow"
-        cow.'setname'("Elsie")
-        dog    = new "Dog"
-        dog.'setname'("Snoopy")
-        pig   = new "Pig"
-        pig.'setname'("Porky")
-
-        cow.'speak'()
-        dog.'speak'()
-        pig.'speak'()
-    .end
-
-=cut


More information about the parrot-commits mailing list