Ada is a modern programming language designed for large, long-lived applications – and embedded systems in particular – where reliability and efficiency are essential. It was originally developed in the early 1980s (this version is generally known as Ada 83) by a team led by Dr. Jean Ichbiah at CII-Honeywell-Bull in France. The language was revised and enhanced in an upward compatible fashion in the early 1990s, under the leadership of Mr. Tucker Taft from Intermetrics in the U.S. The resulting language, Ada 95, was the first internationally standardized (ISO) Object-Oriented Language. Under the auspices of ISO, a further (minor) revision was completed as an amendment to the standard; this version of the language is known as Ada 2005. Work is currently in progress on some additional features (including support for program anotations) and is expected to be completed in 2012.
The name “Ada” is not an acronym; it was chosen in honor of Augusta Ada Lovelace (1815-1852), a mathematician who is sometimes regarded as the world’s first programmer because of her work with Charles Babbage. She was also the daughter of the poet Lord Byron.
Ada is seeing significant usage worldwide in high-integrity / safety-critical / high-security domains including commercial and military aircraft avionics, air traffic control, railroad systems, and medical devices. With its embodiment of modern software engineering principles Ada is an excellent teaching language for both introductory and advanced computer science courses, and it has been the subject of significant university research especially in the area of real-time technologies.
AdaCore has a long history and close connection with the Ada programming language. Company members worked on the original Ada 83 design and review, played key roles in the Ada 95 project and Ada 2005 effort, and continue to be deeply involved with the Ada 2012 revision process. The initial GNAT compiler was essential to the growth of Ada 95; it was delivered at the time of the language’s standardization, thus guaranteeing that users would have a quality implementation for transitioning to Ada 95 from Ada 83 or other languages.
Ada is multi-faceted. From one perspective it is a classical stack-based general-purpose language, not tied to any specific development methodology. It has a simple syntax, structured control statements, flexible data composition facilities, strong type checking, traditional features for code modularization (“subprograms”), and a mechanism for detecting and responding to exceptional run-time conditions (“exception handling”).
But it also includes much more:
Unlike languages based on C syntax (such as C++, Java, and C#), Ada allows the programmer to simply and explicitly specify the range of values that are permitted for variables of scalar types (integer, floating-point, fixed-point, or enumeration types). The attempted assignment of an out-of-range value causes a run-time error. The ability to specify range contraints makes programmer intent explicit and makes it easier to detect a major source of coding and user input errors.
Programming in the large
The original Ada 83 design introduced the package construct, a feature that supports encapsulation (“information hiding”) and modularization, and that allows the developer to control the namespace that is accessible within a given compilation unit. Ada 95 introduced the concept of “child units,” adding considerably flexibility and easing the design of very large systems. Ada 2005 extended the language’s modularization facilities by allowing mutual references between package specifications, thus making it easier to interface with languages such as Java.
A key to reusable components is a mechanism for parameterizing modules with respect to data types and other program entities, for example a stack package for an arbitrary element type. Ada meets this requirement through a facility known as “generics”; since the parameterization is done at compile time, run-time performance is not penalized.
Object-Oriented Programming (OOP)
Ada 83 was object-based, allowing the partitioning of a system into modules corresponding to abstract data types or abstract objects. Full OOP support was not provided since, first, it seemed not to be required in the real-time domain that was Ada’s primary target, and, second, the apparent need for automatic garbage collection in an OO language would have interfered with predictable and efficient performance.
However, large real-time systems often have components such as GUIs that do not have real-time constraints and that could be most effectively developed using OOP features. In part for this reason, Ada 95 supplies comprehensive support for OOP, through its “tagged type” facility: classes, polymorphism, inheritance, and dynamic binding. Ada 95 does not require automatic garbage collection but rather supplies definitional features allowing the developer to supply type-specific storage reclamation operations (“finalization”). Ada 2005 provided additional OOP features including Java-like interfaces and traditional operation invocation notation.
Ada is methologically neutral and does not impose a “distributed overhead” for OOP. If an application does not need OOP, then the OOP features do not have to be used, and there is no run-time penalty.
Ada supplies a structured, high-level facility for concurrency. The unit of concurrency is a program entity known as a “task.” Tasks can communicate implicitly via shared data or explicitly via a synchronous control mechanism known as the rendezvous. A shared data item can be defined abstractly as a “protected object” (a feature introduced in Ada 95), with operations executed under mutual exclusion when invoked from multiple tasks. Asynchronous task interactions are also supported, specifically timeouts and task termination. Such asynchronous behavior is deferred during certain operations, to prevent the possibility of leaving shared data in an inconsistent state. Mechanisms designed to help take advantage of multi-core architectures are being introduced in Ada 2012.
Both in the “core” language and the Systems Programming Annex, Ada supplies the necessary features to allow the programmer to get close to the hardware. For example, you can specify the bit layout for fields in a record, define the alignment and size, place data at specific machine addresses, and express specialized or time-critical code sequences in assembly language. You can also write interrupt handlers in Ada, using the protected type facility.
Ada’s tasking features allow you to express common real-time idioms (periodic tasks, event-driven tasks), and the Real-Time Annex provides several facilities that allow you to avoid unbounded priority inversions. A protected object locking policy is defined that uses priority ceilings; this has an especially efficient implementation in Ada (mutexes are not required) since protected operations are not allowed to block. Ada 95 defined a task dispatching policy that basically requires tasks to run until blocked or preempted, and Ada 2005 introduced several others including Earliest Deadline First.
With its emphasis on sound software engineering principles Ada supports the development of high-integrity applications, including those that need to be certified against safety standards such as DO-178B and security standards such as the Common Criteria. For example, strong typing means that data intended for one purpose will not be accessed via inappropriate operations; errors such as treating pointers as integers (or vice versa) are prevented. And Ada’s array bounds checking prevents buffer overrun vulnerabilities that are common in C and C++.
However, the full language is inappropriate in a safety-critical application, since the generality and flexibility may interfere with traceability / certification requirements. Ada addresses this issue by supplying a compiler directive, pragma Restrictions, that allows you to constrain the language features to a well-defined subset (for example, excluding dynamic OOP facilities).
The evolution of Ada has seen the continued increase in support for safety-critical and high-security applications. Ada 2005 standardized the Ravenscar Profile, a collection of concurrency features that are powerful enough for real-time programming but simple enough to make certification practical. Ada 2012 is introducing annotation facilities for adding pre-conditions, post-conditions, and invariants to programs. These can serve both for run-time checking and as input to static analysis tools.
Ada Benefits Summary
- Helps you design safe and reliable code
- Reduces development costs
- Supports new and changing technologies
- Facilitates development of complex programs
- Helps make code readable and portable
- Reduces certification costs for safety-critical software
Ada Features Summary
- Object orientated programming
- Strong typing
- Abstractions to fit program domain
- Generic programming/templates
- Exception handling
- Facilities for modular organization of code
- Standard libraries for I/O, string handling, numeric computing, containers
- Systems programming
- Concurrent programming
- Real-time programming
- Distributed systems programming
- Numeric processing
- Interfaces to other languages (C, COBOL, Fortran)
In brief, Ada is an internationally standardized language combining object-oriented programming features, well-engineered concurrency facilities, real-time support, and built-in reliability. An appropriate tool for addressing the real issues facing software developers today, Ada is used throughout a number of major industries to design software that protects businesses and lives.