Yığıt Tabanlı Programlama Paradigması
Yığıt tabanlı dillerin tümü, RPN (Reverse Polish Notation, Postfix Notasyon olarak da geçer) notasyonunu kullanır. Bu notasyon, matematiksel ifadeleri yazarken, operatörlerin işlenenlerden(operand) sonra gelmesi esasına dayanır. Bu ifade şeklinin avantajı, yığıtları kullanarak işlem yapmamızı kolaylaştırmasıdır. Üstelik bellek kullanımında da tasarruf sağlar.
Tabloda dikkat edilirse infix notasyondaki işlemlerde işlem öncelikleri çok katı uygulanırken ve aynı zamanda hem çarpma ve bölmenin işlem önceliği dikkate alınıp, parantezlerle öncelik belirlemesi yapılırken; postfix notasyonda parantez kullanımına gerek yoktur ve ayrıca tüm operatörler aynı işlem önceliğine sahiptir. Bu sayede ayıklama(parsing) işlemi oldukça kolaylaşmaktadır. Postfix notasyonda hesaplama yığıt yardımıyla gerçekleştilir. Örnek bir hesaplama süreci aşağıda gösterilmiştir.
İşlem: (5 + 9)
Postfix Karşılığı : 5 9 +
İşlemin gerçekleştirilmesi soldan sağa taranarak yapılır. Yani sol taraftan incelemeye başladığımızda önce '5' ile karşılaşırız. Bu bir sabittir ve doğrudan yığıta atılır.
Yığıt durumu
Ardından gelen '9' incelenir ve sabit bir sayı olduğundan o da yığıta atılır.
Yığıt durumu
Şimdi ise '+' işlemi gelir. Bu bir operatör olduğu için yığıt'tan iki değer çeker(pop) ve gerekli işlemi gerçekleştirip elde ettiği değeri yığıta geri gönderir(push). Yığıtın son hali:
şeklinde olur ve hesaplama gerçekleştirilmiş olur. Yığıt tabanlı diller de temelde bu mantığı kullanır ve bu operatörleri genişleterek, büyük uygulamaların gerçekleştirilmesinde kullanılırlar.
Yığıt tabanlı diller ile bizim sık duyduğumuz programlama paradigmalarının alakası yoktur. Örnek olarak emirli(imperative) programlama olarak geçen ve C, C++, Java, Python gibi popüler dillerde kullanılan bu paradigma yığıt tabanlı dillerde de kullanılabilir. Aynı şekilde prosedürel programlama da yığıt tabanlı dillerde kullanılabilmektedir. Prosedürel programlamaya izin veren ve yığıt tabanını kullanan dillere en iyi örnek Adobe'un PostScript programlama dilidir. Bu dil, özellikle yazıcılar için tasarlanmıştır ve yazıcılar içinde bir yorumlayıcısı bulunur. Her PostScript dokümanı bir PostScript programıdır ve genelde programcılar tarafından değil, başka programlar tarafından bizim yerimize otomatik olarak üretilirler. Bu üretilen PostScript dokümanları yazıcıya gönderildiğinde yazıcı, bu PostScript dokümanını yorumlar. Bu yorumlamayla birlikte yazıcıdan çıktı olarak PostScript dokümanının render edilmiş hali alınır.
Yığıt Tabanlı Diller
İlk yığıt tabanlı dil, Chuck Moore tarafından 1958'de tasarlanan ve günümüzde de kullanılan Forth dilidir. Forth, günümüzde özellikle gömülü(embedded) sistemlerde kullanılmaktadır çünkü bellek kullanımı oldukça verimlidir. Tabi C gibi diller için üretilen derleyiciler, her ne kadar optimizasyonu güçlü kodlar üretebilse de Forth da hala tercih edilen bir dil konumundadır.
Yukarıda da belirtildiği gibi Adobe'un PostScript dili de oldukça popülerdir ve birçok yazıcıda bir PostScript yorumlayıcısı bulunur. Bunlara ek olarak geliştirilmiş bazı yığıt tabanlı diller de vardır. Bunlardan bazıları Cat, Factor, Joy dilleridir. Bu üç dilin ortak özelliği fonksiyonel programlamayı desteklemesidir.
Dikkat edilirse popüler olmuş yığıt tabanlı diller genelde donanımla ilgili alanlarda kullanılmaktadır. Bu bir tesadüf değildir. Çünkü yığıt tabanlı diller bellek kullanımı açısından ön plana çıkan dillerdir. Tabi bu performansı, söz dizimine de borçludur. Çünkü yığıt tabanlı dillerin ayrıştırılması için ek olarak ayrıştırıcı çalıştırmaya gerek kalmayabilir çünkü kelimeler(word) sırayla gezilir ve her karşılan kelimede yığıtta bazı değişiklikler yapılır. Bu durum, Assembly dillerinde olduğu gibi programcıların hızlı kod üretebilmeleri önünde bir engel gibi görünüyor. Ama Cat, Factor gibi dillerin getirdiği yüksek seviyeli soyutlamalar bu sorunun bir nebze önüne geçebiliyor.
PostScript Üzerinde Bazı Örnekler
PostScript'in genel kullanım amacı görsel elemanlar oluşturmak olduğu için güçlü bir grafik render motoruna sahiptir. Bununla birlikte diğer amaçlar için de programlamaya izin vermektedir.
Not: Yığıt tabanlı dillerde değişkenlere ihtiyaç duyulmaz fakat soyutlamayı artırmak için değişkenler de bu tarz dillere eklenmiştir. Örnek olarak Forth'un eski versiyonlarında değişken kavramı yokken günümüzdeki gerçekleştirimlerinde bulunmaktadır.
5 6 add
5 ile 6 yı sırasıyla yığıta atar ve 'add' kelimesi(word) ile karşılaşınca iki tane eleman yığıttan çekilir ve toplama işlemi gerçekleştirilip, sonuç yığıta gönderilir. Stack son hali: 11
/x 7 def
x adlı bir değişken oluşturulur ve 7 değeri o değişkene atanır. 'def' burada tanımlamak anlamına gelir. Yığıtta bir değişiklik olmaz ama yorumlayıcı sonraki bölümlerde bu değişken ismiyle karşılaşırsa değerini yığıta atar.
/foo {1 2 add 5 sub} def
'foo' adlı bir prosedür tanımlar. Prosedürün içeriği { ve } parantezleri arasında yazılır. Burada yığıta 1 ve 2'yi atıp toplayan ve çıkan sonuçtan 5'i çıkaran bir prosedür tanımlanmıştır.
Prosedür veya değişken tanımlama biçimleri birbirine benzerdir. Kullanırken de sadece ismini yazmak yeterlidir. Prosedürler argümanlarını yığıt üzerinden aldıkları için ne tanımlarken ne de kullanırken açıkça argüman belirtmeye gerek yoktur. Yani çağırıken sadece:
foo [enter]
şeklinde çağırmak yeterlidir.
PostScript'te if-else Yapısı
4 3 lt {doğruysa yapılacaklar} {yanlışsa yapılacaklar} ifelse
Örnekte 4 ve 3 sırasıyla yığıta atılır ve 'lt' kelimesiyle 4'ün 3'ten küçük olup olmadığı kontrol edilir. Eğer doğruysa birinci prosedür, yanlışsa ikinci prosedür çalıştırılır. Dikkat edilirse 'ifelse' kelimesi diğer dillerin aksine sona yazılmıştır ve postfix notasyonuna uymuştur. Aslında 'ifelse' diğer dillerin
aksine burada bir fonksiyon yani kelimedir(word). Yani C, Pascal gibi dillerde bulunanın aksine özel anahtar kelimeler(keyword) yoktur ve her şeye birer komut(kelime, word) olarak bakabiliriz.
Etiketler :
[forth]
[yığıt tabanlı programlama]
[stack-based]
[postscript]
[yığıt]
[stack]
[programlama]


