PASM Examples

Are you sure you want PASM?

When you're writing code for parrot, most of the time you will want to be generating PIR code, not PASM. That said, here's some examples!

Hello world!

The first example clearly has to be one that prints out "Hello world!".

  # ``the'' example
  print "Hello world!\n"
  end

When you run this example, you'll get:

Hello world!

Note that the first line of code is a comment, which starts with a '#' character - everything until the end of the line is ignored comment.

Registers

Parrot has four types of registers: integer, float, string, pmc.

The integer, float, and string registers are the basic types used by parrot. PMCs correspond to classes or objects.

One of the few advantages PASM provides over raw bytecode is that it matches the opcode print in PASM to the appropriate print variant. The print opcode that takes a single argument, for example, has eight variants. PASM automatically translated our print to print_sc, or print-string-constant.

Assignment

Assignment between registers is done with the set operator. The following code sets the first integer register to 1, the first number register to 4.2 and the first string register to "Resting"

  set     I1, 1
  set     N1, 4.2
  set     S1, "Resting"
  print   I1
  print   ", "

  print   N1
  print   ", "
  print   S1
  print   "\n"
  end

Prints:

1, 4.200000, Resting

Note how it seems that the print operator is polymorphic - it can print integers, numbers, strings, and string constants. Actually, these are all separate operators (for details look in core.ops) - the assembler decides which to use, keeping our code simple.

The set operator can also copy between registers of the same type.

  set     I1, 10
  set     I3, 30
  set     I1, I3
  print   I1
  print   "\n"

  end

Prints:

30

Remember that the first operand is the destination register, so that last command sets the value of register I1 to the value of register I3. That is, I1 will hold the value 30.

To copy between registers of different types, the set operator is also used:

  set     I1, 10
  set     N1, I1
  set     N2, 4.2
  set     I2, N2
  print   N1
  print   ", "
  print   I2
  print   "\n"
  end

Prints:

10.000000, 4

Note that at the moment there are no operators to convert from or to strings.

Arithmetic opcodes

A number of Parrot opcodes are concerned with arithmetic. The inc and dec opcodes increase/decrease an integer or number register by a constant. If no constant is given, 1 is assumed.

  set     I1, 10
  inc     I1       # I1 is now 11
  inc     I1       # I1 is now 12
  inc     I1       # I1 is now 13
  set     N1, 42.0
  dec     N1       # N1 is now 41.0
  dec     N1       # N1 is now 40.0
  dec     N1       # N1 is now 39.0
  print   I1
  print   ", "
  print   N1
  print   "\n"
  end

Prints:

13, 39.000000

More common arithmetic operators are: add, sub, mul and div, which add, subtract, multiply and divide the contents of registers:

  set     I1, 2
  set     I2, 4
  add     I3, I1, I2  # I3 is now 6 (2+4)
  sub     I3, I1, I2  # I3 is now -2 (2-4)
  mul     I3, I1, I2  # I3 is now 8 (2*4)
  div     I3, I2, I1  # I3 is now 2 (4/2)
  add     I1, I1, 5   # I1 is now 7
  set     N1, 1
  set     N2, 3
  div     N3, N1, N2  # N3 is now 0.333333
  print   I1
  print   ", "
  print   N3
  print   "\n"
  end

Prints:

7, 0.333333

Note that add I1, I1, 5 is also valid: both constants and registers are allowed for the last operand.

There are also other arithmetic operators, such as mod (modulo) and a whole host of transcendental operators (sin, cos, pow, exp, log10...).

String operators

Parrot includes a minimal set of string operators: length (find the length of a string), chopn (remove characters from the end of the string), concat (concatenate one string to the end of another), substr (extract substrings), repeat (repeat a string), index (search for a substring):

  set     S1, "Fourty"
  set     S2, "two"
  length  I1, S2       # I1 is now 3
  print   I1
  print   ", "
  concat  S1, S2       # S1 is "Fourtytwo"

  concat  S3, S1, S2  # S3 is "Fourtytwotwo"
  substr  S2, S1, 0, 4 # S2 is "Four"
  chopn   S1, 3        # S1 is "Fourty"
  print   S1
  print   ", "
  print   S2
  print   ", "

  print   S3
  print   "\n"
  end

Prints:

3, Fourty, Four, Fourtytwotwo

Note that the two-argument concat concatenates the second string onto the end of the first: unlike most other operators is does not create a whole new concatenated string. There is a three-argument version which can do this, however.

Branching and conditionals

Branching is terribly useful in a program. The branch operator is similar to a "goto", and takes a label. Labels are presented at the start of the line with a colon.

  set     S1, "Beautiful"

  branch  CHOIR
EX:
  print   S1
  branch  END
CHOIR:
  set     S2, " plumage!\n"
  concat  S1, S2
  branch  EX
END:
  end

Prints:

Beautiful plumage!

The following conditional operators are available: eq (equal), ne (not equal), lt (less than), le (less than or equal), gt (greater than), ge (greater than or equal). They take two integer or numeric registers and a label to jump to if the condition is true. If the condition is false, then execution goes to the next statement.

The following code prints the numbers from 1 to 10, by looping over until I1 is greater than 10:

  set     I1, 1
REDO:
  gt      I1, 10, END
  print   I1
  print   " "
  inc     I1
  branch  REDO
END:
  print "\n"
  end

Prints:

1 2 3 4 5 6 7 8 9 10 

The conditional operators take a register and either a constant or another register.

The if opcode tests if a register holds a true value. Any value other than zero is true.

  set     I1, 1
  if      I1, TRUE
  print   "False!\n"

  branch  END
TRUE:
  print   "True!\n"
END:
  end

Prints:

True!

Subroutines

Subroutines are a vital part of larger programs.

The simplest kind of subroutine is one that does not pass or return arguments. The important operators here are bsr (Branch SubRoutine, which jumps to a label) and ret (RETurn, which returns from a subroutine). The following code jumps to a subroutine named HELLO which prints a message and returns.

  bsr     HELLO
  end

HELLO:
  print "Hello there!\n"

  ret

Prints:

Hello there!

The parrot calling conventions have recently changed. While examples will be generated for PASM-based calling conventions, it is recommended that you use PIR for actual subroutines.

PMCs (Parrot Magic Cookies)

PMCs are a completely abstracted data type; they may be string, integer, code or anything else. They are roughly equivalent to the SV, AV and HV (and more complex types) defined in Perl 5, and almost exactly equivalent to PythonObject types in Python.

The various types of PMCs shipped with Parrot are defined in the file include/parrot/pmc.h

To use a PMC, you must first create it using the new operator. You can then assign it a value and treat it much like the lower-level types. The following code creates two Integer PMCs and
adds them together.

  new P0, .Integer
  set P0, 123
  new P1, .Integer
  set P1, 321
  add P1, P1, P0
  print P1
  print "\n"
  end

Prints:

444

The following code concatenates a number and a string.

  new     P0, .Integer
  set     P0, 42
  new     P1, .Integer
  set     P1, " is the answer!"
  concat  P0, P0, P1
  print   P0
  print   "\n"
  end

Prints:

 42 is the answer!

You may notice that in the last example, we declare P1 as an Integer type, but then set it to a string value. As with their Perl or Tcl counterparts, PMCs have the ability to change their own type on the fly. (also known as morphing or shimmering). If you trace this code: parrot -t1 foo.pasm ...

     0 new P0, 30                       P0=PMCNULL 
     3 set P0, 42                       P0=Integer=PMC(0xf004f4: 0) 
     6 new P1, 30                       P1=PMCNULL 
     9 set P1, " is the answer!"        P1=Integer=PMC(0xf004e0: 0) 
    12 i_concatenate P0, P1             P0=Integer=PMC(0xf004f4: 42) P1=String=PMC(0xf004e0 Str:" is the answer!")
    16 print P0                         P0=String=PMC(0xf004f4 Str:"42 is the answer!")
    18 print "\n"
42 is the answer!
    20 end

... you see that the P0 and P1 registers are both initialized as the same type (Integers), but at line 12, the concat opcode is processing a Integer (P0) and a String (P1). The assignment on line 9 morphed the PMC in P1 to a different type automatically.