1 puan yazan GN⁺ 2025-12-12 | 1 yorum | WhatsApp'ta paylaş
  • 1988~1995 yılları arasında yayımlanan Jack Crenshaw'ın ‘Let’s Build a Compiler’ kılavuzunu Python ve WebAssembly ile yeniden uygulayan bir proje
  • Orijinalde Pascal ve Motorola 68000 assembly kullanılmıştı, ancak bu çalışmada modern bir ortamda çalışabilir koda dönüştürüldü
  • Kılavuzun odak noktası, özyinelemeli iniş ayrıştırıcısını (recursive-descent parser) doğrudan uygulamak ve ilk aşamalardan itibaren gerçek assembly kodu üretmeye geçmek oldu
  • Crenshaw’nin yaklaşımı söz dizimi yönlendirmeli çeviri (syntax-directed translation) kullanıyor, ancak tip işleme aşamasında sınırlılıklarını gösteriyor
  • Bu yeniden uygulama, klasik kılavuzu modern geliştiricilerin doğrudan çalıştırıp deneyebileceği bir biçimde geri getirmesi açısından önem taşıyor

Klasik kılavuzun arka planı

  • Jack Crenshaw'ın ‘Let’s Build a Compiler’ 1988~1995 yılları arasında yayımlanan, bugün hâlâ sıkça anılan bir derleyici yapım eğitim kaynağıdır
    • Orijinal metin Pascal ile yazılmıştı ve Motorola 68000 assembly kodu üretirdi
    • 35 yıl sonra, 2025'te bile Hacker News gibi platformlarda düzenli olarak gündeme geliyor
  • Yazar bu kılavuzla 2003'te ilk kez karşılaştığında derin bir etki aldığını ve 2025'te onu Python ile WebAssembly'e yeniden taşıdığını anlatıyor

Python ve WebAssembly ile yeniden uygulama

  • Sadece okumakla kalmayıp, kılavuzun derleyicisini Python'a çevirip WebAssembly (WASM) üretecek şekilde uygulanmış
  • Çıktı, GitHub deposunda (eliben/letsbuildacompiler) yayınlanıyor
    • TUTORIAL.md dosyasında her bölümün orijinal metinden Python koduna nasıl eşlendiği açıklanıyor
    • Kullanıcılar, orijinal kılavuzu okurken doğrudan çalıştırılabilir kodlar ile deney yapabiliyor

KISS dili örneği ve WASM çıktısı

  • Crenshaw tarafından tasarlanan KISS dilinin örnek programı, Python sürümü derleyici ile derlenmiş hâliyle gösteriliyor
    • Örnek, procedure, while döngüsü ve değer iletimi ile referans iletimini içeriyor
  • Üretilen WASM metni, başvuru parametresi (by-reference parameter) işleme mantığını içeriyor ve optimizasyon neredeyse hiç uygulanmamış
  • main fonksiyonunda global değişken Xin örtülü olarak döndürülmesi, test kolaylığı için eklenmiş bir düzenektir
  • Üretilen WASM kodu, gerçek çalıştırmayla beklenen sonucu doğrulamak için testlerde kullanılıyor

Kılavuzun güçlü yönleri

  • Crenshaw’nin kılavuzu özyinelemeli iniş ayrıştırıcısını adım adım inşa ederken, karmaşık teoriye göre doğrudan çalışan kod üretimine öncelik verir
    • O dönemde lex ve yacc standart araçlar olarak görülmesine rağmen, el ile yazılan ayrıştırıcının sadeliği ve açıklığı güçlü bir etki bırakır
    • Yazar daha sonraki 20 yıl boyunca manuel özyinelemeli iniş ayrıştırıcısını tercih etmeye başlar
  • Ayrıca çoğu dersin yalnızca sözdizimi çözümlemeye odaklandığı bir dönemde Crenshaw, başlangıç aşamalarından itibaren assembly kod üretimini ele alır

Sınırlamalar ve geliştirme potansiyeli

  • Kılavuz, ayrıştırma sırasında doğrudan kod üretmek için söz dizimi yönlendirmeli çeviri (syntax-directed translation) yaklaşımını kullanır
    • Bu yöntem eğitici olarak faydalı olsa da, önceden tür bilgisinin bilinmemesinden dolayı optimizasyonun zor olduğu bir sınıra takılır
  • Özellikle türlerin 14. bölümde tanıtılmasından sonra orta seviye temsil (IR) veya AST kullanan yapısal bir yaklaşımın gerekliliği ortaya çıkar
  • Crenshaw'nin 14. bölümden sonra kılavuza ara vermesinin nedeni belirtilmemiş olsa da, bunun bu sınırlamayla ilgili olabileceği öne sürülüyor
  • Yazar, 14. bölümü bir dönüm noktası kabul ederek, tür denetimi ve kod üretiminin AST üretildikten sonra yapılmasının daha uygun olduğu görüşünde

Sonuç

  • Orijinal kılavuz, hâlâ bir derleyici yapım giriş kitabı olarak yüksek okunabilirlik ve pratiklik sunuyor
  • Bu Python·WASM sürümü, modern geliştiricilerin eski teknolojilere saplanmadan öğrenebilmeleri için tamamlayıcı bir uygulama olarak sunuluyor
  • GitHub deposu sayesinde herkesin deney yapabilmesi mümkün; derleyici mimarisini doğrudan deneyimleme şansı veren modern bir yeniden yorum olarak değerlendiriliyor

1 yorum

 
GN⁺ 2025-12-12
Hacker News görüşleri
  • Frontend ayrıntılarında kaybolmadan, en baştan itibaren doğrudan çalışan assembly kodu üreten bir öğreticiyi beğendim
    Ghuloum’un yaklaşımında olduğu gibi dilin çok küçük bir parçasından başlayıp tüm yapıyı adım adım genişleten yöntem özellikle çekici
    Yakın zamanda keşfettiğim iyi bir kitap da bu bağlantıdaki kitap; C ve x86 yeni başlayanlar için en ideal hedefler olmasa da ilk derleyiciyi yapmak için harika bir kaynaktı
    Bu arada Ghuloum’un makalesi burada

    • Bu nadir durumlardan biri ama akademik yaklaşımın pratikte yararlılıkla pek örtüşmediği bir örnek olduğunu düşünüyorum
      Eskiden parsing en önemli kısımdı, bu yüzden müfredat da öyle şekillenmişti; bugünse dil özelliklerinin nasıl uygulanacağı daha önemli
      Kendi derleyicini yazıyor olsan bile artık “Claude, bana bu gramer için bir recursive descent parser yaz” dediğinde çoğu zaman tek seferde sonuç alabildiğin bir dönemdeyiz
    • Akademik araştırmacılarla pratikte çalışan geliştiriciler arasındaki farkı hissettim
      Akademi katman (layer) temelli, uygulamacılar ise boru hattı (pipe) temelli yaklaşma eğiliminde
      Katman yaklaşımı derlenebilir kod verir ama çalıştırması zordur; boru hattı yaklaşımı ise çalıştırmayı kolaylaştırır ama yapısallığı zayıftır
      Sonuçta asıl mesele, geliştirmeyi çalıştırılabilir en küçük birimlere bölmektir
  • Bence bu yazı gerçekten meselenin özünü çok iyi yakalamış
    Üniversiteye gitmeden önce bile derleyicilere ilgim vardı ve bu kaynak karşılaştığım en erişilebilir giriş materyaliydi
    17 yaşındayken recursive descent parser’ı kendim yazarak, karmaşık görünen sorunların doğru primitive’lere bölündüğünde basitleştiğini fark etmiştim

    • “Problemi doğru primitive’lere bölmek” programlamanın asıl özüdür
      Algoritmalar hakkında çok kaynak var ama problemlere primitive düzeyinde nasıl yaklaşılacağını anlatan kaynak az
    • Recursive descent yalnızca parser yazma yöntemi değil, aynı zamanda program tasarımı için bir ders
      Eskiden yacc gibi tablo tabanlı parser’lar baskındı ama bugün recursive descent daha pratik ve esnek
      LLM ile kod üretimi sayesinde bu yaklaşım daha da kolaylaştı
      Öğrenme amaçlı oyuncak derleyicilerde AST, IR veya optimizasyonu atlayıp doğrudan kod üretimine geçmek bile fazlasıyla öğretici olabilir
      Eskiden şirkette C’nin bir alt kümesini destekleyen bir test aracı yaparken, parser’ın kod üretmek yerine çalıştırılabilir veri yapıları döndürmesini sağlamıştık
      Örneğin ForLoopStatement sınıfı bir testExpression içeriyor ve Execute() metodu bunu doğrudan çağırıyordu
    • Niklaus Wirth’ün 1971 tarihli Program Development by Stepwise Refinement makalesi, bu düşünme biçimini erken dönemde en iyi ortaya koyan klasiklerden biri
      Fred Brooks’un The Mythical Man-Month kitabında da anılan önemli bir makale
    • Bugünlerde parsing gerektiğinde çoğu kez parser combinator kullanıyorum
      Kavramsal olarak çok doğal ve temiz geliyor
  • Jack Crenshaw’ın öğreticisinde syntax-directed translation yaklaşımının kullanıldığı açıklaması ilginç geldi
    Bunun yalnızca single-pass compiler anlamına mı geldiğini, yoksa daha özel bir kavram mı olduğunu merak ediyorum
    Statik tipli dillerde tür tabanlı optimizasyonun zor olduğunu anlıyorum ama tür denetimi düzeyinde de kısıtlar olup olmadığını bilmek isterim

    • Hedef dil tanımdan sonra kullanım kuralını izliyorsa ve karmaşık tür çıkarımı yoksa, tür tabanlı optimizasyonlar veya constant folding gibi şeyler mümkün olur
      Ama IR yoksa LICM, CSE, GVN gibi ileri seviye optimizasyonlar yapılamaz
      Ben şahsen fonksiyon bazında 2 geçişli derlemeyi tercih ediyorum — ilk geçişte IR oluşturup, hemen ardından kod üretip durumu atarak hızlı ve verimli sonuç alınabiliyor
    • syntax-directed translation daha özel bir kavram; kaynak kod okunurken anında kod üretimi yapılması anlamına gelir
      Single-pass compiler olsa bile aşamalar ayrılıp kod üretimi sadece en sonda da yapılabilir
  • Crenshaw’ın öğreticisi pratik düzeye kadar gitmese de, precedence climbing tekniğiyle genişletilirse çok daha kullanışlı hale geliyor
    İlgili yazı bu bağlantıda güzelce anlatılmış

  • “Let’s Build a Compiler” ile ilgili başlıklara tekrar göz attım
    2007’den 2023’e kadar HN’de birkaç kez paylaşıldığına dair kayıtlar var
    Özellikle Jack Crenshaw röportajı yorum içermese de çok ilginç bir okumaydı

    • Dördüncü bağlantı Crenshaw’ın yazısı değil, aynı başlığı taşıyan başka bir yazı
    • Crenshaw röportajı gerçekten çok iyiydi
  • Kendi projem için küçük bir tanıtım da yapayım: cwerg.org
    Python ve recursive descent parsing kullanıyor, frontend ile backend’i IR üzerinden ayırıyor
    x86 ve ARM için ELF ikilileri üretiyor ve gerçek kullanım hedefleniyor
    Ama epey karmaşık; öğretici tarzda bir şey değil

  • Eskiden USENET’teki comp.compilers haber grubunda Jack Crenshaw’ın öğreticisini öğrenmiş olmanın nostaljisini yaşadım
    Bu arada o grup hâlâ aktif

  • Modern bir derleyici yaklaşımı için şu Cornell blog yazısını öneririm

    • LLVM sayesinde derleyici yapmak şaşırtıcı derecede kolaylaştı
      Her kullandığımda kendimi sanki bir piramidin üstüne birkaç taş daha koyuyormuşum gibi hissediyorum
    • Ama LLVM dolaylı bir yaklaşım olduğu için sınırları var
      LLVM’i backend olarak kullanan dillerde ortak nokta yavaş derleme hızları
      Zig bunun farkında ve kendi backend’ini geliştiriyor; Rust ise hâlâ yavaş derleme sürelerine bağlı
      LLVM, karmaşıklığın kaliteyi garanti ettiği yanılsamasını veriyor ve geliştiricinin özerkliğini zayıflatan bir teknoloji gibi geliyor
      Bu, popüler başka bazı teknolojilere de benziyor (baş harfleri de benzer)
  • Ben de benzer nedenlerle tiny-optimizing-compiler adlı bir öğretici yazdım
    Derleyicinin yalnızca ara aşamaları ve backend kısmını ele alan kısa bir örnek
    GitHub bağlantısı

    • Bunu Lean ile gerçekleştirmek eğlenceli olabilir
  • Küçükken bu öğreticiyi çıktısını alıp yanımda taşıyarak okurdum
    Kısa sürede bir derleyicinin tamamlandığını görmek gerçekten harikaydı
    Beej’s Guide gibi bu tür materyaller CS eğitimindeki en değerli belgelerden bazıları ama hak ettikleri değeri görmüyorlar