giriş
Tipik bir derleyici aşağıdaki adımları gerçekleştirir:
- Ayrıştırma: kaynak metin, soyut bir sözdizimi ağacına (AST) dönüştürülür.
- Referansların diğer modüllere çözümlenmesi (C, bu adımı bağlantı verene kadar erteler).
- Anlamsal doğrulama: ulaşılamayan kod veya yinelenen beyannameler gibi hiçbir anlam ifade etmeyen sözdizimsel olarak doğru beyanları ayıklamak.
- Eşdeğer dönüşümler ve üst düzey optimizasyon: AST, aynı semantik ile daha verimli bir hesaplamayı temsil edecek şekilde dönüştürülür. Bu, örneğin, aşırı yerel atamaları ortadan kaldırarak (ayrıca SSA'ya bakınız ) vb . Ortak alt ifadelerin ve sabit ifadelerin erken hesaplanmasını içerir .
- Kod oluşturma: AST, atlamalar, kayıt tahsisi ve benzerleriyle lineer düşük seviye koda dönüştürülür. Bazı işlev çağrıları bu aşamada, bazı döngüler kontrolsüz vb.
- Gözetleme deliği optimizasyonu: Düşük seviyeli kod, ortadan kaldırılan basit yerel verimsizliklere karşı taranır.
Modern derleyicilerin çoğu (örneğin, gcc ve clang) son iki adımı bir kez daha tekrarlar. İlk kod oluşturma için orta seviye düşük ama platformdan bağımsız bir dil kullanıyorlar. Daha sonra bu dil, platforma özgü bir şekilde aşağı yukarı aynı şeyi yaparak platforma özgü bir koda (x86, ARM vb.) Dönüştürülür. Bu, örneğin mümkünse vektör talimatlarının kullanımını, dal tahmin verimliliğini arttırmak için talimatların yeniden düzenlenmesini vb.
Bundan sonra, nesne kodu bağlantı için hazırdır. Yerel kod derleyicilerinin çoğu, yürütülebilir bir dosya üretmek için bir bağlayıcıyı nasıl arayacaklarını bilir, ancak bu bir derleme adımı değildir. Java ve C # gibi dillerde, VM tarafından yükleme sırasında yapılan tamamen dinamik olabilir.
Temelleri hatırla
- Çalışmasını sağla
- Güzel yapmak
- Verimli yapmak
Bu klasik dizi, tüm yazılım geliştirme için geçerlidir, ancak tekrarlama yapar.
Dizinin ilk basamağına konsantre olun. İşe yarayabilecek en basit şeyi yarat.
Kitapları oku!
Aho ve Ullman'ın Dragon Kitabı'nı okuyun . Bu klasik ve bugün hala oldukça uygulanabilir.
Modern Derleyici Tasarımı da övgüyle karşılandı.
Bu şey şu anda sizin için çok zorsa, önce ayrıştırma hakkında bazı tanıtımları okuyun; genellikle kütüphaneleri ayrıştırma intros ve örnekler içerir.
Özellikle ağaçlarla grafiklerle çalışırken rahat olduğunuzdan emin olun. Bu şeyler, programların mantıksal düzeyde yapıldığı şeylerdir.
Dilinizi iyi tanımlayın
İstediğiniz gösterimi kullanın, ancak dilinizin tam ve tutarlı bir tanımına sahip olduğunuzdan emin olun. Bu, hem sözdizimi hem de anlambilimi içerir.
Gelecekteki derleyici için test senaryoları olarak yeni dilinizde kod parçacıkları yazma zamanı geldi.
Favori dilini kullan
Python veya Ruby'de bir derleyici yazmak veya sizin için hangi dilde olursa olsun tamamen sorun değil. İyi anladığınız basit algoritmalar kullanın. İlk sürümün hızlı, verimli veya özellik tamamlayıcı olması gerekmez. Sadece yeterince doğru ve değiştirilmesi kolay olması gerekiyor.
Gerektiğinde derleyicinin farklı aşamalarını farklı dillerde yazmak da sorun değil.
Çok fazla test yazmaya hazırlanın
Tüm diliniz test durumlarıyla örtülmeli; etkili bir şekilde onlar tarafından tanımlanacaktır . Tercih ettiğiniz test çerçevesiyle tanışın. İlk günden itibaren testleri yazın. Yanlış kod tespiti yerine, doğru kodu kabul eden 'pozitif' testlere yoğunlaşın.
Tüm testleri düzenli olarak yapın. Devam etmeden önce kırık testleri düzeltin. Geçerli bir kodu kabul edemeyen kötü tanımlanmış bir dille bitmek utanç verici olur.
İyi bir ayrıştırıcı oluşturun
Ayrıştırıcı jeneratörler çoktur . Ne istersen seç. Ayrıca sıfırdan kendi ayrıştırıcı yazmak olabilir, ama bu sadece değer senin dilin sözdizimi ise ölü basit.
Ayrıştırıcı sözdizimi hatalarını algılamalı ve raporlamalıdır. Hem olumlu hem de olumsuz birçok test vakası yazın; Dili tanımlarken yazdığınız kodu tekrar kullanın.
Ayrıştırıcınızın çıktısı soyut bir sözdizimi ağacıdır.
Dilinizde modüller varsa, çözümleyicinin çıktısı, oluşturduğunuz 'nesne kodunun' en basit gösterimi olabilir. Bir ağacı bir dosyaya dökmek ve hızlı bir şekilde geri yüklemek için birçok basit yol vardır.
Anlamsal bir doğrulayıcı oluşturun
Büyük olasılıkla diliniz, belirli bağlamlarda anlam ifade etmeyen sözdizimsel olarak doğru yapılara izin verir. Bir örnek, aynı değişkenin yinelenen bir bildirimidir veya yanlış türde bir parametreyi iletmektedir. Doğrulayıcı, ağaca bakarak bu tür hataları algılar.
Doğrulayıcı, kendi dilinizde yazılmış diğer modüllere referansları da çözecek, bu diğer modülleri yükleyecek ve doğrulama işleminde kullanacaktır. Örneğin, bu adım başka bir modülden bir işleve geçirilen parametre sayısının doğru olduğundan emin olacaktır.
Yine birçok test senaryosu yazıp çalıştırın. Önemsiz durumlar, akıllı ve karmaşık sorun giderme işlemlerinde vazgeçilmezdir.
Kodunu oluşturun
Bildiğiniz en basit teknikleri kullanın. Genellikle, bir dil yapısını (bir if
ifade gibi ) bir HTML şablonundan farklı olarak, hafif parametreli bir kod şablonuna doğrudan çevirmek uygundur .
Yine, verimliliği yok sayın ve doğruluğa odaklanın.
Platformdan bağımsız, düşük seviyeli bir VM'yi hedefleyin
Donanıma özgü ayrıntılara özellikle ilgi duymadığınız sürece düşük seviyeli şeyleri görmezden geldiğinizi varsayalım. Bu ayrıntılar kanlı ve karmaşıktır.
Seçenekleriniz:
- LLVM: genellikle x86 ve ARM için verimli makine kodu oluşturulmasına izin verir.
- CLR: .NET, çoğunlukla x86 / Windows tabanlı; JIT’i iyi.
- JVM: Java dünyasını hedef alıyor, çok platformlu, iyi bir JIT'ye sahip.
Optimizasyonu yoksay
Optimizasyon zor. Neredeyse her zaman optimizasyon erkendir. Verimsiz ama doğru kod oluşturun. Ortaya çıkan kodu optimize etmeye çalışmadan önce tüm dili uygulayın.
Tabii ki, önemsiz optimizasyonlar tanıtmak için tamam. Ancak derleyiciniz kararlı olmadan önce kurnaz, tüylü şeylerden kaçının.
Ne olmuş yani?
Bütün bunlar senin için çok korkutucu değilse, lütfen devam et! Basit bir dil için, adımların her biri düşündüğünüzden daha basit olabilir.
Derleyicinizin oluşturduğu bir programdan 'Merhaba dünyayı' görmek çabaya değer olabilir.