Derleyici kendini nasıl derleyebilir?


168

Ben web üzerinde CoffeeScript araştırıyorum http://coffeescript.org/ ve metne sahip

CoffeeScript derleyicisinin kendisi CoffeeScript'te yazılmıştır

Derleyici kendini nasıl derleyebilir veya bu ifade ne anlama gelir?


14
Kendini derleyebilen bir derleyici için başka bir terim self-hostingderleyicidir. Bkz. Programmers.stackexchange.com/q/263651/6221
oɔɯǝɹ

37
Bir derleyici neden kendini derleyemez?
user253751

48
İlgili derleyicinin en az iki kopyası vardır. Önceden var olan yeni bir kopyasını derler. Yenisi eskisiyle aynı olabilir ya da olmayabilir.
bdsl

12
Ayrıca Git ilginizi çekebilir: kaynak kodu elbette bir Git deposunda izlenir.
Greg d'Eon

7
Bu, "Bir Xerox Yazıcı şemaları kendisine nasıl basabilir?" Derleyiciler metni bayt koduna derler. Derleyici kullanılabilir herhangi bir bayt kodunu derleyebiliyorsa, derleyici kodunu ilgili dilde yazabilir ve daha sonra çıktıyı oluşturmak için kodu derleyiciden geçirebilirsiniz.
RLH

Yanıtlar:


219

Bir derleyicinin ilk sürümü, kendisine özgü bir programlama dilinden makine ile oluşturulamaz; karışıklığınız anlaşılabilir. Daha fazla dil özelliğine sahip derleyicinin daha sonraki bir sürümü (yeni dilin ilk sürümünde yeniden yazılmış kaynak) ilk derleyici tarafından oluşturulabilir. Bu sürüm bir sonraki derleyiciyi derleyebilir ve bu böyle devam eder. İşte bir örnek:

  1. İlk CoffeeScript derleyicisi Ruby'de yazılır ve CoffeeScript'in 1. sürümünü üretir
  2. CS derleyicinin kaynak kodu CoffeeScript yeniden yazılmıştır 1
  3. Orijinal CS derleyicisi yeni kodu (CS 1'de yazılmış) derleyicinin sürüm 2'sinde derler
  4. Yeni dil özellikleri eklemek için derleyici kaynak kodunda değişiklikler yapılır
  5. İkinci CS derleyici (CS'de yazılmış ilk derleyici), düzeltilmiş yeni kaynak kodunu derleyicinin 3. sürümüne derler
  6. Her yineleme için 4. ve 5. adımları tekrarlayın

Not: CoffeeScript sürümlerinin tam olarak nasıl numaralandığından emin değilim, bu sadece bir örnektir.

Bu işleme genellikle önyükleme adı verilir . Önyükleme derleyicisinin başka bir örneği Rust dilininrustc derleyicisidir .


5
Bir derleyiciyi önyüklemenin diğer yolu, dilinizin (bir altkümesi) için bir tercüman yazmaktır.
Aron

Başka bir dilde yazılmış bir derleyici veya yorumlayıcı ile önyüklemeye bir başka alternatif olarak, çok eski okul yolu derleyici kaynağını elle monte etmek olacaktır. Chuck Moore, Sorun Odaklı Bir Dil Programlama sonunda bölüm 9, "Bootstrap programları" başlıklı bir Forth tercümanı için bunu nasıl gerçekleştirir ( web.archive.org/web/20160327044521/www.colorforth.com/POL .htm ). Buraya kod girişi, değerlerin bitler için geçiş anahtarları tarafından kontrol edilen bellek adreslerine doğrudan depolanmasını sağlayan bir ön panel aracılığıyla yapılır.
Jeremy

60

Güvene Güvenin Üzerine Düşünceler makalesinde , Unix'in yaratıcılarından Ken Thompson, C derleyicisinin kendisini nasıl derlediğine dair büyüleyici (ve kolayca okunabilir) bir genel bakış yazar. Benzer kavramlar CoffeeScript veya başka bir dile uygulanabilir.

Kendi kodunu derleyen bir derleyici fikri, bir quine : kaynak koduna benzer şekilde benzer : yürütüldüğünde orijinal kaynak kodunu çıktı olarak üretir. İşte bir CoffeeScript sorgusu örneği . Thompson bu C cine örneğini verdi:

char s[] = {
    '\t',
    '0',
    '\n',
    '}',
    ';',
    '\n',
    '\n',
    '/',
    '*',
    '\n',
    … 213 lines omitted …
    0
};

/*
 * The string s is a representation of the body
 * of this program from '0'
 * to the end.
 */

main()
{
    int i;

    printf("char\ts[] = {\n");
    for(i = 0; s[i]; i++)
        printf("\t%d,\n", s[i]);
    printf("%s", s);
}

Daha sonra, derleyiciye '\n'ASCII kodu 10 gibi bir kaçış dizisinin nasıl öğretildiğini merak edebilirsiniz . Cevap, C derleyicisinin bir yerinde, ters eğik çizgi dizilerini tanımak için bunun gibi bazı koşulları içeren karakter değişmezlerini yorumlayan bir rutin olmasıdır:

…
c = next();
if (c != '\\') return c;        /* A normal character */
c = next();
if (c == '\\') return '\\';     /* Two backslashes in the code means one backslash */
if (c == 'r')  return '\r';     /* '\r' is a carriage return */
…

Yani, yukarıdaki koda bir koşul ekleyebiliriz…

if (c == 'n')  return 10;       /* '\n' is a newline */

'\n'ASCII 10'u temsil eden bir derleyici üretmek için . İlginçtir ki, bu derleyici ve onun tarafından derlenen tüm derleyiciler bu eşlemeyi "bilir", böylece kaynak kodun gelecek neslinde, bu son satırı

if (c == 'n')  return '\n';

… Ve doğru olanı yapacak! 10Derleyici gelir ve artık açıkça derleyici'nın kaynak kodunda tanımlanması gerekir. 1

Bu, C kodunda uygulanan C dili özelliğinin bir örneğidir. Şimdi, bu işlemi her dil özelliği için tekrarlayın ve bir "kendi kendini barındıran" derleyiciniz var: C ile yazılmış bir C derleyicisi.


1 Makalede açıklanan arsa bükümü, derleyiciye bunun gibi gerçekleri "öğretebileceği" için, tespit edilmesi zor bir şekilde truva atı yürütülebilir dosyaları üretmenin yanlış öğretilebileceği ve böyle bir sabotaj eyleminin devam edebileceği renkli derleyici tarafından üretilen tüm derleyicilerde.


7
Bu ilginç bir bilgi olsa da, soruyu cevapladığını sanmıyorum. Örneklerinizde halihazırda bir bootstrapped derleyiciniz olduğunu veya C derleyicisinin hangi dilde yazılmış olduğunu varsayalım.
Arturo Torres Sánchez

9
@ ArturoTorresSánchez Farklı açıklamalar farklı insanlar için iyi çalışır. Diğer cevaplarda söylenenleri tekrarlamayı amaçlamıyorum. Aksine, diğer cevapların nasıl düşündüğümden daha yüksek düzeyde konuştuğunu görüyorum. Kişisel olarak, tek bir özelliğin nasıl eklendiğine dair somut bir illüstrasyonu tercih ediyorum ve okuyucunun sığ bir genel bakış yerine bundan kaçmasına izin veriyorum.
200_success

5
Tamam, bakış açını anlıyorum. Sadece soru daha “derleyiciyi derleyen derleyici yoksa nasıl derlenebilir” ve daha az “önyüklemeli derleyiciye yeni özellikler nasıl eklenir” sorusudur.
Arturo Torres Sánchez

17
Sorunun kendisi belirsiz ve açık uçlu. Bazı insanlar bunu "bir CoffeeScript derleyicisinin kendini nasıl derleyebilir?" Bir yorumda belirtildiği gibi, küstah cevap "tıpkı herhangi bir kodu derlemesi gibi neden kendini derleyemesin?" Bunu "kendi kendini barındıran bir derleyici nasıl ortaya çıkabilir?" Anlamına gelir ve derleyicinin kendi dil özelliklerinden biri hakkında nasıl öğretilebileceğinin bir örneğini verdim. Sorunun nasıl uygulandığına dair düşük düzeyli bir örnek sunarak soruyu farklı bir şekilde yanıtlar.
200_success

1
@ ArturoTorresSánchez: "[I] n C derleyicisi hangi dilde yazılıyor?" Uzun zaman önce eski K&R ekinde (IBM 360 için olanı) belirtilen orijinal C derleyicisini korudum. Birçok insan önce BCPL, sonra B'nin ve C'nin B'nin geliştirilmiş bir versiyonu olduğunu biliyor. eski derleyicinin hala B'de yazılan ve hiçbir zaman C'ye yeniden yazılmamış bölümleri. Değişkenler tek harf / rakam biçimindeydi, işaretçi aritmetiğinin otomatik olarak ölçeklendirildiği varsayılmadı, vb. İlk "C" derleyicisi B.'de yazılmıştır.
Eliyahu Skoczylas

29

Zaten çok iyi bir cevap aldınız, ancak size farklı bir bakış açısı sunmak istiyorum, umarım size aydınlatıcı olacaktır. Önce ikimiz üzerinde hemfikir olabileceğimiz iki gerçek belirleyelim:

  1. CoffeeScript derleyicisi, CoffeeScript'te yazılmış programları derleyebilen bir programdır.
  2. CoffeeScript derleyicisi, CoffeeScript'te yazılmış bir programdır.

Eminim ki hem # 1 hem de # 2'nin doğru olduğunu kabul edebilirsiniz. Şimdi, iki ifadeye bakın. Artık CoffeeScript derleyicisinin CoffeeScript derleyicisini derlemesinin tamamen normal olduğunu görüyor musunuz?

Derleyici ne derlediğini umursamıyor . CoffeeScript'te yazılmış bir program olduğu sürece derleyebilir. CoffeeScript derleyicisinin kendisi de böyle bir program olur. CoffeeScript derleyicisi, derlediği CoffeeScript derleyicisinin kendisinin umurunda değildir. Tek gördüğü bazı CoffeeScript kodu. Dönemi.

Derleyici kendini nasıl derleyebilir veya bu ifade ne anlama gelir?

Evet, tam olarak bu ifadenin anlamı budur ve umarım şimdi bu ifadenin nasıl doğru olduğunu görebilirsiniz.


2
Ben kahve betiği hakkında çok şey bilmiyorum ama kahve betiği ile yazılmış olduğunu ancak o zamandan beri derlenmiş ve daha sonra makine kodu olduğunu belirterek nokta 2 netleştirebilir. Her neyse, lütfen tavuk ve yumurta problemini açıklar mısınız? Derleyici henüz bir derleyicinin yazılmadığı bir dilde yazılmışsa, derleyici nasıl çalışabilir veya derlenebilir?
barlop

6
İfadeniz 2 eksik / yanlış ve çok yanıltıcı. ilk cevabın dediği gibi, ilk kahve senaryosunda yazılmadı .. Bu onun sorusuyla çok alakalı. Ve "Bir derleyici kendini nasıl derleyebilir veya bu ifade ne anlama geliyor?" "Evet" diyorsunuz, sanırım (aklım biraz küçük olsa da), kendisinden ziyade kendisinin önceki sürümlerini derlemek için kullanıldığını görüyorum. Ama kendini derlemek için de kullanılıyor mu? Bunun anlamsız olacağını düşünmüştüm.
barlop

2
@barlop: İfade 2'yi " Bugün , CoffeeScript derleyicisi CoffeeScript'te yazılmış bir programdır" olarak değiştirin. Bu daha iyi anlamanıza yardımcı olur mu? Derleyici, bir girdiyi (kodu) bir çıktıya (programa) çeviren bir programdır. Yani Foo dili için bir derleyiciniz varsa, Foo-derleyicisinin kaynak kodunu Foo'nun kendisine yazın ve bu kaynağı ilk Foo-derleyicinize besleyin, çıktı olarak ikinci bir Foo-derleyici alırsınız. Bu birçok dil tarafından yapılır (örneğin tanıdığım tüm C derleyicileri… C ile yazılır).
DarkDust

3
Derleyici kendini derleyemez. Çıktı dosyası, çıktı dosyasını üreten derleyici ile aynı örnek değil. Umarım şimdi bu ifadenin nasıl yanlış olduğunu görebilirsiniz.
pabrams

3
@pabrams Bunu neden varsayıyorsunuz? Çıktı, onu üretmek için kullanılan derleyici ile aynı olabilir. Örneğin, GCC 6.1'i GCC 6.1 ile derlersem, GCC 6.1 ile derlenen bir GCC 6.1 sürümünü alırım. Ve sonra bunu GCC 6.1'i derlemek için kullanırsam, aynı olması gereken (zaman damgaları gibi şeyleri göz ardı ederek) GCC 6.1 ile derlenmiş bir GCC 6.1 sürümünü de alırım.
user253751

9

Derleyici kendini nasıl derleyebilir veya bu ifade ne anlama gelir?

Tam olarak bu demektir. Her şeyden önce, dikkate alınması gereken bazı şeyler. Bakmamız gereken dört nesne var:

  • Herhangi bir keyfi CoffeScript programının kaynak kodu
  • Herhangi bir keyfi CoffeScript programının (oluşturulan) montajı
  • CoffeScript derleyicisinin kaynak kodu
  • CoffeScript derleyicisinin (oluşturulan) montajı

Şimdi, herhangi bir isteğe bağlı CoffeScript programını derlemek ve bu program için montaj oluşturmak için CoffeScript derleyicisinin oluşturulan derlemesini - çalıştırılabilirini - kullanabileceğiniz açıktır.

Şimdi, CoffeScript derleyicisinin kendisi sadece keyfi bir CoffeScript programıdır ve bu nedenle CoffeScript derleyicisi tarafından derlenebilir.

Sizin karışıklık Kendi yeni bir dil oluşturduğunuzda, yok olmasından kaynaklanıyor gibi görünüyor sahip bir derleyici henüz size derleyici derlemek için kullanabilirsiniz. Bu kesinlikle bir tavuk yumurtası sorununa benziyor , değil mi?

Önyükleme adı verilen işlemi tanıtın .

  1. Zaten mevcut bir dilde (CoffeScript olması durumunda, orijinal derleyici Ruby'de yazılmıştır) yeni dilin bir alt kümesini derleyebilen bir derleyici yazarsınız
  2. Yeni dilin alt kümesinde yeni dilin kendisini derleyebilen bir derleyici yazarsınız. Derleyiciyi yalnızca yukarıdaki adımdan derleyebileceği dil özelliklerini kullanabilirsiniz.
  3. Derleyiciyi 2. adımdan derleyiciyi derlemek için kullanın. Bu işlem, ilk olarak yeni dilin bir alt kümesinde yazılan ve yeni dilin bir alt kümesini derleyebilen bir derleme bırakır.

Şimdi yeni özellikler eklemeniz gerekiyor. Diyelim ki - whiledöngüler uyguladınız, ama aynı zamanda- fordöngüler de istiyorsunuz . Bu herhangi bir problem değildir, çünkü herhangi bir- forloop'u -op olacak şekilde yeniden yazabilirsiniz while. Bu while, derleyicinizin kaynak kodunda yalnızca- döngülerini kullanabileceğiniz anlamına gelir , çünkü elinizdeki montaj yalnızca bunları derleyebilir. Ancak derleyicinizin içinde, foronunla-döngülere pase ve derleme yapabilen işlevler oluşturabilirsiniz . Sonra zaten sahip olduğunuz montajı kullanın ve yeni derleyici sürümünü derleyin. Ve şimdi- fordöngüleri ayrıştırabilen ve derleyebilen bir derleyicinin bir montajına sahipsiniz! Şimdi derleyicinizin kaynak dosyasına dönebilir ve whileistemediğiniz-döngülerini-döngülere yeniden yazabilirsiniz for.

Durulayın ve istenen tüm dil özellikleri derleyici ile derleninceye kadar tekrarlayın.

whileve fortabii ki sadece örneklerdi, ama bu istediğiniz yeni dil özellikleri için de geçerli. Ve sonra siz de CoffeScript'in şu an bulunduğunuz durumda: Derleyici kendini derliyor.

Orada çok fazla literatür var. Güven Üzerine Düşünceler Güven , bu konuyla ilgilenen herkesin en az bir kez okuması gereken bir klasiktir.


5
("CoffeeScript derleyicisinin kendisi CoffeeScript'te yazılmıştır" cümlesi doğrudur, ancak "Bir derleyici kendini derleyebilir" ifadesi yanlıştır.)
pabrams

4
Hayır, bu tamamen doğru. Derleyici olabilir kendisini derlemek. Sadece mantıklı değil. Dilin X Sürümü'nü derleyebilen yürütülebilir programınız olduğunu varsayalım. Sürüm X + 1'i derleyebilen bir derleyici yazar ve sahip olduğunuz derleyiciyle (X sürümü olan) derlersiniz. Dilin X + 1 sürümünü derleyebilen bir yürütülebilir dosya ile sonuçlanırsınız. Şimdi, derleyiciyi yeniden derlemek için bu yeni yürütülebilir dosyayı kullanabilirsiniz. Ama hangi amaçla? İstediğinizi yapan yürütülebilir dosya zaten var . Derleyici herhangi bir geçerli programı derleyebilir , böylece tamamen kendini derleyebilir!
Polygnome

1
Aslında, birkaç kez inşa etmek duyulmamış, iirc modern freepascal derleyiciyi toplam 5 kez inşa ediyor.
plugwash

1
@pabrams "Dokunmayın" ve "Sıcak nesne. Dokunmayın" ifadesinin, ifadenin amaçlanan iletisinde bir fark yoktur. Mesajın hedef kitlesi (Programcılar), nasıl yazıldığına bakılmaksızın cümlenin amaçlanan mesajını (Derleyicinin bir yapısı kaynağını derleyebilir) anladığı sürece, bu tartışma anlamsızdır. Şu an olduğu gibi, argümanınız geçersiz. İletinin hedef kitlesinin programcı olmadığını gösterebildiğiniz sürece, ancak ancak o zaman haklısınız.
DarkDestry

2
@pabrams 'İyi İngilizce', fikirleri hedef kitleye ve yazarın veya konuşmacının istediği şekilde açıkça ileten İngilizce'dir. Hedef kitlenin programcı olması ve programcıların anlaması iyi İngilizce'dir. "Işık hem parçacıklar hem de dalgalar olarak vardır" demek temelde "Işık hem fotonlar hem de elektromanyetik dalgalar olarak vardır" ile eşdeğerdir. Bir fizikçi için, kelimenin tam anlamıyla aynı şeyi kastediyorlar. Bu, her zaman daha uzun ve daha net bir yaşlanmayı kullanmamız gerektiği anlamına mı geliyor? Hayır! Çünkü anlam zaten hedef kitleye açık olduğunda okumayı zorlaştırır.
DarkDestry

7

Küçük ama önemli bir açıklama

Burada derleyici terimi , ilgili iki dosya olduğu gerçeğini gözler önüne seriyor . Biri, CoffeScript'te yazılmış girdi dosyaları olarak alınan ve çıktı dosyası olarak başka bir yürütülebilir dosya, bağlanabilir bir nesne dosyası veya paylaşılan bir kütüphane üreten bir yürütülebilir dosyadır. Diğeri, CoffeeScript derleme prosedürünü açıklayan bir CoffeeScript kaynak dosyasıdır.

İlk dosyayı ikinciye uygularsınız, birinciyle aynı derleme işlemini gerçekleştirebilen bir üçüncü (daha fazla, ikinci dosya ilk tarafından uygulanmayan özellikleri tanımlarsa daha fazla) gerçekleştirebilir ve bu nedenle böylece arzu.


4
  1. CoffeeScript derleyicisi ilk olarak Ruby'de yazılmıştır.
  2. CoffeeScript derleyicisi daha sonra CoffeeScript'te yeniden yazıldı.

CoffeeScript derleyicisinin Ruby sürümü zaten mevcut olduğundan, CoffeeScript derleyicisinin CoffeeScript sürümünü oluşturmak için kullanıldı.

resim açıklamasını buraya girin Bu, kendi kendini barındıran bir derleyici olarak bilinir .

Son derece yaygındır ve genellikle bir yazarın o dilin büyümesini sürdürmek için kendi dillerini kullanma arzusundan kaynaklanır.


3

Bu derleyici değil, dilin ifade edilebilirliği meselesidir, çünkü derleyici sadece bazı dillerde yazılmış bir programdır.

"Bir dil yazılır / uygulanır" dediğimizde, aslında bu dil için bir derleyici veya yorumlayıcının uygulandığını kastediyoruz. Dili uygulayan programlar yazabileceğiniz programlama dilleri vardır (aynı dil için derleyiciler / tercümanlardır). Bu diller evrensel diller olarak adlandırılır .

Bunu anlayabilmek için metal bir torna tezgahı düşünün. Metali şekillendirmek için kullanılan bir araçtır. Sadece bu aracı kullanarak, parçalarını oluşturarak başka, özdeş bir araç oluşturmak mümkündür. Böylece, bu alet evrensel bir makinedir. Tabii ki, birincisi diğer araçlar (diğer araçlar) kullanılarak oluşturuldu ve muhtemelen daha düşük kalitedeydi. Ancak birincisi, daha yüksek hassasiyetle yenilerini oluşturmak için kullanıldı.

3D yazıcı neredeyse evrensel bir makinedir. Tüm 3D yazıcıyı bir 3D yazıcı kullanarak yazdırabilirsiniz (plastiği eriten ucu inşa edemezsiniz).


Torna benzetmesini seviyorum. Torna benzetmesinden farklı olarak, ilk derleyici yinelemesindeki kusurlar sonraki tüm derleyicilere aktarılır. Örneğin, yukarıdaki bir yanıt, orijinal derleyicinin yalnızca döngülerde kullandığı döngü için bir özellik eklemekten bahseder. Çıktı for-loop'ları anlar, ancak uygulama while loop'ları ile yapılır. Orijinal while döngüsü uygulaması hatalı veya verimsizse, her zaman olacaktır!

@ Sadece yanlış olan Fizik-Hesaplama. Kötü niyetli hataların yokluğunda, derleyici derlenirken genellikle yayılmaz.
plugwash

Montaj çevirileri, montaj çevirisi düzeltilene kadar yinelemeden yinelemeye geçirilir. Eski özellikleri oluşturan yeni özellikler, temeldeki uygulamayı değiştirmez. Bir süre düşünün.

@plugwash Ken Thompson'ın "Güvenin Güvenine Yansımaları" konusuna bakın - ece.cmu.edu/~ganger/712.fall02/papers/p761-thompson.pdf

3

İndüksiyonla kanıt

Endüktif adım

Derleyicinin n + 1 sürümü X ile yazılmıştır.

Böylece derleyicinin n'inci versiyonu (X ile yazılmıştır) ile derlenebilir.

Temel durum

Ancak X'de yazılmış derleyicinin ilk sürümü X için bir dilde yazılmış bir derleyici tarafından derlenmelidir. Bu adıma derleyicinin önyüklenmesi denir.


1
X dili için ilk derleyici derleyicisi X'de kolayca yazılabilir. Bunun nasıl mümkün olabileceği ilk derleyicinin yorumlanabilmesidir . (X dışında bir dilde yazılmış bir X tercümanı tarafından).
Kaz

0

Derleyiciler, üst düzey bir özellik alır ve bunu donanımda yürütülebilir gibi düşük düzeyli bir uygulamaya dönüştürür. Bu nedenle, spesifikasyonun formatı ile gerçek yürütme arasında, hedeflenen dilin anlambilimi dışında bir ilişki yoktur.

Çapraz derleyiciler bir sistemden başka bir sisteme geçer, çapraz dil derleyicileri bir dil belirtimini başka bir dil belirtimine derler.

Temel olarak derleme sadece bir çeviri ve seviye genellikle dilin alt seviyesinden daha düşük dil seviyesine, ancak birçok varyant var.

Bootstrapping derleyicileri elbette en kafa karıştırıcıdır, çünkü yazıldıkları dili derlerler. Bootstrapping'de yürütülebilir en az mevcut bir sürümü gerektiren ilk adımı unutmayın. Birçok önyüklemeli derleyici önce bir programlama dilinin asgari özellikleri üzerinde çalışır ve yeni özellik önceki özellikler kullanılarak ifade edilebildiği sürece ileriye dönük ek karmaşık dil özellikleri ekler. Eğer durum böyle değilse, "derleyicinin" bir kısmının önceden başka bir dilde geliştirilmesini gerektirecektir.

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.