Você está na página 1de 37

AdaA Crash Course

Copyright 2012 by Peter C. Chapin


Table of Contents
Section 1 Tutorial..................................................................................................................... 1
1.1 Introduction...................................................................................................................................1
1.2 Overview of Ada...........................................................................................................................2
1.3 Hello, Ada!....................................................................................................................................2
1.4 Control Structures.........................................................................................................................4
1.5 Subro!ra"s.................................................................................................................................#
1.$ %&es and Subt&es......................................................................................................................'
1.# Arra&s and (ecords.....................................................................................................................14
1.) *ac+a!es......................................................................................................................................1)
1.' Abstract ,ata %&es....................................................................................................................22
1.1- Strin!s.........................................................................................................................................24
1.11 ./cetions...................................................................................................................................24
1.12 ,iscri"inated %&es...................................................................................................................2$
1.13 0enerics......................................................................................................................................2$
1.14 Access %&es and ,&na"ic 1e"or& Allocation.......................................................................2)
1.15 Co""and 2ine Ar!u"ents and 3ile Handlin!...........................................................................31
1.1$ Ob4ect Oriented *ro!ra""in!....................................................................................................31
1.1# %as+in!........................................................................................................................................31
1.1) Container 2ibrar&........................................................................................................................33
1.1' 2ow 2evel *ro!ra""in!............................................................................................................33
Section 2 Case Study: Huffman Encoding............................................................................33
1.2- %5e Al!orit5".............................................................................................................................33
1.21 I"le"entation 6otes.................................................................................................................3$
Section 3 References............................................................................................................... 37
SECTION 1 TUTORIAL
1.1 Introduction
My name is Peter Chapin. Welcome to my tutorial on the Ada programming language! The pur-
pose of this tutorial is to give you an overview of Ada so that you can start writing Ada programs
quicly. This tutorial does not cover the entire language. Ada is very large so complete coverage
of all its features would tae many more pages than are contained in this document. !owever" it
is my hope that after reading this tutorial you will have a good sense of what Ada is lie" appreci -
ate some of its nicer features" and feel interested in learning more. The references section at the
end of this tutorial points you to several good Ada resources that you can use to further your
study of this fine language.
This tutorial assumes you are already familiar with one or more languages in the C family# C" C$
$" %ava" C&" or something similar. 't is not my intention to teach you how to program. ' assume
*a!e 1 of 3#
you already understand the concepts of loops" data types" functions" and so forth. 'nstead this tu-
torial descri(es how to use these things in Ada. 'n cases where Ada provides features that might
(e unfamiliar to you )such as su(types" discriminated types" and tasing* ' will discuss those fea-
tures a (it more comprehensively.
1.2 Oerie! of Ada
Ada is a powerful language designed to address the following issues#
The development of very large programs (y multiple" loosely connected teams. The lan-
guage has features to help manage a large num(er of program components" and to help
ensure those components are used consistently.
The development of long lived programs that spend most of their time in the maintenance
phase of the software life cycle. The language is designed to promote the reada(ility of
programs. +ou may find Ada code to (e rather ver(ose and tedious to write. !owever" that
e,tra wor pays off later (y maing the code clearer and easier to read when (ugs must (e
fi,ed or enhancements written.
The development of ro(ust programs where correctness" security" and relia(ility are priori-
ties. The language has features designed to mae programming safer and less error prone.
-ome of these features involve e,tra run time checing and thus entail a performance
penalty. !owever" Ada.s design is such that the performance penalty is normally not e,-
cessive.
The development of em(edded systems where low level hardware control" multiple concur-
rent tass" and real time requirements are common. The language has features designed
to support these things while still retaining as much safety as feasi(le.
1." #ello$ Ada%
Whenever you (egin to study a new language or software development environment you should
start (y writing the most trivial program possi(le in that language or environment. /oing this will
e,ercise your a(ility to get programs entered into the system and to get them compiled and e,e-
cuted. Thus we will (egin this tutorial with a short (ut complete program that displays the string
0!ello" Ada!1 on the console.
2igure 3 shows the program. 't starts with what is called a context clause. The conte,t clause
specifies the pacages that will (e used in this particular compilation unit. Most of the code in an
Ada program is in pacages. The standard li(rary components are in child packages of the pac-
age Ada. 'n this case we will (e using facilities in the child pacage Ada.Text_IO.
The main program is a procedure named !ello. The precise name used for the main program can
(e anything4 e,actly which procedure is used as the program.s entry point is specified when the
program is compiled. The procedure consists of two parts# the part (etween is and begin is
called the declarative region. Although empty in this simple case" it is here where you would de-
*a!e 2 of 3#
with Ada.Text_IO;
procedure Hello is
begin
Ada.Text_IO.Put_Line(Hello Ada!"#;
end Hello;
Figure 1: A Trivial Ada Program
clare local varia(les and other similar things. The part (etween the begin and the end constitute
the e,ecuta(le statements of the procedure. 'n this case" the only e,ecuta(le statement is a call
to procedure Put_Line in pacage Ada.Text_IO. As you can pro(a(ly guess from its name"
Put_Line prints the given string onto the program.s standard output device. 't also terminates the
output with an appropriate end-of-line indication.
5otice how the name of the procedure is repeated at the end. This is optional" (ut considered
good practice. 'n more comple, e,amples the reada(ility is improved (y maing it clear e,actly
what is ending. 5otice also the semicolon at the very end of the procedure definition. C family lan-
guages do not require a semicolon here so you might accidentally leave it out.
-pelling out the full name Ada.Text_IO.Put_Line is rather tedious. 'f you wish to avoid it you
can include a use statement for the Ada.Text_IO pacage in the conte,t clause. After doing this"
the names in that pacage (ecome directly visible and can (e used without qualification. The con-
te,t clause (ecomes as shown in 2igure 6.
Many Ada programmers do this to avoid having to write long pacage names all the time. !ow-
ever" indiscriminate use of use can mae it difficult to understand your program (ecause it can (e
hard to tell in which pacage a particular name has (een declared.
Ada is a case insensitive language. Thus identifiers such as Hello" hello" and h$lLo all refer to
the same entity. 't is traditional in modern Ada source code to use all lower case letters for re-
served words. 2or all other identifiers" capitali7e the first letter of each word and separate multiple
words with an underscore. The Ada language does not enforce this convention (ut it is a well es-
ta(lished standard in the Ada community so you should follow it.
8efore continuing ' should descri(e how to compile the simple program a(ove. ' will assume you
are using the free 95AT compiler. This is important (ecause 95AT requires specific file naming
conventions that you must follow. These conventions are not part of the Ada language and are not
necessarily used (y other Ada compilers. !owever" 95AT depends on these conventions in order
to locate the files containing the various compilation units of your program.
The procedure Hello should (e stored in a file named hello.adb. 5otice that the name of the file
must (e in lower case letters and must agree with the name of the procedure stored in that file.
The adb e,tension stands for 0Ada (ody.1 This is in contrast with Ada specification files that are
given an e,tension of ads. +ou will see Ada specifications when ' tal a(out pacages later in this
tutorial. ' will descri(e other 95AT file naming requirements at that time.
To compile hello.adb" open a console )or terminal* window and use the gnat%a&e command as
follows
gnat%a&e hello.adb
The gnat%a&e command will compile the given file and lin the resulting o(:ect code into an e,e-
cuta(le producing" in the a(ove e,ample" hello.exe )on Windows*. +ou can compile Ada pro-
grams without gnat%a&e (y running the compiler and liner separately. There are sometimes
good reasons to do that. !owever" for the programs you will write as a (eginning Ada program-
*a!e 3 of 3#
with Ada.Text_IO; use Ada.Text_IO;
procedure Hello is
begin
Put_Line(Hello Ada!"#;
end Hello;
Figure 2: Context Clause Including use
mer" you should get into the ha(it of using gnat%a&e.
5ote that 95AT comes with a graphical Ada programming environment named 9P- )95AT Pro-
gramming -tudio*. 9P- is similar to other modern integrated development environments such as
Microsoft.s ;isual -tudio or <clipse. 2eel free to e,periment with 9P- if you are interested. !ow-
ever" the use of 9P- is outside the scope of this tutorial.
When the compilation has completed successfully you will find that several additional files have
(een created. The files hello.o and hello.exe )on Windows* are the o(:ect file and e,ecuta(le
file respectively. The file hello.ali is the Ada li(rary information file. This file is used (y 95AT to
implement some of the consistency checing required (y the Ada language. 't is a plain te,t file4
feel free to loo at it. !owever" you would normally ignore the ali files. 'f you delete them" they
will simply (e regenerated the ne,t time you compile your program.
Exercises
3. <nter the trivial program in 2igure 3 )or 2igure 6* into your system. Compile and run it.
6. Mae a minor modification to the trivial program that results in an error. Try compiling the
program again. Try several different minor errors. This will give you a feeling for the inds
of error messages 95AT produces.
=. <,periment with the use statement. Try calling Put_Line without specifying its pacage"
(oth with and without the use statement.
1.& Control Structures
Ada contains all the usual control structures you would e,pect in a modern language. The pro-
gram in 2igure = illustrates a few of them" along with several other features. This program accepts
an integer from the user and checs to see if it is a prime num(er.
This procedure declares a local varia(le named 'u%ber of type Integer in its declarative region.
5otice that the type appears after the name (eing declared )the opposite of C family languages*"
separated from that name with a colon.
*a!e 4 of 3#
Procedure (et from pacage Ada.Integer_Text_IO is used to read an integer from the console. 'f
the value entered is less than two an error message is displayed. 5otice that there are two differ-
ent Put procedures (eing used# one that outputs a string and another that outputs an integer.
>ie C$$ and some other modern languages" Ada allows procedure names to (e overloaded dis-
tinguishing one procedure from another (ased on the parameters. )'n this case the two different
Put procedures are also in different pacages.*
'f the value entered is two or more" the program uses a )or loop to see if any value less than the
given num(er divides into it evenly )produces a 7ero remainder after division*. Ada )or loops scan
over the given range assigning each value in that range to the inde, varia(le )named I in this
case* one at a time. 5otice that it is not necessary to e,plicitly declare the inde, varia(le. The
compiler deduces its type (ased on the type used to define the loop.s range. 't is also important
to understand that if the start of the range is greater than the end of the range" the result is an
empty range. 2or e,ample" the range * .. + contains no mem(ers and a loop using that range
won.t e,ecute at all. 't does not e,ecute starting at two and counting down to one. +ou need to
use the word re,erse to get that effect#
)or I in re,erse + .. * loop
5otice also that i) statements require the word then and that each end is decorated (y the name
of the control structure that is ending. 2inally notice that a single equal sign is used to test for
equality. There is no -- operator in Ada.
2igure ? shows a program that counts the vowels in the te,t at its standard input. +ou can feed
this program te,t using '@A redirection.
This program illustrates while loops and case structures )similar to C.s switch statement*. There
are quite a few things to point out a(out this program. >et.s loo at them in turn.
*a!e 5 of 3#
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure Pri%e is
'u%ber . Integer;
begin
Put(/$nter an integer. /#;
(et('u%ber#;
i) 'u%ber 0 * then
Put(/The ,alue /#; Put('u%ber 1#; Put_Line(/ is bad./#;
else
Put(/The ,alue /#; Put('u%ber 1#;
)or I in * .. ('u%ber 2 +# loop
i) 'u%ber %od I - 1 then
Put_Line(/ is not pri%e./#;
return;
end i);
end loop;
Put_Line(/ is pri%e./#;
end i);
end Pri%e;
Figure 3: A Prime Number Checker
3. ;aria(les can (e initiali7ed when they are declared. The .- operator is used to give a vari-
a(le its initial value )and also to assign a new value to a varia(le*. Thus lie C family lan-
guages" Ada distinguishes (etween test for equality )using -* and initiali7ation@assignment
)using .-*. Bnlie C family languages you.ll never get them mi,ed up (ecause the compiler
will catch all incorrect usage as an error.
6. 'n this program the condition in the while loop involves calling the function $nd_O)_3ile in
pacage Ada.Text_IO. This function returns True if the standard input device is in an end-
of-file state. 5otice that Ada does not require )or even allow* you to use an empty parame-
ter list on functions that tae no parameters. This means that function $nd_O)_3ile loos
lie a varia(le when it is used. This is considered a feature4 it means that read-only vari -
a(les can (e replaced (y parameterless functions without requiring any modification of the
source code that uses that varia(le.
=. The sample program uses the logical operator not. There are also operators and and or
that can (e used in the e,pected way.
?. The case statement (ranches to the appropriate when clause depending on the value in the
varia(le Letter. The two when clauses in this program show several alternatives separated
(y vertical (ars. 'f any of the alternatives match" that clause is e,ecuted. +ou can also
specify ranges in a when clause# when + .. +1 -4 etc.
C. Ada has what are called 0full coverage rules.1 'n a case statement you must account for
every possi(le value that might occur. Providing when clauses for :ust the vowels would (e
an error since you would not have fully covered all possi(le characters. 'n this program '
want to ignore the other characters. To do this" ' provide a when others clause that e,e-
cutes the null statement. This lets future readers of my program now that ' am intention-
ally ignoring the other characters.
*a!e $ of 3#
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure 5owels is
Letter . 6haracter;
5owel_6ount . Integer .- 1;
begin
while not $nd_O)_3ile loop
(et(Letter#;
case Letter is
when 7A787$787I787O78797 -4
5owel_6ount .- 5owel_6ount : +;
when 7a787e787i787o787u7 -4
5owel_6ount .- 5owel_6ount : +;
when others -4
null;
end case;
end loop;
Put(/Total nu%ber o) ,owels - /#; Put(5owel_6ount#;
end 5owels;
Figure : !o"el Counting Program
Exercises
3. The prime num(er checing program in 2igure = is not very efficient. 't can (e improved
(y taing advantage of the following o(servation# 'f 'u%ber is not divisi(le (y any value
less than I" then it can.t (e divisi(le (y any value greater than 'u%ber;I. Thus the upper
(ound of the loop can (e reduced as I increases. Modify the program to use this o(serva-
tion to improve its performance. 5ote# +ou will have to change the )or loop to a while
loop )try using a )or loop first and see what happens*.
6. Modify the prime num(er checing program so that it loops repeatedly accepting num(ers
from the user until the user types -3. +ou can program an infinite loop in Ada as shown in
2igure C. !ave your program print out different error messages for negative num(ers
)other than -3* than for the values 7ero and one. Bse an i) ... elsi) chain )note the spell-
ing of elsi)*. Write a version that uses a case statement instead of an i) ... elsi) chain.
+ou can use Integer73irst in a range definition to represent the first )smallest* 'nteger
value the compiler can represent.
1.' Sub(ro)ra*s
Bnlie C family languages" Ada distinguishes (etween procedures and functions. -pecifically" func-
tions must return a value and must (e called as part of a larger e,pression. Procedures never re-
turn a value )in the sense that functions do* and must (e called in their own statements. Collec-
tively procedures and functions are called subprograms in situations where their differences don.t
matter.
-u(programs can (e defined in any declarative region. Thus it is permissi(le to nest su(program
definitions inside each other. A nested su(program has access to the parameters and local vari-
a(les in the enclosing su(program that are defined a(ove the nested su(program. The scope rules
are largely what you would e,pect. 2igure D shows a variation of the prime num(er checing pro-
gram that introduces a nested function Is_Pri%e that returns True if its argument is a prime
num(er.
'n this case Is_Pri%e has (een declared to tae a parameter ' of type Integer. 't could have
also accessed the local varia(le 'u%ber directly. !owever" it is usually (etter style to pass param-
eters to su(programs in cases where it maes sense. ' also wanted to illustrate the synta, for pa-
rameter declarations. 5ote that (ecause Is_Pri%e is a function a return type must (e specified
and it must (e called in the conte,t of an e,pression )in 2igure D" it is called in the condition of an
i) statement*. Procedure declarations are similar e,cept that no return type is mentioned. Also
when a procedure is called it must not (e part of an e,pression" (ut rather stand (y itself as a sin-
gle statement. -ee the calls to procedures Put and Put_Line in the e,amples so far.
*a!e # of 3#
loop
...
exit when condition;
...
end loop;
Figure #: An In$inite %oo& 'ith an (&tional )xit Condition
The program a(ove also shows the form of a comment. Ada comments start with 22 and run to
the end of the line. As you now" it is good to include comments in your program. !owever" the
e,amples in this tutorial do not include many comments in order to save space )and (ecause the
programs are e,plained in the te,t anyway*.
Procedures also differ from functions in that they support several parameter 0modes.1 2igure E
shows the definition of a procedure that illustrates this. 5otice that a semi-colon is used to sepa-
rate parameter declarations and not a comma as is done in C family languages.
The first parameter declared in 2igure E has mode in. Parameters with this mode are initiali7ed
with the argument provided (y the caller" (ut treated as constants inside the procedure. They can
(e read" (ut not modified. The second parameter has mode out. Parameters with this mode are in
an uninitiali7ed state when the procedure (egins" (ut they can (e used otherwise as ordinary vari -
a(les inside the procedure. Whatever value is assigned to an out parameter (y the time the pro-
cedure ends is sent (ac to the calling environment. The third parameter has mode in out. Pa-
rameters with this mode are initiali7ed with the argument provided (y the caller" and can also (e
modified inside the procedure. The changed value is then returned to the caller to replace the
original value. Feep in mind that" unlie in C" modifications to parameters in Ada )when allowed
(y the parameter mode* affect the arguments used when the procedure is called.
*a!e ) of 3#
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure Pri%e* is
'u%ber . Integer;
22 This )unction returns True i) ' is pri%e; 3alse otherwise.
)unction Is_Pri%e(' . Integer# return <oolean is
begin
)or I in * .. (' = +# loop
i) ' %od I - 1 then
return 3alse;
end i);
end loop;
return True;
end Is_Pri%e;
begin
Put(/$nter an integer. /#;
(et('u%ber#;
i) 'u%ber 0 * then
Put(/The ,alue /#; Put('u%ber 1#; Put_Line(/ is bad./#;
else
Put(/The ,alue /#; Put('u%ber 1#;
i) Is_Pri%e('u%ber# then
Put_Line(/ is pri%e./#;
else
Put_Line(/ is not pri%e./#;
end i);
end i);
end Pri%e*;
Figure *: Prime Number Checker 'ith a Nested Function
The mode in is the default. 2unctions parameters can only have mode in and thus it is common
to leave the mode specification off when defining function parameters
3
. My recommendation" how-
ever" is to always specify the mode when declaring procedure parameters.
>ie C$$" Ada also allows you to define default values for su(program parameters. This is accom-
plished (y initiali7ing the parameter )using the .- operator* when the parameter is declared. 'f no
argument is provided for that parameter when the su(program is called the default value is used
instead.
Ada also allows you to call su(programs using named parameter associations. This method allows
you to associate arguments with the parameters in any order" and it can also greatly improve the
reada(ility of your codeparticularly if you.ve chosen good names for the parameters. 2igure G
shows how the procedure defined in 2igure E might (e called. Assume that the varia(les Accu%u2
lator" '" and Output have (een previously declared as integers.
5otice that the order in which the arguments are provided is not the same as the order in which
the parameters are declared. When named association is used" the order is no longer significant.
5otice also that you can use any e,pression as the argument associated with an in parameter.
!owever" out and in out parameters must (e associated with varia(les and not ar(itrary e,pres-
sions )since putting a value into the result of an e,pression doesn.t really mae sense*.
Exercises
3. Write a procedure 6ount_Pri%es that accepts a range of integers and returns the num(er
of primes" the smallest prime" and the largest prime in that range. +our implementation
should use out parameters to return its results. 't should also mae use of the Is_Pri%e
function defined in 2igure D. Wrap your procedure in a main program that accepts input
values from the user and outputs the results. Bse named parameter association when call -
ing 6ount_Pri%es.
6. 'mplement 6ount_Pri%es from the previous question as a function )or a collection of func-
tions* instead. What are the advantages and disadvantages of each approachH
1.+ T,(es and Subt,(es
'n the e,amples so far you have seen the Ada types 'nteger" Character" and 8oolean. Ada also
has a type 2loat for storing floating point values and a type -tring" which is an array of charac-
ters. Ane important characteristic of Ada that sets it apart from many languages is its strong typ-
1 In t5e uco"in! Ada 2-12 standard t5is li"itation on function ara"eter "odes 5as been re"oved.
*a!e ' of 3#
procedure >ode_$xa%ple
(? . in Integer; @ . out Integer; A . in out Integer# is
begin
? .- +; 22 $rror. 6an7t %odi)B an in para%eter.
@ .- ?; 22 O&aB. 6an read ? and %odi)B @.
A .- A : +; 22 O&aB. 6an read and write an in out para%eter.
end >ode_$xa%ple;
Figure +: Procedure ,e$inition Illustrating Parameter -odes
>ode_$xa%ple(A -4 Accu%ulator ? -4 ':+C @ -4 Output#;
Figure .: Calling Procedure )xam&le "ith Named Association
ing. There is no precise definition of this term" (ut for our purposes we will say that a strongly
typed language is one which does no )or very few* automatic type conversions. Bnlie C" Ada will
not convert integers to floating point values or visa-versa without e,plicit instruction from the pro-
grammer. 2igure I illustrates this.
'f you are not used to strong typing you may find it e,cessively pedantic and annoying. !owever"
it e,ists for a reason. <,perience has shown that many (ugs first manifest themselves as confu-
sion a(out types. 'f you find yourself mi,ing types in your program" it may mean that you have a
logical error. /oes it mae sense to put a value representing velocity into a varia(le that holds a
passenger countH -trong typing can catch errors lie this and thus it promotes software relia(ility.
'n fact" Ada allows you to define your own scalar types. 8y creating a new type for each logically
distinct set of values in your program" you ena(le the compiler to find logical errors that it might
otherwise miss. 2or e,ample" consider a procedure Put_6har that prints a single character onto
the terminal at a given row and column location. 'nstead of declaring the row and column param-
eters as integers" you might introduce two distinct types for those concepts. 2igure 3J shows how
it could loo.
-uppose the main program declared D as type Dow_TBpe and 6 as type 6olu%n_TBpe. 5ow a call
such as Put_6har(6 D 7x7# would (e detected (y the compiler as an error (ecause the types
used for the first two arguments don.t match the types declared for those parameters. Acciden-
tally switching the row and column arguments in a call lie this is an easy error to mae. Ada.s
strong typing" together with the use of appropriate user defined types" allows the compiler to
catch this error rather than waiting until testing to )may(e* find it.
-trong typing can also find errors in ordinary e,pressions. 2or e,ample" consider the assignment
statement D .- *E6 : +. The e,pression on the right hand side has type 6olu%n_TBpe (ut the
*a!e 1- of 3#
procedure Ftrong_TBping_$xa%ple is
I . Integer;
3 . 3loat;
begin
I .- +; 22 O&aB.
I .- +.1; 22 $rror. 6an7t assign a 3loat to an Integer.
3 .- +; 22 $rror. 6an7t assign an Integer to a 3loat.
3 .- +.1; 22 O&aB.
3 .- I; 22 $rror.
I .- 3; 22 $rror.
3 .- 3loat(I#; 22 O&aB. $xplicit con,ersion.
I .- Integer(3#; 22 O&aB. $xplicit con,ersion.
end Ftrong_TBping_$xa%ple;
Figure /: ,emonstration o$ 0trong T1&ing
tBpe Dow_TBpe is range + .. *C;
tBpe 6olu%n_TBpe is range + .. G1;
procedure Put_6har
(Dow . Dow_TBpe; 6ol . 6olu%n_TBpe; Letter . 6haracter# is
begin
22 etc
end Put_6har;
Figure 12: 3sing 0trong T1&ing to )nhance )rror Checking
varia(le on the left hand side has type Dow_TBpe. 't pro(a(ly doesn.t mae sense to (e assigning
a column value to a row varia(le and Ada will flag this statement as an error. 'f it is really your in-
tention to use this computed column value for a row num(er" you need to include an e,plicit con-
version. The result is D .- Dow_TBpe(*E6 : +#.
+ou might (e wondering what happens in the a(ove e,ample if the result of *E6 : + is a value
outside the allowed range specified for type Dow_TBpe. 't is important to understand that Ada
never allows a value to (e assigned to a varia(le that is outside the set of values for that vari -
a(le.s type. 'n this case a run time error would occur )an e,ception would (e raised*.
/efining your own types also helps you write porta(le programs. The only integer type compilers
must support is Integer. The num(er of (its used (y type Integer is implementation defined and
varies from compiler to compiler. Most compilers support additional" non-standard integer types
such as Long_Integer and Long_Long_Integer. !owever" the names of these additional types"
and even their e,istence" varies from compiler to compiler. Kather than deal with this comple,ity
directly you can :ust specify the range of values you desire and the compiler will select the most
appropriate underlying type. 2or e,ample
tBpe <loc&_6ounter_TBpe is range 1 .. +_111_111_111;
;aria(les of type <loc&_6ounter_TBpe may (e represented as Integer or Long_Integer or some
other type as appropriate. !owever" in any case they will (e constrained to only hold values (e-
tween 7ero and one (illion inclusive. 'f the compiler does not have a (uilt-in integer type with a
large enough range it will produce an error message. 'f the compiler accepts your type definition
you will not get any surprises. 5otice also how Ada allows you to em(ed underscores in large
num(ers to improve their reada(ility.
Ada also allows you to define modular types. These types are unsigned and have 0wrap-around1
semantics. 'ncrementing (eyond the end of an ordinary type causes an e,ception" (ut increment-
ing (eyond the end of a modular type wraps around to 7ero. 'n addition the operators not" and"
or" and xor can (e used on modular types to do (itwise manipulation. 2igure 33 demonstrates.
!ere a modular type O))set_TBpe is introduced to hold 36 (it offsets. The varia(le O))set is
mased so that only the lower 3J (its are retained. The snippet in 2igure 33 also demonstrates
Ada.s e,ponentiation operator and how num(ers in (ases other than 3J can (e written. 8ecause
Ada was designed for use in em(edded systems" its support for low level (it manipulation is good.
Enumeration Types
'n many cases you want to define a type that has only a small num(er of allowed values and you
want to name those values a(stractly. 2or e,ample" the definition
tBpe HaB_TBpe is (Fun >on Tue Ied Thu 3ri Fat#;
introduces HaB_TBpe as an enumeration type. ;aria(les of type HaB_TBpe can only tae on the
values listed in the type definition. These values are called enumerators. This is useful for writing
your program in a(stract terms that are easy to understand. 8ecause the compiler treats enumer-
ation types as distinct from integer types )and from each other* you will not (e allowed to mi, un-
*a!e 11 of 3#
tBpe O))set_TBpe is %od *EE+*;
...
O))set . O))set_TBpe;
...
O))set .- O))set and +JKL33K;
Figure 11: ,emonstration o$ -odular T1&es
related concepts without compile time errors.
Discrete Types
The integer types and enumeration types are discrete types (ecause they each represent only a
finite set of )ordered* values. All discrete types share some common properties and it is enlight-
ening to descri(e those properties in a uniform way.
Ada maes e,tensive use of attributes. +ou reference an attri(ute of a type using an apostrophe
)or 0tic1* immediately following the type name. 2or e,ample" HaB_TBpe73irst represents the
first value in the HaB_TBpe enumeration and Integer73irst represents the first )smallest* al-
lowed value of Integer. There is also a Last attri(ute to access the last allowed value. -ome at-
tri(utes (ehave lie functions. 2or e,ample HaB_TBpe7Fucc(Fun# returns >on" the successor of
Fun in the HaB_TBpe enumeration. There is also a Pred attri(ute for finding the predecessor value.
'n addition there is a Pos attri(ute that returns the integer position of a particular enumerator and
a 5al attri(ute that does the reverse. 2or e,ample HaB_TBpe7Pos(>on# is one )the position values
start at 7ero* and HaB_TBpe75al(+# is >on. We will see other attri(utes later in this tutorial.
Kanges of discrete types can (e defined in a uniform way and used" for e,ample" as cases in case
statements and ranges of for loops. 2igure 36" shows a contrived e,ample.
5otice that despite Ada.s full coverage rules it is not necessary to specify a case for Fat. This is
(ecause the compiler can see HaB is limited to Fun .. 3ri and thus will never tae on the value
Fat. Kecall that the loop inde, varia(le of a for loop can not (e modified inside the loop so there is
no possi(ility of the programmer setting HaB to Fat (efore the case statement is reached.
Subtypes
When a new type is defined using tBpe" the compiler regards it as distinct from all other types.
This is strong typing. !owever" sometimes it is (etter to define a constraint on an e,isting type
rather than introduce an entirely new type. There are several different inds of constraints one
might define depending on the type (eing constrained. 'n this section ' will tal a(out range con-
straints on discrete types. As an e,ample" the definition
subtBpe Iee&daB is HaB_TBpe range >on .. 3ri;
introduces a subtype named Iee&daB that only contains the values >on through 3ri. 't is impor-
tant to understand that a su(type is not a new type" (ut :ust a name for a constrained version of
the parent type. The compiler allows varia(les of a su(type to (e mi,ed freely with varia(les of
the parent type. Kun-time checs are added if necessary to verify that no value is ever stored in a
varia(le with a su(type that is outside the range of the su(type. 'f an attempt is made to do so"
the 6onstraint_$rror e,ception is raised. 2igure 3= shows an e,ample
*a!e 12 of 3#
)or HaB in Fun .. 3ri loop
case HaB in
when Fun -4 etc...
when >on 8 Tue -4 etc...
when Ied .. 3ri -4 etc...
end case;
end loop;
Figure 12: ,emonstration o$ ,iscrete 4anges
'n this e,ample a su(type Inter,al is defined in the procedure.s declarative region. The varia(le
? of type Inter,al is given Inter,al.s first value. Mi,ing Inter,al and HaB_TBpe varia(les in the
later assignment statements is allowed (ecause they are really (oth of the same type. 8ecause
Inter,al is a su(type of HaB_TBpe the assignment of ? to HaB must succeed. Thus the compiler
does not need to include any run time checs on the value of ?. !owever" the value of HaB might
(e outside the allowed range of the su(type and so the compiler will need to insert a run time
chec on HaB.s value (efore assigning it to ?. 'f that chec fails" the 6onstraint_$rror e,ception
is raised. Bnder no circumstances can an out of (ounds value (e stored in a varia(le. ' should
point out that in this particular )simplistic* e,ample the compiler.s optimi7er may (e a(le to see
that the value in HaB will (e in (ounds of the su(type since in the assignment :ust (efore it was
given a value from the su(type. 'n that case the compiler is allowed and encouraged to optimi7e
away the run time chec that would normally (e required.
This e,ample also illustrates another important aspect of su(types# they can (e dynamically de-
fined. 5otice that the range on the su(type is taen from the procedure.s parameters. <ach time
the procedure is called that range might (e different. 'n contrast the range specified on full type
definitions must (e static )nown to the compiler*.
A range such as +..+1 is really an a((reviation for the specification of a su(type Integer range
+..+1. Thus a for loop header such as )or I in +..+1 is really :ust an a((reviation for the more
specific )or I in Integer range +..+1. 'n general the for loop specifies a su(type over which
the loop inde, varia(le ranges. This is why in 2igure 36 it was not necessary to provide a case for
Fat. The loop inde, varia(le HaB implicitly declared in the loop header has the su(type HaB_TBpe
range Fun..3ri. The case statement contains alternatives for all possi(le values in that su(type
so the full coverage rules are satisfied.
The Ada environment predefines two important and useful su(types of Integer. Although you
never have to e,plicitly define these types yourself" the compiler (ehaves as if the following two
su(type definitions were always directly visi(le.
subtBpe 'atural is Integer range 1 .. Integer7Last;
subtBpe Positi,e is Integer range + .. Integer7Last;
The su(type 'atural is often useful for counters of various inds. -ince counts can.t (e negative
the run time checing on 'atural.s range constraint can help you find program errors. The su(-
type Positi,e is useful for cases where 7ero is a nonsensical value that should never arise.
Never Use Integer
'n Ada you should avoid using the type Integer )or 3loat* directly in your program. 'nstead it is
(etter practice to introduce your own types or su(types to name the scalar types you need. 'n ad-
*a!e 13 of 3#
procedure He%onstrate_FubtBpes
(Lower 9pper . in HaB_TBpe; HaB . in out HaB_TBpe# is
subtBpe Inter,al is HaB_TBpe range Lower .. 9pper;
? . Inter,al .- Inter,al73irst;
begin
HaB .- ?; 22 'o run ti%e chec&. Iill de)initelB succeed.
? .- HaB; 22 Dun ti%e chec&. HaB %ight be out o) range.
$nd He%onstrate_FubtBpes;
Figure 13: 0ubt1&e ,emonstration
dition to documenting your program (etter" this practice allows the compiler or" in the case of
su(types the runtime system" to catch many logical errors in your code. Ada is designed to help
you write relia(le programs" and its strong typing is a ma:or feature in that regard. !owever" if
you simply declare all your numeric scalar varia(les as Integer uniformly you are largely negat-
ing any (enefits strong typing might provide.
'n this tutorial Integer is used frequently in the e,amples. This is largely (ecause the e,amples
are isolated snippets of code that are not really part of a larger program. <,amples also often use
short and meaningless varia(le names for the same reason. 'n real programs you should use good
varia(le names and" in Ada" well considered type definitions that em(ody as many aspects of your
program.s design as possi(le.
Exercises
3. Bsing the definition of HaB_TBpe presented earlier would you guess that the following
wors or produces a compiler error# )or HaB in HaB_TBpe loop ... H Write a short pro-
gram to see how the compiler (ehaves when presented with a loop lie this.
6. Ane of the e,amples a(ove introduced separate Dow_TBpe and a 6olu%n_TBpe definitions.
What disadvantage is there to eeping these concepts distinctH Would it (e (etter to use a
single Fcreen_6oordinate_TBpe for (oth row and column coordinates insteadH
1.- Arra,s and Records
Bnlie C family languages" arrays in Ada are first class o(:ects. This means you can assign one ar-
ray to another" pass arrays into su(programs and return arrays from functions. <very array has a
type" however" this type does not need to (e named. 2or e,ample
Ior&space . arraB(+ .. +1*M# o) 6haracter;
defines Ior&space to (e an array of characters inde,ed using the integers 3 through 3J6?. 5ote
that although Ior&space has an array type" the name of that type is not specified.
'n fact" you can define arrays using any discrete su(type for the inde, )recall that +..+1*M is re-
ally an a((reviation for an integer su(type specification*. 't is not possi(le to access an array out
of (ounds for e,actly the same reason it.s not possi(le to store an out of (ounds value into a vari -
a(le. The compiler raises the 6onstraint_$rror e,ception in precisely the same way.
2igure 3? shows an e,ample illustrating many important features.
3. Arrays are accessed using parenthesis and not square (racets as in C family languages.
Thus array access has a synta, similar to that of a function call. An array of constant val-
ues and can (e replaced with a function later without clients needing to (e edited.
*a!e 14 of 3#
6. Any discrete su(type" including enumeration su(types" can (e used for an array inde,. 'n
2igure 3? the array Ior&_Hours has elements Ior&_Hours(Fun# and so forth.
=. The nested function AdNust_O,erti%e uses a type defined in the enclosing procedure. This
is perfectly accepta(le. The visi(ility of all names is handled uniformly.
?. 't is possi(le to use array aggregates in e,pressions where an array is e,pected.
Ior&_Hours is assigned a value that specifies every element of the array in one step. The
compiler deduces the type of the aggregate from its conte,t.
C. 5otice that the same su(type is used for (oth the loop inde, varia(le and the array inde,.
This is a common situation and it means the compiler can optimi7e out the run time checs
normally required when accessing an array element. -ince the value of HaB can.t possi(ly
(e outside the range of allowed array inde,es" there is no need to chec that
Ior&_Hours(HaB# is in (ounds.
'n some cases it is appropriate to give a name to a particular array type. This is desira(le if you
plan on declaring many arrays that are intended to have the same type. When the type definition
is in only one place" updating it later is easier. Also you can.t assign one array to another unless
they have the same type and in that case the type has to (e named. 2igure 3C illustrates.
8ecause su(types are defined dynamically the si7e and (ounds of an array can also (e defined dy-
namically. 2or e,ample a declaration such as A . arraB(+..'# o) 'atural is allowed even if the
value of ' is not nown at compile time )for e,ample" it could (e a su(program parameter*. This
*a!e 15 of 3#
procedure $xa%ple is
tBpe HaB_TBpe is (Fun >on Tue Ied Thu 3ri Fat#;
Ior&_Hours . arraB(HaB_TBpe# o) 'atural;
)unction AdNust_O,erti%e
(HaB . HaB_TBpe; Hours . 'atural# return 'atural is
begin
22 'ot shown.
end AdNust_O,erti%e;
begin
Ior&_Hours .- (1 G G G G 1#;
)or HaB in HaB_TBpe loop
Ior&_Hours(HaB# .- AdNust_O,erti%e(HaB Ior&_Hours(HaB##;
end loop;
end $xa%ple;
Figure 1: Arra1 )xam&le
procedure $xa%ple is
tBpe <u))er_TBpe is arraB(1..+1*L# o) 6haracter;
<+ . <u))er_TBpe;
<* . <u))er_TBpe;
<L . arraB(1..+1*L# o) 6haracter;
begin
<+ .- <*; 22 3ine. $ntire arraB assigned.
<+ .- <L; 22 $rror. TBpes don7t %atch. <L has anonB%ous tBpe.
end $xa%ple;
Figure 1#: Named vs Anon1mous Arra1 T1&es
feature means that many places where dynamic allocation is necessary in" for e,ample" C$$ can
(e handled in Ada without the use of e,plicit memory allocators.
Unconstrained Array Types
Ane pro(lem with the standard definition of Pascal
6
is that it is not possi(le to write a procedure
that taes an array of unnown si7e. At first glance it appears that Ada would also have that pro(-
lem. Arrays of different si7es have different types and strong typing will prevent them from (eing
mi,ed. This would (e a serious limitation. To get around this pro(lem Ada has the concept of un-
constrained array types. -uch a type does not specify the (ounds on the array" allowing arrays
with different (ounds to (e in the same type. !owever" the (ounds must (e specified when an ac-
tual array o(:ect is declared so the compiler nows how much memory to allocate for the o(:ect.
2igure 3D shows an e,ample.
Again there are several points to mae a(out this e,ample.
3. The sym(ol 04 )pronounced 0(o,1* is intended to (e a placeholder for information that will
(e filled in later. 'n this case it specifies that the inde, (ounds on the array type
<u))er_TBpe is unconstrained.
6. 't is illegal to declare a varia(le with an unconstrained type without providing constraints.
This is why the declaration of <+ is an error. !owever" the missing array (ounds are speci-
fied in the other declarations. 5otice that it is not necessary for array (ounds to start at
7ero or one. Any particular value is fine as long as it is part of the inde, type mentioned in
2 Standard *ascal is not usable for serious ro!ra""in!. Co""ercial *ascal co"ilers rovide e/tensions to address t5e
s5ortco"in!s in t5e standard version of t5e lan!ua!e.
*a!e 1$ of 3#
procedure 9nconstrained_ArraB_$xa%ple is
tBpe <u))er_TBpe is arraB(Integer range 04# o) 6haracter;
<+ . <u))er_TBpe; 22 $rror. >ust speci)B arraB bounds.
<* . <u))er_TBpe( 1..+C#; 22 O&aB.
<L . <u))er_TBpe( 1..+C#;
<M . <u))er_TBpe(+J..L+#; 22 3ine.
<C . <u))er_TBpe( 1..JL#; 22 'o proble%.
procedure Process_<u))er(<u))er . in <u))er_TBpe# is
begin
)or I in <u))er7Dange loop
22 Ho so%ething with <u))er(I#
end loop;
end Process_<u))er;
begin
<* .- <L; 22 3ine. TBpes %atch and bounds co%patible.
<* .- <M; 22 3ine! TBpes %atch and lengths identical.
<* .- <C; 22 6onstraint_$rror. Lengths don7t %atch.
Process_<u))er(<*#; 22 3ine.
Process_<u))er(<M#; 22 3ine.
Process_<u))er(<C#; 22 3ine.
end 9nconstrained_ArraB_$xa%ple;
Figure 1*: 3nconstrained Arra1 T1&es
the array declaration.
=. 't is fine to declare a su(program" such as Process_<u))er" taing an unconstrained array
type as an parameter. !owever" such a su(program can.t safely access the elements of the
given array using specific inde, values lie 3 or 6 (ecause those values might not (e legal
for the array. 'nstead one needs to use special array attri(utes. 2or e,ample" <u)2
)er73irst is the first inde, value that is valid for array <u))er" and similarly for <u)2
)er7Last. The attri(ute Dange is shorthand for <u))er73irst..<u))er7Last and is quite
useful in for loops as the e,ample illustrates.
?. +ou might find it surprising that the assignment <* .- <M is legal since the array (ounds
do not match. !owever" the two arrays have the same length so corresponding elements
of the arrays are assigned. This is called sliding semantics )(ecause you can imagine slid-
ing one array over until the (ounds do match*.
C. All the calls to Process_<u))er are fine. 'nside the procedure <u))er7Dange adapts itself
to whatever array it is given and" provided the code is written with this in mind" the proce-
dure wors for arrays of any si7e.
Records
'n C family languages composite o(:ects containing components with different types are called
structures. 'n Ada )and many other languages* they are called records. All record types must
have a name and thus must (e declared (efore any o(:ects of that type can (e created. 2igure 3E
shows an e,ample.
This procedure defines a type Hate as a collection of three named components. 5otice that the
HaB and >onth components are defined as su(types of Integer without the (other of naming the
su(types involved )anonymous su(types are used*. TodaB is declared to (e a Hate and initiali7ed
with a record aggregate. 'n this case named association is used to mae it clear which component
gets which initial value" however positional association is also legal.
Kecords can (e assigned as entire units and their components accessed using the dot operator.
5otice that if To%orrow.HaB : + creates a value that is outside the range +..L+" a
6onstraint_$rror e,ception will (e raised" as usual when that out of (ounds value is assigned to
To%orrow.HaB. A(viously a more sophisticated procedure would chec for this and ad:ust the
month as necessary )as well as deal with the fact that not all months are =3 days long*.
*a!e 1# of 3#
procedure $xa%ple is
tBpe Hate is
record
HaB . Integer range + .. L+;
>onth . Integer range + .. +*;
@ear . 'atural;
end record;
TodaB . Hate .- (HaB -4 + >onth -4 O @ear -4 *11O#;
To%orrow . Hate;
begin
To%orrow .- TodaB;
To%orrow.HaB .- To%orrow.HaB : +;
end $xa%ple;
Figure 1+: 4ecord T1&es
1.. /ac0a)es
A pacage is a named container into which you can place su(programs" type definitions" and other
entities that are related to each other. Pacages can even contain other pacages. 'n Ada pac-
ages are the primary way to organi7e and manage the various parts of a program.
Pacages have two parts# a specification that declares the entities that are visi(le to the rest of
the program" and a body that contains the implementation of those entities. The (ody can also
contain private entities that can only (e used inside the pacage. 'n most cases the specification
is stored in a separate file from the (ody and can even (e compiled separately. This maes the
separation (etween a pacage.s interface and implementation more rigorous in Ada than in many
languages" encouraging the programmer to separate the process of software design from con-
struction. This formal separation maes it easier for different groups of people to wor on the de-
sign and construction of a program since those groups would (e woring with different sets of
source files. At least this is the ideal situation. Alas" pacage specifications can have a private sec-
tion" discussed later" that is technically part of the pacage.s implementation. Thus" in some cases
at least" interface and implementation end up in the same file after all.
As an e,ample" consider a simple pacage for displaying te,t on a character mode terminal. 2ig-
ure 3G shows what the specification might loo lie. When using the 95AT compiler" pacage
specifications are stored in files with a .ads e,tension using the same (ase name as the name of
the pacage. 'n this case" the file would (e screen.ads.
There is no e,ecuta(le code in the specification4 it only contains declarations. The e,ample shows
a few types (eing declared and then some procedures that mae use of those types. Pacages can
also contain functions.
Ance the specification has (een written code that maes use of the pacage can (e compiled.
-uch a compilation unit contains a statement such as 0with Fcreen1 in its conte,t clause. 't can
then" for e,ample" refer to the type Fcreen.Dow_TBpe and call procedure Fcreen.Print as you
might e,pect. 5ote that a pacage specification can contain a conte,t clause of its own if it needs"
for e,ample" types defined in some other pacage.
The pacage (ody" stored in a .adb file" contains the implementation of the various su(programs
*a!e 1) of 3#
pac&age Fcreen is
tBpe Dow_TBpe is range +..*C;
tBpe 6olu%n_TBpe is range +..G1;
tBpe 6olor_TBpe is (<lac& Ded (reen <lue Ihite#;
procedure Fet_6ursor_Position
(Dow . in Dow_TBpe; 6olu%n . in 6olu%n_TBpe#;
procedure (et_6ursor_Position
(Dow . out Dow_TBpe; 6olu%n . out 6olu%n_TBpe#;
procedure Fet_Text_6olor(6olor . in 6olor_TBpe#;
procedure (et_Text_6olor(6olor . out 6olor_TBpe#;
procedure Print(Text . Ftring#;
end Fcreen;
Figure 1.: )xam&le Package 0&eci$ication
declared in the specification. The Ada compiler checs for consistency (etween the specification
and the (ody. +ou must implement all su(programs declared in the specification and you must
even use e,actly the same names for the parameters to those su(programs. 'n addition" the (ody
can define types and su(programs that are not declared in the specification. -uch entities can
only (e used inside the pacage (ody4 they are not visi(le to the users of the pacage. 2igure 3I
shows an a((reviated version of screen.adb.
The pacage (ody does not need to include a with clause for its own specification" however it can
with other pacages as necessary in order to gain access to the resources provided (y those
pacages.
When (uilding a large program the pacage specifications can all (e written first" (efore any real
coding starts. The specifications are thus the final output of the design phase of the software de-
velopment life cycle. These specifications can (e compiled separately to verify that they are free
from synta, errors and that they are internally consistent. The compiler can verify that all the
necessary dependencies are e,plicitly declared via appropriate with statements" and that all types
are used in a manner that is consistent with their declarations.
Ance the specifications are in place" the (odies can (e written. 8ecause a pacage (ody only de-
pends on the specifications of the pacages it uses" the (odies can all (e written in parallel" (y dif-
ferent people" without fear of inconsistency creeping into the program
=
. Programmers could (e
for(idden to modify any specification files )for e,ample (y using appropriate access control fea-
tures on a file server or version control system*" requiring any such modifications to first (e
cleared (y a designer. -urprisingly few programming languages en:oy this level of rigor in the
management of code" (ut Ada was designed for large software pro:ects and so its features are
strong in this area.
Package Initialiation
Pacages sometimes contain internal varia(les that need to (e initiali7ed in some comple, way
3 Inconsistenc& at one level of abstraction, t5at is. %5ere is still t5e ossibilit& t5at t5e semantics of a subro!ra" in one
ac+a!e "i!5t be inconsistent fro" t5at e/ected b& t5e subro!ra"7s caller in a different ac+a!e.
*a!e 1' of 3#
pac&age bodB Fcreen is
22 'ot declared in the spec. This is )or internal use onlB.
procedure Helper is
begin
22 I%ple%entation not shown.
end Helper;
22 All subprogra%s declared in spec %ust be i%ple%ented.
procedure Fet_6ursor_Position
(Dow . in Dow_TBpe; 6olu%n . in 6olu%n_TBpe# is
begin
22 I%ple%entation not shown.
end Fet_6ursor_Position;
22 etc...
end Fcreen;
Figure 1/: )xam&le Package 5od1
(efore the pacage can (e used. The pacage author could provide a procedure that does this ini -
tiali7ation" (ut then there is a ris that it won.t get called when it should. 'nstead" a pacage can
define some initiali7ation code of ar(itrary comple,ity (y introducing an e,ecuta(le section in the
pacage (ody. 2igure 6J shows how this can (e done.
'n this e,ample" an internal varia(le 6ounter is initiali7ed (y calling a function in a supporting
pacage Other. This initiali7ation is done when the pacage (ody is elaborated. 5otice that it is
necessary in this e,ample for the (ody of pacage Other to (e ela(orated first so that its initial-
i7ation statements )if any* e,ecute (efore the ela(oration of the (ody of pacage $xa%ple. 'f that
were not the case" then function Loo&up_Initial might not wor properly. To prevent undefined
things from happening" an Ada program will instead raise the e,ception Progra%_$rror at run
time if pacages get ela(orated in an inappropriate order.
To address this potential pro(lem )since you don.t really want the e,ception either* a pragma is
included in the conte,t clause of pacage $xa%ple.s (ody. Pragmas are commands to the compiler
that control the way the program is (uilt. The Ada standard defines several pragmas and imple-
mentations are allowed to define others. 'n this case the use of pragma $laborate_All forces the
(odies of pacage Other and any pacages that pacage Other uses to (e ela(orated (efore the
(ody of pacage $xa%ple. 5ote that the with clauses will automatically cause the specifications of
the withed pacages to (e ela(orated first" (ut not necessarily the (odies. 'n this case it is essen-
tial to control the order in which the pacage (odies are ela(orated. !ence the pragma is neces-
sary.
5otice that Ada does not provide any facilities for automatically cleaning up a pacage with the
program terminates. 'f a pacage has shutdown requirements a procedure must (e defined for
this purpose" and arrangements must (e made to call that procedure at an appropriate time. 'n
em(edded systems" one of the ma:or target application areas for Ada" programs are often never
end. Thus the asymmetric handling of pacage initiali7ation and cleanup is reasona(le in that con-
te,t. Ather programming languages do provide 0module destructors1 of some ind to deal with
this matter more uniformly.
!"ild Packages
8eing a(le to put code into various pacages is useful" (ut in a large program the num(er of pac-
*a!e 2- of 3#
with Other;
prag%a $laborate_All(Other#;
pac&age bodB $xa%ple is
6ounter . Integer; 22 Internal ,ariable.
procedure Fo%e_Operation is
begin
22 I%ple%entation not shown.
end Fo%e_Operation;
begin
6ounter .- Other.Loo&up_Initial(/database.,tc.,sc.edu/#;
end $xa%ple;
Figure 22: Package 'ith Initiali6ation 0ection
ages might also (e large. To cope with this Ada" lie many languages" allows its pacages to (e
organi7ed into a hierarchy of pacages" child pacages" grand child pacages" and so forth. This
allows an entire li(rary to (e contained in a single pacage and yet still allows the various compo-
nents of the li(rary to (e organi7ed into different pacages )or pacage hierarchies* as well. This
is an essential facility for any language that targets the construction of large programs.
As an e,ample" consider a hypothetical data compression li(rary. At the top level we might de-
clare a pacage 6o%press to contain the entire li(rary. Pacage 6o%press itself might (e empty
with a specification that contains no declarations at all )and no (ody*. Alternatively one might in-
clude a few li(rary-wide type definitions or helper su(programs in the top level pacage.
Ane might then define some child pacages of 6o%press. -uppose that 6o%press.Algo contains
the compression algorithms and 6o%press.9tilitB contains utility su(programs that are used (y
the rest of the li(rary (ut that are not directly related to data compression
?
. 2urther child pac-
ages of 6o%press.Algo might (e defined for each compression algorithm supported (y the li(rary.
2or e,ample" 6o%press.Algo.LAI might provide types and su(programs related to the >LW com-
pression algorithm and 6o%press.Algo.Hu))%an might provide types and su(programs related to
the !uffman encoding compression algorithm. 2igure 63 shows a procedure that wishes to use
some of the facilities of this hypothetical li(rary.
'n this e,ample ' assume the >LW pacage provides a type LAI_$ngine that contains all the infor-
mation needed to eep trac of the compression algorithm as it wors )presuma(ly a record of
some ind*. ' also assume that the pacage provides a procedure Process that updates the com-
pressed data using the given string as input.
Clearly a pacage hierarchy with many levels of child pacages will produce very long names for
the entities contained in those deeply nested pacages. This can (e awward" (ut Ada provides
two ways to deal with that. +ou have already met one way# the use statement. 8y including use
6o%press.Algo.LAI in the conte,t clause" the contents of that pacage are made directly visi(le
and the long prefi,es can (e deleted. !owever" Ada also allows you to rename a pacage to
something shorter and more convenient. 2igure 66 shows how it could loo.
The pacage FPueeQe is not a real pacage" (ut rather :ust a shorter" more convenient name for
an e,isting pacage. This allows you to reduce the length of long prefi,es without eliminating
them entirely. Although the Ada community encourages the use of long" descriptive names in Ada
programs" names that are local to a single procedure can sensi(ly (e fairly short since they have
limited scope. Bsing the renaming facility of the language you can introduce a((reviated names
for pacages )or other inds of entities* with limited scope without compromising the overall read-
a(ility of the program.
4 It "i!5t be aroriate to "a+e suc5 a ac+a!e a &rivate &ackage, but t5at feature is not discussed 5ere.
*a!e 21 of 3#
with 6o%press.Algo.LAI;
procedure Hello is
6o%pressor . 6o%press.Algo.LAI.LAI_$ngine;
begin
6o%press.Algo.LAI.Process(6o%pressor /6o%press >e!/#;
end Hello;
Figure 21: 0keleton Program 3sing 71&othetical Com&ress %ibrar1
5otice that the optimal names to use for entities in a pacage will depend on how the pacage it-
self is used. 'n the e,ample a(ove the pacage LAI provides a type LAI_$ngine. 'n cases )such
as shown* where fully qualified names are used the 0>LW1 in the name 0>LWM<ngine1 is redun-
dant and distracting. 't might mae sense to :ust name the type 0<ngine1 yielding a fully qualified
name of 6o%press.Algo.LAI.$ngine. An the other hand" if use statements are used the name
0<ngine1 (y itself is rather am(iguous )what ind of engine is thatH*. 'n that case it maes more
sense to eep the name 0>LWM<ngine.1 /ifferent programmers have different ideas a(out how
much name qualification is appropriate and it leads to differences in the way names are selected.
The pro(lem is that the programmer who write a pacage is often different from the programmer
who uses it and so incompati(le naming styles can arise. Ada.s renaming facility gives the using
programmer a certain degree of control over the names that actually appear in his or her code"
despite the names selected (y the author of a li(rary. 2igure 6= shows an e,ample of a more radi-
cal approach to renaming.
5otice that while pacages and su(programs )and also o(:ects* can (e renamed" types can not (e
renamed in this way. 'nstead you can introduce a su(type without any constraints as a way of ef-
fectively renaming a type.
'n this simple e,ample" the renaming declarations (ul up the code more than they save. !ow-
ever" in a longer and more comple, situation they can (e useful. An the other hand" you should
use renaming declarations cautiously. People reading your code may (e confused (y the new
names if it is not very clear what they represent.
1.1 Abstract 2ata T,(es
Aften it is desira(le to hide the internal structure of a type from its users. This allows the designer
of that type to change its internal structure later without affecting the code that uses that type.
Ada supports this concept (y way of private types. A type can (e declared as private in the visi(le
part of a pacage specification. Bsers can then create varia(les of that type and use the (uilt in
*a!e 22 of 3#
with 6o%press.Algo.LAI;
procedure Hello is
pac&age FPueeQe rena%es 6o%press.Algo;
6o%pressor . FPueeQe.LAI.LAI_$ngine;
begin
FPueeQe.LAI.Process(6o%pressor 6o%press >e!"#;
end Hello;
Figure 22: Com&ression )xam&le "ith Package 4enaming
wit5 Co"ress.Al!o.289:
procedure Hello is
subtBpe LAI_TBpe is 6o%press.Algo.LAI.LAI_$ngine;
procedure 6o%p($ngine . LAI_TBpe; Hata . Ftring#
rena%es 6o%press.Algo.LAI.Process;
6o%pressor . LAI_TBpe;
begin
6o%p(6o%pressor /6o%press >e!/#;
end Hello;
Figure 23: Com&ression )xam&le "ith Arbitrar1 4enaming
assignment and equality test operations on that type. All other operations" however" must (e pro-
vided in the pacage where the type is defined. -u(programs in the same pacage as the type
have access to the type.s internal representation. 2igure 6? shows a hypothetical pacage that
provides a type representing calendar dates.
5ote that in a more realistic version of this pacage" one might introduce different types for year"
month" and day values in order to prevent programs from accidentally mi,ing up those concepts.
!owever" in the interest of (revity ' do not show that in this e,ample. The type Hate is declared
private in the visi(le part of the specification. 't is then later fully defined as a record in the pri -
vate part.
Theoretically the full view of a type should not (e in the specification at all4 it is part of the pac-
age.s implementation and thus should only (e in the pacage (ody. !owever" Ada requires that
private types (e fully defined in pacage specifications as a concession to limited compiler tech-
nology. When the compiler translates code that declares varia(les of the private type" it needs to
now how much memory to set aside for such varia(les. Thus while the programmer is for(idden
to mae use of the private type.s internal structure" the compiler needs to do so. 5ote that some
programming languages go further than Ada in this regard and move all such private information
out of the interface definition. !owever" there is generally an e,ecution performance penalty in-
volved in doing this. 'n Ada it is possi(le to simulate such a feature using the so called 0pimpl id-
iom.1 This method involves access types and controlled types and so is not descri(ed further here.
5ote also that the full view of a private type does not need to (e a record type. Although records
are common in this situation" private types can (e implemented as arrays or even :ust simple
scalars lie Integer or 3loat.
Private types do allow assignment and equality tests. !owever" in some cases it is desira(le to
disallow those things. Ada maes this possi(le using limited private types. A declaration such as
tBpe Hate is li%ited pri,ate4
tells the compiler to disallow (uilt in assignment and equality tests for the specified type. This
does not mean assignment is impossi(le4 it only means that the pacage author must now pro-
vide a procedure to do assignment;if support for assignment is desired. Presuma(ly that proce-
dure would tae whatever steps were necessary to mae the assignment wor properly. Calendar
*a!e 23 of 3#
pac&age $xa%ple is
tBpe Hate is pri,ate;
)unction >a&e(@ear >onth HaB . Integer# return Hate;
)unction (et_@ear(TodaB . Hate# return Integer;
22 etc...
)unction HaB_Hi))erence(3uture Past . Hate# return Integer;
22 etc...
pri,ate
tBpe Hate is
record
@ . Integer;
> . Integer;
H . Integer;
end record;
end $xa%ple;
Figure 2: 0&eci$ication o$ a Package $or Calendar ,ates
dates are not good candidates to mae into a limited type. The component-wise assignment of
one date to another is e,actly the correct way to assign dates. Thus the (uilt in record assignment
operation is fine. -imilar comments apply to the (uilt in test for equality operation. !owever"
types that represent resources outside the computer system )for e,ample a networ connection*
can.t reasona(ly (e assigned. They should (e declared limited private instead.
1.13 Strin)s
To be written...
1.11 E4ce(tions
>ie many modern programming languages" Ada allows su(programs to report error conditions
using exceptions. When an error condition is detected an e,ception is raised. The e,ception prop-
agates to the dynamically nearest handler for that e,ception. Ance the handler has e,ecuted the
e,ception is said to have (een handled and e,ecution continues after the handler. <,ceptions are
not resuma(le. This model is largely the same as that used (y C$$ although the terminology is
different. !owever" unlie C$$" Ada e,ceptions are not ordinary o(:ects with ordinary types. 'n
fact" Ada e,ceptions don.t have a type at all and e,ist outside the language.s type system.
<,ceptions are typically defined in a pacage specification. They are then raised in the pacage
(ody under appropriate conditions and handled (y the pacage users. 2igure 6C shows part of a
specification for a <ig_'u%ber pacage that supports operations on ar(itrary precision integers.
5otice that Ada" lie C$$" allows operators to (e overloaded. 'n Ada this is done (y defining func-
tions with names given (y the operator names in quotation mars. This pacage also defines an
e,ception that will (e raised when one attempts to use <ig_'u%ber./;/ with a 7ero divisor.
The implementation of the division operation might loo" in part" as shown in 2igure 6D.
As you might guess" the raise statement a(orts e,ecution of the function immediately. A proce-
dure that wishes to use <ig_'u%ber might try to handle this e,ception in some useful way. 2igure
6C shows the synta,.
*a!e 24 of 3#
pac&age <ig_'u%ber is
tBpe 'u%ber_TBpe is pri,ate;
Hi,ide_<B_Aero . exception;
)unction /:/(Le)t Dight . 'u%ber_TBpe# return 'u%ber_TBpe;
)unction /2/(Le)t Dight . 'u%ber_TBpe# return 'u%ber_TBpe;
)unction /E/(Le)t Dight . 'u%ber_TBpe# return 'u%ber_TBpe;
)unction /;/(Le)t Dight . 'u%ber_TBpe# return 'u%ber_TBpe;
pri,ate
22 'ot shown.
end <ig_'u%ber;
Figure 2#: 0&eci$ication $or Package Big_Number 8Abbreviated9
The (loc delimited (y begin and end can contain a header exception. After that header a series
of when clauses specify which e,ceptions the (loc is prepared to handle. The special clause when
others is optional and is used for all e,ceptions that are otherwise not mentioned.
'f the normal statements in the (loc e,ecute without e,ception" control continues after the (loc
)sipping over the e,ception clauses*. 'n the e,ample a(ove the procedure returns at that point.
'f an e,ception occurs in the (loc" that e,ception is matched against those mentioned in the
when clauses. 'f a match is found the corresponding statements are e,ecuted and then control
continues after the (loc. 'f no match is found" the (loc is a(orted and the ne,t dynamically en-
closing (loc is searched for a handler instead. 'f you are familiar with C$$ or %ava e,ceptions
none of this should (e surprising.
2igure 6E also shows an interesting detail related to operator overloading. The e,ample assumes
that there is a conte,t clause of with <ig_'u%ber )not shown* (ut no use statement. Thus the di-
vision operator is properly named <ig_'u%ber./;/. Bnfortunately it can.t (e called using the infi,
operator notation with that name. There are several ways to get around this. Ane could include a
use <ig_'u%ber in the conte,t clause or in the procedure.s declarative region. !owever that
would also mae all the other names in pacage <ig_'u%ber directly visi(le and that might not (e
desired. An alternative is to introduce a local function named /;/ that is :ust a renaming )essen-
tially an alias* of the function in the other pacage. As we have seen Ada allows such renaming
declarations in many situations" (ut in this case" every operator function would need a corre-
sponding renaming and that could (e tedious.
2igure 6E shows a more elegant approach. The use tBpe declaration tells the compiler that the
primitive operations of the named type should (e made directly visi(le. ' will discuss primitive op-
erations in more detail in the section on o(:ect oriented programming. 'n this case" the operator
overloads that are declared in pacage <ig_'u%ber are primitive operations. This method allows
all the operator overloads to (e made directly visi(le with one easy statement" and yet does not
mae every name in the pacage directly visi(le.
The Ada language specifies four predefined e,ceptions. These e,ceptions are declared in pacage
-tandard )recall that pacage -tandard is effectively (uilt into the compiler* and thus directly visi -
(le at all times. The four predefined e,ceptions with their use is shown in the following ta(le.
6onstraint_$rror
(aised w5enever a constraint is violated. %5is includes !oin! outside t5e
bounds of a subt&e <or e=uivalentl& t5e allowed ran!e of an arra& inde/> as
well as various ot5er situations.
*a!e 25 of 3#
)unction /;/(Le)t Dight . 'u%ber_TBpe# return 'u%ber_TBpe is
begin
22 Assu%e there is a suitable o,erloaded -" operator.
i) Dight - 1 then
raise Hi,ide_<B_Aero;
end i);
22 Proceed &nowing that the di,isor is not Qero.
end /;/;
Figure 2*: Im&lementation o$ Big_Number."/"
procedure $xa%ple is
use tBpe <ig_'u%ber.'u%ber_TBpe;
? @ A . <ig_'u%ber.'u%ber_TBpe;
begin
22 3ill @ and A with interesting ,alues.
? . - @ ; A;
exception
when <ig_'u%ber.Hi,ide_<B_Aero -4
Put_Line(/<ig 'u%ber di,ision bB Qero!/#;
when others -4
Put_Line(/9nexpected exception!/#;
end $xa%ple;
Figure 2+: 7andling 5ig:Number )xce&tions
Progra%_$rror
(aised w5en certain ill for"ed ro!ra"s t5at can7t be detected b& t5e
co"iler are e/ecuted. 3or e/a"le, if a function ends wit5out e/ecutin! a
return state"ent, Progra%_$rror is raised.
Ftorage_$rror
(aised w5en t5e ro!ra" is out of "e"or&. %5is can occur durin!
d&na"ical "e"or& allocation, or be due to a lac+ of stac+ sace w5en
invo+in! a subro!ra". %5is can also occur durin! t5e elaboration of a
declarative re!ion <for e/a"le if t5e d&na"ic bounds on an arra& are too
lar!e>.
Tas&ing_$rror
(aised in connection wit5 certain tas+in! roble"s. It is outside t5e scoe
of t5is tutorial to cover t5ese details.
Most of the time the predefined e,ceptions are raised automatically (y the program under the ap-
propriate conditions. 't is legal for you to e,plicitly raise them if you choose" (ut it is recom-
mended that you define your own e,ceptions for your code. 5ote that the Ada standard li(rary de-
fines some additional e,ceptions as well. Those e,ceptions are not really predefined (ecause" un-
lie the four a(ove" they are not (uilt into the language itself.
1.12 2iscri*inated T,(es
To be written...
1.1" 5enerics
-tatically checed strongly typed languages lie Ada force su(program argument types and pa-
rameter types to match at compile time. This is awward in situations where the same sequence
of instructions could (e applied to several different types. To satisfy the compile time type chec-
ing requirements" it is necessary to duplicate those instructions for each type (eing used. To get
around this pro(lem" Ada allows you to define generic su(programs and generic pacages where
the types used are parameters to the generic unit. Whenever a new 0version1 of the generic unit
is needed" it is instantiated (y the compiler for specific values of the type parameters.
Ada generics are very similar in concept and purpose to C$$ templates. >ie C$$ templates"
generics are handled entirely at compile time4 each instantiation generates code that is special-
i7ed for the types used to instantiate it. This is different than generics in %ava which are resolved
at run time and that use a common code (ase for all instances
C
. !owever" Ada generics and C$$
templates also differ in some important ways. 2irst Ada requires the programmer to e,plicitly in-
stantiate a generic unit using special synta,. 'n C$$ instantiations are done implicitly. %ust men-
tioning the instance causes it to come into e,istence
D
. 'n addition" Ada generics do not support e,-
plicit speciali7ation or partial speciali7ation" two features of C$$ templates thare used in many
advanced template li(raries.
There are pros and cons to Ada.s approach as compared to C$$.s method. With Ada" it is very
clear where the instantiation occurs )since it is shown e,plicitly in the source code*. !owever" C$
$.s method ena(les advanced programming techniques )template meta-programming* that Ada
can.t easily replicate.
The other ma:or difference (etween Ada generics and C$$ templates is that Ada allows the pro-
grammer to specify the necessary properties of the types used to instantiate a generic unit. 'n
5 Actuall& Ada !enerics allow for t5e ossibilit& of s5arin! code, deendin! on t5e co"iler7s i"le"entation strate!&.
$ C?? also allows e/licit instantiation of te"lates, but it is rarel& used.
*a!e 2$ of 3#
contrast in C$$ one only says that the parameter is a type. 'f a type is used to instantiate a tem-
plate that doesn.t mae sense" the compiler only reali7es that when it is actually doing the instan-
tiation. The resulting error messages are highly cryptic and misleading. 'n contrast the Ada com-
piler can chec (efore it (egins the instantiation process if the given types are accepta(le. 'f they
are not" it can provide a much clearer and more specific error message.
To illustrate how Ada generics loo" consider 2igure 6G that shows the specification of a generic
pacage containing a num(er of sorting procedures.
5otice that the specification has a generic header that defines the parameters to this generic
unit. The first such parameter is a type that will (e called $le%ent_TBpe in the scope of the
generic pacage. 't is declared as a private type to indicate that the pacage will only )(y default*
(e a(le to assign and compare for equality o(:ects of that type. 't is thus possi(le to instantiate
this pacage for private types" (ut non-private types lie 'ntegers" arrays" and records also have
the necessary a(ilities and can (e used. !owever" a limited type )for e,ample" a type declared as
li%ited pri,ate in some other pacage* can not (e used.
This generic pacage also requires its user to provide a function that can compare two
$le%ent_TBpe o(:ects. That function is called /0/ in the scope of the pacage" (ut it could (e
called anything (y the user. 't must" however" have the same profile )the same num(er and type
of parameters*.
'nside the implementation of the generic pacage" $le%ent_TBpe can (e used as a private type
e,cept that it is also permitted to use /0/ to compare two $le%ent_TBpe o(:ects. 5o other opera-
tions on $le%ent_TBpe o(:ects are allowed to guarantee the pacage will instantiate correctly with
any type the user is allowed to use.
2igure 6I shows how this pacage might (e used.
*a!e 2# of 3#
generic
tBpe $le%ent_TBpe is pri,ate;
with )unction /0/(Le)t Dight . $le%ent_TBpe# return <oolean;
pac&age Forters is
tBpe $le%ent_ArraB is arraB('atural range 04# o) $le%ent_TBpe;
procedure Ruic&_Fort(FePuence . in out $le%ent_ArraB#;
procedure Heap_Fort(FePuence . in out $le%ent_ArraB#;
procedure <ubble_Fort(FePuence . in out $le%ent_ArraB#;
end Forters;
Figure 2.: 0&eci$ication o$ a ;eneric Package $or 0orting
5otice the first line in the declarative region that instantiates the generic unit. 'n the e,ample"
named parameter association is used to (ind the generic unit.s arguments to its parameters. The
strange looing construction /0/ -4 Ftandard./0/ is an association (etween the generic param-
eter /0/ )the comparison function* and the operator 0N1 that applies to integers )declared in
pacage -tandard*. 't would (e more typical for the right side of this association )and even the
left side as well* to (e normally named functions.
The name Integer_Forters is given to the specific instance created. That name can then (e used
lie the name of any other pacage. 'n fact" it is legal )and common* to follow a generic instantia-
tion with a use statement to mae the contents of the newly instantiated pacage directly visi(le.
Ada also allows procedures and functions to (e generic using an analogous synta,.
The e,ample in 2igure 6G is fairly simple in that the generic type parameter has very limited a(ili-
ties. 't is also possi(le to specify that the parameter is a discrete type )thus allowing the use of
73irst" 7Last" 7Fucc and 7Pred attri(utes*" an access type" a tagged type" a modular type" a
floating point type" and various other possi(ilities. 'n addition" Ada.s generic facility allows generic
units to (e parameteri7ed on values )so called 0non-type1 parameters in C$$* and varia(les. ' re-
fer you to one of the references for more information on generic units in Ada. The discussion here
is only scratching the surface of the topic.
1.1& Access T,(es and 2,na*ic 6e*or, Allocation
Ada" lie many languages" allows you to create o(:ects that refer to other o(:ects. 't also allows
you to create o(:ects that have a lifetime e,tending (eyond that of the scope in which they are
created. 8oth of these capa(ilities are important and many programming techniques depend on
them. C and C$$ allow the programmer to use ar(itrary pointers" implemented as simple mem-
ory addresses" in any way desired. While this is very powerful" it is also very dangerous. C and C$
$ programs suffer from many (ugs and security vulnera(ilities related to the unrestricted use of
pointers in those languages.
'n Ada pointer types are called access types. >ie C and C$$ pointer varia(les" access varia(les
can (e manipulated separately from the o(:ects to which they point. !owever" unlie C and C$$
pointer types" access types in Ada have a num(er of restrictions on their use that are designed to
mae them safer.
Actually" the history of access types in Ada is quite interesting. 'n Ada G= access types were very
limited (ut also very safe. !owever" e,perience with Ada showed that the limitations were too
*a!e 2) of 3#
with Forters;
procedure $xa%ple is
pac&age Integer_Forters is
new Forters($le%ent_TBpe -4 Integer /0/ -4 Ftandard./0/#;
Hata . Integer_Forters.$le%ent_ArraB;
begin
22 3ill Hata with interesting in)or%ation.
Integer_Forters.Ruic&_Fort(Hata#;
end $xa%ple;
Figure 2/: Instantiating a generic &ackage<
great. Ada IC removed some of the limitations while still managing to eep the safety )at the e,-
pense of complicating the language*. +et even after these changes access types were still not as
fle,i(le as desired. Ada 6JJC removed yet more limitations (ut now requires" in certain cases" run
time checing to (e done to ensure safety
E
. 'n this tutorial ' will not descri(e these issues in de-
tail. My focus here is on the (asic use of access types in Ada.
Access types can (e named or anonymous. ' will only consider named access types4 anonymous
access types have special properties that are outside the scope of this tutorial. 2or e,ample the
declaration
tBpe Integer_Access is access Integer;
declares Integer_Access as a type suita(le for accessing" or pointing at" integers. 5otice that in
this tutorial ' have used a suffi, of E_TBpe when naming a type. 'n this case" however" ' use a
suffi, of E_Access to emphasi7e the nature of the access type. This is" of course" :ust a conven-
tion.
Ance the access type has (een declared" varia(les of that type can then (e declared in the usual
way.
P . Integer_Access;
Ada automatically initiali7es access varia(les to the special value null if no other initiali7ation is
given. Thus access varia(les are either null or they point at some real o(:ect. 'ndeed" the rules of
Ada are such that dangling pointers are not possi(le
G
. Access varia(les can (e copied and com-
pared lie any other varia(le. 2or e,ample if P+ and P* are access varia(les than P+ - P* is true if
they (oth point at the same o(:ect. To refer to the o(:ect pointed at (y an access varia(le you
must use the special .all operation.
P.all .- +;
The .all plays the same role in Ada as the indirection operator )the E* plays in C and C$$. The
use of .all may seem a little odd in this conte,t" (ut understand that most of the time access
types are pointers to records. 'n that case" the components of the record pointed at can (e ac-
cessed directly (y using the component selection operation on the access varia(le itself. 2igure =J
illustrates.
'n this case the .all synta, is very natural. 't shows that you are accessing all the mem(ers of
the referenced o(:ect at the same time. 't is important to notice that Ada normally 0forwards1 op-
erations applied to the access varia(le to the referenced o(:ect. Thus H+.HaB in the e,ample
means the HaB component of the o(:ect pointed at (y H+. Anly operations that are meaningful for
the access type itself are not forwarded. Thus H+ .- H* copies the access values. To copy the o(-
:ects pointed at (y the access varia(les one must use the .all synta,. ' should also note that
synta, such as H+.all.HaB" while ver(ose" is also legal. The .all dereferences H+. The result is a
date record so the selection of the HaB component is meaningful.
# %5ese run ti"e c5ec+s are in cases t5at were reviousl& ille!al. 95en usin! access t&es in older wa&s Ada 2--5 access
t&es re=uire no run ti"e c5ec+s over w5at older Ada versions re=uired.
) %5is isn7t t5e w5ole stor&. It would be "ore accurate to sa& t5at dan!lin! ointers aren7t ossible as lon! as
9nchec&ed_Heallocation is never used.
*a!e 2' of 3#
Access varia(les that refer to arrays also allow the normal array operations to (e forwarded to the
referenced o(:ect. 2igure =3 illustrates.
8ecause of forwarding" using access types is generally quite convenient in Ada. !owever" you
must eep in mind that operations that are meaningful for the access types themselves will (e ap-
plied directly to the access o(:ects and are not forwarded.
-o far we.ve seen how to declare and use access types. !ow does one get an access varia(le to
point at another o(:ect in the first placeH 'n Ada G= there was only one way# using the new opera-
tion. 2or e,ample
P .- new Integer7(1#;
dynamically allocates an integer" initiali7es that integer to 7ero" and then assigns the resulting ac-
cess value to P. !ere ' assume P has an access to integer type. 5otice that argument to new has
the form of a qualified e,pression )the apostrophe is required*. Also as with dynamically allocated
o(:ects in other languages" the lifetime of the o(:ect created in this way e,tends (eyond the life-
time of the access varia(le used to point at it.
#arbage !ollection$
'n many languages dynamically allocated o(:ects are automatically reclaimed when they can no
longer (e accessed. 2or e,ample" in Ada parlance" when all access varia(les pointing at an o(:ect
*a!e 3- of 3#
tBpe Hate is
record
HaB >onth @ear . Integer;
end record;
tBpe Hate_Access is access Hate;
H+ H* . Hate_Access;
...
H+.HaB .- +; 22 Accesses the HaB %e%ber o) re)erenced Hate.
H+ .- H*; 22 6auses H+ to point at sa%e obNect as H*.
H+.all .- H*.all; =2 6opies Hate obNects.
Figure 32: Access T1&e 01ntax
tBpe <u))er_TBpe is arraB(1..+1*L# o) 6haracter;
tBpe <u))er_Access is access <u))er_TBpe;
<+ <* . <u))er_Access;
...
<+ .- <*; 22 6opies onlB the access ,alues.
<+.all .- <*.all 22 6opies arraBs.
<+(1# .- 7?7 22 3orwards index operation.
)or I in <+7Dange loop 22 3orwards 7Dange attribute.
...
end loop;
Figure 31: Access to Arra1 T1&es
go out of scope the o(:ect pointed at (y those varia(les can no longer (e referenced and the
memory it uses should (e made availa(le again. The process of reclaiming such memory is called
garbage collection.
'n Ada gar(age collection is optional. 'mplementations are allowed to provide it" (ut they are not
required to do so. This may seem surprisingly wishy-washy for a language that endeavors to sup-
port relia(le and porta(le programming. The pro(lem is that Ada also endeavors to support low
level em(edded systems and real time programming. 'n such environments gar(age collection is
widely considered a (ad idea. 't is difficult to meet real time o(:ectives if a comple, gar(age col-
lection algorithm might run at any time. Also the space overhead of having a gar(age collector in
the run time system might (e unaccepta(le for space constrained em(edded devices. Advances in
gar(age collection technology has made some of these concerns less pressing today than they
were when Ada was first designed. !owever" these matters are still important. Thus Ada allows"
(ut does not require gar(age collection.
This presents an immediate pro(lem for programmers interested in porta(ility. 'f the implementa-
tion does not collect its gar(age and the programmer taes no steps to manually reclaim allocated
o(:ects" the program will lea memory. This is a disaster for long running programs lie servers.
Thus for ma,imum porta(ility one must assume that gar(age collection is not done and tae steps
accordingly. 'n fact" most Ada implementations do not provide gar(age collection" so this is a very
realistic concern.
The Ada li(rary provides a generic procedure named 9nchec&ed_Heallocation that can (e used
to manually deallocate a dynamically allocated o(:ect. Bnfortunately the use of 9nchec&ed_Heal2
location can violate important safety properties the language otherwise provides. 'n particular" if
you deallocate an o(:ect while an access varia(le still points at it" any further use of that access
varia(le will result in erroneous (ehavior
I
. As a service 9nchec&ed_Heallocation will set the ac-
cess varia(le you give it to null causing future use of that access varia(le to result in a well de-
fined e,ception. !owever" there might (e other access varia(les that point at the same o(:ect and
9nchec&ed_Heallocation can not now a(out all of them in general.
'f your program never uses 9nchec&ed_Heallocation then all access varia(les are either null or
point at a real o(:ect4 dangling pointers are impossi(le. !owever" your program might also lea
memory if the Ada implementation does not provide gar(age collection. Thus in most real pro-
grams 9nchec&ed_Heallocation is used.
This is an e,ample of where Ada compromises safety for the sae of practical reality. 'n fact"
there are several other 9nchec&ed_E operations in Ada that are used to address certain practical
concerns and yet introduce the possi(ility of unsafe programs. -ince every such operation starts
with the word 0Bncheced1 it is an simple matter to search an Ada program for occurrences of
them. This feature maes reviewing the uncheced operations easier.
Show an example of Unchecked_Deallocation...
1.1' Co**and Line Ar)u*ents and 7ile #andlin)
To be written...
1.1+ Ob8ect Oriented /ro)ra**in)
To be written...
' %5e Ada co""unit& uses t5e 5rase @erroneous be5aviorA to refer to undefined be5avior of all +inds, includin! ro!ra"
cras5es.
*a!e 31 of 3#
1.1- Tas0in)
Many programs can (e naturally descri(ed as multiple" interacting" concurrent threads of e,ecu-
tion. Programming environments that provide direct support for concurrency are thus very useful.
-uch support can (e offered (y the operating system or (y the programming language or some
com(ination of the two. The classic way in which operating systems support concurrency is (y al -
lowing multiple independent processes to run simultaneously. This method has the advantage of
offering good isolation (etween the processes so that if one crashes the others are not necessarily
affected. An the other hand" communication (etween processes tends to have high overhead.
Modern operating systems also usually allow programs to (e written that have multiple threads of
control e,ecuting in the same process. This thread level concurrency is harder to program cor-
rectly (ut has reduced overhead as compared to the older style process level concurrency.
'n some environments offering thread level concurrency the programmer must invoe su(pro-
grams in a special li(rary to create and synchroni7e threads. -uch an approach requires relatively
little support from the programming language (ut it tends to (e error prone. Another approach is
to (uild support for thread level concurrency into the programming language itself. This allows the
compiler to tae care of the low level details of thread management" freeing the programmer to
focus on other aspects of the program.s design. Ada uses this second approach and supports con-
current programming as a language feature.
The unit of e,ecution in Ada is called a task. The main program e,ecutes in a tas called the envi-
ronment task. +ou can create additional tass as appropriate to meet your application.s needs.
>ie a pacage each tas has a specification and a (ody. 'n the simplest case a tas specification
only needs to declare that the tas e,ists. 2igure =6 illustrates the (asic synta,.
'n this e,ample a tas 'ag is (oth specified and defined in the declarative region of the main pro-
gram. The tas simply prints 0!ello1 one hundred times with a 3J second delay (etween each line
of output. While the tas does this important wor" the main program simultaneously e,ecutes
the useful function of the program.
*a!e 32 of 3#
with Ada.Text_IO;
with Helper;
procedure >ain is
= Fpeci)ication o) nested tas&.
tas& 'ag;
= <odB o) nested tas&.
tas& bodB 'ag is
begin
)or I in + .. +11 loop
Ada.Text_IO.Put_Line(/Hello/#;
delaB +1.1;
end loop;
end 'ag;
begin
Helper.Fo%ething_9se)ul;
end >ain;
Figure 32: 0im&le Nested Task
't is important to understand that the tas starts e,ecuting automatically as soon as the enclosing
su(program (egins. 't is not necessary to e,plicitly start the tas. 2urthermore the enclosing su(-
program will not return until the tas has completed. Care must (e taen to ensure that the tas
eventually ends. 'f the tas never ends the enclosing su(program will never return.
8ecause the tas is nested inside another program unit it has access to the local varia(les and
other entities declared in the enclosing unit a(ove the tas.s definition. This gives a way for the
tas to share information with the enclosing unit (ut (eware that sharing data in this manner is
difficult and error prone. As ' will descri(e shortly Ada provides much more ro(ust ways for tass
to communicate.
The e,ample a(ove shows a tas nested inside a procedure. Tass can also (e nested inside func-
tions or even inside each other. This allows you to create a tas to assist in the e,ecution of any
su(program without anyone outside your su(program (eing aware that tass are involved. +ou
can also create tass inside a pacage (ody that support the operation of that pacage. 8e aware"
however" that if you do create a tas inside a li(rary pacage (ody you need to arrange for that
tas to eventually end or else the program will never terminate.
1.1. Container Librar,
To be written...
1.11 Lo! Leel /ro)ra**in)
To be written...
SECTION 2 CASE STU29: #U776AN ENCO2IN5
To (etter understand the features of Ada" it is helpful to wor through a small (ut realistic pro-
gram using the language. 'n this section ' will design and implement a simple file compression
utility that uses the !uffman encoding compression algorithm. Although !uffman encoding is not
particularly effective (y itself" it is good enough to provide a usa(le utility for some applications. 't
also provides a good (alance of comple,ity and simplicity for this e,ercise.
1.23 The Al)orith*
!uffman encoding taes advantage of the fact that in most files some (yte values are much more
common than others. 8y assigning short (inary codes to the most commonly occurring values the
file can (e made smaller. Ane consequence" however" of assigning short codes to some values is
that other values must necessarily (e assigned long (inary codes. This is necessary in order to
properly distinguish (etween all possi(le values.
2or e,ample" assume that the most commonly occurring value is assigned a single (it code of 3.
All other values must necessarily have codes starting with J so that they can (e properly recog-
ni7ed. There could (e as many as 6CC such values" requiring G additional (its )for a total of nine
(its* to distinguish those values among themselves.
!uffman encoding finds a way to assign varia(le length codes to the (yte values to minimi7e the
overall file si7e. -pecifically it uses (yte value frequency information to mae the code assign-
ments. That is" commonly occurring (ytes are assigned relatively short codes and infrequently oc-
curring (ytes are assigned correspondingly longer codes. 'tt can (e shown that !uffman encoding
is optimal4 no other compression method that does not tae advantage of correlations can provide
*a!e 33 of 3#
more compression
3J
. !uffman encoding is also an e,ample of a greedy algorithm and is often dis-
cussed in algorithms te,t(oos as such.
The algorithm has three phases.
3. -can the input and count the num(er of times each (yte value occurs.
6. Construct a code tree that reflects the relative frequency of the (yte values and assign the
varia(le length codes to each value.
=. Kewrite the input su(stituting the codes assigned in step &6 for the (yte values.
Ane significant disadvantage to !uffman encoding is that the input must (e scanned completely to
do the frequency analysis (efore any output can (e written. 'n some applications the entire input
is not nown initially )for e,ample# streaming data or user input* and that is a ma:or pro(lem for
this method. 'n such cases the compressor can sometimes mae an educated guess a(out the rel-
ative frequencies of the (yte values" (ased perhaps on past o(servations of similar input" (ut the
results will then (e only appro,imate. This is not an issue in this case4 ' am interested in com-
pressing files and ' have access to the entire file (efore ' have to compress any of it.
The output of the first phase is" conceptually" a ta(le with one entry for each (yte value )6CD en-
tries in all*. Associated with each entry is a count of the num(er of times that value appeared in
the input. 2or e,ample" assume the algorithm is applied to a file containing only the letters .A.
through .<.. The ta(le output (y the first phase might loo as follows#
The ta(le elements (ecome the leaves of a tree. Pseudo code for the tree (uilding algorithm is
shown in 2igure ==. <ach pass of the while loop com(ines the counts from the active nodes with
the smallest and ne,t smallest count. Those nodes are then removed from the active list and the
new node is added to the active list )where its com(ined count is then considered in later passes*.
Thus each pass of the while loop reduces the si7e of the active list (y one. <ventually only a single
active node is left and that node is the root of the code tree.
2or e,ample using the initial counts as shown a(ove" the result after the first past of the while
loop in 2igure == is as follows#
1- Hi!5 end co"ression al!orit5"s alwa&s ta+e advanta!e of correlations for "uc5 5i!5er co"ression ratios.
*a!e 34 of 3#
A. +*+
<. LS
6. C+C
H. J
$. M*
'n the ne,t pass of the while loop the nodes with counts ?6 )smallest* and ?C )ne,t smallest* will
(e com(ined. After the loop finishes e,ecuting in the sample a(ove the code tree loos lie
5otice that the nodes with large counts" such as the node for .A. are com(ined late in the process.
-uch nodes thus end up (eing a short distance from the root of the code tree. This is the (asis for
their short codes. 5otice also that the count in the root node ends up (eing the same as the total
num(er of (ytes in the input. This can (e used as a validity chec on the code tree construction
process.
After the code tree has (een constructed" codes are assigned to the original (yte values (y as-
signing a 3 or J (it to each lin in the code tree. The assignment can (e ar(itrary without affect-
ing the correctness of the result" (ut for the sae of choosing something" ' will assign a 3 (it to
the child node with the larger count value. After the (it assignments" the code tree (ecomes#
*a!e 35 of 3#
IHIL$ 0There is %ore than one acti,e node4 LOOP
03ind nodes x B with the s%allest and next s%allest counts4
06reate a new node Q that co%bines the count ,alues;
Point Q at x and B4
0De%o,e x and B )ro% the set o) acti,e nodes4
0Add Q to the set o) acti,e nodes4
$'H
Figure 33: 7u$$man code tree building &seudo=code
A. C+C
<. LS
6. +*+
H. J
$. M*
. MC
A. C+C
<. LS
6. +*+
H. J
$. M*
. MC
. GO
. *1G
. O*L
The code for a (yte value is then read from the root" assigning (its from left to right in the code
as each lin in the code tree is traversed. 'n my e,ample this yields the codes as shown in Ta(le
3.
5otice how the codes for the most commonly occurring (yte values ).A. and .C.* are short while
the codes for the most infrequently occurring (yte values ).8. and ./.* are long. 5otice also that
there is no am(iguity in the encoding. 2or e,ample" a (it sequence such as 3JJ33J333JJJ can
only (e interpreted as the (yte sequence 0A8CAA<.1 5otice also that if ordinary G (it (ytes are
used the string 0A8CAA<1 would consume D (ytes of space. !owever" the (it sequence
3JJ33J333JJJ is only 36 (its )3.C (ytes* long.
1.21 I*(le*entation Notes
8efore looing at the detailed design of the !uffman compression program ' want to point out a
few issues of interest. Feep these issues in mind when you review the program.s design and the
source code of the program itself.
3. 8oth the input and output files have to (e processed as raw (inary (ytes without structure.
To mae the program general" it should not concern itself with the meaning of the input
file.s contents.
6. The construction of the code tree can.t start until the input file has (een fully analy7ed.
*a!e 3$ of 3#
A. C+C
<. LS
6. +*+
H. J
$. M*
. MC
. GO
. *1G
. O*L
+
1
+
1
+
1
+
1
A 1
B --11
C -1
, --1-
. ---
Table 1: 7u$$man Codes $or )xam&le
-imilarly no output can (e written until the code tree is fully constructed and code se-
quences have (een assigned. This means there is little opportunity for parallelism among
these phases of e,ecution.
=. The pointers in a code tree node sometimes point at other code tree nodes )presuma(ly al -
located dynamically* and sometimes point at the original ta(le of counter values.
?. An au,iliary data structure of some ind will (e necessary to eep trac of which code tree
nodes are currently 0active.1
C. -ince the code sequences have varia(le length" writing the output file is tricy. A way must
(e provided to write partial (ytes and to write long (it sequences that span multiple (ytes.
D. 2or the compressed file to (e decompressed properly the receiver will need to (uild e,actly
the same code tree as the sender. Ane way to allow the receiver to do this would (e for
the sender to transmit the original counts in a header on the compressed file. 'f =6 (it
counts are used" this adds 3J6? (ytes of overhead to the compressed file.
E. 'n a realistic e,ample some code sequences can (e very long )one or two hundred (its in
an e,treme case*. 't may (e appropriate to use a varia(le length data structure to handle
them.
SECTION " RE7ERENCES
3. rogramming in !da "##$ (y %ohn 8arnes. Addison-Wesley" 6JJD. '-85OJ-=6-3=?JEG-E.
This is the definitive te,t on the latest Ada standard.
6. !da as a Second %anguage" second edition (y 5orman !. Cohen. Mc9raw-!ill" 3IID.
'-85OJ-JE-J33DJE-C. This is an e,haustive reference of the Ada IC language. While a (it
dated" it is still a very good resource for modern Ada programming.
=. &oncurrency in !da" second edition (y Alan 8urns and Andy Wellings. Cam(ridge Bniver-
sity Press" 3IIG. '-85OJ-C63-D6I33-P. This (oo focuses on Ada.s features for tasing.
This edition only covers Ada IC" and thus does not discuss the significant tasing related
additions made in the 6JJC standard. !owever" for many programs" the Ada IC features
are more than sufficient.
?. 'igh (ntegrity Software. The S!)* !pproach to Safety and Security (y %ohn 8arnes. Addi-
son-Wesley" 6JJ=. '-85OJ-=63-3=D3D-J. This (oo descri(es a speciali7ed su(set of the
Ada language called -PAKF that is used for the construction of ultra-relia(le software.
C. Wii8oo on Ada# http#@@en.wii(oos.org@wii@AdaMProgramming. This is one of the (etter
of the Wii8oos. As always anything on-line is a wor in progress. 5evertheless many as-
pects of Ada are well descri(ed.
D. Ada 5ewsgroup# news#@@comp.lang.ada. An active newsgroup where you can post ques-
tions and tal with Ada e,perts.
E. Ada 'KC channel# irc#@@irc.freenode.net@&ada. Although often quiet there are usually a few
people there who can answer questions.
G. There are several Ada we( sites. The Ada 'nformation Clearinghouse )http#@@www.adaic.-
com@*" site is a good place to start.
*a!e 3# of 3#

Você também pode gostar