acl-book
TRANSCRIPT
-
Lenguajes de programacin y modelos
de computacin
1
Asignatura: Anlisis Comparativo de Lenguajes
Responsable: Ariel Gonzalez
e-mail: [email protected]
Departamento de Computacin
Facultad de Ciencias Exactas, Fsico-Qumicas y Naturales
Universidad Nacional de Ro Cuarto - Argentina
2013
1
Apunte elaborado por Mg. Marcelo Arroyo en colaboracin con Mg. Ariel Gonzalez.
-
Resumen
Este libro es el resultado del dictado del curso Anlisis Comparativo de Lenguajes
para alumnos de pregrado en la Universidad Nacional de Ro Cuarto.
Si bien existe una vasta bibliografa en el tema, es difcil encontrar un nico libro
que cubriese todos los temas y con el enfoque que es buscado en la asignatura.
Los principales objetivos de este trabajo es recopilar contenidos de varias fuentes
bibliogrcas y compilarlas desde un enfoque de las caractersticas de los lenguajes de
programacin a partir de un punto de vista de modelos de computacin y paradigmas
(o estilos) de programacin, desarrollando los conceptos relevantes de los lenguajes de
programacin.
En cada captulo se desarrollan los conceptos a partir de un lenguaje de progra-
macin bsico, para luego compararlo con las construcciones similares encontradas en
algunos lenguajes de programacin seleccionados.
Los lenguajes de programacin se han seleccionado por su difusin en la industria
y por su importancia desde el punto de vista acadmico, los cuales se analizan en base
a los conceptos bsicos estudiados.
El enfoque es centrado en la eleccin de un lenguaje ncleo, para el cual se dene
su sintaxis y semntica (en base a su mquina abstracta correspondiente). El mismo,
es extendido con adornos sintcticos y otras construcciones bsicas en funcin de las
caractersticas a analizar. La semntica formal permite realizar anlisis de correctitud
y su complejidad computacional.
Este material est dirigido a alumnos de segundo o tercer ao de carreras de cien-
cias de la computacin o ingeniera de software. Sus contenidos permiten desarrollar
un curso en cuatro meses de duracin con prcticas de aula y talleres. Al nal de cada
captulo se proponen ejercicios correspondientes a cada tema.
Los paradigmas estudiados implican el modelo imperativo, funcional, orientado
a objetos, lgico y el concurrente. Este ltimo modelo es transversal a los dems
modelos, por lo que se hace un anlisis y consideraciones en cada contexto en particular.
El lenguaje kernel seleccionado esOz, el cual es un lenguaje acadmico desarrollado
especcamente para el estudio de los diferentes modelos de computacin.
-
ndice general
1. Introduccin 8
1.1. Lenguajes como herramientas de programacin . . . . . . . . . . . . . . 9
1.2. Abstracciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.2.1. Abstraccin procedural . . . . . . . . . . . . . . . . . . . . . . . 10
1.2.2. Abstraccin de datos . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3. Evaluacin de un lenguaje de programacin . . . . . . . . . . . . . . . . 11
1.4. Denicin de un lenguaje de programacin . . . . . . . . . . . . . . . . . 12
1.4.1. Sintaxis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4.1.1. Lenguajes regulares . . . . . . . . . . . . . . . . . . . . 14
1.4.1.2. EBNFs y diagramas de sintaxis . . . . . . . . . . . . . . 15
1.4.2. Semntica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.5. Herramientas para la construccin de programas . . . . . . . . . . . . . 17
1.5.1. Bibliotecas estticas y dinmicas . . . . . . . . . . . . . . . . . . 18
1.6. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2. Lenguajes y modelos de programacin 24
2.1. Modelos o paradigmas de programacin . . . . . . . . . . . . . . . . . . 24
2.1.1. Lenguajes declarativos . . . . . . . . . . . . . . . . . . . . . . . . 26
2.1.2. Lenguajes con estado . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.2. Elementos de un lenguaje de programacin . . . . . . . . . . . . . . . . 27
2.3. Tipos de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.3.1. Tipos de datos simples o bsicos . . . . . . . . . . . . . . . . . . 30
2.3.2. Tipos de datos estructurados . . . . . . . . . . . . . . . . . . . . 31
2.3.3. Chequeo de tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.3.4. Sistemas de tipos fuertes y dbiles . . . . . . . . . . . . . . . . . 33
2.3.5. Polimorsmo y tipos dependientes . . . . . . . . . . . . . . . . . 33
2.3.6. Seguridad del sistema de tipos . . . . . . . . . . . . . . . . . . . 34
2.4. Declaraciones, ligadura y ambientes . . . . . . . . . . . . . . . . . . . . . 34
2.5. Excepciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
2.6. Qu es programar? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
2.7. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
2
-
3. El modelo declarativo 40
3.1. Un lenguaje declarativo . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.1.1. Memoria de asignacin nica . . . . . . . . . . . . . . . . . . . . 42
3.1.2. Creacin de valores . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.1.3. Un programa de ejemplo . . . . . . . . . . . . . . . . . . . . . . . 43
3.1.4. Identicadores de variables . . . . . . . . . . . . . . . . . . . . . 43
3.1.5. Valores parciales, estructuras cclicas y aliasing . . . . . . . . . . 44
3.2. Sintaxis del lenguaje ncleo declarativo . . . . . . . . . . . . . . . . . . 45
3.2.1. Porqu registros y procedimientos? . . . . . . . . . . . . . . . . 46
3.2.2. Adornos sintcticos y abstracciones lingusticas . . . . . . . . . . 46
3.2.3. Operaciones bsicas del lenguaje . . . . . . . . . . . . . . . . . . 48
3.3. Semntica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
3.3.1. La mquina abstracta . . . . . . . . . . . . . . . . . . . . . . . . 49
3.3.2. Ejecucin de un programa . . . . . . . . . . . . . . . . . . . . . . 50
3.3.3. Operaciones sobre ambientes . . . . . . . . . . . . . . . . . . . . 50
3.3.4. Semntica de las sentencias . . . . . . . . . . . . . . . . . . . . . 51
3.3.5. Ejemplo de Ejecucin . . . . . . . . . . . . . . . . . . . . . . . . 52
3.3.6. Sistema de Tipos del lenguaje ncleo declarativo . . . . . . . . . 54
3.3.7. Manejo de la memoria . . . . . . . . . . . . . . . . . . . . . . . . 54
3.3.8. Unicacin (operador '=') . . . . . . . . . . . . . . . . . . . . . . 54
3.3.9. El algoritmo de unicacin . . . . . . . . . . . . . . . . . . . . . 56
3.3.10. Igualdad (operador ==) . . . . . . . . . . . . . . . . . . . . . . 56
3.4. El modelo declarativo con Excepciones . . . . . . . . . . . . . . . . . . . 57
3.4.1. Semntica del try y raise . . . . . . . . . . . . . . . . . . . . . . 58
3.5. Tcnicas de Programacin Declarativa . . . . . . . . . . . . . . . . . . . 59
3.5.1. Lenguajes de Especicacin . . . . . . . . . . . . . . . . . . . . . 59
3.5.2. Computacin Iterativa . . . . . . . . . . . . . . . . . . . . . . . . 59
3.5.3. Del esquema general a una abstraccin de control . . . . . . . . . 60
3.5.4. Computacin Recursiva . . . . . . . . . . . . . . . . . . . . . . . 60
3.5.5. Programacin de Alto Orden . . . . . . . . . . . . . . . . . . . . 61
3.5.5.1. Abstraccin procedimiental . . . . . . . . . . . . . . . . 62
3.5.5.2. Genericidad . . . . . . . . . . . . . . . . . . . . . . . . . 62
3.5.5.3. Instanciacin . . . . . . . . . . . . . . . . . . . . . . . . 63
3.5.5.4. Embebimiento . . . . . . . . . . . . . . . . . . . . . . . 63
3.5.5.5. Curricacin . . . . . . . . . . . . . . . . . . . . . . . . 64
3.6. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
4. Lenguajes funcionales 69
4.1. Programacin funcional . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
4.2. Caractersticas principales . . . . . . . . . . . . . . . . . . . . . . . . . . 70
4.3. Ventajas y desventajas con respecto a la programacin imperativa . . . 71
4.4. Fundamentos tericos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
4.4.1. Clculo lambda . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
4.4.1.1. Reduccin . . . . . . . . . . . . . . . . . . . . . . . . . 74
4.4.1.2. Computacin y clculo lambda . . . . . . . . . . . . . . 74
4.4.1.3. Estrategias de reduccin . . . . . . . . . . . . . . . . . 76
3
-
4.4.2. Lgica combinatoria . . . . . . . . . . . . . . . . . . . . . . . . . 77
4.5. LISP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
4.5.1. Sintaxis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
4.5.2. Semntica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
4.5.3. Estado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
4.5.4. Aplicaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
4.6. Lenguajes funcionales modernos . . . . . . . . . . . . . . . . . . . . . . . 81
4.6.1. ML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
4.6.1.1. Tipos de datos estructurados . . . . . . . . . . . . . . . 82
4.6.1.2. Referencias (variables) . . . . . . . . . . . . . . . . . . . 84
4.6.1.3. Otras caractersticas imperativas . . . . . . . . . . . . . 84
4.6.2. Haskell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
4.6.2.1. Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
4.6.2.2. Casos y patrones . . . . . . . . . . . . . . . . . . . . . . 87
4.6.2.3. Evaluacin perezosa y sus consecuencias . . . . . . . . . 88
4.6.2.4. Ambientes . . . . . . . . . . . . . . . . . . . . . . . . . 88
4.6.2.5. Clases y sobrecarga de operadores . . . . . . . . . . . . 89
4.6.2.6. Emulacin de estado . . . . . . . . . . . . . . . . . . . . 90
4.7. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
5. Programacin Relacional 98
5.1. El modelo de Computacin Relacional . . . . . . . . . . . . . . . . . . . 98
5.1.1. Las sentencias choice y fail . . . . . . . . . . . . . . . . . . . . . 98
5.1.2. Arbol de Bsqueda . . . . . . . . . . . . . . . . . . . . . . . . . . 99
5.1.3. Bsqueda Encapsulada . . . . . . . . . . . . . . . . . . . . . . . . 99
5.1.4. La funcin Solve . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
5.2. Programacin Relacional a Lgica . . . . . . . . . . . . . . . . . . . . . 101
5.2.1. Semntica Operacional y Lgica . . . . . . . . . . . . . . . . . . 102
5.3. Prolog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
5.3.1. Elementos Bsicos . . . . . . . . . . . . . . . . . . . . . . . . . . 105
5.3.2. Clusulas Prolog . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
5.3.3. Fundamentos Lgicos de Prolog . . . . . . . . . . . . . . . . . . . 108
5.3.3.1. La forma Clausal y las clusulas de Horn . . . . . . . . 108
5.3.3.2. El Principio de Resolucin . . . . . . . . . . . . . . . . 109
5.3.3.3. Unicacin y Regla de Resolucin . . . . . . . . . . . . 110
5.3.4. Predicado cut (!) . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
5.3.5. Problema de la Negacin . . . . . . . . . . . . . . . . . . . . . . 115
5.3.6. Predicado fail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
5.4. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
6. El modelo con estado (statefull) 118
6.1. Semntica de celdas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
6.2. Aliasing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
6.3. Igualdad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
6.4. Construccin de sistemas con estado . . . . . . . . . . . . . . . . . . . . 122
6.4.1. Razonando con estado . . . . . . . . . . . . . . . . . . . . . . . . 123
4
-
6.4.2. Programacin basada en componentes . . . . . . . . . . . . . . . 123
6.5. Abstraccin procedural . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
6.6. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
7. Lenguajes de programacin imperativos 127
7.1. Declaraciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
7.2. Expresiones y comandos . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
7.3. Excepciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
7.4. Introduccin al lenguaje C . . . . . . . . . . . . . . . . . . . . . . . . . . 131
7.5. Estructura de un programa C . . . . . . . . . . . . . . . . . . . . . . . . 132
7.6. El compilador C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
7.7. Compilacin de un programa . . . . . . . . . . . . . . . . . . . . . . . . 134
7.8. El pre-procesador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
7.9. Tipos de datos bsicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
7.10. Declaraciones y deniciones . . . . . . . . . . . . . . . . . . . . . . . . . 136
7.11. Deniciones de variables . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
7.12. Deniciones de constantes . . . . . . . . . . . . . . . . . . . . . . . . . . 137
7.13. Deniciones de tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
7.14. Funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
7.15. Alcance de las declaraciones . . . . . . . . . . . . . . . . . . . . . . . . . 138
7.16. Tiempo de vida de las entidades . . . . . . . . . . . . . . . . . . . . . . 139
7.16.1. Cambiando el tiempo de vida de variables locales . . . . . . . . . 140
7.17. Operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
7.17.1. Asignacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
7.17.2. Expresiones condicionales . . . . . . . . . . . . . . . . . . . . . . 142
7.17.3. Otras expresiones . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
7.18. Sentencias de control: comandos . . . . . . . . . . . . . . . . . . . . . . 142
7.18.1. Secuencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
7.18.2. Sentencias condicionales . . . . . . . . . . . . . . . . . . . . . . . 143
7.18.3. Sentencias de iteracin . . . . . . . . . . . . . . . . . . . . . . . . 144
7.18.3.1. Iteracin denida . . . . . . . . . . . . . . . . . . . . . 144
7.18.3.2. Iteracin indenida . . . . . . . . . . . . . . . . . . . . 145
7.19. Tipos de datos estructurados . . . . . . . . . . . . . . . . . . . . . . . . 145
7.19.1. Arreglos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
7.19.2. Estructuras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
7.19.3. Uniones disjuntas . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
7.20. Punteros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
7.20.1. Vectores y punteros . . . . . . . . . . . . . . . . . . . . . . . . . 149
7.20.2. Punteros a funciones . . . . . . . . . . . . . . . . . . . . . . . . . 152
7.21. Manejo de memoria dinmica . . . . . . . . . . . . . . . . . . . . . . . . 153
7.22. Estructuracin de programas: mdulos . . . . . . . . . . . . . . . . . . . 153
7.23. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
5
-
8. Manejo de la memoria 157
8.1. Manejo de la memoria eciente . . . . . . . . . . . . . . . . . . . . . . . 157
8.2. Manejo del stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
8.2.1. Implementacin del manejo de alcance de ambientes. . . . . . . . 162
8.3. Valores creados dinmicamente. Manejo del heap. . . . . . . . . . . . . . 164
8.3.1. Manejo del heap . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
8.3.2. Manejo automtico del heap . . . . . . . . . . . . . . . . . . . . . 166
8.3.3. Algoritmos de recoleccin de basura . . . . . . . . . . . . . . . . 167
8.4. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
9. Programacin orientada a objetos 171
9.1. Objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
9.2. Clases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
9.3. Clases y objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
9.3.1. Inicializacin de atributos . . . . . . . . . . . . . . . . . . . . . . 176
9.3.2. Mtodos y mensajes . . . . . . . . . . . . . . . . . . . . . . . . . 176
9.3.3. Atributos de primera clase . . . . . . . . . . . . . . . . . . . . . . 177
9.4. Herencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
9.4.1. Control de acceso a mtodos (ligadura esttica y dinmica) . . . 178
9.5. Control de acceso a elementos de una clase . . . . . . . . . . . . . . . . 180
9.6. Clases: mdulos, estructuras, tipos? . . . . . . . . . . . . . . . . . . . . 181
9.7. Polimorsmo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
9.8. Clases y mtodos abstractos . . . . . . . . . . . . . . . . . . . . . . . . . 182
9.9. Delegacin y redireccin . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
9.10. Reexin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
9.11. Meta objetos y meta clases . . . . . . . . . . . . . . . . . . . . . . . . . 184
9.12. Constructores y destructores . . . . . . . . . . . . . . . . . . . . . . . . 185
9.13. Herencia mltiple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
9.14. El lenguaje Java (parte secuencial) . . . . . . . . . . . . . . . . . . . . . 187
9.14.1. Herencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
9.15. Generecidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
9.15.1. Templates (plantillas) de C++ . . . . . . . . . . . . . . . . . . . 190
9.16. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
10.Concurrencia 195
10.1. Concurrencia declarativa . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
10.1.1. Semntica de los threads . . . . . . . . . . . . . . . . . . . . . . . 196
10.1.2. Orden de ejecucin . . . . . . . . . . . . . . . . . . . . . . . . . . 197
10.2. Planicacin de threads (scheduling) . . . . . . . . . . . . . . . . . . . . 199
10.3. Control de ejecucin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
10.3.1. Corrutinas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
10.3.2. Barreras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
10.3.3. Ejecucin perezosa (lazy) . . . . . . . . . . . . . . . . . . . . . . 202
10.4. Aplicaciones de tiempo real . . . . . . . . . . . . . . . . . . . . . . . . . 203
10.5. Concurrencia y excepciones . . . . . . . . . . . . . . . . . . . . . . . . . 204
10.6. Sincronizacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
6
-
10.7. Concurrencia con estado compartido . . . . . . . . . . . . . . . . . . . . 205
10.7.1. Primitivas de sincronizacin . . . . . . . . . . . . . . . . . . . . . 207
10.8. Concurrencia con pasaje de mensajes . . . . . . . . . . . . . . . . . . . . 209
10.8.1. Semntica de los puertos . . . . . . . . . . . . . . . . . . . . . . . 210
10.8.2. Protocolos de comunicacin entre procesos . . . . . . . . . . . . . 210
10.9. Deadlock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
10.10.Concurrencia en Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
10.11.Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
7
-
Captulo 1
Introduccin
Los lenguajes de programacin son la herramienta de programacin fundamental
de los desarrolladores de software. Desde los comienzos de la computacin, la pro-
gramacin fue evolucionando desde la simple conguracin de interruptores, pasando
por los primeros lenguajes assembly, los cuales permitan escribir las instrucciones
de mquina en forma simblica y la denicin de macros, hasta llegar a los lenguajes
de programacin de alto nivel que permiten abstraer al programador de los detalles
de la arquitectura y el desarrollo de programas portables entre diferentes sistemas de
computacin
1
.
El objetivo de este material es estudiar los conceptos y principios que encontramos
en los lenguajes de programacin modernos.
Es importante conocer un poco la historia y la evolucin de algunos conceptos para
poder entender algunas caractersticas de algunos lenguajes.
En la actualidad se encuentran catalogados mas de 1500 lenguajes de programacin,
por lo cual una currcula en ciencias de la computacin o de desarrollo de software no
puede enfocarse en base al dictado de cursos sobre lenguajes concretos, sino que es
necesario que se estudien lenguajes de programacin desde el punto de vista de los
diferentes modelos o estilos de computacin en los cuales se basan.
Estos modelos o estilos permiten clasicar a los lenguajes de programacin en fa-
milias que generalmente se conocen como paradigmas.
El estudio de los lenguajes en base al anlisis de cada paradigma permite generalizar
conceptos utilizados en grupos de lenguajes mas que en lenguajes particulares.
El enfoque utilizado permite realizar anlisis de los conceptos utilizados en todos
los lenguajes de programacin existentes, permitiendo realizar comparaciones entre
lenguajes o familias.
El estudio de los conceptos y principios generales, en lugar de estudiar la sintaxis
de lenguajes especcos, permite que el desarrollador pueda estudiar y aprender por s
1
Un sistema de computacin comprende el hardware y el software de base, es decir, sistema oper-
ativo, enlazador, compiladores, editores, etc.
8
-
mismo, a utilizar correctamente las facilidades provistas por un nuevo lenguaje (o uno
desconocido).
Los paradigmas estudiados comprenden el declarativo, dentro del cual podemos
encontrar el funcional y el lgico, el imperativo, en el cual podemos encontrar una gran
cantidad de lenguajes ampliamente utilizados como Pascal, C, Basic, Ada, FORTRAN,
COBOL, . . . , con sus evoluciones en la programacin orientada a objetos (POO) y los
lenguajes basados en componentes.
Los conceptos y principios de la concurrencia son aplicables a todos los dems
paradigmas por lo que se estudia como un paradigma en particular analizndose su
aplicacin en cada modelo de computacin en particular.
1.1. Lenguajes como herramientas de programacin
Un lenguaje de programacin permite al programador denir y usar abstracciones.
El desarrollo de software se basa fundamentalmente en la utilizacin de los lenguajes
de programacin y los procesadores de lenguajes (compiladores, intrpretes y linkers).
Las dems herramientas son auxiliares (como los editores, entornos integrados de
desarrollo, generadores de Cdigo, etc.) y su objetivo es slo hacer ms cmoda, au-
tomatizable y rpida la tarea de produccin de cdigo.
Los mtodos de desarrollo de software, los cuales incluyen lenguajes textuales o
iconogrcos, estn basados en los mismos conceptos adoptados en los lenguajes de
programacin
2
.
La armacin anterior es fcilmente vericable ya que cualquier mtodo de de-
sarrollo deber permitir la generacin de cdigo al menos para algn lenguaje de
programacin.
1.2. Abstracciones
En la seccin anterior se arma que un lenguaje de programacin brinda mecanis-
mos para la denicin y utilizacin de abstracciones.
Estas abstracciones permiten que el programador tome distancia de las caracter-
sticas de bajo nivel del hardware para resolver problemas de una manera mas modular,
y contribuir as a un fcil mantenimiento a travs de su vida til.
Aceptando esta denicin de lo que es un lenguaje de programacin, es mas com-
prensible que los diseadores de software a gran escala, generalmente son personas
con amplios conocimientos sobre lenguajes (y su implementacin), y muestra que es
imposible que un (buen) diseador de software no haya pasado por una etapa de ver-
dadero desarrollo de software, es decir, la escritura de programas concretos en algn
lenguaje de programacin que incorpore conceptos modernos como abstracciones de
2
En realidad las caractersticas que encontramos en los mtodos de desarrollo se pueden encontrar
en lenguajes de programacin desarrollados con bastante anterioridad.
9
-
alto nivel.
Esto nos permite denir el trmino programacin.
Denicin 1.2.1 La programacin es la actividad que consiste en denir y usar ab-
stracciones para resolver problemas algortmicamente.
Es importante comprender as a la programacin, ya que esto muestra el porqu
los mejores programadores o diseadores son aquellos que tienen una buena base en
contenidos, en los cuales el concepto de abstraccin es indispensable en algunas reas
como la matemtica, la lgica y el lgebra.
Un lenguaje de programacin generalmente sugiere uno o ms estilos de progra-
macin, por lo que su estudio permite su mejor aprovechamiento en el proceso de
desarrollo de sotfware.
1.2.1. Abstraccin procedural
Una abstraccin procedural permite encapsular en una unidad sintctica una com-
putacin parametrizada.
Es bien conocida la estrategia de solucin de problemas conocido como divide and
conquer (divide y vencers), la cual se basa en la descomposicin del problema en un
conjunto de subproblemas mas simples y una forma de composicin de esos subprob-
lemas para obtener la solucin nal.
La abstraccin procedural es la base de la implementacin de esta estrategia de
resolucin de problemas. A modo de ejemplo, la programacin funcional se caracteriza
por la denicin de funciones y la composicin funcional. En cambio la programacin
imperativa se caracteriza por denir la evolucin de los estados de un sistema basndose
en la composicin secuencial y en operaciones de cambios de estado (asignacin).
1.2.2. Abstraccin de datos
Generalmente los programas operan sobre ciertos conjuntos de datos. Es bien cono-
cido que los cambios mas frecuentes producidos en un sistema son los de representacin
de los datos que se manipulan. Por este motivo es importante poder ocultar los detalles
de la representacin (o implementacin) de los datos para facilitar el mantenimiento
y la utilizacin de subprogramas.
Los tipos abstractos de datos (ADTs) permiten denir tipos de datos cuyos valores
estn implcitos o denotados por sus operaciones. Es deseable que los lenguajes de
programacin permitan la especicacin o implementacin de ADTs ocultando los
detalles de representacin.
Es sabido que no todos los lenguajes lo permiten, pero las tendencias actuales han
avanzado respecto a las capacidades de modularizacin y ocultamiento de informacin,
otorgando un mayor control en el encapsulamiento de los componentes de las abstrac-
ciones.
10
-
1.3. Evaluacin de un lenguaje de programacin
Un lenguaje de programacin puede ser evaluado desde diferentes puntos de vista.
En particular, un lenguaje debera tener las siguientes propiedades:
Universal: cada problema computable debera ser expresable en el lenguaje.
Esto deja claro que en el contexto de este libro, a modo de ejemplo, un lenguaje
como SQL
3
no es considerado un lenguaje de programacin.
Natural: con su dominio de su aplicacin.
Por ejemplo, un lenguaje orientado al procesamiento vectorial debera ser rico
en tipos de datos de vectores, matrices y sus operaciones relacionadas.
Implementable: debera ser posible escribir un intrprete o un compilador en
algn sistema de computacin.
Eciente: cada caracterstica del lenguaje debera poder implementarse utilizan-
do la menor cantidad de recursos posibles, tanto en espacio (memoria) y nmero
de computaciones (tiempo).
Simple: en cuanto a la cantidad de conceptos en los cuales se basa. A modo de
ejemplo, lenguajes como PLI y ADA han recibido muchas crticas por su falta
de simplicidad.
Uniforme: los conceptos bsicos deberan aplicarse en forma consistente en el
lenguaje. Como un contraejemplo, en Pascal las sentencias for y while aceptan
una nica sentencia en su cuerpo, mientras que la sentencia repeat acepta un
nmero variable de sentencias en su cuerpo.
En C el smbolo * se utiliza tanto para las declaraciones de punteros como para
los operadores de referenciacin y multiplicacin, lo que a menudo confunde y
da lugar a la escritura de programas difciles de entender.
Legible: Los programas deberan ser fciles de entender. Una crtica a los lengua-
jes derivados de C es que son fcilmente confundible los operadores == y =.
Seguro: Los errores deberan ser detectables, preferentemente en forma esttica
(en tiempo de compilacin).
Los lenguajes de programacin son las herramientas bsicas que el programador
tiene en su caja de herramientas. El conocimiento de esas herramientas y cmo y en
qu contexto debe usarse cada uno de ellos hace la diferencia entre un programador
recin iniciado y un experimentado especialista.
Es fundamental que los conceptos sobre lenguajes de programacin estn claros
para poder aplicar (y entender) las otras reas del desarrollo de software como lo son
las estructuras de datos, el diseo de algoritmos y estructuracin (diseo) de progra-
mas complejos. En denitiva estas tareas se basan siempre en un mismo concepto:
abstracciones.
3
En SQL no se pueden expresar clausuras.
11
-
1.4. Denicin de un lenguaje de programacin
Para describir un lenguaje de programacin es necesario denir la forma de sus
frases vlidas del lenguaje y de la semntica o signicado de cada una de ellas.
1.4.1. Sintaxis
Los mecanismos de denicin de sintaxis han sido ampliamente estudiados desde
los inicios de la computacin. El desarrollo de la teora de lenguajes y su clasicacin[6]
ha permitido que se denan formalismos de descripcin de lenguajes formales e inclu-
sive, el desarrollo de herramientas automticas que permiten generar automticamente
programas reconocedores de lenguajes (parsers y lexers) a partir de su especicacin
4
.
La sintaxis de un lenguaje se especica por medio de algn formalismo basado
en gramticas libres de contexto, las cuales permiten especicar la construccin (o
derivacin) de las frases de un lenguaje en forma modular.
Las gramticas libres de contexto contienen un conjunto de reglas de formacin de
las diferentes frases o categoras sintcticas de un lenguaje.
Denicin 1.4.1 Una gramtica libre de contexto (CFG) es una tupla
(VN ; VT ; S; P ), donde VN es el conjunto nito de smbolos no terminales, VT es elconjunto nito de smbolos terminales, S 2 VN es el smbolo de comienzo y P es unconjunto nito de producciones.
Los conjuntos VN y VT deben ser disjuntos ((VN \ VT ) = ;) y denotaremos =VN [ VT .
P es un conjunto de producciones, donde una produccin p 2 P tiene la forma(L;R), donde L 2 VN es la parte izquierda (lhs) de la produccin y R 2 (VN [VT ) esla parte derecha (rhs).
Por claridad, en lugar de describir las producciones como pares, se denotar a una
produccin rotulada p: (X0; (X1; : : : ; Xnp)), con np 0 como:
p : X0 ! X1 : : : Xnp (1.1)y en el caso que np = 0, se escribir como:
p : X0 ! (1.2)De aqu en adelante se asumir que el smbolo de comienzo S aparece en la parteizquierda de una nica produccin y no puede aparecer en la parte derecha de ninguna
produccin
5
.
Es comn que un conjunto de producciones de la forma fX ! ; : : : ;X ! g seabrevie de la forma X ! j : : : j .4
Como las populares herramientas lex y yacc.
5
Esta forma se denomina gramtica extendida.
12
-
Denicin 1.4.2 Sean ; 2 (VN [ VT ) y sea q : X ! ' una produccin de P,entonces XG
q
=)'La relacin
G
=) se denomina relacin de derivacin y se dice que la cadena Xderiva directamente (por aplicacin de la produccin q) a '.Cuando se desee hacer explcita la produccin usada en un paso de derivacin se
denotar como
G
q
=).Se escribir
G
*=) a la clausura reexo-transitiva de la relacin de derivacin.
Denicin 1.4.3 Sea G = (VN ; VT ; S; P ) una gramtica libre de contexto. Una cadena, obtenida por SG
*=) que contiene slo smbolos terminales ( 2 V T ), se denominauna sentencia de G. Si la cadena 2 (VT [VN ) (contiene no terminales) se denominaforma sentencial.
Denicin 1.4.4 El lenguaje generado por G, denotado como
L(G) = fwjw 2 V T j SG
*=)wgDenicin 1.4.5 Sea el grafo dirigido ST = (K;D) un rbol, donde K es un conjuntode nodos y D es una relacin no simtrica, con k0 como raz, una funcin de rotulacinl : K ! VT [ y sean k1; : : : ;Kn, (n > 0), los sucesores inmediatos de k0.El rbol ST = (K;D) es un rbol de derivacin (o parse tree) correspondiente a
G =< VN ; VT ; P; S > si cumple con las siguientes propiedades:
1. K (VN [ VT [ )2. l(K0) = S
3. S ! l(k1) : : : l(kn)4. Si l(ki) 2 VT , (1 i n), o si n = 1 y l(k1) = , entonces Ki es una hoja de
ST .
5. Si l(ki) 2 VN , (1 i n), entonces ki es la raz del rbol sintctico para lagramtica libre de contexto < VN ; VT ; P; l(ki) >.
Denicin 1.4.6 Sea ST(G) un rbol de derivacin para G =< VN ; VT ; S; P >. Lafrontera de ST(G) es la cadena l(k1) : : : l(kn) tal que k1 : : : kn es la secuencia formadapor las hojas de ST(G) visitadas en un recorrido preorden.
Teorema 1.4.1 Sea G =< VN ; VT ; S; P > una gramtica libre de contexto, SG
*=) siy slo si existe un rbol de derivacin para G cuya frontera es .
La gura 1.1 muestra una gramtica libre de contexto y un rbol de derivacin
para la cadena a + b * c.
La gramtica dada en la gura 1.1 es ambiga, ya que para una misma cadena
existen dos (o ms) rboles de derivacin diferentes. Una gramtica puede desam-
bigarse introduciendo producciones que denan la precedencia entre los diferentes no
terminales.
13
-
E > E + EE > E * EE > id
E
+E E
*E Ea
b c
Figura 1.1: Una CFG y un rbol de derivacin.
Denicin 1.4.7 Dos gramticas g1 y g2 son equivalentes si generan el mismo lengua-je, es decir que L(g1) = L(g2)6
.
Hay gramticas inherentemente ambigas para las cuales no existe una gramtica
equivalente no ambiga.
1.4.1.1. Lenguajes regulares
Las palabras que se pueden formar en un lenguaje generalmente se describen con
formalismos que no requieren describir estructuras de las frases. Estos formalismos se
conocen como las gramticas regulares. Existen otros formalismos equivalentes ampli-
amente utilizadas, como las expresiones regulares.
Denicin 1.4.8 Una gramtica regular es una gramtica cuyas producciones tienen
la forma: X ! Y a y X ! a, donde X;Y 2 N y a 2 T .
Estas gramticas slo permiten describir la conformacin de las palabras o tokens
de un lenguaje lenguaje, pero no es posible describir la estructura de frases. A modo
de ejemplo se muestra una gramtica regular que describe la formacin de un valor
entero positivo:
N --> N '0' | N '1' | ... | N '9' | '0' | '1' | ... | '9'
El ejemplo anterior muestra que es extenso denir la forma de construccin de
smbolos de un lenguaje por medio de una gramtica regular, por lo que es comn que
se denan por medio de un formalismo, las expresiones regulares, cuya expresividad es
equivalente y permiten deniciones mas compactas y legibles.
A continuacin se da una gramtica libre de contexto que describe la sintaxis de
una expresin regular:
E --> t
| E E -- secuencia
6
La determinacin si dos gramticas libres de contexto son equivalentes es indecidible, es decir, no
existe un algoritmo que lo determine.
14
-
| (E '|' E) -- alternativa (choice)
| (E)? -- opcional (cero o una vez)
| (E)* -- cero o ms veces
donde t es un smbolo terminal.
Las gramticas regulares extendidas introducen otras construcciones ms cmodas
en la prctica como las siguientes:
E --> [ E ... E ] -- set: equivalente a (E | ... | E)
| (E)+ -- una o ms veces: equivalente a (E(E)*)
1.4.1.2. EBNFs y diagramas de sintaxis
Una Extended Backus Naur Form es una extensin de las gramticas libres de
contexto que permite la descripcin de un lenguaje en forma mas compacta.
Informalmente, se puede decir que permiten escribir expresiones regulares exten-
didas en la parte derecha de las producciones. Las notaciones mas comunmente mas
utilizadas son:
(S): S ocurre una o mas veces.
fSg: S ocurre cero o mas veces.[S]: S es opcional (cero o una vez).
A continuacin de muestra un ejemplo de una EBNF.
...
var-decl --> var id {',' id} ':' type ';'
type --> integer | real | ...
...
if-stmt --> if condition then stmt [ else stmt ]
...
decl
const_decl
proc_fun_decl
var_decl
type_decl
var_decl "var" id ":" id ";"
Figura 1.2: Ejemplo de diagramas de sintaxis.
15
-
Los diagramas de sintaxis son una representacin grca por medio de un grafo
dirigido el cual muestra el ujo de aparicin de los componentes sintcticos. Los nodos
del grafo corresponden a los smbolos terminales y no terminales y los arcos indican
el smbolo que puede seguir en una frase. Es comn que los nodos correspondientes
a los smbolos terminales se denoten con crculos y los nodos que corresponden a no
terminales se denoten como valos.
La gura 1.4.1.2 muestra un ejemplo de diagramas de sintaxis.
1.4.2. Semntica
La semntica de un lenguaje de programacin describe el signicado, compor-
tamiento o efectos de las diferentes frases del lenguaje.
Es muy comn que en los manuales de los lenguajes de programacin la semntica
de cada una de las frases de describa de manera informal.
Esta informalidad ha llevado muchas veces a confusiones en los programadores o
los implementadores de herramientas como compiladores e intrpretes, causando que
los resultados de un programa en una implementacin no sean los mismos que en otra
7
.
Para dar una denicin precisa de la semntica de un lenguaje es necesario utilizar
algn formalismo que describa en forma clara y no ambiga el signicado de las frases.
Se han utilizado diferentes estilos de formalismos para dar semntica:
Denotacional: cada construccin del lenguaje se relaciona con alguna entidad
matemticas (ej: conjuntos, funciones, etc) que representa el signicado de cada
estructura.
Esta forma de dar semntica es til desde el punto de vista terico, pero en
general no es cmodo para los implementadores de lenguajes y los desarrolladores.
Operacional: descripcin del efecto o ejecucin de cada construccin del lengua-
je en una mquina abstracta dada. Una mquina abstracta est basada en algn
modelo de computacin.
Esta forma es til tanto para los implementadores del lenguaje como para los de-
sarrolladores de programas, ya que tienen una visin mas concreta (operacional)
del lenguaje.
Axiomtica: descripcin de cada construccin del lenguaje en trminos de cam-
bios de estado. Un ejemplo es la lgica de Hoare, que es muy til para el desarrollo
y vericacin formal de programas imperativos.
Esta tcnica es til para los desarrolladores pero no demasiado buena para los
implementadores del lenguaje.
En este libro se utilizar la semntica operacional para dar el signicado al lenguaje
que se ir desarrollando en cada captulo, siguiendo la idea de lenguaje ncleo (kernel)
el cual permite dar una sintaxis y semntica de manera sencilla para luego adornar
el lenguaje con mejoras sintcticas (syntactic sugars) y abstracciones sintcticas o
lingsticas prcticas, las cuales tendrn un patrn de traduccin al lenguaje ncleo.
7
Esto ha sucedido en C, C++, FORTRAN, y hasta en los lenguajes de reciente aparicin.
16
-
1.5. Herramientas para la construccin de programas
El programador cuando utiliza un lenguaje de programacin, utiliza herramientas
que implementan el lenguaje. Estas herramientas son programas que permiten ejecutar
en la plataforma de hardware utilizada las construcciones del lenguaje de alto nivel.
En general se disponen de las siguientes herramientas:
Compilador: traduce un programa fuente a un programa assembly u objeto
(archivo binario enlazable).
Intrprete: programa que toma como entrada programas fuentes, genera una
representacin interna adecuada para su ejecucin y evala esa representacin
emulando la semntica de las construcciones del programa dado.
Es posible encontrar intrpretes de bajo nivel, tambin conocidos como ejecutores
de programas. Estos ejecutores interpretan lenguajes de bajo nivel (assembly real
o hipottico).
Es comn que una implementacin de un lenguaje venga acompaado por un
compilador a un assembly de una mquina abstracta y un intrprete de ese
lenguaje de alto nivel. Ejemplos de esto son algunos compiladores de COBOL,
Pascal (se traduca a P-code).
Actualmente uno de los casos mas conocidos sea Java. Es comn que un compi-
lador de Java traduzca los mdulos a un assembly sobre una mquina abstracta
conocida como la Java Virtual Machine (JVM).
Este ltimo enfoque permite obtener portabilidad binaria, ya que es posible eje-
cutar un programa en cualquier plataforma que tenga una implementacin (in-
trprete) de la mquina abstracta.
Enlazador (linker): un archivo objeto puede hacer referencia a smbolos (vari-
ables, rutinas, etc) de otros archivos objetos. Estas referencias se denominan
referencias externas. El linker toma un conjunto de archivos objetos
8
, arma una
imagen en memoria, resuelve las referencias externas de cada uno (asigna direc-
ciones de memoria concretas a cada referencia externa no resuelta) y genera un
archivo binario ejecutable (programa).
En forma ms rigurosa, un linker bsicamente implementa una funcin que toma
una referencia a un smbolo externo y retorna la direccin de memoria de su
denicin.
Generalmente cada archivo objeto se corresponde con un mdulo del programa
fuente. La modularizacin es til para dividir grandes programas en unidades
lgicas reusables.
8
Generalmente llamados mdulos binarios.
17
-
Adems, los ambientes de desarrollo generalmente vienen acompaados por m-
dulos bsicos para hacerlo mas til en la prctica (mdulos para hacer entrada-
salida, funciones matemticas, implementacin de estructuras de datos, etc) lo
que comnmente se conoce como la biblioteca estndar del lenguaje.
Analizador
(lexer)lexico
Analizadorsintactico(parser)
objeto
biblioteca
archivo
referenciasresolucion de
externasedicion ejecutable
archivo
(programa)
Linkeditor (linker)
generadorde codigo
(assembly)codigo
mov ax,...
Optimizador
AnalizadorSemantico
(type checker)fuente tokens
if ( ...
assembler
Compilador
archivoobjeto
archivoif
(
...
Figura 1.3: Esquema de compilacin de un programa.
La gura 1.3 muestra un esquema del proceso de compilacin de un programa.
1.5.1. Bibliotecas estticas y dinmicas
Una biblioteca es un archivo que contiene archivos objeto.
Generalmente un programa de usuario se enlaza con al menos unas cuantas ruti-
nas bsicas que comprenden el sistema de tiempo de ejecucin (runtime system). El
runtime system generalmente incluye rutinas de inicio (start-up) de programas
9
, y la
implementacin de otras rutinas bsicas del lenguaje.
Cuando en el programa obtenido se incluye el cdigo (y posiblemente datos) de las
rutinas de biblioteca utilizadas se denomina enlazado esttico (static linking).
Un programa enlazado estticamente tiene la ventaja que cuando se lo transporta
a otra computadora tiene todas sus dependencias resueltas, es decir que todas sus
9
Una rutina de startup generalmente abre archivos de entrada-salida estndar e invoca a la rutina
principal del programa.
18
-
referencias (a datos y cdigo) estn resueltas y todo est contenido en un nico archivo
binario.
Los primeros sistemas de computacin generalmente soportaban este nico tipo de
enlazado. De aqu el nombre a estos linkers conocidos como link-editores.
A medida que el tamao de los programas crece, el uso de bibliotecas generales
es comn. Ms an, en los sistemas multitarea (o multiprogramacin), comienzan a
aparecer varias desventajas y el mecanismo de enlazado esttico se torna prcticamente
inviable.
Las principales desventajas son:
El tamao de los programas se hace muy grande.
En un sistema multitarea hay grandes cantidades del mismo cdigo replicado en
la memoria y en el sistema de archivos.
No tiene en cuenta la evolucin de las bibliotecas, cuyas nuevas versiones pueden
corregir errores o mejorar su implementacin.
Por este motivo aparece el enfoque de las bibliotecas de enlace dinmico
10
(DLLs).
Este enfoque requiere que el sistema operativo contenga un linker dinmico, es
decir que resuelva las referencias externas de un mdulo (archivo objeto) en tiempo
de ejecucin.
Cuando un proceso (instancia de programa en ejecucin) hace referencia a una
entidad cuya direccin de memoria no haya sido resuelta (referencia externa), ocurre
una trampa (trap) o excepcin generada por el sistema operativo. Esta trampa dispara
una rutina que es la encargada de realizar el enlace dinmico.
Posiblemente se requiera que el cdigo (o al menos la parte requerida) de la bib-
lioteca sea cargada en la memoria (si es que no lo estaba).
Cabe hacer notar que los archivos objetos deben acarrear mas informacin de utili-
dad por el linker dinmico. Un programa debe acarrear la lista de bibliotecas requeridas
y cada archivo objeto de cada bibliotecas debe contener al menos el conjunto de sm-
bolos que exporta.
Las principales ventajas que tiene este mecanismo son:
El cdigo de las rutinas de las bibliotecas se encuentra presente una sola vez (no
hay mltiples copias).
El cdigo se carga baja demanda. Es decir que no se cargar el cdigo de una
biblioteca que no haya sido utilizada en una instancia de ejecucin.
Como desventaja tiene que la ejecucin de los programas tiene una sobrecarga adi-
cional (overhead) que es el tiempo insumido por la resolucin de referencias externas
10
En el mundo UNIX son conocidas como shared libraries.
19
-
y la carga dinmica de cdigo.
Un linker con capacidades de generar bibliotecas dinmicas deber generar archivos
objetos con la informacin adicional que mencionamos arriba y el sistema operativo
deber permitir ejecutar cdigo reubicable, es decir independiente de su ubicacin en
la memoria
11
.
Una biblioteca compartida no debera tener estado propio, ya que puede ser utiliza-
da por mltiples procesos en forma simultnea, es decir que es un recurso compartido
por varios procesos. Por ejemplo, un programador de una biblioteca que pueda uti-
lizarse en forma compartida no podr utilizar variables globales.
Lo anterior es muy importante a la hora de disear bibliotecas. Es bien conocido
el caso de la biblioteca estndar de C, la cual dene una variable global (errno), la
cual contiene el cdigo de error de la ltima llamada al sistema realizada.
Al querer hacer la biblioteca de C compartida, los desarrolladores tuvieron que
implementar un atajo para solucionar este problema.
1.6. Ejercicios
Nota: los ejercicios estn planteados para ser desarrollados en un sistema que
disponga de las herramientas de desarrollo comnmente encontrados en sistemas tipo
UNIX. El prctico se puede desarrollar en cualquier plataforma que tenga instaladas
las herramientas bsicas de desarrollo del proyecto GNU (software libre) instaladas.
Herramientas necesarias: gcc (GNU Compiler Collection), gpc (GNU Pascal Com-
piler), ld, grep y wc.
1. Denir una expresin regular que denote un identicador en Pascal.
2. Denir un autmata nito que acepte el lenguaje denotado por la expresin
regular del ejercicio anterior.
3. Usar el comando grep
12
que seleccione las lneas del archivo fuente Pascal del
ej. 7 los siguientes patrones:
a) Las lneas que contengan Var
b) Las lneas con comentarios
c) Comparar la cantidad de begin y la cantidad de end en un programa Pascal.
Ayuda: usar grep y wc.
4. Dar una EBNF que dena las sentencias de Pascal.
11
Esto se logra utilizando algn mecanismo de memoria virtual (segmentacin o paginado)
12
Uso: grep expresin-regular [le]. Para mas informacin hacer "man grep".
20
-
5. Implementar un programa que reconozca frases segn la siguiente EBNF:
E ! T [0+0E]T ! F [00T ]F ! V j 0(0E0)0V ! (000j010j020j030j040j050j060j070j080j090)+Ayuda: Por cada regla de la gramtica de la forma X !0 a0Y 0b0 se puede denirun procedimiento con la forma:
Procedure X;
begin
if current_token = 'a' then begin
next_token;
Y
end
else
error;
if current_token = 'b' then
next_token
else
error
end;
donde next_token es un procedimiento que obtiene el prximo (smbolo) token
de la entrada.
Para sta gramtica next_token debera reconocer (y obtener) valores numricos
y los smbolos + y * (e ignorar espacios, tabs y new-lines).
Generar patrones de cdigo para reglas que contengan componentes opcionales
(0 o una vez) y repeticiones (0 o mas y 1 o mas).
6. Extender el programa anterior para que evale la expresin.
Ayuda: utilizar una pila de operandos y una pila de operadores.
7. Dado el siguiente programa Pascal y el siguiente fragmento de cdigo C. El
programa CallToC declara una variable externa, le asigna un valor e invoca a un
procedimiento externo, el cual est implementado en C (en el mdulo inc.c),
Program CallToC;
Var x:integer; external name 'y';
Procedure inc_x; external name 'inc_y';
begin { programa principal }
x := 1;
inc_x;
21
-
writeln('x=',x)
end.
/* file inc.c */
int y; /* global integer y */
void inc_y(void)
{
y++;
}
a) compilar el programa Pascal (usando gpc). En caso de error describir su
origen y quin lo genera (compilador o linker).
b) compilar el fragmento de programa C para obtener el archivo objeto corre-
spondiente
13
analizando los pasos realizados. Usar el comando objdump -t
inc.o para ver los smbolos denidos en el archivo objeto.
c) generar un archivo ejecutable en base a los dos mdulos.
d) describir qu pasos se realizaron (compilacin, assembly, linking) en el punto
anterior.
8. Generar una biblioteca esttica (llamada libmylib.a) que contenga el archivo
objeto inc.o (del ejercicio anterior) con la utilidad ar.
Usar el siguiente programa C (el cual invoca a inc_y()) para compilarlo enlazarlocon la biblioteca mylib.
int main(void)
{
inc_y();
}
9. Recompilar el programa Pascal denido arriba usando la biblioteca creada en el
ejercicio anterior.
10. El siguiente programa C muestra la carga de una biblioteca dinmica (math), la
resolucin de una referencia (externa) a la funcin cos (denida en math) y la
invocacin a cos(2.0).
/* File: foo.c */
#include
#include
#include
int main()
{
13
Usar el comando gcc -v -c inc.c.
22
-
void *handle;
double (*cosine)(double); /* Pointer to a function */
/* Load the math library */
handle = dlopen("libm.so", RTLD_LAZY);
/* Get (link) the "cos" function: we get a function pointer */
cosine = (double (*)(double)) dlsym(handle, "cos");
printf("%f\n", cosine(2.0));
dlclose(handle);
exit(EXIT_SUCCESS);
}
Compilar el programa (con el comando gcc -rdynamic -o foo foo.c -ldl) y ejecu-
tarlo.
23
-
Captulo 2
Lenguajes y modelos de
programacin
Un lenguaje de programacin provee tres elementos principales:
1. un modelo de computacin, el cual dene una sintaxis y la semntica (formal o
informal) de sus frases o sentencias.
2. un conjunto de tcnicas de programacin, las cuales denen un modelo o estilo
de programacin.
3. algn mecanismo para el anlisis de programas (razonamiento, clculos de e-
ciencia, etc).
Estos tres puntos denen lo que se conoce como paradigma de programacin.
Un lenguaje de programacin contiene diferentes tipos de constructores con su
sintaxis y su semntica propia. Las diferentes construcciones o frases de un lenguaje
generalmente se denominan sentencias y pueden clasicarse segn su intencin o uso
en un programa.
En este captulo, se analizan las diferentes tipos de sentencias y los conceptos funda-
mentales que podemos encontrar en un lenguaje de programacin, independientemente
al paradigma o modelo que pertenezca.
2.1. Modelos o paradigmas de programacin
Un modelo o paradigma de programacin dene un estilo de programacin. Cada
modelo puede hacer que el programador piense los problemas a resolver desde difer-
entes perspectivas. Los modelos de programacin pueden dividirse, en principio, en
dos grandes grupos:
Modelo declarativo, en donde no existe la nocin de estado (stateless). Es decirque la ejecucin de un programa evoluciona generando nuevos valores. Estos
24
-
valores nunca cambian. Es decir que la nocin de variable (valor mutable) no
existe, sino que los identicadores se ligan (asocian) a valores y esa asociacin se
mantiene inmutable.
Modelo con estado, donde el concepto fundamental es la nocin de asignacin devalores a variables, es decir celdas con contenido mutable en la memoria.
El modelo sin estado se denomina declarativo porque el estilo de programacin permite
enfocar en la descripcin de las computaciones ms que en el detalle de cmo se deben
realizar. En el modelo con estado, generalmente se decribe una computacin como la
evolucin temporal del estado del programa, es decir que se expresa la forma progresiva
en que se arriba a una solucin.
Cada modelo tiene sus ventajas y desventajas.
En el modelo declarativo las ventajas pueden ser:
a) claridad y simplicidad de los programas, ya que no se expresan en trminos de
cambios de estado.
b) permite razonamiento modular (se puede analizar cada unidad en forma indepen-
diente) y usando tcnicas simples como lgica ecuacional e induccin (aritmtica
y/o estructural).
Como desventaja podemos mencionar:
a) algunos problemas se modelan naturalmente con estado. Por ejemplo, operaciones
de entrada-salida, programas cliente-servidor, etc.
b) generalmente se logran rendimientos menores con respecto a programas equivalentes
con estado.
En el modelo con estado podemos mencionar las siguientes ventajas:
a) eciencia.
b) el modelo de programacin est ntimamente relacionado con las arquitecturas de
las computadoras actuales (arquitecturas Von Newman).
El modelo con estados, sin embargo tiene sus desventajas:
a) prdida de razonamiento al estilo ecuacional (ya no es posible reemplazar iguales
por iguales).
b) prdida de razonamiento modular, debido a que las diferentes unidades de programa
pueden actuar sobre una misma porcin del estado del programa.
Denicin 2.1.1 Una expresin es transparente referencialmente si puede ser
reemplazada con el valor denotado por su evaluacin en cada parte del programa que
aparezca. En otro caso diremos que la expresin tiene efectos colaterales.
Las funciones matemticas son transparentes referencialmente, aunque en progra-
macin no necesariamente. En el programa de la gura el siguiente programa de ejem-
plo, suponiendo que f(v) retorna el sucesor de v :
25
-
x := 1;
fx = 1gy := f(x) + x;
fx = 1 ^ y = 2 + 1gse muestra un razonamiento ecuacional, el cual es vlido slo si la funcin f no
tiene efectos colaterales. Si f modicara de alguna manera (en un modelo con estado)
la variable x del ejemplo, el razonamiento anterior deja de ser vlido.
Por esta razn, en el modelo con estado se debe razonar usando alguna lgica que
tenga en cuenta cualquier cambio de estado, como por ejemplo la lgica de Hoare.
Esto muestra la necesidad del uso de ciertas tcnicas de programacin que eviten
el uso de abstracciones (ej: funciones) que tengan efectos colaterales, para permitir un
razonamiento ms modular. Una de las tcnicas mas efectivas es la modularizacin de
los programas, deniendo componentes lo ms independientes posibles, es decir que no
tengan estado compartido.
2.1.1. Lenguajes declarativos
Los lenguajes de programacin declarativos pueden clasicarse en alguna de las
siguientes categoras:
Funcionales: un programa se basa en aplicacin y composicin funcional. Ejem-plos: Haskell y subconjuntos de LISP, SCHEME, y los derivados de ML (SML,
Ocaml, etc)
1
.
Relacionales o lgicos: un programa opera sobre relaciones. Muy tiles para prob-lemas con restricciones, con soluciones mltiples, etc.
Memoria con asignacin nica: se asignan valores a variables una nica vez. Lasvariables estn ligadas a algn valor o no. Las variables ligadas permancen en
ese estado durante todo su tiempo de vida. Ejemplo: subconjunto de Oz.
2.1.2. Lenguajes con estado
Los lenguajes de programacin con estado son los mas comunes de encontrar. Estos
lenguajes se caracterizan por poseer operaciones de cambio de estado de variables.
Estas operaciones se conocen comnmente como sentencias de asignacin.
Es posible clasicar los lenguajes con estado como:
Procedurales (o imperativos): se caracterizan por permitir abstracciones fun-cionales (procedimientos y/o funciones) parametrizadas, sentencias de asignacin
y de control de ujo de la ejecucin y deniciones de variables. Ejemplos: Pascal,
C, Fortran, Cobol, Basic, etc.
Orientados a objetos: permiten denir tipos en clases2 y permiten organizarlasen forma jerrquica, fundamentalmente usando la relacin supertipo-subtipo.
1
Estos ltimos lenguajes no son funcionales puros, ya que tambin permiten programar con estado.
2
Una clase dene un tipo y es adems un mdulo que encapsula la representacin del conjunto de
valores y sus operaciones.
26
-
2.2. Elementos de un lenguaje de programacin
Un lenguaje de programacin ofrece al programador un conjunto de construcciones
o sentencias que pueden clasicarse en las siguiente categoras:
Valores: Todo lenguaje permite expresar valores de diferentes tipos, como porejemplo, valores numricos, strings, caracteres, listas, etc. Los valores de tipos
bsicos se denominan literales (ej: 123.67E2) y los valores de tipos compuestos (o
estructurados) se denominan agregados (ej: {'a','b','c'} en C, [0,2,4,8] en Haskell).
Declaraciones: Una declaracin introduce una nueva entidad, generalmente iden-ticable. Estas entidades pueden ser:
Constantes simblicas: identicadores a valores dados. Ej. en Pascal:Const Pi=3.141516;
Tipos: introducen nuevos tipos denidos por el programador. Ej. en Pascal:Type Point = Record int x, y end;
Variables: identicadores que referencian valores almacenados en memoria. Procedimientos y funciones: abstracciones parametrizadas de comandos yexpresiones, respectivamente.
Externas: hacen referencia a entidades denidas en otros mdulos (o bib-liotecas). Ej (en Pascal): Uses ;
Aquellas declaraciones de entidades representables en memoria se denominan
deniciones. Por ejemplo, son deniciones, las declaraciones de variables y de
procedimientos y funciones, mientras que una declaracin de un tipo no demanda
memoria alguna.
Comandos: sentencias de control de ujo de ejecucin: Comandos bsicos: Como por ejemplo asignacin (en Pascal) o invocacionesa procedimientos.
Secuencia o bloques. Saltos (o secuenciadores): ejemplos como comandos goto L (donde L es unrtulo o punto de programa.
Otros saltos o secuenciadores son ms estructurados como por ejemplo, los
comandos break y continue de C. Generalmente se usan como saltos a
puntos especcos en base a la sentencia en que se encuentran. Por ejemplo,
en C, la sentencia break es un salto al nal de la sentencia y puede aparecer
en las sentencias switch (alternativas por casos) o en una iteracin (for,
while o do-while.
En C, la sentencia continue (slo puede aparecer en una iteracin) produce
un salto en el ujo de ejecucin al comienzo de la iteracin.
En algunos lenguajes, como en C, la expresin return ; retorna (el
valor de ) inmediatamente de la funcin, haciendo que las sentencias
subsiguientes no sean ejecutadas.
27
-
Sentencias de seleccin o condicionales: Ej: if-then-else, case, etc. Iteracin (o repeticin): Denida: el nmero de ciclos est determinado como por ejemplo lasentencia for de Pascal, for-each, etc.
Indenida: el nmero de ciclos est determinado por una condicin aevaluar en tiempo de ejecucin. Ejemplo: sentencias while y repeat-until.
Operadores: Un operador es una funcin con una sintaxis especca de invocacin.Un operador puede verse como una abstraccin sintctica de la invocacin a
una funcin y su objetivo es ofrecer una notacin ms natural al programador.
Por ejemplo, es comn que un lenguaje contenga operadores aritmticos (sobre
enteros, reales, ...), lgicos, de bits (ej: shift), sobre strings, etc.
Los operadores se pueden usar en diferentes notaciones:
injos: operadores binarios donde el operador se escribe entre los operandos.Ejemplos: x * y, a/2, ...
prejos: operadores n-arios donde el operador antecede a su operando. Ej: -x, - - y (en C). Generalmente una invocacin a una funcin toma esta forma:
f(e1; : : : ; en), donde cada ei, (1 i n) es una expresin. posjos: operadores donde el operador sucede al operando. Ej: p (en Pascal) midjos: los operadores se mezclan con sus operandos. Ej: cond? t: f (en C).
Expresiones: Una expresin representa un valor, es decir que puede ser asignablea una variable o constante, pasado como parmetro en una invocacin a un
procedimiento o funcin, etc.
Una expresin se forma de la siguiente manera:
i. Un valor de un tipo determinado es una expresin.
ii. Una referencia (el uso de su identicador) a una variable o constante es una
expresin.
iii. Una invocacin a una funcin, donde cada uno de sus argmentos
3
es una
expresin, es una expresin.
iv. Una aplicacin de un operador a sus operandos (expresiones) correspondi-
entes es una expresin.
v. Si e es una expresin, entonces (e) tambin lo es.
Una expresin que retorna un valor de verdad (boolean) se denomina predicado.
Los operadores generalmente estn predenidos en el lenguaje. Algunos lenguajes
permiten al programador denir nuevos o al menos redenir los existentes.
3
Un argumento en una invocacin a un procedimiento o funcin se denomina parmetro actual o
real . Un identicador de un parmetro en la declaracin de un procedimiento o funcin se denomina
parmetro formal .
28
-
Cada operador tiene denida una cierta precedencia y asociatividad para permitir
al programador evitar el uso excesivo de parntesis para asociar los diferentes compo-
nentes de una expresin.
La precedencia permite establecer el orden de evaluacin de una expresin con
respecto a los dems operadores que aparecen en la misma. Es comn que en el caso
de los operadores aritmticos la precedencia habitual sea que se usa comnmente en
matemticas (ej: * tiene mayor precedencia que +). Por ejemplo, la expresin x+y*z
signica x+(y*z).
La asociatividad dene la parentizacin implcita cuando el operador aparece en
secuencia. Por ejemplo, el operador + generalmente asocia a izquierda, mientras que
el operador de asignacin (=) en C, asocia a derecha. Es decir que la expresin x+y+z
es equivalente a (x+y)+z y x=y=z es equivalente a x=(y=z).
2.3. Tipos de datos
Denicin 2.3.1 Diremos que un tipo de datos es una descripcin de un conjunto
de valores junto con las operaciones que se aplican sobre ellos.
Cada valor corresponde a un tipo de datos. Un valor v es de un tipo T si v 2 T .
Value
Record
Integer Float
Number Procedure
Tuple
Literal List
AtomBool String
Function
Char
Figura 2.1: Jerarqua de tipos bsicos.
Entre los tipos denominados bsicos tenemos dos clases, los cuales pueden jerar-
quizarse segn la gura 2.1:
1. elementales: (tambin llamados bsicos) tales como los nmeros y literales.
Estos valores son indivisibles.
2. estructurados: (o compuestos) como lo son los records. Son estructuras com-
puestos por otros valores.
29
-
Cabe aclarar que en otros lenguajes de programacin existen otros tipos de datos
bsicos como las referencias y los arreglos.
Todo lenguaje de programacin ofrece un conjunto de tipos de datos. La gran
mayora de los lenguajes de programacin modernos permiten la declaracin de nuevos
tipos a partir de otros ya denidos. Esta es una de las principales caractersticas en
la evolucin de los lenguajes de programacin. La posibilidad de denir nuevos tipos
permite la implementacin ms elegante de tipos abstractos de datos , los cuales denen
un tipo de datos en base a sus operaciones.
Los primeros lenguajes (como Fortran, Cobol, Basic), no ofrecan la posibilidad de
denir nuevos tipos, por lo que limitaba bastante la claridad de las abstracciones.
A modo de ejemplo, en la gura 2.2, se muestran dos programas que suman nmeros
complejos. El programa de la izquierda est en un lenguaje que no permite denir
nuevos tipos.
double c_sum_r(double r_1, double r_2) type complex=(double r,i);
{ ... } complex c_sum(complex c1, complex c2)
double c_sum_i(double i_1, double i_2) { ... }
{ ... }
a) Sin nuevos tipos b) Con nuevos tipos denidos
Figura 2.2: Ejemplo de programacin con denicin de nuevos tipos
Las diferentes versiones de la gura 2.2 muestran la diferencia en el estilo y claridad
de los programas.
2.3.1. Tipos de datos simples o bsicos
Cada lenguaje dene un conjunto de tipos bsicos como los siguientes:
numricos:
escalares o numerables: Ej: enteros.
no escalares: Ej: reales.
caracteres
lgicos
punteros y/o referencias
Los enteros pueden representarse en complemento a dos con un nmero jo de bits.
Algunos lenguajes permiten denir el nmero de bits de la representacin, como
por ejemplo, en C: short int , long int , etc.
30
-
Los reales se representan segn algn formato estndar (ej: IEEE) en punto otante
o en punto jo
4
.
Los lgicos se representan comnmente en un byte (ej: 0=false, 1=true), ya que
generalmente es el tamao mnimo de bloque de memoria direccionable.
Los punteros y referencias se usan para acceder indirectamente otros valores y se
representan con una direccin de memoria, por lo que su tamao de representacin
generalmente es igual al nmero de bits necesarios para direccionar una palabra de
memoria.
2.3.2. Tipos de datos estructurados
Estos tipos de datos son aquellos que estn compuestos por un conjunto de otros
valores y pueden clasicarse en base a diferentes caracterscas.
Por el tipo de sus elementos que contienen:
1. homogneos: todos sus elementos son del mismo tipo, como por ejemplo los
arreglos.
2. heterogneos: sus elementos pueden ser de diferente tipo, como los registros.
Por sus caractersticas del manejo de sus elementos:
1. estticos: el nmero de sus elementos est dado por una constante momento de
su creacin. Ejemplo: arreglos en Fortran o Pascal.
2. dinmicos: el nmero de sus elementos es variable. Ejemplos: listas, arreglos y
registros dinmicos, . . . .
3. semi-dinmicos: el nmero de elementos est determinado por una variable
en su creacin pero luego el nmero de sus elementos se mantiene. Ejemplos:
arreglos de C o C++.
Las estructuras de datos estticas permiten una implementacin mas eciente, ya
que la cantidad de memoria a asignar para su representacin es conocida en tiempo de
compilacin y por lo tanto se pueden utilizar tcnicas de manejo de memoria esttica
o mediante una pila.
Los arreglos y los registros estticos o semi-dinmicos permiten una representacin
contiga de sus elementos, lo que permite la implementacin simple de sus operadores
de acceso a sus elementos, generalmente conocidas como selectores
5
.
Generalmente encontramos en los lenguajes a los siguientes tipos:
4
Estos ltimos son muy adecuados para representar importes monetarios.
5
Como los operadores . de los registros y [] de los arreglos.
31
-
Arreglos: contienen a un conjunto de datos almacenados en forma contiga, per-
mitiendo acceder a cada elemento por medio de un operador de indexacin. Un
arreglo puede ser multidimensional. Si tienen una dimensin se denominan vec-
tores, si tienen dos, matrices.
El operador de indexacin (denotado como [index] o (index)) es una funcin
de un tipo ndices (escalar) a un valor del tipo base (el tipo de los elementos
contenidos).
Ejemplo en C: oat v[N]; ... v[0] = 1.5; ...
Algunos lenguajes (ej: Pascal) permiten denir el dominio de los ndices. Otros
(ej: C, Java) el tipo ndice es el rango [0; N 1].Los arreglos son estructuras homogneas, ya que todos los elementos que contiene
son del mismo tipo.
En algunos lenguajes son estticos (como en Pascal) en cuanto a su dimensin,
es decir que su dimensin debe ser una constante. En otros lenguajes (como
C y Java), son semi-dinmicos, es decir que su dimensin puede determinarse
en tiempo de ejecucin (aunque luego no puede cambiarse). Algunos lenguajes
tambin permiten que su dimensin vare en ejecucin, por los que se llaman
dinmicos o de dimensin variable.
Registros (o estructuras): sus componentes (campos) pueden ser de cualquier
tipo. Sus campos son identicables, por lo que se denominan tambin tuplas ro-
tuladas. Generalmente se representan en memoria de forma contiga. El operador
de acceso a los campos generalmente se denota con el smbolo . (punto).
Ejemplo (C):
struct person { int id, char[N] nombre; };
person p; /* variable de tipo p */
p.id = 1; ...
Tuplas: son como los registros pero sus elementos se referencian generalmente
usando proyecciones.
Strings (cadenas de caracteres): generalmente se denotan entre o '. Algunos
lenguajes los representan como arreglos de caracteres (C, Java), mientras que
otros los representan como listas (Haskell, ML).
2.3.3. Chequeo de tipos
Un lenguaje de programacin generalmente deber chequear los tipos de los argu-
mentos u operandos de cada operacin. El proceso de vercar si los operandos de una
operacin son del tipo correcto se denomina type checking. Ese chequeo, en base al
momento en que realiza, puede ser:
Tipado esttico: el chequeo de tipos se realiza en tiempo de compilacin.
32
-
Tipado dinmico: el chequeo de tipos se realiza en tiempo de ejecucin. Los
valores tienen tipo pero las variables no (pueden tomar cualquier valor).
Obviamente el tipado esttico requiere que los tipos de las expresiones se determi-
nen (liguen) en tiempo de compilacin, por lo que se requiere que el programador tenga
que especicar los tipos en las declaraciones o sino el lenguaje tendr que inferirlos de
alguna manera. Algunos lenguajes, como Haskell o ML, las declaraciones de tipos es
opcional, salvo en algunos casos que podra dar lugar a ambigedades. Estos lenguajes
tienen un sistema de tipos y algoritmos de inferencia de tipos muy elaborado.
Un sistema de tipos esttico es una forma simple de vercacin de programas de
acuerdo a las reglas que dene el sistema de tipos para cada una de sus operaciones.
El tipado esttico tiene grandes ventajas ya que un programa que compile, se podra
decir que no tiene errores de tipos (est correctamente tipado).
Un lenguaje con tipado dinmico deber acarrear informacin del tipo
6
de cada uno
de los valores en tiempo de ejecucin.
El tipado dinmico, detectar errores de tipos durante la ejecucin, lo cual puede ser
un gran inconveniente. La ventaja del tipado dinmico es que permite mayor exibili-
dad para denir abstracciones polimrcas
7
con mayor libertad, lo cual da un mayor
poder expresivo (relativo).
El sistema de tipos generalmente es conservador ya que el problema general es
indecidible (es comparable al problema de la parada). Por ejemplo, en una sentencia
de la forma: if cond then 32 else 1+"hola" , an cuando cond evale siempre
a true no compilar (1+"hola" es una expresin mal tipada) ya que en tiempo de
compilacin no se podra inferir que esta ltima expresin nunca se ejecutara.
2.3.4. Sistemas de tipos fuertes y dbiles
Un sistema de tipos fuerte (strong) impide que se ejecute una operacin sobre ar-
gumentos de tipo no esperado.
Un lenguaje con un sistema de tipos dbil (weak) realiza conversiones de tipos
implcitas (casts) o aquellas explcitas. El resultado de la operacin puede variar: por
ejemplo, el siguiente programa:
var x = 5;
var y = ab ;
x+y;
en Visual Basic da error de tipos, mientras que en JavaScript produce el string "5ab".
2.3.5. Polimorsmo y tipos dependientes
Algunos lenguajes permiten que las operaciones operen sobre argumentos de tipos
especcos. En este caso se denomina sistema de tipos monomrco.
6
Puede ser un simple rtulo o marca (tag).
7
Una operacin es polimrca si acepta argumentos de diferentes tipos en diferentes invocaciones.
33
-
Un sistema de tipos que permite operaciones que aceptan argumentos que pueden
ser instancias de una familia (relacionada de algn modo) de tipos se denomina un
sistema polimrco (muchas formas).
Por ejemplo, algunas operaciones en algunos lenguajes son polimrcos (ej: coman-
do write o read de Pascal, aunque Pascal tiene un sistema de tipos monomrco).
Otros lenguajes tienen verdaderos sistemas de tipos polimrcos, como Haskell, que
soporta polimorsmo paramtrico (tambin llamado polimorsmo por instanciacin).
En este caso, una operacin (funcin) dene argumentos con un tipo variable. Cada in-
stanciacin (invocacin a la funcin con valores concretos) determina (estticamente)
el tipo de cada argumento en cada invocacin y chequea si son vlidos.
En la programacin orientada a objetos, una operacin permite que sus argumen-
tos sean instancias de una familia de tipos relacionados de la forma tipo-subtipo. Esas
operaciones se denen como referencias del tipo superior.
Algunos tipos dependen de otros tipos (su tipo base). Por ejemplo, los arreglos son
un tipo dependiente del tipo base (el tipo de cada uno de sus elementos). Estos tipos
se denominan tipos dependientes.
2.3.6. Seguridad del sistema de tipos
Un sistema de tipos es seguro (safe) si no permite operaciones que produciran
condiciones invlidas. Por ejemplo, si un lenguaje no chequea que en una operacin
de indexacin en un arreglo, el ndice est en el rango vlido, es un lenguaje con un
sistema de tipos inseguro.
2.4. Declaraciones, ligadura y ambientes
Una declaracin relaciona un identicador con una o ms entidades. Esta relacin
se denomina ligadura (binding , en ingls).
Por ejemplo, la declaracin de una constante, como const Pi = 3.141517; relaciona
al identicador Pi con un valor y con un tipo determinado (real en este caso).
Una declaracin de un tipo liga un identicador a un tipo.
Una ligadura entre un identicador y alguna de sus propiedades puede determinarse
en dos momentos:
i. durante la compilacin: En este caso se denomina esttica .
ii. en ejecucin o dinmica .
En el ejemplo anterior ambas ligaduras ocurren estticamente, pero en cambio en
una declaracin de una variable, su tipo puede determinarse estticamente pero no su
valor
8
.
8
Algunos lenguajes permiten determinar su valor inicial.
34
-
Una declaracin de alguna entidad (tipo, variable, funcin, etc) alcanza a una cierta
porcin en un programa. La gran mayora de los lenguajes de programacin permiten
que las declaraciones pertenezcan a algn bloque. El alcance de una declaracin es
similar al alcance de variables cuanticadas en lgica. Por ejemplo, en la siguiente
frmula
8x:(p(x) ^ 9y:q(x; y))
El cuanticador universal alcanza a toda la frmula y el cuanticador existencial
alcanza a la subfrmula q(x; y).
Un ambiente (o espacio de nombres) es un conjunto de ligaduras.
Cada sentencia de un programa se ejecuta en un cierto contexto o ambiente, por
lo que su interpretacin depende del ambiente en que se ejecuta.
En un lenguaje con alcance esttico (static scope) las sentencias de un bloque
(de un procedimiento o funcin) se ejecutan en el ambiente de su declaracin. Esto
signica que los valores (los tipos, etc.) de los identicadores referenciados en el bloque
se determina en tiempo de compilacin y corresponden a las declaraciones que con-
tienen textualmete al bloque.
En un lenguaje con alcance dinmico (dynamic scope), un bloque se evala
en el contexto de su invocacin. Es decir que los identicadores referenciados pueden
haberse denido en procedimientos o funciones que invocaron (directa o indirecta-
mente) al actual. Esto signica que su contexto no depende del texto del programa,
sino que su ambiente se determina slo en tiempo de ejecucin.
En el siguiente programa se muestra la diferencia entre alcance esttico y dinmico.
var a = 1;
function f()
{
return a+1;
}
function main()
{
var a = 2;
return f();
}
Con alcance esttico la funcin f se evala en el ambiente de su denicin, por
lo que la invocacin desde main retornar 2. Si f se evaluase en el ambiente de su
invocacin, en ste caso retornara 3 (ya que hara referencia al valor de la variable a
declarada en main ).
El alcance esttico permite razonar sobre programas en forma modular, es decir
sin tener en cuenta sus posibles contextos de invocacin.
Por otro lado, el alcance dinmico provee mayor exibilidad, pero la mayor desven-
taja es que no permite analizar un bloque de cdigo en forma modular, ya que los
35
-
identicadores a los que se hace referencia dependen de una determinada traza de
ejecucin.
Adems, el alcance dinmico tiene otro problema. Suponga que la declaracin de
a en main se dene con tipo string . El programa ahora tendra un error de tipos ya
que la funcin f tratara de sumar un valor de tipo string con un entero.
Por esta razn, generalmente los lenguajes con alcance dinmico tambin tienen
tipado dinmico.
Lenguajes como Clipper, Scheme y Perl permiten tener ambos tipos de alcance.
2.5. Excepciones
Una excepcin es un evento que ocurre durante la ejecucin de un programa, como
producto de la ejecucin de alguna operacin invlida, y require la ejecucin de cdigo
fuera del ujo normal de control. El manejo de excepciones (exception handling), es
una caracterstica de algunos lenguajes de programacin, que permite manejar o con-
trolar los errores en tiempo de ejecucin. Proveen una forma estructurada de atrapar
las situaciones completamente inesperadas, como tambin errores predecibles o resul-
tados inusuales. Todas esas situaciones son llamadas excepciones.
Cmo manejamos situaciones excepcionales dentro de un programa?, como por
ejemplo una divisin por cero, tratar de abrir un archivo inexistente, o seleccionar un
campo inexistente de un registro. Debera ser posible que los programas las mane-
jaran en una forma sencilla. Los lenguajes deberian proveer a los desarrolladores las
herramientas necesarias para detectar errores y manejarlos dentro de un programa
en ejecucin. El programa no debera detenerse cuando esto pasa, mas bien, debera
transferir la ejecucin, en una forma controlada, a otra parte, llamada el manejador
de excepciones, y pasarle a ste un valor que describa el error.
Algunos lenguajes de programacin (como, por ejemplo, Lisp, Ada, C++, C#,
Delphi, Objective C, Java, VB.NET, PHP , Python ,Eiel y Ocaml) incluyen soporte
para el manejo de excepciones. En esos lenguajes, al producirse una excepcin se
desciende en la pila de ejecucin hasta encontrar un manejador para la excepcin, el
cual toma el control en ese momento.
Ejemplo de manejo de excepcin en C:
#include
#include
#include
int main()
{
__try
{
int x,y = 0;
36
-
int z;
z = x / y;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
MessageBoxA(0,"Capturamos la excepcion","SEH Activo",0);
}
return 0;
}
Figura 2.3: Manejo de Excepciones.
Cmo debera ser el mecanismo de manejo de excepciones?.
Podemos realizar dos observaciones. La primera, el mecanismo debera ser capaz de
connar el error, i.e., colocarlo en cuarentena de manera que no contamine todo el
programa. LLamamos a esto el principio de connamiento del error. Suponga que
el programa est hecho de componentes que interactan, organizados en una forma
jerrquica. Cada componente se construye a partir de componentes mas pequeos.
El principio del connamiento del error arma que un error en un componente debe
poderse capturar en la frontera del componente. Por fuera del componente, el error
debe ser invisible o ser reportado en una forma adecuada.
Por lo tanto, el mecanismo produce un "salto"desde el interior del componente
hasta su frontera. La segunda observacin es que este salto debe ser una sola operacin.
El mecanismo deber ser capaz, en una sola operacin, de salirse de tantos niveles como
sea necesario a partir del contexto de anidamiento (ver gura 2.3).
37
-
2.6. Qu es programar?
Analizando los elementos de un lenguaje de programacin, se nota que cuando
se programa, es decir, se soluciona un problema dado por medio de un programa de
computadora, en realidad se termina deniendo un conjunto de tipos.
Por lo que podemos decir que programar es denir tipos y/o usar los valores y
operaciones de un conjunto de tipos denidos.
Como se ver mas adelante, los diferentes modelos, paradigmas de programacin
proveen diferentes estilos en la deniciones de tipos.
2.7. Ejercicios
1. En las siguientes declaraciones Pascal, marque cules son deniciones:
a) const Pi = 3.1415;
b) var x:integer;
c) External Procedure P(x:integer);
d) Function Square(x:integer);
begin
Square = x*x
end
e) type Person = record name:string; age:integer end;
2. Dar un ejemplo en un lenguaje imperativo de una expresin que no tenga trans-
parencia referencial.
3. Determinar (mediante un experimento) el nmero de bits de los enteros en el
compilador Pascal que utilice.
4. Muestre un ejemplo de programa en Haskell y en Pascal que no compile por un
error de tipos an cuando nunca se producira en ejecucin.
5. Muestre un ejemplo de un programa Pascal que compile pero que tenga un error
de tipos en ejecucin.
6. Realice un experimento para determinar qu sistema de equivalencia de tipos
usa Pascal. Justique su respuesta.
7. Dar un programa Pascal que muestre que no tiene un sistema de tipos seguro.
8. El principio de completitud de tipos determina que ninguna operacin debera
restringir arbitrariamente el tipo de sus operandos.
Dar al menos tres ejemplos de operaciones de Pascal que violan este principio.
9. Dado el siguiente programa Pascal, determinar el ambiente de ejecucin de las
sentencias del cuerpo del procedimiento P.
38
-
Program Example;
Var x:integer;
Function F(a:integer):integer;
begin
F := x*a
end;
Procedure P(y:integer)
var x:integer;
z:bool;
begin
x := 1;
z := (y mod 2 == 0);
if z then
x := F(y+1)
else
x := F(y)
end;
begin { main }
x := 2;
P(x)
end.
10. Determine qu tipo de alcance tiene el lenguaje LOGO (usado ampliamente en
la enseanza de la programacin).
11. De un ejemplo de uso de excepciones en Java y C++.
39
-
Captulo 3
El modelo declarativo
Lo agradable de la programacin declarativa es que uno escribe una especicacin
y la ejecuta como un programa. Lo desagradable de la programacin declarativa es
que algunas especicaciones claras resultan en programas increblemente malos. La
esperanza de la programacin declarativa es que se pueda pasar de una especicacin
a un programa razonable sin tener que dejar el lenguaje.
Adaptacin libre de The Craft of Prolog, Richard O'Keefe (1990)
La programacin comprende tres cosas:
Un modelo de computacin, el cual dene formalmente la sintaxis y la semntica
de las frases (sentencias) del lenguaje.
Un conjunto de tcnicas de programacin y principios de diseo. Generalmente
sto se conoce como el modelo (o estilo) de programacin.
Un conjunto de tcnicas para razonar sobre los programas y calcular su eciencia.
Otros autores llaman a los tr