



Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Encontra documentos específicos para os exames da tua universidade
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
As noções básicas sobre o desenho e implementação de linguagens de programação durante um semestre. Aborda conceitos essenciais para o desenvolvimento de linguagens de programação e a resolução de problemas computacionais. O texto também explora a diferença entre interpretadores e compiladores, e os seus respectivos usos e vantagens.
Tipologia: Esquemas
1 / 6
Esta página não é visível na pré-visualização
Não perca as partes importantes!




Esta unidade curricular pretende transmitir ao longo de um semestre as noções fundamentais sobre o desenho e implementação de linguagens de programação. Muitos dos conceitos estudados são essenciais, não só no de- senvolvimento de linguagens de programação, mas também na resolução de problemas de forma computacional [Win06]. Pretende-se ao mesmo tempo aprofundar o conhecimento acerca do funcionamento de linguagens de progra- mação já existentes através do conhecimento profundo dos seus mecanismos de construção.
If you don’t understand interpreters, you can still write programs; you can even be a competent programmer. But you can’t be a master. (Hal Abelson, in prefácio de [FW08])
Durante esta unidade curricular serão apresentados os componentes fun- damentais de construção de linguagens de programação, o seu modelo de execução, verificação e transformação, tendo como foco uma linguagem de alto nível de abstracção. Ao longo de um semestre serão desenvolvidos de forma incremental algoritmos interpretadores, que serão os veículos privilegi- ados para a aprendizagem da semântica de linguagens, dos sistemas de tipos e das técnicas de compilação. Nesta primeira versão das notas de apoio serão descritos brevemente os tópicos abordados em aula, algum código de apoio, e alguns apontadores para outros recursos de estudo e aprofundamento de conhecimentos. Nesta primeira aula descreve-se a arquitetura geral dos interpretadores e compiladores e a sua utilidade no contexto de um sistema de software. Estes tópicos podem ser mais explorados na bibliografia recomendada (nomeada- mente em [AP02, AVAU06]).
Luís Caires, João Costa Seco ICL 2012-2013^31
compiler
Source Program int f(int x) { }^ return^ x+1;
Executable program movl movl %edi,-4(%rbp), -4(%rbp) %eax addl movl $1,%eax, %eax -12(%rbp) movl movl -12(%rbp),%eax, -8(%rbp) %eax movl popq -8(%rbp),%rbp %eax ret
machine
Input data 1001010101010101 (^00101010101001010101010101010101) (^01010101011010111101011010111010) 0110001110101001
Output data 1001010101010101 (^00101010101001010101010101010101) (^01010101011010111101011010111010) 0110001110101001
Figura 1: Compilador
1 Interpretadores / compiladores
Qual a diferença entre um compilador e um interpretador? o que é uma lin- guagem máquina? ou uma linguagem intermédia? o que é um JIT compiler? Cada uma destas ferramentas tem a sua utilidade específica e contexto de utilização adequado. Os interpretadores e compiladores são essencialmente programas cujo comportamento (ou output) não está estabelecido à partida, o seu resultado é definido através de um programa dado como input, escrito numa linguagem de programação. São programas cujos dados são outros programas. Dentro desta categoria encontram-se ainda programas como ferramentas de verifica- ção de programas, ambientes de desenvolvimento, etc. Invariavelmente, os dados de entrada de um compilador e de um interpre- tador é um programa expresso numa linguagem de programação (linguagem fonte). O mais usual é um programa ser expresso por intermédio de um texto, podendo ser expresso de outras formas, usando linguagens visuais por exemplo. Embora a maioria dos conceitos sejam genéricos, no contexto desta unidade curricular focamos em linguagens expressas em texto. A distinção entre interpretadores e compiladores faz-se essencialmente a nível da forma de execução e interação que proporcionam. Existe depois uma miríade de alternativas e combinações sobre as verificações que são fei- tas sobre o código, e sobre a eficiência na execução, e na produtividade da atividade de programação. Os compiladores, cuja interação é representada na Figura 1, transformam
Luís Caires, João Costa Seco ICL 2012-2013^32
compiler
Source Program int f(int return x) x+1;{ }
intermediate language define readnone entry: i32 ssp @f(i32 { %x) nounwind }^ %0^ ret^ =^ i32add^ %0nsw^ i32^ %x,
virtual machine
Input data (^10010101010101010010101010100101) (^01010101010101010101010101101011) (^11010110101110100110001110101001)
Output data (^10010101010101010010101010100101) (^01010101010101010101010101101011) (^11010110101110100110001110101001)
Just in time compiler
Executable code movl movl %edi,-4(%rbp), -4(%rbp) %eax addl movl $1,%eax, %eax -12(%rbp) movl movl -12(%rbp),%eax, -8(%rbp) %eax movl popq -8(%rbp),%rbp %eax ret
Figura 3: Interpretador com compilador JIT
A flexibilidade oferecida pela utilização de um interpretador (da lingua- gem intermédia) é aproveitada no caso das linguagens Java e C# para pos- sibilitar a portabilidade de código. No caso de linguagens como OCaml, Haskell ou Scala, à flexibilidade dada pelo modo interpretação, acrescenta uma verificação de tipos completa e optimizações como a utilização de tail recursion. Na sua estrutura interna, os compiladores e interpretadores partilham alguns componentes, nomeadamente no seu front-end. Na Figura 4, são des- critos os blocos que tipicamente compõem o processo de transformação feito por um interpretador. Os dois primeiros blocos, análise lexicográfica e sintá- tica, transformam o formato de entrada (texto) numa representação interna do programa (tipo de dados) que pode ser mais facilmente tratado por um algoritmo (esta representação será o tema da próxima aula). Essa represen- tação, que pode ou não ser analisada e anotada, é depois interpretada. A arquitetura interna de um compilador é composta por um front-end como aquele descrito para os interpretadores, e por mais duas camadas. Uma camada intermédia e uma camada de saída. A camada intermédia
Luís Caires, João Costa Seco ICL 2012-2013^37
Análise Lexicográfica
Source Program int f(int x) { }^ return^ x+1;
Output data (^10010101010101010010101010100101) (^01010101010101010101010101101011) Análise Sintática^11010110101110100110001110101001
Análise Semântica
tokens
AST
AST anotada
Input data 1001010101010101 (^00101010101001010101010101010101) (^01010101011010111101011010111010) 0110001110101001
Interpretador
Figura 4: Arquitetura de um interpretador
de um compilador típico, faz o tratamento de uma linguagem intermédia. Esta divisão entre front-end e back-end, com um ponto comum numa ca- mada intermédia, permite com uma única ferramenta, criar uma família de compiladores. Compilando e integrando um conjunto de linguagens, e po- dendo produzir código de qualquer destas linguagens para um conjunto de processadores. A Figura 5 mostra os principais blocos que compõem um compilador. Os componentes do front-end de um compilador são basicamente os mesmos do que os de um interpretador. A diferença começa na geração de código numa linguagem intermédia que permite normalmente a realização de operações de análise e optimização de código, e que é agnóstica quanto ao processador para o qual se vai gerar código nativo. O back-end do processador pode então gerar código específico para diferentes processadores, tirando partido das particularidades de cada um.