acl-book

222
7/13/2019 acl-book http://slidepdf.com/reader/full/acl-book 1/222                

Upload: michel-defagot

Post on 12-Oct-2015

38 views

Category:

Documents


0 download

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