Orijinal tercümandan bağımsız bir “önyükleme” tercümanı oluşturmak mümkün mü?


21

Wikipedia'ya göre , derleyici yazma bağlamında "önyükleme" terimi şu anlama gelir :

Bilgisayar bilimlerinde önyükleme, derlemek istediği kaynak programlama dilinde bir derleyici (veya bir derleyici) yazma işlemidir. Bu tekniğin uygulanması, kendi kendini barındıran bir derleyiciye yol açar.

Ve bunun nasıl işe yarayacağını anlayabiliyorum. Ancak, hikaye tercümanlar için biraz farklı görünüyor. Şimdi, elbette, kendi kendini barındıran bir tercüman yazmak mümkündür. İstediğim bu değil. Aslında sorduğum şey: Orijinal, ilk tercümandan bağımsız olarak kendi kendine barındırılan bir tercüman yapmak mümkün mü . Ne demek istediğimi açıklamak için şu örneği düşünün:

İlk tercüman versiyonunuzu X dilinde yazıyorsunuz ve tercüman Y oluşturduğunuz yeni bir dil için . Yürütülebilir bir dosya oluşturmak için önce X dilinin derleyicisini kullanırsınız. Artık, X dilinde yazılmış tercümanı kullanarak, yeni Y dilinizde yazılmış dosyaları yorumlayabilirsiniz .

Şimdi, anladığım kadarıyla, X dilinde yazdığınız tercümanı "önyükleyebilmek" için tercümanı Y dilinde yeniden yazmanız gerekir . Ancak buradaki cevap: tercümanın tamamını Y dilinde yeniden yazsanız bile , X dilinde yazdığınız orijinal tercümana hala ihtiyacınız olacak . Tercümanı Y dilinde çalıştırmak için kaynak dosyaları yorumlamanız gerekecektir. Peki kaynak dosyaları tam olarak ne yorumlayacak? Tabii ki hiçbir şey olamaz, bu yüzden hala ilk tercümanı kullanmaya zorlanıyorsunuz.

Y dilinde ne kadar yeni tercüman yazdığınız önemli değildir , sonraki tercümanları yorumlamak için her zaman X ile yazılmış ilk tercümanı kullanmak zorunda kalacaksınız . Bu sadece tercümanların doğası gereği bir sorun gibi görünüyor.

Ancak , çevirme tarafında, Tercümanlar hakkında Bu Wikipedia makalesi, aslında kendini barındıran tercümanlar hakkında konuşuyor . İşte alakalı olan küçük bir alıntı:

Bir kendi kendine tercüman, kendi kendini yorumlayabilen bir programlama dilinde yazılmış bir programlama dili tercümanıdır; bir örnek, BASIC dilinde yazılmış bir BASIC yorumlayıcısıdır. Kendi kendine tercümanlar, kendini barındıran derleyicilerle ilgilidir.

Yorumlanacak dil için bir derleyici mevcut değilse, bir kendini tercüman oluşturmak, dilin bir ana dilde (başka bir programlama dili veya montajcısı olabilir) uygulanmasını gerektirir. Bunun gibi bir ilk tercümana sahip olmakla birlikte, sistem önyüklenir ve tercümanın yeni sürümleri dilin kendisinde geliştirilebilir

Yine de, bana bunun tam olarak nasıl yapılacağı belli değil. Görünüşe göre, ne olursa olsun, tercümanınızın ilk sürümünü ana bilgisayar dilinde yazılmış olarak kullanmak zorunda kalacaksınız.

Şimdi yukarıda bahsedilen makale, Vikipedi'nin sözde kendini barındıran tercümanlardan bazı örnekler verdiği başka bir makaleye bağlantı vermektedir . Daha yakından bakıldığında, bu kendi kendini barındıran tercümanların çoğunun (özellikle PyPy veya Rubinius gibi daha yaygın olanlardan bazıları) ana "tercümanlık" bölümünün aslında C ++ veya C gibi diğer dillerde yazılmış olduğu görülmektedir.

Peki yukarıda tarif ettiğim şey mümkün mü? Kendi kendine barındırılan bir tercüman, ilk sunucusundan bağımsız olabilir mi? Eğer öyleyse, bu tam olarak nasıl yapılır?

Yanıtlar:


24

Kısa cevap: şüphede haklısın, her zaman X'te yazılmış başka bir tercümana ya da Y'den bir tercümana sahip olduğun başka bir dile derleyiciye ihtiyacın var. Tercümanlar derleyiciler sadece bir dilden diğerine tercüme de, yürütme bazı sisteminizde noktası, orada gerekir hatta sadece işlemci bulunuyor ... tercüman olmak.

Y dilinde ne kadar yeni tercüman yazdığınız önemli değildir , sonraki tercümanları yorumlamak için her zaman X ile yazılmış ilk tercümanı kullanmak zorunda kalacaksınız . Bu sadece tercümanların doğası gereği bir sorun gibi görünüyor.

Doğru. Ne yapabilirsiniz yapmak bir derleyici yazmak olduğunu Y'ye için X (veya tercüman olan başka bir dil), ve hatta o yapabilirsiniz Y . Sonra da çalıştırabilirsiniz Y yazılmış derleyici Y üzerinde Y yazılmış tercüman X (veya Y ile yazılmış tercüman Y üzerinde çalışan Y yazılmış tercüman X veya üzerinde Y yazılmış tercüman Y üzerinde çalışan Y yazılmış tercüman Y üzerinde çalışan YX ile yazılmış tercüman , ya da… ad infinitum) , Y ile X arasında yazılmış Y tercümanınızı derleyin , böylece daha sonra bir X tercüman üzerinde çalıştırabilirsiniz . Bu yolla, X dilinde yazılmış Y tercümanınızdan kurtuldunuz , ancak şimdi X tercümanına ihtiyacınız var (zaten bir taneye sahip olduğumuzu biliyoruz, çünkü aksi halde Y ile yazılmış X tercümanını koyamadık ) ve siz önce bir Y- to- X- derleyici yazmak zorunda kaldım .

Ancak , çevirme tarafında, tercümanlar hakkındaki Wikipedia makalesi aslında kendini barındıran tercümanlar hakkında konuşuyor. İşte alakalı olan küçük bir alıntı:

Bir kendi kendine tercüman, kendi kendini yorumlayabilen bir programlama dilinde yazılmış bir programlama dili tercümanıdır; bir örnek, BASIC dilinde yazılmış bir BASIC yorumlayıcısıdır. Kendi kendine tercümanlar, kendini barındıran derleyicilerle ilgilidir.

Yorumlanacak dil için bir derleyici mevcut değilse, bir kendini tercüman oluşturmak, dilin bir ana dilde (başka bir programlama dili veya montajcısı olabilir) uygulanmasını gerektirir. Bunun gibi bir ilk tercümana sahip olmakla birlikte, sistem önyüklenir ve tercümanın yeni sürümleri dilin kendisinde geliştirilebilir

Yine de, bana bunun tam olarak nasıl yapılacağı belli değil. Görünüşe göre, ne olursa olsun, tercümanınızın ilk sürümünü ana bilgisayar dilinde yazılmış olarak kullanmak zorunda kalacaksınız.

Doğru. Wikipedia makalesinin açıkça , dilinizin ikinci bir uygulamasına ihtiyacınız olduğunu söylediğini ve ilkinden kurtulabileceğinizi söylemediğini unutmayın.

Şimdi yukarıda belirtilen makale, Vikipedi'nin sözde kendini barındıran tercümanlardan bazı örnekler verdiği başka bir makaleye bağlantı vermektedir. Daha yakından bakıldığında, bu kendi kendini barındıran tercümanların çoğunun (özellikle PyPy veya Rubinius gibi daha yaygın olanlardan bazıları) ana "tercümanlık" bölümünün aslında C ++ veya C gibi diğer dillerde yazılmış olduğu görülmektedir.

Yine doğru. Bunlar gerçekten kötü örneklerdir. Mesela Rubinius'u ele alalım. Evet, Rubinius’un Ruby kısmının kendi kendini barındırdığı doğrudur, ancak bir derleyicidir, tercüman değildir: Ruby kaynak kodunu Rubinius bytecode’a derler. Tercüman bölümü OTOH kendine ait değildir: Rubinius bytecode'unu yorumlar, fakat C ++ ile yazılmıştır. Bu nedenle, Rubinius'u "kendi kendine barındırılan bir tercüman" olarak adlandırmak yanlıştır: Kendi kendine barındırılan bölüm bir tercüman değildir ve söz konusu tercüman bölüm kendi kendine barındırılamaz .

PyPy benzer, ancak daha da yanlış: ilk etapta Python'da bile yazılmıyor, farklı bir dil olan RPython'da yazıyor. Anlamsal olarak "genişletilmiş bir alt küme" olan Python'a sözdizimsel olarak benzer, ancak aslında Java ile aynı soyutlama düzeyinde kabaca statik olarak yazılmış bir dildir ve uygulaması, RPython'u C kaynak koduna (ECMAScript) derleyen çoklu arka uçlara sahip bir derleyicidir kaynak kodu, CIL bayt kodu, JVM bayt kodu veya Python kaynak kodu.

Peki yukarıda tarif ettiğim şey mümkün mü? Kendi kendini barındıran bir tercüman asıl sunucusundan bağımsız olabilir mi? Eğer öyleyse, bu tam olarak nasıl yapılır?

Hayır, kendi başına değil. Orijinal tercümanı tutmanız veya bir derleyici yazmanız ve kendi tercümanınızı derlemeniz gerekir.

Orada olan bazı meta-dairesel gibi VM'lerin, Klein (yazılı Öz ) ve Maxine (Java ile yazılmış). Bununla birlikte, burada "meta-dairesel" tanımının farklı olduğunu unutmayın: bu VM'ler yürüttükleri dilde yazılmaz : Klein, Self bytecode'u çalıştırır ancak Self'de yazılır, Maxine JVM bytecode'u çalıştırır ancak Java'da yazılmıştır. Ancak, VM Öz / Java kaynak kodu aslında Öz / JVM bayt kodu derlenmiş ve daha sonra VM tarafından yürütülen, böylece zaman VM işletilirse alır, bu ise o yürütür dilinde. Uf.

Bunun SqueakVM ve Jikes RVM gibi VM'lerden farklı olduğunu da unutmayın . Jikes, Java ile yazılmıştır ve SqueakVM, Slang'da (kabaca üst seviye bir montajcı ile aynı soyutlama düzeyinde statik olarak yazılmış bir sözdizimsel ve anlamsal bir Smalltalk alt kümesi) yazılmıştır ve her ikisi de çalıştırılmadan önce yerel koda statik olarak derlenir. Kendi içlerinde koşmazlar. Sen olabilir , ancak, onları çalıştırmak on-top kendilerini (veya başka bir Smalltalk VM / JVM üstünde). Ancak bu anlamda “meta-dairesel” değildir.

Maxine ve Klein, OTOH yapmakkendi içlerinde koşmak; kendi uygulamalarını kullanarak kendi bayt kodlarını uygularlar. Bu gerçekten akıl almaz! Bazı serin optimizasyon fırsatlarına izin verir, örneğin VM, kullanıcı programı ile birlikte kendisini yürüttüğü için, kullanıcı programından VM'ye yapılan çağrıları sıraya koyabilir ve tam tersi, örneğin çöp toplayıcısına yapılan çağrı veya bellek ayırıcı kullanıcının içine girebilir kodu ve kullanıcı kodundaki yansıtıcı geri aramalar, Sanal Makineye dahil edilebilir. Ayrıca, modern VM'lerin yürüttüğü akıllı optimizasyon püf noktalarının tümü, yürütme programını izleyen ve gerçek iş yüküne ve verilere göre optimize ettikleri yerde, VM, kullanıcı programı yürütürken kullanıcı programını yürütürken aynı püf noktalarını kendine uygulayabilir belirli iş yükünü yürütüyor. Başka bir deyişle, VM bunun için kendini uzmanlaştıçalışan belli bir program olduğunu belli iş yükü.

Ancak, yukarıda "tercüman" kelimesini kullandığımı fark ettim ve her zaman "execute" kullandım? Eh, bu VM'ler tercümanların etrafında kurulmazlar, bunlar (JIT) derleyicileri etrafında kurulur. Daha sonra Maxine'ye eklenmiş bir tercüman vardı, ancak her zaman derleyiciye ihtiyacınız var: VM'yi bir kez daha başka bir VM'nin üzerinde çalıştırmanız gerekir (örneğin, Maxine durumunda Oracle HotSpot), böylece VM (JIT) kendisini derleyebilir. Maxine söz konusu olduğunda, JIT kendi önyükleme aşamasını derleyecek, daha sonra yerel kodu bir önyükleme VM görüntüsüne derleyecektir ve çok basit bir önyükleyiciyi ön tarafa yerleştirecektir (sadece C için yazılmış VM'nin tek bileşeni) , ayrıca Java da olabilir). Artık Maxine'i çalıştırmak için kullanabilirsiniz.


Yeesh . Kendini barındırma tercümanlarının dünyasının bu kadar yapışkan olduğunu hiç bilmiyordum! Yine de güzel bir genel bakış için teşekkür ederiz.
Christian Dean

1
Haha, peki, neden dünya konseptten daha az zihin bükmeli? ;-)
Jörg W Mittag

3
Sanırım sorunlardan biri, insanların söz konusu dillerle sık sık hızlı ve gevşek oynadığıdır. Örneğin, Rubinius genellikle "Ruby'de Ruby" olarak adlandırılır, ancak bu hikayenin sadece yarısıdır. Evet, kesinlikle konuşursak , Rubinius'taki Ruby derleyicisi Ruby'de yazılmıştır, ancak bytecode'ı çalıştıran VM değildir. Ve daha da kötüsü: PyPy'ye genellikle "Python'da Python" denir, ancak aslında orada tek bir Python satırı yoktur. Her şey Python programcılarına aşina olmak için tasarlanmış, ancak Python değil RPython'da yazılmıştır . Aynı şekilde SqueakVM: Smalltalk dilinde yazılmadı,…
Jörg W Mittag

… Aslında içinde kodlanan insanlara göre, soyutlama yeteneklerinde C'den bile daha kötü olan Slang'da yazılmıştır. Slang'ın tek avantajı, Smalltalk'ın uygun bir altkümesi olması ve güçlü bir Smalltalk IDE'yi geliştirebileceğiniz (ve VM'de hata ayıklayabileceğiniz) çalıştırabileceğiniz anlamına gelir.
Jörg W Mittag

2
Sadece başka bir komplikasyon eklemek için: Yorumlanan bazı diller (örneğin, FORTH ve muhtemelen TeX), çalışan sistemin yüklenebilir bir hafıza görüntüsünü çalıştırılabilir bir dosya olarak yazabilir. Bu anlamda, bu tür sistemler daha sonra orijinal yorumlayıcı olmadan çalışabilir. Örneğin, bir keresinde farklı bir CPU için 32 bit sürümü "çapraz yorumlamak" ve farklı bir işletim sistemi üzerinde çalıştırmak için 16 bit FORTH sürümünü kullanarak bir FORTH yorumlayıcısı yazdım. (FORTH dilinin kendi derleyicisini içerdiğine dikkat edin, bu nedenle "FORTH VM" (genellikle yalnızca 10 veya 20 makine kodu yönergesidir)
FORTH'un

7

Kendi kendini barındıran bir tercümanın kendisini çalıştırmak için hala bir tercüman gerektirdiğini ve derleyici ile aynı anlamda önyüklenemeyeceğini belirttiniz.

Ancak, kendi kendine barındırılan bir dil , kendi kendine barındırılan bir tercüman ile aynı şey değildir. Bir tercüman oluşturmak genellikle bir derleyici oluşturmaktan daha kolaydır. Bu nedenle, yeni bir dil uygulamak için, önce ilgisiz bir dilde bir tercüman kullanabiliriz. Daha sonra bu tercümanı dilimiz için bir derleyici geliştirmek üzere kullanabiliriz. Derleyici yorumlandığından dil, daha sonra kendini barındırır. Derleyici daha sonra kendini derleyebilir ve tamamen önyüklenmiş olarak kabul edilebilir.

Bunun özel bir durumu, kendi kendini barındıran bir JIT derleme çalışma zamanıdır. Bir ana dilde bir tercümanla başlayabilir, daha sonra JIT derleyicisini uygulamak için yeni dili kullanır, ardından JIT derleyicisi kendisini derleyebilir. Bu, kendini barındıran bir tercüman gibi hissediyor, ancak sonsuz tercüman sorununu ortadan kaldırıyor. Bu yaklaşım kullanılır, ancak henüz çok yaygın değildir.

İlgili bir başka teknik de, yorumlanmakta olan dilde uzantılar yaratabileceğimiz genişletilebilir bir tercümandır. Örneğin, dilde yeni kodlamalar uygulayabiliriz. Bu, çıplak bağımlı kemikleri yorumlayıcıyı, dairesel bağımlılıklardan kaçındığımız sürece, zengin özellikli bir yorumlayıcıya dönüştürebilir.

Oldukça yaygın olarak ortaya çıkan bir durum, dilin kendi ayrıştırmayı etkileme yeteneğidir, örneğin ayrıştırma zamanı değerlendirilmiş makrolar. Makro dili işlenmekte olan dille aynı olduğundan, tahsis edilmiş veya kısıtlanmış makro dillerinden çok daha zengin özelliklere sahip olma eğilimindedir. Ancak, uzantıyı gerçekleştiren dilin, uzantıdan sonraki dilden biraz farklı bir dil olduğunu not etmek doğrudur.

“Gerçek” kendi kendine barındırılan tercümanlar kullanıldığında, bu genellikle eğitim veya araştırma nedeniyle yapılır. Örneğin, Şema için bir tercüman uygulamak, Programlama dillerini öğretmenin harika bir yoludur (bkz. SICP).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.