Conceituação Conceitos e Técnicas Amarrações Prof. Jairo Francisco de Souza 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 2 Tempos de Amarração Identificador ou Entidade Símbolo 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 local Variável em memória Variável em memória carga do programa 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. 3 4 Identificadores 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 REALR REALéencaradocomoumapalavraespecial REAL=3.0 Nãoéumapalavraespecial C: fopen e fclose (identicadores pré-definidos na biblioteca padrão q podem ser redefinidos pelo programador). Identificadores globais vidalonga nomes longos Camel notation: meuarray Identificadores locais vidacurta nomes curtos letras: i,j,k 5 6 1
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 é,aregiãodoprograma ondeaentidade évisível Ambientes de Amarração Amarração de Identificador a Duas Entidades Distintas no Mesmo Ambiente inta=13; voidf(){ intb=a; inta=2; b=b+a; 7 8 Escopo Escopo estático É 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 9 10 Escopo estático Ocultamentode definições de variáveis em blocos aninhados x x x y y w z z w x Bloco Monolítico Blocos Não Aninhados 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; 11 12 2
Escopo Estático Escopo Estático Referência Seletiva em ADA 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; Problemas com Estrutura Aninhada P P A B C A B C D E D E a b D 13 14 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 intx=10; inty=15; voidf(){ if(y x){ intz=x+y; voidg(){ intw; w=x; voidmain(){ f(); x=x+3; g(); possível pois adota estrutura não aninhada 15 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; 16 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; 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? procedimento sub(){ inteirox=1; procedimento sub1() { escreva( x); procedimento sub2() { inteirox=3; sub1(); sub2(); sub1(); 17 18 3
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 procedimento sub(){ inteirox=1; procedimento sub1() { escreva( x); procedimento sub2() { inteirox=3; sub1(); sub2(); sub1(); Problemas Eficiência Legibilidade Confiabilidade Não usado pela maioria das LPs 19 20 Definições e Declarações 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 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++eJavapermitemqsejamfeitasemqualquerponto Localização de Definições de Variáveis em C++ voidf(){ inta=1; a=a+3; intb=0; b=b+a; 21 22 Declaração de Constantes Definições e Declarações de Tipos EmC constfloatpi=3.14; aindapermitemudançasnovalor #define pi 3.14 mais restritivo Em JAVA finalintconst1 =9; staticfinalintconst2 =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: finalintj; Construtor(){ j=1; Definições Tipos em C struct data{ intd,m,a; ; union angulo{ int graus; float rad; ; Declarações Tipos em C struct data d; typedef union angulo curvatura; typedef struct data aniversario; enum dia_util{ seg, ter, qua, qui, sex ; 23 24 4
Definições e Declarações de Variáveis Definições e Declarações de Variáveis DefiniçõesdeVariáveisemC intk; union angulo ang; struct data d; int*p,i,j,k,v[10]; Definições com Inicialização inti=0; charvirgula =','; floatf,g=3.59; intj,k,l=0,m=23; Definições com Inicialização Dinâmica voidf(intx){ inti; intj=3; i=x+2; intk=i*j*x; Definições com Inicialização em Variáveis Compostas intv[3]={1,2,3; 25 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 27 Verificação de tipo de variáveis Umerrode tipoéaaplicaçãode 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) 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 comprimento2*/ list=47/*listapassaaserdotipoescalar*/ 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. 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. 29 30 5
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 AlgumasLPseasuatipagem: 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); Verificação de tipo e coersão Coersão enfraquece a tipagem forte: erro de tipo pode deixar de ser detectado Porexemplo:sejamaebvariáveisdeclaradasdotipofloated 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. ExemplodeLPscommuitacoersão:Fortran,CeC++; Exemplo de LP com coersão média: Java e C# (metade de C++); Exemplo de LP com baixa coersão: Ada 31 32 Compatibilidade de tipo Importância: Duas variáveis com tipos compatíveis podemteratribuição dovalordeumaà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 nomedetipo 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 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 33 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). 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 type celsius=float; type fahrenheit =Float; 35 36 6
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 paraadadoqueparalpsquetemmuitacoersãodetipos 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, acompatibilidade por tiponãopodeserusada 37 38 Definições e Declarações de Subprogramas Definição de Subprogramas em C intsoma(inta,intb){ returna+b; Declaração de Subprogramas em C int incr(int); void f(void){ intk=incr(10); intincr(intx){ x++; return x; 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; ; intm=3; intn=m; 39 40 Definições Compostas Seqüenciais Definições Compostas Recursivas Definições Seqüenciais em ML valpar=fn(n:int)=>(nmod2=0) valnegacao=fn(t:bool)=>iftthenfalseelsetrue valimpar=negacaoopar valjogo=ifx<ythenparelseimpar Definição Recursiva defunção emc floatpotencia (floatx,intn){ if(n==0){ return 1.0; elseif(n<0){ return 1.0/ potencia (x,-n); else{ returnx*potencia (x,n-1); Tipo Recursivo em C struct lista { int elemento; struct lista * proxima; ; 41 42 7
Definições Compostas Recursivas Definições Compostas Recursivas Definições Mutuamente Recursivas em C void segunda(int); voidprimeira(intn){ if(n<0)return; segunda (n 1); voidsegunda(intn){ if(n<0)return; primeira(n 1); 43 ErroemDefinição defunção strcmp emc intstrcmp(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 valrecmdc=fn(m:int,n:int)=> ifm>nthenmdc(m n,n) elseifm<nthenmdc(m,n m) elsem 44 8