Bagaimana pendekatan membuat bahasa pemrograman JVM?

93

Saya telah membuat kompiler dalam C (menggunakan Lex & Bison) untuk bahasa pemrograman tipe dinamis yang mendukung loop, deklarasi fungsi di dalam fungsi, panggilan rekursif, dll. Saya juga membuat mesin virtual yang menjalankan kode perantara yang dibuat oleh kompilator.

Saya berpikir untuk mengkompilasinya ke bytecode Java daripada kode perantara saya sendiri.

Saya melihat bahwa pertanyaan tentang membuat bahasa JVM telah diajukan , tetapi saya tidak menemukan jawabannya sangat informatif.

Jadi inilah pertanyaanku:

  1. Saya kira untuk membuat bahasa untuk JVM yang harus adalah membaca buku spesifikasi JVM , buku lain apa yang bisa Anda sarankan (kecuali Buku Naga tentunya)? Saya sangat memperhatikan buku atau tutorial tentang cara membuat bahasa JVM, bukan kompiler pada umumnya.
  2. Ada banyak library Java untuk membaca, menulis, dan mengubah .classfile seperti jclasslib , bcel , gnu bytecode , dll. Mana yang akan Anda sarankan? Juga, apakah Anda mengetahui pustaka C yang melakukan pekerjaan yang sama?
  3. Saya berpikir untuk melihat mungkin bahasa lain yang menargetkan JVM seperti Clojure, Jython atau JRuby. Tetapi semua bahasa ini memiliki level yang sangat tinggi dan rumit (untuk membuat kompiler untuk mereka). Saya mencari bahasa pemrograman yang lebih sederhana (saya tidak keberatan jika tidak diketahui atau tidak digunakan) yang menargetkan JVM dan kompilernya adalah open source. Ada ide?
fungsional
sumber

Jawaban:

63

Saya juga akan merekomendasikan ASM, tetapi lihat Jasmin , saya menggunakannya (atau, lebih tepatnya, harus menggunakannya) untuk proyek universitas, dan itu bekerja dengan cukup baik. Saya menulis kombinasi lexer-parser-analyzer-optimizer-generator untuk bahasa pemrograman menggunakan Java dan Jasmin, jadi itu menghasilkan Kode JVM. Saya mengunggah kode di sini ; bagian yang menarik adalah kode sumber itu sendiri . Di folder tersebut bytecode/InsanelyFastByteCodeCreator.java, Anda akan menemukan potongan kode yang mengubah Pohon AST menjadi format input assembler Jasmin. Ini cukup mudah.

Bahasa sumber (yang diubah menjadi AST oleh lexer-parser-analyzer) adalah bagian dari Java yang disebut MiniJava. Ini tidak memiliki beberapa fitur "rumit" seperti pewarisan, konstruktor, metode statis, bidang pribadi, dan metode. Tak satu pun dari fitur tersebut yang sulit diimplementasikan, tetapi ada tugas lain untuk menulis backend x86 (jadi untuk menghasilkan assembler mesin), dan hal-hal tersebut cenderung menjadi sulit jika Anda tidak memiliki JVM yang menangani beberapa hal tersebut.

Jika Anda bertanya-tanya tentang nama kelas yang aneh: Tugas proyek universitas adalah mengubah AST menjadi Grafik SSA (mewakili kode input), mengoptimalkan grafik, dan kemudian mengubahnya menjadi bytecode Java. Itu adalah sekitar ¾ dari pekerjaan proyek dan InsanlyFastByteCodeCreatoritu hanya jalan pintas untuk menguji semuanya.

Lihat buku "Java Virtual Machine" dari Jon Meyer dan Troy Downing. Buku ini sangat merujuk pada Jasmin Assembler; itu cukup membantu untuk memahami internal JVM.

theomega
sumber
Terima kasih atas jawaban Anda, saya akan melihat Jasmin. Dan juga saya akan senang jika Anda dapat mengunggah sumbernya sehingga saya dapat melihatnya. Tentang buku yang Anda sarankan, sepertinya menarik tetapi sudah tidak dicetak dan cukup tua :(.
Buku itu sangat murah bekas. Saya menemukan salinannya seharga beberapa dolar.
namin
Silahkan lihat hasil edit saya di atas, jika ada pertanyaan, saya akan dengan senang hati membantu.
theomega
Tautan ke "kode sumber itu sendiri" rusak. Meskipun saya rasa itu diharapkan setelah 8 tahun.
Llew Vallis
@LlewVallis, jika saya mengartikan semua informasi dengan benar, kodenya sepertinya ada di sini: github.com/replimoc/compiler .
U880D
15

Semester lalu saya telah mengikuti kursus "Konstruksi Penyusun". Proyek kami persis seperti yang ingin Anda lakukan.

Bahasa yang saya gunakan untuk menulis bahasa saya adalah Scala . Ini berjalan pada JVM tetapi mendukung banyak fitur lanjutan yang tidak dimiliki Java (masih sepenuhnya kompatibel dengan Java JVM murni).

Untuk mengeluarkan java bytecode saya telah menggunakan library Scala CAFEBABE . Didokumentasikan dengan baik dan Anda tidak perlu masuk jauh ke dalam kelas java untuk memahami apa yang harus dilakukan.

Selain buku, saya rasa Anda bisa menemukan banyak info dengan menelusuri lab yang telah kami lakukan selama kursus.

Kami
sumber
Ini terdengar seperti kursus yang bagus. Maukah Anda membagikan catatan atau kode Anda?
Pedro
1
Tidak masalah, saya akan memeriksa di mana cadangan saya dan memposting tautan di sini sehingga Anda dapat mengunduhnya secepatnya.
Kami
1
Baik, saya telah mencari kursus kompilator praktis yang menargetkan JVM dengan semua materi online untuk belajar mandiri.
namin
5

ASM dapat menjadi solusi untuk menghasilkan bytecode. Untuk memulai, periksa topik tentang menghasilkan elemen dari manual .

h3xStream
sumber
4

Saya berpikir untuk melihat mungkin bahasa lain yang menargetkan JVM seperti Clojure, Jython atau JRuby. Tetapi semua bahasa ini memiliki level yang sangat tinggi dan rumit (untuk membuat kompiler untuk mereka).

Saran: Bisa lihat di Lua Programming Language , ada implementasi JVM nya seperti LuaJ .

Interpreter Lua yang ringan , cepat, berpusat pada Java yang ditulis untuk J2ME dan J2SE, dengan pustaka untuk paket dasar, string, tabel, paket, matematika, io, os, debug dan coroutine, kompiler , pengikatan luajava, dan mesin skrip yang dapat dicolokkan JSR-233 binding.

(Jangan bingung dengan LuaJava yang menggunakan lib asli dengan pendekatan JNI.)

bakkal
sumber
Terima kasih. Saya akan melihat
4

Akhir pekan lalu, saya bertanya pada diri sendiri pertanyaan yang sama untuk memindahkan bahasa mainan saya ke JVM.

Saya hanya menghabiskan beberapa jam mencari informasi, jadi ambillah referensi ini dengan sebutir garam.

  • Pola Implementasi Bahasa . Saya benci antlr tetapi buku ini terlihat sangat bagus. Jika Anda juga tidak suka antlr, ada baiknya menguraikan "Teknik Parsing. Panduan Praktis."

    Belajar membangun pembaca file konfigurasi, pembaca data, pembuat kode berdasarkan model, penerjemah sumber-ke-sumber, penganalisis sumber, dan juru bahasa. Anda tidak memerlukan latar belakang dalam ilmu komputer — pencipta ANTLR Terence Parr mendemistifikasi penerapan bahasa dengan memecahnya menjadi pola desain yang paling umum. Pola demi pola, Anda akan mempelajari keterampilan utama yang Anda perlukan untuk menerapkan bahasa komputer Anda sendiri.

    Bab 10 mencakup 30 halaman (untuk IMO cepat) topik ini. Namun ada chapter lain yang mungkin menarik bagi Anda.

    • 10 Membangun Penerjemah Bytecode
      • 10.1 Pemrograman Penerjemah Bytecode. .
      • 10.2 Mendefinisikan Sintaks Bahasa Assembly
      • 10.3 Arsitektur Mesin Bytecode. . . . .
      • 10.4 Tujuan dari Sini. . . . . . . . . .
      • Hlm.26. Perakit Bytecode. . . . . . . . . . .
      • Hlm.27. Penerjemah Bytecode Berbasis Stack. . .
      • Hlm.28. Interpreter Bytecode Berbasis Register
      http://pragprog.com/titles/tpdsl/language-implementation-patterns
    • Implementasi Lua 5.0 Ini adalah makalah yang bagus tentang mesin bytecode berbasis register. Bacalah bahkan demi itu.

    • Lisp dalam Potongan Kecil. Buku ini mengajarkan bagaimana menulis 2 schme compailers yang mengkompilasi ke C. Begitu banyak pelajaran yang bisa dipetik dari buku ini. Saya memiliki salinan dari buku ini dan sangat bagus untuk siapa pun yang menarik adalah cadel, tapi mungkin bukan secangkir teh Anda.

      Ini adalah akun komprehensif dari semantik dan implementasi dari seluruh keluarga bahasa Lisp, yaitu Lisp, Skema dan dialek terkait. Ini menjelaskan 11 interpreter dan 2 compiler ...

    http://www.amazon.com/Lisp-Small-Pieces-Christian-Queinnec/dp/0521562473

Periksa VM Dalvik7, VM berbasis register. DVM beroperasi pada bytecode yang diubah dari file Java Class yang dikompilasi oleh compiler Java.

Ada milis tentang topik, bahasa-jvm.

Apakah Anda berencana untuk mengunggah kode ke sembarang tempat? Saya ingin melihatnya.

Pedro
sumber
Are you planning to upload the code to anyplace?Saya tidak bangga dengan kode itu :( ... Saya mungkin akan menulis ulang semuanya. Bagaimanapun, jika saya melakukannya, saya akan memberi tahu Anda. Terima kasih banyak atas saran Anda.
2

Saya akan merekomendasikan agar Anda terlebih dahulu mempelajari cara kerja perakitan JVM, jika Anda belum mengetahuinya.

Banyak petunjuk memiliki bentuk ?name, di mana ?adalah ijika instruksi bekerja pada dengan tipe integer dan ajika bekerja dengan tipe referensi.

Pada dasarnya, JVM adalah mesin stack tanpa register, jadi semua instruksi bekerja dengan data secara langsung di stack. Anda dapat mendorong / memunculkan data dengan ?push/?popdan memindahkan data antara variabel lokal (lokasi tumpukan yang direferensikan oleh offset) dan bagian atas tumpukan menggunakan ?store/?load. Beberapa instruksi penting lainnya adalah invoke???dan if_???.

Untuk kursus kompiler universitas saya, kami menggunakan Jasmin untuk merakit program. Saya tidak tahu apakah ini cara terbaik, tetapi setidaknya ini adalah tempat yang mudah untuk memulai.

Berikut adalah referensi instruksi untuk versi lama JVM, yang mungkin berisi instruksi lebih sedikit daripada yang baru.

Jørgen Fogh
sumber
0

Pertama saya akan mundur, memodifikasi kompiler saya untuk menghasilkan Java yang sebenarnya daripada kode byte Java (yang berarti membuat lebih banyak penerjemah daripada kompiler), dan mengkompilasi output Java dengan lingkungan Java apa pun yang nyaman (yang mungkin akan menghasilkan kode objek yang lebih baik dari kompiler saya sendiri).

Anda dapat menggunakan teknik yang sama (misalnya, mengkompilasi ke C #) untuk menghasilkan kode byte CLI, atau mengkompilasi ke Pascal untuk menghasilkan kode-P, dll.

Tidak jelas mengapa Anda mempertimbangkan kode Java daripada menggunakan VM Anda sendiri, tetapi jika itu untuk kinerja maka tentu saja Anda juga harus mempertimbangkan untuk mengkompilasi ke kode mesin yang sebenarnya.

joe snyder
sumber
Kompilasi untuk JVM akan memungkinkan kode seseorang dijalankan lebih luas daripada jika seseorang mengkompilasi ke kode asli. Selanjutnya, mengompilasi ke bytecode akan memungkinkan kode melakukan beberapa hal yang tidak mungkin dilakukan dalam bahasa Java itu sendiri.
supercat
0

Tentu sekali bisa menggunakan Java untuk menulis bahasa baru. Dengan API refleksi Java Anda bisa mendapatkan llot. Jika kecepatan tidak terlalu penting, saya akan memberikan Java preferensi daripada ASM. Pemrograman lebih mudah dan tidak terlalu rawan kesalahan di Java (IMHO) . Lihatlah bahasa RPN ke-7 . Itu seluruhnya ditulis di Jawa.

Kaplan
sumber