Semântica Denotacional Uma introdução ISBN 0-321-19362-8
Semântica denotacional é um método formal para definir a semântica de linguagens de programação. Interessa a: projetista de linguagens, quem escreve compiladores e programadores. Estes indivíduos têm critérios diferentes para julgar um método).
Requisitos para método deve ser conciso, não ambíguo, aberto à análise matemática, verificável mecanicamente, executável e legível dependendo do seu ponto de vista. A semântica denotacional é uma tentativa de satisfazer a estes objetivos diversos. É um método formal pois é baseado em fundamentos matemáticos bem entendidos e usa uma notação rigorosamente definida (meta-linguagem)
Problema do programador escrever um programa que irá transformar dados satisfazendo algumas propriedades ou asserções P em resultados satisfazendo Q. {P} programa {Q}
Semântica Denotacional A semântica denotacional reconhece a sutil diferença entre uma função um conjunto de pares ordenados possivelmente infinito {<entrada i, saida i >}- e um algoritmo como uma descrição finita de uma função.
Semântica Denotacional Um programa é o algoritmo escrito em uma linguagem particular de programação. Um programa define, ou denota, uma função. Uma semântica denotacional de uma linguagem dá o mapeamento de programas na linguagem para a função denotada
Exemplo: Fatorial = {<0,1>,<1,1>,<2,2>,<3,6>,<4,24>,...} Fat = if n =0 then 1 else n * fat(n-1) Uma boa semântica deve confirmar que o programa denota a função fatorial.
Descrição da Semântica denotacional é escrita em λ-notação que é o cálculo λ de Church com tipos de dados. O método é conciso e poderoso o suficiente para descrever as características das linguagens de programação atuais. Definições formais só são legíveis com prática, sendo a notação equivalente a uma linguagem de programação poderosa mas difícil de ler. É mais adequada ao projetista e implementador de uma linguagem de programação que ao programador.
Vantagens da Semântica denotacional Pode ser mecanizada Mosses desenvolveu um interpretador para semântica denotacional que permite que uma definição seja executada. Algumas linguagens funcionais tais como ML são muito próximas da notação λ com tipo, e podem ser usadas para escrever e executar definições denotacionais
Exemplo de números decimais é apresentado. Os números decimais formam uma linguagem, Num, sobre o alfabeto {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}. Ela pode ser definida pela gramática ν ::= ν δ δ δ::= 0 1 2 3 4 5 6 7 8 9
Exemplo O símbolo ::= pode ser lido como é ou pode ser substituído por. O pode ser lido como ou. Um dígito δ é um 0, ou um 1, ou um 2, e assim por diante. Um numeral é simples dígito ou um numeral seguido de um dígito. As letras gregas ν e δ são variáveis sintáticas sobre partes da linguagem Num.
números decimais são normalmente tomados por significarem, ou denotarem, inteiros que são objetos abstratos. Esta interpretação convencional pode ser feita formalmente pela definição de uma função de valoração V
Função de valoração V V: Num Int V [ν δ] = 10 x V[ν] + V[δ] V[0] =0 V[1] =1 V[2] =3 V[3] =3 V[4] =4 V[5] =5 V[6] =6 V[7] =7 V[8] =8 V[9] =9
V é uma função das sentenças da linguagem Num para os inteiros Int. V édefinido por uma análise caso a caso das alternativas da gramática para Num. Elementos da linguagem estão dentro de chaves para distingui-los da meta linguagem fora. Dentro das chaves estão seqüências de caracteres (strings). Os inteiros fora das chaves estão em itálico. 7 é um caracter que denota o inteiro 7.
valor de um numeral em particular pode agora ser calculado V[123] = 10 x V[12] + 3 = 10 x (10x V[1]+2)+3 = 123
E daí? Não é óbvio?
devemos estar satisfeitos pela definição formal concordar com a intuição em casos simples. Esta é uma característica de boas teorias. O formalismo é necessário quando a intuição não é forte o suficiente. O leitor que não percebe que 7 = 7 não apenas não é verdadeiro mas é um erro em diversas LP (ex Pascal), pode ter perdido o sentido. Note que V capturou a essência da notação posicional, e que V[123] = V[0123] e assim por diante.
Exemplo de uso (uso em compiladores) If ch in [ 0.. 9 ] then Begin n:= ord(ch) ord( 0 ); Ch:= nextch {retorna o próximo char e avança a entrada} While ch in [ 0.. 9 ] do Begin n:= n*10 + ord[ch()- ord( 0 ); Ch := nextch; End End
Exercício Se a definição de V é alterada para V [ν δ] = - 10 x V[ν] + V[δ] Quais são as novas características de V? Qual vantagem esta nova interpretação de Num tem?