amarração e escopo
TRANSCRIPT
Amarração e escopo
Prof: Sergio Souza Costa
Adaptado de © 2004, Programming Language Design Concepts
D.A. Watt, University of Glasgow
Sobre mim
Sérgio Souza CostaProfessor - UFMADoutor em Computação Aplicada (INPE)
https://sites.google.com/site/profsergiocosta/home
https://twitter.com/profsergiocosta
http://gplus.to/sergiosouzacosta
http://www.slideshare.net/skosta/presentations?order=popular
Conteúdo
● Amarrações e ambientes.● Escopo, estrutura de bloco e visibilidade.● Declarações.● Blocos.
Amarrações
Expressões e comandos em linguagens de programação possuem
identificadores.
Amarração é associação entre um identificador e uma entidade, tais como
valores, variaveis e funções.
Cada declaração produz uma ou mais amarrações.
Um ambiente de referenciamento ou namespace é um conjunto de
amarrações.
Cada expressão e ou comando é interpretado em um particular ambiente.
Amarrações: Identificador
Identificadores são utilizados em um contexto mais amplo do que simplesmente em variáveis
●métodos, sub-programas, pacotes, módulos, classes, parâmetros
Um identificador é uma string usada para identificar alguma entidade em um programa.
Para ver onde cada linguagem utiliza identificadores, veja na gramática da linguagem:● https://javacc.dev.java.net/servlets/ProjectDocumentList?folderID=110
Amarrações: Identificador - Formato
● Exemplos:
○ Fortran95: 31 caracteres
○ C89: sem limitação de tamanho (apenas os 31 primeiros são
significativos)
○ C99: 61 primeiros significativos
○ Java, C#, Ada, C++: sem limite
■Os implementadores podem colocar um limite
●Normalmente o limite é dado para reduzir o tamanho da tabela de
símbolos
●Na maioria das linguagens o formato é:
○ letra_ (letra_ | digito)*
Amarrações: Identificador - Formato
●Algumas linguagens permitem espaços nos nomes das variáveis
○ Ex.: Soma dos Salarios, Variavel de teste (anteriores ao FORTRAN 90)
● Linguagens baseadas em C diferenciam minúsculas de maiúsculas
○ ROSE != Rose != rose
○ Pode levar a problemas de legibilidade e facilidade de escrita
■ parseInt != parseint = ParseInt
○Uso de convenções de estilo
Identificador: Atividade
1. Qual é o problema em potencial do uso de nomes sensíveis a capitalização (maiúsculas e minúsculas são diferentes)? Em qual tipo de linguagem esse problema pode ser ainda mais grave ?
procedure p is z: constant Integer := 0;c: Character; procedure q (x: in Float) isc: constant Float := 3.0e6;b: Boolean;begin…end q; begin…end p;
{ b -> variavel booleana,
c -> o numero real 3.0*106,
p -> um procedimento sem parametros,
q -> procedimento com um parametro real,
x -> uma variavel real,
z -> o inteiro 0 }
{ c -> uma variavel caracter,
p -> um procedimento sem parametros,
q -> procedimento com um parametro real,
z -> o inteiro 0 }
Ambiente de referenciamento
Ambiente: Atividade
Qual o ambiente de cada ponto enumerado no programa C abaixo:
int n;(1) void zero(){(2) n=0; }(3) void inc(int d){(4) n+=d; }(5) void main(int argc, char**argv){(6) ... }
Escopo
O escopo de uma declaração (ou de uma amarração) é a porção do
programa no qual ela tem efeito.
Em algumas linguagens antigas (tais como o Cobol), o escopo de cada
declaração era todo o programa.
Nas linguagens modernas existe o conceito de bloco, e o escopo de
cada declaração é controlada por esta estrutura.
Bloco
Um bloco é o elemento que delimita o escopo das declarações.
Ele possui diferentes formas dependendo da linguagem● C: bloco ({}), corpo de funções, unidades de compilação.● Java: bloco ({}), corpo de métodos, declarações de classes, pacotes.● Ada: bloco (declare … begin … end;), corpo de procedures, pacotes,
tasks, etc.
Uma estrutura bloco é a forma em que os blocos são arranjandos no programa.
Blocos monolíticos
Algumas linguagens (como Cobol) possuem uma estrutura de blocos monolítica, o programa completo é um único bloco. O escopo de cada declaração é o programa todo.
declaration of x
declaration of z
declaration of y
declaration of x
declaration of zdeclaration of y
escopo de x, y, z
Estruturas de blocos simples
Algumas linguagens (ex. Fortran) não permitem blocos dentro de outros blocos:
declaration of x
declaration of z
declaration of yescopo de x
escopo de y
escopo de z
Estruturas de blocos aninhadas
Linguagens modernas os blocos podem ser aninhadas dentro de outros blocos.
declaration of x
declaration of z
declaration of y
Escopo de x
Escopo de y
Escopo de z
Escopo e visibilidade
Uma ocorrência da amarração acontece quando existe uma ocorrência de um
identificador I, onde I está amarrado a alguma entidade X;
Uma aplicação da ocorrência do identificador I é uma ocorrência de I, quando
é feita dentro da entidade X na qual I está amarrada.
A essa aplicação, nós dizemos que I denota X.
Se a linguagem tem escopo estático, dizemos que toda aplicação da
ocorrencia de I deve corresponder a exatamente uma ocorrência da
amarração de I.
procedure p is z : constant Integer := 0; c : Character; procedure q (x : in Float) is c : constant Float := 3.0e6; b : Boolean; begin … b … c … x … z … end q; begin … c … z …end p;
Escopo e visibilidade: Exemplo
Ocultação
Se um identificado I é declarado em dois diferente blocos, I denota uma
diferente entidade em cada bloco.
Se identificador I é declado em dois blocos aninhados, I denota uma entidade
no bloco mais externo e uma diferente entidade no bloco mais interno. O
bloco mais interno oculta o mais externo.
declaração de x
declaração de x declaração de x
declaração de xX mais externo
está oculto
Escopo estático
Em LPs com escopo estático (ou léxico), o escopo é determinado através da estrutura textual do programa.
A maioria das linguagens possuem escopo estático.
procedure P is…
begin…
declare…
begin…
end;…
end P; procedure Q is…
beginend Q;
Escopo dinâmico
Algumas linguagens como APL, SNOBOL4 e versões iniciais do LISP tinham escopo dinâmico para variáveis
○ Assim como Perl e COMMON LISP também permitem que variáveis sejam declaradas como tendo escopo dinâmico.
Em LPs com escopo dinâmico, o escopo é determinado através da linha de execução do programa, sendo dependente portanto da ordem de execução das rotinas
○ E não do relacionamento espacial destes
Escopo dinâmico vs estático
x: integerprocedure print_x() begin print(x);endprocedure p2 x: integer; begin x= 4; print_x();endbegin x = 3; p2();end
Se o escopo for dinâmico oprograma imprime 4
Se o escopo for estático, oprograma imprime 3
Escopo dinâmico vs estático
● Existem diversos problemas relacionados ao escopo dinâmico:○ do ínicio ao fim de um programa, todas as variáveis deste estão
disponíveis para os sub-programas■ Não há como proteger tais variáveis de tal acesso
○ não se pode fazer verificação de tipos estática○ os programas são mais difíceis de serem lidos○ acesso mais lento às variáveis
● LISP, por ex. substituiu o escopo dinâmico por estático
Atividade
4. Considerem o seguinte programa:
int add(int i){ return i+d; } void p(){ const int d=1;(1) print(add(20)); } void q(){ const int d=2;(2) print(add(20
a) O que seria impresso em 1 e 2 se o escopo fosse dinâmico.
b) O que aconteceria se o escopo fosse estático.
Declarações
● Uma declaração é uma construção de programas que sera elaborada para produzir amarrações.
● Uma declaração pode ter efeitos colaterais (tais como a criação de uma variavel).
● Uma definição é uma declaração onde o único é produzir amarrações.
Declarações
Formas de declarações:● tipo● constant● variable● definições de procedimentos● …● colaterais● sequenciais● recursivas
Declaração de tipo
●Uma declaração de tipo amarra um identificador a um tipo.
●Uma definição de tipo amarra um identificador a um tipo
existente.
●Alternativamente, uma declaração de tipo pode introduzir um
novo tipo distinto de todos já existentes
Exemplo C: Declaração de tipos
● “typedef …” amarra um identificador a um tipo existente: typedef char* Alpha; Alpha s; char* t; s = t;
● Enquanto “enum …”, “struct …”, ou“union …” amarra um identificador a um novo tipo:
struct Book {Alpha title, int edition};struct Author {Alpha name, int age}; Book b; Author a; a = b;
Exemplo Ada: Declaração de tipos
Em Ada, sempre é definido um novo tipo : type Alpha is array (1 .. 32) of Character; type Book is record title: Alpha;
edition: Integer;
end record;type Author is record name: Alpha;
age: Integer;
end record; b: Book; a: Author; a := b;
Ilegal
Exemplo Haskell: Declaração de tipos
Amarra a um tipo existente (type):
type Nome = Stringtype Idade = Int
type Aluno = (Nome,Idade)type Professor = (Nome,Idade)
getName :: Aluno -> NomegetName (n,_) = n
x :: Professorx = ("Joao", 25)
n = getName (x)
A função getName espera um aluno, porem ela aceitou X que é um professor.
Exemplo Haskell: Declaração de tipos
Amarrando a um novo tipo:
type Nome = Stringtype Idade = Int
data Aluno = Aluno Nome Idadedata Professor = Professor Nome Idade
getName :: Aluno -> NomegetName (Aluno n _) = n
x :: Professorx = Professor "Joao" 25
n = getName (x)
Neste caso a chamada a função getName resulta em uma ação ilegal.
Declaração de Constantes
● Uma declaração de constante amarra um identificador a um valor (constante).
● Em Ada, ela tem a forma: I : constant T := E;
Onde amarra o identificador I ao valor da expressão E, que deve ser do tipo T.
● Algumas linguagens restringem a expressão E a um literal, ou a uma expressão que pode ser avaliada em tempo de compilação.
Declaração de variáveis
● Uma declaração de variavel amarra um identificador a uma variavel.
● Em Ada, tem a seguinte forma: I : T := E;
Essa declaração cria uma variavel de tipo T, amarra I para esta variavel, e inicializa o seu valor pela expressão E.
● Em Ada, é possivel renomear declaração de variáveis: I : T renames V;
Isso amarra I a uma existente variável V.
Declaração de variáveis
● Ada: type Country is (UK, FR, …);pop : array (Country) of Natural; declarec : Country := …;
p : Integer renames pop(c);begin …
p := p + 1;
…
end;
mais direto do quepop(c) := pop(c) + 1;
amara a variável pop(c)
Atividade
5. Em algumas linguagens todas as variáveis deve ser inicializadas em sua declaração. Quais as vantagens e desvantagens dessa exigência.
Definição de procedimentos
Uma definição de procedimento amarra um identificado a um procedimento.
Na maioria das linguagens, podemos definir tanto procedimento quando funções.
Exemplo em Ada
Definição de função: function even (n: Integer) return Boolean isbegin return (n mod 2 = 0);end;
Definição de procedimento:
procedure double (n: in out Integer) isbeginn := n * 2;
end;
Exemplo: Outras linguagens
def hello(): print "Hello World!" return
def multiply(a,b) product = a * bend
multiply a b = a * b
PYTHON
RUBY
HASKELL
Composição de declarações
Como compor um conjunto de declarações:
Colaterais Sequenciais Recursivas
Declaração colateral
Uma declaração colateral tem o formato D1 and D2, onde as sub-declarações são independentes uma da outra.
Incomum em linguagens imperativas, mais presente em linguagens funcionais.
Exemplo ML
val e = 2.7183and pi = 3.1416
Declaração sequencial
Uma declaração seqüencial tem o formato D1; D2, onde D2 é considerada após D1 e amarrações produzidas por D1 podem ser usados em D2.
type Nome = Array[0..30] of Char;
Pessoa = record nome : Nome; idade : Integer;end;
Declarações recursivas
Permite usar amarrações que ela mesmo produz:
type Int_Node;type Int_List isaccess Int_Node;type Int_Node is record elem:Integer; succ:Int_List;endrecord;
Blocos
Grupo de construções de um programa que delimita o escopo das declarações contidas nele. Detalhando mais um pouco ....
Tipos Comandos Expressões
Comando-bloco
É uma forma de comando que contem uma declaração local (ou grupo de declarações) D e um subcomando C.
As amarrações produzidas por D são usada somentes para execuções em C e essas amarrações sobrepõe qualquer amarração ao mesmo identificador no ambiente fora do bloco.
São comuns em linguagens imperativas:
C e Java: { D C }Ada: declare D begin C end;
Expressão-bloco
É uma forma de expressão que contem uma declaração local (ou grupo de declarações) D e um subexpressão E.
As amarrações produzidas por D são usada somentes para avaliação em E e essas amarrações sobrepõe qualquer amarração ao mesmo identificador no ambiente fora do bloco.
Expressão-bloco - Haskell
area r = letpi = 3.1415r2 = r ^ 2
in pi * r2
Tempo da amarração
O momento no tempo onde a amarração ocorre é chamado de tempo de amarração (binding time)● Podem ocorrer em tempo de design da LP, de implementação, de
compilação, de carga, de ligação, de execução
Tempo da amarração
● Por exemplo, o * é normalmente amarrado a operação de multiplicação em tempo de projeto da LP
● Um tipo de dado, tal como int em C, é amarrado a uma lista de valores em tempo de implementação da linguagem
● Variáveis em Java são amarradas a um tipo de dados em tempo de compilação.
● Uma variável é amarrado a uma célula de memória em tempo de carga.
● Variáveis declaradas em métodos em Java são amarradas a memória em tempo de execução.
● Uma chamada a outro pacote é amarrada a esse pacote em tempo de ligação.
Tempo da amarração
● Considere a seguinte sentença em C: count = count + 5
● Exemplos de amarração:○ O tipo de count é amarrado em tempo de compilação○ A lista de valores possíveis para count é definida em tempo de
projeto do compilador C○ O significado do sinal + é determinado em tempo de compilação,
quando o tipo dos operandos for determinado○ A representação interna do literal 5 é amarrada em tempo de
projeto do compilador.○ O valor de count é amarrado em tempo de execução com esta
sentença
Atividade:
6. Defina e exemplifique amarração e tempo de amarração.