Control en subprogramas. Pelczer Ildikó Judit. Díaz Vera Alexei Eleusis. García Cárdenas Egar Arturo.

Slides:



Advertisements
Presentaciones similares
2. Manejo de memoria Manejo de memoria estática
Advertisements

Programación de Computadores
2 Estructuras lineales.. Qué es una estructura? La estructura es una manera de conectar los valores y de manera automática conectarlos de manera que tengan.
ESTRUCTURA DE LOS LENGUAJES DE PROGRAMACION
Metodología de la Programación
Procedimientos y Funciones
Programación I Teoría III
Funciones. Programación, Algoritmos y Estructuras de Datos.
Una variable en un programa es algo con un nombre, cuyo valor puede variar. La manera en que el compilador y enlazador maneja esto es asignando un bloque.
FUNCIONES EN C.
Funcionamiento, programación
EXCEPCIÓN DE ERRORES.
UNIVERSIDAD NACIONAL AUTÓNOMA DE MÉXICO
ALGORÍTMICA Dpto. Ingeniería de Sistemas y Automática
Teoría de lenguajes y compiladores
Unidad 3 Punteros.
Tema 7: Polimorfismo Antonio J. Sierra. Índice Introducción. Sobrecarga de métodos. Objetos como parámetros. Paso de argumentos. Devolución de objetos.
Funciones en lenguaje C
Funciones: conceptos básicos
CI TEORIA semana 8 Subprogramas o funciones Definición de funciones.

Métodos Algoritmos y Desarrollo de Programas I. Cuando utilizar métodos  Los métodos se utilizan para romper un problema en pedazos de forma que este.
TRAMPAS EN EL DISEÑO DE LENGUAJES CON RELACIÓN A LOS NOMBRES - REGLAS DE ALCANCE - COMPILACIÓN POR SEPARADO CONTROL DE FLUJO - EVALUACIÓN DE EXPRESIONES.
Clases y objetos La unidad fundamental de programación OO son las clases. Conjunto de métodos y semántica Qué se va a hacer POO Clase: que define la implementación.
Tema 6: Clases Antonio J. Sierra.
HILOS Y COMUNICACIÓN ENTRE PROCESOS
Nombre, Alcance y Asociaciones (Bindings). Agenda Definición Nombre y Bindings Binding Time Importancia del Binding Time Eventos relacionados a la Asociación.
Semana 5 Subprogramas..
M.C. Meliza Contreras González
PROCEDIMIENTOS FUNCIONES
Programación III Clase 07 Funciones.
Cobol C Pascal Fortran 5. UNIDADES DE PROGRAMAS SmallTalk Java C++
Índice. Revisando conceptos acerca de la memoria.

Clase 10: Estructuras de datos y arreglos.
Paso de parámetros y arreglos. Las aplicaciones (llamadas a procedimiento) Resolución de nombres (gracias al establecimiento de un ambiente) Condicionamiento.
Descomposición Modular. Funciones
Tema 10.3: Asignación de Espacio No Contiguo. Tema 10.3: 2 Silberschatz, Galvin and Gagne ©2005 Fundamentos de los Computadores (ITT, Sist. Electr.),
Tipos de Datos (Data Types)
Programación en Pascal
Abstracción de Datos y Orientación a Objetos.. Vista General. Por qué la abstracción de datos y la programación orientada a objetos. Módulos y módulos.
Asignación de Espacio No Contiguo
Material de apoyo Unidad 4 Estructura de datos
Aplicación de estructuras de datos
1 6. PARAMETRIZACIÓN. 2 Parametrización La parametrización permite realizar una abstracción de la identidad de varios ejemplos de los datos Los valores.
1 Asignación Dinámica de Memoria Agustín J. González Versión original de Kip Irvine ELO 329.
Alcance Dinámico La Asociación Actual para un Nombre dado es el encontrado recientemente durante la ejecución, y no a sido destruido aun por el retornado.
Tipos de Datos. Entrada-Salida.. La entrada-salida (I/O) le permite a un programa comunicarse con el mundo exterior. Esta comunicación puede realizarse.
NVA-LNG1 3. SENTENCIAS. NVA-LNG2 Asignación Es una sentencia que almacena: el valor del argumento ubicado a la derecha del símbolo que la representa En.
Manejo de Punteros y objetos en memoria dinámica en C++
Ada 2º Parte (variables, ámbitos , subrutinas , tipos abstractos de datos y excepciones)
Unidad II Introducción a la programación en C++
Herencia y tipos ● Cuanta memoria se debe asignar a un objeto cuando se asigna en la pila ● La asignación debe hacerse antes de que se conozca la cantida.
APRENDIZ: SANDRA L. CAICEDO C. ORDEN: 20194
Unidad 1: FUNDAMENTOS DE COMPUTACIÓN Y PSEUDOLENGUAJE
Agenda Clase 11 Parametrización. Pasaje de parámetros (modos). Razones de escogencia entre modos. Clausuras como parámetros. Etiquetas, Conformat Arrays,
Términos algoritmo diseñar algoritmo implementar algoritmo
CARACTERÍSTICAS Es un lenguaje de programación estructurado de propósito general. Está estrechamente asociado al sistema operativo UNIX, ya que el propio.
1 Asignación Dinámica de Memoria Agustín J. González ELO 329.
1 5. UNIDADES DE PROGRAMAS. 2 Uso de mecanismos de control de secuencia de: Invocaciones Retornos Entre: PPSP 1 a) I R SP 1 SP 2 b) I R Unidades subordinadas.
Teoría de lenguajes y compiladores
PRINCIPIOS DE PROGRAMACIÓN
UNIDAD 4: Introducción a la Lógica Computacional Objetivo : Interpretar y aplicar adecuadamente los fundamentos básicos de la estructura y funcionamiento.
Introducción a los TADs
Funciones Copyright © 2005 Unidad 1. Copyright © 2005 Objetivos del Aprendizaje Explicar la naturaleza y usos de las funciones. Describir algunas funciones.
MEMORIA DINÁMICA.
Programación en Visual Basic
Omar Herrera Caamal Rigoberto Lizárraga Luis Cetina Luna.
P ROCESO DE E NSAMBLADO Cámara Vázquez Berenice Rubí.
Katty Evangelina Hipólito Chi.   Aunque cada maquina tiene un lenguaje ensamblador distinto, el proceso de ensamblador tiene suficiente similitudes.
Transcripción de la presentación:

Control en subprogramas. Pelczer Ildikó Judit. Díaz Vera Alexei Eleusis. García Cárdenas Egar Arturo.

1. Subprogramas o Rutinas.

Los subprogramas o rutinas son unidades más pequeñas en las que se puede dividir un programa. Procedimientos: Son rutinas que no regresan valor o regresan un valor vacío. Funciones: Son rutinas que regresan un valor.

Las rutinas se introducen mediante una declaración. Las rutinas son descritas mediante una definición. Las rutinas se activan mediante una invocación o llamada.

/*suma es un función que calcula la suma de los primeros n naturales n; se supone que n es positivo*/ int suma(int n) { int i,s; s=0; for(i=1;i<=n;i++) s+=i; return s; }

Alcance: Los elementos que pueden ser accesados por la rutina. Local: Los elementos declarados dentro de ella. No-local: Los elementos declarados independiente de ella. Global: Los elementos visibles para todas las rutinas.

int A(int x, int y);//declaración de una función con dos //parámetros de tipo int con valor de //regreso int; A es visible a partir de este punto float B(int z) //Definición de la función B; //B es visible a partir de { //este punto int w,u;... w=A(z,u); //se llama a A que en este punto ya es visible... }; int A(int x, int y) //esta es la definicón de A { float t;... t=B(x); //B es visible en este punto... }

Nombre: Se usa un encabezado que contiene: El nombre del subprograma. Los parámetros. El valor de regreso (si hay). Tipo: Se define por medio de la firma.

L-value: Es el área de memoria donde se encuentra el código de la rutina. R-value: Es una activación de la rutina.

int(*ps)(int); //esta línea declara que ps es un apuntador a //una rutina de tipo entero en C ps=&suma; //esta línea hace que ps apunte la rutina suma int i=(*ps)(5); //invoca el r-value de la rutina hacia la que //apunta ps

La representación de una rutina en ejecución se llama instancia de la rutina, está compuesta por: Bloque de código: Registro de Activación: Contiene información necesaria para la ejecución. Espacio para las variables locales. Un apuntador de regreso.

Referencia ambiental de una instancia de una rutina: Consiste de todos los elementos locales y no-locales relacionados con los objetos dentro del registro de activación. Local. No-local.

Parámetros formales: Son los que aparecen en la declaración de la rutina. Parámetros reales: Son los que aparecen en la invocación a la rutina.

Procedure Ejemplo(A:T1;B:T2:=W;C:T3); --los parámetros A,B,C son de tipo T1, T2 y T3 --respectivamente; --un valor por omisión de B esá dado por W --las siguientes llamadas son legales si X, Y, Z y C son de --tipo T1, T2 y T3 respectivamente Ejemplo(X,Y,Z); --esta es asociación posicional Ejemplo(X,C=>Z); --X está asociado posicionalmente, --B toma el valor por omisión y --Z está asociado con C explícitamente Ejemplo(C=>Z,A=>X,B=>Y);

1.1. Rutinas Genéricas.

Son machotes (templates) desde los cuales de una rutina general se pueden generar varias rutinas específicas.

template void swap(T& a, T& b) { T temp = a; a = b; b = temp; } void main() { int a=5, b=7; Complex c(1,0), d(4,5); swap(a,b); swap(c,d); }

1.2. Alias y sobrecarga.

Sobrecarga: Un mismo nombre para distintas entidades. Una ocurrencia especifica del nombre debe proveer suficiente información para determinar la entidad de manera única. Alias. Dos o más nombres se refieren a la misma entidad.

a=b+c+b(); //ejemplo de sobrecarga a=b()+c+b(i); //otro ejemplo de sobrecarga int x=0; //en este ejemplo i y j se refieren a x int& i=x; // y cualquier modificación que se haga a int& j=x; //cualquiera de los tres afectará a los tres

1.3. Un procesador semántico abstracto.

SIMPLESEM es un procesador semántico abstracto, consta de: Un apuntador de instrucción IP. Una memoria dividida en dos partes C(Código) y D (Datos). C[X] y D[X] son los valores almacenados en las celdas X de C y D. X es un l-value y D[X] un r-value.

Instrucciones: set dirección, valor jump dirección jumpt dirección, condición halt Entrada –salida: write y read junto con la instrucción set. Se permiten usar operadores aritméticos y lógicos para calcular los distintos parámetros de las instrucciones.

2. Estructura de tiempo de ejecución.

De acuerdo a los requerimientos de memoria se tienen los siguientes tipos de lenguajes: Lenguajes totalmente estáticos. Lenguajes basados en pilas o stack. Lenguajes dinámicos.

2.1. Lenguajes con un solo enunciado simple.

Hay solo una rutina principal que contiene la declaración de lo datos y las instrucciones que los manipulan. Solo se tiene un registro de activación.

main() { int i,j; get(i,j); while(i!=j) if (i>j) i-=j; else j-=i; print(i); }

Ejemplo

2.2. Lenguajes con rutinas simples.

Se tiene un conjunto de declaraciones globales. Un conjunto de declaraciones de rutinas. Una rutina principal. Las rutinas no están anidadas, no se pueden llamar a si mismas y no regresan valor.

El tamaño de los registros de activación se conoce en tiempo de compilación. Los registros de activación se asignan en memoria en tiempo de compilación. El registro de activación consta de: Dirección de regreso. Espacio para las variables locales. En compilación a cada variable se le asocia un desplazamiento.

Varias implementaciones de FORTRAN y COBOL siguen este modelo.

int i=2, j=2, k=3; alfa() { int i=4, l=5; i+=k+1; print(i); print(j); print(k); print(l); } beta() { int k=6; i=j+k; alpha(); print(i); print(j); print(k); } main() { beta(); print(i); print(j); print(k); }

Ejemplo

2.3. Funciones recursivas.

La recursión consiste en: La habilidad que tienen los programas para llamarse a si mismos. Directa. Indirecta. La capacidad de regresar valores.

Se usa una estructura de Stack. Para cada invocación de la rutina se crea un nuevo registro de activación. Todas las instancias comparten el mismo código. A cada variable se le asocia un desplazamiento en el correspondiente registro de activación.

Se tiene que guardar la dirección del registro de activación actual, para enlazar las variables con su dirección. Al momento de regreso se tiene que recuperar el registro de activación de la rutina invocadora. En el registro de activación se coloca un espacio para la dirección de regreso y otro para la dirección base de la rutina invocadora, a este último se le llama liga dinámica.

La cadena de ligas dinámicas a partir del último registro de activación es llamada la cadena dinámica. Para colocar un nuevo registro de activación es necesario conocer la primera celda libre en el Stack. La rutina invocadora extiende su registro de activación para reservar el espacio para el valor de regreso.

int n; int fact(int n) { if (n>1) return n*fact(n-1); else return 1; } main() { get(n); if (n>=0) print(fact(n)); }

Ejemplo

2.4. Estructura de bloques.

Sirve para controlar el alcance y tiempo de vida de las variables. Divide el programa en unidades más pequeñas. Dos bloques pueden ser ajenos o anidados.

Anidamiento por enunciados compuestos.

Las variables localmente declaradas en un enunciado compuesto son visibles en el y en los enunciados compuestos inmersos. Las declaraciones internas enmascaran a las externas con el mismo nombre. Se define también el tiempo de vida de las variables locales, la variable se enlaza a un espacio en memoria mientras el bloque está activo.

Una estructura de bloque se puede describir por medio de un árbol sintáctico de anidamiento. En el registro de activación de una rutina se asigna espacio suficiente para todas las variables. Dos bloques ajenos no pueden estar activos al mismo tiempo. Se puede usar el mismo espacio en memoria para variables distintas en bloques ajenos (overlay).

int f() { // bloque 1 int x,y,w; while(x!=0) { // bloque 2 int x,z; while(...) { // bloque 3 int y; } // fin del bloque 3 if(...) { // bloque 4 int x,w; } // fin del bloque 4 } // fin del bloque 2 if (...) { // bloque 5 int a,b,c,d;... } // fin del bloque 5 } // fin del bloque 1

Ejemplo

Anidamiento por rutinas localmente declaradas.

Las rutinas pueden ser declaradas dentro de otras. Una rutina puede ser usada en el bloque donde ella es declarada y en los bloques inmersos. Incluyendo el cuerpo de la misma rutina. Se puede definir un árbol de anidamiento estático para las subrutinas.

Las variables locales se enlazan en tiempo de ejecución al registro de activación actual. Las variables globales se enlazan en tiempo de compilación. Las variables no locales se tienen que asociar al registro de activación de la rutina envolvente. Para ello se usa un apuntador llamado liga estática.

La secuencia de ligas estáticas empezando en el ultimo registro de activación es llamada cadena estática. Las referencias a variables no-locales se resuelven por medio de la cadena estática. En compilación se puede resolver la distancia en la cadena estática entre uso de una variable y su declaración.

En compilación a cada variable se le puede asociar un par y con un método adicional se resuelve la referencia. Para instalar la liga estática en el registro de activación de una rutina, se sigue una distancia D la liga estática a partir de la rutina invocadora, donde D es la distancia entre la llamada de la rutina invocada y su declaración.

int x,y,z=0; // bloque 0 f1() { // bloque 1 int t,u; f2() { // bloque 2 int x,w; f3() { // bloque 3 int y,w,t;... } // fin del bloque 3 x=y+t+w+z; }... // fin del bloque 2 } // fin del bloque 1 main() { // bloque 4 int z,t;... } // fin del bloque 4 // fin del bloque 0

Ejemplo

PROGRAM anomaly(input,output) PROCEDURE S; {1} BEGIN writeln("wrong one"); END; PROCEDURE T; {Missing: PROCEDURE S; FORWARD; here} PROCEDURE U; BEGIN S {2} END; PROCEDURE S; {3} BEGIN writeln("right one"); END; BEGIN U END; BEGIN T; END.

2.5. Comportamientos más dinámicos.

La intención es proveer mecanismos para el manejo de variables cuyos requerimientos de memoria no se conocen en compilación.

Registros de activación cuyo tamaño se conoce en la unidad de activación.

El tamaño de las variables no se conoce en tiempo de compilación, como es el caso de los arreglos dinámicos. Un descriptor es un área de memoria incluida en el registro de activación, que contiene alguna información de la variable y un apuntador a la dirección en memoria donde estan sus datos.

En compilación se reserva espacio para los descriptores en el registro de activación. El registro de activación se extiende para incluir espacio para la variable. El descriptor apunta a esta área extendida.

type VECTOR is array (INTEGER range<>);... A: VECTOR(0..N); B: VECTOR(1..M);

Alojamiento completamente dinámico de memoria.

Los datos se pueden colocar en memoria de manera explicita a través de ciertas instrucciones. En la mayoría de los lenguajes esto es por medio de apuntadores. Los datos no se pueden colocar en el Stack, así que se colocan en un área de memoria especial llamada Heap. La dirección del dato se enlaza a una variable en el registro de activación.

struct node { int info; node* left; node* right; }... node* n = new node;

2.6. Lenguajes dinámicos.

Adoptan reglas dinámicas en lugar de estáticas.

Tipos dinámicos.

El tipo de variable y sus métodos de acceso no se pueden determinar en compilación. El tipo de la variable se almacena en el registro de activación, junto con un apuntador a su descriptor. Los descriptores son guardados en el heap. El valor también es guardado en el heap.

Alcance dinámico.

- Static versus dynamic, example: A: integer; -global variable Procedure first A=1; Procedure second A: integer; --local varibale First() A:=2; If read_integer()>0 Second() Else First() Write_integer(a)

El alcance de las variables depende de la cadena dinámica. No se tiene liga estática en los registros de activación. No es posible determinar estáticamente el tipo y el contexto de las variables. Por lo cual los programas son más dificiles de leer. Las variables locales pueden ser vistas por cualquier subprograma, por lo cual los programas son menos confiables. Los subprogramas invocados heredan los contextos de los invocadores, lo cual permite una comunicación entre las unidades del programa.

Procedure big; Var x : integer; Procedure sub1; Begin :::x end; -sub1 procedure sub2; var x: integer; begin ::::: end; - sub2 begin -big ::: end -big

Acceso profundo: La cadena dinámica es recorrida hasta encontrar la instancia de la variable. Se requiere guardar en el registro de activación el nombre de la variable.

Procedure c; Integer x,z; Begin X:=u+v; end; Procedure b; Integer w,x; Begin.... End; procedure A; integer v,w; begin :::::: end; program main; integer u,v; begin ::: end; Suppose the following sequence: Main calls A, A calls A, A calls B, B calls C.

Acceso superficial: Los nombres de las variables no se almacenan en el registro de activación. Solo hay una versión visible de una variable en un momento dado. Para implementarlo se puede tener un stack para cada nombre de variable o bien una tabla central de ambiente de referencia.

Stack separado para cada variable: Cuando una nueva variable es creada, se coloca en su respectivo stack. Cuando la rutina termina, la variable se retira del stack. Este método permite referencias rápidas a variables, pero el mantenimiento del stack es costoso.

Tabla central de ambiente de referencia: Contiene una lista de todos los identificadores. En compilación a cada variable se le puede asociar un desplazamiento en esta tabla. Cada identificador esta asociado con su dirección activa en curso. Una bandera indica si un identificador está activo o no.

Para cada activación la tabla debe reflejar el ambiente de referencia. Se necesita un stack oculto para recuperar los ambientes de referencia previos. Las referencias a variables son rápidas pero el mantenimiento del stack oculto es costoso.

El acceso profundo es eficiente al invocar subprogramas, pero las referencias a variables no locales son costosas. En el acceso superficial pasa lo contrario.

2.7. Paso de parámetros.

Existen dos formas en las que un subprograma puede tener acceso a los datos: Acceso directo de variables no-locales. Transmisión de parámetros. Los datos transmitidos como parámetros son ingresados mediante nombre locales para el subprograma.

Datos como parámetros.

Los parámetros formales están caracterizados por uno de los siguientes modelos semánticos: In-mode: Pueden recibir datos del parámetro real. Out-mode: Pueden transmitir datos hacia el parámetro real. Inout-mode: Pueden hacer ambos. Estos modelos describen el comportamiento del parámetro

Existen dos modelos conceptuales de cómo se efectúan las transferencias de datos en las transmisiones: Un valor real es desplazado físicamente (hacia el llamado, hacia el llamador, o ambos). Se usa una transferencia de la transmisión de acceso (usualmente un apuntador).

Paso por copia.

Se divide en tres subtipos: Paso por valor. Paso por resultado. Paso por valor-resultado.

Paso por valor.

El valor del parámetro real se usa para iniciar el valor del parámetro formal. La semántica es in-mode. Se puede implementar por medio de un desplazamiento físico. Desventaja: Si se usa un desplazamiento físico, las operaciones de almacenamiento y de desplazamiento pueden ser costosas si el parámetro es grande.

Ventaja: Los parámetros reales no sufren cambios, lo cual de alguna manera los protege de resultados no deseados.

Void swap (int a, int b) { int temp=a; a=b; b=temp; } We make the call: swap(c,d); The actions can be described like: a=c; b=d; move second parameter value in temp=a; a=b; b=temp;

Paso por resultado.

El parámetro formal actúa como variable local y justo antes del regreso su valor es transferido al parámetro real. La semántica es out-mode. Para implementarlo se requiere almacenamiento suplementario y operaciones de copia.

Desventaja: Puede haber colisión de parámetros, el orden en el que los parámetros reales están asignados determina su valor. La implementación debe ser capaz de elegir entre dos diferentes tiempos para evaluar las direcciones de los parámetros reales: al tiempo de la llamada o al tiempo de su regreso. Esto puede producir diferentes resultados.

Paso por valor- resultado.

El valor del parámetro real es usado para iniciar el parámetro formal. Justo antes de regresar el valor es transferido al parámetro real. La semántica es inout-mode. Desventaja. Requiere de múltiples almacenamientos para parámetros y de tiempo para copiar valores. El orden de asignación de los parámetros puede ser una causa de problemas.

f(int x by val-result, int y by val-result) { x=0; y++; } main() { int i,j; int a[5]={1,2,3,4,5}; get(i,j); f(a[i],a[j]); print(a); }

Ejemplo

Paso por referencia.

Transmite un camino de acceso al parámetro real. El parámetro real es compartido entre invocado e invocador. La semántica es inout-mode. Ventaja. Es eficiente en términos de espacio y tiempo, ya que no se requiere duplicar el espacio ni efectúa copia alguna.

Desventaja. El acceso a los parámetros formales será más lento pues se requiere de más nivel de direccionamiento indirecto que cuando los valores de los datos son transmitidos. Pueden además ocurrir cambios involuntarios en los parámetros actuales. Pueden crearse alias, ya que los caminos de acceso a los subprogramas abiertos estan abiertos.

swap (int& a, int& b) { int temp; temp=a; a=b; b=temp; } main() { int i; int a[5]={1,2,3,4,5}; get(i); swap(i,a[i]); print(a); }

f(int& x, int& y) { x=0; y++; } main() { int i,j; int a[5]={1,2,3,4,5}; get(i,j); f(a[i],a[j]); print(a); }

Ejemplo

Paso por nombre.

El parámetro formal es sustituido textualmente por el parámetro real correspondiente. La semántica es inout-mode. Se implementan mediante un thunk, que es un proceso que evalua la referencia adecuada. Ventaja: Es sumamente flexible.

Desventaja: El proceso es lento. El concepto de ligado tardío en el que está basada la Llamada por nombre es usado en poliformismo dinámico. La evaluación perezosa es otro mecanismo útil (es una forma de ligado tardío): El proceso de evaluación de las partes del código se realiza solo cuando la evaluación es necesaria.

int c=0; swap (int a by name, int b by name) { int temp; temp=a; a=b; b=temp; c++; } main() { int i; int a[5]={1,2,3,4,5}; int c,d; get(i); swap(i,a[i]); print(a); get(c,d); swap(c,d); print(a); }

Ejemplo

Paso por referencia es el estándar en FORTRAN. Paso por nombre es el estándar en ALGOL 60, pero es opcional el paso por valor. SIMULA 67 permite paso por valor, referencia y por nombre. C++, PASCAL y MODULA-2 permiten pasar por valor o por referencia.

Var w,x,y,z:integer; Procedure sub(a,b,c,d:integer); Var i: integer;... end; begin :::: call sub(w,x,y,z) {pass w by value, x by result, y by value-result, z by reference} ::: end;

Rutinas como parámetros.

Las rutinas pueden ser pasadas como parámetros, se dice que las rutinas son objetos primarios. Se tienen 3 opciones para elegir el ambiente de referencia de una rutina parámetro. 1. El ambiente del invocador. 2. El ambiente del bloque en donde está declarada. 3. El ambiente del bloque que incluye la instrucción de llamada que la transmite.

La primera opción se llama enlace superficial. La segunda opción se llama enlace profundo. La tercera opción no ha sido utilizada.

Enlace profundo: Se utiliza en los lenguajes estáticos estructurados por bloques. Se usa para crear una representación explícita del ambiente de referencia. Se comporta como si la rutina pasada como parámetro se ejecutara directamente. Al pasar una rutina como parámetro también se pasa su liga estática.

Para pasar la liga estática de A a B en una unidad U: Si A es un parámetro formal en U, se pasa la liga estática previamente pasada a U. Si A es no-local o localmente visible en U, se pasa un apuntador al registro de activación que esta a d pasos en la cadena estática originada en la invocadora. Donde d es la distancia entre la declaración de A y el punto donde es pasada como parámetro.

Enlace superficial: El ambiente de referencia es determinado por la cadena dinámica, empezando por el ultimo registro de activación. Se usa en algunos lenguajes con alcance dinámico.

int u,v; a() { int y; } b (routine x) { int u,v,y; c() {... y= }; x(); b(c);.... } main () { b(a); }

3. Bibliografía.

Programming language Concepts. Carlo Ghezzi, Mehdi Jazayeri. Tercera Edición, Ed. Wiley. Programming Languages. Design and implementation. Terrence W. Pratt, Marvin V. Zelkowitz. Cuarta Edición, Prentice Hall.

Concepts of programming languages. Robert W. Sebesta. Programming language pragmatics. Michael L. Scott.