Anterior | Superior | Siguiente

Guía de referencia básica de Ada 95

Estructura de un programa. Unidades

Unidades de programa, compilación y librería.

Un programa en Ada se estructura como un conjunto de unidades de programa, pueden ser:
  1. subprogramas, hay dos clases (procedimientos y funciones) y sirven para definir algoritmos.
  2. paquetes, sirven para agrupar conjuntos de entidades relacionadas.
  3. tareas, definen acciones que pueden ejecutarse en paralelo con otras.
  4. unidades protegidas, sirven para coordinar la compartición de datos entre unidades que se ejecutan en concurrencia.
  5. unidades genéricas, son subprogramas o paquetes parametrizados que definen componentes reusables.
Las unidades de programa pueden anidarse unas dentro de otras, pero sólo los subprogramas, paquetes (especificación e implementación) y unidades genéricas pueden ocupar el nivel más externo de anidamiento y formar una unidad de compilación. Una unidad de compilación es un componente de un programa que puede compilarse por separado. Se distinguen dos clases de unidades de compilación: las subunidades, que se encuentran lógicamente incluidas en otro componente, y las unidades de librería, que son componentes independientes que pueden usarse en distintos programas.

Un subprograma principal inicia y gobierna la ejecución de un programa y desde él  se desencadena la ejecución del resto de unidades que lo componen. Generalmente, el subprograma principal es un procedimiento sin parámetros. Implementaciones particulares del lenguaje pueden admitir otro tipo de subprogramas como  subprograma principal.

Una unidad de compilación típica consta de dos partes: (1) una cláusula de contexto que sirve para especificar las unidades de librería que se necesitan (no hace falta si no se necesita ninguna) y (2) una unidad de programa (subprograma, paquete o unidad genérica). El siguiente ejemplo muestra una unidad de compilación que proporciona un procedimiento sin parámetros llamado "Hola" que puede servir como subprograma principal de un programa o como unidad de librería utilizable como parte de un programa más complejo.

with Text_Io; --Cláusula de contexto
use Text_Io;

procedure
Hola is --Elemento de librería (subprograma)
begin
    Put_Line("Hola mundo");
end Hola;

La cláusula de contexto, si aparece, consta obligatoriamente de una cláusula with que es la que especifica, separadas por comas (","), las unidades de librería que se necesitan. En el ejemplo, la cláusula with especifica que se va a necesitar la unidad de librería "Text_Io" que es la que define el procedimiento "Put_Line" usado en el procedimiento "Hola" para escribir un saludo en la salida estándar.

Opcionalmente, se puede emplear además, una cláusula use para especificar unidades de librería que se van a usar con frecuencia, de manera que no sea necesario indicar el nombre de la unidad cada vez que se use un elemento de la misma. En el ejemplo, de no haberse incluido la cláusula use, tendría que haberse escrito:

with Text_Io; --Cláusula de contexto

procedure
Hola is --Elemento de librería (subprograma)
begin
    Text_Io.Put_Line("Hola mundo");
end Hola;

La cláusula use ahorra trabajo y hace que los programas parezcan menos densos. La cláusula use puede ponerse también en cualquier lugar entre las declaraciones de la unidad de programa, aunque ello reduce el alcance de su efecto.

En el caso de que la unidad de librería incluida en el with sea un subprograma, no tiene sentido ponerla en una cláusula use ya que carece de elementos que puedan ser referenciados individualmente.

with Hola; --Cláusula de contexto

procedure
Hola_2 is --Elemento de librería (subprograma)
begin
    Hola; --Llamada al procedimiento "Hola" incluido como
          --unidad de librería en la cláusula de contexto
end Hola;

Unidades genéricas.

Ada permite crear unidades genéricas, es decir, con parámetros que se pueden concretar para diferentes instancias de la unidad, consiguiendo de esta manera la reutilización de un código que se escribe una sola vez. Para ello basta anteceder la declaración de la unidad correspondiente con la palabra "generic"; los parámetros formales de la unidad se sitúan en la zona comprendida entre la palabra "generic" y el comienzo de la declaración de la unidad. Sólo los subprogramas y los paquetes admiten parametrización.

generic
<parámentros formales genéricos>
<unidad genérica>

Parámetros formales genéricos.

Los parámetros formales genéricos pueden ser: objetos, tipos o subprogramas. Al igual que los parámetros formales de los subprogramas, algunas clases de parámetros formales genéricos pueden tener un valor por defecto. Los parámetros formales genéricos se declaran de distinta forma según su naturaleza:
  1. Parámetros por valor. Se declaran como: <nombre>: <tipo> := <valor por defecto>, siendo el valor por defecto opcional.

    Valor1: integer;
    Valor2: positive := 1;

  2. Tipos privados: "private", "limited private", "tagged private",... La definición del tipo privado corresponde, en este caso, al llamador (no va a aparecer en la parte private, si estamos desarrollando un paquete).

    type Tipo1 is private;
    type Tipo2 is limited private;
    type Tipo3 is tagged private;
    type Tipo4 is tagged limited private;
    type Tipo5 is new OtroTipoTagged with private ;
    ...

  3. Tipos escalares:
    1. Discretos. Se utiliza el símbolo "(<>)".
    2. Enteros con signo. Se utiliza "range <>".
    3. Modulares. Se utiliza "mod <>".
    4. Reales en coma flotante. Se utiliza "digits <>".
    5. Reales en coma fija. Se utiliza "delta <>".
    6. Decimales. Se utiliza "delta <> digits <>".
    7. type TDiscreto is (<>);
      type TEntero is range <>;
      type TModular is mod <>;
      type TRealFlot is digits <>;
      type TRealfijo is delta <>;
      type TDecimal is delta <> digits <>;

  4. Arrays. Hay que especificar el tipo de los índices y el tipo de los elementos que pueden ser a su vez parámetros formales genéricos declarados previamente:

    type TElemento is private;
    type Índice is (<>);
    type Vector is array (Índice range <>) of TElemento;

  5. Punteros. Hay que especificar el tipo apuntado que puede ser un parámetro formal genérico declarado previamente:

    type TNodo is private;
    type TP_Nodo is access TNodo;

  6. Subprogramas. Se utiliza la palabra "with" precediendo al protocolo del subprograma que se espera:

    type TElemento is private;
    with procedure Acción(X : in TElemento);

    Se puede especificar un nombre por defecto para el subprograma pasado por parámetro, utilizando "is <nombre>":

    with procedure Acción (X : in TElemento) is Escribir;

    Si se quiere que el nombre por defecto sea el mismo que el del parámetro formal, se pondrá como nombre "<>":

    with procedure Acción (X : in TElemento) is <>;

    En caso de especificar un nombre por defecto se podrá omitir el parámetro al instanciar la unidad.

  7. Paquetes. Se utiliza la palabra "with" precediendo a la instanciación del paquete que queremos como parámetro formal.

    with package <Nombre_formal> is new <Nombre_genérico> (<>);

    Instanciación de unidades genéricas.

    Las unidades genéricas representan una plantilla mediante la cual se indica al compilador cómo poder crear (en distintas situaciones configuradas por los parámetros) unidades no genéricas que responden al mismo funcionamiento general. De esta forma, las unidades genéricas no se usan directamente, sino sólo para crear instancias no genéricas a partir de ellas. Para crear una instancia de una unidad genérica hay que especificar un nombre para la unidad no genérica que el compilador va a construir y los parámetros reales genéricos a utilizar en el lugar de los formales:

    <tipo unidad> <nombre de la instancia> is new <nombre unidad genérica> (<parámetros reales genéricos>);

    Los parámetros reales genéricos se corresponden con los formales por posición, o por nombre si se utiliza el símbolo "=>". No es necesario proporcionar parámetros reales para los formales que tengan un valor por defecto (cuando sea adecuado para el propósito de la instancia).

Grupo de Estructuras de Datos y Lingüística Computacional - ULPGC.

Anterior | Superior | Siguiente