Cree un lenguaje de programación JVM

91

He creado un compilador en C (usando lex & bison) para un lenguaje de programación de tipo dinámico que admite bucles, declaraciones de funciones dentro de funciones, llamadas recursivas, etc. También creé una máquina virtual que ejecuta el código intermedio creado por el compilador.

Ahora estaba pensando en lugar de compilar en mi propio código intermedio, compilarlo en código de bytes de Java.

Vi que la pregunta sobre la creación de un lenguaje JVM ya se ha hecho, pero no encuentro la respuesta muy informativa.

Asi que aqui están mis preguntas:

  1. Supongo que para crear un lenguaje para JVM es imprescindible leer el libro de especificaciones de JVM , ¿qué otros libros puedes sugerir (excepto Dragon Book, por supuesto)? Lo que más me preocupa son los libros o tutoriales sobre cómo crear un lenguaje JVM, no un compilador en general.
  2. Hay muchas bibliotecas de Java para leer, escribir y cambiar archivos .class como jclasslib , bcel , gnu bytecode , etc. ¿Cuál sugeriría? Además, ¿conoce las bibliotecas C que hacen el mismo trabajo?
  3. Estaba pensando en echar un vistazo a quizás otro lenguaje que se dirija a la JVM como Clojure, Jython o JRuby. Pero todos estos lenguajes son de muy alto nivel y complicados (para crear un compilador para ellos). Estaba buscando un lenguaje de programación más simple (no me importa si es desconocido o no se usa) que se dirija a la JVM y su compilador sea de código abierto. ¿Algunas ideas?
funcional
fuente

Respuestas:

61

También recomendaría ASM, pero eche un vistazo a Jasmin , lo usé (o: tuve que usarlo) para un proyecto universitario, y funciona bastante bien, escribí una combinación de lexer / parse / analizador / optimizador / generador para un lenguaje de programación que utiliza java y jasmin, generando código JVM. Subí el código aquí , la parte interesante debería ser el código fuente en sí . En la carpeta "bytecode / InsanelyFastByteCodeCreator.java" encontrará un fragmento de código que transforma un árbol AST en el formato de entrada del ensamblador jasmin. Es bastante sencillo.

El lenguaje fuente (que Lexer + Parser + Analyzer transformó en AST) es un subconjunto de Java llamado MiniJava. Carece de algunas características "complicadas" como herencia, constructores, métodos estáticos, campos / métodos privados. Ninguna de esas características es difícil de implementar, pero había otra tarea para escribir un backend X86 (para generar un ensamblador de máquina), y esas cosas tienden a complicarse si no tiene una JVM que maneje algunas cosas.

En caso de que se pregunte por el extraño nombre de la clase: la tarea del proyecto universitario era transformar el AST en un gráfico SSA (por lo que un gráfico que representa el código de entrada), luego optimizar el gráfico y luego convertir el gráfico en código de bytes java. Eso fue aproximadamente 3/4 del trabajo del proyecto y InsanlyFastByteCodeCreator fue solo un atajo para probar todo.

Eche un vistazo al libro "Java Virtual Machine" de Jon Meyer y Troy Downing. Este libro hace una gran referencia al ensamblador de Jasmin, es bastante útil para comprender los aspectos internos de la JVM.

theomega
fuente
Gracias por tu respuesta, echaré un vistazo a Jasmin. Y también me alegraría si pudieras subir la fuente para que pueda echar un vistazo. Acerca del libro que sugirió, parece interesante pero está agotado y es bastante antiguo :(.
Sin embargo, el libro es de segunda mano muy barato. Encontré una copia por unos dólares.
namin
Echa un vistazo a mi edición anterior, si tienes alguna pregunta, estaré encantado de ayudarte.
theomega
El enlace al "código fuente en sí mismo" está roto. Aunque supongo que es de esperar después de 8 años.
Llew Vallis
@LlewVallis, si interpreto toda la información correctamente, el código parece estar aquí: github.com/replimoc/compiler .
U880D
14

El semestre pasado asistí a un curso de "Construcción de compiladores". Nuestro proyecto fue exactamente lo que quieres hacer.

El idioma que usé para escribir mi idioma fue Scala . Se ejecuta en una JVM pero admite muchas funciones avanzadas que Java no (sigue siendo totalmente compatible con una JVM pura de Java).

Para generar el código de bytes de Java, he usado la biblioteca Scala CAFEBABE . Bien documentado y no es necesario profundizar en las clases de Java para comprender qué hacer.

Además del libro, creo que puede encontrar mucha información revisando los laboratorios que hemos hecho durante el curso.

Kami
fuente
Este suena como un gran curso. ¿Le importaría compartir sus notas o código?
Pedro
1
No hay problema, verificaré dónde están mis copias de seguridad y publicaré un enlace aquí para que pueda descargarlo lo antes posible.
Kami
1
Genial, he estado buscando un curso de compilador práctico que se dirija a la JVM con todo el material en línea para el autoaprendizaje.
namin
5

ASM puede ser una solución para generar códigos de bytes. Para comenzar, consulte los temas sobre la generación de elementos del manual .

h3xStream
fuente
4

Estaba pensando en echar un vistazo a quizás otro lenguaje que se dirija a la JVM como Clojure, Jython o JRuby. Pero todos estos lenguajes son de muy alto nivel y complicados (para crear un compilador para ellos).

Sugerencia: podría echar un vistazo al lenguaje de programación Lua , hay implementaciones de JVM como LuaJ .

Intérprete Lua ligero , rápido y centrado en Java escrito para J2ME y J2SE, con bibliotecas para paquetes básicos, de cadenas, tablas, paquetes, matemáticas, io, os, depuración y corrutina, un compilador , enlaces luajava y motor de scripting JSR-233 conectable fijaciones.

(No confundir con LuaJava que usa bibliotecas nativas con enfoque JNI).

bakkal
fuente
Gracias. Voy a echar un vistazo
3

El fin de semana pasado, me hice la misma pregunta para trasladar mi lenguaje de juguetes a la JVM.

Solo paso unas pocas horas buscando información, así que tome estas referencias con un grano de sal.

  • Patrones de implementación del lenguaje . Odio las antlr pero este libro se ve muy bien. Si tampoco te gusta antlr, hay una gran ventaja en analizar "Técnicas de análisis. Una guía práctica".

    Aprenda a crear lectores de archivos de configuración, lectores de datos, generadores de código basados ​​en modelos, traductores de fuente a fuente, analizadores de fuente e intérpretes. No es necesario tener experiencia en informática: el creador de ANTLR, Terence Parr, desmitifica la implementación del lenguaje dividiéndolo en los patrones de diseño más comunes. Patrón a patrón, aprenderá las habilidades clave que necesita para implementar sus propios lenguajes informáticos.

    El capítulo 10 cubre en 30 páginas (a la OMI rápida) estos temas. Pero hay otro capítulo que probablemente te interese.

    • 10 intérpretes de código de bytes de construcción
      • 10.1 Programación de intérpretes de códigos de bytes. .
      • 10.2 Definición de una sintaxis en lenguaje ensamblador
      • 10.3 Arquitectura de la máquina de códigos de bytes. . . . .
      • 10.4 Adónde ir desde aquí. . . . . . . . . .
      • P.26. Ensamblador de código de bytes. . . . . . . . . . .
      • P.27. Intérprete de código de bytes basado en pila. . .
      • P.28. Intérprete de código de bytes basado en registros
      http://pragprog.com/titles/tpdsl/language-implementation-patterns
    • La implementación de Lua 5.0 Este es un gran artículo sobre máquinas de códigos de bytes basadas en registros. Ve y léelo incluso por el simple hecho de hacerlo.

    • Lisp en pedazos pequeños. Este libro enseña cómo escribir comparadores de 2 schme que compilen en C. Se pueden aprender muchas lecciones de este libro. Soy dueño de una copia de este libro y es realmente bueno para cualquier persona interesante que cecea, pero tal vez no sea su taza de té.

      Esta es una descripción completa de la semántica y la implementación de toda la familia de lenguajes Lisp, a saber, Lisp, Scheme y dialectos relacionados. Describe 11 intérpretes y 2 compiladores ...

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

Compruebe la máquina virtual Dalvik7, una máquina virtual basada en registros. El DVM funciona con códigos de bytes que se transforman a partir de los archivos Java Class compilados por un compilador Java.

Hay una lista de correo sobre el tema, jvm-languages.

¿Está planeando cargar el código en algún lugar? Me gustaría echarle un vistazo.

Pedro
fuente
Are you planning to upload the code to anyplace?No estoy orgulloso de ese código :( ... Quizás lo reescribiera todo. De todos modos, si lo hago, se lo haré saber. Muchas gracias por sus sugerencias.
2

Le recomendaría que primero aprenda cómo funciona el ensamblaje de JVM, si aún no lo sabe.

Muchas instrucciones tienen la forma ?name, donde ?es isi la instrucción funciona con un tipo entero ya si funciona con un tipo de referencia.

Básicamente, JVM es una máquina de pila sin registros, por lo que todas las instrucciones funcionan con datos directamente en la pila. Puede enviar / extraer datos con?push/?pop y mover datos entre las variables locales (ubicaciones de pila referenciadas por compensaciones) y la parte superior de la pila usando ?store/?load. Algunas otras instrucciones importantes son invoke???y if_???.

por el curso de compilación de mi universidad usamos Jasmin para ensamblar los programas. No sé si esta es la mejor manera, pero al menos es un lugar fácil para comenzar.

Aquí hay una referencia de instrucciones para una versión anterior de la JVM, que puede contener menos instrucciones que una nueva.

Jørgen Fogh
fuente
0

Primero retrocedería, modificaría mi compilador para generar Java real en lugar de códigos de bytes de Java (lo que significa crear más un traductor que un compilador) y compilaría la salida de Java con cualquier entorno de Java que sea conveniente (lo que probablemente generaría un mejor código de objeto que mi propio compilador).

Puede usar la misma técnica (por ejemplo, compilar en C #) para generar códigos de bytes CLI, o compilar en Pascal para generar código P, etc.

No está claro por qué está considerando los códigos Java en lugar de usar su propia máquina virtual, pero si es por rendimiento, por supuesto, también debería considerar la compilación en código de máquina real.

joe snyder
fuente
La compilación para la JVM permitirá que el código de uno se ejecute más ampliamente que si se compila en código nativo. Además, la compilación en código de bytes hará posible que el código haga algunas cosas que no son posibles dentro del propio lenguaje Java.
supercat
0

Por supuesto, una vez podría usar Java para escribir un nuevo lenguaje. Con la API de reflexión de Java, puede obtener un llot. Si la velocidad no importa demasiado, le daría preferencia a Java en lugar de ASM. La programación es más fácil y menos propensa a errores en Java (en mi humilde opinión) . Eche un vistazo al séptimo idioma de RPN . Está completamente escrito en Java.

Kaplan
fuente