Pragmática das Linguagens de

Documentos relacionados
Pragmática das Linguagens de Programação 2004/2005

Fundamentos de Programação

Capítulo 7. Expressões e Sentenças de Atribuição

Fundamentos de Programação

02. [Sebesta, 2000] Qual é o perigo potencial dos nomes que fazem distinção entre maiúsculas e minúsculas?

Linguagens de Programação Funcional

Nomes, vinculações e escopos

Linguagens de Programação Conceitos e Técnicas. Amarrações

Ambientes de Execução

Ambientes de Execução

Programação em Sistemas Computacionais

Compiladores Ambiente de Execução

Paradigmas de Linguagens de Programação. Nomes, Vinculações, Verificação de Tipos e Escopos

Conceitos de Linguagem de Programação - 2

Fundamentos da Programação

Paradigmas de Linguagens de Programação. Expressões e Instruções de Atribuição

Nomes, vinculações e escopos

Linguagem de Programação e Compiladores

Expressões e sentença de atribuição

Conceitos de Linguagens de Programação

Compiladores. Introdução à Compiladores

Linguagem C. Brian W. Kernighan, Dennis Ritchie (K&R) Slides adaptados, inspirados, muitos copiados dos slides do professor Pedro Pereira

02. [Sebesta, 2000] Quais são as vantagens e as desvantagens dos tipos de dados decimais?

Layout. Módulos. Normalmente, cada módulo está armazenado num ficheiro com o mesmo nome do módulo. Exemplo.hs

Fundamentos de Programação

Programação. MEAer e LEE. Bertinho Andrade da Costa. Instituto Superior Técnico. Argumentos da linha de comando Funções recursivas

Compiladores Ambiente de Execução

1º Exame de INTRODUÇÃO À PROGRAMAÇÃO Licenciatura em Engenharia Mecânica 30 de Junho de º Semestre

Compiladores. Análise Semântica

Linguagens de Programação. Nomes, Escopos e Vinculações (Bindings) Carlos Bazilio

DAS5102 Fundamentos da Estrutura da Informação

ao paradigma imperativo

Computação e Programação

Correção do 1º Exame de INTRODUÇÃO À PROGRAMAÇÃO Licenciatura em Engenharia Mecânica 30 de Junho de 2006, 2º Semestre

Fundamentos de Programação

CANape/vSignalyzer. Data Mining and Report Examples Offline Analysis V

Lista 02: Pilhas & Filas

Construção de Compiladores. Capítulo 1. Introdução. José Romildo Malaquias. Departamento de Computação Universidade Federal de Ouro Preto 2014.

Implementando subprogramas

Primeira Prova de Linguagens de Programação - DCC024B -

Exercícios. Alocação Dinâmica. Alocação dinâmica de memória. Alocação de memória. Alocação da Memória Principal. Alocação da Memória Principal

SEMÂNTICA 02/09/2013. Conceitos de LPs - Semântica

Fundamentos de Programação

Trabalho Linguagem e Programação de Compiladores

Programação de Computadores IV. Introdução a Linguagens de Programação Simone Martins SLIDES CEDIDOS POR BRUNO MARQUES 1

Um Compilador Simples. Definição de uma Linguagem. Estrutura de Vanguarda. Gramática Livre de Contexto. Exemplo 1

Introdução à Programação em C (I)

Compiladores e Computabilidade

Programação Estruturada Prof. Rodrigo Hausen Organização e Gerenciamento de Memória

Programação I Aula 17 Correção de programas Pedro Vasconcelos DCC/FCUP

Paradigmas. Fortran, Algol, Algol-68, Pascal, C, Cobol, PL/I

Transcrição:

Instituto Superior Técnico Pragmática das Linguagens de Programação 2004/2005 Primeiro Exame/Segundo Teste 17/12/2004 Número: Turma: Nome: Escreva o seu número em todas as folhas do teste. O tamanho das respostas deve ser limitado ao espaço fornecido para cada pergunta. Pode usar os versos das folhas para rascunho. O exame tem 5 páginas e a duração é de 2.0 hora. A cotação de cada questão encontra-se indicada entre parêntesis. Boa sorte. 1. (1.5) Podemos classificar os erros de um programa de acordo com o momento em que são detectados e de acordo com a parte do compilador que os detecta. Mostre fragmentos de programas (escritos nas linguagens que preferir) que demonstrem: (a) (0.3) Um erro léxico. Em C um identificador tem de começar por uma letra: int 1b = 5; (b) (0.3) Um erro sintático. Em C uma divisão necessita de dois operandos: printf("result:%d", a /); (c) (0.3) Um erro semântico estático. visível em compile time. int quo = 123 / 0; Em C uma divisão por zero (d) (0.3) Um erro semântico dinâmico. Em C uma divisão por zero invisível em compile time. int quo = 123 / x; //com x = 0 (e) (0.3) Um erro que o compilador não detecta nem gera código para detectar. Em C a indexação de arrays.

Número: 2 int v[5] = { 1, 3, 5, 7,9 ;... printf("%d", v[x]); //com x > 4 ou x < 0 2. (3.0) Em Fortran 77 as variáveis locais são tipicamente alocadas estaticamente. Em Algol e seus descendentes (Pascal, C, Ada) as variáveis locais são tipicamente alocadas no stack. Em Common Lisp e Scheme as variáveis locais são alocadas no heap (embora possam ser alocadas no stack em certos casos). (a) (1.5) Dê um exemplo de um fragmento de programa em C (ou Pascal ou Ada) que não funcionará correctamente se as variáveis locais forem alocadas estaticamente. int fact (int n) { if (n == 0) { return 1; else { return n * fact(n - 1); (b) (1.5) Dê um exemplo de um fragmento de programa em Common Lisp (ou Scheme) que não funcionará correctamente se as variáveis locais forem alocadas exclusivamente no stack. (define (make-adder n) (lambda (x) (+ x n))) (define add3 (make-adder 3)) (add3 5) 3. (2.0) O compilador GCC da GNU permite compilar programas escritos usando algumas extensões à linguagem C. Uma dessas extensões é a possibilidade de ter funções dentro de outras funções. Eis um resumo da documentação dessa extensão: 5.4 Nested Functions A nested function is a function defined inside another function. The nested function s name is local to the block where it is defined. The nested function can access all the variables of the containing function that are visible at the point of its definition. For example, here we show a nested function which uses an inherited variable named offset:

Número: 3 bar (int *array, int offset, int size) { int access (int *array, int index) { return array[index + offset]; int i; /*... */ for (i = 0; i < size; i++) /*... */ access (array, i) /*... */ It is possible to call the nested function from outside the scope of its name by storing its address or passing the address to another function: hack (int *array, int size) { void store (int index, int value) { array[index] = value; intermediate (store, size); Here, the function intermediate receives the address of store as an argument. If intermediate calls store, the arguments given to store are used to store into array. (a) (1.0) Dadas as características da linguagem C explique as limitações que são expectáveis relativamente à utilização desta extensão. Quando se invoca uma função interna a outra função, é necessário que a função que a contém ainda esteja em execução, caso contrário as referências às variáveis livres da primeira não terão significado. (b) (1.0) Esquecendo as questões de performance, explique as implicações da eliminação das limitações que referiu no ponto anterior. Seria necessário que o ambiente da função interna permanecesse activo mesmo depois da função que a contém ter terminado. Isto implica que esse ambiente passe a ter duração indefinida, só podendo ser eliminado quando se perdem todas as referências para a função interna. Isto sugere ainda a necessidade de ter um mecanismo de recolha de lixo.

Número: 4 4. (3.0) Considere o seguinte programa Scheme: (define (misterio i) (define (f1 i f) (if (> i 1) (f) (f1 2 (f3)))) (define (f3) (define (f2) i) f2) (f1 1 f1)) (a) (1.0) Admitindo que Scheme é uma linguagem de âmbito léxico, qual o valor da expressão (misterio 3)? Justifique. Quando f1 é aplicada como resultado da expressão (misterio 3), o teste do if falha e a função f1 invocase recursivamente usando como argumento o resultado da invocação da função f3 que é a função f2. No momento em que esta função é criada, é-lhe associado o ambiente léxico em que i diz respeito ao parâmetro do procedimento misterio que, como não foi alterado, tem o valor 3. Na invocação recursiva de f1, o teste é bem sucedido e é invocada a função f que designa f2 que devolve o valor de i que era 3. (b) (1.0) Admitindo que Scheme era uma linguagem de âmbito dinâmico com shallow binding, qual o valor da expressão (misterio 3)? Justifique. Com shallow binding, a associação entre uma função e o seu ambiente envolvente é feita no momento da aplicação da função. Neste caso, quando f1 é aplicada, o teste do if falha e a função f1 invoca-se recursivamente usando como argumento o resultado da invocação da função f3 que é a função f2. Nesta segunda invocação recursiva, o teste é bem sucedido e é invocada a função f que designa f2 mas é apenas neste momento que se estabelece a associação entre a função f2 e o ambiente envolvente. Neste ambiente, f2 devolve o valor de i que,

Número: 5 neste momento, é 2. (c) (1.0) Admitindo que Scheme era uma linguagem de âmbito dinâmico com deep binding, qual o valor da expressão (misterio 3)? Justifique. Com deep binding, a associação entre uma função e o seu ambiente envolvente é feita no momento da criação da função. Neste caso, quando f1 é aplicada, o teste do if falha e a função f1 invoca-se recursivamente usando como argumento o resultado da invocação da função f3 que é a função f2 mas com o ambiente associado contendo a ligação i=1 que é o último valor de i ainda visível em f2. Nesta segunda invocação recursiva, o teste é bem sucedido e é invocada a função f que designa f2 mas cujo valor devolvido é o valor de i no momento em que a função tinha sido criada, que era 1. 5. (0.5) Considere a seguinte expressão escrita em notação infixa: (a + (b - c)) * d A mesma expressão escrita em notação prefixa fica com a seguinte forma: * + a - b c d No entanto, as linguagens da família Lisp empregam uma notação prefixa ligeiramente diferente denominada notação prefixa com parêntesis: (* (+ a (- b c)) d) Explique qual a vantagem da notação prefixa com parêntesis das linguagens Lisp sobre a notação prefixa simples e dê um exemplo onde essa vantagem seja visível por comparação com o mesmo exemplo escrito em notação prefixa simples. A vantagem está na utilização de operadores que podem receber um número variável de operandos. Como exemplo, temos: (* (+ a b (- c d e) f) g h) Em notação infixa simples teríamos de escrever: * * + a + b + - - c d e f g h