SlideShare uma empresa Scribd logo
1 de 49
Baixar para ler offline
Criando sua própria
linguagem de programação
Dev In Sampa
São Paulo, 28 de novembro de 2009
Por quê?


Cada nova linguagem é um campo aberto para
livre experimentação

Compilação é uma arena em que todas as suas
habilidades são necessárias
A verdade verdadeira

“Por que escrever um programa se você pode
escrever um programa para escrever um
programa?”

                          — Autor desconhecido



A verdade verdadeira é que é divertido ;)
Na prática

Você pode usar um parser mais sofisticado para
suas DSLs

Você pode resolver problemas de portar código de
um domínio para outro com um tradutor

Você pode usar um interpretador para construir
geradores mais sofisticados
Na pior das hipóteses...


“Se uma linguagem não é capaz de afetar o modo
como você pensa sobre programação, não vale a
pena aprendê-la”

                                  — Alan Perlis
Um pouco de conceitos
Linguagem


“Uma notação para escrever programas, que são
especificações para a computação de uma
algoritmo”

                                  — Wikipedia
Elementos


Sintaxe: o que é escrito, descrita em uma
gramática formal

Semântica: o que isso significa, especificado em
termos de formalizações de compilação e
execução
Gramáticas formais


Value ← [0-9]+ / '(' Expr ')'
Product ← Value (('*' / '/') Value)*
Sum ← Product (('+' / '-') Product)*
Expr ← Sum
Do texto à execução
  CÓDIGO FONTE              SAÍDA

              PARSING

 ANÁLISE LÉXICA           COMPILADOR
                        INTERPRETADOR
                           TRADUTOR
     TOKENS



ANÁLISE SINTÁTICA           AST
Introduzindo “Mirror”
Inspiração

Sintaxe baseada em Smalltalk e IO

Slot-based como Self

Forte e dinamicamente tipada

Interpretada, via bytecodes
Mirror
World mirrorInto: "Fib".


Fib set: "of:" to: [ n |
     n <= 2
       ifTrue: [ 1. ]
       ifFalse: [ (of: n - 1) + (of: n - 2). ].
].


(Fib of: 10) transcribeAndBreak.
Análise

Via Treetop, um packrat parser em Ruby

  PEGs

  Análise versus geração

  Sem ambigüidades

Gera uma árvore sintática que é compilada para
uma representação em bytecodes
AST #1


(Fib of: 2 + 3)
  transcribeAndBreak.
AST #2


(Fib of: 2 + 3)
  transcribeAndBreak.
Bytecode

push 3
push 2
send +
load Fib
send of:
send transcribeAndBreak
pop
A gramática
Blocos básicos
grammar Mirror


  rule statements
      (spaces? statement spaces? "." spaces?)* <Statements>
  end


  rule statement
      message_expression
  end


  rule message_expression
      keyword_expression / binary_expression / unary_expression
  end


  # ...


end
Keywords

grammar Mirror


  rule keyword_expression
      variable:binary_expression?
        keywords:(spaces? keyword spaces expression:binary_expression)+
          <KeywordExpression>
  end


  # Account deposit: 100 from: user.
  # ...


end
Expressões binárias
grammar Mirror


  rule binary_expression
      variable:unary_expression spaces?
        selector:binary_selector spaces?
        expression:binary_expression <BinaryExpression> /
      unary_expression
  end


  # 2 + 3 * (account balance).
  # ...


end
Expressões unárias
grammar Mirror


  rule unary_expression
        variable:primary
          selectors:(spaces selector:identifier !colon)+
            <UnaryExpression> /
        primary
  end


  # (Account current balance) transcribeAndBreak.
  # ...


end
Juntando as peças
irb> MirrorParser.new.parse('2 + 3.')


SyntaxNode+Statements offset=0, "2 + 3." (build):
  SyntaxNode+Statements0 offset=0, "2 + 3." (statement):
    SyntaxNode+BinaryExpression0+BinaryExpression offset=0, "2 + 3":
      SyntaxNode+IntegerLiteral offset=0, "2" (build):
        SyntaxNode offset=0, "2"
      SyntaxNode+Spaces2 offset=1, " ":
      SyntaxNode offset=2, "+":
        SyntaxNode offset=2, "+"
      SyntaxNode+IntegerLiteral offset=4, "3" (build):
        SyntaxNode offset=4, "3"
Convertendo a AST
Blocos básicos
#     rule statements
#         (spaces? statement spaces? "." spaces?)* <Statements>
#     end


module Statements
    def build
       elements.collect do |element|
            Ast::Statement.new(element.statement.build)
       end
    end
end


class Statement
    def initialize(expression)
       @expression = expression
    end
end
Expressões binárias
#     rule binary_expression
#         variable:unary_expression spaces?
#           selector:binary_selector spaces?
#           expression:binary_expression <BinaryExpression> /
#         unary_expression


module BinaryExpression
    def build
       Ast::Message.new(variable.build, selector.text_value, expression.build)
    end
end


class Message
    def initialize(target, selector, *arguments)
       @target = target
       @selector = selector
       @arguments = arguments
    end
end
Juntando as peças

irb> MirrorParser.new.parse('2 + 3.').build


[
    #<Ast::Statement
      @expression =
        #<Ast::Message
          @selector = "+",
          @target = #<Ast::Literal @value = "2", @type = :integer>,
          @arguments = [#<Ast::Literal @value = "3", @type = :integer>]>>
]
Geração de código
Double dispatch
class CodeGenerator


  def initialize(ast)
      @ast = ast
  end


  def generate
      @ast.collect { |statement| generate_any(statement) }.flatten
  end


  def generate_any(ast)
      send("generate_#{ast.class.name.demodulize.underscore}", ast)
  end


  # ...


end
Blocos básicos
class CodeGenerator


  def generate_statement(ast)
      ([generate_any(ast.expression)] + [Bytecode::Pop.new]).flatten
  end


  def generate_variable(ast)
      Bytecode::Load.new(ast.name)
  end


  # ...


end
Mensagens
class CodeGenerator


  def generate_message(ast)
      instructions = []
      ast.arguments.reverse.each do |argument|
        instructions += [generate_any(argument)].flatten
      end
      instructions += [generate_any(ast.target)].flatten
      instructions << Bytecode::Message.new(ast.selector)
      instructions
  end


  # ...


end
Bytecodes
class Pop
  def inspect
      "pop"
  end
end


class Message
  def initialize(selector)
      @selector = selector
      @selector_name = get_selector_name(selector)
      @selector_method = get_selector_method(selector)
      @arity = get_selector_arity(selector)
  end
  # ...
end
Juntando as peças

irb> ast = MirrorParser.new.parse('2 + 3.').build


irb> CodeGenerator.new(ast).generate


[
    push 3,
    push 2,
    send +,
    pop
]
Modelo de execução
Containers & Slots
   ACCOUNT

   BALANCE           0

    DEPOSIT:   BLOCK CONTEXT

   WITHDRAW:   BLOCK CONTEXT

     USER          USER
Universe & World
  UNIVERSE         WORLD

   WORLD       MIRRORINTO:

   ERROR           SET: TO:
Detalhes

O envio de mensagens acontece em um contexto
que é gerado para cada mensagem

Blocos geram contextos empilhados

O interpretador percorre os contextos até
encontrar o objeto apropriado para enviar a
mensagem
Máquina virtual
Máquina Virtual
class VM


  def initialize(instructions)
      @instructions = instructions
  end


  def run
      reset_instruction_pointer
      while has_instructions?
        execute(next_instruction)
      end
  end


  # ...


end
Máquina Virtual
class VM


  def execute(instruction)
      case instruction
      when Bytecode::Implicit
        stack_push_and_wrap(current_context)
      when Bytecode::Pop
        stack.pop
      when Bytecode::Push
        stack_push_and_wrap(instruction.value)
      when Bytecode::Load
        stack_push_and_wrap(walk_contexts(instruction.name))
      # ...
      end
  end


end
Juntando as peças

irb> Interpreter.run(true, "World offload: 2 + 2.")


[4]


irb> Interpreter.run(true, "World offload: [ 2 + 2. ] value.")


[4]
Próximos passos
Próximos passos
Arrays

Inlining de mensagens comuns

  Primitivas: + - * / at: at:put:

  ifTrue:ifFalse et al

  to:do et al

Melhor uso de blocos
LLVM

Uma estratégia de compilação

Um conjunto de instruções virtualizado

Uma infra-estrutura de compilação

Um conjunto de ferramentas
LLVM

Efetivamente uma DSL para geração de código
intermediário otimizado e portável

Estático ou JIT

Usado por MacRuby, Rubinius, Unladden
Swallow e outros
LLVM: Uso

Transformar slots de código em funções

Transformar closures em funções quando não
fizer sentido que os mesmos sejam inline

Compilar o próprio interpretador para ser
parcialmente jitted
LLVM: Uso

module = LLVM::Module.new("mirror")
type = Type::function(MACHINE_WORD, [])
function = module.get_or_insert_function("main", type)


entry_block = function.create_block
exit_block_true = function.create_block
exit_block_false = function.create_block


builder = entry_block.builder
cmp = builder.icmp_sgt(-1.llvm, 1.llvm)
builder.cond_br(cmp, exit_block_true, exit_block_false)
LLVM: Uso


builder = exit_block_true.builder
builder.return(1.llvm)


builder = exit_block_false.builder
builder.return(0.llvm)


ExecutionEngine.get(module)
ExecutionEngine.run_autoconvert(function)
Questões?

@rferraz
http://logbr.reflectivesurface.com

Mais conteúdo relacionado

Mais procurados

Introdução a JavaScript
Introdução a JavaScriptIntrodução a JavaScript
Introdução a JavaScriptBruno Catão
 
BDD: Torne viva a documentação de seus sistemas
BDD: Torne viva a documentação de seus sistemasBDD: Torne viva a documentação de seus sistemas
BDD: Torne viva a documentação de seus sistemasVitor Mattos
 
Delphi Parallel Programming Library
Delphi Parallel Programming LibraryDelphi Parallel Programming Library
Delphi Parallel Programming LibraryMario Guedes
 
Testes com javascript
Testes com javascriptTestes com javascript
Testes com javascriptLaís Lima
 
Delphi Conference 2012 - Programação Baseado em Regras com RTTI
Delphi Conference 2012 - Programação Baseado em Regras com RTTIDelphi Conference 2012 - Programação Baseado em Regras com RTTI
Delphi Conference 2012 - Programação Baseado em Regras com RTTIMario Guedes
 
Xdebug seus problemas acabaram - tdc floripa 2017
Xdebug   seus problemas acabaram - tdc floripa 2017Xdebug   seus problemas acabaram - tdc floripa 2017
Xdebug seus problemas acabaram - tdc floripa 2017Vitor Mattos
 
JavaScript: agora é sério
JavaScript: agora é sérioJavaScript: agora é sério
JavaScript: agora é sérioLuciano Ramalho
 
Processo de Desenvolvimento de Software - Linguagens Imperativas x Declarativas
Processo de Desenvolvimento de Software - Linguagens Imperativas x DeclarativasProcesso de Desenvolvimento de Software - Linguagens Imperativas x Declarativas
Processo de Desenvolvimento de Software - Linguagens Imperativas x DeclarativasNatanael Simões
 
Apostila de Introdução ao C#.net
Apostila de Introdução ao C#.netApostila de Introdução ao C#.net
Apostila de Introdução ao C#.netAndre Nascimento
 
Processo de Desenvolvimento de Software - Programação
Processo de Desenvolvimento de Software - ProgramaçãoProcesso de Desenvolvimento de Software - Programação
Processo de Desenvolvimento de Software - ProgramaçãoNatanael Simões
 
Delphi Conference 2012 - Controlando a Concorrência em Aplicações Multi-Thread
Delphi Conference 2012 - Controlando a Concorrência em Aplicações Multi-ThreadDelphi Conference 2012 - Controlando a Concorrência em Aplicações Multi-Thread
Delphi Conference 2012 - Controlando a Concorrência em Aplicações Multi-ThreadMario Guedes
 
O futuro do elephante: as promessas do php para 2019
O futuro do elephante: as promessas do php para 2019O futuro do elephante: as promessas do php para 2019
O futuro do elephante: as promessas do php para 2019Cassio Santos
 
F I C+ + L P 05
F I C+ + L P 05F I C+ + L P 05
F I C+ + L P 05t34m0nana
 
tmn - Introdução ao JavaScript
tmn - Introdução ao JavaScripttmn - Introdução ao JavaScript
tmn - Introdução ao JavaScriptClaudio Gamboa
 
Testes unitários como ferramentas de design de código
Testes unitários como ferramentas de design de códigoTestes unitários como ferramentas de design de código
Testes unitários como ferramentas de design de códigoPaula Grangeiro
 

Mais procurados (18)

Introdução a JavaScript
Introdução a JavaScriptIntrodução a JavaScript
Introdução a JavaScript
 
BDD: Torne viva a documentação de seus sistemas
BDD: Torne viva a documentação de seus sistemasBDD: Torne viva a documentação de seus sistemas
BDD: Torne viva a documentação de seus sistemas
 
Delphi Parallel Programming Library
Delphi Parallel Programming LibraryDelphi Parallel Programming Library
Delphi Parallel Programming Library
 
Testes com javascript
Testes com javascriptTestes com javascript
Testes com javascript
 
Delphi Conference 2012 - Programação Baseado em Regras com RTTI
Delphi Conference 2012 - Programação Baseado em Regras com RTTIDelphi Conference 2012 - Programação Baseado em Regras com RTTI
Delphi Conference 2012 - Programação Baseado em Regras com RTTI
 
Xdebug seus problemas acabaram - tdc floripa 2017
Xdebug   seus problemas acabaram - tdc floripa 2017Xdebug   seus problemas acabaram - tdc floripa 2017
Xdebug seus problemas acabaram - tdc floripa 2017
 
JavaScript: agora é sério
JavaScript: agora é sérioJavaScript: agora é sério
JavaScript: agora é sério
 
Aula2
Aula2Aula2
Aula2
 
Processo de Desenvolvimento de Software - Linguagens Imperativas x Declarativas
Processo de Desenvolvimento de Software - Linguagens Imperativas x DeclarativasProcesso de Desenvolvimento de Software - Linguagens Imperativas x Declarativas
Processo de Desenvolvimento de Software - Linguagens Imperativas x Declarativas
 
Apostila de Introdução ao C#.net
Apostila de Introdução ao C#.netApostila de Introdução ao C#.net
Apostila de Introdução ao C#.net
 
Processo de Desenvolvimento de Software - Programação
Processo de Desenvolvimento de Software - ProgramaçãoProcesso de Desenvolvimento de Software - Programação
Processo de Desenvolvimento de Software - Programação
 
Delphi Conference 2012 - Controlando a Concorrência em Aplicações Multi-Thread
Delphi Conference 2012 - Controlando a Concorrência em Aplicações Multi-ThreadDelphi Conference 2012 - Controlando a Concorrência em Aplicações Multi-Thread
Delphi Conference 2012 - Controlando a Concorrência em Aplicações Multi-Thread
 
O futuro do elephante: as promessas do php para 2019
O futuro do elephante: as promessas do php para 2019O futuro do elephante: as promessas do php para 2019
O futuro do elephante: as promessas do php para 2019
 
Csharp
CsharpCsharp
Csharp
 
F I C+ + L P 05
F I C+ + L P 05F I C+ + L P 05
F I C+ + L P 05
 
tmn - Introdução ao JavaScript
tmn - Introdução ao JavaScripttmn - Introdução ao JavaScript
tmn - Introdução ao JavaScript
 
Zephir
ZephirZephir
Zephir
 
Testes unitários como ferramentas de design de código
Testes unitários como ferramentas de design de códigoTestes unitários como ferramentas de design de código
Testes unitários como ferramentas de design de código
 

Destaque

Crie sua Linguagem de Programação com XText
Crie sua Linguagem de Programação com XTextCrie sua Linguagem de Programação com XText
Crie sua Linguagem de Programação com XTextMichel Albonico
 
A linguagem de programação Erlang
A linguagem de programação ErlangA linguagem de programação Erlang
A linguagem de programação Erlangelliando dias
 
Geração de código linguagem c
Geração de código   linguagem cGeração de código   linguagem c
Geração de código linguagem cJefferson Bessa
 
Arquitetura do coprocessador Intel® Xeon Phi™ - Intel Software Conference 2013
Arquitetura do coprocessador Intel® Xeon Phi™ - Intel Software Conference 2013Arquitetura do coprocessador Intel® Xeon Phi™ - Intel Software Conference 2013
Arquitetura do coprocessador Intel® Xeon Phi™ - Intel Software Conference 2013Intel Software Brasil
 
Algoritmos Gulosos - Troco Mínimo
Algoritmos Gulosos - Troco MínimoAlgoritmos Gulosos - Troco Mínimo
Algoritmos Gulosos - Troco MínimoGabriel Albuquerque
 
Como criar seu próprio Framework
Como criar seu próprio FrameworkComo criar seu próprio Framework
Como criar seu próprio FrameworkHiarison Gigante
 
ΟΡΘΟΔΟΞΙΑ ΚΑΙ ΑΙΡΕΣΙΣ - ΕΚΔΟΣΕΙΣ ΠΕΡΙΟΔΙΚΟΥ Ο ΑΓΙΟΡΕΙΤΗΣ - ΑΘΗΝΑΙ 1982
ΟΡΘΟΔΟΞΙΑ ΚΑΙ ΑΙΡΕΣΙΣ - ΕΚΔΟΣΕΙΣ ΠΕΡΙΟΔΙΚΟΥ Ο ΑΓΙΟΡΕΙΤΗΣ - ΑΘΗΝΑΙ 1982ΟΡΘΟΔΟΞΙΑ ΚΑΙ ΑΙΡΕΣΙΣ - ΕΚΔΟΣΕΙΣ ΠΕΡΙΟΔΙΚΟΥ Ο ΑΓΙΟΡΕΙΤΗΣ - ΑΘΗΝΑΙ 1982
ΟΡΘΟΔΟΞΙΑ ΚΑΙ ΑΙΡΕΣΙΣ - ΕΚΔΟΣΕΙΣ ΠΕΡΙΟΔΙΚΟΥ Ο ΑΓΙΟΡΕΙΤΗΣ - ΑΘΗΝΑΙ 1982Spyridon Voykalis
 
Aula 8 - Lógica de Programação - Variáveis, Tipos de dados e Operadores
Aula 8 - Lógica de Programação - Variáveis, Tipos de dados e OperadoresAula 8 - Lógica de Programação - Variáveis, Tipos de dados e Operadores
Aula 8 - Lógica de Programação - Variáveis, Tipos de dados e OperadoresAndré Constantino da Silva
 
JavaFX: A nova biblioteca gráfica da plataforma Java
JavaFX: A nova biblioteca gráfica da plataforma JavaJavaFX: A nova biblioteca gráfica da plataforma Java
JavaFX: A nova biblioteca gráfica da plataforma JavajesuinoPower
 
Javascript levado a serio
Javascript levado a serioJavascript levado a serio
Javascript levado a serioJaydson Gomes
 
Campanha da fraternidade 2017 cf 2017 biomas brasileiros resumo do texto base
Campanha da fraternidade 2017 cf 2017 biomas brasileiros resumo do texto baseCampanha da fraternidade 2017 cf 2017 biomas brasileiros resumo do texto base
Campanha da fraternidade 2017 cf 2017 biomas brasileiros resumo do texto baseAntonio De Assis Ribeiro
 

Destaque (12)

Crie sua Linguagem de Programação com XText
Crie sua Linguagem de Programação com XTextCrie sua Linguagem de Programação com XText
Crie sua Linguagem de Programação com XText
 
A linguagem de programação Erlang
A linguagem de programação ErlangA linguagem de programação Erlang
A linguagem de programação Erlang
 
Geração de código linguagem c
Geração de código   linguagem cGeração de código   linguagem c
Geração de código linguagem c
 
Arquitetura do coprocessador Intel® Xeon Phi™ - Intel Software Conference 2013
Arquitetura do coprocessador Intel® Xeon Phi™ - Intel Software Conference 2013Arquitetura do coprocessador Intel® Xeon Phi™ - Intel Software Conference 2013
Arquitetura do coprocessador Intel® Xeon Phi™ - Intel Software Conference 2013
 
Algoritmos Gulosos - Troco Mínimo
Algoritmos Gulosos - Troco MínimoAlgoritmos Gulosos - Troco Mínimo
Algoritmos Gulosos - Troco Mínimo
 
Como criar seu próprio Framework
Como criar seu próprio FrameworkComo criar seu próprio Framework
Como criar seu próprio Framework
 
Javascript para adultos
Javascript para adultosJavascript para adultos
Javascript para adultos
 
ΟΡΘΟΔΟΞΙΑ ΚΑΙ ΑΙΡΕΣΙΣ - ΕΚΔΟΣΕΙΣ ΠΕΡΙΟΔΙΚΟΥ Ο ΑΓΙΟΡΕΙΤΗΣ - ΑΘΗΝΑΙ 1982
ΟΡΘΟΔΟΞΙΑ ΚΑΙ ΑΙΡΕΣΙΣ - ΕΚΔΟΣΕΙΣ ΠΕΡΙΟΔΙΚΟΥ Ο ΑΓΙΟΡΕΙΤΗΣ - ΑΘΗΝΑΙ 1982ΟΡΘΟΔΟΞΙΑ ΚΑΙ ΑΙΡΕΣΙΣ - ΕΚΔΟΣΕΙΣ ΠΕΡΙΟΔΙΚΟΥ Ο ΑΓΙΟΡΕΙΤΗΣ - ΑΘΗΝΑΙ 1982
ΟΡΘΟΔΟΞΙΑ ΚΑΙ ΑΙΡΕΣΙΣ - ΕΚΔΟΣΕΙΣ ΠΕΡΙΟΔΙΚΟΥ Ο ΑΓΙΟΡΕΙΤΗΣ - ΑΘΗΝΑΙ 1982
 
Aula 8 - Lógica de Programação - Variáveis, Tipos de dados e Operadores
Aula 8 - Lógica de Programação - Variáveis, Tipos de dados e OperadoresAula 8 - Lógica de Programação - Variáveis, Tipos de dados e Operadores
Aula 8 - Lógica de Programação - Variáveis, Tipos de dados e Operadores
 
JavaFX: A nova biblioteca gráfica da plataforma Java
JavaFX: A nova biblioteca gráfica da plataforma JavaJavaFX: A nova biblioteca gráfica da plataforma Java
JavaFX: A nova biblioteca gráfica da plataforma Java
 
Javascript levado a serio
Javascript levado a serioJavascript levado a serio
Javascript levado a serio
 
Campanha da fraternidade 2017 cf 2017 biomas brasileiros resumo do texto base
Campanha da fraternidade 2017 cf 2017 biomas brasileiros resumo do texto baseCampanha da fraternidade 2017 cf 2017 biomas brasileiros resumo do texto base
Campanha da fraternidade 2017 cf 2017 biomas brasileiros resumo do texto base
 

Semelhante a Criando sua própria linguagem de programação

Semelhante a Criando sua própria linguagem de programação (20)

O que mudou no Ruby 1.9
O que mudou no Ruby 1.9O que mudou no Ruby 1.9
O que mudou no Ruby 1.9
 
Palestra cbq
Palestra cbqPalestra cbq
Palestra cbq
 
Aula c++ estruturas de dados
Aula c++   estruturas de dadosAula c++   estruturas de dados
Aula c++ estruturas de dados
 
Programação Orientada a Testes
Programação Orientada a TestesProgramação Orientada a Testes
Programação Orientada a Testes
 
JS Experience 2017 - WebAssembly na Prática
JS Experience 2017 - WebAssembly na PráticaJS Experience 2017 - WebAssembly na Prática
JS Experience 2017 - WebAssembly na Prática
 
Redes 1 - Sockets em C#
Redes 1 - Sockets em C#Redes 1 - Sockets em C#
Redes 1 - Sockets em C#
 
Introdução ao CMake
Introdução ao CMakeIntrodução ao CMake
Introdução ao CMake
 
Minicurso Ruby on Rails
Minicurso Ruby on RailsMinicurso Ruby on Rails
Minicurso Ruby on Rails
 
SOLID através de BDD: um guia prático para rubistas
SOLID através de BDD: um guia prático para rubistasSOLID através de BDD: um guia prático para rubistas
SOLID através de BDD: um guia prático para rubistas
 
Ruby & Rails
Ruby & RailsRuby & Rails
Ruby & Rails
 
TypeScript - Campus party 2013
TypeScript - Campus party 2013TypeScript - Campus party 2013
TypeScript - Campus party 2013
 
Escrevendo modulos python com rust
Escrevendo modulos python com rustEscrevendo modulos python com rust
Escrevendo modulos python com rust
 
Minicurso Python
Minicurso PythonMinicurso Python
Minicurso Python
 
Trabalho
TrabalhoTrabalho
Trabalho
 
Minicurso kotlin UTFPR
Minicurso kotlin UTFPR Minicurso kotlin UTFPR
Minicurso kotlin UTFPR
 
Minicurso kotlin no desenvolvimento mobile - UTFPR
Minicurso kotlin no desenvolvimento mobile - UTFPRMinicurso kotlin no desenvolvimento mobile - UTFPR
Minicurso kotlin no desenvolvimento mobile - UTFPR
 
Cool 3 assembly para linux
Cool 3   assembly para linuxCool 3   assembly para linux
Cool 3 assembly para linux
 
Microsoft S2B - C# ASP.NET
Microsoft S2B - C# ASP.NETMicrosoft S2B - C# ASP.NET
Microsoft S2B - C# ASP.NET
 
Introdução Ruby 1.8.7 + Rails 3
Introdução Ruby 1.8.7 + Rails 3Introdução Ruby 1.8.7 + Rails 3
Introdução Ruby 1.8.7 + Rails 3
 
Oficial
OficialOficial
Oficial
 

Criando sua própria linguagem de programação

  • 1. Criando sua própria linguagem de programação Dev In Sampa São Paulo, 28 de novembro de 2009
  • 2. Por quê? Cada nova linguagem é um campo aberto para livre experimentação Compilação é uma arena em que todas as suas habilidades são necessárias
  • 3. A verdade verdadeira “Por que escrever um programa se você pode escrever um programa para escrever um programa?” — Autor desconhecido A verdade verdadeira é que é divertido ;)
  • 4. Na prática Você pode usar um parser mais sofisticado para suas DSLs Você pode resolver problemas de portar código de um domínio para outro com um tradutor Você pode usar um interpretador para construir geradores mais sofisticados
  • 5. Na pior das hipóteses... “Se uma linguagem não é capaz de afetar o modo como você pensa sobre programação, não vale a pena aprendê-la” — Alan Perlis
  • 6. Um pouco de conceitos
  • 7. Linguagem “Uma notação para escrever programas, que são especificações para a computação de uma algoritmo” — Wikipedia
  • 8. Elementos Sintaxe: o que é escrito, descrita em uma gramática formal Semântica: o que isso significa, especificado em termos de formalizações de compilação e execução
  • 9. Gramáticas formais Value ← [0-9]+ / '(' Expr ')' Product ← Value (('*' / '/') Value)* Sum ← Product (('+' / '-') Product)* Expr ← Sum
  • 10. Do texto à execução CÓDIGO FONTE SAÍDA PARSING ANÁLISE LÉXICA COMPILADOR INTERPRETADOR TRADUTOR TOKENS ANÁLISE SINTÁTICA AST
  • 12. Inspiração Sintaxe baseada em Smalltalk e IO Slot-based como Self Forte e dinamicamente tipada Interpretada, via bytecodes
  • 13. Mirror World mirrorInto: "Fib". Fib set: "of:" to: [ n | n <= 2 ifTrue: [ 1. ] ifFalse: [ (of: n - 1) + (of: n - 2). ]. ]. (Fib of: 10) transcribeAndBreak.
  • 14. Análise Via Treetop, um packrat parser em Ruby PEGs Análise versus geração Sem ambigüidades Gera uma árvore sintática que é compilada para uma representação em bytecodes
  • 15. AST #1 (Fib of: 2 + 3) transcribeAndBreak.
  • 16. AST #2 (Fib of: 2 + 3) transcribeAndBreak.
  • 17. Bytecode push 3 push 2 send + load Fib send of: send transcribeAndBreak pop
  • 19. Blocos básicos grammar Mirror rule statements (spaces? statement spaces? "." spaces?)* <Statements> end rule statement message_expression end rule message_expression keyword_expression / binary_expression / unary_expression end # ... end
  • 20. Keywords grammar Mirror rule keyword_expression variable:binary_expression? keywords:(spaces? keyword spaces expression:binary_expression)+ <KeywordExpression> end # Account deposit: 100 from: user. # ... end
  • 21. Expressões binárias grammar Mirror rule binary_expression variable:unary_expression spaces? selector:binary_selector spaces? expression:binary_expression <BinaryExpression> / unary_expression end # 2 + 3 * (account balance). # ... end
  • 22. Expressões unárias grammar Mirror rule unary_expression variable:primary selectors:(spaces selector:identifier !colon)+ <UnaryExpression> / primary end # (Account current balance) transcribeAndBreak. # ... end
  • 23. Juntando as peças irb> MirrorParser.new.parse('2 + 3.') SyntaxNode+Statements offset=0, "2 + 3." (build): SyntaxNode+Statements0 offset=0, "2 + 3." (statement): SyntaxNode+BinaryExpression0+BinaryExpression offset=0, "2 + 3": SyntaxNode+IntegerLiteral offset=0, "2" (build): SyntaxNode offset=0, "2" SyntaxNode+Spaces2 offset=1, " ": SyntaxNode offset=2, "+": SyntaxNode offset=2, "+" SyntaxNode+IntegerLiteral offset=4, "3" (build): SyntaxNode offset=4, "3"
  • 25. Blocos básicos # rule statements # (spaces? statement spaces? "." spaces?)* <Statements> # end module Statements def build elements.collect do |element| Ast::Statement.new(element.statement.build) end end end class Statement def initialize(expression) @expression = expression end end
  • 26. Expressões binárias # rule binary_expression # variable:unary_expression spaces? # selector:binary_selector spaces? # expression:binary_expression <BinaryExpression> / # unary_expression module BinaryExpression def build Ast::Message.new(variable.build, selector.text_value, expression.build) end end class Message def initialize(target, selector, *arguments) @target = target @selector = selector @arguments = arguments end end
  • 27. Juntando as peças irb> MirrorParser.new.parse('2 + 3.').build [ #<Ast::Statement @expression = #<Ast::Message @selector = "+", @target = #<Ast::Literal @value = "2", @type = :integer>, @arguments = [#<Ast::Literal @value = "3", @type = :integer>]>> ]
  • 29. Double dispatch class CodeGenerator def initialize(ast) @ast = ast end def generate @ast.collect { |statement| generate_any(statement) }.flatten end def generate_any(ast) send("generate_#{ast.class.name.demodulize.underscore}", ast) end # ... end
  • 30. Blocos básicos class CodeGenerator def generate_statement(ast) ([generate_any(ast.expression)] + [Bytecode::Pop.new]).flatten end def generate_variable(ast) Bytecode::Load.new(ast.name) end # ... end
  • 31. Mensagens class CodeGenerator def generate_message(ast) instructions = [] ast.arguments.reverse.each do |argument| instructions += [generate_any(argument)].flatten end instructions += [generate_any(ast.target)].flatten instructions << Bytecode::Message.new(ast.selector) instructions end # ... end
  • 32. Bytecodes class Pop def inspect "pop" end end class Message def initialize(selector) @selector = selector @selector_name = get_selector_name(selector) @selector_method = get_selector_method(selector) @arity = get_selector_arity(selector) end # ... end
  • 33. Juntando as peças irb> ast = MirrorParser.new.parse('2 + 3.').build irb> CodeGenerator.new(ast).generate [ push 3, push 2, send +, pop ]
  • 35. Containers & Slots ACCOUNT BALANCE 0 DEPOSIT: BLOCK CONTEXT WITHDRAW: BLOCK CONTEXT USER USER
  • 36. Universe & World UNIVERSE WORLD WORLD MIRRORINTO: ERROR SET: TO:
  • 37. Detalhes O envio de mensagens acontece em um contexto que é gerado para cada mensagem Blocos geram contextos empilhados O interpretador percorre os contextos até encontrar o objeto apropriado para enviar a mensagem
  • 39. Máquina Virtual class VM def initialize(instructions) @instructions = instructions end def run reset_instruction_pointer while has_instructions? execute(next_instruction) end end # ... end
  • 40. Máquina Virtual class VM def execute(instruction) case instruction when Bytecode::Implicit stack_push_and_wrap(current_context) when Bytecode::Pop stack.pop when Bytecode::Push stack_push_and_wrap(instruction.value) when Bytecode::Load stack_push_and_wrap(walk_contexts(instruction.name)) # ... end end end
  • 41. Juntando as peças irb> Interpreter.run(true, "World offload: 2 + 2.") [4] irb> Interpreter.run(true, "World offload: [ 2 + 2. ] value.") [4]
  • 43. Próximos passos Arrays Inlining de mensagens comuns Primitivas: + - * / at: at:put: ifTrue:ifFalse et al to:do et al Melhor uso de blocos
  • 44. LLVM Uma estratégia de compilação Um conjunto de instruções virtualizado Uma infra-estrutura de compilação Um conjunto de ferramentas
  • 45. LLVM Efetivamente uma DSL para geração de código intermediário otimizado e portável Estático ou JIT Usado por MacRuby, Rubinius, Unladden Swallow e outros
  • 46. LLVM: Uso Transformar slots de código em funções Transformar closures em funções quando não fizer sentido que os mesmos sejam inline Compilar o próprio interpretador para ser parcialmente jitted
  • 47. LLVM: Uso module = LLVM::Module.new("mirror") type = Type::function(MACHINE_WORD, []) function = module.get_or_insert_function("main", type) entry_block = function.create_block exit_block_true = function.create_block exit_block_false = function.create_block builder = entry_block.builder cmp = builder.icmp_sgt(-1.llvm, 1.llvm) builder.cond_br(cmp, exit_block_true, exit_block_false)
  • 48. LLVM: Uso builder = exit_block_true.builder builder.return(1.llvm) builder = exit_block_false.builder builder.return(0.llvm) ExecutionEngine.get(module) ExecutionEngine.run_autoconvert(function)