INTRODUÇÃO A COMPILADORES Visão Macro Cláudio, Ibraim, Robson, Rafael O PROBLEMA: IMPLEMENTAR linguagens de ALTO NÍVEL em um computador cuja linguagem de máquina é de NÍVEL MUITO MAIS BAIXO. A SOLUÇÃO: TRADUZIR essas LINGUAGENS usando a própria LINGUAGEM DE MÁQUINA DA CPU. TRADUTOR É um programa que traduz um programa fonte escrito em uma linguagem qualquer (linguagem fonte) para um programa objeto equivalente escrito em outra linguagem (linguagem objeto) Linguagem Fonte Tradutor Linguagem Objeto COMPILADOR É um TRADUTOR em que a LINGUAGEM FONTE é uma linguagem DE ALTO NÍVEL e a LINGUAGEM OBJETO é uma linguagem DE BAIXO NÍVEL (assembly ou máquina) Linguagem Fonte (Alto Nível) Compilador Linguagem Objeto (assembly ou máquina) Programa Fonte Compilador Análise Análise Léxica Análise Sintática Análise Semântica Síntese Geração de Código Intermediário Otimização de Código Geração de Código Programa Objeto DESCOMPILADOR É um programa que realiza a OPERAÇÃO INVERSA do COMPILADOR, ou seja, da LINGUAGEM OBJETO ele EXTRAI a LINGUAGEM FONTE. Linguagem Objeto (assembly ou máquina) Descompilador Linguagem Fonte (Alto Nível) INTERPRETADOR • Processa o código fonte, analisando um comando a cada vez que esse deve ser executado. • Processamento é feito junto os dados de entrada, em tempo de execução. • Não produz um programa objeto. 2 1 Determinar a ação a ser executada. Obter o próximo comando a ser executado. Buscar os dados necessários. 3 Executar a ação. Tratar o resultado. INTERPRETADOR Programa Fonte Interpretador Dados Interpretação pura Saída Vantagens Compiladores Interpretadores Desvantagens Execução mais rápida Várias etapas de tradução Permite a otimização do código fonte Necessita de mais memória para a sua execução Programa fonte não precisa ser fornecido ao utilizador Processo de correção de erros e depuração é mais demorado Depuração do programa é mais simples Execução do programa é mais lenta Consome menos memória Necessário fornecer o programa fonte ao utilizador Resultado imediato do programa ou rotina desenvolvida MONTADOR (assembler) • É um tradutor que mapeia instruções em linguagem simbólica (assembly) para instruções de linguagem de máquina. • Geralmente os comandos seguem a relação 1:1. MONTADOR (assembler) Linguagem simbólica Montador Linguagem de máquina • Alguns compiladores produzem esse trabalho diretamente. Jasmin (Java Assembler Interface) • Montador de assembly JVM para arquivos class. • Recebe um arquivo texto como entrada. Linguagem simbólica Jasmin .class DESMONTADOR (dissassembler) • Um desmontador é um programa que converte código de máquina em código de montagem (assembly). • Constantes simbólicas, comentários e rótulos de endereçamento não são recuperados. MÁQUINA VIRTUAL • Uma máquina virtual é um computador fictício criado por um programa de simulação. Estes programas podem simular um computador de arquitetura diferente. • Um bom exemplo para maquina virtual no contexto de compiladores e a JVM COMPILADOR HÍBRIDO • Um compilador é um programa que, a partir de um código escrito em uma linguagem cria um programa semanticamente equivalente, porém escrito em outra linguagem. • Um compilador hibrido tem o papel de converter o código fonte em um código chamado de bytecode, que é uma linguagem de baixo nível. COMPILADOR HÍBRIDO • O bytecode irá ser interpretado numa máquina virtual, que fará a execução. O • bytecode é um estágio intermédio entre o código-fonte e a aplicação final. CARREGADOR • O carregador coleta os programas traduzidos separadamente e liga-os em um único módulo e depois carrega o modulo absoluto na memória principal, substituindo os endereços relativos ao módulo de carga por endereços reais de memória. Processo de Execução Editor Compilador Carregador de classes disco O programa é criado em um editor e armazenado no disco disco Compilador gera os bytecodes e os armazena no disco _________ _________ _________ ___ O carregador de classes coloca os bytecodes na memória memória disco Verificador de bytecodes _________ _________ _________ ___ O verificador de bytecodes confirma se todos os bytecodes estão corretos e se não violam as restrições de segurança da linguagem Java memória Interpretador _________ _________ _________ ___ memória O interpretador lê os bytecodes e executa o programa COMPILER-TO-COMPILER • São softwares capaz de gerar através de outras linguagens de alto nível outros compiladores • Exemplo o JavaCC, que passo o código fonte para Java e depois segue o fluxo normal de um programa na plataforma. EXTENSÕES DE ARQUIVOS • Arquivos .java – Arquivos utilizado na construção de programas na linguagem java. • Arquivos .class – Arquivos pré-compilados – Arquivos a serem interpretados pela JVM • Arquivos .jj – Geração de novas linguagens. • Arquivos .j – Similar a assembly. Linguagem fonte, Intermediária e Destino. • Fonte – Linguagem de fácil interpretação para um programador. – Linguagem não compilada. • Intermediária – Linguagem pré-compilada – Bytecode – Interpretada pela Máquina Virtual • Linguagem destino – Geralmente linguagem de máquina. Exemplos de arquivos 1/6 • Extensão .java public class Exemplo01 { public static void main(String args[]) { double a,b; a = 40 + 30; b = a + 20; } } Exemplos de arquivos 2/6 • Extensão .jj /* Analex.jj - Analisador Léxico */ options { JDK_VERSION = "1.5"; DEBUG_PARSER = false; DEBUG_TOKEN_MANAGER = false; } PARSER_BEGIN(Analex) import java.io.*; public class Analex { public static void main(String args[]) throws ParseException { try { Analex x = new Analex(new FileInputStream(args[0])); x.S(); } catch(FileNotFoundException e) { System.out.println("Arquivo não encontrado"); } } } Exemplos de arquivos 3/6 PARSER_END(Analex) SKIP : { " " | "\t" | "\r" | "\n" } SKIP : { "/*" : comentario } <comentario> SKIP: { "*/" : DEFAULT | <~[]> } TOKEN [IGNORE_CASE] : { < BREAK: "break" > } TOKEN : { < IDENT: "_"(["a"-"z","A"-"Z","_","0"-"9"] )* > | < INT: (["0"-"9"])+("L"|"l")? > } Exemplos de arquivos 4/6 TOKEN: { < VOGAIS: (["a","e","i","o","u"]){3} > | < ARQ: "\"" ((~[".", ":", ";", "\\"]) {1,8} ( "." (~[".", ":", ";", "\\"]){1,3})?) "\"" > } JAVACODE void S() { Token t; do { t = getNextToken(); System.out.println(tokenImage[t.kind]+"\t"+t.image); } while(t.kind != EOF); } Exemplos de arquivos 5/6 • Arquivo fonte: a := XIX + IV + II; b := XXXVIII; soma := a + b; exibe soma; • Arquivo '.j' .source prog_destino.java .class public prog_destino .super java/lang/Object .method public <init>()V .limit stack 1 .limit locals 1 aload_0 invokespecial java/lang/Object/<init>()V return .end method Exemplos de arquivos 6/6 .method public static main([Ljava/lang/String;)V .limit stack 4 .limit locals 100 ldc2_w 19.0 ldc2_w 4.0 dadd ldc2_w 2.0 dadd dstore 1 ldc2_w 38.0 dstore 3 dload 1 dload 3 dadd dstore 5 getstatic java/lang/System/out Ljava/io/PrintStream; dload 5 invokevirtual java/io/PrintStream/println(D)V return .end method • Execução: 63.0