Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Aprendendo compiladores fazendo um - Parte 1

Aprendendo compiladores fazendo um - Parte 1

Vídeo da Talk: https://youtu.be/t77ThZNCJGY

Aprender mais sobre compiladores é uma excelente forma de desmitificar o que acontece no momento entre iniciar a build do código e obter o output. Isso é ótimo para se tornar um melhor desenvolver e expandir seus horizontes; desse modo é possível entender mais sobre o funcionamento de ferramentas como Babel e máquinas virtuais, assim como outras áreas, como otimização e engenharia reversa.

Nessa primeira parte da talk "Aprendendo compiladores fazendo um" introduzo sobre design de linguagens, motivações em fazer um novo compilador e descrevendo as etapas de compilação, sempre visando como você pode desenvolver o seu próprio compilador para a sua própria linguagem.

Repositório do compilador de EventMacro: https://github.com/macabeus/macro-compiler

Bruno Macabeus

July 05, 2018
Tweet

More Decks by Bruno Macabeus

Other Decks in Programming

Transcript

  1. Compilador é um software que traduz da linguagem A para

    a linguagem B Definições A pode ser igual a B!
  2. Compilador é um software que traduz da linguagem A para

    a linguagem B Definições Mas precisa ser entre linguagens?
  3. Compilador é um programa que transforma uma representação de dados

    em outra representação de dados de alguma forma equivalente ou relacionada à primeira. Definições
  4. TypeScript é um superset de JS que compila
 para JS

    com o diferencial de implementar tipos
  5. TypeScript é um superset de JS que compila
 para JS

    com o diferencial de implementar tipos // JS const createUser = (id, level) => { // code... } createUser(42, 'guest') // O ID realmente é um number? // Quais seriam todos os level? // O usuário criado é retornado pela função?
  6. // JS const createUser = (id, level) => { //

    code... } createUser(42, 'guest') // O ID realmente é um number? // Quais seriam todos os level? // O usuário criado é retornado pela função? // TypeScript enum level { guest = 'guest', normal = 'normal', admin = 'admin', } const createUser = (id: number, level: level) => { // code... } createUser(42, level.guest) // Todas aquelas dúvidas são respondidas
 // bastando ver a assinatura da função! TypeScript é um superset de JS que compila
 para JS com o diferencial de implementar tipos
  7. Koka é uma linguagem que separa os valores dos side-effects,

    além de inferir em tempo de compilação
  8. // Swift func getEvenNumber() -> Int { // algum código...

    } getEvenNumber() // essa função gera IO? resultado é determinístico? // pode ser que nunca termine? Koka é uma linguagem que separa os valores dos side-effects, além de inferir em tempo de compilação
  9. // Swift func getEvenNumber() -> Int { // algum código...

    } getEvenNumber() // essa função gera IO? resultado é determinístico? // pode ser que nunca termine? // Koka
 function getEvenNumber() : ndet int {
 // algum código...
 } function main() {
 getEvenNumber() // basta ver a assinatura da função
 // para saber que o é um número aleatório!
 } Koka é uma linguagem que separa os valores dos side-effects, além de inferir em tempo de compilação
  10. // Koka
 function getEvenNumber() : ndet int {
 return randomInt()

    * 2
 } function main() {
 getEvenNumber() // basta ver a assinatura da função
 // para saber que o é um número aleatório!
 } // Swift func getEvenNumber() -> Int { return Int(arc4random()) * 2 } getEvenNumber() // essa função gera IO? resultado é determinístico? // pode ser que nunca termine? Koka é uma linguagem que separa os valores dos side-effects, além de inferir em tempo de compilação
  11. automacro ref { InInventory "Rough Oridecon" > 4 call ref-while

    } macro ref-while { log go to refiner do move prt_in 59 60 $ori = &invamount(Rough Oridecon) log I have $ori Rough Oridecons while (&invamount(Rough Oridecon) > 4) { do talk 0 pause 0.8 do talk resp 0 } } EventMacro
  12. automacro ref { InInventory "Rough Oridecon" > 4 call ref-while

    } macro ref-while { log go to refiner do move prt_in 59 60 $ori = &invamount(Rough Oridecon) log I have $ori Rough Oridecons while (&invamount(Rough Oridecon) > 4) { do talk 0 pause 0.8 do talk resp 0 } } EventMacro
  13. automacro ref { InInventory "Rough Oridecon" > 4 call ref-while

    } macro ref-while { log go to refiner do move prt_in 59 60 $ori = &invamount(Rough Oridecon) log I have $ori Rough Oridecons while (&invamount(Rough Oridecon) > 4) { do talk 0 pause 0.8 do talk resp 0 } } EventMacro
  14. automacro ref { InInventory "Rough Oridecon" > 4 call ref-while

    } macro ref-while { log go to refiner do move prt_in 59 60 $ori = &invamount(Rough Oridecon) log I have $ori Rough Oridecons while (&invamount(Rough Oridecon) > 4) { do talk 0 pause 0.8 do talk resp 0 } } EventMacro
  15. automacro ref { InInventory "Rough Oridecon" > 4 call ref-while

    } macro ref-while { log go to refiner do move prt_in 59 60 $ori = &invamount(Rough Oridecon) log I have $ori Rough Oridecons while (&invamount(Rough Oridecon) > 4) { do talk 0 pause 0.8 do talk resp 0 } } EventMacro
  16. automacro ref { InInventory "Rough Oridecon" > 4 call ref-while

    } macro ref-while { log go to refiner do move prt_in 59 60 $ori = &invamount(Rough Oridecon) log I have $ori Rough Oridecons while (&invamount(Rough Oridecon) > 4) { do talk 0 pause 0.8 do talk resp 0 } } EventMacro
  17. automacro ref { InInventory "Rough Oridecon" > 4 call ref-while

    } macro ref-while { log go to refiner do move prt_in 59 60 $ori = &invamount(Rough Oridecon) log I have $ori Rough Oridecons while (&invamount(Rough Oridecon) > 4) { do talk 0 pause 0.8 do talk resp 0 } } EventMacro
  18. automacro ref { InInventory "Rough Oridecon" > 4 call ref-while

    } macro ref-while { log go to refiner do move prt_in 59 60 $ori = &invamount(Rough Oridecon) log I have $ori Rough Oridecons while (&invamount(Rough Oridecon) > 4) { do talk 0 pause 0.8 do talk resp 0 } } EventMacro
  19. EventMacro automacro ref { InInventory "Rough Oridecon" > 4 call

    ref-while } macro ref-while { log go to refiner do move prt_in 59 60 $ori = &invamount(Rough Oridecon) log I have $ori Rough Oridecons while (&invamount(Rough Oridecon) > 4) { do talk 0 pause 0.8 do talk resp 0 } }
  20. ' EventMacro ' automacro ref { InInventory "Rough Oridecon" >

    4 call ref-while } macro ref-while { log go to refiner do move prt_in 59 60 $ori = &invamount(Rough Oridecon) log I have $ori Rough Oridecons while (&invamount(Rough Oridecon) > 4) { do talk 0 pause 0.8 do talk resp 0 } }
  21. EventMacro Fortemente influenciada por Perl my $scalar = 'foo'; my

    @array = (1, 2, 3); my %hash = (1 => 'foo', 2 => 'bar');
  22. EventMacro ⛏ Desenvolvida visando facilitar a escrita de um interpretador

    regexp-based Funciona através de um plugin que interpreta o código Fortemente influenciada por Perl
  23. Voltada para iniciantes EventMacro ⛏ Desenvolvida visando facilitar a escrita

    de um interpretador regexp-based Funciona através de um plugin que interpreta o código Fortemente influenciada por Perl
  24. Mensagens de erro e warning em tempo de compilação MacroCompiler

    Nós podemos construir um compilador para o EventMacro!
  25. MacroCompiler Mensagens de erro e warning em tempo de compilação

    Nós podemos construir um compilador para o EventMacro! Código final otimizado
  26. Maior facilidade em implementar novas features MacroCompiler Código final otimizado

    Mensagens de erro e warning em tempo de compilação Nós podemos construir um compilador para o EventMacro!
  27. Trata-se de estruturar a API pública de uma biblioteca como

    se ela fosse uma linguagem de programação eDSL (embedded domain-specific language) pode ser uma solução mais simples!
  28. Trata-se de estruturar a API pública de uma biblioteca como

    se ela fosse uma linguagem de programação eDSL (embedded domain-specific language) pode ser uma solução mais simples! // css selector em JS + jQuery
 const element = $('#foo .bar');
  29. Trata-se de estruturar a API pública de uma biblioteca como

    se ela fosse uma linguagem de programação eDSL (embedded domain-specific language) pode ser uma solução mais simples! // JS
 const myRegexp = /^age (\d+)/ // css selector em JS + jQuery
 const element = $('#foo .bar');
  30. Trata-se de estruturar a API pública de uma biblioteca como

    se ela fosse uma linguagem de programação eDSL (embedded domain-specific language) pode ser uma solução mais simples! // Haskell + Functional MetaPost library
 beginfig(1)
 pair A, B, C;
 A:=(0, 0); B:=(1cm, 0); C:=(0, 1cm);
 draw A--B--C--cycle;
 endfig;
  31. Desenvolver o design de uma linguagem é mais a respeito

    de como a pessoa vai se comunicar com o computador
  32. Desenvolver o design de uma linguagem é mais a respeito

    de como a pessoa vai se comunicar com o computador Desenvolver um compilador é um desenvolvimento de software
  33. macro sayHi { } $someone = Macabeus log Hi, $someone

    Parser Código fonte Análise semântica Otimização Geração de código Análise léxica
  34. macro sayHi { } $someone = Macabeus log Hi, $someone

    [
 keyword(macro),
 identifier(sayHi),
 openBraces, newLine,
 scalarIdentifier(someone),
 equal,
 text(Macabeus), newLine,
 keyword(log),
 text(Hi, ),
 scalarIdentifier(someone),
 newLine, closeBraces
 ] Parser Código fonte Análise semântica Otimização Geração de código Análise léxica
  35. macro sayHi { } $someone = Macabeus log Hi, $someone

    [
 keyword(macro),
 identifier(sayHi),
 openBraces, newLine,
 scalarIdentifier(someone),
 equal,
 text(Macabeus), newLine,
 keyword(log),
 text(Hi, ),
 scalarIdentifier(someone),
 newLine, closeBraces
 ] Parser Código fonte Análise semântica Otimização Geração de código Análise léxica
  36. macro sayHi { } $someone = Macabeus log Hi, $someone

    [
 keyword(macro),
 identifier(sayHi),
 openBraces, newLine,
 scalarIdentifier(someone),
 equal,
 text(Macabeus), newLine,
 keyword(log),
 text(Hi, ),
 scalarIdentifier(someone),
 newLine, closeBraces
 ] Parser Código fonte Análise semântica Otimização Geração de código Análise léxica
  37. macro sayHi { } $someone = Macabeus log Hi, $someone

    [
 keyword(macro),
 identifier(sayHi),
 openBraces, newLine,
 scalarIdentifier(someone),
 equal,
 text(Macabeus), newLine,
 keyword(log),
 text(Hi, ),
 scalarIdentifier(someone),
 newLine, closeBraces
 ] Parser Código fonte Análise semântica Otimização Geração de código Análise léxica
  38. macro sayHi { } $someone = Macabeus log Hi, $someone

    [
 keyword(macro),
 identifier(sayHi),
 openBraces, newLine,
 scalarIdentifier(someone),
 equal,
 text(Macabeus), newLine,
 keyword(log),
 text(Hi, ),
 scalarIdentifier(someone),
 newLine, closeBraces
 ] Parser Código fonte Análise semântica Otimização Geração de código Análise léxica
  39. macro sayHi { } $someone = Macabeus log Hi, $someone

    [
 keyword(macro),
 identifier(sayHi),
 openBraces, newLine,
 scalarIdentifier(someone),
 equal,
 text(Macabeus), newLine,
 keyword(log),
 text(Hi, ),
 scalarIdentifier(someone),
 newLine, closeBraces
 ] Parser Código fonte Análise semântica Otimização Geração de código Análise léxica
  40. macro sayHi { } $someone = Macabeus log Hi, $someone

    Parser Código fonte Análise semântica Otimização Geração de código Análise léxica
  41. macro sayHi { } $someone = Macabeus log Hi, $someone

    Parser Código fonte Análise semântica Otimização Geração de código Análise léxica
  42. macro sayHi { } log $someone = Macabeus Hi, $someone

    Parser Código fonte Análise semântica Otimização Geração de código Análise léxica
  43. macro sayHi { } log $someone = Macabeus Hi, $someone

    Parser Código fonte Análise semântica Otimização Geração de código Análise léxica
  44. macro sayHi { } log $someone = Macabeus Hi, $someone

    Symbol table macro_write : sayHi
  45. macro sayHi { } log $someone = Macabeus Hi, $someone

    Symbol table macro_write : sayHi variable_write: $someone
  46. macro sayHi { } log $someone = Macabeus Hi, $someone

    Symbol table macro_write : sayHi variable_write: $someone variable_read : $someone
  47. macro sayHi { } log $someone = Macabeus Hi, $someone

    Symbol table macro_write : sayHi variable_write: $someone variable_read : $someone
  48. macro sayHi { } log $someone = Macabeus Hi, $someone

    Parser Código fonte Análise semântica Otimização Geração de código Análise léxica
  49. macro sayHi { } log $someone = Macabeus Hi, $someone

    Parser Código fonte Análise semântica Otimização Geração de código Análise léxica
  50. macro sayHi { } log $someone = Macabeus Hi, $someone

    Dead code strip Constant folding Otimizações
  51. macro sayHi { } log $someone = Macabeus Hi, $someone

    Dead code strip Constant folding Otimizações
  52. macro sayHi { } log $someone = Macabeus Hi, $someone

    Dead code strip Constant folding Otimizações
  53. macro sayHi { } log Hi, Macabeus Dead code strip

    Constant folding Otimizações $someone = Macabeus
  54. macro sayHi { } log Hi, Macabeus Dead code strip

    Constant folding Otimizações $someone = Macabeus
  55. macro sayHi { } log Hi, Macabeus Dead code strip

    Constant folding Otimizações $someone = Macabeus
  56. macro sayHi { } log Hi, Dead code strip Constant

    folding Otimizações Macabeus
  57. macro sayHi { } log Hi, Dead code strip Constant

    folding Otimizações Macabeus
  58. macro sayHi { } log Hi, Dead code strip Constant

    folding Otimizações Macabeus
  59. macro sayHi { } log Hi, Dead code strip Constant

    folding Otimizações Macabeus
  60. macro sayHi { } log Hi, Macabeus Parser Código fonte

    Análise semântica Otimização Geração de código Análise léxica
  61. macro sayHi { } log Hi, Macabeus Parser Código fonte

    Análise semântica Otimização Geração de código Análise léxica
  62. macro sayHi { } log Hi, Macabeus package macroCompiled; Plugins::register(

    'macroCompiled', 'Compiled version of eventMacro.txt', &on_unload ); sub on_unload { } Corpo Cabeçalho Geração de código
  63. macro sayHi { } log Hi, Macabeus package macroCompiled; Plugins::register(

    'macroCompiled', 'Compiled version of eventMacro.txt', &on_unload ); sub on_unload { } Corpo Cabeçalho Geração de código
  64. macro sayHi { } log Hi, Macabeus Corpo Cabeçalho Geração

    de código package macroCompiled; use Log qw(message); Plugins::register( 'macroCompiled', 'Compiled version of eventMacro.txt', &on_unload ); sub on_unload { }
  65. macro sayHi { } log Hi, Macabeus Corpo Cabeçalho Geração

    de código package macroCompiled; use Log qw(message); Plugins::register( 'macroCompiled', 'Compiled version of eventMacro.txt', &on_unload ); sub on_unload { }
  66. macro sayHi { } log Hi, Macabeus Corpo Cabeçalho Geração

    de código package macroCompiled; use Log qw(message); Plugins::register( 'macroCompiled', 'Compiled version of eventMacro.txt', &on_unload ); sub on_unload { }
  67. macro sayHi { } log Hi, Macabeus Corpo Cabeçalho Geração

    de código package macroCompiled; use Log qw(message); Plugins::register( 'macroCompiled', 'Compiled version of eventMacro.txt', &on_unload ); sub on_unload { }
  68. macro sayHi { } log Hi, Macabeus Corpo Cabeçalho Geração

    de código package macroCompiled; use Log qw(message); Plugins::register( 'macroCompiled', 'Compiled version of eventMacro.txt', &on_unload ); sub on_unload { } sub macro_sayHi { }
  69. macro sayHi { } log Hi, Macabeus Corpo Cabeçalho Geração

    de código package macroCompiled; use Log qw(message); Plugins::register( 'macroCompiled', 'Compiled version of eventMacro.txt', &on_unload ); sub on_unload { } sub macro_sayHi { message 
 }
  70. macro sayHi { } log Hi, Macabeus Corpo Cabeçalho Geração

    de código package macroCompiled; use Log qw(message); Plugins::register( 'macroCompiled', 'Compiled version of eventMacro.txt', &on_unload ); sub on_unload { } sub macro_sayHi { message 
 }
  71. macro sayHi { } log Hi, Macabeus Corpo Cabeçalho Geração

    de código package macroCompiled; use Log qw(message); Plugins::register( 'macroCompiled', 'Compiled version of eventMacro.txt', &on_unload ); sub on_unload { } sub macro_sayHi { message "Hi, Macabeus" ."\n"; }
  72. macro sayHi { } log Hi, Macabeus Corpo Cabeçalho Geração

    de código package macroCompiled; use Log qw(message); Plugins::register( 'macroCompiled', 'Compiled version of eventMacro.txt', &on_unload ); sub on_unload { } sub macro_sayHi { message "Hi, Macabeus" ."\n"; }
  73. macro sayHi { } log Hi, Macabeus package macroCompiled; use

    Log qw(message); Plugins::register( 'macroCompiled', 'Compiled version of eventMacro.txt', &on_unload ); sub on_unload { } sub macro_sayHi { message "Hi, Macabeus" ."\n"; } Parser Código fonte Análise semântica Otimização Geração de código Análise léxica
  74. Isso é uma simplificação! AST (pode) ter nós de metadados

    Compilador pode ter várias etapas intermediárias
  75. Isso é uma simplificação! AST (pode) ter nós de metadados

    Compilador pode ter várias etapas intermediárias Como ele pode produzir o código alvo diretamente
  76. Créditos das imagens: - https://darkchiichan.deviantart.com/ - https://www.newgrounds.com/art/view/shidoisnthere/tree-pixel-art-2 Onde aprender mais:

    - DSL & eDSL http://bit.ly/quora-edsl - Análise léxica http://esprima.org/ - Sobre design de linguagem e compilador - http://bit.ly/quora-language-x-compiler - http://bit.ly/quora-language-x-compiler-2