Crie uma linguagem de programação JVM

91

Eu criei um compilador em C (usando lex & bison) para uma linguagem de programação de tipo dinâmico que suporta loops, declarações de funções dentro de funções, chamadas recursivas, etc. Eu também criei uma máquina virtual que executa o código intermediário criado pelo compilador.

Agora eu estava pensando em compilar meu próprio código intermediário, compilá-lo em código de bytes java.

Eu vi que a pergunta sobre a criação de uma linguagem JVM já foi feita, mas não acho a resposta muito informativa.

Então, aqui estão as minhas questões:

  1. Eu acho que para criar uma linguagem para JVM uma obrigação é ler o livro de especificações da JVM , que outros livros você pode sugerir (exceto Dragon Book, é claro)? Estou mais preocupado com livros ou tutoriais sobre como criar uma linguagem JVM, não um compilador em geral.
  2. Existem muitas bibliotecas Java para ler, gravar e alterar arquivos .class como jclasslib , bcel , gnu bytecode , etc. Qual você sugere? Além disso, você está ciente das bibliotecas C que fazem o mesmo trabalho?
  3. Eu estava pensando em dar uma olhada em outra linguagem que vise a JVM como Clojure, Jython ou JRuby. Mas todas essas linguagens são de alto nível e complicadas (para criar um compilador para elas). Eu estava procurando por uma linguagem de programação mais simples (não me importo se é desconhecida ou não usada) que tem como alvo a JVM e seu compilador é de código aberto. Alguma ideia?
funcionais
fonte

Respostas:

61

Eu também recomendaria o ASM, mas dê uma olhada no Jasmin , eu o usei (ou: tive que usá-lo) para um projeto de universidade e funciona muito bem, escrevi uma combinação de lexer / parse / analisador / otimizador / gerador para uma linguagem de programação usando java e jasmin, gerando código JVM. Eu carreguei o código aqui , a parte interessante deve ser o próprio código-fonte . Na pasta "bytecode / InsanelyFastByteCodeCreator.java" você encontra um pedaço de código que transforma uma árvore AST no formato de entrada do montador jasmin. É bastante simples.

A linguagem-fonte (que foi transformada em AST por Lexer + Parser + Analyzer) é um subconjunto de Java chamado MiniJava. Faltam alguns recursos "complicados" como Herança, Construtores, métodos estáticos, campos / métodos privados. Nenhum desses recursos é difícil de implementar, mas havia outra tarefa para escrever um back-end X86 (para gerar um montador de máquina), e essas coisas tendem a ficar difíceis se você não tiver um JVM que lida com algumas coisas.

Caso você esteja se perguntando sobre o estranho nome da classe: A tarefa do projeto da universidade era transformar o AST em um gráfico SSA (ou seja, um gráfico representando o código de entrada), otimizar o gráfico e transformá-lo em código de bytes java. Isso foi cerca de 3/4 do trabalho do projeto e o InsanlyFastByteCodeCreator foi apenas um atalho para testar tudo.

Dê uma olhada no livro "Java Virtual Machine" de Jon Meyer e Troy Downing. Este livro faz muitas referências ao Jasmin-Assembler e é muito útil para entender os componentes internos da JVM.

theomega
fonte
Obrigado pela sua resposta, vou dar uma olhada no Jasmin. E também ficaria feliz se você pudesse enviar a fonte para que eu possa dar uma olhada. Sobre o livro que você sugeriu, parece interessante, mas está esgotado e bastante antigo :(.
O livro é de segunda mão muito barato. Encontrei uma cópia por alguns dólares.
data de
Dê uma olhada na minha edição acima, se você tiver alguma dúvida, ficarei feliz em ajudar.
theomega
O link para o "código-fonte em si" está quebrado. Embora eu ache que isso é esperado após 8 anos.
Llew Vallis de
@LlewVallis, se eu interpretar todas as informações corretamente, o código parece estar aqui: github.com/replimoc/compiler .
U880D
14

No semestre passado, participei de um curso de "Construção de compiladores". Nosso projeto foi exatamente o que você deseja fazer.

A linguagem que usei para escrever minha linguagem foi Scala . Ele é executado em uma JVM, mas oferece suporte a muitos recursos avançados que o Java não oferece (ainda é totalmente compatível com uma JVM Java pura).

Para gerar bytecode em java, usei a biblioteca Scala CAFEBABE . Bem documentado e você não precisa se aprofundar nas classes java para entender o que fazer.

Ao lado do livro, acho que você pode encontrar muitas informações visitando os laboratórios que fizemos durante o curso.

Kami
fonte
Parece um ótimo curso. Você se importaria de compartilhar suas notas ou código?
Pedro
1
Não tem problema, vou verificar onde estão meus backups e postar um link aqui para que você possa baixá-lo o mais rápido possível.
Kami
1
Legal, estou procurando um curso prático de compilador que tenha como alvo a JVM com todo o material online para auto-estudo.
data de
5

ASM pode ser uma solução para gerar bytecode. Para começar, verifique os tópicos de geração de elementos do manual .

h3xStream
fonte
4

Eu estava pensando em dar uma olhada em outra linguagem que visa a JVM, como Clojure, Jython ou JRuby. Mas todas essas linguagens são de alto nível e complicadas (para criar um compilador para elas).

Sugestão: você poderia dar uma olhada na Linguagem de Programação Lua , existem implementações JVM dela como LuaJ .

Intérprete de Lua leve , rápido e centrado em Java escrito para J2ME e J2SE, com bibliotecas para pacotes básicos, string, tabela, pacote, matemática, io, os, depuração e corrotina, um compilador , ligações luajava e mecanismo de script plugável JSR-233 ligações.

(Não deve ser confundido com LuaJava, que usa bibliotecas nativas com abordagem JNI.)

Bakkal
fonte
Obrigado. Vou dar uma olhada
3

No fim de semana passado, eu estava me perguntando a mesma coisa para portar minha linguagem de brinquedo para a JVM.

Eu gasto apenas algumas horas pesquisando informações, então considere essas referências com cautela.

  • Padrões de implementação de linguagem . Eu odeio antlr, mas este livro parece muito bom. Se você também não gosta de antlr, há um bom guia de análise de "Técnicas de análise. Um guia prático".

    Aprenda a construir leitores de arquivo de configuração, leitores de dados, geradores de código baseados em modelos, tradutores de fonte para fonte, analisadores de fonte e intérpretes. Você não precisa ter experiência em ciência da computação - o criador do ANTLR, Terence Parr, desmistifica a implementação da linguagem dividindo-a nos padrões de projeto mais comuns. Padrão por padrão, você aprenderá as principais habilidades necessárias para implementar suas próprias linguagens de computador.

    O Capítulo 10 cobre em 30 páginas (para acelerar a IMO) esses tópicos. Mas há outro capítulo em que provavelmente você se interessará.

    • 10 Construindo Intérpretes Bytecode
      • 10.1 Programando intérpretes de bytecode. .
      • 10.2 Definindo uma sintaxe de linguagem Assembly
      • 10.3 Arquitetura da máquina de bytecode. . . . .
      • 10.4 Para onde ir a partir daqui. . . . . . . . . .
      • P.26. Bytecode Assembler. . . . . . . . . . .
      • P.27. Intérprete de Bytecode Baseado em Pilha. . .
      • P.28. Intérprete de Bytecode Baseado em Registro
      http://pragprog.com/titles/tpdsl/language-implementation-patterns
    • A implementação de Lua 5.0 Este é um ótimo artigo sobre máquinas de bytecode baseadas em registradores. Vá e leia, mesmo que seja por isso.

    • Lisp em pequenos pedaços. Este livro ensina como escrever compiladores de 2 schme que compilam para C. Muitas lições podem ser aprendidas com este livro. Eu tenho uma cópia deste livro e é realmente bom para qualquer pessoa interessante é ceceio, mas talvez não para sua xícara de chá.

      Este é um relato abrangente da semântica e da implementação de toda a família de linguagens Lisp, nomeadamente Lisp, Scheme e dialetos relacionados. Ele descreve 11 intérpretes e 2 compiladores ...

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

Verifique o Dalvik7 VM, um VM baseado em registro. O DVM opera em bytecodes que são transformados a partir dos arquivos Java Class compilados por um compilador Java.

Existe uma lista de discussão sobre o assunto, jvm-languages.

Você está planejando enviar o código para qualquer lugar? Eu gostaria de dar uma olhada.

Pedro
fonte
Are you planning to upload the code to anyplace?Não estou orgulhoso desse código :( ... Talvez eu reescrevesse tudo. De qualquer forma, se eu fizer isso, avisarei. Muito obrigado por suas sugestões.
2

Eu recomendaria que você primeiro aprendesse como a montagem da JVM funciona, se ainda não o conhece.

Muitas instruções têm a forma ?name, onde ?é ise a instrução funciona com um tipo inteiro e ase funciona com um tipo de referência.

Basicamente, a JVM é uma máquina de pilha sem registros, portanto, todas as instruções funcionam com dados diretamente na pilha. Você pode enviar / ?push/?popretirar dados com e mover dados entre variáveis ​​locais (localizações de pilha referenciadas por deslocamentos) e o topo da pilha usando ?store/?load. Algumas outras instruções importantes são invoke???e if_???.

Para o curso de compilador da minha universidade , usamos Jasmin para montar os programas. Não sei se esse é o melhor caminho, mas pelo menos é um lugar fácil para começar.

Aqui está uma referência de instrução para uma versão antiga da JVM, que pode conter menos instruções do que uma nova.

Jørgen Fogh
fonte
0

Primeiro, eu recuaria, modificaria meu compilador para gerar Java real em vez de códigos de bytes Java (o que significa criar mais um tradutor do que um compilador) e compilar a saída Java com qualquer ambiente Java que seja conveniente (o que provavelmente geraria um código-objeto melhor do que meu próprio compilador).

Você pode usar a mesma técnica (por exemplo, compilar em C #) para gerar códigos de byte CLI ou compilar em Pascal para gerar código P, etc.

Não está claro por que você está considerando códigos Java em vez de usar sua própria VM, mas se for para desempenho, é claro que você também deve considerar a compilação para o código de máquina real.

joe snyder
fonte
Compilar para a JVM permitirá que o código seja executado de forma mais ampla do que se compilar para código nativo. Além disso, a compilação para bytecode tornará possível para o código fazer algumas coisas que não são possíveis dentro da própria linguagem Java.
supercat
0

Claro, uma vez poderia usar Java para escrever uma nova linguagem. Com a API de reflexão do Java, você pode conseguir muito. Se a velocidade não importa muito, eu daria preferência ao Java em vez de ASM. A programação é mais fácil e menos sujeita a erros em Java (IMHO) . Dê uma olhada na linguagem RPN . É inteiramente escrito em Java.

Kaplan
fonte