Está en la página 1de 10

Manejo de tipos de las expresiones

Introduccin

Un lenguaje sigue una serie de reglas establecidas por convenciones de los


seres humanos, las cuales permiten una buena comunicacin entre ellos. Al
igual que los seres humanos, las computadoras tambin requieren de un
lenguaje el cual les permita comunicarse de computador a computador, y no
slo eso, sino que tambin debe de existir una manera de que el ser humano
pueda platicar con un ordenador.

Esta necesidad dio origen a la creacin de lenguajes que permiten a las


personas programar las funciones de las computadoras. Pero el lenguaje no
es suficiente, debe de existir una herramienta que traduzca el lenguaje que
un humano habla a un ordenador, al lenguaje que el ordenador entiende; a
esta herramienta se le conoce como traductor, o ms correctamente,
compilador.

Un lenguaje de programacin (y no slo de programacin, sino tambin de


maquetacin, estilos, creacin de macros, etc.) tambin adoptan las
convenciones de las cuales se hablaban hace un momento. Estas
convenciones, en una forma general, pueden categorizarse como reglas
lxicas, reglas sintcticas y reglas semnticas. Cada una de estas reglas
dictan la manera en que el lenguaje debe de ser escrito para que el
compilador comprenda las instrucciones que, posteriormente le traducir al
ordenador y ste ltimo deber de ejecutar.

Las reglas lxicas, de forma general, dictan que cada uno de los smbolos
empleados escritos en el lenguaje, deben de pertenecer al alfabeto del
mismo; las reglas sintcticas, por medio de una serie de gramticas, definen
la estructura y el acomodo de las cadenas; y las reglas semnticas dicen que
las instrucciones escritas deben de tener sentido. Pero, para garantizar que
esto se cumpla, cada uno de ellos realiza una serie de operaciones. En
cuanto al semntico, lleva a cabo una serie de comprobaciones:
comprobaciones de unicidad; comprobaciones de enlace; comprobaciones de
tipo, etc.
En este escrito nos enfocaremos a la comprobacin de tipos del anlisis
semntico, y ms especficamente, a la manera en que los tipos son
manejados.

El ensayo comienza hablando un poco de la comprobacin de tipos, as


como de los tipos que existen. Posteriormente se aborda acerca de la
expresin de tipo.

Ms adelante se ilustra con un ejemplo prctico de una gramtica libre de


contexto, la cual se transforma en una gramtica atribuida y posteriormente
se le aaden los predicados correspondientes.

El ensayo finaliza abordando el tema de sistema de tipos, donde se habla


del entendimiento que tuve acerca de l, se aborda un poco acerca de la
inferencia de tipos y de las reglas que debe de cumplir un compilador para
realizar la conversin de tipos equivalentes.
Manejo de tipos
Un compilador debe de comprobar si el programa fuente sigue tanto las
convenciones sintcticas como las semnticas del lenguaje fuente. Esta
comprobacin (perteneciente a la categora de comprobacin esttica)
garantiza la deteccin y conmutacin de algunas clases de errores de
programacin.

Como ya se mencion, el analizador semntico se encarga de realizar


distintos tipos de comprobaciones, entre ellas la comprobacin de tipos.

Un comprobador de tipos se asegura de que el tipo de una construccin


coincida con el previsto en su contexto (Louden, 2004).

Para disear un comprobador de tipos para un lenguaje, ste se basa en


informacin acerca de las construcciones sintcticas del lenguaje, la nocin
de tipos y las reglas para asignar tipos a las construcciones del lenguaje.

Existen dos categoras de tipos: tipos bsicos, y tipos construidos. Los tipos
bsicos corresponden a tipos atmicos sin una estructura interna, como
pueden ser int ,char , float , short ,boolean , etc. En cuanto a los lenguajes
construidos, son tipos que s cuentan con una estructura interna, como por
ejemplo String , Integer ; un tipo de dato abstracto definido por el
programador, como Persona, Transporte; un apuntador o una funcin (Ortn
et al, 2004).

El tipo de una construccin de un lenguaje se denota mediante una


expresin de tipo. Una expresin de tipo es una manera de expresar el tipo
de cualquier construccin de un lenguaje. Dicho de otra manera, es la forma
en que un procesador de lenguaje representa cada tipo del lenguaje que
procesa (Ortn et al, 2004).

A partir de las reglas semnticas se desarrolla la comprobacin de tipos


para expresiones, sentencias y funciones. El comprobador de tipos es un
esquema de traduccin que sintetiza el tipo de cada expresin a partir de los
tipos de las sub-expresiones (Tremblay & Sorenson, 1985).

Para comprobar los tipos en las expresiones, se utiliza un atributo que


indique el tipo de la expresin. Este tipo se infiere a partir de los distintos
componentes de la expresin y de las reglas de tipos definidas por el
lenguaje.

Abordando un ejemplo del lenguaje de programacin Pascal, las


expresiones estn definidas por la siguiente gramtica libre de contexto:

(1) expresion false


(2) expresion true
(3) expresion cte_caracter
(4) expresion cte_entera
(5) expresion cte_real
(6) expresion1 expresion2 AND expresion3
(7) expresion1 expresion2 OR expresion3
(8) expresion1 NOT expresion2
(9) expresion1 ( expresion2 )
(10) expresion1 expresion2 + expresion3
(11) expresion1 expresion2 expresion3
(12) expresion1 expresion2 * expresion3
(13) expresion1 expresion2 / expresion3
(14) expresion1 expresion2 div expresion3
(15) expresion1 expresion2 > expresion3
(16) expresion1 expresion2 < expresion3
(17) expresion1 expresion2 = expresion3

A partir de esta gramtica libre de contexto se define una gramtica


atribuida donde se aade un atributo por produccin:

P R
(1) expresion.et = boolean
(2) expresion.et = boolean
(3) expresion.et = char
(4) expresion.et = integer
(5) expresion.et = real
(6) expresion1.et = boolean
(7) expresion1.et = boolean
(8) expresion1.et = boolean
(9) expresion1.et = expresion2.et
(10) expresion1.et =
MayorTipo(expresion2.et,expresion3.et)
(11) expresion1.et =
MayorTipo(expresion2.et,expresion3.et)
(12) expresion1.et =
MayorTipo(expresion2.et,expresion3.et)
(13) expresion1.et =
MayorTipo(expresion2.et,expresion3.et)
(14) expresion1.et = integer
(15) expresion1.et = boolean
(16) expresion1.et = boolean
(17) expresion1.et = boolean

ExpTipo mayorTipo(ExpTipo t1,ExpTipo t2) {


if ( t1==real || t2==real ) return real;
return integer;
}

As mismo, es necesario especificar un conjunto de predicados los cuales


ayuden a identificar los casos de posibles errores de la gramtica atribuida:

P B
(6) expresion2.et==boolean && expresion3.et==boolean
(7) expresion2.et==boolean && expresion3.et==boolean
(8) expresion2.et==boolean
(10) realOentero(expresion2.et,expresion3.et)
(11) realOentero(expresion2.et,expresion3.et)
(12) realOentero(expresion2.et,expresion3.et)
(13) realOentero(expresion2.et,expresion3.et)
(14) expresion2.et==integer && expresion3.et==integer
(15) realOentero(expresion2.et,expresion3.et) ||
(expresion2.et==char && expresion3.et==char)
(16) realOentero(expresion2.et,expresion3.et) ||
(expresion2.et==char && expresion3.et==char)
(17) realOentero(expresion2.et,expresion3.et) ||
(expresion2.et==char && expresion3.et==char)

boolean realOentero(ExpTipo t1,ExpTtipo t2) {


return (t1==integer || t2==real) &&
(t1==integer || t2==real );
}

Ejemplo recuperado de Ortn et al (2004).


Como podemos observar en el ejemplo anterior, en la gramtica libre de
contexto se definen las posibles operaciones a realizar y al pasar a la
gramtica atribuida se aade el atributo et donde se le asocia un tipo de
dato para cada produccin de la gramtica libre de contexto. Este atributo
nos ayuda a determinar el resultado de las operaciones para el lenguaje, en
este caso Pascal. Algo que se puede observar de esta gramtica es que, en
las producciones 10, 11, 12 y 13, correspondientes a las operaciones
aritmticas bsicas, en la gramtica atribuida se aade un mtodo llamado
MayorTipo , el cual cumple la funcin de inferir el tipo de dato resultado. Lo
que hace bsicamente esta funcin es determinar si uno de los tipos es real,
el resultado ser real, sino ser entero.

Al pasar a los predicados, se aaden una serie de reglas que deben de


cumplirse para cada produccin. Como ejemplo, para las producciones 6, 7 y
8, correspondientes a operaciones lgicas, los operandos deben de ser
booleanos. En caso de no cumplir con la serie de predicados, se producir un
error que debe de ser capturado por el generador de errores e identificar
dicho error como error semntico.

El sistema de tipos es parte de la comprobacin de tipos, ste define una


serie de reglas que permiten asignar tipos a las distintas partes de un
programa y verificar su correccin. El sistema de tipos est formado por las
definiciones y reglas que permiten comprobar el dominio de un identificador
y en qu contexto puede ste ser usado. Cada lenguaje tiene su propio
sistema de tipos, y puede o no variar de una a otra implementacin, segn
sea el diseo de dicho lenguaje (Pyster, 1988).

Las funciones principales del sistema de tipos es la inferencia de tipos, la


cual debe de calcular y mantener la informacin sobre los tipos de datos; y la
verificacin de tipo, donde debe de asegurar que las partes de un programa
tiene sentido segn las reglas de tipo del lenguaje.

La comprobacin de tipos puede ser esttica o dinmica, pero debe de


tomarse en cuenta que entre ms comprobaciones se realicen en la fase de
compilacin, menos tendrn que realizarse durante la ejecucin, lo cual
repercute directamente en la eficiencia del programa objeto.

Parte de la comprobacin de tipos consiste en la conversin explcita, en


donde se realizan transformaciones del tipo de una expresin con un
propsito determinado; y la coercin, que consiste en la conversin de tipos
que realiza de forma implcita el compilador.

Con esto, podemos darnos una idea de que existen dos tipos conversin:
explcita e implcita. En la conversin explcita, el programador indica el tipo
de destino. sta funciona como una llamada a una funcin, la cual recibe un
tipo y devuelve otro. Y en la conversin implcita, es el compilador quien
convierte automticamente elementos de un tipo de elemento a otro. En este
caso la conversin se lleva a cabo en la accin semntica de la regla donde
se realiza.

Como sabemos, la informacin de tipos, ya sea implcita o explcita, se


mantiene en la tabla de smbolos. Por lo que esta informacin se recupera de
la tabla de smbolos mediante el verificador de tipo cuando se hace
referencia al nombre asociado.

Para analizar los diferentes tipos que intervienen dentro de un programa,


el compilador debe de contar con una estructura interna que le permita
manejar cmodamente las expresiones de tipos. Esta estructura interna debe
de ser fcilmente manipulable, pues su creacin se realiza conforme se hace
la lectura del programa fuente. Adems, debe de permitir comparar
fcilmente las expresiones asignadas a distintos trozos de cdigo,
especialmente a los identificadores de las variables (Ortn et al, 2004).

La caracterstica ms importante del sistema de tipos de un lenguaje es el


conjunto de reglas que permiten decidir cundo dos tipos de expresiones de
tipo son equivalentes. En muchos casos, estas reglas no se definen como
parte de las especificaciones del lenguaje, debido a diferentes
interpretaciones de los diseadores de compiladores.

Existen tres formas de equivalencia: estructural, nominal y funcional.

Equivalencia estructural. Es cuando se trata del mismo tipo bsico, o se


forman por aplicacin de un mismo constructor a tipos
estructuralmente equivalentes.

Equivalencia nominal. Dos tipos son nominalmente equivalentes


cuando son estructuralmente equivalentes considerando como tipos
bsicos e indivisibles a los identificadores de tipos.
Equivalencia funcional. Dos tipos se consideran equivalentes
funcionalmente cuando pueden emplearse indistintamente en un
mismo contexto.

Debe de entenderse la diferencia entre tipos compatibles y tipos


fundamentalmente equivalentes; en el primer caso, el compilador realiza
sobre uno de ellos una transformacin interna para que ambos se
transformen en tipos equivalentes; en el segundo caso, no se realiza ninguna
modificacin interna, sino que se realiza el criterio de equivalencia.

As mismo, es posible realizar distintas operaciones con un mismo


operador, como es el caso del operador de suma, que, en varios lenguajes (C,
Java, C#, Go, etc.) funciona como operador de suma y operador de
concatenacin. A esto se le conoce como sobrecarga de operadores. El
compilador debe de dar solucin a este problema segn sea el criterio del
diseador del lenguaje, si es que se permite operaciones de este tipo. En
este caso, deben de establecerse reglas y predicados para el manejo de
dicha sobrecarga, donde se especifique el tipo del resultado de la operacin.
Por ejemplo, si se tiene tres variables String text , int num , y String res , y se
realiza la siguiente operacin res=text +num , el sistema de tipos debe de
inferir que el resultado de la operacin text +num debe de ser tipo String y
ste es compatible con la variable res , debido a que son del mismo tipo.
Conclusin
El anlisis semntico, para comprobar que las instrucciones escritas en un
lenguaje tengan sentido, realiza una serie de comprobaciones. Entre las
comprobaciones que ste realiza se encuentra la comprobacin de tipos.

La comprobacin de tipos en el anlisis semntico es de suma importancia,


ya que ste se encarga de comprobar los tipos de los identificadores y de las
operaciones realizadas en un programa. As mismo, determinar el tipo del
resultado de dichas operaciones.

Una correcta comprobacin de tipos en tiempo de compilacin es de suma


importancia, ya que, entre ms comprobaciones durante el proceso de
compilacin se realicen, menos se harn durante tiempo de ejecucin, lo cual
repercute directamente en en la eficiencia de la ejecucin de un lenguaje de
programacin.

Otro aspecto importante es la conversin de tipos, para ello existen una


serie de reglas para las mismas, y queda a criterio del diseador del lenguaje
de decidir qu tipos son compatibles entre s y es posible realizar
operaciones entre ellos.
Referencias bibliogrficas

Ortn F., Cueva J., Luengo M., Juan A., Labra J., Izquierdo R. (2004). Anlisis
semntico en procesadores de lenguaje. Asturias, Espaa: Universidad de
Oviedo.

Tremblay J., Sorenson P. (1985). The theory and practice of compiler


writing. New York, NY: McGraw-Hill.

Pyster A. (1988). Compiler design and construction. New York, NY: Van
Nostrand Reinhold.

Louden K. (2004). Construccin de compiladores: principios y prctica (1ra


ed.). Thomson.

Glvez S., Mora M. (2005). Java a tope: traductores y compiladores con


LEX/YACC, JFLEX/CUP y JavaCC. Universidad de Mlaga: Mlaga, Espaa.