Burung Beo - Contoh Pemrograman
Pemrograman burung beo mirip dengan pemrograman bahasa assembly dan Anda mendapat kesempatan untuk bekerja di tingkat yang lebih rendah. Berikut adalah daftar contoh pemrograman untuk membuat Anda mengetahui berbagai aspek Pemrograman Parrot.
Klasik Halo dunia!
Menggunakan register
Menjumlahkan kotak
Angka Fibonacci
Menghitung faktorial
Mengompilasi ke PBC
PIR vs. PASM
Klasik Halo dunia!
Buat file bernama hello.pir yang berisi kode berikut:
.sub _main
print "Hello world!\n"
end
.end
Kemudian jalankan dengan mengetik:
parrot hello.pir
Seperti yang diharapkan, ini akan menampilkan teks 'Hello world!' di konsol, diikuti oleh baris baru (karena \ n).
Dalam contoh di atas, '.sub _main' menyatakan bahwa instruksi yang mengikuti membuat subrutin bernama '_main', hingga '.end' ditemukan. Baris kedua berisi instruksi cetak. Dalam hal ini, kami memanggil varian dari instruksi yang menerima string konstan. Assembler akan menentukan varian instruksi mana yang akan digunakan untuk kita. Baris ketiga berisi instruksi 'end', yang menyebabkan interpreter berhenti.
Menggunakan Register
Kita dapat memodifikasi hello.pir untuk menyimpan string Hello world! \ N pertama dalam register dan kemudian menggunakan register itu dengan instruksi cetak.
.sub _main
set S1, "Hello world!\n"
print S1
end
.end
Di sini kami telah menyatakan dengan tepat register mana yang akan digunakan. Namun, dengan mengganti S1 dengan $ S1 kita dapat mendelegasikan pilihan register mana yang akan digunakan ke Parrot. Dimungkinkan juga untuk menggunakan notasi = daripada menulis instruksi set.
.sub _main
$S0 = "Hello world!\n"
print $S0
end
.end
Untuk membuat PIR lebih mudah dibaca, register bernama dapat digunakan. Ini kemudian dipetakan ke register bernomor nyata.
.sub _main
.local string hello
hello = "Hello world!\n"
print hello
end
.end
Direktif '.local' menunjukkan bahwa register bernama hanya diperlukan di dalam unit kompilasi saat ini (yaitu, antara .sub dan .end). Mengikuti '.local' adalah sebuah tipe. Ini bisa berupa int (untuk register I), float (untuk register N), string (untuk register S), pmc (untuk register P) atau nama jenis PMC.
Menjumlahkan kotak
Contoh ini memperkenalkan beberapa instruksi lagi dan sintaks PIR. Baris yang dimulai dengan # adalah komentar.
.sub _main
# State the number of squares to sum.
.local int maxnum
maxnum = 10
# Some named registers we'll use.
# Note how we can declare many
# registers of the same type on one line.
.local int i, total, temp
total = 0
# Loop to do the sum.
i = 1
loop:
temp = i * i
total += temp
inc i
if i <= maxnum goto loop
# Output result.
print "The sum of the first "
print maxnum
print " squares is "
print total
print ".\n"
end
.end
PIR memberikan sedikit gula sintaksis yang membuatnya terlihat lebih tinggi daripada perakitan. Sebagai contoh:
temp = i * i
Apakah hanya cara lain untuk menulis lebih banyak assembly-ish:
mul temp, i, i
Dan:
if i <= maxnum goto loop
Sama dengan:
le i, maxnum, loop
Dan:
total += temp
Sama dengan:
add total, temp
Sebagai aturan, setiap kali instruksi Parrot mengubah isi register, itu akan menjadi register pertama saat menulis instruksi dalam bentuk assembly.
Seperti biasa dalam bahasa assembly, loop dan pilihan diimplementasikan dalam istilah pernyataan dan label cabang bersyarat, seperti yang ditunjukkan di atas. Pemrograman perakitan adalah salah satu tempat di mana menggunakan goto bukanlah bentuk yang buruk!
Angka Fibonacci
Deret Fibonacci didefinisikan seperti ini: ambil dua angka, 1 dan 1. Kemudian berulang kali menjumlahkan dua angka terakhir dalam deret tersebut untuk membuat angka berikutnya: 1, 1, 2, 3, 5, 8, 13, dan seterusnya . Angka Fibonacci fib (n) adalah angka ke-n dalam rangkaian tersebut. Berikut adalah program assembler Parrot sederhana yang menemukan 20 angka Fibonacci pertama:
# Some simple code to print some Fibonacci numbers
print "The first 20 fibonacci numbers are:\n"
set I1, 0
set I2, 20
set I3, 1
set I4, 1
REDO: eq I1, I2, DONE, NEXT
NEXT: set I5, I4
add I4, I3, I4
set I3, I5
print I3
print "\n"
inc I1
branch REDO
DONE: end
Ini adalah kode yang setara di Perl:
print "The first 20 fibonacci numbers are:\n";
my $i = 0;
my $target = 20; my $a = 1;
my $b = 1; until ($i == $target) { my $num = $b; $b += $a; $a = $num; print $a,"\n";
$i++;
}
NOTE:Sebagai titik perhatian yang bagus, salah satu cara terpendek dan terindah untuk mencetak deret Fibonacci di Perl adalah perl -le '$ b = 1; mencetak$a+=$b saat mencetak $b+=$Sebuah'.
Menghitung faktorial secara rekursif
Dalam contoh ini kita mendefinisikan fungsi faktorial dan secara rekursif memanggilnya untuk menghitung faktorial.
.sub _fact
# Get input parameter.
.param int n
# return (n > 1 ? n * _fact(n - 1) : 1)
.local int result
if n > 1 goto recurse
result = 1
goto return
recurse:
$I0 = n - 1 result = _fact($I0)
result *= n
return:
.return (result)
.end
.sub _main :main
.local int f, i
# We'll do factorial 0 to 10.
i = 0
loop:
f = _fact(i)
print "Factorial of "
print i
print " is "
print f
print ".\n"
inc i
if i <= 10 goto loop
# That's it.
end
.end
Mari kita lihat sub _fact terlebih dahulu. Satu hal yang telah diabaikan sebelumnya adalah mengapa nama-nama subrutin, semuanya dimulai dengan garis bawah! Hal ini dilakukan hanya sebagai cara untuk menunjukkan bahwa label tersebut bersifat global dan bukan mencakup subrutin tertentu. Ini penting karena label kemudian dapat dilihat oleh subrutin lain.
Baris pertama, .param int n, menetapkan bahwa subrutin ini mengambil satu parameter integer dan kita ingin merujuk ke register yang diteruskan dengan nama n untuk subrutin lainnya.
Banyak hal berikut ini telah dilihat dalam contoh sebelumnya, selain dari pembacaan baris:
result = _fact($I0)
Baris tunggal PIR ini sebenarnya mewakili beberapa baris PASM. Pertama, nilai dalam register $ I0 dipindahkan ke register yang sesuai agar dapat diterima sebagai parameter integer oleh fungsi _fact. Register terkait panggilan lainnya kemudian disiapkan, diikuti dengan _fact yang dipanggil. Kemudian, setelah _fact kembali, nilai yang dikembalikan oleh _fact ditempatkan ke dalam register berdasarkan hasil nama.
Tepat sebelum .end dari sub _fact, perintah .return digunakan untuk memastikan nilai yang disimpan dalam register; hasil bernama ditempatkan ke dalam register yang benar agar dapat dilihat sebagai nilai kembali oleh kode yang memanggil sub.
Panggilan ke _fact in main bekerja dengan cara yang sama seperti panggilan rekursif ke _fact dalam sub _fact itu sendiri. Bit yang tersisa dari sintaks baru adalah: main, ditulis setelah .sub _main. Secara default, PIR mengasumsikan bahwa eksekusi dimulai dengan sub pertama dalam file. Perilaku ini dapat diubah dengan menandai sub diawali dengan: main.
Mengompilasi ke PBC
Untuk mengkompilasi PIR menjadi bytecode, gunakan tanda -o dan tentukan file keluaran dengan ekstensi .pbc.
parrot -o factorial.pbc factorial.pir
PIR vs. PASM
PIR dapat diubah menjadi PASM dengan menjalankan:
parrot -o hello.pasm hello.pir
PASM untuk contoh terakhir terlihat seperti ini:
_main:
set S30, "Hello world!\n"
print S30
end
PASM tidak menangani alokasi register atau memberikan dukungan untuk register bernama. Itu juga tidak memiliki direktif .sub dan .end, sebagai gantinya menggantinya dengan label di awal instruksi.