• No results found

Ada Distilled: An Introduction to Ada Programming - Free Computer, Programming, Mathematics, Technical Books, Lecture Notes and Tutorials

N/A
N/A
Protected

Academic year: 2020

Share "Ada Distilled: An Introduction to Ada Programming - Free Computer, Programming, Mathematics, Technical Books, Lecture Notes and Tutorials"

Copied!
113
0
0

Loading.... (view fulltext now)

Full text

(1)

Page 1 of 113

An Introduction to Ada Programming

for

Experienced Computer Programmers

by

Richard Riehle

AdaWorks Software Engineering

http://www.adaworks.com

Copyright 2002, AdaWorks Software Engineering

(2)

Page 2 of 113

Acknowledgments

There are always a lot of people involved in the creation of any book, even one as small and modest as this one. Those who have contributed to the best features of this book include my students at Naval Postgraduate School, Mr. Michael Berenato of Computer Sciences Corporation, Mr. Ed Colbert of Absolute Software, and many students from Lockheed-Martin Corporation, Computer Sciences Corporation, British Aerospace, various branches of the uniformed services, to name a few. I also owe a special thanks to Dr. Ben Brosgol, Dr. Robert Dewar, Mr. Mark Gerhardt, and Dr. Mantak Shing for what I have learned from them. Also thanks to the contributors to comp.lang.ada Usenet forum and the Team_Ada Listserve. Phil Thornley deserves extra credit for his detailed reading of the manuscript and many corrections.

Special thanks goes to Ed Colbert for his careful study of some of my program examples. He is one of those people who can spot a program error at fifty paces. Using this unique skill, Ed brought many errors, some big and some small, to my attention. Also thanks to more recent input from Phil Thornley and Adrian Hoe.

Any other errors are strictly mine. Any mistakes in wording, spelling, or facts are mine and mine alone.

I hope this book will be valuable to the intended audience. It is moderate in its intent: help the beginning Ada programmer get a good start with some useful examples of working code. More advanced books are listed in the bibliography. The serious student should also have one of those books at hand when starting in on a real project.

Richard Riehle

Intended Audience for this Book

This book is aimed at experienced programmers who want to learn Ada at the programming level. It is not a "...for dummies" book, nor is it intended as a program design book. Instead, we highlight some key features of the Ada language, with coded examples, that are essential for getting started as an Ada programmer.

Ada is a rich and flexibile language used for designing large-scale software systems. This book emphasizes syntax, control structures, subprogram rules, and how-to coding issues rather than design issues. There are other really fine books available that deal with design. Also, this is not a comprehensive treatment of the Ada language. The bibliography lists some books that can help you once you have finished the material in this book.

Think of this a quick-start book, one that enables you, the experienced programmer, to get into the Ada language quickly and easily. The examples use text-oriented programs for simplicity of learning. If you prefer to do the exercises for a GUI environment, check out the sites listed for compilers and tools so you can download bindings for programming in a variety of windowing environments, including Wintel, Linux, and Unix. Of particular interest to those wanting to explore Window style programming are GtkAda, CLAW, GWindows, and JEWL. The last of these, JEWL, is especially useful if you have no prior experience writing Windows programs.

Happy Coding,

(3)

Page 3 of 113

Table of Contents

TABLE OF CONTENTS... 3

1. WHAT IS ADA DISTILLED? ... 4

2. SUMMARY OF LANGUAGE ... 5

3. TYPES AND THE TYPE MODEL ... 16

4. CONTROL STRUCTURES FOR ALGORITHMS... 26

5. ACCESS TYPES (POINTERS) ... 33

6. SUBPROGRAMS... 40

7. PACKAGE DESIGN... 47

8. CHILD LIBRARY UNITS ... 52

9. OBJECT-ORIENTED PROGRAMMING WITH PACKAGES... 57

10. USING STANDARD LIBRARIES AND ANNEXES ... 64

11. EXCEPTION MANAGEMENT ... 71

12. GENERIC COMPONENTS... 74

13. NEW NAMES FROM OLD ONES ... 82

14. CONCURRENCY WITH TASKING... 87

A. ANNEXES, APPENDICES AND STANDARD LIBRARIES... 92

ANNEX L PRAGMAS - LANGUAGE-DEFINED COMPILER DIRECTIVES... 104

WINDOWS 95/98/NT/XP/ME/2000 PROGRAMMING ... 105

C. BIBLIOGRAPHY... 107

The Ada language is designed to maximize the possibilities for error detection early in the development process. This reduces the overall cost of software development since it is known that errors corrected early, will cost less than those detected late. No other language, not C++, not Java, not Eiffel, provides the level of support for safety-critical software found in Ada. Developers can and do make mistakes, even using Ada, but the probability of such mistakes is substantially less when using Ada than it is when using other languages. Therefore, when failure is not acceptable, during development or during software execution, the wise developer will select Ada. Although Ada is not as popular as some of the more well-known languages, it has substantial benefits over most of them when software dependability is a primary objective. In addition, contemporary Ada is as appropriate for developing GUI-based applications, information systems applications, and computationally intensive systems as any existing language. It is truly a general-purpose language, well-suited to any kind of software problem you might encounter.

(4)

Page 4 of 113

1. What is Ada Distilled?

This book is for experienced programmers new to Ada. Heavily commented example programs help experienced programmer experiment with Ada. This is not a comprehensive book on the entire Ada language. In particular, we say very little about Ada.Finalization, Storage Pool Management,

Representation Specifications, Concurrency, and other more advanced topics. Other books, listed in the bibliography, cover advanced topics. This book is an entry point to your study of Ada.

The text is organized around example programs with line-by-line comments. Ada comments are the double-hyphen and continue to the end of a line. Comments might be explanatory notes and/or

corresponding section of the Ada Language Reference Manual (ALRM) in the format of ALRM X.5.3/22.

with Ada.Text_IO; -- 1 10.1.2, A.10 Context clause procedure Hello is -- 2 6.3 Specification with "is"

begin -- 3 6.3 Start algorithmic code

Ada.Text_IO.Put_Line(“Hello Ada”); -- 4 A.10.6 Executable source code end Hello; -- 5 6.3 End of procedure scope

where each line is numbered. The 10.1.2 and 6.3, etc. refer to ALRM Chapters 6.3, 10.1.2. A.10.6 refers to Annex A.10.6. There is occasional commentary by source code line number. The line numbers are not part of Ada, but provided on our examples for ease of commentary. Boxed notes are also included for some examples. The preceding example shows one of these as:

1.1 Ada Compilers and Tools

Ada 95 compilers support a wide range of platforms. A free, open source, compiler, GNAT, based on GNU technology, can be downloaded from the Web. Commercial Ada compilers and tools are available from: Ada Core Technologies (GNAT), DDC-I, Rational (recently acquired by IBM), RR Software, Irvine Compiler Corporation, Green Hills, SofCheck, Aonix, and OC Systems. Free editors, including AdaGide, are useful for developing small Ada programs. More information on tools, including GUI development tools, can be accessed using one of the URL's mentioned in the introduction and in the bibliography. Development tools exist for many operating systems. These include CLAW for Microsoft Operating Systems, and GtkAda for other GUI environments including Microsoft operating systems, Linux, BSD, OS/2, Java Virtual Machine, and every variety of Unix. The AdaGide editor is available for MS Windows.

1.2 Ada Education

The bibliography of this book lists some of the books and educational resources available to the student of Ada. Some colleges and universities offer Ada courses. In addition, companies such as AdaWorks Software Engineering provide classes for anyone interested in Ada software development.

1.3 Ada Software Practice

There is a lot of misinformation about Ada. One misconception is that it is a large, bloated language designed by committee. This is not true. Ada is designed around a few simple principles that provide the architecture for the language syntax and semantics. Once you understand these principles, Ada will be as easy as many other languages. We highlight some of those design principles in this book. One important principle is that the Ada compiler never assumes anything. Everything is explicit. Nothing in Ada is implicit. This helps the compiler help you write more dependable code. Oh, and you'll rarely need the debugger once you are experienced with Ada. Also, your Ada programs will usually compile to nearly any contemporary platform and execute on that platform without change.

A hello program in Ada.

This will compile and execute with any Ada compiler.

(5)

Page 5 of 113

2. Summary of Language

2.1 Goals and Philosophy

Every programming language is intended to satisfy some purpose, some set of goals. Sometimes the goals are stated in terms of a programming paradigm. For example, a goal might be to design an object-oriented programming language. Another goal might call for a language that conforms to some existing

programming model with extensions to satisfy some new notions of programming techniques. Ada's goals correspond to the final product of the software process. Ada is not designed to satisfy an academic notion of how programs should be designed and written. Ada's Goals are:

High reliability and dependability for safety-critical environments,

Maintainable over a long span by someone who has never seen the code before,

Emphasis on program readability instead of program writeability,

Capability for efficient software development using reusable components

In summary, Ada is designed to maximize the error checking a compiler can do early in the development process. Each syntactic construct is intended to help the compiler meet this goal. This means some Ada syntax may initially seem extraneous but has an important role in alerting the compiler to potential errors in your code. The default for every Ada construct is safe. Ada allows you to relax that default when

necessary. Contrast Ada's default of safe with most of the C family of languages where the default is usually, unsafe. The safety default is one of Ada's most important contributions to engineering software.

Another important idea is expressiveness over expressibility. Nearly any idea can be expressed in any programming language. That is not good enough. Ada puts emphasis on expressiveness, not just expressibility. In Ada, we map the solution to the problem rather than the problem to the solution.

2.2 Elementary Syntax

2.2.1 Identifiers

Identifiers in Ada are not case sensitive. The identifiers Niacin, NIACIN, NiAcIn will be interpreted by the compiler as the same. Underbars are common in Ada source code identifiers; e.g. Down_The_Hatch. There is a worldwide shortage of curly braces. Consequently, Ada does not use { and }. Also, Ada does not use square braces such as [ and ] . Ada has sixty-nine reserved words. Reserved words will usually be shown in bold-face type in this book. (See Appendix A for a complete list of reserved words).

2.2.2 Statements, Scope Resolution, Visibility

An Ada statement is terminated with a semicolon. The entire scope of a statement is contained within the start of that statement and the corresponding semicolon. Compound statements are permitted. A

compound statement has an explicit end of scope clause. A statement may be a subprogram call, a simple expression, or an assignment statement. Here are some sample statements:

X := C * (A + B); -- 1 Simple assignment statement

Move (X , Y); -- 2 A procedure call statement

if A = B then -- 3 Start a compound if statement

J := Ada.Numerics.Pi * Diameter; -- 4 Compute the circumference of a circle

else -- 5 Part of compound if statement

J := Ada.Numerics.Pi * Radius ** 2; -- 6 Compute area of a circle

end if; -- 7 End of compound statement scope

if (A and B) or ((X and T) and (P or Q)) then -- 8 Parentheses required in mixed and/or construct

Compute(A); -- 9 Call Compute subprogram

else -- 10 Part of compound statement

Compute(P); -- 11 Subprogram call statement

end if; -- 12 End of compound statement scope

Ada is not an acronym. It is the name of the daughter of the English Poet, Lord Byron. She is credited with being the "first computer programmer" because of the prescience demonstrated in her early writings that described Charles Babbage's Analytical Engine. She was honored for this contribution by having a language named after her.

The syntax of Ada is actually easy to learn and use. It is only when you get further in your study that you will discover its full power. Just as there is "no royal road to mathematics," there is no royal road to software engineering. Ada can help, but much of programming still requires diligent study and practice.

Ada's unique idea of visibility often causes difficulties for new Ada programmers. Once you understand visibility, nearly everything else about Ada will be clear to you.

Yes, you can hack solutions in Ada if you want. However, it is intended as a language for disciplined design and construction of high reliability software.

(6)

Page 6 of 113

Note on Line 8 that an Ada conditional statement cannot mix and and or unless the expression includes parentheses. This eliminates problems associated with such expressions. It also eliminates arguments about precedence of mixed expressions, and errors due to incorrect assumptions about precedence.

2.2.3 Methods (Operators and Operations)

Methods in Ada are subprograms (procedures/functions) and include both operators and operations. Operators include the symbols: =, /=, <, >, <=, >=, &, +, -, /, *. Other operators are the reserved words, and, or, xor, not, abs, rem, mod. One issue that annoys newcomers to Ada is the strictness of the

visibility rules associated with operators. We will discuss the visibility rules and techniques for using them sensibly in Section 2.4 and elsewhere in this book. For detailed operator rules, see ALRM 4.5.

All other methods are called operations. One operation, assignment uses the compound symbol: := . The Ada programmer may not directly overload the assignment operation. Assignment is predefined for most Ada types. It is prohibited for limited types. We describe limited types later in this book.

The Ada programmer may declare type-specific methods. An experienced Ada designer uses the package specification for declaring such methods, and for overriding/overloading existing methods.

The membership test, not considered an operation by the language, has important method-like properties. Membership test uses the reserved word in. Combine the word in with the word not (not in) for a negative membership test. Membership testing is permitted for every Ada type, including limited types.

2.3 Library and Compilation Units

2.3.1 Library Units

An Ada program is composed of library units. A library unit is a unit that can be referred to using a with

clause. The technical name for the with clause is context clause. A context clause is a little like a #include

compiler directive in other languages, but with important differences. A library unit must successfully compile before the compiler will recognize it in a context clause. Each compiled unit is placed in a [sometimes virtual] library. Unlike a #include , the context clause does not make elements of a library unit visible. Instead, a context clause simply puts the library unit in scope, making it potentially visible.

A library unit may be a package or a subprogram. Subprograms are either functions or procedures.

1) package A collection of resources with something in common, usually a data type.

2) procedure A simple executable series of declarations and associated algorithmic code.

3) function An executable entity which always returns a data type result.

4) child unit A package, procedure, or function that is a child of a package.

An Ada library unit consists of a specification part and implementation part. The implementation is sometimes called a body. For a subprogram the specification part could be coded as,

procedure Open (F : in out File); -- Procedure specification; requires body.

function Is_Open (F : File) return Boolean; -- Function specification; requires body

A package is a collection of services (public and private), usually related through some data type. Most Ada library units will be packages. A package specification includes type declarations, subprograms (procedures and functions), and exceptions. Also, a package usually consists of a specification part (public and private) and an implementation part. The implementation part of a package is called the package body. A package specification almost always (not always) requires a package body.

A single library unit may be composed of more than one compilation unit. This is called separate compilation. Ada ensures that separately compiled units preserve their continuity in relationship to related units. That is, date and time checking, library name resolution, and date and time checking of compiled units ensures every unit is always in phase with every other related complation and library unit

C/C++ programmer note: An Ada subprogram specification is analogous to, but not identical to, a function prototype.

See 4.2.2

(7)

Page 7 of 113

Here is a typical specification for a package library unit. The specification has two parts, public and private. A client of a package can access only specification's public part, not its private part.

packageMachinery_1_3 is -- 1 Package specification; requires body type Machine is private; -- 2 Specifies the visible part of the data type; procedure Turn_On (M : in out Machine); -- 3 procedure specification

procedure Turn_Off (M : in out Machine); -- 4 procedure specification function Is_On (M : in Machine) return Boolean; -- 5 function specification

private -- 6 private part hidden from a client of contract

type Machine is record -- 7 full definition of the publicly declared type Turned_On : Boolean := False; -- 8 component of the type; OOP attribute

end record; -- 9 scope terminator for the component

end Machinery_1_3; -- 10 scope terminator for the specification

Here is a possible package body, which implements the specification. It is separately compiled.

package bodyMachinery_1_3 is -- 1 Package body; implements specification declarations procedure Turn_On (M : in out Machine) is -- 2 Repeat procedure specification; compiler checks this

begin -- 3 Starts algorithmic section of procedure

M.Turned_ON := True; -- 4 Simple assignment statement of boolean value

endTurn_On; -- 5 Procedure scope terminator is required

procedure Turn_Off (M : in out Machine) is -- 6 Must match profile in specification

begin -- 7 Algorithms between begin and end

M.Turned_On := False; -- 8 M.Turned called dot notation

end Turn_Off; -- 9 Name is optional but end is required

function Is_On (M : in Machine) return Boolean is -- 10 In mode is like a constant; it may

begin -- 11 not be on left side of assignment

returnM.Turned_On; -- 12 return statement required of every function

endIs_On; -- 13 Scope terminator for function

end Machinery_1_3; -- 14 End of all declarations for this package

Most often, the specification and the body are compiled separately. A specification must compile without errors before its body can be compiled. The Ada compiler will issue a fatal error if the body is out of phase with the specification. A programmer creating a client of the package, can only see the public part of the specification. The specification is a contract with a client of the package. The contract must be sufficient for the client to engage the promised services. Every declaration in the specification must conform, exactly, to the code in the body. The Ada compiler detects non-conformance to ensure consistency over the lifetime of the whole library unit. A change to a specification requires recompilation of the body. A change to the body does not require recompilation of the specification. Consider this client subprogram:

with Machinery_1_3; -- 1 Context clause. Puts Machinery_1_3 in scope

procedure Test_Machinery_1_3 is -- 2 Specifxication for the procedure

Widget : Machinery_1_3.Machine; -- 3 Local object of type Machine

begin -- 4 Starts the algorithmic section of this procedure

Machinery_1_3.Turn_On (M => Widget); -- 5 Call the Turn_On using dot notation and named association Machinery_1_3.Turn_Off (M => Widget); -- 6 Call the Turn_On using dot notation and named association end Test_Machinery_1_3; -- 7 Scope of subprogram terminates with the end clause

A client of the package, such as Test_Machinery_1_3, never has visibility to the private part or the body of the package. Its only v iew is to the public part. However, the entire package is in scope, including the body. The body is completely hidden from all views from outside the package even though it in scope.

Public part

Private part

Body

(8)

Page 8 of 113

2.3.2 Compilation Units

As noted earlier, library units can be composed of smaller units called compilation units. The library unit is the full entity referenced in a context clause. An Ada package, as a library unit, is usually compiled as two compilation units: package specification and package body. Do not think of a package specification as a C++ .h file. The Ada rules are more rigorous than those for C++ .h files. The package body does not need to with its own specification. A package body can be further subdivided into even smaller

compilation units called subunits. Subunits, used wisely, benefit the maintenance cycle of existing Ada programs.

The specification of Machinery_1_3 in the previous section can be compiled by itself. Later, the package body can be compiled. The procedure Test_Machinery_1_3 may be compiled before the package body of Machinery_1_3. The test program cannot be linked until all separately compiled units are compiled.

The package body for Machinery_1_3 could have been coded for separate compilation as,

packagebodyMachinery_1_3 is -- 1

procedure Turn_On (M : in out Machine) is separate; -- 2 procedure Turn_Off (M : in out Machine) is separate; -- 3

function Is_On (M : in Machine) -- 4

return Boolean isseparate; -- 5

end Machinery_1_3; -- 6

Compilation units in most Ada programs will be a package specification and package body. Sometimes, as in lines 2, 3, 5, you may see a subprogram specification compiled with the word separate instead of an ... is ... end implementation. This implies separate compilation of the body for that subprogram.

Ada does not force separate compilation, but some Ada compilers do. An implementation is free to impose this requirement. The standards for most Ada development shops also require separate compilation.

An Ada package may have child library units. A package, such as package Machinery, may be the root of a tree of child library units. This provides a unique opportunity for separate compilation and extension.

Here is an example of parent-child library units.

packageMessenger is -- 1 Package specification; requires body

type Message is private; -- 2 Visible part of the data type; name only function Create (S : String) return Message; -- 3 function specification

procedure Send (M in Message); -- 4 procedure specification procedure Receive (M : out Message); -- 5 procedure specification function Size (M : in Message) return Natural; -- 6 function specification

private -- 7 private part hidden from a client of contract

type Message is record -- 8 full definition of the publicly declared type Text : String (1..120) := (others => ' '); -- 9 string component of the type; OOP attribute Length : Natural := 0; -- 10 how many of the 120 values are in use

end record; -- 11 scope terminator for the component

end Messenger; -- 12 scope terminator for the specification

with Ada.Calendar;

packageMessenger.Dated is -- 1 Package specification; requires body type Dated_Message is private; -- 2 Visible part of the data type; name only function Create (M : in Message) -- 3 function specification

return Dated_Message; -- 4 function always specifies a return type

private -- 5 private part hidden from a client of contract

type Dated_Message is record -- 6 full definition of the publicly declared type

Text : Message; -- 7 string component of the type; OOP attribute

Date : Ada.Calendar.Time; -- 8 how many of the 120 values are in use

end record; -- 9 scope terminator for the component

end Messenger.Dated; -- 10 scope terminator for the specification

A subprogram declared is separate places a subunit in the library. The subunit may have its own context clauses, its own local variables, and its own algorithmic code. Also, each subunit may be compiled independently once its parent has been successfully compiled. This means easier, faster maintenance and better unit testing. During development, each subunit can be assigned to a different programmer

Parent Library Unit

Child Library

Unit See Chapter 8 for more on child library units.

(9)

Page 9 of 113

At first, a child library unit might be mistaken as a form of inheritance. The experienced OOP practitioner will see that it is not inheritance; the is_a is relationship is absent. Rather, it allows one to extend the original package and add more features. The declarative region for Messenger has been extended to include the declarations of Messenger.Dated. Any client of Messenger.Dated has direct visibility to the public declarations of Messenger. The private part of Messenger.Dated and the body of Messenger.Dated has direct visibility to the private and public parts of Messenger.

Dated_Message is implemented is a has_a relationship. This means that Dated_Message contains a value of type Message. Dated_Message cannot be converted to an object of type Message. They are two distinct types, even though one is nested within another.

2.4 Scope and Visibility

Failure to understand the difference between scope and visibility causes more problems for new Ada programmers than any other single topic. It is an idea central to the design of all Ada software. There is an entire ALRM chapter devoted to it, Chapter 8. A with clause puts a library unit into scope; but none of the resources of that unit are directly visible to a client. This is different from a #include in the C family of languages. Separating scope from visibility is an important software engineering concept. It is seldom designed into other programming languages. This book has many coded examples that illustrate visibility rules. Ada has several techniques for making in-scope elements directly visible.

2.4.1 Scope

Every Ada statement has an enclosing scope. Sometimes the scope is easy to see in the source code. There is an entry point (declare, subprogram identifier, composite type identifier, package identifier, etc.) and an explicit point of termination. Explicit terminations are coded with an end statement. Anytime you see an end clause, you know it is closing a scope. Scope can be nested. For example, a procedure may be declared inside another procedure. The scope of context clause (with clause) is not as obvious. The context clause puts the full resources of a library unit in scope, but makes none directly visible.

A pure interpretation of the scope mechanism might better describe this in terms of a declarative region. However, since this book is intended as an introduction to the practical aspects of the Ada, we limit our discussion to a more pragmatic view of the visibility mechanism. For a more rigorous description, please consult the Ada LRM, Chapter 8.

A with (context) clause implies a dependency on the library unit named in that clause. This dependency can be at either the specification level of the withing library unit or deferred to the body of that unit.

2.4.2 Visibility

An entity may be in scope but not directly visibile. This concept is better developed in Ada than in most programming languages. Throughout Ada Distilled you will see visibility examples such as:

use clauses makes all public resources of a package directly visible

use type clauses makes public operators directly visible for designated type

entity dot notation entity in notation is directly visible; usually the best option

renaming , locally, of operations/operators usually best option for making operators directly visible

During development, an Ada compiler error message may advise you that some entity is not visible at the point where it is declared or used. Most often a visibility problem will relate to

operators (2.7). One of the mechanisms from the above list can make that entity visible. It will be easier to demonstrate visibility in the code examples than to trudge through a tedious jungle of prose. Watch for uses of the visibility mechanisms above in our coded examples.

Some programmers find the concept of visibility more difficult than any other part of Ada. Once they really understand visibility, everything else in language makes sense.

NOTE: ISO Standard C++

namespace adopts a weakened form of Ada's scope and visibility model.

Understanding visibility is the key to understanding Ada. Important

(10)

Page 10 of 113

2.5 Declarations, Elaboration, Dependencies

Most Ada software systems are composed of many independent components, most in the form of packages. These packages are associated with each other through context clauses (i.e., with clause).

Notice that dependencies between library units can be deferred to the package body. This unique feature of Ada is based on the integral nature of library units and takes advantage of the separate compilation capability. Ada gives us the best of both capabilities. We can minimize the design dependencies by declaring context clauses for the package body instead for the package specification. This eliminates the need to re-compile (or re-examine) the relationships each time we make a change somewhere in our design.

An Ada program includes declarations and executable statements. A package specification is a set of declarations. The package body may also contain localized declarations. The scope of the declarations can be thought of as a declarative region. In the declarative region, declarations are in scope but not necessarily visible. Declarations in a package body are in the declarative region, but are not visible to a client or child library unit.

2.5.1 Elaboration

Declarations must be elaborated before the program can begin its algorithmic part. Elaboration is the set of actions a program must complete before it can begin its algorithmic actions. It usually takes place without action by the programmer. Ada does provide some pragmas (compiler directives) for control over the timing and order of elaboration. Usually, elaboration occurs at execution time. A programmer may specify compile-time elaboration through pragma Preelaborate or pragma Pure. If that compile-time elaboration is possible, it may occur according to the semantics of each pragma.

Library units named in a context (with) clause must be elaborated before they are actually available to a client. When there are multiple context clauses, each must be elaborated. In some circumstances, resources of one library unit must finish elaborating before another library unit complete its elaboration.

2.5.2 Ada Comb

An Ada program unit may sometimes be viewed in terms of the "Ada Comb," an idea first introduced to me years ago by Mr. Mark Gerhardt. The Ada Comb demonstrates how declarations and algorithms are related within an implementation; i.e, subprogram body, task body, declare block, package body, etc.

kind-of-unit unit-name -- 1 procedure, function, package body, declare block, etc.

local declarations -- 2 Must be elaborated prior to begin statement

begin -- 3 Elaboration is done. Now start executing statements handled-sequence-of-statements -- 4 Handled because of the exception handler entry

exception -- 5 Optional. Not every comb needs this.

sequence-of-statements -- 6 This is the area for exception handler code end unit-name; -- 7 Every comb requires a scope terminator with A;

with B; with C; package Q is ... end Q;

with A; with B; with C; package R is ... end R; with E; with F; package body R is ...

end R;

with R; package T is ... end T;

with A; package body T is ...

end T; with T;

package body Q is ...

end Q;

specification specification specification

body body body

(11)

Page 11 of 113

Ada is a block-structured language. Local declarations may contain: other subprogram declarations (including their body), instances of types, instances of generic units, tasks or task types, protected objects or protected types, use clauses, compiler directives (pragmas), local type declarations, constants, and anything else that falls into the category of the items just listed. Even though the list of legal entities in a declaration is long, only a few elements are actually used in practice. Be aware of the Ada Comb when studying the subprograms and algorithmic structures in this book.

The handled-sequence-of-statements includes statements that operate on declarations. This includes assignment, comparisons, transfers of control, algorithmic code. More specifically, we see the three fundamental control structures of the structure theorem (Jacopini and Böhm): sequence, iteration, selection. You may also see a declare block, with local declarations, within the handled-sequence-of-statements.

with Ada.Text_IO; -- 1 Is elaborated before being used

with Machinery; -- 2 Is elaborated before being used

procedure Ada_Comb_Example_1 is -- 3 Name of enclosing unit

Data : Machinery.Machine; -- 4 Declarations local to enclosing unit

begin -- 5

declare -- 6 Can declare local variables in this block

Data : Integer := 42; -- 7 The name, Data, hides the global declarations

begin -- 8 Integer Data now is visible; Outer Data is not

Data := Data + 1; -- 9 Handled sequence of statements

exception -- 10 Start exception handler part of unit

whensome-exception => -- 11 Name the exception after reserved word, when

-- sequence of statements -- 12 Any legal sequence of statements here

end; -- 13 End of scope of declare block

end Ada_Comb_Example_1; -- 14 End of enclosing scope

The Ada comb may be found in most algorithmic units. This includes procedures, functions, package bodies, task bodies, and declare blocks. These units may also include some kind of identifier (label). In production code, it is helpful to include the label at the beginning of the comb as well as at the end of it. Here is a variation on the previous example

procedure Ada_Comb_Example_2 is -- 1 Name of procedure

Data : Float := 0.0; -- 2 Floating point declaration in scope

begin -- 3

Integer_Block: -- 4 A label for the declare block

declare -- 5 Can declare local variables in this block

Data : Integer := 42; -- 6 The name, Data, hides the global declarations

begin -- 7 Integer Data now is visible; Float Data is not directly visible

Data := Data + 1; -- 8 Simple incrementing statement

exception -- 9 Localized exception handling region

when Constraint_Error => ... -- 10 Statements to handle the exception

end Integer_Block; -- 11 Named end of scope for declare block

Data := Data + 451.0; -- 12 Float data is once more visible

end Ada_Comb_Example_2; -- 13 End of scope of procedure

(12)

Page 12 of 113

2.6 Variables and Constants

A variable is an entity that can change its value within your program. That is, you may assign new values to it after it is declared. A constant, once declared with an assigned value, may not be changed during its lifetime in your program. Variables and constants may be declared in a certain place in your program, called the declarative part. Every variable and constant must be associated with some type. The basic syntax for a variable declaration is,

name_of_variable : name_of_type; -- for a scalar or constrained composite type

name_of_variable : name_of_type(constraint) ; -- for an unconstrained composite type

Declarations for predefined types (see package Standard in the appendices of this book)

Value : Integer; -- see Annex A.1, package Standard

Degrees : Float; -- see Annex A.1, package Standard

Sentinel : Character; -- see Annex A.1, package Standard

Result : Boolean; -- see Annex A.1, package Standard

Text : String(1..120); -- Must always constrain a string variable

We could also initialize a variable at the time it is declared,

Channel : Integer := 42; -- "...life, the universe, and everything."

Pi : Float := Ada.Numerics.Pi; -- from Annex A.5, ALRM

ESC : Character := Ada.Characters.Latin_1.ESC; -- from Annex A, ALRM

Is_On : Boolean := True; -- from Annex A.1, ALRM

Text : String(1..120) := (others => '*'); -- Every element initialized to asterisk

2.7 Operations and Operators

Ada distinguishes between operations and operators. Operators are usually the infix methods used for arithmetic, comparison, and logical statements. Operators present a visibility problem for a new Ada programmer. Watch for the discussion of operator visibility that follows in this section.

2.7.1 Assignment Operation

Somewhere among his published aphorisms and deprecations, Edsger Dijkstra observes that too few programmers really understand the complexities of the assignment statement. I have not been able to excavate the exact quote from those of his publications immediately at hand. It is true, however, that assignment is increasingly complicated as new programming languages are invented. Ada is no exception, and may actually have more complicated rules about assignment than some other languages.

The Ada assignment operation, := , is a compound symbol composed of a colon symbol and equal symbol. It is predefined for every Ada type except limited types. It is illegal, in Ada, to directly overload, rename, or alias the assignment operation. In a statement such as,

A := B + C * (F / 3);

the expression on the right side of the assignment operation is evaluated and the result of that evaluation is placed in the location designated by the variable on the left side. All the variables on both sides must be of the same type. In an expression,

X := Y;Note: Although Ada does not allow direct overloading of the assignment operator, it is sometimes useful to do that kind of overloading, andAda has a facility for designing in this feature safely but indirectly, by deriving from a controlled type.

Reminder: the assignment operator is legal only on non-limited types. Also, both sides of the assignment operator must conform to each other. Composite types must have the same size and constraints.

:=

String is defined in package Standard as an unconstrained array

(13)

Page 13 of 113

X and Y must both be of the same type. If values in an assignment statement are not of the same type, the programmer may, under strictly defined rules, convert Y to a type corresponding to the type of X.

type X_Type is ... -- Ellipses are not part of the Ada language; used for simplification here type Y_Type is ...

X := X_Type(Y); -- When type conversion is legal between the types

Type conversion is not legal between all types. If both types are numeric, the conversion is probably legal. If one type is derived from another, it is legal. Otherwise, type conversion is probably not legal.

Assignment may be more complicated if the source and target objects in the assigment statement are composite types. It is especially complicated if those composite types include pointers (access values) that reference some other object. In this case, access value components may create entertaining problems for the programmer. For this reason, composite types constructed from pointers should be limited types. For limited types, one would define a Deep Copy procedure. Ada makes it illegal to directly overload the assignment operator. Study an example of a deep copy in the generic Queue_Manager later in this book.

Sometimes two types are so completely different that assignment must be performed using a special generic function, Ada.Unchecked_Conversion. Do not be too hasty to use this function. Often there is another option. Note the following example:

with Ada.Unchecked_Conversion; -- 1 Chapter 13 or ALRM

procedure Unchecked_Example is -- 2 Generally speaking, don't do this

type Vector is array (1 .. 4) of Integer; -- 3 Array with four components

for Vector'Size use 4 * Integer'Size; -- 4 Define number of bits for the array

type Data is record -- 5

V1, V2, V3, V4 : Integer; -- 6 A record with four components

end record; -- 7

for Data'Size use 4 * Integer'Size; -- 8 Same number of bits as the array

function Convert is new Unchecked_Conversion -- 9

(Source => Vector, Target => Data); -- 10 Convert a Vector to a Data

The_Vector : Vector := (2, 4, 6, 8); -- 11 Intilialize a Vector with values

The_Data : Data := (1, 3, 5, 7); -- 12 Intilialize a Record with values

begin -- 13

The_Data := Convert(The_Vector); -- 14 Assignment via unchecked conversion

end Unchecked_Example; -- 15

Even though Line 14 probably works just fine in all cases, many Ada practitioners will prefer to do the assignments one at a time from the components of Vector to the components of Data. There will be more code, but selected component assignment is guaranteed to work under all circumstances. Unchecked conversion may be less certain unless you are careful about what you are doing.

2.7.2 Other Operations

There are several reserved words that behave like operations. Most of these such as abort, delay, accept, select, and terminate are related to tasking. Others include raise (for exceptions), goto, and null. Some Ada practitioners might not agree with the notion that these are operations, however, in any other language they would be so considered.

Other operations, for non-limited types, are described in Chapter Four of the Ada Language Reference Manual. Again, these might not be thought of as operations, but they do have functionality that leads us to classify them as operations. These include array slicing, type conversion, type qualification, dynamic allocation of access objects, and attribute modification (Annex K of ALRM).

(14)

Page 14 of 113

be declared in the public part of a package specification. They are implemented in the body of a package. For example, in a stack package, the operations might be Push, Pop, Is_Full, Is_Empty. For abstract data types, the operations are described as subprograms on the type.

2.7.3 Operators

As mentioned in Section 3.2.2, Ada distinguishes between operators and operations. This distinction is useful for visibility management. Operators may be overloaded.

Operators can be thought of as functions. For example, for a type, T, function signatures might be:

function "=" (Left, Right : T) return Boolean; -- signature for equality operator

function ">=" (Left, Right : T) return Boolean; -- signature for equality operator

function "+" (Left, Right : T) return T; -- signature for addition operator

This signature style applies to all operators. The name of the operator is named in double quotes as if it were a string. You may overload operators for your own types. In Ada, the return type is part of the signature. There is a special visibility clause that makes all the operators for a named type fully visible:

use typetypename; -- typename is the name of the type in scope. It might need to be dot qualified

Some designers prefer to make selected operators visible using the renames clause instead of the the use type clause. For example, if type T is defined in package P,

function "+" (Left, Right : P.T) return P.T renames P."+"; -- makes "+" directly visible

The above function renames the addition operator for a specific type. It uses dot notation to reference the package in which the type is defined. You can code this in the declarations of a unit that has a context clause for (for example) P and a type P.T. This makes the plus operator directly visible in the immediately enclosing scope. Many Ada practitioners feel this is a better engineering solution to controlling visibility than any of the other options. It does have the effect of ensuring that no accidental coding of some other operator is possible since only this one is directly visible.

2.8 Elementary Sequential Programs

Ada supports two kinds of subprograms: procedures and functions. A subprogram may be a standalone library unit. Often it a subprogram is declared in some other unit such as a package specification. The implementation part of the subprogram is called the "body." The body for Open might be coded as:

procedure Open(F : in out File) is -- 1 Note the reserved word, is

-- optional local declarations -- 2 Between is and begin, local declarations

begin -- 3 Subprogram body requires a begin

-- some sequence of statements -- 4 Some statements or reserved word null; end Open; -- Most standards require repeating the identifier here -- 5 End required; Identifier optional but usual

Sometimes we code the subprogram specification and body together, as just shown. There are many cases of this in the example subprograms in this book. The optional local declarations on Line 2 are local to the subprogram. That is, they are never visible to another unit. This is one more level of visibility. When you fully understand the visibility rules, you will understand most of Ada.

(15)

Page 15 of 113

2.8.1 Subprogram Parameters

Subprograms may have formal parameters. Formal parameters must have a name, a type, and a mode. A mode tells the compiler how a parameter will be used in a subprogram. The parameter mode may be in,

out, in out, or access. The following table simplifies the concept of parameter mode:

Mode Function Procedure Assigment Operator Position

in Yes Yes Only right side of := (a constant in subprogram) out No Yes Right or Left side of := (but has no initial value)

in out No Yes Right or Left side of := (has initial value)

access Yes Yes Only right side of := (but might assign to component)

The table is an over-simplification. It will work well for you as a programmer. Just understand that out mode parameters are not called with an initial value, and access mode parameters (See Chapter 5) are pointing to some other data. The data being accessed may be modified even though the access value itself may not. Examples of parameters and their modes within a subprogram,

2.8.2 Subprogram Specifications with Parameters

procedure Clear (The_List : in out List); -- The_List can be on either side of :=

function Is_Empty (The_List : in List) return Boolean; -- The_List can be on right side of :=

function Is_Full (The_List : List) return Boolean; -- default in mode

procedure Get (The_List : in List; Data : out Item); -- two modes; two parameters

procedure Set_Col (To : in Positive_Count := 1); -- default value for in mode

procedure Update (The_List : in out List; Data : in Item); -- two modes; two parameters function Item_Count (The_List : access List) return Natural; -- The_List can be on right side of :=

procedure Item_Count (The_List : access List; -- The_List can be on allowed on right of :=

Count : out Count); --unitialized; left or right of := function M_Data (Azimuth, Elevation, Time : Float) return Float; -- Three parameters, same type

A call to a formal parameter with an actual parameter should usually include named association. Consider function M_Data, above. Which is more readable and more likely to be accurate?

R := M_Data (42.8, 16.2, 32.8);

R := M_Data (Elevation => 16.2, Time => 32.8, Azimuth => 42.8);

Consider a problem that often occurs in languages such as C or C++ with three parameters of the same type:

int mdata (int x, int y, int z) { ... }

In C, there is no easy way to explicitly ensure correct actual values are being sent to the right formal arguments. Consequently, it is easy to accidentally call a function with the wrong data, even if that data is of the correct type. Some more recent languages have adopted this feature from Ada.

Ada programmers, using named association, prevent this kind of accident because errors are easily detected by the compiler. This can save countless hours of debugging time. Later, when someone needs to

maintain a program using named association there is less difficulty determining what parameters are being used and when. This is especially useful for parameter lists where some of the formal parameters have default values.

What happens if the wrong parameters of the right type are passed?

The compound symbol means associate the formal parameter with the named actual parameter.

Named association enables explicit interfaces. This is an important engineering principle for software.

Named association where actual parameter is associated with

(16)

Page 16 of 113

3. Types and the Type Model

3.1 Rigorous Type Rules

Type safety is the language feature for which Ada is best known. It is actually only one of the many strong points in Ada. The following discussion will clarify how it works. A type, in Ada, consists of four parts,

1. A name for the type

2. A set of operations for the type 3. A set of values for the type

4. A set of rules governing type relationships; e.g., a wall between objects of differing types

The last feature, the wall, is the default of the Ada typing model. Ada does provide capabilities for getting around or over the wall, but the wall is always there. There are two general categories of type, elementary and composite. A composite type is a record or an array. Everything else, for our purposes in this book, is an elementary type. (Note: there are minor exceptions to this definition when you get into more advanced Ada). Some types are predefined in a package Standard (see this Appendix A of this book). From the object-oriented viewpoint, a type has state, operations to modify state and operations to query state.

3.2 Type Safety

A better way to view strong typing is to think in terms of type safety. Every construct in Ada is type safe. For Ada, type safe is the default. For most languages, type safe is not the default. In still other languages, type safety is an illusion because of structural equivalence or implicit type promotion. Ada does not support either of those concepts because they are not type-safe. An Ada designer declares data types, usually in a package specification. The declared types include a constrained set of values and operations appropriate to the problem being solved. This ensures a rigorous contract between the client of a type and the promise made by the package in which the type is defined.

3.3 Declaring and Defining Types

3.3.1 Categories of types

Ada types can be viewed in two broad categories: limited, and non-limited. A type with a limited view cannot be used with the := expression, ever. All other types can be used with := as long as that assignment is between compatible (or converted view of) types. Ada defines certain types as always limited. These include task types, protected types, and record types with access discriminants.

Types in Ada may be considered in terms of their view. A type may be defined with a public view which can be seen by a client of the type, and a non-public view that is seen by the implementation of the type. We sometimes speak of the partial view of the type. A partial view is a public view with a corresponding non-public view. Partial views are usually defined as private or limited private. Also, the public view of a type may be limited where the implementation view of that same type may be non-limited. Ada does not define a protected view directly analogous to C++ or Java. However, some of the essential properties of that view are available as necessary.

Another important category is private type versus non-private type. A limited type may also be private. A type with a private view may also have a view that is not private. Any Ada data type may have a view that is private with a corresponding view that is not private. The predefined operations for a non-limited private type include: := operation, = operator, /= operator. Any other operations for a private type must be declared explicitly by the package specification in which the type is publicly declared.

(17)

Page 17 of 113

3.3.2 A Package of Non-private Type Definitions

In addition to predefined types declare in package Standard, the designer may also define types. These may be constrained or unconstrained, limited or non limited. Here are some sample type declarations.

package Own_Types is

type Color is (Red, Orange, Yellow, Green, Blue, Indigo, Violet); -- 1 An enumerated type; -- an ordered set of values; not a synonym for a set of integer values -- 2 A single line comment type Farenheit is digits 7 range -473.0..451.0; -- 3 Floating point type

type Money is delta 0.01 digits 12; -- 4 Financial data type for accounting

type Quarndex is range -3_000..10_000; -- 5 Integer type; note underbar notation type Vector is array(1..100) of Farenheit; -- 6 Constrained array type

type Color_Mix is array(Color) of Boolean; -- 7 Constrained by Color set

type Inventory is record -- 8 A constrained record type

Description : String(1..80) := (others => ' '); -- 9 Initialized string type record component

Identifier : Positive; -- 10 A positive type record component

end record; -- 11 End of record scope required by Ada

type Inventory_Pointer is access all Inventory; -- 12 Declaring a pointer type in Ada

type QData is array(Positive range <>) of Quarndex; -- 13 Unconstrained array type

type Account is tagged record -- 14 See next example: 1.5.3.3

ID : String (1..20); -- 15 Uninitialized string type component

Amount : Money := 0.0; -- 16 See line 4 of this package

end record; -- 17 Required by language

type Account_Ref is access all Account'Class; -- 19 Classwide pointer type for tagged type

end Own_Types;

3.3.3 A Private type Package

package Own_Private_Types is -- 1

type Inventory is limited private; -- 2 Partial definition of limited private type

type Inventory_Pointer is access all Inventory; -- 3 Declaring a pointer type in Ada

procedure Create(Inv : in out Inventory); -- 4 Create an empty instance of Inventory

-- More operations for type Inventory -- 5

type Account is tagged private; -- 6 Partial definition of a tagged type

type Account_Ref is access all Account'Class; -- 7 Classwide pointer type for tagged type

procedure Create(Inv : in out Inventory); -- 8 Creates an empty Inventory record

function Create (D : String; ID : Positive) return Account_Ref; -- 9 returns access to new Inventory record

-- More operations for tagged type, Account -- 10

private -- 11 Begin private part of package

type Inventory is record -- 12 A constrained record type

Description : String(1..80) := (others => ' '); -- 13 Initialized string type record component

Identifier : Positive; -- 14 A positive type record component

end record; -- 15 End of record scope required by Ada

-- 16

type Account is tagged record -- 17 Extensible record tagged type

ID : String(1..12); -- 18 Uninitialized string type component

Amount : Float := 0.0; -- 19 A float type record component

end record; -- 20 Required by language

end Own_Private_Types; -- 21

Note the signature of the Create procedure on Line 4. Since the inventory type is limited private, we would often want the mode of parameter list to be in out. However, it is legal to have mode of out only.

3.4 Deriving and Extending Types

A new type may be derived from an existing type. Using the definitions from the previous package,

type Repair_Parts_Inventory is new Inventory; -- no extension of parent record is possible here -- because it is not a tagged type

where Repair_Parts inherits all the operations and data definitions included in its parent type. Also,

Public view of specification

(18)

Page 18 of 113

type Liability is new Account -- 1 extended from tagged parent, lines 6, 17-20, above

withrecord -- 2 required ;phrase for this construct

Credit_Value : Float; -- 3 extends with third component of the record

Debit_Value : Float; -- 4 fourth component of the record

end record; -- 5 record now extended with four elements

in which Liability, derived from Account, inherits all the operations and components of its parent type but also adds two more components. This means that Liability now has four components, not just two. This is called extensible type inheritance. From the above list of types, one might have a access (pointer) variable,

Current_Account : Account_Ref; -- Points to Account or Liability objects

which can point to objects of any type derived from Account. That is, any type in Account'Class. This permits the construction of heterogeneous data structures.

3.5 Operations on Types

As mentioned in Section 2.7.3, Ada distinguishes between operators and operations. Legal syntax for operations on types is defined in 4.5 of the ALRM. In general the rules are pretty simple. A limited type has no language-defined operations, not even the := (assignment) operation. Every other type has :=, at minimum. The following table summarizes some (not all) of these possibilities.

3.6 Where to Declare a Type

Usually, a type will be declared in a package specification along with its exported operations. Therefore,

package Machinery is -- 1 Package specification; requires body

type Machine is private; -- 2 Specifies the visible part of the data type;

procedure Turn_On (M : in out Machine); -- 3 procedure specification

procedure Turn_Off (M : in out Machine); -- 4 procedure specification

function Is_On (M : in Machine) return Boolean; -- 5 function specification

function ">" (L, R : Machine) return Boolean; -- 6 Declare the ">" function for private type

private -- 7 private part hidden from a client of contract

type Machine is record -- 8 full definition of the publicly declared type Turned_On : Boolean := False; -- 9 component of the type; OOP attribute

end record; -- 10 scope terminator for the component

end Machinery; -- 11 scope terminator for the specification

Note: membership test not officially an operation or operator. It cannot be overloaded. It is available for limited types.

:= = <, >, <=, >= & +, -, *, / abs rem/mod in not in

A. Non-Limited Types Y Y .. .. .. .. .. Y Y

1. Elementary Y Y .. .. .. .. .. Y Y

a. Scalar Y Y Y .. .. .. .. Y Y

1) Discrete Y Y Y .. .. .. .. Y Y

Enumerated Y Y Y .. .. .. .. Y Y

Integer Y Y Y .. Y Y Y Y Y

Modular (Unsigned) Y Y Y .. Y N Y Y Y

2) Not Discrete Y Y Y .. .. .. N Y Y

Float Y Y Y .. Y Y N Y Y

Fixed Y Y Y .. Y Y N Y Y

Decimal Y Y Y .. Y Y N Y Y

2. Composite Y Y .. .. N N N Y Y

1) Record Y Y N .. N N N Y Y

2) Array .. .. .. Y N N N Y Y

Constrained Y Y Y Y N N N Y Y

Unconstrained .. .. N .. N N N Y Y

3. Private Y N N N N Y Y

B. Limited N N N N N N N Y Y

(19)

Page 19 of 113

will imply that the public operations available to a client of Machinery, for the type Machine, are:

pre-defined assignment and test for equality and inequality

procedures Turn_On and Turn_Off

functions Is_On and ">"

no other operations on type Machine are available in package Machinery.

The language defined operations for a private type, Machine, are only assignment ( := ) , Equality ( = ),

and Inequality (/=). All other operations and operators for Machine must be explicitly declared in the contract, i.e., the package specification. The package has overloaded the ">" operator, so a client of this package can do a greater than compare on two machine objects.

3.7 The Wall Between Types

The fourth property for a type, the wall, is illustrated using the following declarations,

package Some_Types is -- 1 Declare specification name

type Channel is range 2..136; -- 2 A constrained integer

type Signal is new Integer -- 3 Derived from Standard.Integer

range 1..150 -- 4 with a range constraint

type Level is digits 7; -- 5 A floating point type

subtype Small_Signal is Signal -- 6 No wall with objects of type Signal

range 2..14; -- 7 but smaller range than Signal

type Color is (Red, Yellow, Green, Blue); -- 8 Enumerated type with four values

type Light is (Red, Yellow, Green); -- 9 Another enumerated type

type Traffic is new Color -- 10 Derived from Color but with a

range Red..Green; -- 11 smaller range of values.

end Some_Types; -- 12.

Warning. Most Ada practitioners recommend against this kind of package. It works well for our teaching example, but is poor design practice. Generally, a package should be designed so each type is

accompanied by an explicit set of exported operations rather than depending on those predefined.

3.7.1 Type Rule Examples

The following procedure uses the package, Some_Types. It illustrates how the typing rules work. Therefore, this procedure will not compile for reasons shown. A corrected example will follow .

with Some_Types; -- 1 No corresponding use clause; in scope only

procedure Will_Not_Compile is -- 2 Correct. Too many errors for this to compile

Ch1, Ch2, Ch3 : Some_Types.Channel := 42; -- 3 Notice the dot notation in declaration Sig1, Sig2 : Some_Types.Signal := 27; -- 4 Dot notatation makes type Signal visible

Level_1, Level_2 : Some_Types.Level := 360.0; -- 5 Dot notation again. No use clause so this is required

Tiny : Some_Types.Small_Signal := 4; -- 6

Color_1, Color_2 : Some_Types.Color := Some_Types.Red; -- 7 Dot notation required here Light_1, Light_2 : Some_Types.Light := Some_Types.Red; -- 8

Tr1, Tr2, Tr3 : Some_Types.Traffic := Some_Types.Red; -- 9

begin -- 10

Ch3 := Ch1 + ch2; -- 11 Cannot compile; + operator not directly visible

Level_1 := Ch1; -- 12 Incompatible data types

Tiny := Sig1; -- 13 This is OK because of subtype

Color_1 := Light_1; -- 14 Incompatible types in expression

Light_2 := Tr1; -- 15 Incompatible types

Light_3 := Some_Types.Light(Color_1); -- 16 Type conversion not permitted for these types

Tr3 := Color_1; -- 17 Incompatible types

Tr1 := Some_Types.Traffic'Succ(Tr2); -- 18 This statement is OK

end Will_Not_Compile; -- 19

The following example corrects some of the problems with the preceding one. Note the need for type conversion. We include an example of unchecked conversion. Generally, unchecked conversion is a bad

Note: by a "wall" we mean that values of differing types may not be directly mixed in expressions. Type conversion can sometimes help you across the wall. Other times, more roundabout approaches are required. This is in keeping with Ada's charter to be as type safe as

References

Related documents

CDM: Cognitive diagnostic modeling; CFI: Comparative fit index; DIF: Differential item functioning; DL: Diagram labelling; GF: Gap filling; GFI: Goodness of fit index; ICI:

The three stages are defined according to the relative amplitude ( δ z ) values of 0.1 and 0.6 mm. Diameters of the red and white particles which comprise the lower and upper

This review of studies that have used data-driven meth- odologies to examine clustering of obesogenic behaviors has shown that diet, PA and sedentary behavior cluster in children

Once the initial set of practical applications had been cre- ated for each target behaviour, the intervention subgroup designed a structured programme plan for which delivery in

The results of the econometric analysis support that both inward and outward FDIs have positive effects on productivity growth at the regional level, after controlling for a

In relation to this study, a possible explanation for this is that students who were in the high mathematics performance group were driven to learn for extrinsic reasons and

The main purpose of this work was the evaluation of different CZM formulations to predict the strength of adhesively-bonded scarf joints, considering the tensile and shear

B-HCM: Hypoxia conditioned media from BMSC; B-MCM: Metabolically conditioned media from BMSC; BMSC: Bone marrow stromal cells; ELISA: Enzyme-linked immunosorbent assay; F-HCM: