Parrotとたわむれる(2)くらい

すっかり忘れてましたけど、Parrotで遊びたかったのです。とりあえずよく覚えてないので復習。
PASMはParrotのアセンブリ言語。Parrotの命令と一対一で対応する。PIRはParrotの中間表現。低レイヤーのPASMと上位レイヤーの言語の間に位置する。PASMよりいくらか人間向け。

というわけでPIRでcatプログラム書いてみる。引数無しで標準入力を、引数があればそうして渡されたファイルを標準出力に。

% parrot cat.pir cat.pir
.sub main
  .local int argnum
  .local pmc args, input
  .local string file, line
  get_params '(0)', args
  argnum = 1
  file = args[argnum]
  if file goto OPENFILE
STDIN:
  getstdin input
LOOP1:
  readline line, input
  print line
  if line goto LOOP1
  close input
  inc argnum
  file = args[argnum]
  unless file goto END
OPENFILE:
  open input, file, "<"
  if input goto LOOP1
  print "can't open "
  print file
  print "\n"
END:
.end

このようにparrotコマンドからごく普通のスクリプトであるかのように呼ぶこともできる。また、バイトコンパイルもできる。

% parrot -o cat.pbc cat.pir
% parrot cat.pbc cat.pir
.sub main
  .local int argnum
  .local pmc args, input
...

アセンブルもできます。何故かぶっこわれたPASMを出力するらしいですが。

% parrot -o cat.pasm cat.pir
% parrot cat.pir cat.pasm
# IMCC does produce b0rken PASM files
# see http://guest@rt.perl.org/rt3/Ticket/Display.html?id=32392
main:
        get_params
        set I0, 1
        set S1, P1[I0]
        if S1, OPENFILE
STDIN:
        getstdin P0
LOOP1:
        readline S0, P0
        print S0
        if S0, LOOP1
        close P0
        inc I0
        set S1, P1[I0]
        unless S1, END
OPENFILE:
        open P0, S1, "<"
        if P0, LOOP1
        print "can't open "
        print S1
        print "\n"
END:
        set_returns
        returncc

ネイティブコードまで落として、JITがどうこうなこともできるらしいけど、よくわからん。バイトコードからELFコードを吐ける。

% parrot -o cat.o cat.pbc
% objdump -S cat.o
cat.o:     file format elf32-i386

Disassembly of section .text:

00000000 <run_compiled>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   d9 2d 00 34 ef b7       fldcw  0xb7ef3400
   9:   53                      push   %ebx
   a:   56                      push   %esi
   b:   57                      push   %edi
   c:   8b 45 08                mov    0x8(%ebp),%eax
...

test