Estudos de Linguagens de Programação - Revisão (marinho.mlm@gmail.com) O que é uma Linguagem de Programação? Linguagem usada por uma pessoa para expressar um processo através do qual um computador pode resolver um problema. 1
Por que estudar Conceitos de Linguagens de Programação? Aumento da capacidade de expressar idéias. Melhor uso de uma LP. Melhor escolha de uma LP. Maior facilidade em aprender novas LPs. Maior habilidade em projetar novas LPs. Possibilitar o avanço global da computação. Entender a importância da implementação. Domínios de Programação Aplicações Científicas Assembly, FORTRAN, Algol 60 Aplicações Comerciais Inteligência Artificial LISP (McCarthy, 1959), Linguagem funcional. Prolog (Clocksin e Mellish, 1970), Linguagem Lógica. Programação de Sistemas Construção de Scripts (Scripting Languages) 2
Classificação das LPs As LPs podem ser classificadas de diversas formas, algumas são quanto ao: Nível de Utilização; Propósito; Paradigma; Classificação das LPs Quanto ao nível de utilização classificam-se em: Linguagens de Máquina; Linguagens de Baixo Nível; Linguagens de Alto Nível; FORTRAN, Algol, COBOL, Pascal, Python, C++. 3
Classificação das LPs Quanto ao propósito (domínio de aplicação): Aplicações Comerciais Cobol, Clipper, Mumps, Natural; Desenvolvimento de Software Básico C, C++, Pascal; Desenvolvimento de Sistemas Especialistas Lisp, Prolog; Educacionais: Logo, Basic; Aplicações Científicas: Fortran, Algol; Propósito Específico Simula, HTML, VRML, Java, LEX, YACC. Métodos de Implementação Compilação Interpretação Pura Sistemas de Implementação Híbridos 4
Compilação Interpretação Pura 5
Sistemas Híbridos Comparativo Compilação Eficiência - Execução rápida dos programas, pois são executados diretamente em linguagem de máquina. Problemas com Portabilidade. Interpretação Pura Flexibilidade e Portabilidade do código-fonte. Problemas de eficiência, normalmente 10 a 100 vezes menor comparada ao compilado e Maior Consumo de Memória. Raramente Usada. Híbrido Une Vantagens dos Outros Métodos. 6
Critérios de Avaliação das Linguagens de Programação Princípais Critérios de Avaliação das Linguagens de Programação Legibilidade Capacidade de Escrita Confiabilidade 7
Legibilidade Facilidade de leitura e entendimento de programas escritos em uma determinada linguagem. Quanto maior a legibilidade de programas, mais fácil é a manipulação dos mesmos para correção, extensão e melhoramento (manutenção) Legibilidade Características que contribuem para legibilidade: Simplicidade Ortogonalidade Instruções de Controle Tipos e Estruturas de Dados 8
Legibilidade - Simplicidade Linguagem com grande número de componentes básicos é mais difícil de ser aprendida do que uma com poucos desses componentes. Programadores acabam ignorando componentes de linguagens complexas. Legibilidade é afetada quando programadores se defrontam com programas que usam componentes que foram ignorados. Legibilidade - Simplicidade Multiplicidade de formas com um mesmo significado Em C: count = count + 1; count += 1; count++; ++count; Sobrecarga de operadores: único símbolo tem mais de um significado Em C: + Para somar números inteiros como para ponto-flutuante. * para multiplicação de números quanto para operações de manipulação de ponteiros 9
Legibilidade - Ortogonalidade Um conjunto relativamente pequeno de construções primitivas pode ser combinado em um número relativamente pequeno de maneiras para construir as estruturas de controle e de dados da linguagem. Qualquer possível combinação de primitivas é legal e tem significado. Exemplo: Suponha uma linguagem com quatro tipos de dados (int, float, double, char) e dois operadores de tipos (ponteiros e arrays). Ponteiros devem ser capazes de apontar para qualquer tipo de variável ou estrutura de dados. Legibilidade - Instruções de Controle Uso de comandos goto Um programa que pode ser lido de cima para baixo é mais fácil de entender do que um programa que obriga o leitor a dar saltos para seguir o fluxo da execução. 10
Legibilidade - Instruções de Controle Em algumas linguagens, goto é necessário: Legibilidade - Tipos de Dados Tipos de dados facilitam a identificação do uso de variáveis e dos domínios de valores que podem representar. Por exemplo, em C não existem tipos booleanos, ao contrário do Pascal: Em C: Em Pascal: ocorreu_erro_de_leitura = 1; ocorreu_erro_de_leitura := true; 11
Legibilidade - Estruturas Estruturas fornecem métodos para representar valores relacionados de uma forma mais legível, do que por exemplo usando coleções de arrays separados. Capacidade de Escrita Medida da facilidade para criar programas destinado a um domínio de problema escolhido. A maioria das características que afetam legibilidade também afetam a capacidade de escrita Escrever um programa exige uma releitura freqüente do que já foi escrito. Domínio dos problemas influência no julgamento da capacidade de escrita de uma linguagem COBOL para produção de relatórios comerciais. 12
Confiabilidade Considera-se um programa confiável quando executa o que foi atribuído de modo esperado, sobre quaisquer condições. Características que contribuem para a confiabilidade: Verificação de Tipos Tratamento de Exceções Aliasing Legibilidade e Capacidade de Escrita Nomes, Vinculações, Verificação de Tipos e Escopos 13
Introdução Uma variável de programa é uma abstração de uma célula de memória ou de um conjunto de células de memória do computador. Introdução Atributos de uma variável: Nome; Endereço; Tipo; Valor; Tempo de Vida; Escopo; 14
Nomes Seqüência de caracteres usada para identificar alguma entidade de um programa Variáveis, rótulos, subprogramas, parâmetros formais,... Nome Identificador A mudança das linguagens de máquina para Assembly foi uma substituição dos endereços de memória numéricos por nome Aumenta a legibilidade, capacidade de escrita e modificabilidade Nomes - Palavras Especiais São utilizadas em LPs para tornar os programas mais legíveis ao dar nome para ações a serem executadas e separar entidades sintáticas; Palavra especial pode ser: Palavra-chave Palavra Reservada Palavra Pré-definida 15
Nomes - Palavras Especiais Palavra-chave pode ser usada como nome Em FORTRAN: REAL APPLE REAL é palavra-chave que indica instrução declarativa REAL = 3.4 REAL indica nome de variável Compiladores FORTRAN e leitores de seus programas devem reconhecer a diferença entre nomes e palavras-chave pelo contexto INTEGER REAL REAL INTEGER Problemas de Legibilidade Nomes - Palavras Especiais Palavra Reservada é especial e não pode ser usada como nome Em C e Java: do, while, for, if,... Palavra Pré-definida está entre palavra reservada e nome definido pelo usuário Tem significado pré-definido, mas pode ser redefinido pelo usuário Em C: printf, scanf definidas em stdio.h 16
Endereço de uma Variável É o endereço da posição de memória associada com a variável É chamado de seu valor-l, que é o exigido quando a variável aparece no lado esquerdo (left side) de uma instrução de atribuição Exemplo: float num = 3.14; Endereço de uma Variável - Aliases Quando mais de um nome de variável pode ser utilizado para acessar uma única localização de memória, os nomes são chamados de aliases C/C++: Uniões, Ponteiros. Ada e Pascal: Registros Variantes e Ponteiros. Comprometem a legibilidade Variável pode ter seu valor modificado por uma atribuição a uma variável diferente 17
Endereço de uma Variável - Aliases Exemplo C/C++: Tipo de uma Variável Determina a faixa de valores que uma determinada variável pode assumir e o conjunto de operações definidas para os valores daquele tipo; Exemplo: INTEGER de FORTRAN Valores entre 32.768 a 32.767 Operações de adição, subtração, multiplicação, divisão e exponenciação. 18
Valor de uma Variável O valor de uma variável é chamado de valor-r, que é o exigido quando a variável é usada no lado direito (right side) de uma instrução de atribuição Exemplo: maior = num; Valor-l deve ser determinado primeiro Vinculação Uma vinculação é uma associação, como por exemplo, entre um atributo e uma entidade ou entre uma operação e um símbolo O momento em que uma vinculação desenvolve-se é chamado tempo de vinculação 19
Vinculação Vinculação Estática Ocorre antes do tempo de execução, e; Permanece inalterada ao longo da execução do programa. Vinculação Dinâmica Ocorre durante a execução do programa, ou; Pode ser modificada no decorrer da execução. Vinculação Vinculação de Atributos a Variáveis Vinculação de Tipo Vinculação de Armazenamento Vinculação de Valor 20
Vinculações de Tipos a Variáveis Antes que uma variável possa ser referenciada em um programa, ela deve ser vinculada a um tipo de dados É importante saber quando e como esta vinculação ocorre Vinculação Estática de Tipos Vinculação Dinâmica de Tipos Vinculação Estática de Tipos Quando? Em tempo de compilação Como? Declaração de Variáveis Associação estática de uma variável a um tipo de dados Pode ser: Declaração explícita; Declaração implícita. 21
Vinculação Estática de Tipos Declaração Explícita É uma instrução em um programa que lista nomes de variáveis e especifica que elas são de um determinado tipo Pascal, C, C++, Java Exemplo: Pascal e C (sempre no início de um bloco) Vinculação Estática de Tipos Declaração Implícita É um meio de associar variáveis a tipos de dados através de convenções padrão sem utilizar instruções de declaração. A primeira ocorrência de um nome de variável em um programa constitui sua declaração implícita. ML, Perl, FORTRAN, Basic, PL/I 22
Vinculação Estática de Tipos Declaração Implícita (cont) FORTRAN Demais letras REAL I,J,K,L,M ou N INTEGER Perl (qualquer posição do bloco) Nome iniciado com $ Tipo escalar $num = 7 Nome iniciado com @ Tipo array @nome = ( maria, joão, ana, pedro ) Vinculação Estática de Tipos Declaração Implícita (cont) Vantagem Conveniência para o programador Desvantagem Problemas de legibilidade Dificulta as checagens do compilador 23
Vinculação Dinâmica de Tipos Com vinculação dinâmica de tipos, o tipo de uma variável não é especificado por nenhuma instrução de declaração. A variável é vinculada a um tipo de dados quando lhe é atribuído um valor em uma instrução de atribuição Tipo pode ser o tipo do valor, da variável ou da expressão no lado direito da atribuição PHP, APL, SNOBOL4, LISP, SMALLTALK Vinculação Dinâmica de Tipos Exemplos 24
Vinculação Dinâmica de Tipos Vantagem Flexibilidade criação de programas genéricos Desvantagens Diminua a capacidade do compilador na detecção de erros Alto custo de implementação Checagem de tipos em tempo de execução Descritor de tipo Memória de tamanho variável Vinculações de Armazenamento Alocação Processo de vinculação de uma variável de programa a uma célula de memória de um pool de memória disponível. Desalocação Processo de devolução de uma célula de memória desvinculada de uma variável ao pool de memória disponível. 25
Tempo de Vida Tempo de vida (lifetime) de uma variável é o tempo durante o qual ela está vinculada a uma localização de memória específica; Tempo de vida de um variável é o intervalo de tempo decorrente entre a sua criação (alocação) e a sua deleção (desalocação). Tempo de Vida Classificação das Variáveis Variáveis Estáticas Variáveis Stack-Dinâmicas Variáveis Heap-Dinâmicas Explícitas Variáveis Heap-Dinâmicas Implícitas 26
Variáveis Estáticas São aquelas vinculadas a células de memória antes que a execução inicie-se e assim permanece até que a execução encerre-se. O tempo de vida de uma variável estática é o tempo de execução do programa todo, mesmo que tenham sido declaradas dentro de um bloco interno. Variáveis Estáticas Exemplos: Variáveis globais C e FORTRAN I, II e IV; C, C++, Java e PHP: variáveis locais declaradas como static Retêm o seu conteúdo entre sucessivas ativações do bloco no qual ela foi declarada. 27
Variáveis Estáticas Exemplo em C/C++ Variáveis Estáticas Exemplo - PHP 28
Variáveis Stack-Dinâmicas São vinculadas ao armazenamento no instante da elaboração de suas instruções de declaração. A elaboração de uma instrução de declaração ocorre quando a execução do programa atinge o código da declaração. Possuem vinculação estática de tipos Exemplo: Variáveis Locais Variáveis Stack-Dinâmicas O tempo de vida de uma variável local corresponde exatamente ao tempo de ativação do bloco no qual ela foi declarada. Tempo de ativação de um bloco é o intervalo de tempo durante o qual o bloco está sendo executado. Uma variável local terá vários tempos de vida se o bloco no qual ela tiver sido declarada for ativado várias vezes. 29
Gráfico de Tempo de Vida Exemplo em C/C++ Gráfico de Tempo de Vida Exemplo em C/C++ 30
Variáveis Heap-Dinâmicas Explícitas São células de memória sem nome alocadas e desalocadas por instruções explícitas em tempo de execução, especificadas pelo programador. Uma variável anônima e, por isso, só pode ser acessada através de um ponteiro ou de uma variável de referência. São usadas freqüentemente para estruturas dinâmicas que precisam crescer e encolher durante a execução. Variáveis Heap-Dinâmicas Explícitas A criação (alocação) de uma variável heapdinâmica explícita é feita por uma função chamada alocadora ou por um operador que retornam o endereço da variável heap alocada. Heap é um conjunto de células de armazenamento disponíveis Desvantagens: Dificuldade de usar corretamente variáveis de ponteiro ou referência. Custo para alocação e desalocação. 31
Variáveis Heap-Dinâmicas Explícitas Exemplo: Operador new de C++ Variáveis Heap-Dinâmicas Explícitas A destruição (desalocação) de uma variável heap-dinâmica explícita pode ocorrer de duas maneiras: Função ou operador de desalocação; Garbage collection (coleta de lixo) 32
Variáveis Heap-Dinâmicas Explícitas Operador Desalocador Desalocação realizada explicitamente pelo programador Exemplo: Operador delete do C++ Variáveis Heap-Dinâmicas Explícitas Observação: A função ou operador de desalocação força a deleção de uma variável heap. Perigo! Se ainda houver algum ponteiro para a região de memória desalocada, este ponteiro torna-se uma referência perdida (dangling reference). 33
Variáveis Heap-Dinâmicas Explícitas Exemplo C++: Variáveis Heap-Dinâmicas Explícitas Observações: Uma variável heap-dinâmica explícita permanece acessível enquanto houver uma variável do tipo ponteiro que aponte para ela. Uma variável heap-dinâmica explícita perdida é uma variável heap-dinâmica explícita alocada mas não mais acessível ao programa usuário (lixo de memória) Vazamento de memória (memory leakage) 34
Variáveis Heap-Dinâmicas Explícitas O Tempo de vida de uma variável heapdinâmica explícita vai desde o momento de sua criação até o momento em que ela é desalocada ou se torna inacessível. Variáveis Heap-Dinâmicas Explícitas Exemplo C++: 35
Variáveis Heap-Dinâmicas Implícitas São vinculadas ao armazenamento do heap somente quando lhe são atribuídos valores. Todos os seus atributos vinculam-se todas as vezes que são atribuídos. Exemplo JavaScript: Variáveis Heap-Dinâmicas Implícitas O tempo de vida de uma variável heapdinâmica implícita vai desde o momento de sua criação até o momento em que ela se torna inacessível. Variáveis heap-dinâmicas implícitas são desalocadas pelo processo de garbage collection 36
Bloco Um bloco é uma seção de código que contém suas próprias declarações. Variáveis Locais Uma variável é local em um bloco de programa se for declarada dentro dele. Variáveis Não-Locais As variáveis não-locais de um bloco são visíveis dentro dele, mas foram declaradas fora dele. Escopo O escopo de uma variável é a faixa de instruções na qual a variável é visível, ou seja, pode ser referenciada. O bloco delimita o escopo de suas declarações. 37
Exemplo de Bloco C++ Exemplo de Bloco - Pascal 38
Escopo e Visibilidade Em um programa que contém mais de um bloco, é possível que o mesmo identificador I seja declarado em diferentes blocos. Em geral, o identificador I denotará uma entidade diferente em cada bloco. O programador, ao declarar e usar um identificador dentro de um bloco, não precisa se preocupar se ele foi declarado e está sendo utilizado em um outro bloco. Escopo e Visibilidade Exemplo - Pascal: 39
Escopo e Visibilidade Exemplo Pascal: Escopo e Visibilidade Casos Interessantes: Existem linguagens onde o escopo de uma variável local começa no ponto onde ela foi declarada e termina no final do bloco onde a declaração foi feita. Exemplo: C++, Java 40
Escopo Estático Quando um identificador de variável é encontrado, a associação entre o identificador e a entidade que ele representa é feita localizandose a instrução de declaração do identificador. Ocorre em tempo de compilação (static scoping) Escopo Estático 41
Escopo Estático Pergunta: Dado o programa abaixo, qual o resultado de teste(h) nos pontos A e B? Escopo Estático Resposta - Com escopo estático, teste(h): Nos pontos A e B, sempre vai retornar o dobro do valor de h. Pascal, Fortran, Ada, C, C++, Java. 42
Escopo Dinâmico Quando um identificador de variável é encontrado, a associação entre o identificador e a entidade que ele representa é feita localizando-se a instrução de declaração do identificador Ocorre em tempo de execução(dynamic scoping) Escopo Dinâmico Pergunta: Dado o programa abaixo, qual o resultado de teste(h) nos pontos A e B? 43
Escopo Dinâmico Resposta - Com escopo dinâmico, teste(h): No ponto A, vai retornar o dobro do valor de h; No ponto B, vai retornar o triplo do valor de h. Lisp, Smalltalk, APL, SNOBOL4. Tipos de Dados 44
Introdução Tipos de Dados Primitivos Compostos Ponteiros Strings Tipos Primitivos Tipos de dados não definidos em termos de outros tipos. Costumam ser definidos na implementação da LP Sofrem influência direta do hardware. São utilizados por quase todas as linguagens de programação 45
Tipos Primitivos Subdividem-se em: Tipos Embutidos ou Pré-Definidos Tipos Numéricos Inteiro, Ponto-Flutuante e Decimal Tipo Booleano Tipo Caractere Tipos Ordinais Definidos pelos Usuários Tipo Enumeração Tipo Intervalo (Subfaixa) Tipos Compostos São tipos cujos valores são compostos ou estruturados por valores mais simples Registros, vetores, listas, arquivos,... Construtores: Produto Cartesiano União Disjunta Conjunto de Potências Mapeamento Recursão 46
Produto Cartesiano Tipo Registro O tipo de dados registro utiliza o conceito de produto cartesiano Uma variável do tipo registro é um par ordenado de valores de tipos possivelmente diferentes Cada elemento individual é identificado por seu nome Produto Cartesiano São produtos cartesiano os registros de PASCAL, MODULA 2, ADA e COBOL e as estruturas de C Exemplos: Record (Pascal) Struct (C) Class (Java) 47
Produto Cartesiano Exemplo -Struct do C: data = int x {jan,,dez} x int Produto Cartesiano Exemplo - Record do Pascal: data = {1,,31} x {jan,,dez} x 1901,,2100} 48
Produto Cartesiano Exemplo - Class do Java: Pessoa = String x int x float União Disjunta O tipo de dados união utiliza o conceito de união disjunta Uma variável do tipo união pode armazenar valores de tipos diferentes em diferentes momentos de um programa Exemplos: Variant Record (Pascal, Object Pascal, Modula 2 e ADA) REDEFINES (COBOL) EQUIVALENCE (FORTRAN) Union (Algol 68, C, C++) 49
União Disjunta Exemplo Union de C: Numero = Integer + Real Conjuntos de Potências Exemplo - tipo set do Pascal: 50
Tipos Recursivos Tipos recursivos podem ser definidos a partir de ponteiros ou diretamente Ponteiros Ponteiro é um conceito de baixo nível relacionado com a arquitetura dos computadores 51