Apakah ada program yang dapat 'menerjemahkan' kode sumber antara dua bahasa (dengan asumsi penerjemah memiliki akses ke perpustakaan yang diperlukan)?
Jika ada, bagaimana cara kerjanya (teknik yang digunakan, pengetahuan yang dibutuhkan, dll)? Bagaimana mereka layak dibangun?
Jika tidak, pembatasan apa yang mencegah perkembangan mereka? Apakah ini masalah lengkap AI (terjemahan bahasa alami terdaftar sebagai satu)?
Konversi EDIT hanya diharapkan, ketika bahasa memiliki kekuatan ekspresi yang sama, dapat memecahkan masalah yang sama dan kode yang akan dikonversi dapat diekspresikan dalam bahasa tujuan. (Misalnya konversi dari skrip shell ke MATLAB tidak diharapkan).
computability
programming-languages
compilers
Tobi Alafin
sumber
sumber
Jawaban:
TLDR; ini mungkin tetapi tidak praktis.
Ini akhirnya menjadi bagian yang sulit, dan merupakan bagian dari mengapa hal-hal seperti ini tidak berakhir digunakan dalam praktik.
Semua kompiler adalah penerjemah. Menerjemahkan dari satu bahasa ke bahasa lain sangat mungkin dilakukan, dan ini benar-benar dilakukan oleh semua kompiler. Bahasa yang dikeluarkan oleh kompiler sebagai output pada umumnya adalah kode mesin atau perakitan, tetapi ini hanyalah bahasa lain, dan ada kompiler (kadang-kadang disebut transpiler atau transkompiler) yang menerjemahkan antara dua bahasa . Misalnya, ada gamut bahasa kompilasi-ke-Javascript seperti PureScript, Elm, ClojureScript, dll.
Menerjemahkan antara dua bahasa Turing Lengkap selalu memungkinkan. Mengabaikan hal-hal seperti panggilan perpustakaan dan FFI dan bit praktis jahat lainnya yang menghalangi, yaitu. Jika bahasa Turing Lengkap, maka Anda memiliki:
Jadi, untuk menerjemahkan dari bahasa A ke bahasa B, Anda mengubah kode A menjadi Mesin Turing, lalu mengonversi mesin itu menjadi kode B.
Tentu saja, dalam praktiknya, bit praktis menghalangi, dan ini juga mengharuskan Anda memiliki terjemahan yang dapat diakses oleh Anda. Mereka ada pada dasarnya untuk setiap bahasa, tetapi itu tidak berarti seseorang telah meluangkan waktu untuk menuliskannya.
Melakukan terjemahan ini secara efisien itu sulit . Bahasa yang berbeda memprioritaskan hal yang berbeda. Misalnya, jika Anda menerjemahkan dari C ke Python, Anda mungkin harus akhirnya mensimulasikan memori C sebagai kamus Python, sehingga Anda dapat melakukan aritmatika pointer. Akan ada overhead terkait dengan ini, karena Anda sekarang tidak mengakses instruksi memori logam kosong.
Bahasa yang berbeda memiliki prioritas kinerja yang berbeda, sehingga sesuatu yang dioptimalkan satu bahasa (atau lebih tepatnya, implementasi dari satu bahasa dioptimalkan) mungkin mustahil dilakukan dengan cepat dalam bahasa lain. Menerjemahkan bahasa fungsional dengan panggilan ekor yang tepat akan memperlambat jika Anda menerjemahkannya ke bahasa tanpa panggilan ekor yang tepat.
Melakukan terjemahan ini tidak membuat kode dapat dibaca . Sangat mudah untuk mendapatkan sepotong kode dalam bahasa B yang berperilaku sama dengan kode dari bahasa A. Sulit untuk membuatnya terlihat seperti kode yang ditulis manusia dalam B, karena sejumlah alasan. A dan B mungkin memiliki alat abstraksi yang berbeda, dan komputer tidak tahu apa yang membuat kode dapat dibaca. Ini akan benar terutama jika Anda akhirnya menggunakan terjemahan Mesin Turing yang saya jelaskan sebelumnya.
Ini menimbulkan pertanyaan: apa gunanya terjemahan seperti itu? Jika semua yang Anda dapatkan pada kami blok kode lambat, tidak terbaca, mengapa tidak mengkompilasinya ke kode mesin dan menggunakan beberapa jenis FFI atau komunikasi antar-proses untuk menghubungkan potongan-potongan bersama?
Ada beberapa pengecualian untuk ini. Terkadang Anda membutuhkan hal-hal dalam bahasa tertentu (seperti JavaScript). Terkadang bahasa mirip, dan terjemahan yang masuk akal mudah. Terkadang suatu bahasa tidak dimaksudkan untuk dijalankan, tetapi untuk memiliki kode yang diekstraksi ke bahasa lain (seperti Coq).
Tetapi secara umum, ini bukan hal yang sangat praktis.
sumber
Ada beberapa program seperti itu. Misalnya penerjemah Lisp-ke-Fortran, yang banyak digunakan pada zaman mereka. Compiler Lisp tunggal tidak mengkompilasi Lisp secara langsung tetapi menghasilkan kode C sebagai gantinya yang kemudian dikompilasi oleh kompiler C biasa. Contoh lain adalah Vala yang tidak dikompilasi secara langsung tetapi pertama-tama diterjemahkan ke C ++ sebelum kode C ++ dikompilasi. Qt ditulis dalam MOC, bahasa yang diterjemahkan ke C ++ untuk mengkompilasinya (tetapi karena MOC hanya C ++ dengan beberapa perintah tambahan, seseorang dapat berdebat jika benar-benar dinamai "bahasa baru") - dan sebelum ada adalah kompiler C ++ ada C ++ - to-C-translators. Dan beberapa proyek ditulis dalam Pascal dan kemudian diterjemahkan ke C. Juga dentang dan Jawa cenderung semacam itu karena mereka menerjemahkan C ++ dan kode Java ke beberapa bahasa perantara yang kemudian dapat diproses lebih lanjut.
Apa yang tidak dapat Anda harapkan dari hasil penerjemah bahasa adalah bahwa hasilnya masuk akal bagi seorang pembaca manusia: Tugas program adalah menulis kode yang menghasilkan program yang melakukan hal yang sama dengan kode asli (yang menurut pengalaman saya mungkin atau mungkin tidak berfungsi, tergantung fitur bahasa yang mana dan perpustakaan eksternal yang Anda gunakan). Tetapi karena tidak tahu tujuan tugas ini dilakukan untuk sisa arti program mungkin hilang sebagian besar.
sumber
Bukan jawaban langsung, tetapi di dalamnya ada tool call ILSpy , yang ditulis untuk .Net Framework, dan memungkinkan Anda mendekompilasi rakitan .Net ke C # atau VB.Net.
Jika Anda tidak terbiasa dengan sifat .Net, Anda dapat menulis kode .Net dalam banyak bahasa tetapi terutama C # atau VB.Net. Ketika kompiler mengkompilasi aplikasi, itu menerjemahkan kode ke kode "Bahasa Menengah" (atau IL untuk singkatnya). Kode ini kemudian dikompilasi ke binari .Net.
Karena aplikasi .Net adalah binari yang dikompilasi dari kode IL, ILSpy dapat mengambil aplikasi .Net, membalikkannya kembali ke kode IL dan, kemudian, mengambilnya selangkah lebih maju dan membalikkannya kembali ke C # atau VB.Net.
Dengan menggunakan alat ini, yang harus Anda lakukan adalah mengkompilasi aplikasi, dan kemudian Anda dapat menelusuri file yang dikompilasi sebagai kode IL, C # atau VB.Net. Untuk lebih jelasnya, tidak masalah bahasa apa kode awalnya ditulis. Selama biner adalah .Net perakitan, itu dapat merekayasa balik file yang dikompilasi dan output konten sebagai salah satu dari tiga bahasa ini.
Saya tahu ini bukan kompiler, tetapi ini adalah alat yang menawarkan hasil akhir yang mirip dengan apa yang Anda cari dan, pada kenyataannya, saya telah menggunakan ini untuk "menerjemahkan" proyek VB.Net menjadi sesuatu yang sedikit lebih akrab dengan saya-- C #.
sumber
Untuk kasus penggunaan Anda (berdasarkan komentar), sepertinya SWIG mungkin berguna.
sumber
Saya ingat f2c yang terhormat , yang menerjemahkan dari sumber ke sumber dari Fortran 77 ke C.
Itu (kadang-kadang ...) digunakan terutama untuk menerjemahkan kode numerik dari beberapa dekade yang lalu tanpa harus mengintegrasikan kompiler fortran ke toolchain Anda.
sumber
Sepotong teori yang memberi tahu Anda bahwa program semacam itu ada, pada prinsipnya, disebut penomoran yang dapat diterima . Kita dapat membuktikan bahwa ada kompiler yang dapat dihitung antara dua penomoran tersebut, dan setiap formalisme lengkap Turing (atau bahasa pemrograman) pada dasarnya adalah satu.
sumber