Saturday, August 11, 2012

AdaTutor - Generic Instantiation

Displaying Integers

with Ada.Text_IO;                               with Ada.Text_IO;
use  Ada.Text_IO;                               use  Ada.Text_IO;
procedure Hello is       THIS          THIS     procedure Add is
begin                 <= IS              IS =>  begin
  Put_Line("Hello!");    RIGHT        WRONG       Put_Line(2 + 2);
end Hello;                                      end Add;
Now let's write a program called Add that computes 2 + 2 and displays the result.  You may think that we could take the Hello program and substitute 2 + 2 for "Hello!", but that won't work.  (We never said Ada is easy!)  Why won't it work?  Because Ada.Text_IO doesn't have a procedure Put_Line that takes an Integer parameter.  One correct program is this:
with Ada.Text_IO; use Ada.Text_IO;
procedure Add is
  package My_Int_IO is new Integer_IO(Integer); use My_Int_IO;
  Put(2 + 2);
end Add;
The package Ada.Text_IO contains procedures for type String.  This package is ready-to-use.  However, inside Ada.Text_IO is another package, Integer_IO, that's not ready-to-use.
 Put_Line for type String  
 Put      for type String  
 Get_Line for type String   
 Get      for type String   
 ______ Integer_IO ______   
 | Put for type <>      |   
 | Get for type <>      |   
 | ...                  |   
It's called a generic package because it has an empty box (<>) in place of the type.  We can make a new, ready-to-use package from Integer_IO by giving the type: package My_Int_IO is new Integer_IO(Integer); we could have used any name in place of My_Int_IO.  Note that we've declared our new package locally inside the procedure Add.  My_Int_IO now has the same procedures and functions as Integer_IO, but with the empty box filled in with the type Integer.

Since Integer_IO (and therefore My_Int_IO) doesn't have a Put_Line, we call My_Int_IO.Put and then Ada.Text_IO.New_Line.  Note that our program says use My_Int_IO; after declaring My_Int_IO.  When the compiler sees the call Put(2 + 2); it writes code to call My_Int_IO.Put rather than Ada.Text_IO.Put, because My_Int_IO.Put takes a parameter of type Integer.  The compiler then finds New_Line in Ada.Text_IO and writes a call to Ada.Text_IO.New_Line.


True or False?  In our example, a program could call Integer_IO.Put.

Generic Instantiation

       package My_Int_IO is new Integer_IO(Integer);

    ______ Integer_IO ______    ______ My_Int_IO _______
    | Put for type <>      |    | Put for type Integer |
    | Get for type <>      |    | Get for type Integer |
    | ...                  |    | ...                  |
    |______________________|    |______________________|

This process of creating an instance of the generic package Integer_IO for the type Integer is called generic instantiation.  Later in this course we'll learn to write our own generic packages, procedures, and functions.  However, we wanted to learn, early in the course, how to instantiate an already written generic package in order to display integers.

But why does Ada make Ada.Text_IO ready-to-use for Strings, while Integer_IO is generic, and has to be instantiated for Integers?  Because programs normally use only one type String, but can have several integer types.  Right now, we know of only one integer type, the standard Integer.  Later we'll learn about user-defined types and derived types, and we'll see how there can be many integer types.  Integer_IO can be instantiated for each of these types.

Ada 95 provides a ready-to-use package Ada.Integer_Text_IO, which is equivalent to the package we obtain by instantiating Ada.Text_IO.Integer_IO for the type Integer.  Thus, with an Ada 95 compiler, the above program wouldn't have to do its own instantiation of Integer_IO; instead, it could have added Ada.Integer_Text_IO to both the with and the use clause.  However not all Ada 83 compilers provide such a package, and those that do use a non-standard name, such as IIO.

There's another generic package within Ada.Text_IO called Float_IO.  Input and output of floating point numbers is done by instantiating Float_IO for the type Float.  As with integers, we'll later learn how there can be several floating point types besides the standard Float; that's why Ada.Text_IO.Float_IO is generic.  (Ada 95 provides us with a ready-to-use package called Ada.Float_Text_IO, equivalent to the package we obtain by instantiating Ada.Text_IO.Float_IO for the type Float.  However, not all Ada 83 compilers provide a similar package, and those that do use a non-standard name like FIO.)

Later in this course, when we cover attributes, we'll learn another way to display Integers (and, in Ada 95, Floats as well), by using the 'Image attribute.

We're now ready for our first Outside Assignment!  Let's compile and run our two sample programs, Hello and Add.  The files HELLO.ADA and ADD.ADA are already supplied for you, and they're written to work with Ada 83 compilers as well as Ada 95.  (That's why they say simply Text_IO instead of Ada.Text_IO.)

< prev   next >

1 comment:

Anonymous said...

Very clear. Thanks