Definiciones Alcance Estático Lenguajes de Programación I Alcance Ernesto Hernández-Novich <emhn@usb.ve> c 2007-2010 Copyright Alcance Dinámico Definiciones Alcance Estático Alcance Dinámico ¿Qué quiere decir Alcance? El alcance de una asociación es la región de un programa en la cual dicha asociación está activa y visible. Se usa simplemente alcance para hacer referencia a la región de un programa en la que un nombre o una asociación tiene validez. Puede ser estático o dinámico. Definiciones Alcance Estático Alcance Dinámico Alcance Estático Basado en el texto del programa fuente También llamado alcance léxicográfico. El alcance se determina a tiempo de compilación y es independiente del flujo de ejecución. Variedades simples Sólo variables globales (BASIC). Globales y locales sin anidamiento (Fortran). Variedades completas – cualquier lenguajes moderno. El programador puede mirar el texto del programa, y pensar en función de sustituciones de variables Definiciones Alcance Estático Alcance Dinámico Anidamiento De subrutinas, de bloques, de módulos, de clases... Regla del bloque con alcance más cercano: todo nombre declarado en algún alcance, es visible en ese y en cualquiera que esté anidado a menos que quede escondido por una declaración del mismo nombre. ¿Y los elementos predefinidos (built-in) del lenguaje? Definiciones Alcance Estático Alcance Dinámico ¿Qué puede verse y dónde? Variables globales – dentro de todo el módulo o programa. Variables locales – dentro del procedimiento o subrutina, o del bloque que las contiene. De “afuera hacia adentro”, siempre y cuando haya anidamiento y no haya redefinición – la redefinición oculta parcialmente el alcance externo. De adentro hacia afuera, nunca. Definiciones Alcance Estático Alcance Dinámico ¿Cómo se implementa el alcance estático? El compilador construye una tabla de símbolos – diccionario con información para cada símbolo conocido. Símbolo global – información incluye la dirección asignada. Símbolo local – información incluye el offset dentro del registro de activación. Manejo de anidamiento – pila de tablas o árbol de tablas, con apuntador al entorno actual. enterScope al procesar un bloque anidado – empila una nueva tabla y le apunta. exitScope al terminar con el bloque anidado – desempilar la tabla y apunta al entorno circundante. La tabla se conserva dentro del ejecutable sólo si se desea soportar debugging o profiling. Definiciones Alcance Estático Alcance Dinámico Acceso a Objetos No-Locales En cualquier instante de ejecución nos encontramos en un stack frame particular y es necesario encontrar: Variables globales. Stack frames que nos contienen – sus locales están a nuestro alcance. Mantener un enlace estático (static link) al registro de activación para la invocación más reciente de la rutina que contiene al registro de activación actual – el padre léxico a tiempo de ejecución. k rutinas anidadas – cadena estática de longitud k. Alcanzar una variable/parámetro declarado j alcances hacia afuera – recorrer j pasos por la cadena estática y luego usar el offset. La tabla de símbolos indica el nivel de anidamiento. Definiciones Alcance Estático Registro de activación reloaded El rastro de la ejecución y el acceso no-local proc A { proc B { proc C { } proc D { C(); } D() } proc E { B(); } E(); } Alcance Dinámico Definiciones Alcance Estático Alcance Dinámico Registro de activación reloaded El rastro de la ejecución y el acceso no-local proc A { proc B { proc C { } proc D { C(); } D() } proc E { B(); } E(); } ← SP Sub C ← BP Sub D estática Sub B Sub E Sub A dinámica Definiciones Alcance Estático Alcance Dinámico Módulos Cuando el alcance rompe la frontera del archivo Búsqueda de abstracción escondiendo información. Reducir la contaminación del espacio de nombres de los programas. Los nombres dentro de un módulo: Son visibles entre sí (reglas de alcance por medio). Visibles desde el exterior cuando son exportados. Ven símbolos exteriores cuando han sido importados. C++ los llama namespaces, Modula los llama modules, Perl los llama packages, Clu los llama clusters... lo importante es el efecto. Módulo como tipo vs. módulo como librería. Definiciones Alcance Estático Alcance Dinámico ¿Qué hace falta para tener módulos? Especificar cuando comienza un módulo. Cuáles nombres pueden ser exportados y como: Sólo lectura. Opacamente (útil para tipos de datos). En algunos lenguajes es posible separar las declaraciones del módulo (module head) de la implantación del módulo (module body). Utilizar otros módulos importando nombres Si es necesario hacerlo explícitamente, se habla de alcances cerrados (Closed Scope). Si no es necesario hacerlo, se habla de alcances abiertos (Open Scope). En general es más útil el alcance abierto selectivo. Definiciones Alcance Estático Alcance Dinámico Alcance Dinámico Basado en el flujo de ejecución del programa Se determina a tiempo de ejecución y depende del flujo de control, particularmente del orden en que sean invocadas las subrutinas. La asociación actual para un nombre particular es la encontrada más recientemente durante la ejecución y que aún no haya sido destruida. El flujo de ejecución es impredecible – las asociaciones no pueden determinarse a tiempo de compilación. Diferir verificaciones semánticas a tiempo de ejecución. Definiciones Alcance Estático Alcance Dinámico ¿Cómo se implementa el alcance dinámico? Depende del flujo de ejecución, así que debe mantenerse a tiempo de ejecución. El compilador genera código apropiado para el mecanismo. El interpretador incorpora el mecanismo. Mecanismo de Listas de Asociación (A-list) Una lista ordenada de parejas símbolo/valor. Se usan como pilas – enterScope y exitScope son equivalentes a push y pop de la pareja. Acceder a un símbolo – buscar su primera ocurrencia para recuperar o modificar la información asociada. Mecanismo de Tablas Centrales de Referencia Diccionario de símbolos a lista de valores. La lista de valores contiene el más reciente al princpio. Definiciones Alcance Estático Alcance Dinámico Diferencia muy sutil ¿Qué imprime el programa? a : integer; procedure primera a := 1 end procedure segunda a : integer primera() end a := 2 if read.integer() > 0 segunda() else primera() print(a) Alcance Estático Siempre imprime 1 Alcance Dinámico Imprime 1 o 2 según lo que se lea con read. Definiciones Alcance Estático Alcance Dinámico ¿Y cómo puede ser útil? Simplifica la adaptación de rutinas en algunos casos: en lugar de pasar argumentos, las rutinas pueden usar variables que sean controladas por alcance estático. Ese problema se puede resolver sin usar alcance dinámico: Usando polimorfismo con parámetros por defecto. Usando varias rutinas con parámetros diferentes. Se puede usar una variable global/local estática, salvarla, poner el valor nuevo, llamar a la rutina y restaurarla después.