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.