Apakah ada program yang dapat 'menerjemahkan' kode sumber antara dua bahasa?

28

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).

Tobi Alafin
sumber
14
Apa yang Anda maksud dengan "dua bahasa"? Tentunya ada program yang dapat menerjemahkan dari satu bahasa ke bahasa lain. Mereka disebut "kompiler". Itulah definisi kompiler: program yang menerjemahkan program dari satu bahasa ke bahasa lain. Tapi "ada dua bahasa"? Saya pikir itu tidak mungkin. Penerjemah harus mengetahui sumber dan bahasa target, dan biasanya khusus untuk pasangan bahasa tertentu.
Jörg W Mittag
Program ini menyediakan sumber dan bahasa target. Saya sedang berpikir untuk menulis sebuah program dalam C ++, menerjemahkannya ke Java, python, Perl, Ruby, Go, dll. Mungkin ada beberapa batasan (saya tidak berharap itu untuk mengubah skrip shell Anda ke MATLAB misalnya).
Tobi Alafin
4
Ya, mereka disebut kompiler, mereka bekerja seperti kompiler dan mereka dapat dibangun seperti kompiler.
user253751
1
Jika dengan "dua bahasa" Anda benar-benar berarti bahwa program (terbatas) harus dapat membaca dan memahami jumlah bahasa input yang tak terbatas, jawabannya adalah sepele tidak . Namun, ambillah sekumpulan bahasa input yang terbatas dan Anda dapat menemukan kompiler untuk semua bahasa itu ..
Bakuriu

Jawaban:

57

TLDR; ini mungkin tetapi tidak praktis.

(dengan asumsi penerjemah memiliki akses ke perpustakaan yang diperlukan)?

Ini akhirnya menjadi bagian yang sulit, dan merupakan bagian dari mengapa hal-hal seperti ini tidak berakhir digunakan dalam praktik.

  1. 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.

  2. 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:

    • Terjemahan yang mengonversi Mesin Turing ke kode dalam bahasa ini
    • Terjemahan dari bahasa ini ke dalam Mesin Turing

    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.

  3. 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.

  4. 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.

Ya ampun
sumber
5
Salah satu contoh untuk Point 4 adalah asm.js . Hari ini, adalah mungkin untuk membuatnya agak terbaca, menggunakan Javascript Source Maps dan Element Inspector, tetapi tidak ada yang mau melakukan itu ...
Ismael Miguel
1
Modelica adalah contoh lain dari bahasa yang dirancang untuk dikompilasi ke bahasa lain (dalam hal ini C).
Pasang kembali Monica
Diterjemahkan secara web dari C ++ ke javascript.
Surt
Ada banyak contoh transponder dari X ke Y, tetapi itu berbeda dari apa pun yang universal ke kompiler apa pun. Jelas ada kasus-kasus di mana transpiling masuk akal.
jmite
Satu pengecualian penting yang hilang dari IMO: dikompilasi ke C. Alasannya adalah bahwa banyak sistem yang tidak umum memiliki kompiler C yang ada, yang umumnya dapat mengeluarkan kode mesin yang cukup masuk akal. Oleh karena itu, dengan mengkompilasi bahasa ke C, Anda tidak perlu memiliki backend untuk arsitektur langka itu.
MSalters
2

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.

Gunter Königsmann
sumber
0

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 #.

RLH
sumber
0

Untuk kasus penggunaan Anda (berdasarkan komentar), sepertinya SWIG mungkin berguna.

SWIG adalah alat pengembangan perangkat lunak yang menghubungkan program yang ditulis dalam C dan C ++ dengan berbagai bahasa pemrograman tingkat tinggi. SWIG digunakan dengan berbagai jenis bahasa target termasuk bahasa scripting umum seperti Javascript, Perl, PHP, Python, Tcl dan Ruby. Daftar bahasa yang didukung juga mencakup bahasa non-skrip seperti C #, Common Lisp (CLISP, Allegro CL, CFFI, UFFI), D, Bahasa Go, Java termasuk Android, Lua, Modula-3, OCAML, Oktaf, Scilab dan R Juga beberapa implementasi Skema yang ditafsirkan dan dikompilasi (Guile, MzScheme / Racket, Chicken) didukung.

Nathan Ringo
sumber
0

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.

Alexandre C.
sumber
0

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.

Raphael
sumber