Jenis pola apa yang dapat saya terapkan pada kode agar lebih mudah diterjemahkan ke bahasa pemrograman lain? [Tutup]

95

Saya akan melakukan proyek sampingan yang bertujuan untuk menerjemahkan kode dari satu bahasa pemrograman ke bahasa lain. Bahasa yang saya gunakan adalah PHP dan Python (Python ke PHP seharusnya lebih mudah untuk memulai), tetapi idealnya saya dapat menambahkan bahasa lain dengan (relatif) dengan mudah. Rencananya adalah:

  • Ini diarahkan untuk pengembangan web. Kode asli dan target akan berada di atas kerangka kerja (yang juga harus saya tulis). Kerangka kerja ini akan menerapkan pola desain MVC dan mengikuti konvensi pengkodean yang ketat. Ini akan membuat terjemahan menjadi lebih mudah.

  • Saya juga melihat IOC dan injeksi ketergantungan, karena mereka mungkin membuat proses terjemahan lebih mudah dan lebih sedikit rawan kesalahan.

  • Saya akan menggunakan modul parser Python , yang memungkinkan saya mengutak-atik Pohon Sintaks Abstrak. Rupanya yang paling dekat yang bisa saya dapatkan dengan PHP adalah token_get_all () , yang merupakan permulaan.

  • Sejak saat itu saya dapat membangun AST, tabel simbol, dan aliran kontrol.

Kemudian saya yakin saya dapat mulai mengeluarkan kode. Saya tidak butuh terjemahan yang sempurna . Saya masih harus meninjau kode yang dibuat dan memperbaiki masalah. Idealnya, penerjemah harus menandai terjemahan yang bermasalah.

Sebelum Anda bertanya "Apa gunanya semua ini?" Jawabannya adalah ... Ini akan menjadi pengalaman belajar yang menarik. Jika Anda memiliki wawasan tentang cara membuat ini tidak terlalu menakutkan, beri tahu saya.


EDIT:

Saya lebih tertarik untuk mengetahui jenis pola apa yang dapat saya terapkan pada kode untuk membuatnya lebih mudah dalam menerjemahkan (yaitu: IoC, SOA?) Kode daripada bagaimana melakukan terjemahan.

NullUserException
sumber
6
Pernahkah Anda melihat sistem seperti .NET CLR atau Perl6's Parrot? Mereka mengompilasi satu set bahasa hingga ke representasi perantara yang dapat dijalankan oleh penerjemah umum. Jika Anda dapat kembali dari representasi perantara ke sebuah bahasa, Anda memiliki penerjemah.
Borealid
1
@Borealid AFAIK NET CIL adalah (relatif) mudah untuk mengkompilasi menjadi , tapi keberuntungan mendapatkan dibaca kembali kode dari itu. Melihat Parrot sekarang.
NullUserException
Ada proyek serupa untuk bahasa lain; Saya tidak yakin seberapa kaya pengarangnya. Dan saya sebenarnya banyak menahan diri di sini, dengan membutuhkan kerangka kerja dan mematuhi konvensi pengkodean yang ketat.
NullUserException
2
Saya tidak dapat menambahkan pengetahuan khusus apa pun, tetapi apakah Anda pernah melihat piyama ( pyjs.org ), khususnya translator.py? Ini adalah kompiler python ke javascript.
stephan
3
EDIT Ulang: Jika Anda memiliki kendali atas kode yang akan diterjemahkan, hal paling jelas yang harus dilakukan adalah menghindari konstruksi yang sulit diterjemahkan! Misalnya, C jauh lebih mudah untuk diterjemahkan ke Java jika tidak ada aritmatika penunjuk. Untuk Python, saya mungkin akan menjauh dari penutupan. Hal lain yang dapat Anda lakukan adalah menulis kode sumber sedemikian rupa sehingga bagian yang lebih sulit diterjemahkan selalu dikodekan secara idiomatis, membuatnya lebih mudah untuk dikenali dan menangani kasus-kasus khusus.
Ira Baxter

Jawaban:

122

Saya telah membangun alat (DMS Software Reengineering Toolkit) untuk melakukan manipulasi program tujuan umum (dengan terjemahan bahasa menjadi kasus khusus) sejak 1995, didukung oleh tim ilmuwan komputer yang kuat. DMS menyediakan penguraian generik, pembuatan AST, tabel simbol, kontrol dan analisis aliran data, penerapan aturan terjemahan, regenerasi teks sumber dengan komentar, dll., Semua diparameterisasi oleh definisi eksplisit bahasa komputer.

Jumlah mesin yang Anda perlukan untuk melakukan ini dengan baik sangat banyak (terutama jika Anda ingin melakukannya untuk beberapa bahasa secara umum), dan kemudian Anda memerlukan parser yang andal untuk bahasa dengan definisi yang tidak dapat diandalkan (PHP adalah contoh sempurna untuk ini. ).

Tidak ada yang salah dengan Anda memikirkan tentang membangun penerjemah bahasa-ke-bahasa atau mencobanya, tetapi saya pikir Anda akan menganggap ini tugas yang jauh lebih besar untuk bahasa nyata daripada yang Anda harapkan. Kami memiliki sekitar 100 tahun manusia yang diinvestasikan hanya dalam DMS, dan 6-12 bulan lagi dalam setiap definisi bahasa yang "dapat diandalkan" (termasuk yang kami buat dengan susah payah untuk PHP), lebih banyak lagi untuk bahasa yang tidak menyenangkan seperti C ++. Ini akan menjadi "pengalaman belajar yang luar biasa"; itu untuk kita. (Anda mungkin menemukan bagian Makalah Teknis di situs web di atas menarik untuk memulai pembelajaran itu).

Orang sering mencoba untuk membangun sejenis mesin yang digeneralisasikan dengan memulai dengan beberapa bagian teknologi yang mereka kenal, yang melakukan sebagian pekerjaan. (Python ASTs adalah contoh yang bagus). Kabar baiknya, sebagian pekerjaan sudah selesai. Kabar buruknya adalah bahwa permesinan memiliki jutaan asumsi yang tertanam di dalamnya, yang sebagian besar tidak akan Anda temukan sampai Anda mencoba untuk bergulat dengan melakukan sesuatu yang lain. Pada titik itu Anda menemukan bahwa mesin tersebut terhubung untuk melakukan apa yang awalnya dilakukannya, dan akan benar-benar menolak upaya Anda untuk membuatnya melakukan sesuatu yang lain. (Saya menduga mencoba membuat Python AST untuk memodelkan PHP akan sangat menyenangkan).

Alasan saya mulai membangun DMS pada awalnya adalah untuk membangun fondasi yang memiliki sedikit asumsi bawaan. Ada beberapa yang membuat kami pusing. Sejauh ini, tidak ada lubang hitam. (Bagian tersulit dari pekerjaan saya selama 15 tahun terakhir adalah mencoba mencegah asumsi semacam itu merayap masuk).

Banyak orang juga membuat kesalahan dengan berasumsi bahwa jika mereka dapat mengurai (dan mungkin mendapatkan AST), mereka sedang dalam proses untuk melakukan sesuatu yang rumit. Salah satu pelajaran yang sulit adalah Anda memerlukan tabel simbol dan analisis aliran untuk melakukan analisis atau transformasi program yang baik. AST diperlukan tetapi tidak cukup. Inilah alasan mengapa buku penyusun Aho & Ullman tidak berhenti di bab 2. (OP memiliki hak ini karena dia berencana untuk membangun mesin tambahan di luar AST). Untuk informasi lebih lanjut tentang topik ini, lihat Life After Parsing .

Komentar tentang "Saya tidak butuh terjemahan yang sempurna" merepotkan. Apa yang dilakukan penerjemah lemah adalah mengubah 80% kode "mudah", menyisakan 20% yang sulit dikerjakan dengan tangan. Jika aplikasi yang ingin Anda ubah berukuran cukup kecil, dan Anda hanya bermaksud untuk mengubahnya sekali saja, maka 20% itu tidak masalah. Jika Anda ingin mengonversi banyak aplikasi (atau bahkan aplikasi yang sama dengan sedikit perubahan seiring waktu), ini tidak bagus. Jika Anda mencoba mengonversi 100K SLOC maka 20% adalah 20.000 baris kode asli yang sulit diterjemahkan, dipahami, dan dimodifikasi dalam konteks 80.000 baris program terjemahan lainnya yang belum Anda pahami. Itu membutuhkan usaha yang sangat besar. Pada tingkat jutaan baris, ini tidak mungkin dalam praktiknya.lebih sulit dan mereka biasanya mengetahuinya dengan sangat menyakitkan dengan penundaan waktu yang lama, biaya tinggi dan seringkali kegagalan langsung.)

Apa yang harus Anda bidik untuk menerjemahkan sistem skala besar adalah persentase rasio konversi yang tinggi, atau sepertinya Anda tidak dapat menyelesaikan bagian manual dari aktivitas penerjemahan.

Pertimbangan utama lainnya adalah ukuran kode yang akan diterjemahkan. Dibutuhkan banyak energi untuk membangun penerjemah yang berfungsi dan tangguh, bahkan dengan alat yang bagus. Meskipun tampak seksi dan keren untuk membangun penerjemah daripada hanya melakukan konversi manual, untuk basis kode kecil (misalnya, hingga sekitar 100K SLOC menurut pengalaman kami) ekonomi tidak membenarkannya. Tidak ada yang menyukai jawaban ini, tetapi jika Anda benar-benar harus menerjemahkan kode 10K SLOC, Anda mungkin lebih baik hanya menggigit peluru dan melakukannya. Dan ya, itu menyakitkan.

Saya menganggap alat kami sangat bagus (tapi kemudian, saya cukup bias). Dan masih sangat sulit untuk membangun penerjemah yang baik; kami membutuhkan waktu sekitar 1,5-2 tahun kerja dan kami tahu cara menggunakan alat kami. Perbedaannya adalah dengan mesin sebanyak ini, kita lebih sering berhasil daripada gagal.

Ira Baxter
sumber
8
Pernahkah Anda mempertimbangkan untuk menyumbangkan definisi PHP yang "dibuat dengan susah payah" kembali ke komunitas PHP secara luas, atau terlalu terkait erat dengan aliran pendapatan Anda sendiri untuk membuatnya memungkinkan?
TML
53
Saya telah diminta untuk membuat semua yang kami lakukan menjadi "open source" oleh banyak orang yang tidak ingin berkontribusi pada aliran pendapatan, dan tidak memiliki energi untuk melakukan pekerjaan dan open source sendiri. Jika Anda hanya berkontribusi sebagian kecil untuk proyek yang sangat besar, dan / atau Anda memiliki sumber pendapatan lain, "open source" tampaknya bagus. Jika Anda telah melakukan semua pekerjaan itu sendiri dan itu adalah satu-satunya sumber pendapatan Anda, ini jauh lebih menarik. [Saya tidak ingin berdiskusi tentang manfaat relatif dari filosofi "perangkat lunak bebas", jadi saya tidak akan berpartisipasi dalam komentar lebih lanjut di sepanjang baris ini]
Ira Baxter
9
Saya setuju dengan apa yang Anda katakan di sini, itulah sebabnya saya mengutarakan pertanyaan seperti yang saya lakukan. Menurut saya, dari tanggapan itu kita akan mengerti bahwa Anda merasa itu terlalu terkait erat dengan pendapatan Anda, dan sama sekali tidak ada yang salah dengan itu - menurut saya itu layak untuk ditanyakan.
TML
3
@IraBaxter Anda baru saja mengucapkan idiom umum tentang praktik yang berkaitan dengan komputer yang dapat diterapkan pada banyak praktik lainnya. Satu-satunya hal yang menarik dari semua yang Anda tulis adalah tautan ke semanticdesigns.com (yang kebetulan adalah perusahaan Anda)
amirouche
1
Anda sering memberikan link ke halaman terkait Clang dalam jawaban Anda. Itu hanya membuktikan bahwa orang lain bisa membuat halaman web. Sebagian besar dari kita berasumsi bahwa halaman web yang ditulis dengan baik menyiratkan bahwa ada pekerjaan serius dan nyata di belakangnya dan bukan hanya upaya penipuan untuk menipu pembaca seperti yang tampaknya Anda maksudkan dalam jawaban Anda. Apakah Anda benar-benar yakin bahwa halaman web itu palsu? Halaman tersebut berisi informasi referensi ke sumber yang "relevan"; itu dianonomisasi karena kontrak untuk pekerjaan mensyaratkan itu. Bahwa saya tidak dapat membantu.
Ira Baxter
13

Jawaban saya akan membahas tugas khusus parsing Python untuk menerjemahkannya ke bahasa lain, dan bukan aspek tingkat tinggi yang diatasi dengan baik oleh Ira dalam jawabannya.

Singkatnya: jangan gunakan modul parser, ada cara yang lebih mudah.

The astmodul, tersedia sejak Python 2.6 jauh lebih cocok untuk kebutuhan Anda, karena memberi Anda AST siap pakai untuk bekerja dengan. Saya telah menulis artikel tentang ini tahun lalu, tetapi singkatnya, gunakan parsemetode astuntuk mengurai kode sumber Python menjadi AST. The parsermodul akan memberikan pohon parsing, bukan AST. Waspadai perbedaannya .

Sekarang, karena AST Python cukup detail, mengingat AST, pekerjaan front-end tidak terlalu sulit. Saya kira Anda dapat memiliki prototipe sederhana untuk beberapa bagian fungsi yang siap dengan cukup cepat. Namun, mendapatkan solusi lengkap akan membutuhkan waktu lebih lama, terutama karena semantik bahasanya berbeda. Bagian sederhana dari bahasa (fungsi, tipe dasar, dan sebagainya) dapat dengan mudah diterjemahkan, tetapi begitu Anda masuk ke lapisan yang lebih kompleks, Anda memerlukan alat berat untuk meniru inti satu bahasa dengan bahasa lain. Sebagai contoh pertimbangkan generator Python dan pemahaman daftar yang tidak ada di PHP (menurut pengetahuan terbaik saya, yang diakui buruk ketika PHP terlibat).

Untuk memberi Anda satu tip terakhir, pertimbangkan 2to3alat yang dibuat oleh pengembang Python untuk menerjemahkan kode Python 2 ke kode Python 3. Dari segi front-end, ia memiliki sebagian besar elemen yang Anda butuhkan untuk menerjemahkan Python menjadi sesuatu . Namun, karena inti Python 2 dan 3 serupa, tidak diperlukan mesin emulasi di sana.

Eli Bendersky
sumber
Weeeell. 2to3hanyalah AST ke AST. Itu tidak mendukung melakukan apa pun yang melampaui kemampuan astmodul. Perhatikan bahwa semua terjemahan beralih dari sintaks yang didukung oleh proses python host ke sintaks yang didukung oleh proses python host. Tidak ada penerjemah yang menambahkan, katakanlah, penjelasan fungsi, karena 2.6 tidak mendukungnya.
habnabit
... dan pertanyaan OP mungkin dibingkai, jangka pendek, bagaimana mendapatkan dari Python 2.6 AST ke ... sesuatu di PHP. Modul ast kemungkinan besar tidak ingin merepresentasikan sintaks PHP dengan baik, jadi bahkan ast untuk ast.
Ira Baxter
2
@Aaron: 2to3dapat dilihat sebagai contoh penggunaan AST yang dihasilkan dari ast.
Eli Bendersky
AFAIK, 2to3 bisa dibilang merupakan terjemahan yang lebih mudah dari Python ke PHP (lagipula, Python-nya ke Python, kan)? Dan bahkan itu tidak bekerja dengan baik. Perhatikan banyaknya Python 2.6 yang belum didorong melalui 2to3 ... karena tampaknya ada banyak tambalan tangan terjemahan pos yang masih harus dilakukan. Jika 100% otomatis, Python 2.6 akan mati.
Ira Baxter
5

Menulis penerjemah bukanlah hal yang mustahil, terutama mengingat Joel's Intern melakukannya selama musim panas.

Jika Anda ingin melakukan satu bahasa, itu mudah. Jika Anda ingin berbuat lebih banyak, itu sedikit lebih sulit, tetapi tidak terlalu banyak. Bagian tersulit adalah, meskipun bahasa lengkap turing dapat melakukan apa yang dilakukan bahasa lengkap turing lainnya, tipe data bawaan dapat mengubah apa yang dilakukan bahasa secara fenomenal.

Misalnya:

word = 'This is not a word'
print word[::-2]

membutuhkan banyak kode C ++ untuk diduplikasi (ok, Anda bisa melakukannya cukup singkat dengan beberapa konstruksi perulangan, tapi tetap saja).

Itu agak menyimpang, kurasa.

Apakah Anda pernah menulis tokenizer / parser berdasarkan tata bahasa? Anda mungkin ingin mempelajari cara melakukannya jika belum melakukannya, karena itulah bagian utama dari proyek ini. Apa yang akan saya lakukan adalah membuat sintaks lengkap Turing dasar - sesuatu yang cukup mirip dengan bytecode Python . Kemudian Anda membuat lexer / parser yang menggunakan tata bahasa (mungkin menggunakan BNF ), dan berdasarkan tata bahasa, mengkompilasi bahasa tersebut ke dalam bahasa perantara Anda. Kemudian yang ingin Anda lakukan adalah melakukan kebalikannya - membuat parser dari bahasa Anda ke bahasa target berdasarkan tata bahasa.

Masalah paling jelas yang saya lihat adalah pada awalnya Anda mungkin akan membuat kode yang sangat tidak efisien, terutama dalam bahasa yang lebih kuat * seperti Python.

Tetapi jika Anda melakukannya dengan cara ini maka Anda mungkin dapat menemukan cara untuk mengoptimalkan keluaran saat Anda melanjutkan. Untuk meringkas:

  • baca tata bahasa yang tersedia
  • kompilasi program menjadi sintaks menengah (tetapi juga Turing complete)
  • kompilasi program menengah ke dalam bahasa akhir (berdasarkan tata bahasa yang disediakan)
  • ...?
  • Keuntungan!(?)

* Dengan kuat maksud saya ini membutuhkan 4 baris:

myinput = raw_input("Enter something: ")
print myinput.replace('a', 'A')
print sum(ord(c) for c in myinput)
print myinput[::-1]

Tunjukkan pada saya bahasa lain yang dapat melakukan hal seperti itu dalam 4 baris, dan saya akan menunjukkan kepada Anda bahasa yang sekuat Python.

Wayne Werner
sumber
“Apakah Anda pernah menulis tokenizer / parser berdasarkan tata bahasa?” Saya telah melakukannya menggunakan JavaCC.
NullUserException
2
Pekerja magang Joel melakukan sebagian pekerjaan selama musim panas. Bahasa sumbernya adalah bagian dari bahasa yang sudah ada, dan mungkin bagian ini bisa disesuaikan. Itu membuat pekerjaan itu jauh lebih mudah. Demikian pula, NullPointerException mungkin ingin memulai dengan bagian Python yang lebih mudah, mungkin meneruskan hal-hal yang lebih sulit untuk konversi manual (seperti yang disebutkan dalam pertanyaan).
David Thornley
@NullUserException: Anda akan memiliki beberapa eksposur, tetapi pada dasarnya Anda akan melakukan implementasi ulang JavaCC, hanya sebagai pengganti Java sebagai bahasa output, Anda akan melakukan <masukkan bahasa di sini>. @David, lumayan. Bahkan Thistle membutuhkan bantuan dalam beberapa konstruksi bahasa. Jika saya adalah OP, saya akan mencari fungsionalitas terlebih dahulu, kemudian mengoptimalkan, jika tidak saya akan terjebak selamanya mencoba untuk mendapatkan C ++ untuk melakukan pemotongan string (dengan langkah-langkah): p
Wayne Werner
@WayneWerner Sebagai catatan, bahasa seperti C # tidak memerlukan baris baru sama sekali. (Setidaknya, tidak setelah Anda menghapus komentar satu baris.) Jadi Anda bisa menulis program C # dalam satu baris. Tapi tentu saja saya mengerti apa yang Anda maksud.
leviathanbadger
@ aboveyou00: Saya rasa itu tidak benar. Jika Anda melarang praprosesor bersyarat, Anda mungkin benar.
Ira Baxter
3

Ada beberapa jawaban yang memberi tahu Anda untuk tidak repot. Nah, seberapa membantu itu? Anda ingin belajar? Kamu bisa belajar. Ini kompilasi. Kebetulan bahasa target Anda bukanlah kode mesin, tetapi bahasa tingkat tinggi lainnya. Ini dilakukan setiap saat.

Ada cara yang relatif mudah untuk memulai. Pertama, dapatkan http://sourceforge.net/projects/lime-php/ (jika Anda ingin bekerja di PHP) atau semacamnya dan lihat kode contoh. Selanjutnya, Anda dapat menulis penganalisis leksikal menggunakan urutan ekspresi reguler dan memasukkan token ke parser yang Anda buat. Tindakan semantik Anda dapat menghasilkan kode secara langsung dalam bahasa lain atau membangun beberapa struktur data (pikirkan objek, man) yang dapat Anda pijat dan lintasi untuk menghasilkan kode keluaran.

Anda beruntung dengan PHP dan Python karena dalam banyak hal mereka memiliki bahasa yang sama satu sama lain, tetapi dengan sintaks yang berbeda. Bagian tersulit adalah mengatasi perbedaan semantik antara bentuk tata bahasa dan struktur data. Misalnya, Python memiliki daftar dan kamus, sedangkan PHP hanya memiliki array assoc.

Pendekatan "pelajar" adalah membuat sesuatu yang berfungsi dengan baik untuk subset bahasa yang dibatasi (seperti hanya pernyataan cetak, matematika sederhana, dan tugas variabel), dan kemudian secara bertahap menghapus batasan. Pada dasarnya itulah yang dilakukan oleh semua orang "besar" di lapangan.

Oh, dan karena Anda tidak memiliki tipe statis di Python, mungkin yang terbaik adalah menulis dan mengandalkan fungsi PHP seperti "python_add" yang menambahkan angka, string, atau objek sesuai dengan cara Python melakukannya.

Jelas, ini bisa menjadi jauh lebih besar jika Anda membiarkannya.

Ian
sumber
3
Sebenarnya, saya tidak mengatakan "jangan repot-repot". Apa yang saya katakan adalah, "menerjemahkan bahasa secara umum sangat sulit". Jika OP melanjutkan ke jalur aslinya menggunakan pohon Python untuk mencoba dan menghasilkan PHP, dia akan belajar banyak dan saya mendukung pengalaman belajar; Saya mulai dari sana juga. Dia tidak akan bisa menambahkan bahasa baru dengan mudah.
Ira Baxter
@IraBaxter Saya tidak dapat mendukung pernyataan Anda, melakukan Python-> PHP dan PHP-> Javascript akan sangat mudah. cf. bagian terakhir stackoverflow.com/a/22850139/140837 di tengah jawaban Saya juga menangani "argumentasi" Anda
amirouche
2

Saya akan kedua sudut pandang @EliBendersky tentang penggunaan ast.parse daripada parser (yang tidak saya ketahui sebelumnya). Saya juga sangat merekomendasikan Anda untuk mereview blognya. Saya menggunakan ast.parse untuk melakukan Python-> penerjemah JavaScript (@ https://bitbucket.org/amirouche/pythonium ). Aku telah datang dengan desain Pythonium oleh agak meninjau implementasi lain dan mencoba mereka sendiri. Saya bercabang Pythonium dari https://github.com/PythonJS/PythonJS yang juga saya mulai, Ini sebenarnya penulisan ulang lengkap. Desain keseluruhan terinspirasi dari kertas PyPy dan http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-89-1.pdf .

Semua yang saya coba, dari awal hingga solusi terbaik, bahkan jika itu terlihat seperti pemasaran Pythonium sebenarnya tidak (jangan ragu untuk memberi tahu saya jika ada sesuatu yang tampaknya tidak benar untuk netiket):

  • Menerapkan semantik Python di Plain Old JavaScript menggunakan warisan prototipe: AFAIK tidak mungkin menerapkan warisan berganda Python menggunakan sistem objek prototipe JS. Saya mencoba melakukannya menggunakan trik lain nanti (lih. Getattribute). Sejauh yang saya tahu tidak ada implementasi Python multiple inheritance dalam JavaScript, yang terbaik yang ada adalah Single inhertance + mixins dan saya tidak yakin mereka menangani diamond inheritance. Mirip dengan Skulpt tapi tanpa clojure google.

  • Saya mencoba dengan Google clojure, seperti Skulpt (compiler) daripada benar-benar membaca kode Skulpt #fail. Pokoknya karena sistem objek berbasis prototipe JS masih mustahil. Membuat pengikatan sangat sulit, Anda perlu menulis JavaScript dan banyak kode boilerplate (lihat https://github.com/skulpt/skulpt/issues/50 di mana saya adalah hantu). Saat itu belum ada cara yang jelas untuk mengintegrasikan binding dalam sistem build. Saya pikir Skulpt adalah sebuah pustaka dan Anda hanya perlu memasukkan file .py Anda ke dalam html untuk dieksekusi, tidak ada fase kompilasi yang harus dilakukan oleh pengembang.

  • Telah mencoba pyjaco (compiler) tetapi membuat binding (memanggil kode Javascript dari kode Python) sangat sulit, terlalu banyak kode boilerplate yang harus dibuat setiap saat. Sekarang saya pikir pyjaco adalah salah satu yang lebih dekat dengan Pythonium. pyjaco ditulis dengan Python (ast.parse juga) tetapi banyak yang ditulis dalam JavaScript dan menggunakan warisan prototipe.

Saya tidak pernah benar-benar berhasil menjalankan Piyama #fail dan tidak pernah mencoba membaca kode #fail lagi. Tetapi dalam pikiran saya, piyama melakukan terjemahan API-> API (atau kerangka kerja ke kerangka kerja) dan bukan terjemahan Python ke JavaScript. Framework JavaScript menggunakan data yang sudah ada di halaman atau data dari server. Kode Python hanya "pipa". Setelah itu saya menemukan bahwa piyama sebenarnya adalah penerjemah python-> js asli.

Masih saya pikir itu mungkin untuk melakukan terjemahan API-> API (atau kerangka kerja-> kerangka kerja) dan pada dasarnya itulah yang saya lakukan di Pythonium tetapi pada tingkat yang lebih rendah. Mungkin Piyama menggunakan algoritme yang sama dengan Pythonium ...

Kemudian saya menemukan brython sepenuhnya ditulis dalam Javascript seperti Skulpt, tidak perlu kompilasi dan banyak bulu ... tetapi ditulis dalam JavaScript.

Sejak baris awal yang ditulis selama proyek ini, saya tahu tentang PyPy, bahkan backend JavaScript untuk PyPy. Ya, Anda bisa, jika menemukannya, langsung membuat juru bahasa Python dalam JavaScript dari PyPy. Orang bilang, itu bencana. Saya tidak membaca di mana mengapa. Tapi saya pikir alasannya adalah bahwa bahasa perantara yang mereka gunakan untuk mengimplementasikan interpreter, RPython, adalah bagian dari Python yang disesuaikan untuk diterjemahkan ke C (dan mungkin asm). Ira Baxter mengatakan Anda selalu membuat asumsi ketika Anda membangun sesuatu dan mungkin Anda menyempurnakannya untuk menjadi yang terbaik dalam hal terjemahan PyPy: Python-> C. Asumsi tersebut mungkin tidak relevan dalam konteks lain, lebih buruk lagi asumsi tersebut dapat menjadi overhead, jika tidak, terjemahan langsung kemungkinan besar akan selalu lebih baik.

Memiliki penerjemah yang ditulis dengan Python terdengar seperti ide (sangat) bagus. Tetapi saya lebih tertarik pada kompiler karena alasan kinerja juga sebenarnya lebih mudah untuk mengkompilasi Python ke JavaScript daripada menafsirkannya.

Saya memulai PythonJS dengan ide menyusun subset Python yang bisa saya terjemahkan dengan mudah ke JavaScript. Pada awalnya saya bahkan tidak repot-repot mengimplementasikan sistem OO karena pengalaman masa lalu. Bagian dari Python yang saya capai untuk menerjemahkan ke JavaScript adalah:

  • berfungsi dengan semantik parameter lengkap baik dalam definisi maupun pemanggilan. Ini adalah bagian yang paling saya banggakan.
  • sementara / jika / elif / lain
  • Jenis Python diubah menjadi jenis JavaScript (tidak ada jenis python apapun)
  • untuk dapat mengulang hanya array Javascript (untuk array dalam)
  • Akses transparan ke JavaScript: jika Anda menulis Array dengan kode Python, itu akan diterjemahkan ke Array dalam javascript. Ini adalah pencapaian terbesar dalam hal kegunaan dibandingkan para pesaingnya.
  • Anda dapat meneruskan fungsi yang ditentukan dalam sumber Python ke fungsi javascript. Argumen default akan diperhitungkan.
  • Itu menambahkan memiliki fungsi khusus yang disebut baru yang diterjemahkan ke JavaScript baru misalnya: baru (Python) (1, 2, spam, "telur") diterjemahkan ke "Python baru (1, 2, spam," telur ").
  • "var" secara otomatis ditangani oleh penerjemah. (temuan yang sangat bagus dari Brett (kontributor PythonJS).
  • kata kunci global
  • penutupan
  • lambdas
  • pemahaman daftar
  • impor didukung melalui requirejs
  • warisan kelas tunggal + mixin melalui classyjs

Ini tampak seperti banyak tetapi sebenarnya sangat sempit dibandingkan dengan semantik penuh dari Python. Ini benar-benar JavaScript dengan sintaks Python.

JS yang dihasilkan sempurna yaitu. tidak ada biaya tambahan, tidak dapat ditingkatkan dalam hal kinerja dengan mengeditnya lebih lanjut. Jika Anda dapat meningkatkan kode yang dihasilkan, Anda juga dapat melakukannya dari file sumber Python. Selain itu, kompilator tidak bergantung pada trik JS apa pun yang dapat Anda temukan di .js yang ditulis oleh http://superherojs.com/ , jadi sangat mudah dibaca.

Keturunan langsung dari bagian PythonJS ini adalah mode Pythonium Veloce. Implementasi lengkap dapat ditemukan di @ https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/veloce/veloce.py?at=master 793 SLOC + sekitar 100 SLOC kode bersama dengan penerjemah lain.

Versi pystones.py yang diadaptasi dapat diterjemahkan dalam mode Veloce cf. https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pystone/?at=master

Setelah menyiapkan terjemahan Python-> JavaScript dasar, saya memilih jalur lain untuk menerjemahkan Python lengkap ke JavaScript. Cara fasih melakukan kode berbasis kelas berorientasi objek kecuali bahasa target adalah JS sehingga Anda memiliki akses ke array, objek seperti peta dan banyak trik lainnya dan semua bagian itu ditulis dengan Python. IIRC tidak ada kode javascript yang ditulis oleh penerjemah Pythonium. Mendapatkan warisan tunggal tidaklah sulit, berikut adalah bagian-bagian yang sulit membuat Pythonium sepenuhnya sesuai dengan Python:

  • spam.eggdengan Python selalu diterjemahkan ke getattribute(spam, "egg")Saya tidak membuat profil ini secara khusus tetapi saya pikir di mana itu kehilangan banyak waktu dan saya tidak yakin saya dapat memperbaikinya dengan asm.js atau yang lainnya.
  • urutan resolusi metode: bahkan dengan algoritma yang ditulis dengan Python, menerjemahkannya ke kode yang kompatibel dengan Python Veloce adalah usaha besar.
  • getattributre : algoritma resolusi getattribute sebenarnya agak rumit dan masih tidak mendukung deskriptor data
  • berbasis kelas metaclass: Saya tahu di mana harus memasang kode, tapi tetap ...
  • bu terakhir paling tidak: some_callable (...) selalu diterjemahkan ke "call (some_callable)". AFAIK penerjemah tidak menggunakan inferensi sama sekali, jadi setiap kali Anda melakukan panggilan, Anda perlu memeriksa jenis objek untuk menyebutnya sesuai dengan maksud panggilannya.

Bagian ini menjadi faktor dalam https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/compliant/runtime.py?at=master Ini ditulis dengan Python yang kompatibel dengan Python Veloce.

Penerjemah yang benar-benar sesuai https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/compliant/compliant.py?at=master tidak membuat kode JavaScript secara langsung dan yang terpenting tidak melakukan transformasi ast-> ast . Saya mencoba ast-> ast dan ast bahkan jika lebih bagus dari cst tidak bagus untuk bekerja dengan ast.NodeTransformer dan yang lebih penting saya tidak perlu melakukan ast-> ast.

Melakukan python ast to python ast dalam kasus saya setidaknya mungkin akan menjadi peningkatan kinerja karena saya kadang-kadang memeriksa konten blok sebelum membuat kode yang terkait dengannya, misalnya:

  • var / global: untuk dapat var sesuatu saya harus tahu apa yang saya butuhkan dan bukan untuk var. Alih-alih membuat pelacakan blok, variabel mana yang dibuat dalam blok tertentu dan menyisipkannya di atas blok fungsi yang dihasilkan, saya hanya mencari penetapan variabel yang relevan ketika saya memasuki blok sebelum benar-benar mengunjungi simpul anak untuk menghasilkan kode terkait.
  • yield, generator memiliki sintaks khusus dalam JS, jadi saya perlu tahu fungsi Python mana yang merupakan generator ketika saya ingin menulis "var my_generator = function"

Jadi saya tidak benar-benar mengunjungi setiap node sekali untuk setiap fase terjemahan.

Proses keseluruhan dapat digambarkan sebagai:

Python source code -> Python ast -> Python source code compatible with Veloce mode -> Python ast -> JavaScript source code

Bawaan Python ditulis dalam kode Python (!), IIRC ada beberapa batasan terkait dengan jenis bootstraping, tetapi Anda memiliki akses ke semua yang dapat menerjemahkan Pythonium dalam mode yang sesuai. Kunjungi https://bitbucket.org/amirouche/pythonium/src/33898da731ee2d768ced392f1c369afd746c25d7/pythonium/compliant/builtins/?at=master

Membaca kode JS yang dihasilkan dari pythonium compliant dapat dipahami tetapi peta sumber akan sangat membantu.

Nasihat berharga yang dapat saya berikan kepada Anda sehubungan dengan pengalaman ini adalah orang tua yang baik hati:

  • meninjau secara ekstensif subjek baik dalam literatur dan proyek yang ada, sumber tertutup atau gratis. Ketika saya meninjau berbagai proyek yang ada, saya seharusnya memberikan lebih banyak waktu dan motivasi.
  • mengajukan pertanyaan! Jika saya tahu sebelumnya bahwa backend PyPy tidak berguna karena overhead akibat ketidakcocokan semantik C / Javascript. Saya mungkin memiliki ide Pythonium jauh sebelum 6 bulan yang lalu mungkin 3 tahun yang lalu.
  • tahu apa yang ingin Anda lakukan, punya target. Untuk proyek ini saya memiliki tujuan yang berbeda: berlatih sedikit javascript, belajar lebih banyak tentang Python dan dapat menulis kode Python yang akan berjalan di browser (lebih banyak dan itu di bawah).
  • kegagalan adalah pengalaman
  • langkah kecil adalah satu langkah
  • mulai dari yang kecil
  • bercita-cita tinggi
  • lakukan demo
  • pengulangan

Dengan mode Python Veloce saja, saya sangat senang! Namun dalam perjalanan saya menemukan bahwa apa yang sebenarnya saya cari adalah membebaskan saya dan orang lain dari Javascript, tetapi yang lebih penting adalah dapat membuat dengan cara yang nyaman. Hal ini membawa saya ke Skema, DSL, Model, dan akhirnya model khusus domain (lihat http://dsmforum.org/ ).

Tentang apa tanggapan Ira Baxter:

Estimasi tersebut tidak membantu sama sekali. Saya menggunakan waktu luang kurang lebih 6 bulan untuk PythonJS dan Pythonium. Jadi saya bisa berharap lebih dari 6 bulan penuh waktu. Saya pikir kita semua tahu apa arti 100 man-year dalam konteks perusahaan dan tidak berarti sama sekali ...

Ketika seseorang mengatakan sesuatu itu sulit atau lebih sering tidak mungkin, saya menjawab bahwa "hanya perlu waktu untuk menemukan solusi untuk masalah yang tidak mungkin" sebaliknya mengatakan tidak ada yang mustahil kecuali jika terbukti tidak mungkin dalam hal ini bukti matematika ...

Jika tidak terbukti tidak mungkin maka itu menyisakan ruang untuk imajinasi:

  • menemukan bukti yang membuktikan itu tidak mungkin

dan

  • Jika tidak mungkin mungkin ada masalah "inferior" yang bisa punya solusi.

atau

  • jika bukan tidak mungkin, temukan solusi

Ini bukan hanya pemikiran optimis. Ketika saya memulai Python-> Javascript semua orang mengatakan itu tidak mungkin. PyPy tidak mungkin. Metaclasses terlalu keras. dll ... Saya pikir satu-satunya revolusi yang membawa PyPy di ​​atas kertas Skema-> C (yang berusia 25 tahun) adalah beberapa generasi JIT otomatis (menurut saya petunjuk berdasarkan yang tertulis dalam penerjemah RPython).

Kebanyakan orang yang mengatakan bahwa sesuatu itu "sulit" atau "tidak mungkin" tidak memberikan alasannya. C ++ sulit diurai? Saya tahu itu, tetap saja mereka adalah pengurai C ++ (gratis). Kejahatan dalam detailnya? Saya tahu itu. Mengatakan tidak mungkin sendirian tidak membantu, Ini bahkan lebih buruk daripada "tidak membantu" itu mengecilkan hati, dan beberapa orang bermaksud untuk membuat orang lain putus asa. Saya mendengar tentang pertanyaan ini melalui /programming/22621164/how-to-automatically-generate-a-parser-code-to-code-translator-from-a-corpus .

Apa kesempurnaan bagimu ? Begitulah cara Anda menentukan tujuan berikutnya dan mungkin mencapai tujuan keseluruhan.

Saya lebih tertarik untuk mengetahui jenis pola apa yang dapat saya terapkan pada kode untuk membuatnya lebih mudah dalam menerjemahkan (yaitu: IoC, SOA?) Kode daripada bagaimana melakukan terjemahan.

Saya tidak melihat pola yang tidak dapat diterjemahkan dari satu bahasa ke bahasa lain setidaknya dengan cara yang kurang sempurna. Karena terjemahan bahasa ke bahasa dimungkinkan, Anda sebaiknya membidiknya terlebih dahulu. Karena menurut saya menurut http://en.wikipedia.org/wiki/Graph_isomorphism_problem , terjemahan antara dua bahasa komputer adalah isomorfisme pohon atau DAG. Bahkan jika kita sudah tahu bahwa keduanya sama-sama lengkap, jadi ...

Framework-> Framework yang saya visualisasikan lebih baik sebagai API-> terjemahan API mungkin masih menjadi sesuatu yang mungkin Anda ingat sebagai cara untuk meningkatkan kode yang dihasilkan. Misalnya: Prolog sebagai sintaks yang sangat spesifik tetapi Anda tetap dapat melakukan Prolog seperti komputasi dengan menggambarkan grafik yang sama dengan Python ... Jika saya menerapkan penerjemah Prolog ke Python, saya tidak akan menerapkan penyatuan dengan Python tetapi di perpustakaan C dan datang menggunakan "sintaks Python" yang sangat mudah dibaca oleh seorang Pythonist. Pada akhirnya, sintaks hanya "lukisan" yang kita beri arti (itulah mengapa saya memulai skema). Kejahatan ada dalam detail bahasanya dan saya tidak berbicara tentang sintaks. Konsep-konsep yang digunakan dalam bahasa getattributehook (Anda bisa hidup tanpanya) tetapi fitur VM yang diperlukan seperti pengoptimalan tail-recursion bisa sulit ditangani. Anda tidak peduli jika program awal tidak menggunakan rekursi tail dan bahkan jika tidak ada rekursi ekor dalam bahasa target Anda dapat mengemulasinya menggunakan greenlets / event loop.

Untuk bahasa target dan sumber, cari:

  • Ide besar dan spesifik
  • Ide bersama yang kecil dan umum

Dari sini akan muncul:

  • Hal-hal yang mudah diterjemahkan
  • Hal-hal yang sulit diterjemahkan

Anda juga mungkin dapat mengetahui apa yang akan diterjemahkan ke kode cepat dan lambat.

Ada juga pertanyaan tentang stdlib atau perpustakaan apa pun tetapi tidak ada jawaban yang jelas, itu tergantung tujuan Anda.

Kode idiomatik atau kode yang dihasilkan yang dapat dibaca juga memiliki solusi ...

Menargetkan platform seperti PHP jauh lebih mudah daripada menargetkan browser karena Anda dapat memberikan implementasi C jalur lambat dan / atau kritis.

Mengingat proyek pertama Anda adalah menerjemahkan Python ke PHP, setidaknya untuk subset PHP3 yang saya ketahui, menyesuaikan veloce.py adalah pilihan terbaik Anda. Jika Anda dapat mengimplementasikan veloce.py untuk PHP maka mungkin Anda akan dapat menjalankan mode yang sesuai ... Juga jika Anda dapat menerjemahkan PHP ke subset PHP, Anda dapat membuat dengan php_veloce.py itu berarti Anda dapat menerjemahkan PHP ke subset Python yang dapat digunakan veloce.py yang berarti Anda dapat menerjemahkan PHP ke Javascript. Hanya mengatakan ...

Anda juga dapat melihat perpustakaan tersebut:

Anda juga mungkin tertarik dengan posting blog ini (dan komentar): https://www.rfk.id.au/blog/entry/pypy-js-poc-jit/

amirouche
sumber
Satu-satunya hal yang tetap menggetarkan bagi saya tentang terjemahan bahasa komputer ke bahasa komputer satu-ke-satu dijelaskan di stackoverflow.com/questions/22621164/…
amirouche
Saya mendukung jawaban lain tentang tipe data. Dalam Pythonium saya bahkan tidak berencana untuk mendukung tipe integer & float yang benar dalam mode yang sesuai tanpa asm.js.
amirouche
OK, jadi jika saya memberi Anda paket Python 100K SLOC, dan Anda menjalankannya melalui "penerjemah" Anda, apakah saya mendapatkan program yang berfungsi? Berapa banyak pekerjaan tangan pasca-terjemahan yang diperlukan untuk memperbaikinya? Apa yang Anda katakan di sini adalah, "mengingat parser bagus yang sudah ada untuk Python yang membangun AST, saya dapat membangun penerjemah parsial dalam 6 bulan". Tidak ada yang terkejut. 6 bulan tidak menurut standar kebanyakan orang "agak mudah" (mengutip dari komentar Anda yang lain). Memecahkan masalah yang tersisa akan membutuhkan lebih banyak usaha. Jawaban saya berkata, pada dasarnya "melakukan ini tidaklah mudah", dan "melakukannya secara umum itu sulit".
Ira Baxter
... poin terakhir sebagai tanggapan atas keinginan awal OP: "idealnya saya akan dapat menambahkan bahasa lain dengan (relatif) dengan mudah.", yang secara spesifik dialamatkan oleh jawaban saya.
Ira Baxter
Saya mohon untuk tidak setuju, terutama ketika Anda tahu apa yang Anda lakukan, itu mudah dan yang berikut tidak sulit, itu hanya masalah menyelesaikan sesuatu. Saya tidak yakin di mana Anda berurusan dengan sesuatu yang spesifik untuk pertanyaan itu. Anda mengatakan dalam 4 atau 5 paragraf bahwa perusahaan Anda melakukannya, dan itu sulit. Tetapi sebaliknya Anda menyebarkan FUD tentang subjek tersebut, sementara bersikap baik di luar topik seperti Anda berada di stackoverflow.com/questions/22621164/… . Dalam waktu penuh 6 bulan saya akan menulis penerjemah penuh.
amirouche
0

Anda dapat melihat kompiler Vala , yang menerjemahkan Vala (bahasa mirip C #) ke dalam C.

ptomato
sumber
Itu adalah tujuan desain Vala untuk diterjemahkan ke C dan membuat pengembangan dengan perpustakaan gnome menjadi mudah.
amirouche