Misalkan X adalah bahasa input, Z adalah bahasa output, maka f adalah kompiler, yang ditulis dalam bahasa Y.
f = X -> Z
Karena f hanya sebuah program, saya pikir Y dapat bahasa apa pun, bukan? Jadi kita dapat memiliki kompiler f1, f2, masing-masing ditulis dalam Y1, Y2.
f1 = f Y1
f2 = f Y2
g = Z -> M
h = g . f # We get a compiler X -> M
Ambil cpython compiler misalnya, X adalah Python, Z adalah kode VM Python, Y adalah C.
cpython = Python -> PythonVMCode C
interpreter = PythonVMCode -> Nothing
interpreter2 = PythonVMCode -> MachineCode
Sumber-sumber Python dikompilasi ke kode VM Python, file .pyc, kemudian ditafsirkan oleh penerjemah. Sepertinya mungkin ada kompiler yang dapat langsung melakukan Python -> MachineCode, meskipun jauh lebih sulit untuk diimplementasikan:
hardpython = interpreter2 . cpython
Kita juga dapat menulis kompiler lain melakukan pekerjaan Python -> PythonVMCode, dalam bahasa lain, katakan Python itu sendiri.
mypython = Python -> PythonVMCode Python
mypython2 = Python -> PythonVMCode Ruby
Sekarang, inilah contoh rumit PyPy. Saya hanya pemula di PyPy, koreksi saya jika saya salah:
PyPy doc http://doc.pypy.org/en/latest/architecture.html#pypy-the-translation-framework
Tujuan kami adalah untuk memberikan solusi yang mungkin untuk masalah pelaksana bahasa: harus menulis penerjemah l * o * p untuk bahasa yang dinamis dan platform p dengan o keputusan desain yang penting.
Kita dapat berpikir l adalah X, p adalah Y. Ada sebuah program yang menerjemahkan semua program RPython ke C:
rpython_compiler = RPython -> C Python
pypy = Python -> Nothing RPython
translate = compile the program pypy written in RPython using rpython_compiler
py2rpy = Python -> RPython Python
py2c = Python -> C Python
py2c = rpython_compiler . py2rpy
Program RPython sama seperti instruksi VM, rpython_compiler adalah VM.
q1. pypy adalah interpreter, program RPython yang dapat menginterpretasikan kode Python, tidak ada bahasa output, jadi kita tidak bisa menganggapnya sebagai kompiler, kan?
Ditambahkan:
- Saya baru menemukan bahwa walaupun setelah menerjemahkan, pypy masih menjadi penerjemah, hanya saja kali ini ditulis dalam C.
- Jika kita melihat jauh ke dalam pypy interpreter, saya percaya pasti ada semacam kompiler, yang mengkompilasi sumber Python ke beberapa AST, kemudian jalankan
seperti ini:
compiler_inside_pypy = Python -> AST_or_so
q2. Bisakah kompiler py2rpy ada, mengubah semua program Python menjadi RPython? Dalam bahasa mana itu ditulis tidak relevan. Jika ya, kami mendapatkan py2c kompiler lain. Apa perbedaan antara pypy dan py2rpy di alam? Apakah py2rpy jauh lebih sulit untuk ditulis daripada pypy?
q3. Apakah ada aturan umum atau teori yang tersedia tentang ini?
Lebih banyak kompiler:
gcc_c = C -> asm? C # not sure, gimple or rtl?
g++ = C++ -> asm? C
clang = C -> LLVM_IR C++
jython = Python -> JVMCode java
ironpython = Python -> CLI C#
q4. Diberikan f = X -> Z, sebuah program P ditulis dalam X. Ketika kita ingin mempercepat P, apa yang bisa kita lakukan? Cara berbisa:
tulis ulang P dalam algoritma yang lebih efisien
tulis ulang f untuk menghasilkan Z yang lebih baik
jika Z ditafsirkan, tulislah juru bahasa Z yang lebih baik (PyPy ada di sini?)
mempercepat program yang ditulis dalam Z secara rekursif
dapatkan mesin yang lebih baik
ps. Pertanyaan ini bukan tentang hal-hal teknologi tentang cara menulis kompiler, tetapi kelayakan dan kompleksitas penulisan kompiler jenis tertentu.
Jawaban:
PyPy mirip dengan CPython, keduanya memiliki kompiler + juru bahasa. CPython memiliki kompiler yang ditulis dalam C yang mengkompilasi bytecode Python ke Python VM kemudian mengeksekusi bytecode dalam sebuah interpreter yang ditulis dalam C. PyPy memiliki kompiler yang ditulis dalam RPython yang mengkompilasi bytecode Python ke Python VM, kemudian mengeksekusinya dalam PyPy Interpreter yang ditulis dalam RPython.
Bisakah sebuah compiler py2rpy ada? Secara teoritis ya. Turing menjamin kelengkapan begitu.
Salah satu metode untuk membangun
py2rpy
adalah dengan hanya memasukkan kode sumber dari juru bahasa Python yang ditulis dalam RPython dalam kode sumber yang dihasilkan. Contoh kompiler py2rpy, ditulis dalam Bash:sekarang setiap kali Anda perlu menerjemahkan kode Python ke kode RPython, Anda memanggil skrip ini, yang menghasilkan - dalam $ outputdir - RPython
main.rpy
, kode sumber Penerjemah Python RPython, dan prog.py. biner gumpalan biner Dan kemudian Anda dapat menjalankan skrip RPython yang dihasilkan dengan memanggilrpython main.rpy
.(catatan: karena saya tidak terbiasa dengan proyek rpython, sintaks untuk memanggil interpreter rpython, kemampuan untuk mengimpor pypy dan melakukan pypy.execfile, dan ekstensi .rpy murni dibuat, tetapi saya pikir Anda mengerti maksudnya)
Ya, bahasa Turing Lengkap apa pun secara teoritis dapat diterjemahkan ke bahasa Turing Lengkap apa pun. Beberapa bahasa mungkin jauh lebih sulit diterjemahkan daripada bahasa lain, tetapi jika pertanyaannya adalah "apakah mungkin?", Jawabannya adalah "ya"
Tidak ada pertanyaan di sini.
sumber
Does pypy have to be written in RPython in your compiler?
Tidak, tidak perlu ditulis dalam RPython, tetapi RPython harus dapat memberi tahu "penerjemah tambahan" / "runtime" untuk menjalankan kode Python. Ya memang benar ini bukan "kompiler" dalam arti praktis, tetapi ini adalah bukti konstruktif bahwa mungkin untuk menulisPython -> RPython
.Is pypy still using the Python VM?
Saya percaya pypy tidak menggunakan CPython sama sekali (saya bisa saja salah), malahan PyPy memiliki implementasi sendiri dari "Python VM" yang ditulis dalam RPython.Python -> RPython
kompiler yang lebih praktis .Untuk menjawab q2 saja, ada buku kompiler oleh William McKeeman di mana teori kompiler untuk bahasa X ditulis dalam bahasa Y yang menghasilkan bahasa keluaran Z dieksplorasi melalui sistem diagram-T. Diterbitkan pada tahun 1970-an, judul tidak diserahkan, maaf
sumber
q1. Secara umum, juru bahasa bukan kompiler. Perbedaan utama antara kompiler dan interpreter adalah bahwa interpreter mulai baru, dengan kode sumber dalam bahasa sumber, setiap saat. Jika pypy Anda bukan pyAST, atau pyP-code, dan kemudian Anda memiliki juru bahasa AST atau P-code, maka Anda bisa memanggil pyAST kompiler. Ini adalah cara kerja kompiler UCC PASCAL lama bekerja (juga beberapa yang lain): mereka dikompilasi ke beberapa kode-P, yang ditafsirkan ketika program dijalankan. (Bahkan. NET menyediakan sesuatu seperti ini, ketika kekompakan kode objek yang dihasilkan jauh lebih penting daripada kecepatan.)
q2. Ya tentu saja. Lihat UCSD PASCAL (dan banyak lainnya).
q3. Gali teks-teks klasik dalam ilmu komputer. Baca di Concurrent PASCAL, oleh Per Brinch-Hansen (jika ingatanku). Banyak yang telah ditulis tentang kompiler dan pembuatan kode. Membuat pseudocode yang tidak tergantung pada mesin biasanya jauh lebih mudah daripada menghasilkan kode mesin: pseudocode biasanya bebas dari keanehan yang dikandung oleh mesin nyata.
q4. Jika Anda ingin objek yang Anda buat berjalan lebih cepat, Anda membuat kompiler lebih pintar, untuk melakukan optimasi yang lebih baik. Jika objek Anda ditafsirkan, Anda mempertimbangkan untuk mendorong operasi yang lebih kompleks ke dalam konstruksi pseudoin primitif (CISC vs RISC adalah analoginya), maka Anda melakukan yang terbaik untuk mengoptimalkan frack out dari juru bahasa Anda.
Jika Anda ingin kompiler Anda berjalan lebih cepat, Anda harus melihat SEMUANYA, termasuk memikirkan kembali kode sumber Anda. Setelah memuat kompiler itu sendiri, bagian kompilasi yang paling memakan waktu adalah SELALU membaca kode sumber ke dalam kompiler. (Sebagai contoh, pertimbangkan C ++. Semua hal lainnya relatif sama, sebuah kompiler yang harus menghitung 9.000 (atau mungkin 50.000) baris #include file untuk mengkompilasi program "Hello, World" yang sederhana tidak akan pernah secepat satu yang hanya perlu membaca empat atau lima baris.)
Saya tidak ingat di mana saya membacanya, tetapi kompiler Oberon asli di ETH-Zurich memiliki mekanisme tabel simbol yang sangat canggih, cukup elegan. Benchmark Wirth untuk kinerja kompiler adalah waktu yang dibutuhkan bagi kompiler untuk mengkompilasi dirinya sendiri. Suatu pagi, dia masuk, menarik keluar tabel simbol ultra-pohon simbol multiply-linked yang cantik, dan menggantinya dengan array linier sederhana dan pencarian linear lurus. Mahasiswa pascasarjana dalam kelompoknya TERSAMPIR. Setelah perubahan, kompiler menjadi lebih cepat, karena modul-modul yang dikompilasi selalu cukup kecil sehingga monster elegan mengenakan overhead total lebih banyak daripada array linier dan pencarian linear.
sumber
Pertanyaan Anda sebagaimana dinyatakan membuat saya percaya bahwa apa yang benar-benar Anda inginkan / butuhkan adalah penjelasan tentang apa itu kompiler, apa penerjemah itu dan perbedaan di antara keduanya.
Kompiler memetakan program yang ditulis dalam bahasa X ke program yang secara fungsional setara ditulis dalam bahasa Y. Sebagai contoh, kompiler dari Pascal ke C mungkin mengkompilasi
untuk
Kebanyakan kompiler mengkompilasi 'ke bawah', sehingga mereka mengkompilasi bahasa pemrograman tingkat tinggi ke dalam bahasa tingkat lebih rendah, bahasa tingkat bawah yang paling tinggi adalah kode mesin.
Sebagian besar kompiler mengkompilasi langsung ke kode mesin, tetapi beberapa (terutama bahasa Java dan .NET) mengkompilasi ke 'bytecode' ( Java bytecode dan CIL ). Pikirkan bytecode sebagai kode mesin untuk komputer hipotetis. Bytecode ini kemudian diartikan atau JITted ketika dijalankan (lebih lanjut tentang itu nanti).
Seorang penerjemah mengeksekusi suatu program yang ditulis dalam beberapa bahasa Z. Seorang penerjemah membaca suatu program sedikit demi sedikit, mengeksekusinya seiring berjalannya waktu. Contohnya:
Bayangkan penerjemah melihat baris program itu untuk baris, memeriksa baris, mengeksekusi apa yang dilakukannya, melihat baris berikutnya dan seterusnya.
Contoh terbaik juru bahasa adalah CPU komputer Anda. Ini mengartikan kode mesin dan menjalankannya. Cara kerja CPU ditentukan oleh bagaimana ia dibangun secara fisik. Cara kerja program juru bahasa ditentukan oleh seperti apa kode tersebut. CPU karenanya menginterpretasikan dan mengeksekusi program interpreter, yang pada gilirannya menginterpretasikan dan mengeksekusi inputnya. Anda dapat menghubungkan penerjemah dengan cara ini.
JITter adalah kompiler Just-In-Time. JITter adalah kompiler. Satu-satunya perbedaan adalah waktu dieksekusi: sebagian besar program ditulis, dikompilasi, dikirim ke penggunanya dan kemudian dieksekusi, tetapi bytecode Java dan CIL dikirim ke penggunanya terlebih dahulu, dan sebelum mereka dieksekusi mereka dikompilasi ke mesin kode pengguna mereka.
C # -> (kompilasi) -> CIL -> dikirim ke pelanggan -> (kompilasi sesaat sebelum eksekusi) -> kode mesin -> (jalankan)
Hal terakhir yang ingin Anda ketahui adalah kelengkapan Turing ( tautan ). Bahasa pemrograman adalah Turing Lengkap jika dapat menghitung semua yang bisa ' mesin Turing ', yaitu setidaknya sama kuatnya dengan mesin Turing. The Gereja-Turing tesis menyatakan bahwa mesin Turing setidaknya sekuat setiap mesin yang kita dapat pernah membangun. Oleh karena itu, setiap bahasa lengkap Turing sama kuatnya dengan mesin Turing, dan karena itu semua bahasa lengkap Turing sama kuatnya.
Dengan kata lain, selama bahasa pemrograman Anda Turing lengkap (hampir semuanya), tidak masalah bahasa yang Anda pilih, karena mereka semua dapat menghitung hal yang sama. Ini juga berarti bahwa sangat tidak relevan bahasa pemrograman mana yang Anda pilih untuk menulis kompiler atau juru bahasa Anda. Last but not least, itu berarti Anda selalu dapat menulis kompiler dari bahasa X ke Y jika X dan Y keduanya Turing lengkap.
Perhatikan bahwa menjadi Turing selesai tidak mengatakan apa-apa tentang apakah bahasa Anda efisien, atau tentang semua detail implementasi CPU Anda dan perangkat keras lain, atau kualitas kompiler yang Anda gunakan untuk bahasa tersebut. Juga, sistem operasi Anda mungkin memutuskan program Anda tidak memiliki hak untuk membuka file, tetapi itu tidak menghalangi kemampuan Anda untuk menghitung apa pun - saya sengaja tidak mendefinisikan komputasi, karena itu akan membutuhkan dinding teks yang lain.
sumber