DISEÑO E IMPLEMENTACION Estructura y operación de una computadora: COMPUTADORA SUBYACENTE (clase1 y 2) Una computadora es un conjunto integrado de algoritmos y estructuras de datos capaz de almacenar y ejecutar programas. Se puede construir una computadora como un dispositivo físico real, utilizando alambres circuitos integrados, etc. en cuyo caso se le conoce como computadora real o computadora de hardware. También, se puede construir a través a través de software por medio de programas que se ejecutan en otra computadora, y en este caso se trata de una computadora simulada por software. Un lenguaje de programación se implementa construyendo un traductor, el cual traduce los programas que están en el lenguaje a programas en lenguaje maquina que pueden ser ejecutados directamente por alguna maquina. Una computadora consiste en seis componentes fundamentales que corresponden estrechamente a los aspectos principales de una lenguaje de programación: 1. Datos: Una computadora debe suministrar diversas clases de datos elementales y estructuras de datos que se van a manipular. 2. Operaciones primitivas: una computadora debe proveer un conjunto de operaciones primitivas útiles para la manipulación de datos. 3. Control de secuencia: Una computadora debe aportar mecanismos para controlar el orden en el que se van a ejecutar las operaciones primitivas. 4. Acceso a datos: una computadora debe proporcionar mecanismos para controlar los datos que se suministran a cada ejecución de una operación. 5. Gestión de almacenamiento: una computadora debe proveer mecanismos para controlar la asignación de almacenamiento para programas y datos. 6. Entorno de operación: una computadora debe suministrar mecanismos para la comunicación con un entorno externo que contiene programas y datos que van procesar. Traductores: la programación, se hace en un lenguaje de alto nivel muy alejado del lenguaje maquina mismo del hardware. El problema con el cual se encuentra el implementador de lenguajes es, como hacer que se ejecuten programas en el lenguaje de alto nivel en la computadora real que se tiene a la mano, independientemente de su lenguaje de maquina. Existen dos soluciones para estas cuestiones: 1. TRADUCCIÓN (compilación): el termino general traductor denota cualquier procesador de lenguaje que acepta programas en cierto lenguaje fuente (que puede ser de alto o bajo nivel) como entrada y produce programas funcionalmente equivalentes en otro lenguaje objeto como salida. Varios tipos de traductores tienen nombres particulares: a) Un ensamblador: es un traductor cuyo lenguaje objeto es alguna variedad de lenguaje de maquina para una computadora real pero cuyo lenguaje fuente, constituye en gran medida una representación simbólica del código de maquina objeto. b) Un compilador es un traductor cuyo lenguaje fuente es un lenguaje de alto nivel y cuyo lenguaje objeto se aproxima al lenguaje de maquina de una computadora real. c) Un cargador o editor de vínculos es un traductor cuyo lenguaje objeto es un código de maquina real y cuyo lenguaje fuente es casi idéntico. d) Un preprocesador o un macroprocesador es un traductor cuyo lenguaje fuente es una forma ampliada de un lenguaje de alto nivel y cuyo lenguaje objeto es la forma estándar del mismo lenguaje. 2. SIMULACIÓN DE SOFTWARE (interpretación de software): para realizar esta simulación se construye un conjunto de programas en el lenguaje de maquina de la computadora anfitrión que representan los algoritmos (y estructuras de datos) necesarios para la ejecución de programas en el lenguaje de alto nivel. Etapas de traducción: el proceso de traducción de un programa, de su sintaxis original a una forma ejecutable, es medular en toda implementación de lenguajes de programación. Desde el punto de vista lógico, la traducción se puede dividir en dos partes principales: el análisis del programa fuente de entrada y la síntesis del programa objeto ejecutable. En casi todos los traductores, estas etapas lógicas no están claramente separadas, sino que se mezclan de manera que se alterna el análisis con la síntesis. Análisis del programa fuente: para un traductor, el programa fuente se presenta inicialmente como una serie larga y no diferenciada de símbolos, compuesta de miles o decenas de miles de caracteres. Durante la traducción, se debe construir un análisis de la estructura del programa. 1 Análisis léxico: la fase fundamental de cualquier traducción es agrupar esta serie de caracteres en sus constituyentes elementales: identificadores, delimitadores, símbolos de operadores, palabras claves, comentarios, etc. Esta fase se conoce como análisis léxico, y las unidades básicas de programa que resultan de este análisis se llaman elemento o componentes léxicos. El analizador léxico debe identificar el tipo de cada elemento léxico (operador, numero, delimitador, etc) y adjuntar una marca de tipo. Análisis sintáctico: la segunda etapa de la traducción es el análisis sintáctico (parsing). En ella se identifican las estructuras de programa mas grande (enunciado, declaraciones, expresiones, etc), usando los elementos léxicos producidos por el analizador léxico. El análisis sintáctico se altera ordinariamente con el análisis semántico. Primero, el analizador sintáctico identifica una serie de elementos léxicos que forman una unidad sintáctica como una expresión, enunciado, etc.. Se llama entonces a un analizador semántico para que procese esta unidad. Por lo común, el analizador sintáctico y semántico se comunican a través de una pila. Análisis semántico: tal vez es la fase medular de la traducción. Aquí se procesan las estructuras sintácticas reconocidas por el analizador sintáctico y la estructura del código objeto ejecutable comienza a tomar forma. El análisis semántico es el puente entre las partes de análisis y de síntesis de la traducción. En esta etapa ocurre también un cierto numero de otras funciones subsidiarias importantes, entre ellas el mantenimiento de tablas de símbolos, la mayor parte de la detección de errores, la expansión de macros y la ejecución de enunciados de tiempo de compilación. El analizador semántico se divide ordinariamente en un conjunto de analizadores semántico mas pequeños, cada uno de los cuales maneja un tipo particular de construcción de programa. Síntesis del programa objeto: las etapas finales de la traducción se ocupan de la construcción del programa ejecutable a partir de las salidas que produce el analizador semántico. Esta fase implica necesariamente generación de código y también puede incluir optimización del programa generado. Si los subprogramas se traducen por separado, o si se emplean subprogramas de biblioteca, se necesita una etapa final de vinculación y carga para producir el programa completo listo para ejecutarse. COMPUTADORA VIRTUAL Y TIEMPO DE ENLACE Cuando se implementa un lenguaje de programación, las estructuras de datos y algoritmos en tiempo de ejecución que se emplean en la ejecución de programas definen una computadora. Cuando un lenguaje de programación se esta implementando en una computadora particular, el implementador determina primero la computadora virtual que representa una interpretación de la semántica del lenguaje y luego se construye esa computadora virtual a partir de los elementos de hardware y software que suministra la computadora subyacente. Síntesis y semántica: la sintaxis de un lenguaje de programación es el aspecto que ofrece el programa. Proporcionar las reglas de sintaxis para un lenguaje de programación significa decir como se escriben los enunciados, declaraciones y otras construcciones del lenguaje. La semántica de un lenguaje de programación es el significado que se da a las diversas construcciones sintácticas. Ejemplo de ello: v:array [0..9] of entero. Jerarquía de computadoras: la computadora virtual que un programador utiliza cuando decide hacer un programa en algún lenguaje de alto nivel esta formada, de hecho, por una jerarquía de computadoras virtuales. Hasta abajo debe haber, una computadora de hardware real. Sin embargo, el programador ordinario rara vez tiene trato directo con esta computadora. En vez de ello, esta computadora de hardware se transforma sucesivamente a través de capas de software (o microprogramas) en una computadora virtual que puede ser radicalmente distinta. El segundo nivel de computadora virtual (o el tercero si un microprograma forma el segundo nivel) esta definido por la compleja colección de rutinas que se conoce como sistema operativo. Los programas que el programador construye añaden un nivel mas a la jerarquía. EJEMPLO: Datos de entrada Datos de salida Aplicación (PROGRAMA)- Desarrollada por el ProgramadorComputadora Virtual ( Ej. Leng. C-(BIBLIOTECA) Computadora virtual del SISTEMA OPERATIVO Computadora virtual del FIRWARE- (Inst. en lenguaje maquina implementadas por microcódigo ejecutado por la maquina real)Computadora de hardware real- (implementada por dispositivos físicos). Modelo de computación: 2 ESQUEMA 1 Lenguaje Fuente Lenguaje Ejecutable Traductor Interpretación Compilación Interprete Compilador Preprocesador Enlazador Fácil desarrollo Mas rápido a la hora de ejecutarlo Un solo archivo Costo de traducción único Traducción n veces Traductores simples Independencia C, PASCAL, ASM en la arquitectura de la maquina PHP, PERL PARADIGMAS Y TÉCNICAS DE PROGRAMACION (clase 3) Luego de analizar el entorno real de la computadora que va a contener el programa de objetos traducidos de un programa y la computadora virtual que va a proporcionar el almacenamiento de datos en tiempo de ejecución y las operaciones para la ejecución del programa traducido, hay que ver el modelo de computación que maneja el lenguaje de programación. Existen cuatro modelos básicos de computación que describen casi todos los lenguajes de programación actuales: 1. Lenguaje imperativos o de procedimiento EJEMPLO FORTRAN, C. Son lenguajes controlados por mandatos u orientados a enunciados (instrucciones). Estos lenguajes se componen de una serie de procedimientos (subprogramas, funciones o subrutinas) que se ejecutan cuando se les llama. Un programa se compone de una serie de enunciados, y la ejecución de cada enunciado hace que el interprete cambie el valor de una localidad o mas en su memoria. El estado de la maquina virtual va cambiando. Ejemplo leer un carácter. 2. Lenguajes aplicativos o funcional EJEMPLO LISP, ML Desde el punto de vista de su diseño, están destinados a programarse en forma aplicativa. La ejecución de una expresión es el concepto principal que se necesita para la secuencia de programas. 3. Programación lógica (con base en reglas) : se ejecutan verificando la presencia de una cierta condición habilitadora y, cuando se satisface, ejecutan una acción apropiada. El lenguaje mas común es PROLOG, que también se conoce como un lenguaje de programación lógico, puesto que las condiciones habilitadoras básicas son ciertas clases de expresiones lógicas de predicados. Base de hechos: le digo algo concreto. Base de reglas: manera para determinar una situación. 4. Programación con restricciones: Para problemas con planificaciones. Árbol de reglas. 5. Programación estructurada: Una sola entrada, una sola salida. 6. Programación orientada a objetos: en este caso se construyen objetos complejos de datos y luego se designa un conjunto limitado de funciones para que operen con esos datos. Características: Encapsulamiento. Unión de una serie de datos con el algoritmo. Heredan propiedades. Polimorfismo. 7. Basada en objetos: 8. Programación orientada a aspectos: El código se reutiliza. Ejemplo JAVA Desacople. 3 9. Programación dirigida por eventos: Ejemplo: bloc de notas. Sin no le doy un evento no realiza nada. El control de flujo de ejecución es dirigido por el usuario. 10. TDD: aquí desarrollo una serie de test, para luego ejecutarlo. Desarrollo el test. Programamos. Ejecutados. (clase 4) 11. Programación orientada por lotes: 12. Pipeline Prog: tener un tubo que conecta 2 elementos. 13. Programación por capas: lo normal se da entre 2 o 3 capas. Presentación visual (formulación, interfaz). 14. Interfaces: hay que definir las interfaces en la capa. 15. Programación por lotes (OLE): toma una serie de componentes y lo enlazo para que resuelva un problema. Ej. notepad. 16. Desarrollo de aplicaciones visual: 17. Programación orientada a tablas: EJEMPLO ACCES. Todo se trabaja a nivel datos mediante tablas. 18. Multiplataforma: permite ejecutar un programa que corra bajo diferentes SO. 19. Multiparadigmas: EJEMPLO JAVA, C++. Cada paradigma puede estar compuesto de otros paradigmas adentro. 20. Plataformas nuevas: Inteligencia artificial. Agente. Algoritmos genéticos. TIPOS DE DATOS: (clase 5) Un tipo de dato es una clase datos ligados a un conjunto de operaciones para crearlos y manipularlos. Todo lenguaje tiene un conjunto de tipos primitivos de datos que están integrados al lenguaje. Además, un lenguaje puede proveer recursos que permitan al programador definir nuevos tipos de datos. Los elementos básicos de una especificación de un tipo de datos son: 1. los atributos que distinguen objetos de datos de ese tipo. 2. los valores que los objetos de datos de ese tipo pueden tener, y 3. las operaciones que definen las posibles manipulaciones de objetos de datos de ese tipo. Cualquier programa, no importa que lenguaje use, se puede considerar como la especificación de un conjunto de operaciones que se van a aplicar a ciertos datos en un orden determinado. Es decir que estas tres áreas, DATOS, OPERACIONES y CONTROL, forman el programa. DEFINICION DE OBJETOS DE DATOS, VARIABLES Y CONSTANTES: Las áreas de almacenamiento de datos de una computadora real, como la memoria, registros internos y medios externos, tienen por lo general una estructura relativamente simple como la serie de bits agrupados en bytes o palabras. Computadora Hardware (metal: se trabaja con secuencia de bits). El almacenamiento de datos de la computadora virtual para un lenguaje de programación tiende a tener una organización mas compleja, con arreglos, pilas, números, cadena de caracteres y otras formas de datos que existen en diferentes puntos durante la ejecución de un programa. 4 Computadora Virtual (Lenguaje- Vectores, arreglos, enteros). Objetos de datos: es un agrupación de 1 o mas datos en tiempo de ejecución en una computadora virtual. Durante la ejecución de un programa, existen muchos objetos de datos de distintos tipos. Estos objetos de datos y sus interrelaciones cambian de manera dinámica durante la ejecución del programa. Algunos objetos de datos que existen durante la ejecución de programas son definidos por el programador, es decir, son variables, constantes, arreglos, archivos, etc, que el programador crea y manipula de manera explicita a través de declaraciones y enunciados en el programa. Otros objetos de datos son definidos por el sistema (maquina virtual). Es decir, que la maquina virtual construye para “mantenimiento” durante la ejecución de programas, y se generan ordinariamente de manera automática. Un objeto de dato se caracteriza por un conjunto de atributos, el mas importante es su tipo de datos. Los atributos determinan el numero y tipo de valores que el objeto de datos puede contener. Definición de valor de datos: puede ser un solo numero o, posiblemente un apuntador a otro objeto de dato. Un valor de datos se representa ordinariamente por medio de un patrón particular de bits en el almacenamiento de la computadora. Si se observa el curso de la ejecución de un programa, ciertos objetos de datos existen al principio de la ejecución y otro se crean dinámicamente durante la misma. Algunos objetos de datos se destruyen durante la ejecución; otros persisten hasta que el programa concluye. Así pues, cada objeto tiene un tiempo de vida durante el cual puede usarse para guardar valores de datos. Un objeto de datos participa en varios enlaces durante su tiempo de vida. Mientras que los atributos de un objeto no varían durante su tiempo de vida, los enlaces pueden cambiar de manera dinámica. Los atributos y enlaces mas importantes son: 1. Tipo: (Conj. de valores de datos que el objeto puede tomar). 2. Localidad: (Posición de memoria en donde se encuentre). 3. Valor: (Este enlace es por lo general resultado de una asignación). 4. Nombre: (por medio de los cuales se puede hacer referencia al objeto durante la ejecución del programa). 5. Componente: (El enlace de un objeto de datos a uno o mas objetos de datos, de los cuales es un componente se suele representar por un valor apuntador, y se puede modificar a través de un cambio en el apuntador). Variables y constantes: Un objeto de datos que el programador define y nombra explícitamente en un programa se conoce como una variable. Una variable simple es un objeto elemental de datos con nombre. El o los valores de una variable es modificable por operaciones de asignación, es decir, que el valor puede cambiar durante su tiempo de vida. Una constante es un objeto de dato con nombre que esta enlazado en forma permanente a un valor (o valores) durante su tiempo de vida. Existen 2 tipos de constantes: 1. Constante literal: (tipos de datos primitivas) ejemplo integer. 2. Definida por el programador: hay que especificar las operaciones y clase de objeto. (clase 6) Áreas: Especificaciones de ese tipo de dato. Implementación del tipo de dato. Como se representa ese tipo de dato. Especificaciones: Atributos nombre Valores: determina los valores que se le pueden dar a un objeto de dato. Operaciones: pueden ser primitivas o definidas por el programador. Representación matemática. Actividad: es la cantidad de operaciones. Operaciones unarias. Operaciones binarias. Operaciones trinarias. Implementación: Representación de almacenamiento. Short_ equivale a 8 bits. Algoritmo o procedimiento que trabaje con ese tipo de dato. REPRESENTACIÓN SINTACTICA (como escribo esas declaraciones) 5 (clase 7) Al escribir un programa, el programador determina el nombre y tipo de cada objeto de datos que se necesita. También se debe especificar el tiempo de vida de cada objeto de datos, durante que parte de la ejecución del programa se necesita, así como las operaciones que se le habrá de aplicar. Declaraciones de ese tipo: hay que decidir con que objeto de datos vamos a utilizar en el programa. Que operaciones vamos a aplicar. Tiempo de vida que va a tener. En que parte del programa los vamos a usar. Las herramientas que se utilizan son las declaración. Una DECLARACIÓN es un enunciado de programa que sirve para comunicar al traductor del lenguaje información acerca del nombre y tipo de los objetos de datos que se necesitan durante la ejecución del programa. Los modificadores de declaraciones son : Const Valor inicial Register (reg. del proceso). Especifico en lenguaje C. Propósito de las declaraciones: las declaraciones tienen varios propósitos importantes: 1. Selección de representación de almacenamiento: si una declaración proporciona información al traductor del lenguaje acerca del tipo de dato, y los atributos de un objeto de dato, entonces el traductor suele poder determinar la mejor representación de almacenamiento para ese objeto de dato, con una reducción consecuente del requerimiento global de almacenamiento y del tiempo de ejecución para el programa que se esta traduciendo. 2. Gestión de los tiempo de vida: suele hacer posible el uso de procedimientos mas eficientes de gestión de almacenamiento durante la ejecución del programa. 3. Operaciones polimorficas: (generales- homónimas). Las declaraciones permiten ordinariamente al traductor del lenguaje determinar en tiempo de compilación cual es la operación particular que designa un símbolo de operación homónimo. Ejemplo de ello es el signo +, en donde realiza una suma de 2 variables, o concateno 2 variables. 4. verificación de tipos: el propósito mas importante de las declaraciones, desde el punto de vista del programador, es permitir la verificación estática de tipos antes que la verificación dinámica. Verificación y conversión de tipos: las representaciones de almacenamiento que se incorporan en el hardware de la computadora no incluyen ordinariamente información de tipos, y las operaciones primitivas sobre los datos no llevan a cabo verificación de tipos. Al nivel de hardware, las computadoras convencionales son particularmente poco confiables para detectar errores de tipo de datos. Verificación de tipos significa comprobar que cada operación que un programa ejecuta recibe el numero apropiado de argumentos de tipo correcto de dato. La verificación de tipos se puede efectuar en tiempo de ejecución (verificación dinámica de tipos) o en tiempo de compilación (verificación estática de tipos). Las verificaciones dinámicas de tipos es la verificación en tiempo de ejecución que por lo común se efectúa inmediatamente antes de la ejecución de una operación particular. Este tipo de verificación se implementa por lo general guardando una marca de tipo en cada objeto de datos, la cual indica el tipo de dato del objeto. Cada operación se implementa entonces de modo que comience con una secuencia de verificación de tipos. Las operaciones se efectúan solo si los tipos de argumentos son correctos. Definición: comprobar que cada operación recibe el numero correcto de argumentos y de los TDA correctos. La ventaja principal de los tipos dinámicos es la flexibilidad en el diseño de programas: no se requieren declaraciones y el tipo de objeto de datos asociado con un nombre de variable puede cambiar según se requiere durante la ejecución del programa. El programador queda libre de casi todas las preocupaciones acerca de tipos de datos. Sin embargo la verificación dinámica de tipos tiene varias desventajas importantes. 1. Es difícil depurar los programas y eliminar por completo todos los errores de tipo de argumento. 2. La verificación dinámica de tipo requiere que la información de tipos se conserve durante la ejecución del programa. 3. La verificación dinámica de tipo se debe implementar ordinariamente en el software, puesto que el hardware subyacente rara vez proporciona apoyo. Casi todos los lenguajes intentan eliminar o reducir al mínimo la verificación dinámica de tipos efectuando la verificación de tipo durante la compilación. La verificación estática de tipo: se efectúa durante la traducción de un programa. Características: Se efectúa durante la traducción de un programa. Puede haber errores del programador, y en consecuencia deberá repararlo. 6 El tipo de dato se mantiene. Es constante. Si todos los errores de tipo se pueden detectar al momento de compilar, se dice que el lenguaje es fuerte. Ej. PASCAL. Por lo común, la información necesaria se suministra en parte mediante declaraciones que proporciona el programador y en parte por otras estructuras del lenguaje. La información que se requiere es: 1. Para cada operación, el numero, orden y tipo de datos de sus argumentos y resultados. 2. Para cada variable, el tipo de objeto de dato nombrado. 3. el tipo de cada objeto de datos constante. Durante las fases iniciales de traducción de un programa, el compilador (u otro traductor) recoge información de declaraciones del programa en diversas tablas, principalmente una tabla de símbolos que contiene información de tipos acerca de variables y operaciones. Después de reunir toda la información de tipos, se verifica cada operación que invoca al programa para determinar si el tipo de cada argumento es valido. CONTROL DE SECUENCIA (clase 8) En un lenguaje de programación, las estructuras de control proporcionan el marco básico dentro del cual las operaciones y datos se combinan en programas y conjunto de programas. A partir de aquí, se debe considerar su organización en programas completos ejecutables. Esto implica dos aspectos: el control del orden de ejecución de las operaciones, el cual designamos como control de secuencia, y el control de la transmisión de datos entre los subprogramas de un programa, el cual llamamos control de datos. Control de secuencia: las estructuras de control de secuencia se pueden clasificar convenientemente en tres grupos: 1. Estructuras que se usan en expresiones, como regla de precedencia y paréntesis. 2. Estructuras que se usan entre enunciados o grupos de enunciados o grupos de enunciados, como enunciados condicionales e iterativos. 3. Estructuras que se usan entre subprogramas, como llamadas de subprogramas y corrutinas. Las estructuras de control de secuencia pueden ser implícitas o explicitas. Implícitas o por omisión, son las que el lenguaje define que están en operación, a menos que el programador las modifique a través de alguna estructura explicita. Explicitas, son aquellas que el programador puede usar en forma optativa para modificar el orden implícito de las operaciones definido por el lenguaje. Elementos : Expresiones aritméticas. Expresiones no aritméticas. Entre enunciados. Entre SP (ejemplo llamada a una función) CONTROL DE SECUENCIA ENTRE EXPRESIONES ARITMÉTICAS: Un ejemplo de esta expresión es la formula para el computo de raíces de la ecuación cuadrática. Esta formula, implica un conjunto de al menos 15 operaciones individuales. La notación es compacta y natural, y el procesador de lenguajes, se ocupa del almacenamiento temporal y la optimización. Entonces parece fácil afirmar, que la disponibilidad de expresiones en los lenguajes de alto nivel es una de sus ventajas principales sobre los lenguajes de maquina y ensamblador. Las expresiones son un dispositivo poderoso y natural para representar series de operaciones, pero representan nuevos problemas. Representación de estructura de árbol: el mecanismo básico de control de secuencia en expresiones es la composición funcional: se especifica una operación y sus operandos. La composición funcional confiere a una expresión la estructura característica de una árbol, donde el nodo raíz del árbol representa la operación principal, los nodos intermedios representan las operaciones de nivel intermedio y las hojas representan referencias de datos (o constantes). Sintaxis para expresiones: las notaciones mas comunes son: o Notación prefija (polaca): al escribir llamadas de función, se escribe ordinariamente el nombre de la función antes de sus argumentos. Esto se hace extensivo a todas las operaciones de una expresión. En notación por prefijos, se escribe primero el símbolo de la operación seguido de los operandos. Una variable de esta notación, se designa como polaca de Cambridge. En este caso, un operador y sus argumentos están rodeados por paréntesis. Una expresión se vera entonces como un conjunto anidado de listas. (clase 9) CONTROL DE SECUENCIA ENTRE ENUNCIADOS 7 Los resultados de cualquier programa están determinados por sus enunciados básicos que aplican operaciones a objetos de datos. Son ejemplo de estos enunciados básicos los enunciados de asignación, llamadas a subprogramas, y enunciados de entrada salida. Cada enunciado básico se puede considerar como una unidad que representa un solo paso en el computo. Los cambios al estado del computo por asignación de valores a objetos de datos es el mecanismo mas importante que afecta el estado de un computo que realiza un programa. Existen varias formas de esta clase de enunciado. CONTROL SECUENCIA EN LOS SUBPROGRAMAS Llamada / regreso simple de subprogramas: en programación estamos acostumbrados a ver los programas como jerarquías. Un programa se compone de un solo programa principal, el cual, durante la ejecución, puede llamar varios subprogramas, los que a su vez pueden llamar otros subprogramas, y así sucesivamente. Se espera que cada subprograma termine su ejecución en cierto punto y regrese el control al programa que lo llamo. Durante la ejecución de un subprograma, la ejecución del programa que lo llamo se detiene temporalmente. Cuando se completa la ejecución del subprograma, la ejecución del programa que lo llamo se reanuda en el punto que sigue de inmediato a la llamada del subprograma que lo llamo. Esta estructura de control se suele explicar por la regla de copia. Es decir, las llamadas de subprograma se pueden considerar como estructuras de control que simplemente hacen innecesario copiar grandes números de enunciados idénticos o casi idénticos que ocurren en mas de un lugar en un programa. Atributos del control de dato: Las características de control de datos un lenguaje de programación son aquellas partes que tienen que ver con la accesibilidad de datos en diferentes puntos durante la ejecución del programa. Las características de control de datos de un lenguaje determinan como se pueden suministrar datos a cada operación, y como se puede guardar el resultado de una operación y recuperarlo para uso posterior como operando por parte de una operación subsiguiente. Asociaciones y ambientes de referencia: cada programa o subprograma tiene un conjunto de asociaciones de identificadores disponibles para su uso al hacer referencias durante su ejecución. Este conjunto de asociaciones de identificador se conoce como el ambiente de referencia del subprograma. Es ordinariamente invariable durante su ejecución. Se establece cuando se crea la activación del subprograma y permanece sin cambios durante el tiempo de vida de la activación. El ambiente de referencia de un subprograma puede tener varios componentes: 1. Ambiente local 2. Ambiente no local 3. Ambiente global de referencia 4. Ambiente predefinido de referencia Visibilidad: se dice que una asociación para un identificador es visible dentro de un subprograma si es parte del ambiente de referencia para ese programa. Una asociación que existe pero no forma parte del ambiente de referencia actualmente en ejecución se dice que esta oculta de ese subprograma. Basados en reglas de visibilidad voy a tener 2 conceptos: 1. El alcance estático: de una declaración es la parte del texto del programa donde un uso del identificador es una referencia a esa declaración particular del identificador. 2. El alcance dinámico es el conjunto de activaciones de subprograma en las cuales la asociación es visible durante la ejecución. 8