FLP Datos y Operaciones
FLP Datos y Operaciones
FLP Datos y Operaciones
Apunte de Cátedra
Contenidos
1. Conceptos Básicos
2. Datos
- Datos Simples
- Datos Estructurados
3. Operaciones
- Operaciones Primitivas
- Operaciones Extensibles
CONCEPTOS BÁSICOS
Ejemplo
int count;
-
-
count = count + 5;
El tiempo de binding es muy importante para entender la semántica de un LP, por ejemplo:
a) para entender que hace un programa o debe hacer para asociar los parámetros actuales en una
llamada con los parámetros formales
b) para determinar el valor actual de una variable, es necesario saber cuando la variable fue asociada a
su almacenamiento
c) Recursividad
- Página 1 -
Carrera: Licenciatura en Sistemas
Asignatura: Fundamentos de Lenguajes de Programación
Apunte de Cátedra
El tiempo de binding responderá la pregunta ¿cuándo ocurren las cosas, en tiempo de compilación o en
tiempo de ejecución?
Cambios pequeños en la definición del LP producen cambios en los tiempos de binding que afectan
totalmente las características de un LP.
control
datos operaciones
DATOS
Algunos objetos de datos que existen durante la ejecución de un programa son definidos por el programador:
variables, constantes, arreglos, archivos, etc. Otros objetos de datos son definidos por el sistema, son objetos
que construye el sistema para “mantenimiento” durante la ejecución del programa y a los cuales el
programador no tiene acceso, por ejemplo: pilas de almacenamiento, registro de activación, etc.
Un objeto de datos es un recipiente para valores de datos (lugar donde se puede guardar un valor y luego
recuperar). Un objeto se caracteriza por un conjunto de atributos (tipo).
Valor de datos: puede ser un solo número, carácter o posiblemente un apuntador a un objeto de datos.
Un valor de datos se representa por medio de un patrón particular de bits.
Un objeto de datos participa de varios enlaces durante el tiempo de vida, mientras que los atributos de un
objeto de datos, no varía durante su tiempo de vida. Enlaces más importantes:
1. Tipo: asociación que comúnmente se hace en tiempo de compilación, asociando al objeto de dato con un
conjunto de valores que pueden tomar.
2. Localidad: enlace del objeto de datos con una localidad de almacenamiento en la memoria. Por lo
general no puede ser modificado por el programador sino que es establecida y modificado por rutinas de
gestión de almacenamiento.
3. Valor: enlace por lo general resultado de una asignación.
- Página 2 -
Carrera: Licenciatura en Sistemas
Asignatura: Fundamentos de Lenguajes de Programación
Apunte de Cátedra
4. Nombre: enlace a uno o más nombres por medio de los cuales se puede hacer referencia durante la
ejecución del programa. Por lo general se establece mediante declaración.
5. Componente: el enlace de uno o más objetos de datos a uno o más objetos de datos (pointers)
Los objetos de datos variables pueden ser simples o complejos, tienen un nombre y se les da valor mediante
una asignación. Las constantes, son simples y tienen nombre.
Tipos de datos
El tipo de un dato indicará los valores que puede tomar y las operaciones que se le pueden aplicar.
Cuando se diseña un LP deberá especificarse para cada tipo de dato: atributos, valores y operaciones.
Cuando se implementa el LP deberá implementarse para cada tipo de datos: representación del
almacenamiento y representación de las operaciones (como manipulará los objetos de datos).
Declaraciones
Para el LP la declaración es una operación que le permite al compilador organizar el manejo de datos. Para
el programador la declaración es un enunciado donde especifica: identificadores y tipo de variables (se hace
binding). El lugar de la declaración implica determinar el tiempo de vida.
En Pascal hay una sección para declarar variables
var
entero : integer;
r : real;
Ejemplo:
Var
A : array[2..20] of integer;
- Página 3 -
Carrera: Licenciatura en Sistemas
Asignatura: Fundamentos de Lenguajes de Programación
Apunte de Cátedra
1.Datos Simples
a) Números (enteros y reales) por lo general se utiliza la representación del hardware con descriptor
estático (implícito) pero hay LP que utilizan descriptor dinámico (explícito) como Lisp y Prolog.
α signo datos
α dirección en la tabla de
Descriptor: cantidad de símbolos
bytes, signo
b) Carácter: la representación de almacenamiento es igual que para los enteros solo que no requiere bits
para el signo, lo cual lo hace más sencillo (0-127 ASCII)
c) Strings
α → entero
α → string
- Página 4 -
Carrera: Licenciatura en Sistemas
Asignatura: Fundamentos de Lenguajes de Programación
Apunte de Cátedra
2. Datos Estructurados
- Arreglos
Se organiza con un descriptor que contiene los límites del subíndice al tipo base y la dirección de
comienzo. El almacenamiento se hace en bytes contiguos.
Para acceder a A[I] con dir = α + ( I – LI ) * N
En Pascal, el tipo del índice puede ser cualquier escalar. Por dicha razón el descriptor del arreglo debe
almacenar información referida al tipo del índice y el cómputo de la dirección de acceso se complica un
poco.
- Página 5 -
Carrera: Licenciatura en Sistemas
Asignatura: Fundamentos de Lenguajes de Programación
Apunte de Cátedra
- Registros
El almacenamiento es secuencial pero el descriptor es más complejo. El acceso es en general aleatorio.
- Conjuntos
Hay dos formas de almacenamiento:
a) Cadenas de bits
Universo de valores del conjunto : e1, e2, ...en. El conjunto S se representa por una cadena de bit como:
αs → 1 0 1 0 0 1 0 0 1
e1 en
- Significa que el elemento e1 está en el conjunto y el elemento e2 no.
- Se usa el bit 1 para indicar que el elemento esta y el bit 0 para lo contrario.
- Esta implementación sirve para universos pequeños.
b) Dispersión – Hash
0 → →
1
f(K) 2
K
N → →
OPERACIONES
Tipos de operaciones
- Sobre los datos del usuario (las usuales)
- Sobre los datos del sistema (llamadas a subprogramas, declaraciones, pasaje de parámetros, etc.)
- Página 6 -
Carrera: Licenciatura en Sistemas
Asignatura: Fundamentos de Lenguajes de Programación
Apunte de Cátedra
Existen multitudes de operaciones, desde la suma hasta la unificación, es imposible e inútil abarcar
todas.
El conjunto de operaciones definidas para un tipo de datos determina como se pueden manipular los
objetos de datos de ese tipo. Las operaciones pueden ser operaciones primitivas, las operaciones se
especifican como parte de la definición del LP o pueden ser operaciones definidas por el programador
(subprogramas, métodos).
Signatura: número, orden y tipos de datos de los argumentos y número, orden y tipo de los resultados. Es
conveniente usar la notación matemática:
nombre_operación : tipo_argumento x tipo_argumento x....... tipo_argumento → tipo_resultado
Ejemplos
a) adición de enteros: + : entero x entero → entero
b) igualdad: = : entero x entero → booleano
c) raíz cuadrada: sqrt : real → real
Operaciones indefinidas: operaciones que no están definidas para ciertas entradas (excepción – underflow)
Argumentos implícitos: la operación puede acceder a argumentos implícitos a través de variables globales u
otras referencias no locales, lo cual deja sin resolver la cantidad de datos que utiliza la operación.
Efectos colaterales: (resultados implícitos) Una operación puede devolver un resultado explicito, pero
también puede modificar los valores guardados en otros objetos de datos, tanto definidos por el programador
como por el sistema. Estos resultados implícitos se conocen como efectos colaterales. Una función puede
modificar sus argumentos de entrada y también devolver un valor.
Automodificación: Una operación puede modificar su propia estructura interna, ya sean sus datos locales
que se retienen entre ejecuciones o su propio código. Los resultados que la operación produce, por lo tanto,
dependen no solo de los argumentos de entrada sino del historial completo de llamadas anteriores
(operaciones sensibles al historial). Ejemplo: el generador de números random o aleatorios, que aunque se
les da los mismos argumentos genera diferentes números. Esto es porque guarda como dato local “el número
semilla” que se modifica entre llamada y llamada, y se utiliza para el cómputo.
- Página 7 -
Carrera: Licenciatura en Sistemas
Asignatura: Fundamentos de Lenguajes de Programación
Apunte de Cátedra
Declaración de operaciones
Por lo general las operaciones primitivas no deben ser declarados (si los argumentos usados en las mismas).
Sin embargo, si es común declarar la signatura completa de las operaciones definidas por el programador
(funciones o procedimiento)
Ejemplo
float Sub(int X, float Y) // en C
Operaciones Primitivas
1. Aritméticas: Los operandos y el resultado son números. Puede haber excepción-overflow pero no hay
efectos colaterales, operadores implícitos o automodificación. La diferencia fundamental entre los diferentes
LP es si puede hacer chequeo estático.
2. Relacionales: Los operandos son (en gral.) del mismo tipo (números, chars, strings) y el resultado es un
booleano (o bien, 0 y 1 en C). En algunos casos la declaración de tipos permite chequeo estático.
3. Booleanas: recibe y entrega boléanos (0-1)
4.Conversión de tipos: si durante la verificación de tipos (estática o dinámica) ocurre una discordancia entre
el tipo real de un argumento y el tipo esperado para esa operación, entonces:
- error (compilación o ejecución)
- se aplica una coerción (conversión implícita de tipos) para cambiar el argumento de tipo real al tipo
correcto.
Signatura: conversión_operación : tipo1 → tipo2
Casi todos los LP proveen conversión de tipo:
- Explícitas: las hace el programador. Por ejemplo, la función round en Pascal, cast en C y Java.
- Implícitas: las hace automáticamente el lenguaje.
Ejemplos:
Si B es entero y C es real
A: = B + C; // Tanto Pascal como C pasarán B a real antes de hacer la adición
Si P es longint y Q es integer
L := P + Q; // se pasa Q a longint
5. Asignación: es una operación. Su resultado es implícito (modifica el estado de una variable) El resultado
puede ser explícito (C) o puede no estar permitido (Pascal).
La asignación es una operación básica para combinar el enlace de un valor de un objeto de datos. Trabaja
por efecto colateral. Recibe un operando y modifica el contenido de la referencia.
A := B + C
R E
- Página 8 -
Carrera: Licenciatura en Sistemas
Asignatura: Fundamentos de Lenguajes de Programación
Apunte de Cátedra
Supongamos que E se evalúa sin problemas pero es de tipo diferente a R. Si el tipo puede convertirse sin
colisión (entero a real) entonces se hace, sino:
- error en tiempo de ejecución (Pascal).
- conversión automática del resultado (C) .
- conversión automática del tipo de R. (Lisp).
Semántica de la asignación:
A = B o A := B Significa asignar una copia del valor de la variable B a la variable A.
(A y B son enteros)
- En Pascal y Modula-2 están ambos tipos de subprogramas, pero no se usa CALL sino llamada implícita.
- En principio las funciones no siempre pueden ponerse en asignaciones: for i:= f(x)....
- En C solo hay funciones, lo cual hace más homogéneo el tratamiento en general.
- Las operaciones en un subprograma son los parámetros (formales o actuales) En algunos lenguajes, el
espacio de memoria para dichos parámetros y los resultados, deben reservarse “antes de la ejecución”
(Pascal). Además el tipo de resultado está limitado a los predefinidos. (se solucionan con estructuras
dinámicas y pasajes por referencia).
Un subprograma es una operación abstracta definida por el programador. Casi todo los LP ofrecen
facilidades para definir e invocar subprogramas. Debemos tener en cuenta dos puntos de vista:
1. Diseño de programas: el sentido que tiene el subprograma para el programador que lo define (varias
operaciones primitivas)
2. Diseño del LP: aspectos del LP que posibilitan al programador definir subprogramas (tipo de
compilador) y su implementación que posibilita la invocación de los subprogramas en tiempo de ejecución.
Definición de un subprograma:
1. Especificación
2. Implementación
La especificación comprende:
- Nombre del subprograma
- Página 9 -
Carrera: Licenciatura en Sistemas
Asignatura: Fundamentos de Lenguajes de Programación
Apunte de Cátedra
- Signatura
- Acción (descripción de la función del subprograma)
Ejemplo:
float FN (float X, int Y) // C
function FN (X: real; Y: integer) : real; // Pascal
Cuando un subprograma devuelve explícitamente un resultado se denomina por lo general “función”. Pero
algunos subprogramas devuelven más de un resultado o ninguno. Se denominan procedimientos o
subrutinas.
Ejemplo
void Sub (flota X, int Y, flota Z, int *W); // en C
procedure Sub (X: real, Y: real, Var Z: real, Var W: real); // en Pascal
Estos subprogramas, pueden modificar los valores de los argumentos (E/S) devuelven resultados
implícitamente.
- signatura: Sub : real1 x entero1 → real2 x entero2
¿qué significa la siguiente signatura? Sub : real1 x entero1 → real1
Implementación de un subprograma:
Un subprograma se implementa usando estructuras de datos y operaciones que suministra el LP. La
implementación por lo general está definida por un cuerpo: declaración + enunciados.
Verificación de tipos:
Se hace igual que para las operaciones primitivas (sobre argumentos y resultados)
Puede ser estática o dinámica
- Página 10 -
Carrera: Licenciatura en Sistemas
Asignatura: Fundamentos de Lenguajes de Programación
Apunte de Cátedra
El programador escribe una “definición” de subprograma como una propiedad estática (tiempo de
compilación); durante la ejecución si se llama (invoca) el subprograma se crea una “activación” del
subprograma. Cuando se completa la ejecución del subprograma la activación se destruye. Si se hace otra
llamada, se crea otra activación. A partir de una sola definición se pueden crear muchas activaciones
durante la ejecución del programa. Es decir definición ≠ activación, la información disponible es
diferente.
Pero la definición se considera una “plantilla” para crear activaciones. Cuando un subprograma se activa
deberán estar disponibles todos los datos que requiera (argumentos, locales) es decir, una activación se
representa como un bloque de almacenamiento que contienen ciertos elementos de datos componentes que
son importantes para la activación del subprograma. Debe asignarse almacenamiento cuando se destruye una
activación. Tienen un “tiempo de vida”, el tiempo durante la ejecución entre la “llamada” que la crea y el
“retorno” que la destruye.
Esta definición especifica los componentes necesarios para una activación en tiempo de ejecución:
1. El renglón de la signatura suministra información para el almacenamiento de parámetros (X e Y) y el
almacenamiento del resultado, de tipo real.
2. Las declaraciones indicarán la necesidad de almacenamiento de variables locales (M y N).
3. Almacenamiento de literales y constantes valinic = 20 y valfinal = 10 como constantes, 20 y 10 como
literales.
4. Almacenamiento para código ejecutable.
La definición del subprograma permite organizar estas áreas de almacenamiento y determina el código
ejecutable durante la traducción/compilación. El resultado de la traducción es la plantilla que se usa para
construir cada actividad particular en el momento en que el subprograma es invocado en la ejecución.
- Página 11 -
Carrera: Licenciatura en Sistemas
Asignatura: Fundamentos de Lenguajes de Programación
Apunte de Cátedra
Parte estática: segmento de código (constantes, código, literales). Esta parte no varía durante la
ejecución de subprogramas y por lo tanto una solo copia puede ser compartida por todas las activaciones.
Parte dinámica: registro de activación (parámetros, variables locales, resultados, otros datos de
almacenamiento). Esta parte tiene la misma estructura para cada activación, pero diferentes valores. Cada
activación tienen una copia propia del registro de activación.
Registro de Activación
para FN Invocaciones
sucesivas
Segmento de Código Registro de Activación del subprograma
para FN para FN FN
Registro de Activación
para FN
Solo se almacena un segmento de código para toda la ejecución de todo un programa (creado
estáticamente).
Los registros de activación se crean y destruyen dinámicamente durante la ejecución. Cada vez que se
llama al subprograma y cada vez que el mismo concluye.
El tamaño y estructura del registro de activación se puede determinar durante la traducción. Por lo tanto
el compilador puede determinar cuántos componentes se necesitan para guardar los datos necesarios en el
registro de activación y la posición de cada componente en el mismo. Se puede tener acceso a los
componentes usando el cálculo de dirección base más desplazamiento para registros ordinarios.
Para crear un nuevo registro de activación solo se requiere que se conozca el tamaño del bloque de
almacenamiento del registro, en vez de su estructura interna en detalle. En lugar de guardar una plantilla
completa de registro de activación en tiempo de ejecución solo se debe guardar el tamaño del registro de
activación para que lo use la operación de “llamar” al crear el registro de activación. La gestión de
almacenamiento en la llamada y retorno de subprogramas implica solo la asignación de un bloque de tamaño
apropiado y su liberación.
Prólogo
Cuando se llama un subprograma, tiene lugar un cierto número de acciones ocultas que se ocupan de:
establecer el registro de activación, transmitir los parámetros, crear vínculos para referencias no locales y
actividades similares (mantenimiento). Para que este prólogo se ejecute el traductor inserta el bloque de
código antes que el código del subprograma.
- Página 12 -
Carrera: Licenciatura en Sistemas
Asignatura: Fundamentos de Lenguajes de Programación
Apunte de Cátedra
Epílogo
Cuando un subprograma termina, deben realizarse una serie de tareas de “mantenimiento”: devolver los
resultados, liberar memoria. Igual que el prólogo, el traductor inserta este código al final del subprograma.
- Página 13 -