Ada (en honor de Lady Augusta Ada Byron) es un lenguaje de programación estático de propósito general y fuertemente tipado, inspirado en Pascal, que fue creado en 1983 por Jean Ichbiah de CII Honeywell Bull por encargo del Departamento de Defensa de los Estados Unidos. Es un lenguaje multipropósito, orientado a objetos y concurrente, pudiendo llegar desde la facilidad de Pascal hasta la flexibilidad de C++.
Fue diseñado con la seguridad en mente y con una filosofía orientada a la reducción de errores comunes y difíciles de descubrir. Para ello se basa en un tipado muy fuerte, detecta muchos errores en tiempo de compilación, razón por la cula facilita la creación de programas fiables. Ada se usa principalmente en entornos en los que se necesita una gran seguridad y fiabilidad como la defensa, la aeronáutica, la gestión del tráfico aéreo y la industria aeroespacial entre otros.
Para utilizar el compilador GNAT, primeramente, se debe seguir lo pasos de instalación especificados por el instalador Gnat313p.exe.
Posteriormente, para poder ejecutar apropiadamente los ejemplos de ADA propuestos, será necesario editar el archivo autoexec.bat de Windows para modificar la variable del sistema PATH, especificando dónde se encuentran tales ejemplos. A su vez, es necesario reflejar dónde se encuentra el directorio ...\GNAT\bin.
Los programas ADA poseen la extensión “.adb”. Para realizar la compilación y generación del programa ejecutable es necesario el siguiente comando, el cual se ingresa en una interfaz de comandos de MSDOS:
gnatmake -gnatf <nombre de archivo.adb>
Cabe aclarar, por simple conveniencia, que es necesario estar ubicado en el directorio dónde se encuentra el archivo a compilar. Luego de ejecutar el comando antes mencionado, se genera un archivo ejecutable el cual permite ver los resultados del programa antes compilado.
Debido a que existen otras formas de compilación de programas ADA, aconsejamos ver “GNAT for Windows NT: User's Guide”.
Además de los ejemplos propuestos por la cátedra, se pueden encontrar otros proporcionados por el software instalado (GNAT) y una gran cantidad de definiciones de términos ADA.
La forma de pasar parámetros en ADA se realiza anteponiendo en la definición de los parámetros (parámetros formales) alguno de las siguientes especificaciones: IN, OUT, o IN OUT. Si se omite alguno de ellos, se toma por defecto que es IN.
La definición de cada forma de pasar los parámetros es la siguiente:
IN: El parámetro formal es una constante y permite sólo lectura del valor asociado al parámetro actual.
IN OUT: El parámetro formal es una variable y permite tanto leer como modificar el valor asociado al parámetro actual.
OUT: El parámetro formal es una variable y permite sólo modificar el valor asociado al parámetro actual.
Existen otras formas de pasar parámetros al momento de invocar a subprogramas. Estos modos de pasaje de parámetros se llaman por NOMBRE y por DEFECTO (Named and Default Parameters).
Los parámetros por nombre, expresan explícitamente el valor que será pasado al parámetro formal:
<Nombre del Parámetro Formal> => <Valor | Variable>
El pasaje de parámetros por nombre permite también los parámetros por defecto. Esto significa que a veces uno o más parámetros definidos con IN, toman el mismo valor en cada evocación. Para ello se provee una expresión por defecto en la especificación del subprograma (parámetros formales) y se omite el parámetro real correspondiente en el llamado al subprograma.
En los ejemplos mencionados en la siguiente sección se ilustran los diferentes modos de pasar parámetros en ADA.
Ejemplos simples de pasaje de parámetros resueltos proporcionado por la cátedra
Ejemplo de los modos IN, OUT, IN OUT, NAMED y DEFAULT parameters
OBSERVACIÓN: Se adjuntan cuatro ejemplos triviales sobre los distintos modos o formas de pasaje de parámetros en ADA.
Ejemplo 1: ADA_Ej1.adb.
Parámetros implicados IN, OUT, IN OUT.
Se ingresan dos números. Al primero de ellos, se le suma dos unidades y se lo multiplica por el segundo (procedimiento PROD).
Finalmente, se muestra el resultado de los parámetros reales luego de invocar a PROD.
Ejemplo 2: ADA_Ej2.adb.
Parámetros implicados IN OUT.
Se tiene un arreglo de N elementos, donde cada celda del arreglo tiene el valor 1.
Se muestra como influye la variación del índice de recorrido del arreglo (por el modo IN OUT) dentro del procedimiento SILLY.
Finalmente, se muestra el valor de tal índice y el estado del arreglo luego de invocar a SILLY.
Ejemplo 3: ADA_Ej3.adb.
Parámetros implicados NAMED PARAMETERS.
Se tiene un procedimiento (CUADRATIC) que calcula las raíces de una ecuación cuadrática (Ax2+Bx+C=0).
Se pasan como parámetro los términos A, B y C de dicha expresión, para luego mostrar el valor de las raíces encontradas.
Ejemplo 4: ADA_Ej4.adb.
Parámetros implicados DEFAULT PARAMETERS.
Se tiene un procedimiento (GENERICS) el cual establece valores por defecto a sus parámetros.
Luego de diferentes invocaciones a dicho procedimiento, se muestran los resultados obtenidos sobre tales parámetros.
En la mayoría de los lenguajes las conversiones son implícitas. Ada requiere que las conversiones sean explícitas, de lo contrario arrojan errores de compilación. Las conversiones explícitas se permiten entre tipos relacionados como los definidos a continuación:
conversión_tipo ::= tipo_indicado (expresión_a_convertir)
Las únicas conversiones permitidas corresponden a los siguientes tres casos:
Tipos numéricos: La expresión puede ser de cualquier tipo numérico; el valor de la expresión es convertido al tipo base del tipo indicado, donde el tipo base debe ser un tipo numérico.
Tipos arreglo: La conversión es permitida cuando para ambos tipos de arreglos (el tipo operando, y el tipo base del tipo indicado) los tipos de indice para cada dimensión son los mismos o uno es derivado de otro, y los tipos componentes son los mismos o uno es derivado de otro.
Tipos derivados: La conversión es permitida cuando el tipo del operando es directamente derivado del tipo indicado, o viceversa. La conversión puede resultar en un cambio de representación.
Ejemplos de conversiones de tipos numéricos proporcionados por la cátedra
CONV_EJ1.ADB: Ejemplo de conversión de tipo numéricos básicos
CONV_EJ2.ADB: Ejemplo de conversión definiendo nuevos tipos a partir de los tipos numéricos básicos
CONV_EJ3.ADB: Ejemplo de conversión definiendo subtipos a partir de tipos definidos por el usuario.
http://isa.uniovi.es/docencia/TiempoReal/Recursos/Transpa_Ada/
http://www.gnat.com
http://www.gedlc.ulpgc.es/docencia/mp_i/GuiaAda
http://lidi.info.unlp.edu.ar/~catedras/ada/
http://www.gnat.com
Barnes, J. G. P. Programming in ADA – Second Edition. October, 1983.
Ada95 Reference Manual
GNAT for Windows NT: User's Guide.
GNAT, The GNU Ada 95 Compiler. Document revision level 1.316. GNAT Version 3.1
------------------------------------------------------------------------------
-- CONV_EJ1.ADB - Ejemplo sencillo de conversion de tipos numericos basicos.
-- Catedra Lenguajes de Programacion 1
-- UNCPBA - Universidad Nacional del Centro de la Prov. de Bs. As.
------------------------------------------------------------------------------
-- OBSERVACIONES:
-- En este ejemplo se usaron los siguientes procedimientos de ADA, los cuales
-- se encuentran en el paquete Gnat.IO:
-- Put: Produce una salida por pantalla.
-- En la primer sentencia se convierte una expresion real a un entero y asig-
-- narla a un entero. En la segunda, se convierte un entero a un real.
------------------------------------------------------------------------------
With Gnat.IO; use Gnat.IO;
procedure ej1 is
S: Integer;
T: Float;
F: Float;
begin
Put("Entre un valor para T:");
Get(Integer(T));
New_Line;
S:=Integer(T);
F:=Float(S);
Put("F es: ");
New_Line;
Put(S);
end ej1;
------------------------------------------------------------------------------
-- CONV_EJ2.ADB - Ejemplo sencillo de un procedimiento en el que dado dos
-- valores enteros obtenidos desde teclado se los suma e imprime el resultado.
-- Catedra Lenguajes de Programacion 1
-- UNCPBA - Universidad Nacional del Centro de la Prov. de Bs. As.
------------------------------------------------------------------------------
-- OBSERVACIONES:
-- En este ejemplo se usaron los siguientes procedimientos de ADA, los cuales
-- se encuentran en el paquete Gnat.IO:
-- Put Produce una salida por pantalla.
-- Get Produce una entrada por pantalla.
-- New_Line Muestra una nueva linea en blanco por pantalla.
-- Put_Line Muestra una cadena de caracteres por pantalla.
-- Type Define un nuevo tipo definido por el usuario
------------------------------------------------------------------------------
-- With Gnat.IO; use Gnat.IO;
-- procedure ej2 is
-- type Peras is new Integer;
-- type Naranjas is new Integer;
-- A : Peras;
-- B : Naranjas;
-- C : Integer;
-- begin
-- Put ("Ingrese primer operando entero: ");
-- Get (A);
-- New_Line;
-- Put ("Ingrese segundo operando entero: ");
-- Get (B);
-- New_Line;
-- C:= A+B;
-- Put ("La suma es: ");
-- Put (C);
-- end ej2;
------------------------------------------------------------------------
-- OBSERVACIONES: Si ejecutamos el codigo anterior arrojara errores de
-- compilacion en la suma debido a que los operandos son de distinto
-- tipo. De la misma forma, no permite obtener los valores por teclado.
-- Para poder realizar estas operaciones es necesario indicar explicita-
-- mente que las variables A y B se las usa como enteros.
-- El codigo correcto seria el siguiente:
-------------------------------------------------------------------------
With Gnat.IO; use Gnat.IO;
procedure ej2 is
type Peras is new Integer;
type Naranjas is new Integer;
P : Peras;
N : Naranjas;
S : Integer;
begin
Put ("Ingrese primer operando entero: ");
Get (Integer(N));
New_Line;
Put ("Ingrese segundo operando entero: ");
Get (Integer(P));
New_Line;
S:= Integer(P)+Integer(N);
Put ("La suma es: ");
Put (S);
end ej2;
--------------------------------------------------------------------------------
-- CONV_EJ3.ADB - Ejemplo simple de conversiones explicitas con tipos derivados.
-- Catedra Lenguajes de Programacion 1
-- UNCPBA - Universidad Nacional del Centro de la Prov. de Bs. As.
---------------------------------------------------------------------------------
-- OBSERVACIONES:
-- En este ejemplo se usaron los siguientes procedimientos de ADA, los cuales
-- se encuentran en el paquete Gnat.IO:
-- Put Produce una salida por pantalla.
-- Get Produce una entrada por pantalla.
-- New_Line Muestra una nueva linea en blanco por pantalla.
-- Put_Line Muestra una cadena de caracteres por pantalla.
-- Type...is new Define un subtipo derivado de un tipo definido por el usuario
---------------------------------------------------------------------------------
With Gnat.IO; use Gnat.IO;
procedure ej3 is
type DIA is (LUN,MAR,MIE,JUE,VIE,SAB,DOM);
type DIASEMANA is new DIA range LUN..VIE; --tipo derivado
DiaEntrega: DIASEMANA;
DiaFeriado: DIA;
begin
DiaEntrega:= DIASEMANA(DiaFeriado); --CASO 1
DiaFeriado:= DIA(DiaEntrega); -- CASO 2
end;
-------------------------------------------------------------------------------------------------------------
-- OBSERVACIONES: En el ejemplo anterior la primer sentencia no siempre se puede ejecutar. Se produce
-- un error en tiempo de ejecucion debido a que intenta asignar a una variable un valor que no es alcanzado
-- por su tipo .
-- CASO 1: Si la variable DiaFeriado hubiera tenido asignado un valor entre LUN.. VIE, la conversion se podria
-- realizar sin producirse el error. Pero si,
-- DiaFeriado:= DOM;
-- DiaEntrega:= DIASEMANA(DiaFeriado);
-- daria error de ejecucion porque DOM no es un valor que esta en el rango de DIASEMANA
-- CASO 2: La conversion inversa, de una variable del tipo DIASEMANA al tipo DIA, no produce problemas ya que el rango de
-- DIASEMANA esta contenido dentro del rango del tipo DIA
---------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------
-- ADA_Ej1.adb - Ejemplo simple de pasaje de parametros en ADA
-- Ejemplo de los modos IN, OUT, IN OUT
-- Catedra Lenguajes de Programacion 1
-- UNICEN - Universidad Nacional del Centro de la Prov. de Bs. As.
------------------------------------------------------------------------------
-- OBSERVACIONES:
-- En este ejemplo se usaron los siguientes procedimientos de ADA, los cuales
-- se encuentran en el paquete Gnat.IO:
-- Put Produce una salida por pantalla.
-- Get Produce una entrada por pantalla.
-- New_Line Muestra una nueva linea en blanco por pantalla.
-- Put_Line Muestra una cadena de caracteres por pantalla.
------------------------------------------------------------------------------
With Gnat.IO; use Gnat.IO;
procedure ADA_EJ1 is
A, B, C, D : Integer;
procedure PROD (P, Q : in INTEGER; R: out INTEGER; S: in out INTEGER ) is
begin
R := P * Q;
S := R;
end PROD;
begin
New_Line;
Put_Line (" --- ADA_Ej1.adb - Ejemplo simple de pasaje de parametros en ADA ---");
Put_line (" --- IN / OUT / IN OUT PARAMETERS ---");
New_Line;
Put("Ingrese A: ");
Get (A);
New_Line;
Put("Ingrese B: ");
Get (B);
New_Line;
PROD (2+A, B, C, D);
Put_Line("El resultado de (2+A)*B es: ");
New_Line;
Put("Por parametro OUT: ");
Put(C);
New_Line;
Put("Por parametro IN OUT: ");
Put(D);
New_Line;
end ADA_EJ1;
--------------------------------------------------------------------------------
-- ADA_Ej2.ADB - Ejemplo simple de pasaje de parametros IN OUT.
-- Catedra Lenguajes de Programacion 1
-- UNICEN - Universidad Nacional del Centro de la Prov. de Bs. As.
---------------------------------------------------------------------------------
-- OBSERVACIONES:
-- En este ejemplo, el modo in equivale a copiar en X un valor en la llamada,
-- el modo out equivale a copiar el valor de X al terminar de ejecutar el procedimiento
-- y el modo in out equivale a la composicion de los anteriores.
-- Put Produce una salida por pantalla.
-- Get Produce una entrada por pantalla.
-- New_Line Muestra una nueva linea en blanco por pantalla.
-- Put_Line Muestra una cadena de caracteres por pantalla.
---------------------------------------------------------------------------------
with Text_IO; use Text_IO;
procedure ADA2 is
I:INTEGER;
A:array (1 .. 10) of INTEGER;
procedure SILLY (X: in out INTEGER) is
begin
I:=I+1;
X:=X+1;
end SILLY;
begin
A(5):=1;
I:=5;
SILLY(A(I));
end;
-------------------------------------------------------------------------------------------------------------
-- OBSERVACIONES: En el ejemplo anterior, el valor final en A(5) sera 2,
-- I tomara el valor 6, pero A(6) no sera afectado. Es decir, al momento de la
-- llamada la variable X se asocia a A(5) no a A(I), por lo que cualquier cambio
-- en I no influye en X. Si el modo es in, entonces el parametro real
-- puede ser cualquier cualquier expresion del tipo indicado en el parametro formal.
-- En los otros casos el parametro real debe ser necesariamente una variable del tipo
-- adecuado. La identidad de dicha variable queda determinada cuando se produce la
-- llamada y no puede ser cambiada dentro del procedimiento.
---------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------
-- ADA_Ej3.adb - Ejemplo simple de pasaje de parametros en ADA
-- Ejemplo del modo por NOMBRE (NAMED)
-- Catedra Lenguajes de Programacion 1
-- UNICEN - Universidad Nacional del Centro de la Prov. de Bs. As.
------------------------------------------------------------------------------
-- OBSERVACIONES:
-- En este ejemplo se usaron los siguientes procedimientos de ADA, los cuales
-- se encuentran en el paquete Text_IO.IO:
-- New_Line Muestra una nueva linea en blanco por pantalla.
-- Put_Line Muestra una cadena de caracteres por pantalla.
-- Instancias de Text_IO.Float_Io:
-- Flt_Io Instancia necesaria para utilizar numeros en
-- punto flotante.
-- Procedimientos que se encuentran en Text_IO.Float_Io:
-- Flt_Io.Put Muestra un numero en punto flotante por pantalla.
------------------------------------------------------------------------------
with Text_IO; use Text_IO;
procedure ADA_Ej3 is
package Flt_Io is new Text_IO.Float_Io (Float);
STATUS: boolean;
D, E: float;
procedure QUADRATIC(A, B, C: in Float; ROOT_1, ROOT_2: out Float; OK: out BOOLEAN) is
D: constant float:= B**2-4.0*A*C;
begin
if D < 0.0 or A = 0.0 then
OK := FALSE;
return;
end if;
ROOT_1 := (-B+(D*D))/(2.0*A);
ROOT_2 := (-B-(D*D))/(2.0*A);
OK := TRUE;
end QUADRATIC;
begin
New_Line;
Put_Line (" --- ADA_Ej3.adb - Ejemplo simple de pasaje de parametros en ADA ---");
Put_line (" --- NAMED PARAMETERS ---");
New_Line;
QUADRATIC(A => 2.0, B => 53.0, C => 2.0, ROOT_1 => D, ROOT_2 => E, OK => STATUS);
New_Line;
if STATUS then
Put_Line ("Las raices son: ");
Flt_Io.Put (D);
Put_Line (" y ");
Flt_Io.Put (E);
end if;
New_Line;
end ADA_EJ3;
------------------------------------------------------------------------------
-- ADA_Ej4.adb - Ejemplo simple de pasaje de parametros en ADA
-- Ejemplo del modo POR DEFECTO (DEFAULT PARAMETERS)
-- Catedra Lenguajes de Programacion 1
-- UNICEN - Universidad Nacional del Centro de la Prov. de Bs. As.
------------------------------------------------------------------------------
-- OBSERVACIONES:
-- En este ejemplo se usaron los siguientes procedimientos de ADA, los cuales
-- se encuentran en el paquete Text_IO:
-- Text_IO.Put_Line Produce una salida por pantalla.
-- New_Line Muestra una nueva linea en blanco por pantalla.
-- Put Muestra una cadena de caracteres por pantalla.
------------------------------------------------------------------------------
With Text_IO; use Text_IO;
procedure ADA_Ej4 is
procedure GENERICS(PARAM_1: STRING:= "Valor_A"; PARAM_2: STRING:= "Valor_C"; PARAM_3: STRING:= "Valor_E") is
begin
Put(" Parametro 1 vale: ");
Text_IO.Put_Line (PARAM_1);
Put(" Parametro 2 vale: ");
Text_IO.Put_Line (PARAM_2);
Put(" Parametro 3 vale: ");
Text_IO.Put_Line (PARAM_3);
New_Line;
end GENERICS;
begin
New_Line;
Put_Line (" --- ADA_Ej4.adb - Ejemplo simple de pasaje de parametros en ADA ---");
Put_line (" --- DEFAULT PARAMETERS ---");
New_Line;
Put_Line (" Con GENERICS(Param_2 => Valor_D) ");
GENERICS(Param_2 => "Valor_D");
Put_Line (" Con GENERICS(Valor_B, Param_3 => Valor_F)");
GENERICS("Valor_B", Param_3 => "Valor_F");
Put_Line (" Con GENERICS( ) ");
GENERICS;
Put_Line (" Con GENERICS(Valor_A, Valor_D)");
GENERICS("Valor_A", "Valor_D");
New_Line;
end ADA_EJ4;
Dado el siguiente programa en ADA, mostrar cuál es la salida para cada una de las invocaciones del procedimiento PASAJE. Analice los resultados.
With Gnat.IO; use Gnat.IO;
procedure ADA_EJ6 is
N : constant integer:=7;
type ARREGLO is array (1 .. N) of INTEGER;
I: INTEGER;
A: ARREGLO;
function RESTA (W: in INTEGER; Y:in INTEGER) return INTEGER is
begin
return (W-Y);
end RESTA;
procedure MENOSUNO (W: in out INTEGER) is
begin
put ("W es:");
put (W);
new_line;
I := RESTA (I,1); -- Decremento el Global I
W := RESTA (W,1); -- Decremento el parámetro A(PAR_1)
end MENOSUNO;
procedure INIC (Z: in out ARREGLO) is
begin
for J in 1 .. N loop
Z (J):=9;
end loop;
end INIC;
procedure MOSTRAR (T: in ARREGLO) is
begin
put ("ARREGLO = ");
for Q in 1..N loop -- Error: loop; sin el ;
put (T(Q));
put (" ");
end loop;
end MOSTRAR;
procedure PASAJE (PAR_1: INTEGER:=7; PAR_2: INTEGER:=1; PAR_3: INTEGER:=4) is
begin
INIC(A); -- Seteo el arreglo con 9
I:= 2; -- Global I = 2
MENOSUNO ( A (PAR_1) ); -- Le paso la posición del arreglo dada en el parámetro.
A(2):= A(2) + PAR_3; -- La pos 2 se le incremente PAR_3
MOSTRAR (A);
end PASAJE;
begin
put_line ("-- PASAJE_1");
PASAJE;
-- Uso los parámetros por defecto (7,1,4)
-- Seteo todos en 9
-- Resto 1 a la pos 7 (9-1=8)
-- Resto 1 a I (2-1=1)
-- A la pos 2 le sumo 4 (9+4=13)
new_line;
new_line;
put_line ("-- PASAJE_2");
PASAJE(PAR_1 => 2); -- Error: ==> en vez de =>
-- Uso los defectos: (2,1,4)
-- Seteo todos en 9
-- Resto 1 a la pos 2 (9-1=8)
-- Resto 1 a I (2-1=1)
-- A la pos 2 le sumo 4 (8+4=12)
new_line;
new_line;
put_line ("-- PASAJE_3");
PASAJE (1,1,1);
-- No uso ningún defecto (1,1,1)
-- Seteo todos en 9
-- Resto 1 a la pos 1 (9-1=8)
-- Resto 1 a I (2-1=1)
-- A la pos 2 le sumo 1 (9+1=10)
end ADA_EJ6;