Ada for Software Engineers - Preface and Table of Contents


Albert Einstein once said that `things should be as simple as possible, but not simpler'. Einstein could have been talking about programming languages, as the landscape is strewn with `simple' languages that, several versions later, have 500-page reference manuals! The truth is that we expect a lot of our programming languages. Turing machines just aren't sophisticated enough for modern software development; we demand support for encapsulation and abstraction, type checking and exception handling, polymorphism and more. Ada, unlike other languages which grew by gradual addition of features, was designed as a coherent programming language for complex software systems. As if to justify Einstein's saying, Ada is no more complex than the final versions of `simpler' languages.

However, the complexity of modern programming languages leaves textbook writers with a painful dilemma: either gloss over the gory details, or write books that are heavy enough to be classified as lethal weapons. Is there another way? Strange as it may seem, you can get an excellent concise description of Ada 95 for free: the Ada Reference Manual (ARM), which is the document defining the language standard. The ARM has a reputation for being ponderous reading meant for `language lawyers'. Nevertheless, I believe that, with a bit of guidance, software engineers can learn to read most of the ARM. Ada for Software Engineers is written to equip you with the knowledge necessary to use the Ada 95 programming language to develop software systems. I will try to teach you how the individual language constructs are used in actual programs, and I will try to explain the terminology and concepts used in the language standard.

The book is intended for software engineers making the transition to Ada, and for upper-level undergraduate and graduate students (including those who have had the good fortune to study Ada as their first programming language!). No specific Ada knowledge is assumed; the prerequisites are a basic knowledge of computer science and computer systems, and significant programming experience (not necessarily in Ada). As the title implies, this book is for you if you are a software engineer or training to become one.

The Ada language will be taught using a few---relatively large---case studies, rather than a large number of small examples each crafted to demonstrate a particular construct or rule. Experienced programmers know that the key to mastering a programming language is not to memorize the syntax and semantics of individual constructs, but to learn how to integrate the constructs into language-specific paradigms. We will need to gloss over details when explaining a case study; rest assured that everything will eventually be explained, or you will find a pointer to the explanation in the ARM. Certain sections marked with one or two asterisks should be omitted during your initial study of Ada. This material is not necessarily more difficult, but you can't learn everything at once, and these are topics that can be left for your second and third reading of the book.

After an introductory chapter, Chapters 2--4 quickly cover elementary language constructs such as statements, subprograms, arrays, records and pointers that should be familiar from your previous programming experience. The core of the book is the progressive development a of case study demonstrating the Ada constructs for object-oriented programming: packages and private types (Chapter 5), type extension, inheritance, class-wide types and dynamic polymorphism (Chapter 6) and generics (Chapter 7). Chapters 8--12 cover specialized topics: the type system in depth, input--output and program structure. Chapters 13--16 form a second core of the book, discussing topics broadly covered by the term systems programming: multitasking, hardware interfaces, systems programming, and real-time and distributed systems. Most of these chapters are relatively independent of the material following Chapter 5 on packages. Appendix A Tips for Transition will help Pascal, C, C++ and Java programmers relate constructs in those languages to the constructs of Ada. A special feature of the book is the Glossary (Appendix B), which explains the ARM terminology with examples . In addition, discussions in the text are cross-referenced to the relevant paragraphs in the ARM. Appendix D contains a set of quizzes: these are programs designed to demonstrate lesser-known rules of the language. The best way to approach them is to use the hints in Appendix E, which are references to the relevant ARM paragraph, and to look up the answers in Appendix F only after you believe that you have solved a quiz. I have not included programming exercises; my suggestion is that you modify, extend and improve the case studies.

All the case studies, quizzes and programs in the book were compiled and executed. LaTeX-formatted text was automatically produced from the source code with a small amount of additional manual formatting. The program that transforms Ada source code to LaTeX is itself the subject of one of the case studies! Source code that is unchanged from one case study to another is usually omitted; the full source code of each executable program is available on the companion CD-ROM. Files names are given in the margin at the beginning of each program. The CD-ROM also contains Ada 95 compilers, plaintext and hypertext versions of the ARM and other material as specified in Appendix C. Appendix G is a guide to sources of information on Ada, both printed and electronic.

The painting on the cover is ``The Railway Bridge, Argentueil'' by Claude Monet. Ada has been extensively used in the construction of software for rail systems which are known for their high level of safety and reliability.

Acknowledgements: I would not have been able to learn Ada 95 without the GNAT compiler from the NYU/ACT team led by Robert Dewar and Edmond Schonberg. In particular, they deserve thanks not so much for fixing the bugs I uncovered, but for their patience with me when I tried to pass off my own misunderstandings as bugs in their compiler. I would like to thank Michael Feldman, Kevlin Henney, Richard Riehle, Reuben Sumner, Tucker Taft and Peter Wegner for reviewing the manuscript, Tucker Taft for helping me with the fine points of the Ada language, and my editor Simon Plumtree for his support and assistance.

Table of Contents

Chapter 1 The Language for a Complex World 1
1.1 Programming or software engineering? 1
1.2 Reliable software engineering 2
1.3 Language in software engineering 3
1.4 Ada for software engineering 3
1.5 The development of Ada 5
1.6 From Ada 83 to Ada 95 6
1.7 The Ada Reference Manual 7

Chapter 2 A Simple Ada Program 11
2.1 Case study: country of origin 11
2.2 Structure of a program 12
2.3 Statements 13
2.4 Predefined exceptions 14
2.5 Types 15
2.6 Subtypes 21
2.7 Lexical elements 24

Chapter 3 Arrays 27
3.1 Case study: fill and justify text 27
3.2 Array types 32
3.3 Constrained array subtypes and objects* 38
3.4 Type conversion* 39
3.5 Operations on one-dimensional arrays* 39
3.6 The context of array aggregates** 40
3.7 Parameter modes 41

Chapter 4 Elementary Data Structures 45
4.1 Case study: array priority queue 45
4.2 Records 48
4.3 Parameter associations and overloading 49
4.4 Declaring and raising exceptions 52
4.5 Case study: tree priority queue 56
4.6 Access types 59

Chapter 5 Packages and Abstract Data Types 63
5.1 Modularization 63
5.2 Case study: priority queue package 64
5.3 Private types 75
5.4 Limited types 78

Chapter 6 Type Extension and Inheritance 85
6.1 Case study: discrete event simulation 85
6.2 Tagged types 87
6.3 Primitive operations 92
6.4 Overriding an operation 93
6.5 Class-wide types 98
6.6 Dynamic dispatching 103
6.7 Encapsulation and child packages 107
6.8 Type conversion* 113
6.9 Objects of class-wide type* 116
6.10 Abstract types* 119
6.11 Implementation of dispatching** 121
6.12 Multiple controlling operands** 123
6.13 Dispatching on the function result** 124

Chapter 7 Generics 127
7.1 Generic declaration and instantiation 128
7.2 The contract model 132
7.3 Generic formal subprograms 134
7.4 Dependence of generic formal parameters 136
7.5 Generic formal tagged private types* 138
7.6 Generic formal derived types* 141
7.7 Generic formal objects* 146
7.8 Indefinite and abstract parameters** 146
7.9 Formal package parameters** 148
7.10 Generic children* 153
7.11 Limitations of the contract model** 154

Chapter 8 Types Revisited 157
8.1 Characters and strings 157
8.2 Discriminants 166
8.3 Variant records 168
8.4 Representation items 171
8.5 Deeper into discriminants 172
8.6 Untagged derived types* 177

Chapter 9 Access Types 181
9.1 General access types 181
9.2 Access-to-subprogram types 182
9.3 Case study: callback 182
9.4 Accessibility rules 185
9.5 Access parameters* 186
9.6 Storage pools* 189
9.7 Controlled types* 190
9.8 Access discriminants** 195

Chapter 10 Numeric Types 199
10.1 Principles of numeric types 199
10.2 Integer types 202
10.3 Types versus subtypes 203
10.4 Modular types 204
10.5 Real types 205
10.6 Floating point types 206
10.7 Fixed point types 209
10.8 Advanced concepts* 216

Chapter 11 Input--output 223
11.1 Libraries for input--output 223
11.2 Package Exceptions* 225
11.3 Streams** 227
Chapter 12 Program Structure 233

12.1 Compilation and execution 233
12.2 Subunits 234
12.3 Pragmas* 236
12.4 Elaboration* 237
12.5 Renamings 239
12.6 Use type clause 241
12.7 Visibility rules** 241
12.8 Overloading** 243

Chapter 13 Concurrency 245
13.1 Concepts 245
13.2 Tasks and protected objects 248
13.3 Rendezvous 254
13.4 Case study: the CEO problem 262
13.5 Entry families 269
13.6 Protected subprograms 271
13.7 The requeue statement 272
13.8 Rules for entries of protected types* 273

Chapter 14 Advanced Concurrency 279
14.1 Activation and termination 279
14.2 Exceptions 283
14.3 Time 284
14.4 Periodic tasks 285
14.5 Timed and conditional entry calls 288
14.6 Asynchronous transfer of control* 291
14.7 Alternatives for selective accept 292
14.8 Case study: concurrent simulation 293
14.9 Tasks as access discriminants** 298

Chapter 15 Systems Programming* 303
15.1 Implementation dependencies 303
15.2 Annex B Interface to Other Languages 305
15.3 Annex C Systems Programming 310
15.4 Hardware interfacing 311
15.5 Low-level tasking** 314

Chapter 16 Real-Time and Distributed Systems* 321
16.1 Annex D Real-Time Systems 321
16.2 Scheduling 321
16.3 Monotonic Time 329
16.4 More on real-time systems** 330
16.5 Annex E Distributed Systems 333
16.6 Annex H Safety and Security 339

Appendix A Tips for Transition 343
A.1 Pascal 343
A.2 C 345
A.3 C++ 347
A.4 Java 349

Appendix B Glossary of ARM Terms 351

Appendix C The CD-ROM 373
C.1 Ada resources 373
C.2 Source code 374

Appendix D Quizzes 375

Appendix E Hints 399

Appendix F Answers 401

Appendix G Further Reading 409
G.1 Hard copy 409
G.2 Electronic 410