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.egg
dengan 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/