170 likes | 344 Views
Conversão de Tipos. Exemplo: x + i, onde x é do tipo real e i é do tipo integer. A especificação da linguagem deve indicar se a linguagem suporta este tipo de expressão, e qual a conversão necessária. Conversões neste caso podem ser inseridas pelo typechecker: (+.real) x (inttoreal (i)).
E N D
Conversão de Tipos • Exemplo: x + i, onde x é do tipo real e i é do tipo integer. • A especificação da linguagem deve indicar se a linguagem suporta este tipo de expressão, e qual a conversão necessária. • Conversões neste caso podem ser inseridas pelo typechecker: (+.real) x (inttoreal (i))
Coerções • Conversões de tipo implícitas são chamadas de coerções. • Coerções normalmente são limitadas a conversões em que não há perda de informação: inteiro para real, mas não o contrário. • Conversões explícitas são idênticas às aplicações de funções normais.
Coerções (cont.) • Exemplos de tratamento de conversões em diferentes linguagens: • Ada: sempre explícitas • Pascal e Haskell não misturam caracteres e inteiros, como ocorre em C. • x é um array de float, há alguma diferença em inicializá-lo nas formas abaixo?for (i=0;i<n;i++) {x[i] = 1;}for (i=0;i<n;i++) {x[i] = 1.0;}
Overloading de funções e operadores • Um símbolo é overloaded se o seu significado depende do contexto. Exemplos: • operador ‘+’ em floats, inteiros, números complexos etc. • ‘(‘ e ‘)’ em Ada: índice de arrays, chamada de funções, conversão de tipos (cast). • overloading é resolvido quando um valor único para o símbolo é determinado.
Descobrindo os tipos de operadores overloaded • Ao invés de trabalharmos com o tipo de uma expressão, podemos trabalhar com o conjunto de tipos possíveis de uma expressão. • Na maioria das linguagens uma expressão tem que ter (ao final da verificação) um único tipo!
Descobrindo os tipos de operadores overloaded (cont.) E E1 { E.types = E1 .types } E id { E.types = lookup(id.entry) } E E1 (E2) { E.types = { t | s E2 .types st E1.types}}
Funções e operadores polimórficos • procedimento ou função que pode ser executado com argumentos de tipos diferentes. • Exemplos built-in nas linguagens: índices de arrays, aplicação de funções, operações sobre ponteiros.
Por que funções polimórficas? • Facilitam a implementação de algorítimos que manipulam estruturas de dados, independentemente do tipo da estrutura. • Exemplo: Pascal (ou C) vs. Haskell
Exemplo em Pascal • type link = ^cell; cell = record info: integer; next: link; end;function length (lptr : link) : integer;var len : integer;begin len = 0; while (lptr <> nil) do begin len := len + 1; lptr := lptr^.next; end; length := len;end;
Exemplo em Haskell • length :: [t] -> Int;length [] = 0length (a:as) = 1 + length as ou • length :: [t] -> Int;length lptr = if null lptr then 0 else 1 + length (tail lptr)
Variáveis de tipos • servem para identificar um tipo que não é conhecido em uma determinada parte do programa. • Inferência de tipos permite determinar o tipo a partir de seu uso, e.g. descobrir o tipo de uma função a partir de sua definição.
Exemplo: map em pascal (ou C) • type link = ^cell;function map (lptr : link; procedure p);begin while (lptr <> nil) do begin p(lptr); lptr := lptr^.next; end;end;
Exemplo: deref em pascal (ou C) • function deref (p);begin return p^;end;
Estendendo a linguagem para suportar polimorfismo P D ; E D D ; D | id : Q Q type_variable . Q | T T T ‘->’ T | T T | unary_constructor ( T ) | basic_type | type_variable | ( T )
Regras para inferência de tipos • Ocorrências distintas de uma função polimórfica em uma expressão podem ter tipos diferentes. • Como variáveis podem aparecer em expressões de tipos, temos que rever a noção de equivalência de tipos. Usamos unificação ao invés de equivalência. • Usar um mecanismo para guardar os resultados da unificação dos tipos.
Substituições, instâncias e unificação • substituições: mapeamento de variáveis de tipos em expressões de tipos. • instâncias: tipos mais específicos são instâncias de tipos mais genéricos. • expressões de tipo t1 e t2unificam se existe uma substituição S tal que S(t1) = S(t2). Queremos o unificador mais geral, i.e. que gere o mínimo de restrições nas variáveis nas expressões.