Parrot - Hızlı Kılavuz
Programımızı geleneksel Perl ile beslediğimizde, önce dahili bir temsil veya bayt kodu olarak derlenir; bu bayt kodu daha sonra yorumlanmak üzere Perl içinde neredeyse ayrı bir alt sisteme beslenir. Yani Perl'in çalışmasının iki farklı aşaması vardır:
Bayt koduna derleme ve
Bayt kodunun yorumlanması.
Bu Perl'e özgü değildir. Bu tasarımı takip eden diğer diller arasında Python, Ruby, Tcl ve hatta Java bulunur.
Java bayt kodunu makine diline çevirip çalıştıran, platformdan bağımsız bir yürütme ortamı olan Java Sanal Makinesi (JVM) olduğunu da biliyoruz. Bu kavramı anlarsanız, Parrot'u anlayacaksınız.
Parrotyorumlanan diller için bayt kodunu verimli bir şekilde derlemek ve yürütmek için tasarlanmış sanal bir makinedir. Parrot, son Perl 6 derleyicisinin hedefidir ve Pugs ve Tcl, Ruby, Python vb. Gibi çeşitli diğer diller için arka uç olarak kullanılır.
Papağan, en popüler dil olan "C" kullanılarak yazılmıştır.
Başlamadan önce Parrot'un son bir kopyasını indirip makinemize kuralım.
Parrot indirme bağlantısı Parrot CVS Snapshot'ta mevcuttur . Parrot'un en son sürümünü indirin ve kurmak için aşağıdaki adımları izleyin:
İndirilen dosyanın sıkıştırmasını açın ve açın.
Makinenizde zaten Perl 5'in kurulu olduğundan emin olun.
Şimdi şunları yapın:
% cd parrot
% perl Configure.pl
Parrot Configure
Copyright (C) 2001 Yet Another Society
Since you're running this script, you obviously have
Perl 5 -- I'll be pulling some defaults from its configuration.
...
Daha sonra yerel yapılandırmanızla ilgili bir dizi soru sorulacak; neredeyse her zaman her biri için return / enter tuşuna basabilirsiniz.
Son olarak, make test_prog yazmanız söylenecek ve Parrot test yorumlayıcısını başarıyla oluşturacaktır.
Şimdi bazı testler yapmalısınız; bu nedenle 'test yap' yazın ve aşağıdaki gibi bir okuma görmelisiniz:
perl t/harness
t/op/basic.....ok,1/2 skipped:label constants unimplemented in
assembler
t/op/string....ok, 1/4 skipped: I'm unable to write it!
All tests successful, 2 subtests skipped.
Files=2, Tests=6,......
Bunu okuduğunuzda, daha fazla test olabilir ve atlananlardan bazıları atlamayabilir, ancak hiçbirinin başarısız olmamasına dikkat edin!
Bir papağan yürütülebilir dosyasını yükledikten sonra, Parrot 'Örnekler' bölümünde verilen çeşitli örnek türlerine göz atabilirsiniz . Parrot deposundaki örnekler dizinine de bakabilirsiniz.
Parrot şu anda dört şekilde uygulama talimatlarını kabul edebiliyor. PIR (Parrot Intermediate Representation) insanlar tarafından yazılacak ve derleyiciler tarafından oluşturulacak şekilde tasarlanmıştır. Parametrelerin işlevlere aktarılma şekli gibi bazı düşük düzeyli ayrıntıları gizler.
PASM (Parrot Assembly), PIR'ın altındaki bir seviyedir - hala insan tarafından okunabilir / yazılabilir ve bir derleyici tarafından oluşturulabilir, ancak yazarın çağrı kuralları ve kayıt tahsisi gibi ayrıntılarla ilgilenmesi gerekir. PAST (Parrot Abstract Syntax Tree), Parrot'un soyut sözdizimi ağaç stili girdisini kabul etmesini sağlar - derleyiciler yazanlar için yararlıdır.
Yukarıdaki giriş biçimlerinin tümü, Parrot içinde otomatik olarak PBC'ye (Parrot Bytecode) dönüştürülür. Bu, makine koduna çok benzer, ancak Parrot yorumlayıcısı tarafından anlaşılır.
İnsan tarafından okunabilir veya insanlar tarafından yazılabilir olması amaçlanmamıştır, ancak diğer formlardan farklı olarak uygulama, bir montaj aşamasına ihtiyaç duymadan hemen başlayabilir. Parrot bayt kodu platformdan bağımsızdır.
Talimat seti
Parrot komut seti aritmetik ve mantıksal operatörler, karşılaştırma ve dallanma / atlama (döngüleri uygulamak için, eğer ... sonra inşa eder, vb.), Genel ve sözcüksel değişkenleri bulma ve depolama, sınıflar ve nesnelerle çalışma, alt rutinleri ve yöntemleri çağırma parametreleri, G / Ç, iş parçacıkları ve daha fazlası ile.
Java Virtual Machine gibi, Parrot da sizi bellek tahsisi konusunda endişelenmekten kurtarır.
Parrot, çöp toplama sağlar.
Parrot programlarının hafızayı açık bir şekilde boşaltmasına gerek yoktur.
Ayrılan bellek, artık kullanılmadığında yani artık referans gösterilmediğinde serbest bırakılacaktır.
Parrot Garbage Collector, istenmeyen hafızayla ilgilenmek için periyodik olarak çalışır.
Parrot CPU'nun dört temel veri türü vardır:
IV
Bir tamsayı türü; bir işaretçiyi tutacak kadar geniş olması garantilidir.
NV
Mimariden bağımsız bir kayan nokta türü.
STRING
Soyutlanmış, kodlamadan bağımsız bir dize türü.
PMC
Skaler.
İlk üç tür hemen hemen kendinden açıklamalıdır; son tür - Parrot Magic Cookies'in anlaşılması biraz daha zordur.
PMC'ler nedir?
PMC, Parrot Magic Cookie anlamına gelir. PMC'ler, toplu veri türleri (diziler, karma tablolar vb.) Dahil olmak üzere herhangi bir karmaşık veri yapısını veya türünü temsil eder. Bir PMC, üzerinde gerçekleştirilen aritmetik, mantıksal ve dizgi işlemleri için kendi davranışını uygulayabilir ve dile özgü davranışın uygulanmasına izin verir. PMC'ler, Parrot yürütülebilir dosyasında yerleşik olabilir veya gerektiğinde dinamik olarak yüklenebilir.
Mevcut Perl 5 sanal makine bir yığın makinesidir. İşlemler arasında değerleri bir yığın üzerinde tutarak iletişim kurar. İşlemler değerleri yığına yükler, yapmaları gereken her şeyi yapar ve sonucu yığına geri koyar. Bununla çalışmak kolay ama yavaştır.
İki sayıyı birbirine eklemek için, üç yığın itme ve iki yığın çıkarma yapmanız gerekir. Daha da kötüsü, yığının çalışma zamanında büyümesi gerekir ve bu, belleği ayırmak istemediğinizde bellek ayırmak anlamına gelir.
Yani Parrot, sanal makineler için yerleşik geleneği kıracak ve gerçek bir donanım CPU mimarisine daha çok benzer bir kayıt mimarisi kullanacak. Bunun başka bir avantajı var. Yazılım CPU'larımız için kayıt tabanlı CPU'lar için derleyicilerin ve optimize edicilerin nasıl yazılacağına dair tüm mevcut literatürü kullanabiliriz!
Parrot, her tür için uzman kayıtlara sahiptir: 32 IV kaydı, 32 NV kaydı, 32 dizi kaydı ve 32 PMC kaydı. Parrot assembler'da bunlar sırasıyla I1 ... I32, N1 ... N32, S1 ... S32, P1 ... P32 olarak adlandırılır.
Şimdi bir montajcıya bakalım. Bu kayıtları set operatörü ile ayarlayabiliriz:
set I1, 10
set N1, 3.1415
set S1, "Hello, Parrot"
Tüm Parrot operasyonları aynı formata sahiptir: operatörün adı, hedef kayıt ve ardından işlenenler.
Gerçekleştirebileceğiniz çeşitli işlemler vardır. Örneğin, bir kaydın veya sabitin içeriğini yazdırabiliriz:
set I1, 10
print "The contents of register I1 is: "
print I1
print "\n"
Yukarıdaki talimatlar I1 yazmacının içeriği şu şekilde sonuçlanacaktır : 10
Kayıtlar üzerinde matematiksel işlemler yapabiliriz:
# Add the contents of I2 to the contents of I1
add I1, I1, I2
# Multiply I2 by I4 and store in I3
mul I3, I2, I4
# Increment I1 by one
inc I1
# Decrement N3 by 1.5
dec N3, 1.5
Hatta bazı basit dize manipülasyonları bile yapabiliriz:
set S1, "fish"
set S2, "bone"
concat S1, S2 # S1 is now "fishbone"
set S3, "w"
substr S4, S1, 1, 7
concat S3, S4 # S3 is now "wishbone"
length I1, S3 # I1 is now 8
Akış kontrolü olmadan kod biraz sıkıcı hale gelir; yeni başlayanlar için, Parrot dallanma ve etiketleri biliyor. Şube operasyonu Perl'in goto'suna eşdeğerdir:
branch TERRY
JOHN: print "fjords\n"
branch END
MICHAEL: print " pining"
branch GRAHAM
TERRY: print "It's"
branch MICHAEL
GRAHAM: print " for the "
branch JOHN
END: end
Ayrıca, bir kaydın gerçek bir değer içerip içermediğini görmek için basit testler gerçekleştirebilir:
set I1, 12
set I2, 5
mod I3, I2, I2
if I3, REMAIND, DIVISOR
REMAIND: print "5 divides 12 with remainder "
print I3
branch DONE
DIVISOR: print "5 is an integer divisor of 12"
DONE: print "\n"
end
Karşılaştırma için Perl'de nasıl görüneceği aşağıda açıklanmıştır:
$i1 = 12;
$i2 = 5;
$i3 = $i1 % $i2;
if ($i3) {
print "5 divides 12 with remainder ";
print $i3;
} else {
print "5 is an integer divisor of 12";
}
print "\n";
exit;
Papağan Operatörü
Tüm sayısal karşılaştırıcılara sahibiz: eq, ne, lt, gt, le ve ge. Bu operatörleri farklı türlerdeki argümanlar üzerinde kullanamayacağınızı unutmayın; Hatta, ne tür bir argüman kullandığınızı söylemek için op'a _i veya _n sonekini eklemeniz bile gerekebilir, gerçi siz bunu okuduğunuzda assembler bunu sizin için tanrılaştırmalı.
Parrot programlama, assembly dili programlamasına benzer ve daha düşük seviyede çalışma şansınız olur. Parrot Programlamanın çeşitli yönlerinden haberdar olmanızı sağlayacak programlama örneklerinin listesi burada.
- Klasik Merhaba dünya!
- Kayıtları kullanma
- Toplam kareler
- Fibonacci Sayıları
- Faktöriyel hesaplama
- PBC'ye Derleme
- PIR ve PASM
Klasik Merhaba dünya!
Aşağıdaki kodu içeren hello.pir adında bir dosya oluşturun:
.sub _main
print "Hello world!\n"
end
.end
Ardından şunu yazarak çalıştırın:
parrot hello.pir
Beklendiği gibi, bu "Merhaba dünya!" Metnini görüntüleyecektir. konsolda, ardından yeni bir satır (\ n nedeniyle).
Yukarıdaki örnekte, '.sub _main', bir '.end' ile karşılaşılıncaya kadar, takip eden talimatların '_main' adlı bir alt yordamı oluşturduğunu belirtir. İkinci satır, yazdırma talimatını içerir. Bu durumda, sabit bir dizeyi kabul eden talimatın varyantını çağırıyoruz. Montajcı, talimatın hangi varyantını bizim için kullanacağına karar verir. Üçüncü satır, yorumlayıcının sonlandırmasına neden olan 'son' talimatını içerir.
Kayıtları Kullanma
Hello.pir'i ilk önce Hello world! \ N dizgesini bir kayıtta saklayacak ve sonra bu kaydı yazdırma talimatıyla birlikte kullanacak şekilde değiştirebiliriz.
.sub _main
set S1, "Hello world!\n"
print S1
end
.end
Burada tam olarak hangi kaydın kullanılacağını belirttik. Bununla birlikte, S1'i $ S1 ile değiştirerek, Parrot'a hangi kaydın kullanılacağına ilişkin seçim yetkisi verebiliriz. Ayrıca set talimatını yazmak yerine bir notasyon kullanmak da mümkündür.
.sub _main
$S0 = "Hello world!\n"
print $S0
end
.end
PIR'ı daha da okunabilir hale getirmek için, adlandırılmış kayıtlar kullanılabilir. Bunlar daha sonra gerçek numaralı kayıtlarla eşleştirilir.
.sub _main
.local string hello
hello = "Hello world!\n"
print hello
end
.end
'.Local' yönergesi, adlandırılmış yazmacın yalnızca mevcut derleme biriminde (yani .sub ve .end arasında) gerekli olduğunu belirtir. Aşağıdaki ".local" bir türdür. Bu int (I kayıtları için), float (N kayıtları için), dize (S kayıtları için), pmc (P kayıtları için) veya bir PMC tipi adı olabilir.
Toplam kareler
Bu örnek, biraz daha fazla talimat ve PIR sözdizimi sunar. # İle başlayan satırlar yorumlardır.
.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, montajdan daha yüksek seviyede görünmesini sağlayan bir miktar sözdizimsel şeker sağlar. Örneğin:
temp = i * i
Daha montajlı yazmanın başka bir yolu:
mul temp, i, i
Ve:
if i <= maxnum goto loop
Aynıdır:
le i, maxnum, loop
Ve:
total += temp
Aynıdır:
add total, temp
Kural olarak, bir Parrot talimatı bir kaydın içeriğini her değiştirdiğinde, bu, talimatı montaj biçiminde yazarken ilk kayıt olacaktır.
Montaj dillerinde olağan olduğu gibi, döngüler ve seçimler, yukarıda gösterildiği gibi koşullu dal ifadeleri ve etiketler açısından uygulanır. Assembly programlama, goto kullanmanın kötü bir form olmadığı bir yerdir!
Fibonacci Sayıları
Fibonacci serisi şu şekilde tanımlanır: 1 ve 1 olmak üzere iki sayı alın.Sonra bir sonrakini yapmak için serideki son iki sayıyı tekrar tekrar ekleyin: 1, 1, 2, 3, 5, 8, 13, vb. . Fibonacci numarası fib (n), serideki n'inci sayıdır. İşte ilk 20 Fibonacci sayısını bulan basit bir Parrot assembler programı:
# 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
Bu, Perl'deki eşdeğer koddur:
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:İnce bir ilgi noktası olarak, Perl'de bir Fibonacci serisini yazdırmanın en kısa ve kesinlikle en güzel yollarından biri perl -le '$ b = 1'dir; print $ a + = $ b iken print $ b + = $ a '.
Özyinelemeli hesaplama faktöryel
Bu örnekte faktöriyel bir fonksiyon tanımlıyoruz ve onu faktöriyel hesaplamak için yinelemeli olarak çağırıyoruz.
.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
Önce _fact alt kısmına bakalım. Daha önce gözden geçirilen bir nokta, alt yordamların adlarının neden hepsinin bir alt çizgiyle başlamasıdır! Bu, belirli bir alt yordamı kapsamaktan çok, etiketin küresel olduğunu göstermenin bir yolu olarak yapılır. Etiket daha sonra diğer alt programlar tarafından görülebileceği için bu önemlidir.
İlk satır, .param int n, bu alt yordamın bir tamsayı parametresi aldığını ve alt yordamın geri kalanı için n adıyla geçirildiği kayda başvurmak istediğimizi belirtir.
Aşağıdakilerin çoğu, satır okuması dışında önceki örneklerde görülmüştür:
result = _fact($I0)
Bu tek PIR satırı aslında epeyce PASM satırını temsil eder. İlk olarak, $ I0 yazmacındaki değer, _fact fonksiyonu tarafından bir tamsayı parametresi olarak alınabilmesi için uygun kayda taşınır. Diğer arama ile ilgili kayıtlar daha sonra kurulur ve ardından _fact çağrılır. Ardından, _fact döndüğünde, _fact tarafından döndürülen değer, sonuç adıyla birlikte kayda yerleştirilir.
_Fact alt kısmının .endinden hemen önce, kayıtta tutulan değeri sağlamak için bir .return yönergesi kullanılır; adlandırılmış sonuç, alt'ı çağıran kod tarafından bir dönüş değeri olarak görülebilmesi için doğru kayda yerleştirilir.
_Fact in main çağrısı, sub _fact içinde _fact için yinelemeli çağrı ile aynı şekilde çalışır. Yeni sözdiziminin geriye kalan tek biti: main, .sub _main'den sonra yazılır. Varsayılan olarak PIR, yürütmenin dosyadaki ilk alt ile başladığını varsayar. Bu davranış, başlangıç olarak alt işaretlenerek değiştirilebilir: ana.
PBC'ye Derleme
PIR'ı bayt koduna derlemek için -o işaretini kullanın ve .pbc uzantılı bir çıktı dosyası belirtin.
parrot -o factorial.pbc factorial.pir
PIR ve PASM
PIR, aşağıdakileri çalıştırarak PASM'ye dönüştürülebilir:
parrot -o hello.pasm hello.pir
Son örnek için PASM şuna benzer:
_main:
set S30, "Hello world!\n"
print S30
end
PASM, kayıt tahsisini işlemez veya adlandırılmış kayıtlar için destek sağlamaz. Ayrıca, .sub ve .end direktiflerine sahip değildir, bunun yerine talimatların başında bir etiketle değiştirilir.