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

Aprendendo compiladores fazendo um - Parte 2

Aprendendo compiladores fazendo um - Parte 2

Vídeo dessa talk: https://youtu.be/q9T6Y2ZjE54
Vídeo da Parte 1: https://youtu.be/t77ThZNCJGY
Vídeo da demonstração do compilador: https://youtu.be/BAS0EZ0Yg6g

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 segunda parte da talk "Aprendendo compiladores fazendo um" vamos adentrar bem mais no código de como o Macro Compiler funciona. Veremos todas as etapas de compilação, como as gramáticas, parser combinator, análise semântica, tratamento de erros, otimização, geração de código e testes! Assim clarificando como um compilador pode ser implementado.

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

Bruno Macabeus

September 04, 2018
Tweet

More Decks by Bruno Macabeus

Other Decks in Programming

Transcript

  1. “The language or notation we are using to express or

    record our thoughts, are the major factors determining what we can think or express at all!” Edsger W. Dijkstra
  2. Context-free Grammars Parsing Expression Grammar Regular Grammars eDSL É uma

    forma muito simples de representar a gramática de uma linguagem.
  3. Context-free Grammars Parsing Expression Grammar Regular Grammars eDSL move prontera

    30 42 move 30 42 É uma forma muito simples de representar a gramática de uma linguagem. Regexp (regular expression) é um exemplo
  4. Context-free Grammars Parsing Expression Grammar Regular Grammars eDSL /move (?:(\w+)

    )?(\d+) (\d+)/ move prontera 30 42 move 30 42 É uma forma muito simples de representar a gramática de uma linguagem. Regexp (regular expression) é um exemplo
  5. Context-free Grammars Parsing Expression Grammar Regular Grammars eDSL Uma das

    limitações é não ser possível especificar uma sequência arbitrária de comandos. Por conta disso, não é possível descrever uma sequência aninhada de blocos de comandos
  6. Context-free Grammars Parsing Expression Grammar Regular Grammars eDSL { evil_query(id:

    42) { complex_field {
 complex_field { field } } } } Uma das limitações é não ser possível especificar uma sequência arbitrária de comandos. Por conta disso, não é possível descrever uma sequência aninhada de blocos de comandos
  7. Context-free Grammars Parsing Expression Grammar Regular Grammars eDSL { evil_query(id:

    42) { complex_field {
 complex_field { field } } } } Uma das limitações é não ser possível especificar uma sequência arbitrária de comandos. Por conta disso, não é possível descrever uma sequência aninhada de blocos de comandos
  8. Uma eDSL é uma biblioteca com interface da qual mimetiza

    uma linguagem de programação, isto é, apresenta palavras primitivas e a possibilidade combiná-las para construir rotinas Context-free Grammars Parsing Expression Grammar eDSL Regular Grammars
  9. Pode-se embutir em uma linguagem uma outra linguagem cuja finalidade

    dela é especificar gramáticas Context-free Grammars Parsing Expression Grammar eDSL Regular Grammars
  10. Context-free Grammars Parsing Expression Grammar eDSL Regular Grammars sequence([
 ignore(string("move")),


    ignore(spaces()),
 
 many(letter()),
 skip(spaces()),
 
 integer(),
 ignore(spaces()),
 
 integer()
 ]) Pode-se embutir em uma linguagem uma outra linguagem cuja finalidade dela é especificar gramáticas
  11. Define um conjunto de símbolos e as respectivas transformações válidas

    de cada um. Context-free Grammars Parsing Expression Grammar Regular Grammars eDSL
  12. Define um conjunto de símbolos e as respectivas transformações válidas

    de cada um. Um exemplo de CFG (Context-free Grammars) é o BNF (Backus–Naur Form): Context-free Grammars Parsing Expression Grammar Regular Grammars eDSL <vowel> :== "a" | "e" | "i" | "o" | "u" <digit> :== "0" | "1" | "2" | "3" | "4" |
 "5" | "6" | "7" | "8" | "9" <character> :== <vowel> | <digit> <text> :== <character> | <text> <character>
  13. Define um conjunto de símbolos e as respectivas transformações válidas

    de cada um. Um exemplo de CFG (Context-free Grammars) é o BNF (Backus–Naur Form): Context-free Grammars Parsing Expression Grammar Regular Grammars eDSL <vowel> :== "a" | "e" | "i" | "o" | "u" <digit> :== "0" | "1" | "2" | "3" | "4" |
 "5" | "6" | "7" | "8" | "9" <character> :== <vowel> | <digit> <text> :== <character> | <text> <character> ei9 zyp
  14. Similar ao CFG. Também define um conjunto de símbolos e

    as respectivas transformações. Context-free Grammars Parsing Expression Grammar Regular Grammars eDSL
  15. Similar ao CFG. Também define um conjunto de símbolos e

    as respectivas transformações. Exemplo de PEG (Parsing Expression Grammar): Context-free Grammars Parsing Expression Grammar Regular Grammars eDSL vowel ← 'a' / 'e' / 'i' / 'o' / 'u' digit ← [0-9] character ← vowel / digit text ← character+
  16. Parsing Expression Grammar Regular Grammars eDSL Context-free Grammars As principais

    diferenças entre CFG e PEG são:
 - notação <vowel> :== "a" | "e" | "i" | "o" | "u" <digit> :== "0" | "1" | "2" | "3" | "4" |
 "5" | "6" | "7" | "8" | "9" <character> :== <vowel> | <digit> <text> :== <character> | <text> <character> vowel ← 'a' / 'e' / 'i' / 'o' / 'u' digit ← [0-9] character ← vowel / digit text ← character+
  17. Parsing Expression Grammar Regular Grammars eDSL Context-free Grammars As principais

    diferenças entre CFG e PEG são:
 - notação - interpretação das regras
  18. Parsing Expression Grammar Regular Grammars eDSL Context-free Grammars As principais

    diferenças entre CFG e PEG são:
 - notação - interpretação das regras CFG Regra A
 Regra B
 Regra C CFG Regra B
 Regra C
 Regra A = PEG Regra A
 Regra B
 Regra C PEG Regra B
 Regra C
 Regra A ≠
  19. Parsing Expression Grammar Regular Grammars eDSL Context-free Grammars As principais

    diferenças entre CFG e PEG são:
 - notação - interpretação das regras CFG Regra A
 Regra B
 Regra C CFG Regra B
 Regra C
 Regra A = PEG Regra A
 Regra B
 Regra C PEG Regra B
 Regra C
 Regra A ≠ “Hmm.. posso usar tanto A ou B… Então devo usar qual?”
  20. Parsing Expression Grammar Regular Grammars eDSL Context-free Grammars As principais

    diferenças entre CFG e PEG são:
 - notação - interpretação das regras CFG Regra A
 Regra B
 Regra C CFG Regra B
 Regra C
 Regra A = PEG Regra A
 Regra B
 Regra C PEG Regra B
 Regra C
 Regra A ≠ Sei lá! Sei lá! “Hmm.. posso usar tanto A ou B… Então devo usar qual?”
  21. Parsing Expression Grammar Regular Grammars eDSL Context-free Grammars As principais

    diferenças entre CFG e PEG são:
 - notação - interpretação das regras CFG Regra A
 Regra B
 Regra C CFG Regra B
 Regra C
 Regra A = PEG Regra A
 Regra B
 Regra C PEG Regra B
 Regra C
 Regra A ≠ Sei lá! Use B,
 veio
 antes! Sei lá! Use A,
 veio
 antes! “Hmm.. posso usar tanto A ou B… Então devo usar qual?”
  22. Em alguns momentos, pode ser que a sua gramática seja

    recursiva. &rand(0, 5) ScalarValue
  23. A symbols table é importante para tornar mais acessível as

    informações da AST para as demais etapas de compilação
  24. read macros: [ "foo", "bar" ] write macros: [ "foo"

    ] difference: [ "bar" ] Devemos disparar um erro
 devido a leitura de "bar" !
  25. Erro semântico macro example { $never_read_var = &rand(1, 4) #

    warning log number: $never_written_var # fatal error }
  26. macro setVars { $foo = value $bar = &rand(1, 4)

    } macro example { $name = macabeus call setVars log foo: $foo log bar: $bar log name: $name $name = pagarme log name: $name }
  27. macro setVars { $foo = value $bar = &rand(1, 4)

    } macro example { $name = macabeus call setVars log foo: $foo log bar: $bar log name: $name $name = pagarme log name: $name } ➡
  28. macro setVars { $foo = value $bar = &rand(1, 4)

    } macro example { $name = macabeus call setVars log foo: $foo log bar: $bar log name: $name $name = pagarme log name: $name } macro setVars { $foo = value $bar = &rand(1, 4) } macro example { $name = macabeus call setVars log foo: value log bar: $bar log name: macabeus $name = pagarme log name: pagarme } ➡
  29. macro setVars { $foo = value $bar = &rand(1, 4)

    } macro example { $name = macabeus call setVars log foo: $foo log bar: $bar log name: $name $name = pagarme log name: $name } macro setVars { $foo = value $bar = &rand(1, 4) } macro example { $name = macabeus call setVars log foo: value log bar: $bar log name: macabeus $name = pagarme log name: pagarme } ➡
  30. macro setVars { $foo = value $bar = &rand(1, 4)

    } macro example { $name = macabeus call setVars log foo: log bar: log name: $name = pagarme log name: } Contexto das últimas
 variáveis na macro Contexto das variáveis na seta setVars
 $foo: value
 $bar: is nondeterministic
 example
 $name: pagarme $foo $bar $name
  31. macro setVars { $foo = value $bar = &rand(1, 4)

    } macro example { $name = macabeus call setVars log foo: log bar: log name: $name = pagarme log name: } Contexto das últimas
 variáveis na macro Contexto das variáveis na seta setVars
 $foo: value
 $bar: is nondeterministic
 example
 $name: pagarme $foo $bar $name $name
  32. macro setVars { $foo = value $bar = &rand(1, 4)

    } macro example { $name = macabeus call setVars log foo: log bar: log name: $name = pagarme log name: } Contexto das últimas
 variáveis na macro Contexto das variáveis na seta setVars
 $foo: value
 $bar: is nondeterministic
 example
 $name: pagarme $name: macabeus $foo $bar $name $name
  33. macro setVars { $foo = value $bar = &rand(1, 4)

    } macro example { $name = macabeus call setVars log foo: log bar: log name: $name = pagarme log name: } Contexto das últimas
 variáveis na macro Contexto das variáveis na seta setVars
 $foo: value
 $bar: is nondeterministic
 example
 $name: pagarme $name: macabeus $foo: value
 $bar: is nondeterministic $foo $bar $name $name
  34. macro setVars { $foo = value $bar = &rand(1, 4)

    } macro example { $name = macabeus call setVars log foo: log bar: log name: $name = pagarme log name: } Contexto das últimas
 variáveis na macro Contexto das variáveis na seta setVars
 $foo: value
 $bar: is nondeterministic
 example
 $name: pagarme $name: macabeus $foo: value
 $bar: is nondeterministic $bar $name value $name
  35. macro setVars { $foo = value $bar = &rand(1, 4)

    } macro example { $name = macabeus call setVars log foo: log bar: log name: $name = pagarme log name: } Contexto das últimas
 variáveis na macro Contexto das variáveis na seta setVars
 $foo: value
 $bar: is nondeterministic
 example
 $name: pagarme $name: macabeus $foo: value
 $bar: is nondeterministic $bar $name value $name
  36. macro setVars { $foo = value $bar = &rand(1, 4)

    } macro example { $name = macabeus call setVars log foo: log bar: log name: $name = pagarme log name: } Contexto das últimas
 variáveis na macro Contexto das variáveis na seta setVars
 $foo: value
 $bar: is nondeterministic
 example
 $name: pagarme $name: macabeus $foo: value
 $bar: is nondeterministic $bar value macabeus $name
  37. macro setVars { $foo = value $bar = &rand(1, 4)

    } macro example { $name = macabeus call setVars log foo: log bar: log name: $name = pagarme log name: } Contexto das últimas
 variáveis na macro Contexto das variáveis na seta setVars
 $foo: value
 $bar: is nondeterministic
 example
 $name: pagarme $foo: value
 $bar: is nondeterministic $name: pagarme $bar value macabeus $name
  38. macro setVars { $foo = value $bar = &rand(1, 4)

    } macro example { $name = macabeus call setVars log foo: log bar: log name: $name = pagarme log name: } Contexto das últimas
 variáveis na macro Contexto das variáveis na seta setVars
 $foo: value
 $bar: is nondeterministic
 example
 $name: pagarme $foo: value
 $bar: is nondeterministic $name: pagarme $bar value macabeus pagarme
  39. header body footer [
 "push",
 "@values",
 ",",
 [ "f", "o",

    "o" ], ";" ] [
 "push",
 "@values",
 ",", "f", "o", "o", ";" ]
  40. header body footer encontrar quais variáveis são escritas para declará-las


    encontrar os módulos do OpenKore que precisa importar
  41. header body footer encontrar quais variáveis são escritas para declará-las


    encontrar os módulos do OpenKore que precisa importar
  42. header body footer encontrar quais variáveis são escritas para declará-las


    encontrar os módulos do OpenKore que precisa importar
  43. header body footer encontrar quais variáveis são escritas para declará-las


    encontrar os módulos do OpenKore que precisa importar
  44. header body footer encontrar quais variáveis são escritas para declará-las


    encontrar os módulos do OpenKore que precisa importar
  45. header body footer gerar boilerplate
 encontrar quais variáveis são escritas

    para declará-las
 encontrar os módulos do OpenKore que precisa importar
 ✏ encontrar quais macros são escritas para tornar chamáveis
  46. Functional test E2e test Testo as otimizações checando a AST…

    porém, o importante é verificar se a semântica está preservada. 
 Verificar se está gerando uma AST equivalente garante trivialmente que a semântica é preservada
  47. Agradecimentos ao Pedro Castilho por ter me ajudado pra caralho

    em desenvolver o compilador e essa talk
  48. Para aprender mais - Material bem didática sobre como funciona

    parser funciona http://theorangeduck.com/page/you-could- have-invented-parser-combinators - Para ver mais possibilidades de fazer interprocess communication no Elixir https://youtu.be/ZrBhuP6OrFI - Manual foda sobre parser https://tomassetti.me/guide- parsing-algorithms-terminology/ - Lib em Ruby de parser generator com PEG, a Parslet