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 ...