Documentos de Académico
Documentos de Profesional
Documentos de Cultura
probacionDeTipos PDF
probacionDeTipos PDF
m
b
i
t
o
n
i
v
e
l
0
m
b
i
t
o
n
i
v
e
l
1
m
b
i
t
o
n
i
v
e
l
1
m
b
i
t
o
n
i
v
e
l
2
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Introduccin
Qu es la comprobacin de tipos?
La labor de comprobacin de tipos consiste en conferir a las construcciones sintcticas del lenguaje la
semntica de tipificacin que acabamos de describir y en realizar todo tipo de comprobaciones de dicha
ndole. Por su naturaleza, sin embargo, sta se encuentra repartida entre la fase de anlisis semntico
y la generacinde cdigo intermedio
Anlisis semntico
Generacin cdigo
intermedio
S
WHILE E DO S
E > E
S
WHILE E DO S
E > E
LD a t1
LD b t2
GRT t3 t1 t2
BRZ t3 L1
I. Comprobaciones estticas
II. Comprobaciones dinmicas
Las comprobaciones estticas recogen el compendio de todas aquellas
tareas de carcter semntico que, por su naturaleza, pueden ser realizadas
directamente durante la fase de compilacin mediante el uso de los
artefactos y mecanismos propios de dicha fase. Este tipo de
comprobaciones son beneficiosas puesto que confieren seguridad a la
ejecucindel programa
Las comprobaciones dinmicas son aquellas que no se realizan durante la
fase de compilacin y se delegan al momento de la ejecucin del programa.
Ello requiere generar cdigo ejecutable especficamente diseado para
realizar tales comprobaciones. Los lenguajes con una carga excesiva de
comprobaciones dinmicas generan programas ms largos, lentos e
inseguros en ejecucin
Tipos de comprobaciones semnticas
Tema 7
Tema 8-9
Pascal Fortran
La capacidad de poder utilizar un mismo
operador para articular diferentes operaciones
en funcin de los tipos de datos involucrados se
llama sobrecarga de operadores. Es frecuente
sobrecargar los operadores aritmticos y
relacionales de un lenguaje
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Sistemas de tipos
Elementos de un sistema de tipos
La descripcin del sistema de tipos de un lenguaje de programacin se articula, fundamentalmente,
mediante la definicin de los tipos primitivos y constructores compuestos, sus reglas de composicin,
las operaciones permitidas sobre cada uno de ellos y el tipo de resultado que provocan
Verificacin de tipos sobre operadores
La mayora de operadores de un lenguaje de programacin pueden operarse satisfactoriamente
sobre un subconjunto de tipos primitivos del lenguaje. Esto desencadena una serie de conceptos tan
interrelacionados entre si que conviene abordarlos conjuntamente
II. Compatibilidad de tipos
2 + 3.5
4.2 * 3
En los ejemplos en Pascal puede verse como
los operadores sobrecargados suma (+) y
producto (*) definen los tipos entero y real como
compatibles entre s, mientras que en C resultan
compatibles el tipo carcter, entero y flotante
con respecto a los mismos operadores
Se dice que dos tipos son compatibles
entre si, con respecto a un operador, si son
equivalentes o si se pueden operar
satisfactoriamente a travs de dicho
operador
a + 3.5
4.2 * 3
Pascal C
La capacidad de sobrecarga de los operadores
de un lenguaje, introduce el concepto de
compatibilidad de tipos, que se aplica cuando
dichos tipos pueden ser satisfactoriamente
operados a travs de un operador sobrecargado
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Sistemas de tipos
Elementos de un sistema de tipos
La descripcin del sistema de tipos de un lenguaje de programacin se articula, fundamentalmente,
mediante la definicin de los tipos primitivos y constructores compuestos, sus reglas de composicin,
las operaciones permitidas sobre cada uno de ellos y el tipo de resultado que provocan
Verificacin de tipos sobre operadores
La mayora de operadores de un lenguaje de programacin pueden operarse satisfactoriamente
sobre un subconjunto de tipos primitivos del lenguaje. Esto desencadena una serie de conceptos tan
interrelacionados entre si que conviene abordarlos conjuntamente
III. Coercin de tipos
2 + 3.5
4.2 * 3
En los ejemplos de Pascal ambas operaciones
operan entre reales y por tanto los operandos
enteros se convierten a real. Igual ocurre con la
primera expresin en C que convierte el carcter
a a entero y de ah a flotante para poder
operarse. Estas conversiones se llaman
implcitas. Sin embargo la ultima fuerza a
convertir el flotante a entero con perdida de
informacin. Esta conversin es explcita
La coercin de tipos es el proceso
mediante el cual el sistema de tipos
convierte la subexpresin menos restrictiva
hacia la ms restrictiva cuando ambas son
de distinto tipo
a + 3.5
(int) 4.2 * 3
Pascal C
La compatibilidad de tipos permite operar
expresiones de tipos diferentes pero
comnmente fuerza conversiones de tipo hacia
el tipo ms restrictivo. Este efecto recibe el
nombre de conversino coercinde tipos
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Sistemas de tipos
Elementos de un sistema de tipos
La descripcin del sistema de tipos de un lenguaje de programacin se articula, fundamentalmente,
mediante la definicin de los tipos primitivos y constructores compuestos, sus reglas de composicin,
las operaciones permitidas sobre cada uno de ellos y el tipo de resultado que provocan
Verificacin de tipos sobre operadores
La mayora de operadores de un lenguaje de programacin pueden operarse satisfactoriamente
sobre un subconjunto de tipos primitivos del lenguaje. Esto desencadena una serie de conceptos tan
interrelacionados entre si que conviene abordarlos conjuntamente
Byte
Integer
Word
Real
Double
Error
Error
Error
Byte
Integer
Word
Real
Double
Boolean
Char
String
...
Byte Integer Word Real Double Boolean Char String
Integer
Integer
Word
Real
Double
Error
Error
Error
Word
Word
Word
Real
Double
Error
Error
Error
Real
Real
Real
Real
Double
Error
Error
Error
Double
Double
Double
Double
Double
Error
Error
Error
Error
Error
Error
Error
Error
Error
Error
Error
+
Error
Error
Error
Error
Error
Error
Error
Error
Error
Error
Error
Error
Error
Error
Error
Error
operador
tipos
Coercin o error
Matriz de compatibilidad para el operador +
Constructores
de tipos
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Sistemas de tipos
Elementos de un sistema de tipos
La descripcin del sistema de tipos de un lenguaje de programacin se articula, fundamentalmente,
mediante la definicin de los tipos primitivos y constructores compuestos, sus reglas de composicin,
las operaciones permitidas sobre cada uno de ellos y el tipo de resultado que provocan
Verificacin de tipos sobre subprogramas
La sobrecarga es un trmino que puede ser igualmente aplicado sobre los procedimientos y
funciones declarados en un programa. Esto permite soportar diferentes implementaciones de un
mismo subprograma con igual identificador pero diferente, nmero, tipo u orden de parmetros
formales en su declaracin. La implementacin invocada depender de los tipos aplicados en la
expresinde llamada
El procedimiento de suma est
sobrecargado. La sobrecarga de
subprogramas es ms propia de
lenguajes orientados a objetos que
de lenguajes estructurados. En ese
contexto se llama polimorfismo
La sobrecarga de subprogramas es la capacidad de un lenguaje de
permitir la declaracin de varios procedimientos o funciones con el mismo
nombre pero distinto, nmero, tipo u orden de parmetros formales
TYPE TVector = ARRAY [1..10] OF INTEGER
TMatriz = ARRAY [1..10][1..5] OF INTEGER
VAR v, w: Tvector; m, n : TMatriz;
PROCEDURE sumar (v, w: TVector; VAR r:TVector); ...
PROCEDURE sumar (m, n: TMatriz; VAR r:TMatriz); ...
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Construccin de comprobadores de tipos en la prctica
Artefactos de un comprobador de tipos
Antes de comenzar con la descripcin de la implementacin del comprobador de tipos para cada parte
de la gramtica de un lenguaje es necesario presentar la coleccin de artefactos que sern utilizados
dentro de la misma. A continuacindescribimos aquellos que aparecenen el framework de soporte
Consltese el documento
directrices de implementacin
Gestor de mbitos
La manera de gestionar los mbitos activos es a travs de una pila de mbitos interna. Cada
operacin openScope crea un nuevo objeto Scope y lo apila sobre la pila. Cada operacin
closeScope, saca el mbito de la cima de la pila
...
BEGIN
FOR i := 1 TO 10 DO
m [i] := Validar (Read (i));
END;
END;
ScopeManager
Ejemplo
...
FUNCTION suma (m, n: TVector) : TVector;
VAR i : INTEGER;
vSuma : TVector;
BEGIN
...
ScopeManager
Global [0]
suma[1]
...
BEGIN
Leer (v);
Leer (w);
v := suma (v, w);
END.
ScopeManager
Global [0] Global [0]
Leer[1]
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Construccin de comprobadores de tipos en la prctica
Implementacin de un comprobador de tipos sencillo en cup
Una vez conocidos los artefactos necesarios para implementar un comprobador de tipos, podemos
describir la forma del esquema de traduccin para cada seccin de una gramtica. En nuestros
ejemplos utilizaremos una estilo Pascal aunque es fcilmente trasladable a C. Como cup no admite
atributos heredados la solucin propuesta se ver someramente condicionada por este hecho
Apertura del mbito inicial
program ::= cabecera cuerpo;
cabecera ::= PROGRAM ID:id PYC {:
String name = id.getLexema ();
scopeManager.openScope (name);
// Insertar todos los TypeSimple en la TT
:};
cuerpo ::= declaraciones bSentencias; {:
scopeManager.closeScope (); :}
declaraciones ::= bConstantes
bTipos
bVariables
dSubprogramas;
bConstantes ::= CONST dConstantes | ;
bTipos ::= TYPE dTipos | ;
bVariables ::= VAR dVariables | ;
dConstantes ::= dConstantes dConstante
| dConstante;
dConstante ::= ID:id IGUAL rNumero:rn {:
ScopeIF scope = scopeManager.getCurrentScope ();
SymbolTable sTable = scope.getSymbolTable ();
String name = id.getLexema ();
Object value = rn.getValue ();
if (sTable.containsSymbol (name)) {
semanticErrorManager.semanticFatalError (...);
} else {
TypeIF type;
if (value instanceof Integer) type = TypeSimple.ENTERO;
if (value instanceof Float) type = TypeSimple.REAL;
if (value instanceof Boolean) type = TypeSimple.LOGICO;
SymbolConstant sC = new SymbolConstant (name, value, type);
sTable.add (sC);
:};
rNumero ::= NUM:n {:
RESULT = new RNumero (n.getValue ()); :}
Declaracin de constantes
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Construccin de comprobadores de tipos en la prctica
Una vez conocidos los artefactos necesarios para implementar un comprobador de tipos, podemos
describir la forma del esquema de traduccin para cada seccin de una gramtica. En nuestros
ejemplos utilizaremos una estilo Pascal aunque es fcilmente trasladable a C. Como cup no admite
atributos heredados la solucin propuesta se ver someramente condicionada por este hecho
Declaracin de constantes Declaracin de tipos
| ID:id {:
String name = id.getLexema ();
if (scopeManager.containsSymbol (name)) {
SymbolIF s = scopeManager.searchSymbol (name);
if (s instanceof SymbolConstant) {
SymbolConstant sC = (SymbolConstant) s;
Object value = sC.getValue();
RESULT = new RNumero (value);
} else
semanticErrorManager.semanticFatalError (...);
} else
semanticErrorManager.semanticFatalError (...);
:};
dTipos ::= dTipos dTipo
| dTipo;
dTipo ::= ID:id IGUAL tipo:t {:
String name = id.getLexema ();
TypeIF type = t.getType ();
type.setName (name);
ScopeIF scope = scopeManager.getCurrentScope ();
TypeTableIF tTable = scope.getTypeTable ();
tTable.addType (name, type);
:};
tipo ::= dArray:t {: RESULT = new Tipo (t.getType()); :}
| dRecord:t {: RESULT = new Tipo (t.getType()); :}
| rTipo:t {: RESULT = new Tipo (t.getType()); :};
rTipo ::= INTEGER {: RESULT = new RTipo (TypeSimple.ENTERO); :}
| REAL {: RESULT = new RTipo (TypeSimple.REAL); :}
Implementacin de un comprobador de tipos sencillo en cup
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Construccin de comprobadores de tipos en la prctica
Una vez conocidos los artefactos necesarios para implementar un comprobador de tipos, podemos
describir la forma del esquema de traduccin para cada seccin de una gramtica. En nuestros
ejemplos utilizaremos una estilo Pascal aunque es fcilmente trasladable a C. Como cup no admite
atributos heredados la solucin propuesta se ver someramente condicionada por este hecho
Declaracin de tipos Declaracin de tipos
| ID:id {:
String name = id.getLexema ();
if (scopeManager.containsType (name)) {
TypeIF type = scopeManager.searchType (name);
RESULT = new Rtipo (type);
} else
semanticErrorManager.semanticFatalError (...);
:}
dArray ::= ARRAY rArray:t PYC {:
RESULT = new dArray (t.getType ());
:};
rArray ::= CI rNumero::n1 DD rNumero:n2 CD rArray:t
{: Object min = n1.getValue ();
Object max = n2.getValue ();
TypeIF tBase = t.getType ();
TypeIF tArray = new TypeArray (min, max, tBase);
RESULT = new RArray (tArray); :}
| OF rTipo:t {: RESULT = new RArray (t.getType()); :};
dRecord ::= RECORD BEGIN bCampos:t END {:
RESULT = new DRecord (t.getTypeRecord ());
:};
bCampos ::= bCampos:t1 lCampos:t2 PYC {:
TypeRecord tR1 = t1.getTypeRecord ();
TypeRecord tR2 = t2.getTypeRecord ();
TypeRecord tR = new TypeRecord ();
if (tr2.constainsSome (tR1)) semanticErrorManager.semanti...
else { tR.addAllFields (tR1);
tR.addAllFields (tR2);
RESULT = new BCampos (tR); }
:}
| lCampos:t {:
TypeRecord tR = t.getTypeRecord ();
RESULT = new BCampos (tR); :};
:};
Implementacin de un comprobador de tipos sencillo en cup
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Construccin de comprobadores de tipos en la prctica
Una vez conocidos los artefactos necesarios para implementar un comprobador de tipos, podemos
describir la forma del esquema de traduccin para cada seccin de una gramtica. En nuestros
ejemplos utilizaremos una estilo Pascal aunque es fcilmente trasladable a C. Como cup no admite
atributos heredados la solucin propuesta se ver someramente condicionada por este hecho
Declaracin de tipos Declaracin de variables
lCampos ::= ID:id DP rTipo:t {:
String name = id.getLexema ();
TypeIF type = t.getType ();
TypeRecord tR = new TypeRecord ();
tR.addField (name, type);
RESULT = new LCampos (tR, type);
:}
| ID:id COMA lCampos:t {:
String name = id.getLexema ();
TypeRecord tR = t.getTypeRecord ();
if (!(tR.containsField (name))) {
TypeIF type = t.getType ();
tR.addField (name, type);
} else
semanticErrorManager.semanticFatalError (...);
:}
dVariables ::= dVariables dVariable
| dVariable;
dVariable ::= ID:id DP rTipo:t {:
String name = id.getLexema ();
TypeIF type = t.getType ();
ScopeIF scope = scopeManager.getCurrentScope ();
SymbolTable sTable = scope.getSymbolTable ();
if (!(sTable.containsSymbol (name))) {
SymbolVariable sV = new SymbolVariable (name, type);
sTable.addSymbol (name, sV);
RESULT = new DVariables (type);
} else semanticErrorManager.semanticFatalError (...);
:}
| ID:id COMA dVariables:t {:
<<igual que en la regla anterior>>
:};
Implementacin de un comprobador de tipos sencillo en cup
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Construccin de comprobadores de tipos en la prctica
Una vez conocidos los artefactos necesarios para implementar un comprobador de tipos, podemos
describir la forma del esquema de traduccin para cada seccin de una gramtica. En nuestros
ejemplos utilizaremos una estilo Pascal aunque es fcilmente trasladable a C. Como cup no admite
atributos heredados la solucin propuesta se ver someramente condicionada por este hecho
Declaracin de subprogramas Declaracin de subprogramas
dSubprogramas ::= dSubprogramas dSubprograma | ;
dSubprograma ::= dProcedimiento | dFuncion;
dProcedimiento ::= pCabecera cuerpo;
dFuncion ::= fCabecera cuerpo;
fCabecera ::= FUNCTION ID:id PI pFormales:pfs PD DP
rTipo:t {: String name = id.getLexema ();
if ((!scopeManager.containsSymbol (name)) &&
(scopeManager.containsType (name))) {
ScopeIF pScope = scopeManager.getCurrentScope ();
SymbolTableIF psTable = pScope.getSymbolTable ();
TypeTableIF ptTable = pScope.getTypeTable ();
TypeFunction tF = new TypeFunction (name);
SymbolFunction sF = new SymbolFunction (name, tF);
ScopeIF scope = scopeManager.openScope (name);
SymbolTableIF sTable = scope.getSymbolTable ();
for (SymbolParameter p : pfs.getParameters()) {
sTable.addSymbol (p.getName (), p);
tF.addParameterType (p.getType ()); }
tF.setReturnType (t.getType ());
ptTable.addType (name, tF);
psTable.addSymbol (name, sF);
} else semanticErrorManager.semanticFatalError (...); :}
pFormales ::= lPFormales:lpf {:
List <SymbolParameter> lp = lpf.getParameters ();
RESULT = new PFormales (lp);
:}
| {: RESULT = new pFormales (); :} ;
lPFormales ::= lPFormales:lpf PYC dPFormales:dpf {:
List <SymbolParameter> lp = dpf.getParameters ();
lpf.addAllParameters (lp);
RESULT = lpf;
:} | dPFormales:dpf {:
List <SymbolParameter> lp = dpf.getParameters ();
RESULT = new LPFormales (lp); :};
Implementacin de un comprobador de tipos sencillo en cup
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Construccin de comprobadores de tipos en la prctica
Una vez conocidos los artefactos necesarios para implementar un comprobador de tipos, podemos
describir la forma del esquema de traduccin para cada seccin de una gramtica. En nuestros
ejemplos utilizaremos una estilo Pascal aunque es fcilmente trasladable a C. Como cup no admite
atributos heredados la solucin propuesta se ver someramente condicionada por este hecho
Declaracin de subprogramas Expresiones
dPFormales ::= ID:id PD rTipo:t PYC {:
String n = id.getLexema ();
TypeIF type = t.getType ();
SymbolParameter sp = new SymbolParameter (n,type);
RESULT = new DPFormales (sp, type);
:}
| ID:id COMA dPFormales:dpf {:
String n = id.getLexema ();
TypeIF type = dpf.getType ();
SymbolParameter sp = new SymbolParameter(n,type);
dpf.addParameter (sp, type);
RESULT = dpf;
:};
pCabecera ::= FUNCTION ID:id PI pFormales:pfs PD {:
<< igual que en fCabecera pero sin tipo de
retorno e insertandoun Symbol/Type Procedure
en vez de un Symbol/Type Function >> :};
exp ::= exp:e1 MAS exp:e2 {:
TypeIF t1 = e1.getType ();
TypeIF t2 = e2.getType ();
if (t1.isCompatible (t2, TypeSimple.MAS)) {
TypeIF t = t1.cast (t2, TypeSimple.MAS);
RESULT = new Exp (t);
} else semanticErrorManager.semanticFatalError (...);
:}
| exp MENOS exp {:...:}
| exp POR exp {:...:}
| exp DIV exp {:...:}
| rNumero:rn {:
Object value = rn.getValue ();
TypeIF type;
if (value instanceof Integer) type = TypeSimple.ENTERO;
if (value instanceof Float) type = TypeSimple.REAL;
RESULT = new Exp (type); :}
Implementacin de un comprobador de tipos sencillo en cup
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Construccin de comprobadores de tipos en la prctica
Una vez conocidos los artefactos necesarios para implementar un comprobador de tipos, podemos
describir la forma del esquema de traduccin para cada seccin de una gramtica. En nuestros
ejemplos utilizaremos una estilo Pascal aunque es fcilmente trasladable a C. Como cup no admite
atributos heredados la solucin propuesta se ver someramente condicionada por este hecho
Expresiones Expresiones
| PI exp:e PD {:
TypeIF type = e.getType ();
RESULT = new Exp (type);
:}
| fCall:fc {:
TypeIF type = fc.getType ();
RESULT = new Exp (type);
:}
| referencia:ref {:
TypeIF type = ref.getType ();
RESULT = new Exp (type);
:}
referencia ::= ID:id {:
String name = id.getLexema ();
if (scopeManager.contains (name)) {
SymbolIF sId = scopeManager.searchSymbol (name);
TypeIF type = sId.getType ();
RESULT = new Referencia (type);
} else SemanticErrorManager.semanticFactalError (...);
:}
| referencia:r PTO ID:id {:
String name = id.getLexema ();
TypeIF rType = r.getType ();
if (rType instanceof TypeRecord) {
TypeRecord tRec = (TypeRecord) rType;
if (tRec.containsField (name)) {
Type innerType = tRec.getType (name);
RESULT = new Referencia (innerType);
} else SemanticErrorManager.semanticFactalError (...);
} else SemanticErrorManager.semanticFactalError (...);
:}
Implementacin de un comprobador de tipos sencillo en cup
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Construccin de comprobadores de tipos en la prctica
Una vez conocidos los artefactos necesarios para implementar un comprobador de tipos, podemos
describir la forma del esquema de traduccin para cada seccin de una gramtica. En nuestros
ejemplos utilizaremos una estilo Pascal aunque es fcilmente trasladable a C. Como cup no admite
atributos heredados la solucin propuesta se ver someramente condicionada por este hecho
Expresiones Expresiones
| referencia:r CI exp:e CD {:
TypeIF eType = e.getType ();
if (eType.equals(TypeIF.ENTERO)) {
Type rType = r.getType ();
if (rType instanceof TypeArray) {
TypeArray arrayType = (TypeArray) rType;
Type innerType = arrayType.getBaseType ();
RESULT = new Reference (innerType);
} else SemanticErrorManager.semanticFatal...;
} else SemanticErrorManager.semanticFatal...;
:}
fCall ::= ID:id PI pActuales:pa PD {:
String name = id.getLexema ();
if (scopeManager.containsSymbol (name)) {
SymbolIF s = scopeManager.searchSymbol (name);
if (s instanceof SymbolFunction) {
SymbolFunction sf = (SymbolFunction)s;
TypeFunction tF = sF.getType ();
List <TypeIF> aParams = pa.getParameterTypes ();
List <TypeIF> fParams = tF.getParameters ();
if (aParams.equals(fParams)) {
TypeIF returnType = tF.getReturnType ();
RESULT = new Fcall (returnType);
} else SemanticErrorManager.semanticFatalError (...);
} else SemanticErrorManager.semanticFatalError (...);
} else SemanticErrorManager.semanticFatalError (...);
:};
pActuales ::= pActuales:pa COMA exp:e {:
TypeIF type = e.getType();
pa.addParameterType (type);
RESULT = pa;
:}
| exp:e {: TypeIF type = e.getType ();
RESULT = new PActuales (type); :};
Implementacin de un comprobador de tipos sencillo en cup
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Construccin de comprobadores de tipos en la prctica
Una vez conocidos los artefactos necesarios para implementar un comprobador de tipos, podemos
describir la forma del esquema de traduccin para cada seccin de una gramtica. En nuestros
ejemplos utilizaremos una estilo Pascal aunque es fcilmente trasladable a C. Como cup no admite
atributos heredados la solucin propuesta se ver someramente condicionada por este hecho
Sentencias Sentencias
cuerpo ::= BEGIN lSentencias END PYC;
lSentencias ::= lSentencias sentencia | ;
sentencia ::= sentenciaIf |
sentenciaWhile |
sentenciaAsignacion |
pCall |
cuerpo;
sentenciaIf ::= IF PI exp:e PD THEN sentencia
ELSE sentencia {:
TypeIF type = e.getType ();
if (!(type instanceof TypeSimple.LOGICO))
semanticErrorManager.semanticFatalError (...);
:}
SentenciaWhile ::= WHILE PI exp:e PD DO sentencia {:
<<igual que sentenciaIf>>
:}
sentenciaAsignacin ::= referencia:r IGUAL exp:e PYC {:
TypeIF eType = e.getType ();
TypeIF rType = r.getType ();
if (rType instanceof TypeFunction ||
rType instanceof TypeProcedure) {
rType = rType.getReturnType ();
ScopeIF currentScope = scopeManager.getCurrentScope();
if (!r.getScope().equals(currentScope))
semanticErrorManager.semanticFatalError (...);
}
if (!(rType.isCompatible (eType, TypeIF.IGUAL)))
semanticErrorManager.semanticFatalError (...);
:}
pCall ::= ID:id PI pActuales:pa PD PYC; {:
<<igual que fCall>>
:}
Implementacin de un comprobador de tipos sencillo en cup
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Construccin de comprobadores de tipos en la prctica
Una vez esbozado el esquema de traduccin en cup para un comprobador de tipos sencillo sobre una
gramtica estilo Pascal, estamos en disposicin de tratar algunos temas avanzados de inters que
discutimos a continuacin
Inferencia de tipos
Temas avanzados de un comprobador de tipos
La inferencia de tipos es el proceso por el cual un comprobador de tipos infiere el tipo de una
construccin gramatical a partir de su contexto. Esto es especialmente til en lenguajes sin tipificacin
explcita
Ejemplo I
dConstante ::= ID:id IGUAL numero:n {:
...
String name = id.getLexema ();
Object value = n.getValue ();
TypeIF type;
if (value instanceof Integer) type = TypeSimple.ENTERO;
if (value instanceof Float) type = TypeSimple.REAL;
if (value instanceof Boolean) type = TypeSimple.LOGICO;
SymbolConstant sC = new SymbolConstant (name, value, type);
sTable.add (sC);
:};
dConstante
ID
numero
=
(3.5)
El caso ms sencillo de inferencia de tipos
se produce en la declaracin de
constantes. En efecto, el tipo de la
constante no se declara explcitamente sino
que se infiere del valor asignado a la misma
en la declaracin
(3.5)
{Real}
numero ID
{Byte, Word, Integer,
Real, Double}
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Construccin de comprobadores de tipos en la prctica
Una vez esbozado el esquema de traduccin en cup para un comprobador de tipos sencillo sobre una
gramtica estilo Pascal, estamos en disposicin de tratar algunos temas avanzados de inters que
discutimos a continuacin
Inferencia de tipos
Temas avanzados de un comprobador de tipos
La inferencia de tipos es el proceso por el cual un comprobador de tipos infiere el tipo de una
construccin gramatical a partir de su contexto. Esto es especialmente til en lenguajes sin tipificacin
explcita
Ejemplo II
exp ::= exp:e1 MAS exp:e2 {:
TypeIF t1 = e1.getTypes ();
TypeIF t2 = e2.getTypes ();
t1.removeIncompatibles (t2, TypeIF.MAS);
t2.removeIncompatibles (t1, typeIF.MAS);
SymbolVariable e1Var = e1.getVariable();
SymbolVariable e2Var = e2.getVariable();
if (e1Var != null) e1Var.setTypes (t1);
if (e2Var != null) e1Var.setTypes (t2);
if (t1.isEmpty() || t2.isEmpty) semanticErrorManager...;
else { Types types = new Types (t1);
types.addAllTypes (t2);
RESULT = new Exp (types); }
:}
exp
exp
exp
+
En el caso de lenguajes sin tipificacin, la
construccin sintctica infiere que los
nicos posibles valores para ID son los
numricos, descartando Boolean, Char y
String
(3.5)
{Real}
numero ID
{Byte, Word, Integer,
Real, Double}
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Construccin de comprobadores de tipos en la prctica
Una vez esbozado el esquema de traduccin en cup para un comprobador de tipos sencillo sobre una
gramtica estilo Pascal, estamos en disposicin de tratar algunos temas avanzados de inters que
discutimos a continuacin
Temas avanzados de un comprobador de tipos
Sobrecarga de subprogramas
Como ya se coment anteriormente, existen lenguajes que dan soporte a la sobrecarga de
subprogramas. Es decir permiten declarar varias versiones de funciones o procedimiento con igual
nombre pero distinto numero, tipo u orden de parmetros. La implementacin de esta capacidad se
estudiar para funciones ya que para procedimientos resulta similar
En la declaracin
fCabecera ::= FUNCTION ID:id PI pFormales:pfs PD DP
rTipo:t {:
String name = id.getLexema ();
TypeIF t = <<tipo para esta versin de la funcin>>
TypeFunction tFun = <<buscar el tipo por name>>
tFun.addSignature (t);
...
:}
fCall ::= ID:id PI pActuales:pa PD {:
String name = id.getLexema ();
if (scopeManager.containsSymbol (name)) {
TypeIF t = scopeManager.searchType (name);
if (t instance of TypeFunction) {
TypeFunction tF = (TypeFunction) t;
List<List<TypeIF>> signatures = tF.getSignatures ();
for (<<cada signatura>>) {
<<proceder como antes comprobando que alguna
signatura encaja con la llamada actual>>
}
}
}
Ahora cada TypeFunction contiene una
coleccin de signaturas (una lista interna de
lo que antes era TypeFunction). Al declarar
una nueva funcin ha de aadirse a la lista
En la invocacin
Javier Vlez Reyes jvelez@lsi.uned.es
Anlisis semntico. Comprobacin de tipos
Construccin de comprobadores de tipos en la prctica
Una vez esbozado el esquema de traduccin en cup para un comprobador de tipos sencillo sobre una
gramtica estilo Pascal, estamos en disposicin de tratar algunos temas avanzados de inters que
discutimos a continuacin
Temas avanzados de un comprobador de tipos
Recuperacin de errores semnticos
La recuperacin de errores semnticos es algo menos frecuente que la de errores sintcticos. Sin
embargo es posible realizarlo mediante una extensin conveniente del esquema de traduccin dirigido
por la sintaxis. En concreto se utilizan para expresiones y sentencias dos nuevos valores para el
atributo de tipo: error y correcto.
sentencia
IF
THEN
exp
Boolean = tipo. exp
sentencia
exp >
true 4
.tipo = ENTERO
.tipo = Correcto
.tipo = error
.tipo = error
Los errores se almacenan como formas de
tipo y se van acumulando para indicar qu
partes del rbol de anlisis sintctico
contiene error