Banyak pertanyaan yang diajukan di sini tentang penerapan bahasa yang ditafsirkan vs dikompilasi. Saya bertanya-tanya apakah perbedaan itu benar-benar masuk akal. (Sebenarnya pertanyaannya biasanya tentang bahasa, tetapi mereka benar-benar memikirkan implementasi paling populer dari bahasa-bahasa itu).
Saat ini hampir tidak ada implementasi yang ditafsirkan secara ketat. yaitu tidak ada yang mem-parsing dan menjalankan kode satu baris pada suatu waktu. Selain itu, implementasi yang dikompilasi ke kode mesin juga menjadi kurang umum. Semakin, kompiler menargetkan semacam mesin virtual.
Bahkan, sebagian besar implementasi konvergen pada strategi dasar yang sama. Kompiler menghasilkan bytecode yang ditafsirkan atau dikompilasi ke kode asli melalui JIT. Ini benar-benar campuran dari ide-ide tradisional kompilasi dan interpretasi.
Jadi saya bertanya: Apakah ada perbedaan yang berguna antara implementasi yang ditafsirkan dan implementasi yang disusun akhir-akhir ini?
sumber
P-code
telah diperkenalkan pada tahun 1966 dulu. IBM Aix sudah ada sejak 1986.Jawaban:
Penting untuk diingat bahwa menafsirkan dan menyusun bukan hanya alternatif satu sama lain. Pada akhirnya, program apa pun yang Anda tulis (termasuk yang dikompilasi ke kode mesin) ditafsirkan. Menafsirkan kode berarti mengambil satu set instruksi dan mengembalikan jawaban.
Kompilasi, di sisi lain, berarti mengubah program dalam satu bahasa ke bahasa lain. Biasanya diasumsikan bahwa ketika kompilasi berlangsung, kode dikompilasi ke bahasa "level bawah" (mis. Kode mesin, semacam bytecode VM, dll.). Kode yang dikompilasi ini masih ditafsirkan kemudian.
Sehubungan dengan pertanyaan Anda tentang apakah ada perbedaan yang berguna antara bahasa yang ditafsirkan dan dikompilasi, pendapat pribadi saya adalah bahwa setiap orang harus memiliki pemahaman dasar tentang apa yang terjadi pada kode yang mereka tulis selama interpretasi. Jadi, jika kode mereka sedang dikompilasi JIT, atau bytecode-cache, dll, programmer setidaknya harus memiliki pemahaman dasar tentang apa artinya itu.
sumber
Perbedaan ini sangat bermakna karena bahasa yang dikompilasi membatasi semantik dengan cara yang tidak perlu ditafsirkan bahasa. Beberapa teknik interpretif sangat sulit (praktis tidak mungkin) untuk dikompilasi.
Kode yang diinterpretasikan dapat melakukan hal-hal seperti menghasilkan kode pada waktu berjalan, dan memberikan visibilitas kode tersebut ke binding leksikal dari ruang lingkup yang ada. Itu salah satu contohnya. Lain adalah bahwa penerjemah dapat diperluas dengan kode yang ditafsirkan yang dapat mengontrol bagaimana kode dievaluasi. Ini adalah dasar untuk "fexprs" Lisp kuno: fungsi yang dipanggil dengan argumen yang tidak dievaluasi dan memutuskan apa yang harus dilakukan dengannya (memiliki akses penuh ke lingkungan yang diperlukan untuk menjalankan kode dan mengevaluasi variabel, dll). Dalam bahasa yang dikompilasi, Anda tidak dapat benar-benar menggunakan teknik itu; Anda menggunakan makro sebagai gantinya: fungsi yang dipanggil pada waktu kompilasi dengan argumen yang tidak dievaluasi, dan menerjemahkan kode daripada menafsirkan.
Beberapa implementasi bahasa dibangun di sekitar teknik ini; penulisnya menolak kompilasi sebagai tujuan penting, dan lebih memilih merangkul jenis fleksibilitas ini.
Menafsirkan akan selalu berguna sebagai teknik untuk bootstrap kompiler. Untuk contoh konkret, lihat CLISP (implementasi populer Common Lisp). CLISP memiliki kompiler yang ditulis dengan sendirinya. Ketika Anda membangun CLISP, kompiler itu sedang ditafsirkan selama langkah-langkah awal membangun. Ini digunakan untuk mengkompilasi sendiri, dan kemudian setelah dikompilasi, kompilasi kemudian dilakukan dengan menggunakan kompiler yang dikompilasi.
Tanpa kernel interpreter, Anda perlu melakukan bootstrap dengan beberapa Lisp yang ada, seperti yang dilakukan SBCL.
Dengan interpretasi, Anda dapat mengembangkan bahasa dari awal mutlak, dimulai dengan bahasa assembly. Kembangkan I / O dasar dan rutinitas inti, lalu tulis eval, bahasa mesin. Setelah Anda memiliki eval, tulis dalam bahasa tingkat tinggi; kernel kode mesin melakukan evaluasi. Gunakan fasilitas ini untuk memperluas perpustakaan dengan lebih banyak rutinitas dan menulis kompiler juga. Gunakan kompiler untuk mengkompilasi rutinitas tersebut dan kompilator itu sendiri.
Interpretasi: batu loncatan penting di jalan menuju kompilasi!
sumber
Sebenarnya banyak implementasi bahasa masih ditafsirkan secara ketat, Anda mungkin tidak menyadarinya. Untuk beberapa nama: bahasa shell UNIX, Windows cmd dan shell PowerScript, Perl, awk, sed, MATLAB, Mathematica dan sebagainya.
sumber
Saya pikir: Benar-benar Ya .
Sungguh, C ++ bertujuan untuk port ke kompiler domain beberapa konsep tingkat tinggi yang biasanya diserahkan kepada juru bahasa, tetapi tetap di sisi minoritas ...
sumber
Perbedaan yang berguna: program yang ditafsirkan dapat memodifikasi diri mereka sendiri dengan menambahkan atau mengubah fungsi saat runtime.
sumber