Baixe o app para aproveitar ainda mais
Prévia do material em texto
8/27/2009 1 Linguagens de Programação Conceitos e Técnicas Amarrações Prof. Jairo Francisco de Souza Conceituação • Amarração (ou binding) é uma associação entre entidades de programação, tais como entre uma variável e seu valor ou entre um identificador e um tipo • Enfoque na amarração de identificadores a entidades Linguagens de Programação 2 Tempos de Amarração Linguagens de Programação 3 Identifica- dor ou Símbolo Entidade Tempo de Amarração * Operação de multiplicação projeto da LP int Intervalo de inteiros projeto da LP (JAVA) implementação do compilador (C) variável Tipo compilação (C) execução (polimorfismo em C++) função Código correspondente da função ligação variável global Variável em memória carga do programa variável local Variável em memória execução Amarração Estática X Dinâmica • Amarração estática – Se ocorre antes da execução do programa e permanece inalterada ao longo de toda a execução. • Amarração dinâmica – Quando a amarração ocorre ou é alterada durante a execução do programa. Linguagens de Programação 4 Identificadores • Identificadores são cadeias de caracteres definidas pelos programadores para servirem de referência a entidades de computação • Objetivam aumentar a legibilidade, redigibilidade e modificabilidade • LPs podem ser case sensitive e limitar o número máximo de caracteres • Alguns identificadores podem ter significado especial para a LP – Palavras reservadas ≠ Palavra Chave ≠ Palavras Pré-definidas – FORTRAN: exemplo de palavra-chave REAL R � REAL é encarado como uma palavra especial REAL = 3.0 � Não é uma palavra especial – C: fopen e fclose (identicadores pré-definidos na biblioteca padrão q podem ser redefinidos pelo programador). Linguagens de Programação 5 Identificadores • Identificadores globais – vida longa – nomes longos – Camel notation: meuArray • Identificadores locais – vida curta – nomes curtos – letras: i,j,k Linguagens de Programação 6 8/27/2009 2 Ambientes de Amarração • A interpretação de comandos e expressões, tais como a = 5 ou g(a + 1), dependem do que denotam os identificadores utilizados nesses comandos e expressões • Um ambiente (ou environment) é um conjunto de amarrações • Cada amarração possui um determinado escopo, isto é, a região do programa onde a entidade é visível Linguagens de Programação 7 Ambientes de Amarração • Amarração de Identificador a Duas Entidades Distintas no Mesmo Ambiente int a = 13; void f() { int b = a; int a = 2; b = b + a; } Linguagens de Programação 8 Escopo • É formado pelas instruções nas quais a variável é visível – Uma variável é visível em uma instrução se ela puder ser referenciada na instrução • O programador precisa ter um conhecimento completo das regras de escopo de uma LP para escrever e ler programas nela – Elas determinam como a ocorrência de um nome deve ser associado a uma variável; – Em particular, como a referência a uma variável declarada fora do subprograma ou bloco corrente (variável não-local) é associada a uma declaração e, dessa forma, a seus atributos; • Um variável é local a uma unidade ou bloco de programa se ele é declarada lá – As variáveis não-locais de uma unidade ou bloco de programa são aquelas visíveis mas não declaradas lá • Métodos de determinação do escopo de variáveis: estático e dinâmico Linguagens de Programação 9 Escopo estático Linguagens de Programação 10 Escopo estático Linguagens de Programação 11 x x y z w x y z w x Bloco Monolítico Blocos Não Aninhados Blocos Aninhados Ocultamento de definições de variáveis em blocos aninhados • A declaração de uma variável “oculta” qualquer outra declaração de variável com o mesmo nome, em um escopo mais abrangente; • Problema com a utilização das regras de escopo estático: visibilidade exagerada para algumas variáveis. P.ex: as variáveis declaradas no programa principal são visíveis a todos os subprogramas; Linguagens de Programação 12 8/27/2009 3 Escopo Estático • Referência Seletiva em ADA Linguagens de Programação 13 procedure A is x : INTEGER; procedure B is y : INTEGER; procedure C is x : INTEGER; begin x := A.x; end C; begin null; end B; begin null; end A; Escopo Estático • Problemas com Estrutura Aninhada Linguagens de Programação 14 P A B C D E D P A B C E D a b Escopo Estático • Abordagem mista na qual blocos definidos por funções adotam uma estrutura não-aninhada e os blocos internos às funções adotam uma estrutura aninhada. • Estrutura de Blocos de C int x = 10; int y = 15; void f() { if (y – x) { int z = x + y; } } void g() { int w; w = x; } Linguagens de Programação 15 void main() { f(); x = x + 3; g(); � possível pois adota estrutura não aninhada } Escopo Dinâmico • Baseado na seqüência da chamada dos subprogramas, e não na sua posição dentro do texto do programa; • Determinado em tempo de execução; • Exemplos: – LPs que adotaram escopo dinâmico: APL, SNOBOL4, e as primeiras versões do LISP; – Perl e COMMON LISP: usam as regras de escopo estático, mas permitem que variáveis sejam declaradas como tendo escopo dinâmico; Linguagens de Programação 16 Escopo Dinâmico Linguagens de Programação 17 • Se a seqüência de ativação for (1), a referência à variável X em Sub1 vai ser resolvida com a declaração de X em Sub2; • Se a seqüência de ativação for (2), a referência à variável X em Sub1 vai ser resolvida com a declaração de X em Big; Escopo Dinâmico procedimento sub() { inteiro x = 1; procedimento sub1() { escreva( x); } procedimento sub2() { inteiro x = 3; sub1(); } sub2(); sub1(); } Linguagens de Programação 18 • Exemplo: Usando escopo dinâmico, qual seria o valor impresso por escreva(x) quando a instrução sub().sub2() for executada? E quando a instrução sub().sub1() for executada? 8/27/2009 4 Escopo Dinâmico procedimento sub() { inteiro x = 1; procedimento sub1() { escreva( x); } procedimento sub2() { inteiro x = 3; sub1(); } sub2(); sub1(); } Linguagens de Programação 19 • Exemplo: Usando escopo dinâmico, qual seria o valor impresso por escreva(x) quando a instrução sub().sub2() for executada? R: 3 E quando a instrução sub().sub1() for executada? R: 1 Escopo Dinâmico • Problemas – Eficiência – Legibilidade – Confiabilidade • Não usado pela maioria das LPs Linguagens de Programação 20 Definições e Declarações • Definições produzem amarrações entre identificadores e entidades criadas na própria definição • Declarações produzem amarrações entre identificadores e entidades já criadas ou que ainda o serão Linguagens de Programação 21 Definições e Declarações • Algumas LPs permitem declarações e definições dentro de blocos. • A maioria dos compiladores C requer que elas sejam feitas imediatamente após o marcador { • C++ e Java permitem q sejam feitas em qualquer ponto • Localização de Definições de Variáveis em C++ void f() { int a = 1; a = a + 3; int b = 0; b = b + a; } Linguagens de Programação 22 Declaração de Constantes • Em C const float pi = 3.14; � ainda permite mudanças no valor #define pi 3.14 � mais restritivo • Em JAVA final int const1 = 9; static final int const2 = 39; final int const3 = (int)(Math.random()*20); static final const4 = (int)(Math.random()*20); Inicialização de constantes em lugar distinto da declaração, em Java: final int j; Construtor () { j = 1; } Linguagens de Programação 23 Definições e Declarações de Tipos struct data {int d, m, a; }; Linguagens de Programação 24 union angulo { int graus; float rad; }; enum dia_util { seg, ter, qua, qui, sex }; �Definições Tipos em C �Declarações Tipos em C struct data d; typedef union angulo curvatura; typedef struct data aniversario; 8/27/2009 5 Definições e Declarações de Variáveis • Definições de Variáveis em C int k; union angulo ang; struct data d; int *p, i, j, k, v[10]; • Definições com Inicialização int i = 0; char virgula = ','; float f, g = 3.59; int j, k, l = 0, m=23; Linguagens de Programação 25 Definições e Declarações de Variáveis • Definições com Inicialização Dinâmica void f(int x) { int i; int j = 3; i = x + 2; int k = i * j * x; } • Definições com Inicialização em Variáveis Compostas int v[3] = { 1, 2, 3 }; Linguagens de Programação 26 Verificação de tipo de variáveis • Verificação de que os operandos são de “tipo compatível” com o operador; • O tipo de um operando é compatível com o do operador quando ele é um dos tipos aceitos pelo operador ou quando ele pode ser automaticamente convertido para um desses tipos (coersão) – Exemplo: se, em Java, uma variável int é somada a uma variável float, o valor da variável int é convertido automaticamente para float antes da soma. • Além dos operadores da LP (que normalmente representam operações pré-definidas), também estão sujeitos à verificação de tipo: – Subprogramas (que podem ser vistos como operações definidas pelo programador): os argumentos dos subprogramas devem ser de tipo compatível com o subprograma; – Comandos de atribuição: o resultado da expressão do lado direito (do sinal de atribuição) deve ser de tipo compatível com o da variável do lado esquerdo Linguagens de Programação 27 Verificação de tipo de variáveis • Um erro de tipo é a aplicação de um operador a um operando de tipo não-compatível • LPs com vinculação estática de tipo: a verificação de tipo pode ser feita de forma estática (em tempo de compilação) – Exceção: quando a LP permite que uma célula de memória assuma valores de tipos diferentes ao longo da execução; p.ex: Fortran (Equivalence), Ada (variant records), C e C++ (unions) Linguagens de Programação 28 Amarração dinâmica de tipos • A variável é vinculada a um tipo quando a ela é atribuído um valor: ela assume o tipo do valor que recebe; • Exemplos de LPs com vinculação dinâmica de tipo: PHP e JavaScript. Por exemplo, em JavaScript: – list = [10.2, 3.5] /*list passa a ser do tipo vetor de comprimento 2 */ – list = 47 /* lista passa a ser do tipo escalar */ • Vantagem da vinculação dinâmica de tipo: flexibilidade – Exemplo: um programa para processar uma lista de números pode ser feito como um programa genérico, capaz de funcionar corretamente, qualquer que seja o tipo dos dados fornecidos. Linguagens de Programação 29 Amarração dinâmica de tipos • Desvantagens – Menor confiabilidade; – Maior custo: • A verificação de tipo deve ser feita em tempo de execução; • Gasto maior de memória: toda variável precisa ter, em tempo de execução, um descritor associado a ela; • A implementação da LP tem de ser feita através de interpretação pura (10x mais demorado em relação à compilação); isso porque os computadores não tem instruções capazes de manipular operandos de tipo desconhecido. Linguagens de Programação 30 8/27/2009 6 Tipagem forte • Uma LP é fortemente tipada se erros de tipo são sempre detectados. • Requisito: o tipo de todos os operandos devem poder ser determinados, seja em tempo de compilação ou em tempo de execução • Importância: os programas são mais confiáveis • Algumas LPs e a sua tipagem: – Fortran 95: não é fortemente tipado (instrução Equivalence); – Ada: quase fortemente tipada (função Unchecked_Conversion); – C e C++: não são fortemente tipadas(union types); – ML: fortemente tipada (tipos são declarados ou inferidos estaticamente); – Java e C#: quase fortemente tipada (conversão explícita de tipo); Linguagens de Programação 31 Verificação de tipo e coersão • Coersão enfraquece a tipagem forte: erro de tipo pode deixar de ser detectado • Por exemplo: sejam a e b variáveis declaradas do tipo float e d do tipo int. Suponha que o programador desejava calcular a + b, mas em vez disso digitou a + d por engano. Em Java esse erro não seria detectado, pois o compilador providenciaria a conversão automática (coersão) do valor inteiro de d para o correspondente valor real, e a soma seria realizada. • Exemplo de LPs com muita coersão: Fortran, C e C++; • Exemplo de LP com coersão média: Java e C# (metade de C++); • Exemplo de LP com baixa coersão: Ada Linguagens de Programação 32 Compatibilidade de tipo • Importância: Duas variáveis com tipos compatíveis podem ter atribuição do valor de uma à outra • Métodos de determinação da compatibilidade de tipo: – Compatibilidade por nome do tipo: duas variáveis têm tipos compatíveis se elas são definidas na mesma declaração, ou em declarações que utilizam o mesmo nome de tipo – Compatibilidade por estrutura do tipo: duas variáveis têm tipos compatíveis se eles possuem estruturas idênticas. • Existem algumas variações desses métodos, e muitas LPs utilizam uma combinação de ambos Linguagens de Programação 33 Compatibilidade por nome • Mais fácil de implementar mas muito restritivo. Por exemplo, uma variável do tipo sub-faixa de inteiros não é compatível com uma variável do tipo inteiro: type Indextype is 1..100; count:Integer; index:Indextype; /*count e index são consideradas de tipos incompatíveis Linguagens de Programação 34 Compatibilidade por estrutura • Mais flexível mas também mais difícil de implementar (qual deve ser o critério para considerar duas estruturas idênticas?) • Impede diferenciar tipos com a mesma estrutura. Por exemplo, com a declaração abaixo, variáveis dos tipos celsius e fahrenheit seriam consideradas compatíveis, podendo aparecer misturadas em uma expressão (o que não é apropriado). type celsius=Float; type fahrenheit =Float; Linguagens de Programação 35 Compatibilidade em algumas LPs • Ada: – Em geral, utiliza a compatibilidade por nome, mas tem o construtor de tipos subtype (subtipo), que evita o problema associado com esse método: subtype Small_type is Integer range 0..99; /* Variáveis do tipo Small_type são compatíveis com variáveis Integer Linguagens de Programação 36 8/27/2009 7 Compatibilidade em algumas LPs • Ada: – Utiliza compatibilidade por estrutura para variáveis do tipo array; entretanto, variáveis de tipos anônimos não são compatíveis entre si, mesmo tendo a mesma estrutura: A :array(1..10) of Integer; B :array(1..10) of Integer; /* A e B são de tipos incompatíveis, embora a estrutura dos seus tipos seja idêntica – As regras de compatibilidade de tipo são mais importantes para Ada do que para LPs que tem muita coersão de tipos Linguagens de Programação 37 Compatibilidade em algumas LPs • C: – Utiliza compatibilidade por estrutura para todos os tipos exceto para aqueles criados com os construtores struct e union. – Toda declaração struct e union cria um novo tipo incompatível com qualquer outro tipo. • C++: – Utiliza compatibilidade por nome • Fortran e COBOL: – Os tipos não tem nome, e portanto, a compatibilidade por tipo não pode ser usada Linguagens de Programação 38 Definições e Declarações de Subprogramas • Definição de Subprogramas em C int soma (int a, int b) { return a + b; } • Declaração de Subprogramas em C int incr (int); void f(void) { int k = incr(10); } int incr (int x) { x++; return x; } Linguagens de Programação 39 Definições Compostas Seqüenciais • Definições Seqüenciais em C struct funcionario { char nome [30];int matricula; float salario; }; struct empresa { funcionario listafunc [1000]; int numfunc; float faturamento; }; int m = 3; int n = m; Linguagens de Programação 40 Definições Compostas Seqüenciais • Definições Seqüenciais em ML val par = fn (n: int) => (n mod 2 = 0) val negacao = fn (t: bool) => if t then false else true val impar = negacao o par val jogo = if x < y then par else impar Linguagens de Programação 41 Definições Compostas Recursivas • Definição Recursiva de Função em C float potencia (float x, int n) { if (n == 0) { return 1.0; } else if (n < 0) { return 1.0/ potencia (x, -n); } else { return x * potencia (x, n - 1); } } Linguagens de Programação 42 �Tipo Recursivo em C struct lista { int elemento; struct lista * proxima; }; 8/27/2009 8 Definições Compostas Recursivas • Definições Mutuamente Recursivas em C void segunda (int); void primeira (int n) { if (n < 0) return; segunda (n – 1); } void segunda (int n) { if (n < 0) return; primeira (n – 1); } Linguagens de Programação 43 Definições Compostas Recursivas • Erro em Definição de Função strcmp em C int strcmp (char *p, char *q) { return !strcmp (p, q); � função da biblioteca, ao invés da função recursiva! } • Seria interessante se pudéssemos dizer se a função é recursiva ou não • Explicitação de Recursividade em Função ML val rec mdc = fn ( m:int, n: int) = > if m > n then mdc (m – n, n) else if m < n then mdc (m, n – m) else m Linguagens de Programação 44
Compartilhar