ThinkGeek - Cool Stuff for Geeks and Technophiles

Monday, July 7, 2008

Parrot magic cookies

In a statically typed language, all variables are given a type when they are created. Take these declarations in C:


int i = 4;
char c = '4';


The variables i and c are not equal, and can't interact with each other. You can't add i and c to get 8, and you can't concatenate i and c to get 44, not without some sort of explicit conversion. (Well, technically you can add or concatenate them, but you'll be surprised by the results.)


int add = i + c;


The value of add is not 8, but 56. When a char variable is accessed as an integer, is is the ascii value (in this case, 52 for the character '4'), which is used.

In a dynamically typed language, that's not the case. Types are inferred. For example, in Perl:


$i = 4;
$c = '4';

$add = $i + $c;
$cat = $i . $c;


In this case, $add = 8 and $cat = 44. An integer or a character will be implicitly converted to the type the operator needs.

The currently most popular virtual machines (the Java VM and Microsoft's CLR) were built for statically typed languages. Parrot, since it will target Perl along with other dynamically typed languages, must have a way to handle implicit type conversion.

Parrot's solution is the PMC -- Parrot Magic Cookie. What can we do with PMCs?


.sub main :main
    $P0 = new Integer
    $P0 = 2
    printout($P0)
    inc $P0
    printout($P0)
    $P0 = "0"
    printout($P0)
    $P1 = new Float
    $P1 = 3.0
    $P0 = $P1
    printout($P0)
    $P0 = $P0 / 2.0
    printout($P0)
    $P0 = "2"
    printout($P0)
    $P0 = $P0 + 2
    printout($P0)
    $P0 = $P0 . "2"
    printout($P0)
    $P0 = $P0 / 8
    printout($P0)
    $P1 = "String"
    $P0 = $P0 + $P1
    printout($P0)
.end

.sub printout
    .param pmc pmcvalue
    .local string pmctype
    pmctype = typeof pmcvalue
    print pmcvalue
    print "\t"
    print pmctype
    print "\n"
.end


$P0 is a PMC register. The value in $P0 can be of any type, and can change its type dynamically based on the current context. The output of this script:


2       Integer
3       Integer
0       String
3       Float
1.5     Float
2       String
4       String
42      String
5.25    String
0       String


The biggest surprise to me was that after the $P0 = "2" assignment, the typeof $P0 remained a string even after arithmetic operations, yet those arithmetic operations accurately updated the value of $P0. The only way to change the PMC type was to explicitly assign a different type. Less of a surprise was that the attempt to add a string to the float value stored in $P0 yielded a value of 0.

PMCs are useful for much more, however, than mere dynamic typing. I'll cover some other uses in later posts.

Labels: , ,