DERLEYİCİ(COMPILER) VE YORUMLAYICI(INTERPRETER) ÜZERİNE BİR DENEME

Mustafa Şenel
5 min readOct 6, 2017

--

Bu yazıyı Twitter’da bir tweet üzerinden başlayan tartışmanın, sonunda bir kavram karmaşasına dönüşmesi üzerine herkesin bu konuyu araştırması ve bunun üzerine bir yazı yazması kararı aldığımız için yazdım. Bu yazıda “Derleyici nedir?”, “Yorumlayıcı nedir?”, “Java derlenir mi?”, “Python yorumlanır mı?”, “JVM nedir?”, “PVM var mıdır?” gibi konulara değinmeye çalışacağım. Fakat konuya geçmeden önce, bu konu hakkında ‘uzman’ olmadığımı, yanlış veya eksik bilgi verebileceğimi -bu durumda beni uyarmanızı/düzeltmenizi bekliyorum- ve hiç Python yazmadığımı belirtmek isterim. Artık konuya geçebiliriz.

Derleyici Nedir?

Bilgisayarlarla ilgili insanlar arasında sıklıkla duyabileceğiniz en derin bilgilerden biri bilgisayarların aslında 0 ve 1’lerle çalıştığı –yani ikilik tabanda- başka hiçbir şeyi anlamayacağı yönündedir. Bu tarz söylemlerin genelde kalabalık bir grup içerisinde muhabbet esnasında konuşulacak konuların bitmesi ve konunun bir sebeple bilişime gelmesi sonrasında biri tarafından söylenmesi ve meclis içerisinde “Nasıl ya?” tepkisinin alınması gerekir. Fakat işte yolu bir sebepten bilişim ile kesişen bizlerde bu şaşırma hali biraz tersten meydana geliyor. Öncelikle bilgisayarın temeli ve mimarisi anlatılıyor ve bu sırra vakıf oluyoruz. Lakin iş kodlama yapmaya geldiğinde bize “Yazın; diyez işareti-include-boşluk-küçüktür-stdio…” dendiğinde kafalarımızda “İyi de bilgisayar bunları nasıl anlayacak?” sorusu bizi dürtmektedir. Bu soruyu gidermek için, sonrasında bize “Bilgisayar onları doğrudan anlamıyor, onlar ‘derlenerek’ arka tarafta ‘makine dili’ne çevriliyor” denir. Aslında buraya kadar olan herşey doğrudur fakat eksiktir. Bu eksikliğin –yazının başında bahsettiğim gibi- üzerine ilerde farklı diller, farklı platformlar eklendikçe bir kavram karmaşası oluşuyor ve bildiğimizi sandığımız şeylerin altının boş olduğunu anlıyoruz.

Bu konu üzerinde yaptığım araştırmalar sonrasında derleyici hakkında aşağıdaki gibi bir ortak tanım olduğu kanısına vardım. Derleyici, yüksek seviye bir programlama dilinde (high-level programming language) yazılmış bir kaynak kodun, başka bir hedef dile veya bilgisayarın/işlemcinin anlayabileceği makine diline tercümesini yapan bir programdır. Derleyiciler herhangi bir dil ile yazılmış olabilir. Her dil için bir veya daha fazla derleyici geliştirilebilir, bir dil için aynı zamanda hem derleyici hem yorumlayıcı yazılabilir. Kaynaklar kısmında sizinle paylaştığım linkte bir C programının derlenmesini adım adım anlatmışlar. Burada aynı örneği kısaca anlatmak istiyorum.

Öncelikle ‘adder.c’ isminde bir dosyamız olsun ve içerisine aşağıdaki kodları eklediğimizi varsayalım:

#include <stdio.h>

#define topla(a,b) (a+b) //makro kullanımı

int main()

{

int a=5, b=4; //Toplanacak sayılar

printf(“Toplam: %d\n”, topla(a,b));

return 0;

}

Dosyamızı kaydettikten sonra yazdığımız kodu çalıştırabilmek için 4 aşamadan oluşan derleme işlemine geçeceğiz:

1- Ön İşleme(Pre-Processing)

2- Derleme(Compilation)

3- Çevirme(Assembly)

4- Bağlama(Linking)

Derleyici olarak GNU C Compiler(GCC) programını kullanacağız. Bu 4 aşamayı inceleyebilmek için bazı parametreler vereceğiz:

gcc –Wall –save-temps adder.c –o adder

  • Wall : Tüm derleyici hatalarını bildirmek için kullanılır.
  • save-temps : Derleme aşamalarında oluşan dosyaları da kaydeder.
  • o : Çıktı dosyamıza isim vermemizi sağlar.

1-Ön İşleme(Pre-Processing)

Bu aşamada kaynak kodumuz içindeki;

  • Yorum satırları kaldırılır,
  • Kütüphaneler eklenir,
  • Makrolar eklenir.

Bu aşama sonrasında çalışma dizinimizde ‘adder.i’ dosyası oluşur. Bu dosya içerisine baktığımızda #include, #define satırlarının gittiğini ve yazdığımız koddan çok daha fazlasının eklendiğini görürüz. Kendi yazdığımız bölüme geldiğimizde de yorum satırlarının silindiğini ve tanımladığımız ‘add(a,b)’ makrosu yerine karşılığı olan (a+b)’nin yazıldığını görürüz:

adder.i

2-Derleme(Compilation)

Bu aşamada ‘adder.i’ dosyası derlenir ve çıktı olarak ‘adder.s’ dosyası oluşur. ‘adder.s’ dosyasını açtığınızda 3–4 harfli komutların sıralandığını göreceksiniz. Eğer daha önceden uğraştıysanız bu komutların Assembly diline ait olduğunu hemen anlayabilirsiniz. Özetle bu aşamada hazırlanan C kodları, aşağıda gördüğünüz gibi Assembly kodlarına tercüme edilmektedir.

adder.s

3-Çevirme(Assembly)

Bu aşamada da elde ettiğimiz Assembly kodları Assembler vasıtasıyla makine diline çevrilir ve çıktı olarak ‘adder.o’ dosyası oluşur. Bu aşamada yalnızca bizim yazmış olduğumuz kodların çevirisi yapılır, printf() çağrısı gibi harici kodlar çözümlenmez. Adder.o dosyasının içeriği aşağıdaki gibidir:

adder.o

4-Bağlama(Linking)

Bu son aşamada ise bağlayıcı programı(linker) kodumuzun ihtiyaç duyduğu harici fonksiyon çağrılarını tanımlarıyla birlikte programımıza bağlar. Linker ihtiyaç duyulan bu fonksiyonların nerede bulunduğunu bilir ve programımıza ekstra kodlar ekler. Bu eklemeyi ‘adder.o’ ve ‘adder’ dosyalarının boyutunu kıyaslayarak anlayabilirsiniz.

Yorumlayıcı(Interpreter) Nedir?

Yorumlayıcı, kaynak kodu komut komut okuyup üzerinde çalışılan makinenin komut setine çevirerek çalıştıran bir programdır. Yorumlanarak çalıştırılan yüksek seviyeli diller doğrudan yorumlanmazlar. Genellikle bir ara forma(Opcode, Bytecode vs.) derlenir ve bu kodlar yorumlanarak yerel makine diline çevrilir ve işletilir. Java, PHP, Python gibi yorumlanan diller aslında yorumlama aşamasına geçilmeden önce en az 1 kere derlenirler.

Java’da yazdığımız kodlar ‘.java’ uzantısı ile kaydedilmektedir. Bu ‘.java’ dosyalarının içerisinde bizim yazmış olduğumuz kodlar veya dışarıdan çağırdığımız hazır kodlar bulunabilir ve Java dilinde komutlar bulunur. Örneğin aşağıdaki gibi ‘Adder.java’ isminde iki sayıyı toplayan bir programımız olsun:

Adder.java

Daha sonra tamamlanan kaynak kodlar Java Compiler(Javac) ile derlenerek ‘.class’ uzantılı bytecode denilen dosyalar oluşturulur. Bu dosyaların içerisinde Java Sanal Makinesi(Java Virtual Machine) için oluşturulmuş makine kodları bulunur. Fakat bu kodlar JVM’e özel olarak derlenmiştir. Yerel işlemcinin komut setinden farklıdır. Aşağıda Adder.java kaynak kodlarının derlenmesi sonucu oluşturulan ‘Adder.class’ dosyasının içeriğinin bir kısmı görülmektedir:

Adder.class

Java yorumlayıcısı JVM’in bir parçası olarak tam da bu noktadan sonra çalışmaktadır. Oluşturulan bu bytecode dosyalarını komut komut işleyerek yerel makine diline çevirir ve çalıştırır. Program bu şekilde işletilmiş olur. Böylece yazılan bir Java kodu önce derlenerek bytecode’a çevrilir, ardından yerel makine koduna yorumlanarak çalıştırılır.

PHP’de benzer bir şekilde çalışmaktadır. Buradaki işlemleri ise Zend Engine üstlenmektedir. Yazılan bir PHP kodu ZendOpcode denilen bir ara koda dönüştürülür. Daha sonra Zend Engine bu kodları işleterek yerel makine üzerinde çalıştırır ve hedeflenen çıktıları (HTML gibi) elde eder.

Bu yazıya başlayana kadar Python’u derlenen bir dil olarak bilsem ve doğrudan işlemci üzerinde koştuğunu zannetsem de gerçek bundan farklıymış. Yazılan bir Python programı bir Java programına benzer adımlardan geçmekteymiş. Yazdığımız kodları barındıran ‘.py’ uzantılı dosya öncelikle derlenerek bytecode’a çevrilmekte ve ‘Derlenmiş Python Dosyası(Compiled Python Files)’ anlamına gelen ‘.pyc’ uzantılı bir dosya içerisine yazılmaktaymış. Ardından bu bytecode’lar tıpkı Java’da olduğu gibi Pyton yorumlayıcısı tarafından yorumlanmakta ve işletilmektedir. Bu yüzden Python için de bir sanal makinenin varlığından söz edebiliriz. Fakat yukarıda da bahsettiğim gibi bir dil için tek bir kıstas yoktur. Sadece derlenir veya sadece yorumlanır demek yanlış olur. Bu çıkarımlar dili ortaya atan insanların bize sunmuş olduğu standart yapıya göre yapılmaktadır ve onların bize sunmuş olduğu derleyici veya yorumlayıcı yazılımlar ön plana çıkmaktadır. Fakat bir dil için farklı yorumlayıcı veya derleyiciler geliştirilebilir. Örneğin Python kodlarını Java platformuna taşıyan Jython ve C ortamına taşıyan cPython buna örnek olarak verilebilir.

Bu konu hakkında yazabileceklerim bu kadar. Tavsiye, öneri ve düzeltmelerinizi benimle paylaşırsanız sevinirim. Bir başka yazıda görüşmek dileğiyle.

KAYNAKLAR

http://www.geeksforgeeks.org/compiling-a-c-program-behind-the-scenes/

http://introcs.cs.princeton.edu/java/82compiler/

http://swatij.me/python/python-interpreted-or-compiled/

https://stackoverflow.com/questions/2998215/if-python-is-interpreted-what-are-pyc-files

--

--