Perbedaan antara kode yang ditafsirkan dan dikompilasi mungkin fiksi, seperti yang digarisbawahi oleh komentar Raphael :
the claim seems to be trivially wrong without further assumptions: if there is
an interpreter, I can always bundle interpreter and code in one executable ...
Faktanya adalah bahwa kode selalu diinterpretasikan, oleh perangkat lunak, oleh perangkat keras atau kombinasi keduanya, dan proses kompilasi tidak dapat menentukan mana yang akan.
Apa yang Anda anggap kompilasi adalah proses terjemahan dari satu bahasa (untuk sumber) ke bahasa lain (untuk target). Dan, juru bahasa untuk biasanya berbeda dari interpreter untuk .T S TSTST
Program ini disusun diterjemahkan dari satu bentuk sintaksis ke bentuk sintaksis lain , sehingga, mengingat semantik dimaksudkan dari bahasa dan , dan P T memiliki perilaku komputasi yang sama, hingga beberapa hal yang Anda biasanya mencoba untuk berubah, mungkin untuk mengoptimalkan, seperti kompleksitas atau efisiensi sederhana (waktu, ruang, permukaan, konsumsi energi). Saya mencoba untuk tidak berbicara tentang kesetaraan fungsional, karena akan membutuhkan definisi yang tepat.P T S T P SPSPTSTPSPT
Beberapa kompiler telah benar-benar digunakan hanya untuk mengurangi ukuran kode, bukan untuk "meningkatkan" eksekusi. Ini adalah kasus untuk bahasa yang digunakan dalam sistem Plato (meskipun mereka tidak menyebutnya kompilasi).
Anda dapat mempertimbangkan kode Anda sepenuhnya dikompilasi jika setelah proses kompilasi, Anda tidak perlu lagi interpreter untuk . Paling tidak, itulah satu-satunya cara saya dapat membaca pertanyaan Anda, sebagai rekayasa daripada pertanyaan teoretis (karena, secara teoritis, saya selalu dapat membangun kembali penerjemah).S
Satu hal yang dapat menimbulkan masalah, afaik, adalah meta-sirkularitas . Saat itulah sebuah program akan memanipulasi struktur sintaksis dalam bahasa sumbernya sendiri , menciptakan fragmen program yang kemudian diintepretasi seolah-olah mereka telah menjadi bagian dari program aslinya. Karena Anda dapat menghasilkan fragmen program yang sewenang-wenang dalam bahasa S sebagai hasil perhitungan sewenang-wenang memanipulasi fragmen sintaksis yang tidak bermakna, saya kira Anda bisa membuatnya hampir mustahil (dari sudut pandang teknik) untuk mengkompilasi program ke dalam bahasa T , sehingga sekarang menghasilkan fragmen T . Oleh karena itu penerjemah untuk S akan diperlukan, atau setidaknya kompiler dari S keSSTTSS untukkompilasi on-the-fly onfragmen yang dihasilkan dalam S (lihat jugadokumen ini).TS
Tapi saya tidak yakin bagaimana ini bisa diformalkan dengan benar (dan tidak punya waktu sekarang untuk itu). Dan tidak mungkin adalah kata besar untuk masalah yang tidak diformalkan.
Keterangan lebih lanjut
Ditambahkan setelah 36 jam. Anda mungkin ingin melewatkan sekuel yang sangat panjang ini.
Banyak komentar untuk pertanyaan ini menunjukkan dua pandangan tentang masalah: pandangan teoretis yang melihatnya sebagai tidak berarti, dan pandangan teknik yang sayangnya tidak begitu mudah diformalkan.
Ada banyak cara untuk melihat interpretasi dan kompilasi, dan saya akan mencoba membuat sketsa beberapa. Saya akan berusaha menjadi informal seperti yang saya bisa lakukan
Diagram Tombstone
Salah satu formalisasi awal (awal 1960-an hingga akhir 1990) adalah diagram T atau
Tombstone . Diagram-diagram ini disajikan dalam elemen grafis komposable bahasa implementasi interpreter atau kompiler, bahasa sumber ditafsirkan atau dikompilasi, dan bahasa target dalam kasus kompiler. Versi yang lebih rumit dapat menambahkan atribut. Representasi grafis ini dapat dilihat sebagai aksioma, aturan inferensi, dapat digunakan untuk menghasilkan generasi prosesor secara otomatis dari bukti keberadaannya dari aksioma, à la Curry-Howard (walaupun saya tidak yakin hal itu dilakukan pada tahun enam puluhan :).
Evaluasi parsial
Pandangan lain yang menarik adalah paradigma evaluasi parsial . Saya mengambil pandangan sederhana tentang program sebagai semacam implementasi fungsi yang menghitung jawaban yang diberikan beberapa data input. Kemudian seorang juru
untuk bahasa S adalah sebuah program yang mengambil program p S
ditulis dalam S dan data d untuk program tersebut, dan menghitung hasil sesuai dengan semantik S . Evaluasi parsial adalah teknik untuk mengkhususkan program dua argumen yang 1 dan yang 2 , ketika hanya satu argumen, mengatakan sebuah 1sayaSShalSSdSa1a2a1, dikenal. Maksudnya adalah untuk memiliki evaluasi yang lebih cepat ketika Anda akhirnya mendapatkan argumen kedua . Hal ini sangat berguna jika suatu 2 perubahan lebih sering daripada sebuah 1 karena biaya evaluasi parsial dengan sebuah 1 dapat diamortisasi pada semua perhitungan di mana hanya satu 2 berubah.a2a2a1a1a2
Ini adalah situasi yang sering terjadi dalam perancangan algoritma (seringkali menjadi topik dari komentar pertama pada SE-CS), ketika beberapa bagian yang lebih statis dari data diproses sebelumnya, sehingga biaya pra-pemrosesan dapat diamortisasi pada semua aplikasi dari algoritma dengan lebih banyak bagian variabel dari data input.
Ini juga merupakan situasi para penafsir, karena argumen pertama adalah program yang akan dieksekusi, dan biasanya dieksekusi berkali-kali dengan data yang berbeda (atau meminta sub-bagian dieksekusi berkali-kali dengan data yang berbeda). Oleh karena itu menjadi ide alami untuk mengkhususkan juru bahasa untuk evaluasi yang lebih cepat dari program yang diberikan dengan sebagian mengevaluasinya pada program ini sebagai argumen pertama. Ini dapat dilihat sebagai cara menyusun program, dan telah ada pekerjaan penelitian yang signifikan untuk menyusun dengan mengevaluasi sebagian penerjemah pada argumen (program) pertamanya.
Teorema Smn
Poin bagus tentang pendekatan evaluasi parsial adalah bahwa ia berakar pada teori (meskipun teori dapat menjadi pembohong), terutama dalam
teorema Smn Kleene . Saya mencoba di sini untuk memberikan presentasi intuitif tentang itu, berharap itu tidak akan mengecewakan para ahli teori murni.
Dengan penomoran Gödel dari fungsi rekursif, Anda dapat melihat φ sebagai perangkat keras Anda, sehingga mengingat nomor Gödel p
(baca kode objek ) dari sebuah program φ p adalah fungsi yang didefinisikan oleh p (yaitu dikomputasi oleh kode objek pada perangkat keras Anda ).φφpφpp
Dalam bentuknya yang paling sederhana, teorema ini dinyatakan dalam wikipedia sebagai berikut (hingga perubahan kecil dalam notasi):
Diberikan penomoran Gödel dari fungsi rekursif, ada fungsi rekursif primitif σ dari dua argumen dengan properti berikut: untuk setiap angka Gödel q dari fungsi yang dapat dihitung sebagian f dengan dua argumen, ekspresi φ σ ( q , x ) ( y ) dan f ( x , y ) didefinisikan untuk kombinasi bilangan asli x dan y yang sama , dan nilainya sama untuk kombinasi tersebut. Dengan kata lain, persamaan fungsi ekstensional berikut berlaku untuk setiapφσqfφσ(q,x)(y)f(x,y)xy :
xφσ(q,x)≃λy.φq(x,y).
Sekarang, dengan mengambil sebagai interpreter I S , x sebagai kode sumber program p S , dan y sebagai data d untuk program itu, kita dapat menulis:
qISxhalSydφσ( SayaS, halS)≃ λ d. φsayaS( halS, d) .
dapat dilihat sebagai pelaksanaan penafsir saya S
pada perangkat keras, yaitu, sebagai kotak hitam siap untuk menafsirkan program yang ditulis dalam bahasa S .φsayaSsayaSS
Fungsi dapat dilihat sebagai fungsi yang mengkhususkan juru bahasa I S untuk program P S , seperti dalam evaluasi parsial. Dengan demikian jumlah Gödel σ ( I S , p S ) dapat dilihat memiliki kode objek yang versi terkompilasi program p S .σsayaSPSσ( SayaS, halS)halS
Jadi fungsinya dapat dilihat sebagai fungsi yang mengambil sebagai argumen kode sumber dari program q S yang
ditulis dalam bahasa S , dan mengembalikan versi kode objek untuk program itu. Jadi C S adalah apa yang biasanya disebut sebuah kompiler.CS= λ qS.σ( ( SayaS, qS)qSSCS
Beberapa kesimpulan
Namun, seperti yang saya katakan: "teori bisa menjadi pembohong", atau sebenarnya sepertinya satu. Masalahnya adalah kita tidak mengetahui fungsi . Sebenarnya ada banyak fungsi seperti itu, dan tebakan saya adalah bahwa pembuktian teorema dapat menggunakan definisi yang sangat sederhana untuk itu, yang mungkin tidak lebih baik, dari sudut pandang teknik, daripada solusi yang diusulkan oleh Raphael: untuk sekadar membundel kode sumber q S dengan interpreter saya S . Ini selalu bisa dilakukan, sehingga kita dapat mengatakan: kompilasi selalu mungkin.σqSsayaS
Memformalkan gagasan yang lebih ketat tentang apa itu kompiler akan memerlukan pendekatan teoretis yang lebih halus. Saya tidak tahu apa yang mungkin telah dilakukan ke arah itu. Pekerjaan yang sangat nyata dilakukan pada evaluasi parsial lebih realistis dari sudut pandang teknik. Dan tentu saja ada teknik lain untuk menulis kompiler, termasuk ekstraksi program dari bukti spesifikasi mereka, seperti yang dikembangkan dalam konteks tipe-teori, berdasarkan isomorfisma Curry-Howard (tapi saya keluar dari domain kompetensi saya) .
Tujuan saya di sini adalah untuk menunjukkan bahwa ucapan Raphael bukanlah "gila", tetapi pengingat yang waras bahwa segala sesuatu tidak jelas, dan bahkan tidak sederhana. Mengatakan bahwa sesuatu itu tidak mungkin adalah pernyataan yang kuat yang memang membutuhkan definisi dan bukti yang tepat, jika hanya untuk memiliki pemahaman yang tepat tentang bagaimana dan mengapa itu tidak mungkin . Tetapi membangun formalisasi yang tepat untuk mengekspresikan bukti semacam itu mungkin cukup sulit.
Ini mengatakan, bahkan jika fitur tertentu tidak dapat dikompilasi, dalam pengertian yang dipahami oleh para insinyur, teknik kompilasi standar selalu dapat diterapkan pada bagian-bagian dari program yang tidak menggunakan fitur seperti itu, seperti yang dinyatakan oleh jawaban Gilles.
Untuk mengikuti kata kunci Gilles bahwa, tergantung pada bahasanya, beberapa hal dapat dilakukan pada waktu kompilasi, sementara yang lain harus dilakukan pada saat run-time, sehingga memerlukan kode spesifik, kita dapat melihat bahwa konsep kompilasi sebenarnya tidak jelas, dan mungkin tidak dapat didefinisikan dengan cara apa pun yang memuaskan. Kompilasi hanya merupakan proses optimasi, seperti yang saya coba tunjukkan di bagian evaluasi parsial , ketika saya membandingkannya dengan preprocessing data statis dalam beberapa algoritma.
Sebagai proses optimasi yang kompleks, konsep kompilasi sebenarnya milik sebuah kontinum. Bergantung pada karakteristik bahasa, atau program, beberapa informasi mungkin tersedia secara statis dan memungkinkan pengoptimalan yang lebih baik. Hal-hal lain harus ditunda untuk dijalankan. Ketika segala sesuatunya menjadi sangat buruk, semuanya harus dilakukan pada saat run-time setidaknya untuk beberapa bagian program, dan menggabungkan kode sumber dengan penerjemah adalah yang dapat Anda lakukan. Jadi bundling ini hanyalah akhir dari rangkaian kompilasi ini. Banyak penelitian tentang kompiler adalah tentang menemukan cara untuk melakukan secara statis apa yang dulu dilakukan secara dinamis. Pengumpulan sampah waktu kompilasi tampaknya merupakan contoh yang baik.
Perhatikan bahwa mengatakan bahwa proses kompilasi harus menghasilkan kode mesin tidak membantu. Itulah yang dapat dilakukan bundling sebagai penerjemah adalah kode mesin (well, masalahnya bisa sedikit lebih kompleks dengan kompilasi silang).