Mengapa kompiler hosting sendiri dianggap sebagai ritus peralihan untuk bahasa baru?


30

Saya telah mendengar di sejumlah tempat sekarang bahwa orang mengharapkan bahasa untuk digunakan, atau setidaknya memiliki, kompiler hosting sendiri untuk mendapatkan penghormatan.

Saya ingin tahu mengapa ini terjadi. Kompiler sepertinya adalah perangkat lunak yang sangat penting untuk ditulis, dan saya kira tidak semua bahasa cocok untuk membuatnya. Bukankah lebih masuk akal untuk menghabiskan upaya bekerja dalam sesuatu yang akan memberikan hasil yang lebih baik?


17
"Sebuah kompiler tampaknya seperti perangkat lunak yang sangat penting untuk ditulis, dan saya kira tidak semua bahasa cocok untuk membuatnya.": Saya akan menganggap ini alasan yang sangat baik untuk mencoba menulis kompiler dalam bahasa baru, yaitu untuk membuktikan bahwa bahasa tersebut sesuai dengan tugas.
Giorgio

13
Kecuali itu bahasa tujuan khusus, bahasa yang tidak cocok untuk menulis kompiler mungkin tidak cocok untuk apa yang ingin saya lakukan juga.
CodesInChaos

3
AFAIK, ini tidak selalu benar untuk Fortran. Beberapa kompiler Fortran (mis. gfortranDari GCC ...) tidak dikodekan dalam Fortran.
Basile Starynkevitch

Jawaban:


29

Bukankah lebih masuk akal untuk menghabiskan upaya bekerja dalam sesuatu yang akan memberikan hasil yang lebih baik?

Seperti apa?

Yang menyenangkan tentang kompiler adalah mereka tidak memiliki banyak dependensi. Ini menjadikan mereka kandidat yang baik untuk bahasa baru yang kemungkinan belum memiliki perpustakaan standar yang sangat besar atau beragam.

Lebih baik lagi, mereka membutuhkan berbagai hal, sementara juga dipelajari dengan baik. Variasi membantu memastikan bahwa contoh Anda menguji berbagai bagian bahasa. Dipelajari dengan baik berarti Anda memiliki kompiler lain untuk dibandingkan - serta memberikan kepercayaan yang lebih besar pada jenis akademik yang Anda tahu apa yang Anda lakukan.

Dan sementara kompiler tampak seperti satu ton pekerjaan, mereka cukup kecil dalam skema besar hal. Jika pelaksana bahasa bahkan tidak dapat melakukan sesuatu yang mereka lakukan sebelumnya dalam bahasa baru, bagaimana mereka akan melakukan hal-hal baru? Bagaimana mereka menangani hal-hal yang sangat besar seperti perpustakaan standar atau IDE?


Sama seperti catatan tambahan, saya ingin menyebutkan bahwa meskipun baik, masih ada berbagai alasan mengapa kompiler dapat ditulis dalam bahasa lain. Sebagai contoh, sebagian besar mesin javascript tidak ditulis dalam javascript. Ada banyak alasan untuk ini: integrasi dengan perangkat lunak lain, menautkan ke pustaka / dependensi yang ada, alat yang unggul, kinerja, kode warisan ... Kadang-kadang, kompilasi sendiri bahasa bagus, tetapi masih masuk akal untuk mempertahankan kompiler inti di lain. Namun, bahasa itu sendiri masuk akal. Hanya saja Anda biasanya tidak mampu membangun kembali seluruh ekosistem.
dagnelies

2
@arnaud Dan fakta bahwa kompiler Javascript akan membutuhkan lingkungan Javascript, yang tidak dapat ditulis dalam Javascript karena Javascript membutuhkan lingkungan Javascript, <ulangi secara paradoks> , karena lingkungan Javascript tidak disediakan oleh sistem operasi (dan jika adalah, itu tidak akan ditulis dalam Javascript).
Qix

3
@Qix en.wikipedia.org/wiki/Bootstrapping_%28compilers%29 Tapi terutama tidak ada alasan untuk menggunakannya. Ini secara luas dikenal sebagai bahasa yang buruk, browser lolos dengan tidak menggunakannya untuk kompilasi karena mereka mengendalikan situasi :), sementara kita semua tidak punya pilihan di web.
Den

3
Saya tidak begitu yakin tentang klaim "tidak memiliki banyak ketergantungan". Itu mungkin benar untuk front-end kompiler . Tetapi segera setelah Anda memiliki AST, menggulung pengoptimal Anda sendiri dan pembuat kode tidak terlihat seperti rute yang menjanjikan. Terlepas dari kenyataan bahwa teknik optimisasi modern membutuhkan mesin logika formal canggih yang mungkin ingin digunakan perpustakaan pihak ketiga, tidak ada alasan untuk menciptakan kembali roda untuk setiap bahasa baru alih-alih membangun fondasi kekuatan industri seperti GCC atau LLVM.
5gon12eder

30

Tujuan memiliki kompiler dalam bahasa yang dikompilasi sering kali merupakan bagian dari praktik " makan makanan anjing Anda sendiri ." Ini menunjukkan kepada dunia bahwa Anda menganggap bahasa, kompiler, dan ekosistem modul dan alat pendukung sebagai "cukup baik untuk pekerjaan serius" atau "siap produksi."

Ini juga memiliki efek baik memaksa mereka yang paling dekat dengan bahasa, kompiler, dan desain runtime untuk secara langsung menghadapi efek dari semua keputusan yang telah mereka buat, dan prioritas pengembangan yang telah mereka pilih - kutil dan semua. Ini sering mengarah pada kelompok inti yang tidak hanya memahami lingkungan bahasa dalam teori, tetapi yang memiliki pengalaman praktis yang luas menggunakan bahasa / alat dalam wadah kondisi kata yang keras dan nyata.


1
untuk kelengkapan: makan makanan anjing Anda sendiri ; lihat diberi makan anjing (adj) atau dogfooding (kata kerja)
Qix

17

Orang-orang menciptakan bahasa tujuan umum baru karena satu alasan utama: mereka membenci setidaknya satu hal tentang setiap bahasa lain di luar sana. Inilah sebabnya mengapa begitu banyak bahasa tidak muncul begitu saja. Anda memiliki ide bagus untuk bahasa yang akan meningkatkan kehidupan pemrograman Anda, tetapi Anda harus membuat implementasi pertama dalam bahasa yang mengganggu Anda setidaknya dalam satu cara. Hosting otomatis berarti Anda tidak perlu lagi menggunakan bahasa yang menjengkelkan itu. Itu sebabnya pencipta bahasa bekerja menuju langkah itu, dan melihatnya sebagai tonggak utama.

Banyak fitur bahasa terlihat bagus di atas kertas, tetapi ketika Anda menggunakannya untuk proyek nyata, Anda mulai melihat keterbatasannya. Sebagai contoh, banyak bahasa pada awalnya tidak memiliki dukungan unicode yang layak. Menyelesaikan proyek besar membantu memastikan banyak dari situasi semacam itu telah ditemui dan ditangani, dan kompiler hosting sendiri adalah proyek yang sama bagusnya dengan proyek apa pun. Itu sebabnya orang selain pencipta bahasa melihatnya sebagai tonggak utama.

Itu tidak berarti itu satu - satunya tonggak yang patut dicatat. Ada fungsionalitas yang tidak dilakukan oleh kompiler, seperti integrasi database, antarmuka grafis, jaringan, dll.


Saya merasa seperti bahasa (asli) adalah bahasa ketika ia dapat mengkompilasi dirinya sendiri dan kernel linux dapat dipindahkan ke dalamnya (karena ia mencakup sebagian besar / semua tugas yang diperlukan agar sebagian besar OS modern berfungsi).
Qix

Dukungan Unicode yang Layak tidak benar-benar diperlukan untuk menulis kompiler.
Paŭlo Ebermann

11

Steve Yegge menulis posting blog yang hebat , yang secara tidak langsung membahas hal ini.

Poin # 1: kompiler mencakup hampir setiap aspek ilmu komputer. Mereka kursus tingkat atas karena Anda perlu mengetahui semua hal lain yang Anda pelajari dalam kurikulum ilmu komputer hanya untuk memulai. Struktur data, pencarian dan penyortiran, kinerja asimptotik, pewarnaan grafik? Semuanya ada di sana.

Ada alasan mengapa Knuth telah mengerjakan "Pemrograman Komputer" yang monumental (dan tidak pernah berakhir) selama beberapa dekade, meskipun itu dimulai sebagai (hanya) buku teks kompiler. Dengan cara yang sama seperti yang dikatakan Carl Sagan, "Jika Anda ingin membuat pai apel dari awal, Anda harus terlebih dahulu menciptakan alam semesta", jika Anda ingin menulis kompiler, Anda harus terlebih dahulu berurusan dengan hampir setiap aspek ilmu komputer.

Itu berarti jika kompiler di-host-sendiri, maka cukup yakin untuk dapat melakukan apa yang saya butuhkan, apa pun yang saya lakukan. Sebaliknya, jika Anda tidak menulis kompiler dalam bahasa Anda, ada kemungkinan ia melewatkan sesuatu yang benar-benar penting bagi seseorang, karena para pelaksana bahasa tidak pernah harus menulis sebuah program yang mengharuskan mereka untuk memikirkan semua masalah itu.

Poin besar # 2: dari 30.000 kaki, sejumlah masalah yang mengejutkan terlihat seperti kompiler.

Compiler mengambil aliran simbol, mencari tahu struktur mereka sesuai dengan beberapa aturan yang telah ditentukan domain-spesifik, dan mengubahnya menjadi aliran simbol lain. Kedengarannya cukup umum, bukan? Yah begitulah.

Apakah Anda berada di tim Visual C ++ atau tidak, Anda akan sering perlu melakukan sesuatu yang terlihat seperti bagian dari kompiler. Saya melakukannya setiap hari.

Tidak seperti kebanyakan profesi lain, pemrogram tidak hanya menggunakan alat, tetapi membangun alat mereka sendiri. Seorang programmer yang tidak dapat (karena kurangnya keterampilan, atau kurangnya alat yang dapat digunakan untuk membangun alat lain) alat tulis akan selamanya cacat, terbatas pada alat yang disediakan orang lain.

Jika suatu bahasa "tidak cocok untuk membuat" program yang dapat mengambil aliran simbol, menerapkan aturan kepadanya, dan mengubahnya menjadi aliran simbol lain, yang terdengar seperti bahasa yang sangat terbatas, dan bukan bahasa yang akan berguna untuk saya.

(Untungnya, saya tidak berpikir ada banyak bahasa pemrograman yang tidak cocok untuk mengubah simbol. C mungkin adalah salah satu bahasa terburuk yang digunakan saat ini, namun kompiler C biasanya di-host-sendiri, sehingga tidak pernah menghentikan siapa pun.)

Alasan ketiga saya akan berakhir dengan, dari pengalaman pribadi, tidak disebutkan oleh Yegge (karena dia tidak menulis tentang "mengapa tuan rumah"): itu menghilangkan bug. Saat Anda menulis kompiler, itu berarti setiap kali Anda membangunnya (bukan hanya setiap kali Anda menjalankannya ), Anda bergantung padanya untuk bekerja, dan untuk bekerja dengan benar terhadap basis kode berukuran layak (kompiler itu sendiri).

Bulan ini saya telah menggunakan kompiler non-self-host yang relatif baru dan terkenal (Anda mungkin bisa menebak yang mana), dan saya tidak bisa pergi 2 hari tanpa membuat kesalahan. Saya bertanya-tanya berapa banyak desainer sebenarnya harus menggunakannya.


8

Jika Anda ingin memiliki kompiler untuk bahasa X menjadi hosting sendiri, pertama Anda harus mengimplementasikannya dalam beberapa bahasa lain, katakanlah Y, sehingga dibutuhkan input untuk bahasa X dan mengeluarkan kode assembly, atau beberapa kode perantara, atau bahkan kode objek untuk mesin yang dijalankan oleh kompiler. Anda ingin memilih bahasa Y agar semirip mungkin dengan bahasa X, karena pada titik tertentu Anda akan menerjemahkan kode yang ditulis dalam Y ke X.

Tetapi Anda tidak ingin menulis lagi kompiler dalam bahasa Y daripada yang diperlukan, jadi untuk memulainya, Anda hanya mengimplementasikan sebagian dari bahasa tersebut - menghilangkan konstruksi yang berlebihan. Dalam kasus jenis bahasa 'C', sementara tetapi tidak untuk atau melakukan sementara . jika tetapi tidak ada kasus atau op tersier. Tidak ada struktur atau serikat pekerja atau enumerasi. Dll. Apa yang tersisa hanya cukup untuk menulis parser dan generator kode dasar untuk bahasa X. Kemudian periksa hasilnya. Lagi.

Setelah ini berfungsi, Anda dapat menulis ulang sumber kompiler yang ditulis dalam bahasa Y ke dalam bahasa X, dan kompilasi sumber bahasa X menggunakan kompiler yang ditulis dalam bahasa Y. Outputnya akan berupa kompiler baru yang ditulis dalam bahasa baru X yang mengkompilasi bahasa X, yaitu sekarang menjadi hosting sendiri. Namun itu tidak lengkap karena Anda hanya menerapkan sebagian bahasa dalam bahasa Y.

Jadi sekarang Anda menambahkan fitur yang hilang, menguji masing-masing (atau kelompok fitur) bahwa mereka menghasilkan kode yang benar. yaitu begitu fitur diimplementasikan dalam kompiler, Anda dapat menulis program pengujian menggunakan fitur baru, mengkompilasi dan mengujinya, tetapi Anda tidak harus menggunakannya dalam sumber kompiler. Setelah fitur baru diverifikasi, Anda kemudian dapat menggunakan fitur-fitur baru ini di sumber kompiler itu sendiri - mungkin mengganti beberapa kode asli yang ditulis dalam subset bahasa - kompilasi ulang sumber kompiler menggunakan versi dengan fitur-fitur baru.

Anda sekarang memiliki mekanisme untuk menambahkan fitur baru ke bahasa - dan, setelah pembuatan kode untuk fitur telah diverifikasi dengan benar, mereka dapat digunakan dalam generasi berikutnya dari kompiler itu sendiri.

Kembali 60 tahun yang lalu ketika komputer pertama kali tiba di tempat kejadian (dan kemudian lagi ketika mikroprosesor pertama kali tiba), tidak ada bahasa Y yang cocok untuk mengimplementasikan kompiler awal. Jadi kompiler pertama harus ditulis dalam kode assembly, dan kemudian ketika cukup kompiler berjalan, kode assembly akan diganti dengan versi yang ditulis dalam bahasa baru. Juga tidak ada assembler? Seluruh prosesor jatuh ke tingkat lain, dengan assembler yang awalnya ditulis dalam kode mesin .


2

Apakah mungkin untuk menghasilkan bahasa pemrograman yang tidak dirancang dengan baik untuk menulis kompiler tetapi dirancang dengan baik untuk tujuan lain?

Melihat bahasa seperti SQL, saya kira jawabannya adalah ya. Tetapi bahasa-bahasa seperti itu bukan tujuan umum.


1
Ditantang diterima: Tulis kompiler C dalam SQL.
Qix

2

Siapa yang mengatakan itu? ... pokoknya, itu hanya pendapat. Beberapa mungkin setuju, beberapa mungkin tidak, tidak ada benar atau salah di sini. Beberapa bahasa memiliki kompiler yang ditulis sendiri, yang lain tidak. Terserah.

Namun demikian, saya pikir ini adalah latihan yang bagus / pembuktian konsep jika suatu bahasa dapat "mengkompilasi sendiri" ... itu hanya ... bagus ... dan itu membuktikan bahasanya cocok untuk melakukan beberapa hal kompleks.

Saya juga ingin menyebutkan bahwa meskipun baik, masih ada berbagai alasan mengapa kompiler dapat ditulis dalam bahasa lain. Sebagai contoh, sebagian besar mesin javascript tidak ditulis dalam javascript. Ada banyak alasan untuk ini: integrasi dengan perangkat lunak lain, menautkan ke pustaka / dependensi yang ada, alat yang unggul, kinerja, kode warisan ... Kadang-kadang, kompilasi sendiri bahasa bagus, tetapi masih masuk akal untuk mempertahankan kompiler inti di lain. Namun, bahasa itu sendiri masuk akal. Hanya saja Anda biasanya tidak mampu membangun kembali seluruh ekosistem.


2

Dentang ditulis dalam C ++. Tidak akan terlalu sulit untuk menulis ulang kompiler Dentang Objective-C di Objective-C, tetapi kemudian itu akan sangat tidak berguna. Setiap perubahan dalam kompiler C ++ harus diulang kembali di Objective-C dan sebaliknya. Jadi kenapa?

Sekarang ada kompiler Clang Swift. Tentunya kompiler itu dapat ditulis ulang di Swift. Tapi apa tujuannya? Untuk menunjukkan bahwa bahasanya cukup kuat untuk menulis kompiler di dalamnya? Tidak ada yang peduli jika Anda dapat menulis kompiler di Swift. Orang - orang peduli jika Anda dapat menulis antarmuka pengguna di Swift, dan Anda dapat membuktikannya.

Jika Anda memiliki kompiler yang teruji dengan baik yang dapat dengan mudah diadaptasi untuk mengkompilasi bahasa yang berbeda, itu tidak ada gunanya untuk menulis ulang ke dalam bahasa yang berbeda, kecuali jika menulis ulang dalam satu bahasa yang berbeda akan membuatnya lebih mudah untuk bekerja dengan kompiler. Dan jika masuk akal untuk menulis Dentang di Swift, misalnya, maka kompiler Dentang C, C ++, dan Objective-C semua akan ditulis dalam Swift.

Ada hal-hal yang lebih penting untuk dilakukan daripada membuktikan bahwa Anda dapat menulis kompiler dalam beberapa bahasa pemrograman.


1

Ini menunjukkan bahwa bahasa tersebut mampu memproses pemrosesan string yang kompleks dan menerjemahkan ke bahasa lain / menafsirkannya sendiri.

Dalam proses membuat kompiler (proyek besar pertama) akan ada masalah yang mengemuka.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.