Modern Programming Languages - 13-17 - Ada
Modern Programming Languages - 13-17 - Ada
Modern Programming
Languages
Lecture 13-17
Ada Programming Language
An Introduction
Design Goals
Ada programs also catch many errors at run-time if they can't be caught at
compile-time (this checking can be turned off to improve performance if desired).
Ada History
The need for a single standard language was felt in 1975 and the draft
requirements were given the code name strawman. Strawman was refined to
Woodman and then Tinman in 1976. It was further refined to ironman. At that
time proposals were invited for the design of a new language. Out of the 17
proposals received, four were selected and given the code names of green, red,
blue, and yellow. Initial designs were submitted in 1978 and red and green short
listed on the basis of these designs. Standard requirements were then refined to
steelman. The designs were refined further and finally Green was selected in
1979. DoD announced that the language will be called Ada. The 1995 revision of
Ada (Ada 95) was developed by a small team led by Tucker Taft. In both cases,
the design underwent a public comment period where the designers responded
to public comments.
Ada Features
The salient features of Ada language are as follows:
• Packages (modules) of related types, objects, and operations can be
defined.
• Packages and types can be made generic (parameterized through a
template) to help create reusable components.
• It is strongly typed
• Errors can be signaled as exceptions and handled explicitly. Many serious
errors (such as computational overflow and invalid array indexes) are
automatically caught and handled through this exception mechanism,
improving program reliability.
• Tasks (multiple parallel threads of control) can be created and
communicate. This is a major capability not supported in a standard way
by many other languages.
• Data representation can be precisely controlled to support systems
programming.
• A predefined library is included; it provides input/output (I/O), string
manipulation, numeric functions, a command line interface, and a random
number generator (the last two were available in Ada 83, but are
standardized in Ada 95).
• Object-oriented programming is supported (this is a new feature of Ada
95). In fact, Ada 95 is the first internationally standardized object-oriented
programming language.
• Interfaces to other languages (such as C, Fortran, and COBOL) are
included in the language.
Ada Operators
Ada has a rich set of operators. The following table gives a list of these operators
and also shown corresponding C++ operators for reference.
It is important to note that Ada has not included operators like PlusEquals as
such operators reduce readability.
Operator Overloading
Ada allows a limited overloading of operators. The exception in Ada is that the
assignment operator ( := ) cannot be overridden. It can be overridden in case of
inheritance from a special kind of “abstract class”. When you override the
equality operator ( = ) you also implicitly override the inequality operator ( /= ).
Ada Types
Ada provides a large number of kinds of data types. Ada does not have a
predefined inheritance hierarchy like many object oriented programming
languages. Ada allows you to define your own data types, including numeric data
types. Defining your own type in Ada creates a new type.
Elementary Types
• Scalar Types
• Discrete Types
• Real Types
• Fixed Point Types
• Access Types
Discrete Types
Integer Types
We first look at Signed Integer types. Ada, like other languages, supports signed
integers. However, in this languages we can also define our own integer type
with a limited set of values as shown in the following example:
This defines a type Marks with the property that a variable of this type can only
have values between 0 and 100.
finalScore : Marks;
You may also note that the syntax of Ada for variable declaration is different from
C. In this case, the type comes after the variable name and is separated by a :
from the variable names.
Modular types support modular arithmetic and have wrap around property. This
concept is elaborated with the help of the following example:
q : m := 6; -- initialization
…
q := q + 2; -- result is 1
Character Types
These are good enough for most purposes, but you can define your own types
just like the integer types:
Enumeration Types
2. One can however add/subtract one (sort of increment and decrement) using
the Pred and Succ as shown below:
State’Pred (S1)
State’Succ (S2)
3. Unlike C, the same symbolic literal can be used in two enumeration types. For
example:
The Ada compiler will use the type of the variable in question and there will be no
ambiguity.
Boolean Types
Expressions of type Boolean are used in logical statements and are used as
conditions in the if statements, while loops, exit statements, etc.
Like most other languages, Ada also supports floating point types. In this case,
we can also explicitly declare the desired precision of the number. For example:
defines a type with 10 decimal digits of precision and a valid range of values from
-1.0 through 1.0.
Ada also supports fixed point real numbers that are used for more precise
decimal arithmetic such as financial applications. In the Ordinary fixed point type,
the distance between values is implemented as a power of 2. For example:
The type Batting_Averages is a fixed point type whose values are eve nly spaced
real numbers in the range from 0 through 1. The distance between the values is
no more than 1/1000. The actual distance between values may be 1/1024, which
is 2 -10.
The important difference in the definition of a decimal fixed point type from an
ordinary fixed point type is the specification of the number of digits of precision.
This example also shows how Ada allows you to specify numeric literals with
underscores separating groups of digits. The underscore is used to improve
readability.
Arrays
Like most other languages, Ada also supports arrays. One major difference
between the arrays in Ada and C is that the indexes of arrays in Ada do not start
from 0. In fact, the range of indexes to be used can be defined by the
programmer as shown below:
An array type can also be defined without a specific size. In this case the size is
defined at the time of instantiation of a variable of that type. For example:
Last_Name : String(1..20);
Another very interesting feature of Ada is that the array indexes can be of any
discrete type. For example if we define Days as below:
then we can create an array which uses Days (or any sub-range of Days) as the
array indexes as shown below.
Now the type Daily_Sales is an array type of size 7 and indexes Monday through
Sunday. Also note that these literals will be used as indexes in the statements
that reference array elements.
Record Definitions
Record types are like structures in C. The following example shows a record type
Address with three fields.
Once defined, it can be used to declare variables of that type as shown below:
My_Address : Address;
The dot operator, ‘.’, is used to access individual fields. This is demonstrated in
the example below:
My_Address.Postal_Code := “00000-0000”;
Discriminated Records
Discriminated records are like union types in C. There are however major
differences between C union types and Ada discriminated records. The union
type in C is fundamentally unsafe, and therefore unacceptable. For example,
consider the following definition:
Now puzzle has either an int or a float. But at runtime, the compiler and the
environment cannot tell which particular value has been stored currently. So we
have to trust the programmer. In Ada we are short on trust. The whole philosophy
is that a programmer is a human and all humans make mistakes. So to make it
safer, Ada uses discriminants in a record that tell what type of data is currently
stored there. This is shown in the following example:
Now the value of the discriminant V shows what type is currently present.
Variables of a discriminated type are referenced as shown in the following
example:
Puzzle : Int_Float;
…
Puzzle := (Float, 1.0);
F := Puzzle.Float_Val; -- OK
I := Puzzle.Int_Val; -- type mismatch - raise exception
…
Puzzle.V := SomeIntValue; -- not allowed!
subtype PuzzleI is puzzle (Int); -- this type only holds int values
These can also be used to specify array dimensions :
Subtype Vlen is Integer range 1 .. 10;
type Vstr (Vlen : Integer := 0) is record
Data : String (1 .. Vlen);
end record;
VV : Vstr := (5, “hello”);
Access Types
Note that, unlike C, there is no notational difference for accessing a record field
directly or through an access value.
To refer to the entire record accessed by an access value use the following
notation:
Print(A_Ref.all);
Statement Forms
Assignment statement
Like all imperative languages, Ada also supports the assignment sta tement.
However, in Ada the assignment is not an expression like C. The syntax of the
assignment statement is as follows:
Variable := expression;
Note that, in Ada, ‘:=’ is used as the assignment operator whereas ‘=’ is used as
assignment operator in C.
If Statement
The Ada if statement is fully blocked. In fact, all Ada control structures are fully
blocked. That means, we do not have two separate forms if we need only one
statement to be executed if the condition for the if statement is true and if we
want more than one statements. The body of the if statements is always in side a
a complete block that starts with the then keyword and end with end if as shown
below:
if condition then
-- statement(s)
end if;
If an if statement has multiple else parts with separate conditions, then Ada uses
the keyword elsif to indicate that. The else part is optional and comes at the end.
Each if statement must have a corresponding end if in it. The following examples
demonstrate this concept.
if condition1 then
-- statement(s)
elsif condition2 then
if condition3 then
-- statements
end if;
-- statement(s)
…
else
-- statement(s)
end if;
if condition1 then
-- statements
elsif condition2 then
if condition3 then
-- statements
end if;
-- statements
…
else if condition4 then
-- this is a new if statement and hence must have its own end if
-- statements
end if;
-- statements
end if;
Case Statements
case expression is
when choice list =>
sequence-of-statements
when choice list =>
sequence-of-statements
when others =>
sequence-of-statements
end case;
case TODAY is
when MON .. THU =>
WORK;
when FRI =>
WORK; PARTY;
when SAT | SUN =>
REST;
end case;
All values in when branches must be static and all possible values of expression
must be included exactly once. In Ada, the case expression must match one of
the choices given in the when clause as an exception will be raised as run time if
there is no match. when others => is like default in C and is used to cover all
the rest of the choices not mentioned in the above when clauses.
Looping
Simple Loop
A simple loop is used to signify a potentially infinite loop. These loops are
typically used in operating systems and embedded systems. Its syntax is as
follows:
loop
-- Loop body goes here
end loop;
The exit statement can be used to come out of the loop as shown below.
loop
-- Loop body goes here
exit when condition;
end loop;
loop
-- Loop body goes here
if condition then
exit;
end if;
end loop;
The exit statement is like the break statement in C but there are certain
differences and will be discussed later.
Ada has only the pre-test while loop and does not support the post-test loop like
the do-while statement in C. The while statement in Ada has the following
structure.
The semantics of the while statement are exactly the same as its counterpart in
C.
The for statement in Ada is however quite different here. In C, the for statement
is virtually the same as the while statement as the condition in the C for
statement is checked in each iteration and the number of iterations therefore
cannot be determined upfront.
In Ada for statement, the number of iterations are fixed the first time the control
hits the for statement and is specified by a range just like the choice_list in the
case statement as shown below:
The value of the loop variable can be used but cannot be changed inside the
loop body. The loop counting can be done in the reverse order as well. This is
shown below.
Exit statement
The exit statement can be used with our without a when condition as mentioned
in the case of the loop statement.
exit;
exit when condition;
It can only be used in a loop. It can use labels and can be used to specify the
specific loop to exit as shown below.
Outer : loop
Inner : loop
…
exit Inner when Done;
end loop Inner;
end loop Outer;
Block Statement
Return statement
The return statement can only be used in subprograms and has the following
form:
return; -- procedure
return expression; -- function
Raise statement
Raise statement is like throw statement in C++ and is used to raise exception as
shown below:
raise exception-name;
Declaring an exception
Exceptions are declared just like any other variable before they can be raised.
This is shown in the following example:
Raising an exception
Like throw in C++, an Ada programmer can explicitly raise an exception and it
strips stack frames till a handler is found.
raise Disaster;
Handling an exception
Like C++, an exception handling code may be written at the end of a block.
begin
statements
exception
when exception1 => statements;
when exception2 => statements;
end;
Subprograms
In Ada, there are two types of subprograms: procedures and functions. Unlike C,
we can also have nesting of subprograms. A subprogram defined inside another
subprogram an be used by its parent, children, or sibling subprograms only.
Packages
The primary structure used for encapsulation in Ada is called a package.
Packages are used to group data and subprograms. Packages can be
hierarchical, allowing a structured and extensible relationship for data and code.
All the standard Ada libraries are defined within packages.
package STACK is
procedure PUSH (x : INTEGER);
function POP return INTEGER;
end STACK;
Tagged Type
A tagged type is like a record which can be used to declare objects. Following is
an example of a tagged type:
In this example, type Employee inherits all the fields and primitive operations of
type Person.
Generics
Generics are like templates in C++ and allow parameterization of subprograms
and packages with parameters which can be types and subprograms as well as
values and objects. The following example elaborates the concept of generics.
generic
MAX : positive;
type item is private;
package STACK is
procedure PUSH (x : item);
function POP return item;
end STACK;
Note that the type of the item is left unspecified. The corresponding body of
STACK package is as follows:
Once we have the generic definition, we can instantiate our own STACK for the
given type which is integer in the following example.
declare
package myStack is new STACK(100, integer);
use myStack;
begin
…
push (i);
…
O := pop;
…
end;
Concurrency
Ada Tasking allows the initiation of concurrent tasks which i nitiates several
parallel activities which cooperate as needed. Its syntax is similar to packages as
shown below:
task thisTask is
…-- interfaces
end thisTask;
task simpleTask; -- this task does not provide an interface to other tasks
procedure COOKING is
begin
cookMeat;
cookRice;
cookPudding;
end COOKING;
As these steps can be carried out in parallel, we define tasks for these tasks as
shown below:
procedure COOKING is
task cookMeat;
task body cookMeat is
begin
-- follow instructions for cooking meat
end cookMeat;
task cookRice;
task body cookRice is
begin
-- follow instructions for cooking rice
end cookRice;
begin
cookPudding;
end COOKING;
Other Features
Ada is a HUGE language and we have looked at may be only 25-30% of this
language. It is to be remembered that the main objective of the Ada design was
to incorporate the contemporary software engineering knowledge in it. In general,
software development time is: 10% design, 10% coding, 60% debug and 20%
test. Last 80% of the project is spent trying to find and eliminate mistakes made
in the first 20% of the project. Therefore Ada promised to spend 20% time in
design, 60% in coding, 10% in debug, and 10% in testing. Therefore cutting the
entire cycle time in half!
When Roman engineers built a bridge, they had to stand under it while the
first legion marched across. If programmers today worked under similar
ground rules, they might well find themselves getting much more
interested in Ada.