Kod bajtowy Perla używany w Perlu 5 jest maszyną stosową z operacjami umiarkowanie wysokiego poziomu. Perl 6 używać będzie maszyny wirtualnej Parrot.
Wynikiem kompilacji:
print "Hello, world!\n";
jest następujący bytecode:
OP enter COP nextstate OP pushmark SVOP const PV "Hello, world!\n" LISTOP print LISTOP leave
Klasy opcodów
Opcody są pogrupowane w kilka klas zależnie od tego na jakich argumentach działają. Klasy te to:
- OP – ogólna klasa,
- COP – informacja dla debugera,
- SVOP – operacje na skalarach,
- PADOP,
- UNOP – operacje unarne,
- LOGOP – operacje logiczne (sterujące),
- BINOP – operacje binarne,
- LISTOP – operacje działające na listach,
- PMOP – operacje na wyrażeniach regularnych,
- LOOPOP – operacje pętli,
- …
Stos
Stos nie zawiera obiektów, a jedynie wskaźniki do nich.
Żeby wywołać operacje unarną lub binarną umieszczamy jej argumenty na stosie i wywołujemy ją.
Na przykład operacja unarna UNOP negate
pobierze najwyższy element ze stosu i wstawi na stos jego zanegowaną wartość, operacja binarna BINOP add
pobierze dwa najwyższe elementy ze stosu i wstawi ich sumę.
Żeby wywołać operację wymagającą większej ilości argumentów:
- zaznaczamy za pomocą
OP pushmark
, że zaczyna się nowa ramka stosu, - umieszczamy na stosie wszystkie argumenty zaczynając od pierwszego,
- wywołujemy odpowiednią operację (np.
LISTOP print
), lub umieszczamy na stosie adres funkcji do wywołania (PADOP gv GV *foo
), po czym ją wywołujemy za pomocąUNOP entersub
.
Przykład wywołania $x = "Hello, world!\n"
:
COP nextstate SVOP const PV "Hello, world!\n" PADOP gvsv GV *x BINOP sassign
Przykład wywołania $x = -$y
:
PADOP gvsv GV *y UNOP negate PADOP gvsv GV *x BINOP sassign
Przykład wywołania $x = $y + $z
:
PADOP gvsv GV *y PADOP gvsv GV *z BINOP add PADOP gvsv GV *x BINOP sassign
Przykład wywołania print(1,2,3)
:
OP pushmark SVOP const IV 1 SVOP const IV 2 SVOP const IV 3 LISTOP print
Przykład wywołania foo(1,2,3)
:
COP nextstate OP pushmark SVOP const IV 1 SVOP const IV 2 SVOP const IV 3 PADOP gv GV *foo UNOP entersub
Operacje na zmiennych skalarnych
Opcode PADOP gvsv
umieszcza na stosie adres zmiennej.
Opcode SVOP const
umieszcza na stosie stałą.
Opcode BINOP sassign
przypisuje zmiennej, odnośnik do której adres znajduje się na najwyższej pozycji stosu. Adres zostaje zdjęty ze stosu, ale wartość zostaje.
Przykład wywołania $x = $y
:
PADOP gvsv GV *y PADOP gvsv GV *x BINOP sassign
Przykład wywołania $x = $y = $z
:
PADOP gvsv GV *z PADOP gvsv GV *y BINOP sassign PADOP gvsv GV *x BINOP sassign
Operacje na liczbach
Podstawowe operacje arytmetyczne to:
Operacja | Perl | Bytecode |
---|---|---|
dodawanie | $x + $y |
BINOP add |
odejmowanie | $x – $y |
BINOP substract |
mnożenie | $x * $y |
BINOP multiply |
dzielenie | $x / $y |
BINOP divide |
reszta modulo | $x % $y |
BINOP modulo |
bitowe AND | $x & $y |
BINOP bit_and |
bitowe OR | $x | $y |
BINOP bit_or |
bitowe XOR | $x ^ $y |
BINOP bit_xor |
negacja arytmetyczna | -$x |
UNOP negate |
negacja bitowa | ~$x |
UNOP complement |
sinus | sin($x) |
UNOP sin |
cosinus | cos($x) |
UNOP cos |
funkcja wykładnicza | exp($x) |
UNOP exp |
logarytm | log($x) |
UNOP log |
pierwiastek | sqrt($x) |
UNOP sqrt |
większe | $x > $y |
BINOP gt |
większe równe | $x >= $y |
BINOP ge |
mniejsze | $x < $y |
BINOP lt |
mniejsze równe | $x <= $y |
BINOP le |
równe | $x == $y |
BINOP eq |
nierówne | $x != $y |
BINOP ne |
porównanie | $x <=> $y |
BINOP ncmp |
przesunięcie bitowe w lewo | $x << $y |
BINOP left_shift |
przesunięcie bitowe w prawo | $x >> $y |
BINOP right_shift |
preinkrementacja | ++$x |
UNOP preinc |
predekrementacja | --$x |
UNOP predec |
postinkrementacja | $x++ |
UNOP postinc |
postdekrementacja | $y-- |
UNOP postdec |
Operatory ++
i --
działają też na łańcuchach. Wersje pre- i post- różnią się tym, co zostaje na stosie.
Operacje na łańcuchach znaków
Operacja | Perl | Bytecode |
---|---|---|
sklejenie | $x . $y |
BINOP concat |
długość | length($x) |
UNOP length |
zamiana wszystkich liter na wielkie | uc($x) |
UNOP uc |
zamiana wszystkich liter na małe | lc($x) |
UNOP lc |
zamiana pierwszego znaku na wielką literę | ucfirst($x) |
UNOP ucfirst |
zamiana pierwszego znaku na małą literę | lcfirst($x) |
UNOP lcfirst |
większe | $x gt $y |
BINOP sgt |
większe równe | $x ge $y |
BINOP sge |
mniejsze | $x lt $y |
BINOP slt |
mniejsze równe | $x le $y |
BINOP sle |
równe | $x eq $y |
BINOP seq |
nierówne | $x ne $y |
BINOP sne |
porównanie | $x cmp $y |
BINOP scmp |