Large scale project DoD in to design a language for reliable software. Commissioned in late 70's and early 80's. Specifications completed in 1983. First validated Ada compiler was developed at NYU under Profs. Robert Dewar and Ed Schonberg. Written in SETL and ran as slow as mud. Major extensions in 1995 (Ada-95).

Distinguishing Features

Examples: Hello World

Hello World
Hello World 1 2 3

Example: Stack abstract data type Stack Package Declaration
adt_stack.adb: Stack Package Definition
adt_main.adb: Stack Package Definition

Features to note:

Control structures and expressions


Static, strong typing.

Scalar types

Numeric types, Enumeration types, Booleans.

User defined types


A: array (Integer range 1 .. 6) of Float;
A: array (1 .. 6) of Float;
A'First=1, A'Last=6, A'Length=6, A'Range = 1..6. Array types:
type ThreeDVector is array(1 .. 3) of Float
Unconstrained array type:
type Vector is array(Integer range < >) of Float;


type Person is record First, Last: String; Birth: Integer end record;

Discriminated record types (variant records)

type ItemCat is (Book, Article, MS);
type BibRecord(Category: ItemCat)
   record Author, Title: string;
       case Category is
         when Book => year: Integer,
                      publisher: String;
         when Article => year, vol, pStart, pEnd: Integer;
                         journal: String;
        end case;
     end record;
Can only accesss B.pStart if B.Category = Article.
If you change B.Category, it wipes out all the variant fields.

Pointers and dynamic objects

type PersonPtr is access Person;
PP : PersonPtr;
PP := new Person; -- allocated from stack, returns pointer.

As of Ada-95, it is possible to create pointers to a stack object, but the lifetime of the object must be greater than the lifetime of the pointer. Usually a static check; sometimes a dynamic check.

Lots of other pointer mechanisms and notations.

Garbage collection is optional -- up to implementation. User deallocation is supported.



Package specification contains declarations of the externally visible parts of the package. The package body contains the private elements and the bodies of the functions.

Package specifications can be top-level or imbedded in the declaration of another package or a subprogram.

Types can be:

Import package with "use packageName"


The exception handler for a procedure follows the body of the procedure.
function ...
   body of function
exception when ExceptionName => Action
               ExceptionName => Action
               others => Action
User-defined exceptions are raised using "raise ExceptionName".

A standard library provides functionalities for passing more information from the raiser to the catcher.

Passing functions as parameters

Not supported in Ada-83, but added in Ada-95. (I didn't discuss this in earlier lectures, so it won't be on the exam.) E.g.
-- Define type pRealFloat as a pointer to a function from Float to Float
type pRealFun is access function(X: Float) return Float;

function integrate(F: pRealFun; L,U: Float, N: Integer) return Float is
   begin ...
           Sum := Sum + F(X)*Delta;    -- Call of function referenced by F;

function square(X: Float) return Float is begin return X*X end;

integrate(square'Access, -- creates pointer to function square
          0.0, 10.0 100)


A generic parameter may be a type, a subprogram, or a package. ask about generic types on the exam.

Generic type and function

  type Item is private;
  type ItemArray is array(Integer range < >) of Item;
  with function f(X: Item) return Item;
  procedure ArrayApplier (A,B: in out ItemArray) is
     begin for I in A'Range loop
             B[I] := f(A[I]);
           end loop

function square(X: Float) return Float is begin return X*X end;

type FArray is array(Integer range < >) of Float;

function ApplySquare is new ArrayApplier(Float,FArray,square);
Works essentially like a structured macro: with each instance of the generic that is created, the compiler essentially copies the source code and compiles it into a separate function. (Most generics work this way; the major exception is Java.)


A thread is called a "task" in Ada.

Tasks can be individual or instances of a task type.

Individual task:

task Name;
task body Name is begin ... end 
Individual tasks begin when program execution begins.

Task types:

type task TaskName; -- Declaration
task body Name is begin ... end -- Body
type TArray is array(< >) of TaskName;
type PTask is access TaskName;

procedure foo is
N1, N2 : TaskName;
TA : TArray(1..10);
PT : PTask;

begin  -- N1, N2, TA start running on entering begin.
   PT = new Ptask;  -- PT starts running now

Synchronization: Rendezvous and Protection


One thread is the caller (C) and one thread is the acceptor (A).

From the point of view of A: When A reaches an accept entry point, it halts until some caller C calls that entry point. The in parameters are received; the body of the accept is executed; the out parameters are returned to C; and then A continues executing.

From the point of view of C: When C calls an entry point of task A, it posts the in parameters, and then goes to sleep. When A is ready to accept the call, the run-time system delivers the parameters, and A executes its body, and returns the out parameters. Then C wakes up and continues execution.

Calling syntax in C: A.E(actual parameters);
Accepting syntax in A: Entry points are declared at the start of A.

accept E(formal parameters) do ... body of E ... end E.
Note that C has to know about A but A does not have to know about C (like a procedure call.)


Various mechanisms for achieving mutual exclusion on code or mutually exclusive access to objects. More or less analogous to the Java mechanism. I won't ask about it.

Object orientation

Added in Ada-95. Usual stuff: Class = type. Derived types, method overriding, dynamic dispatching (the default), various modes of multiple inheritance. I won't ask about it.