Converter um intérprete em um compilador?

8

Primeiro, sei que essa é uma pergunta feita por muitos outros programadores antes de mim. Mas não consegui encontrar nenhum recurso utilizável que pudesse me ajudar.

Bem, estou criando uma linguagem de programação chamada "Light". A sintaxe é comparável ao python, mas tem um conceito estrito de orientação a objetos.

Eu fiz um intérprete (em C ++) para essa linguagem ainda, meu problema é como transformar isso em um executável. (Ou simplesmente: como faço para criar um compilador?)

Agradecimentos para sua atenção

PS: Encontrei alguns links para um tutorial muito antigo, mas está em Pascal ...

EDIT: Bem, bem. Agora eu encontrei um tutorial adequado para C ++. Sobre o projeto: Houve algumas mudanças. Agora, o idioma é chamado "Q". (kju Dot).

LaVolpe
fonte
aprenda primeiro o idioma de destino e veja como você traduziria os blocos de código básico do seu idioma para o outro idioma
catraca anormal
1
Você está "meramente" tentando escrever um compilador (com o conhecimento prévio da implementação de um intérprete para o mesmo idioma) ou está literalmente tentando transformar seu intérprete em um compilador? Seu fraseado está me dando idéias ;-)
4
Uma projeção de Futamura?
Dan D.
1
Isso é trivial - basta especializar seu intérprete contra um código-fonte específico para obter sua versão compilada.
SK-logic,
A questão é sobre a técnica chamada como "compilador de rastreamento"
Dmitry Ponyatov 27/12/19

Respostas:

12

As duas primeiras etapas de lexing / análise (e análise, dependendo de como está estruturada) podem ser as mesmas. Mas você precisará converter sua representação em uma representação geradora de código. Normalmente, o LLVM é usado por entusiastas, pois é praticamente a única biblioteca geradora de código livre remotamente decente existente.

DeadMG
fonte
Era exatamente isso que eu ia escrever, mas você entendeu primeiro. Tenha um +1.
Mason Wheeler
3
Errado. Simplesmente emitir C (ou C ++, ou qualquer outra coisa) é muito mais popular para os projetos de compiladores amadores. LLVM é muito mais complicado. E JVM ou .NET não são piores que o LLVM para essa finalidade.
SK-logic,
Esses compiladores não produzem executáveis, o que o OP deseja. Quanto ao .NET / JVM, isso realmente depende da semântica de sua linguagem.
23413 DeadMG
1
O @DeadMG, ghcpor exemplo, é perfeitamente capaz de produzir executáveis ​​via C. Assim como centenas de outros compiladores baseados em C. Sua religião proíbe que você use popen(...)em um compilador? Então você tem que se jogar fora gcc. Quanto ao .NET, ao contrário da JVM, ele é capaz de atender a uma ampla variedade de semânticas, devido a seus recursos inseguros.
SK-logic,
Eu usei o LLVM (com ligações python) e funcionou como um encanto. :)
LaVolpe
4

Se tudo o que você realmente deseja é um executável, você pode anexar o script ao final de um executável de intérprete e executá-lo.

Consulte: /programming/5795446/appending-data-to-an-exe

Como alternativa, você pode fazer com que o intérprete carregue o código de um arquivo no mesmo diretório que o intérprete e obtenha praticamente o mesmo resultado, apenas com vários arquivos.

Um compilador verdadeiro converteria o código em outro idioma e usaria o compilador para esse idioma. Mas se você apenas deseja distribuir executáveis, não há necessidade de fazer isso.

Winston Ewert
fonte
Bem, eu conheço essa maneira de fazer as malas :) usei para Python (antes de ouvir falar de py2exe). Para mim, isso é trapaça e o outro problema é o desempenho. Minha linguagem como está agora é de baixo nível, mas estritamente objetivada.
LaVolpe 23/02
não faz compilador definitivamente, único intérprete embutir
Dmitry Ponyatov
1
@DmitryPonyatov, você sentiu a necessidade de comentar quase sete anos depois dizendo o que eu já havia dito na minha resposta?
Winston Ewert
3

Você também pode considerar usar System.Reflection.Emit no .NET runtime para gerar um executável .NET. Isso lhe dará acesso a um ambiente orientado a objetos existente que já resolveu alguns problemas para você, e o exe resultante pode ser independente da plataforma. O tempo de execução compilará o código intermediário no .exe para o código da máquina, conforme necessário, portanto o desempenho deve ser comparável ao que você obteria da compilação direta no código nativo.

Vincent Povirk
fonte
Provavelmente, é uma boa idéia, mas projetei meu idioma para ser de baixo nível em algum momento;) Agora estou tentando explorar a documentação de OpCodes da Intels.
LaVolpe 11/11
0

Você está perguntando sobre a técnica conhecida como "compilador de rastreamento": o intérprete reúne informações sobre a execução do código e cria incrementalmente código de baixo nível usando dados coletados.

https://en.wikipedia.org/wiki/Tracing_just-in-time_compilation

https://stefan-marr.de/papers/oopsla-marr-ducasse-meta-tracing-vs-partial-evaluation/

A diferença do JIT clássico é o fato de os dados de rastreamento coletados e o código compilado serem preservados a cada execução de um programa, o que fornece não apenas código de máquina executável, mas também otimização de dados reais (ou de treinamento). A primeira passagem é um conjunto de testes, que deve passar em todas as ramificações do programa, para criar código para cada parte do seu programa. Os próximos são programas executados com dados reais (uso de produção), que coletam e aplicam otimizações (coisas como ordenação de ramificações nos casos mais frequentemente usados).

Esse método é muito mais complexo de implementar do que um esquema clássico de construção do compilador, por isso não é usado com freqüência e é complexo encontrar um bom conjunto de tutoriais sobre como fazer o mesmo compilador.

Dmitry Ponyatov
fonte