Sophie

Sophie

distrib > Fedora > 15 > i386 > by-pkgid > 1e007a96761035f261351a68e7601417 > files > 206

parrot-docs-3.6.0-2.fc15.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Parrot  - Programming Parrot &#45;&#45; PMCs</title>
        <link rel="stylesheet" type="text/css"
            href="../../../../resources/parrot.css"
            media="all">
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    </head>
    <body>
        <div id="wrapper">
            <div id="header">

                <a href="http://www.parrot.org">
                <img border=0 src="../../../../resources/parrot_logo.png" id="logo" alt="parrot">
                </a>
            </div> <!-- "header" -->
            <div id="divider"></div>
            <div id="mainbody">
                <div id="breadcrumb">
                    <a href="../../../../html/index.html">Home</a> &raquo; <a href="../../../../html/developer.html">Developer Documentation</a> &raquo; Programming Parrot &#45;&#45; PMCs
                </div>

<h1><a name="Programming_Parrot_&#45;&#45;_PMCs"
>Programming Parrot &#45;&#45; PMCs</a></h1>

<h2><a name="Preliminaries"
>Preliminaries</a></h2>

<p>To run the example code in this article,
you&#39;ll need to obtain a copy of Parrot and build it for your system.
For information on obtaining Parrot,
see <a href='http://www.parrot.org/'><a href="http://www.parrot.org/">http://www.parrot.org/</a></a>.
Instructions for compiling Parrot are available in the Parrot distribution itself.
All code examples in this article were tested with Parrot 0.8.1</p>

<h2><a name="A_quick_review_of_Parrot"
>A quick review of Parrot</a></h2>

<p>As mentioned by Alberto Manuel Sim&#195;&#181;es in TPR 2.3,
Parrot is a register&#45;based virtual machine with 4 register types: Integer,
String,
Number and PMC.
PIR registers are referenced by a <code>$</code> character,
a capital letter signifying the register type followed by the register number (<code>$S15</code> is String register number 15).
Parrot programs consist of lines of text where each line contains one opcode and its arguments.</p>

<p>Each subroutine will have as many registers available of each basic type (int,
num,
string,
and pmc) 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 hardware CPUs (and the original design of Parrot),
in which there are a fixed number of registers.</p>

<p>PIR also provides for a more &#34;natural&#34; syntax for opcodes than the standard assembly language <code>op arg, arg</code> format.
Rather than writing <code>set $I1, 0</code> to assign a zero to the $I1 register,
you may instead write <code>$I1 = 0</code>.
PIR also provides easy syntax for creating named variables and constants,
subroutines,
passing parameters to subroutines,
accessing parameters by name,
etc.</p>

<p>Now,
on to business ...</p>

<h2><a name="What&#39;s_a_PMC?"
>What&#39;s a PMC?</a></h2>

<p>Integers,
strings,
and floating point numbers are common data types in most programming languages,
but what&#39;s a PMC?
PMC stands for &#34;<i>P</i>oly<i>M</i>orphic <i>C</i>ontainer&#34;.
PMCs are how Parrot handles more complicated structures and behaviors,
such as arrays,
hashes,
and objects.
anything that can&#39;t be expressed using just integers,
floating point numbers and strings can be expressed with a PMC.</p>

<p>Parrot comes with many types of PMC that encapsulate common,
useful behavior.</p>

<p>Many of the PMC type names give clues as to how they are used.
Here&#39;s a table that gives a short description of several interesting and useful PMC types:</p>

<pre>    PMC type        Description of PMC
    &#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;        &#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;
    Env             access environment variables
    Iterator        iterate over aggregates such as arrays or hashes
    Array           A generic, resizable array
    Hash            A generic, resizable hash
    String          Similar to a string register but in PMC form
    Integer         Similar to an int register but in PMC form
    Float           Similar to a num register but in PMC form
    Exception       The standard exception mechanism
    Timer           A timer of course :)</pre>

<h2><a name="Your_wish_is_my_command_line"
>Your wish is my command line</a></h2>

<p>Before I take a closer look at some of these PMC types, let&#39;s look at a common thing that people want to know how to do &#45;&#45; read command line arguments. The subroutine designated as the main program (by the <code>:main</code> 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&#39;s write a program that reads the command line arguments and outputs them one per line:</p>

<h3><a name="Example_2:_reading_command_line_arguments,_take_1"
>Example 2: reading command line arguments, take 1</a></h3>
<pre>    .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
</pre>
<p>The <code>.param</code> directive tells parrot that I want this subroutine to accept a single parameter and that parameter is some sort of PMC that I&#39;ve named <code>args</code>. Since this is the main subroutine of my program (as designated by the <code>:main</code> modifier to the subroutine), Parrot arranges for the <code>args</code> PMC to be an aggregate of some sort that contains the command line arguments. We then repeatedly use the <code>shift</code> opcode to remove an element from the front of <code>args</code> and place it into a string register which I then output. When the <code>args</code> PMC is empty, it will evaluate as a boolean false and the conditional on line 4 will cause the program to end.</p>

<p>One problem with my program is that it&#39;s destructive to the <code>args</code> PMC. What if I wanted to use the <code>args</code> 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.</p>

<h3><a name="Example_3:_reading_command_line_arguments,_take_2"
>Example 3: reading command line arguments, take 2</a></h3>
<pre>    .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
</pre>
<p>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 <code>$P0</code>, the statement <code>$I0 = $P0</code> assigns 5 to the register <code>$I0</code>)</p>

<p>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&#39;m assigning to a string register and then printing that register. Why didn&#39;t I just do <code>print args[$I0]</code> instead? Because this isn&#39;t a high level language. PIR provides a nicer syntax but it&#39;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&#39;s an opcode to index into an aggregate and an opcode to print a string, there is no opcode to do <i>both</i> of those things.</p>

<p>BTW, what type of aggregate is the <code>args</code> PMC anyway? Another way to use the <code>typeof</code> opcode is to pass it an actual PMC:</p>

<h3><a name="Example_4:_Typing_the_args_PMC"
>Example 4: Typing the <code>args</code> PMC</a></h3>
<pre>    .sub _ :main
        .param pmc args
        $S0 = typeof args
        print $S0
        print "\n"
    .end
</pre>
<p>When you run this program it should output &#34;ResizableStringArray&#34;. If you assign the result of the <code>typeof</code> opcode to a string thing, you get the name of the PMC type.</p>

<h2><a name="&#34;You_are_standing_in_a_field_of_PMCs&#34;"
>&#34;You are standing in a field of PMCs&#34;</a></h2>

<p>Now, let&#39;s get back to that table above. The <code>Env</code> 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 <code>Env</code> do something similar?</p>

<p>Nope. If you want to access environment variables <i>you</i> need to create a PMC of type <code>Env</code>. This is accomplished by the <code>new</code> opcode like so: <code>$P0 = new &#39;Env&#39;</code> After that statement, <code>$P0</code> will contain a hash consisting of all of the environment variables at that time.</p>

<p>But, both the keys and values the <code>Env</code> hash are strings, so how do I iterate over them as I did for the command line? We can&#39;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&#45;&#45;<code>Iterator</code></p>

<p>An <code>Iterator</code> PMC is used, as its name implies, to iterate over aggregates. It doesn&#39;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.</p>

<p>Here&#39;s a program that outputs the name and value of all environment variables:</p>

<h3><a name="Example_5:_output_environment"
>Example 5: output environment</a></h3>
<pre>    .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
</pre>
<p>Lines 3 and 4 create my new PMCs. Line 3 creates a new <code>Env</code> 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 <code>Iterator</code> PMC and initializes it with the PMC that I wish to iterate over (my newly created <code>Env</code> PMC in this case). From that point on, I treat the <code>Iterator</code> much the same way I first treated the PMC of command line arguments. Test if it&#39;s &#34;empty&#34; (the iterator has been exhausted) and shift elements from the <code>Iterator</code> in order to walk from one end of the aggregate to the other. A key difference is however, I&#39;m not modifying the original aggregate, just the <code>Iterator</code> 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 <a href='TODO#docs%2Fpmc%2Fiterator.pod'>&#34;docs/pmc/iterator.pod&#34; in parrot</a></p>

<p>So, to output the environment variables, I use the <code>Iterator</code> to walk the keys, and then index each key into the <code>Env</code> PMC to get the value associated with that key and then output it. Simple. Say ... couldn&#39;t I have iterated over the command line this same way? Sure!</p>

<h3><a name="Example_6:_reading_command_line_arguments,_take_3"
>Example 6: reading command line arguments, take 3</a></h3>
<pre>    .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
</pre>
<p>Notice how this code approaches the simplicity of the original that destructively iterated the <code>args</code> PMC. Using indexes can quickly become complicated by comparison.</p>

<h2><a name="How_do_I_create_my_own_PMC_type?"
>How do I create my own PMC type?</a></h2>

<p>That&#39;s really beyond the scope of this article, but if you&#39;re really interested in doing so, get a copy of the Parrot source and read the file <code>docs/vtables.pod</code>. This file outlines the steps you need to take to create a new PMC type.</p>

<h2><a name="A_few_more_PMC_examples"
>A few more PMC examples</a></h2>

<p>I&#39;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)</p>

<h3><a name="Example_7:_Triggering_an_exception"
>Example 7: Triggering an exception</a></h3>
<pre>    .sub _ :main
        $P0 = new 'Exception'
        $P0 = "The sky is falling!"
        throw $P0
    .end
</pre>
<h3><a name="Example_8:_Setting_a_timer"
>Example 8: Setting a timer</a></h3>
<pre>    .include 'timer.pasm'                   # for the timer constants

    .sub expired
       say 'Timer has expired!'
       exit 1
    .end

    .sub main :main
       $P0 = new 'Timer'
       $P1 = get_global 'expired'

       $P0[.PARROT_TIMER_HANDLER] = $P1    # call sub in $P1 when timer goes off
       $P0[.PARROT_TIMER_SEC]     = 2      # trigger in 10 seconds
       $P0[.PARROT_TIMER_REPEAT]  = 1      # repeat indefinitely
       $P0[.PARROT_TIMER_RUNNING] = 1      # start timer immediately
       set_global 'timer', $P0             # keep the timer around

       $I0 = 0
    loop:
       print $I0
       say ': running...'
       inc $I0
       sleep 1                             # wait a second
       goto loop
    .end
</pre>
<h2><a name="Author"
>Author</a></h2>

<p>Jonathan Scott Duff &#60;duff@pobox.com&#62;</p>

<h2><a name="Thanks"
>Thanks</a></h2>

<blockquote>
<p>* Alberto Sim&#195;&#181;es</p>
</blockquote>
            </div> <!-- "mainbody" -->
            <div id="divider"></div>
            <div id="footer">
	        Copyright &copy; 2002-2011, Parrot Foundation.
            </div>
        </div> <!-- "wrapper" -->
    </body>
</html>