INTERNATIONAL STANDARD ISO/IEC 8652:1995(E) INFORMATION TECHNOLOGY -- PROGRAMMING LANGUAGES -- ADA [Revision of first edition (ISO 8652:1987)] ANNOTATED ADA REFERENCE MANUAL Language and Standard Libraries Version 6.0 21 December 1994 Copyright (C) 1992,1993,1994,1995 Intermetrics, Inc. This copyright is assigned to the U.S. Government. All rights reserved. This document may be copied, in whole or in part, in any form or by any means, as is or with alterations, provided that (1) alterations are clearly marked as alterations and (2) this copyright notice is included unmodified in any copy. Compiled copies of standard library units and examples need not contain this copyright notice so long as the notice is included in all copies of source code and documentation. INTERNATIONAL ORGANIZATION FOR STANDARDIZATION INTERNATIONAL ELECTROTECHNICAL COMMISSION Copyright (C) 1992,1993,1994,1995 Intermetrics, Inc. This copyright is assigned to the U.S. Government. All rights reserved. This document may be copied, in whole or in part, in any form or by any means, as is or with alterations, provided that (1) alterations are clearly marked as alterations and (2) this copyright notice is included unmodified in any copy. Compiled copies of standard library units and examples need not contain this copyright notice so long as the notice is included in all copies of source code and documentation. Foreword 1 ISO (the International Organization for Standardization) and IEC (the International Electrotechnical Commission) form the specialized system for worldwide standardization. National bodies that are members of ISO or IEC participate in the development of International Standards through technical committees established by the respective organization to deal with particular fields of technical activity. ISO and IEC technical committees collaborate in fields of mutual interest. Other international organizations, governmental and non-governmental, in liaison with ISO and IEC, also take part in the work. 2 In the field of information technology, ISO and IEC have established a joint technical committee, ISO/IEC JTC 1. Draft International Standards adopted by the joint technical committee are circulated to national bodies for voting. Publication as an International Standard requires approval by at least 75 % of the national bodies casting a vote. 3 International Standard ISO/IEC 8652 was prepared by Joint Technical Committee ISO/IEC JTC 1, Information Technology. 4 This second edition cancels and replaces the first edition (ISO 8652:1987), of which it constitutes a technical revision. 5 Annexes A to J form an integral part of this International Standard. Annexes K to P are for information only. 5.a Discussion: This document is the Annotated Ada Reference Manual (AARM). It contains the entire text of the Ada 9X standard (ISO/IEC 8652:1995(E)), plus various annotations. It is intended primarily for compiler writers, validation test writers, and other language lawyers. The annotations include detailed rationale for individual rules and explanations of some of the more arcane interactions among the rules. Introduction 1 This is the Annotated Ada Reference Manual. 2 Other available Ada documents include: 3 Rationale for the Ada Programming Language -- 1995 edition, which gives an introduction to the new features of Ada, and explains the rationale behind them. Programmers should read this first. 4 The Ada Reference Manual (RM). This is the International Standard -- ISO/IEC 8652:1995(E). 5 Changes to Ada -- 1987 to 1995. This document lists in detail the changes made to the 1987 edition of the standard. Design Goals 6 Ada was originally designed with three overriding concerns: program reliability and maintenance, programming as a human activity, and efficiency. This revision to the language was designed to provide greater flexibility and extensibility, additional control over storage management and synchroniza- tion, and standardized packages oriented toward supporting important application areas, while at the same time retaining the original emphasis on reliability, maintainability, and efficiency. 7 The need for languages that promote reliability and simplify maintenance is well established. Hence emphasis was placed on program readability over ease of writing. For example, the rules of the language require that program variables be explicitly declared and that their type be specified. Since the type of a variable is invariant, compilers can ensure that operations on variables are compatible with the properties intended for objects of the type. Furthermore, error-prone notations have been avoided, and the syntax of the language avoids the use of encoded forms in favor of more English-like constructs. Finally, the language offers support for separate compilation of program units in a way that facilitates program development and maintenance, and which provides the same degree of checking between units as within a unit. 8 Concern for the human programmer was also stressed during the design. Above all, an attempt was made to keep to a relatively small number of underlying concepts integrated in a consistent and systematic way while continuing to avoid the pitfalls of excessive involution. The design especially aims to provide language constructs that correspond intuitively to the normal expectations of users. 9 Like many other human activities, the development of programs is becoming ever more decentralized and distributed. Consequently, the ability to assemble a program from independently produced software components continues to be a central idea in the design. The concepts of packages, of private types, and of generic units are directly related to this idea, which has ramifications in many other aspects of the language. An allied concern is the maintenance of programs to match changing requirements; type extension and the hierarchical library enable a program to be modified while minimizing disturbance to existing tested and trusted components. 10 No language can avoid the problem of efficiency. Languages that require over-elaborate compilers, or that lead to the inefficient use of storage or execution time, force these inefficiencies on all machines and on all programs. Every construct of the language was examined in the light of present implementation techniques. Any proposed construct whose implementation was unclear or that required excessive machine resources was rejected. Language Summary 11 An Ada program is composed of one or more program units. Program units may be subprograms (which define executable algorithms), packages (which define collections of entities), task units (which define concurrent computations), protected units (which define operations for the coordinated sharing of data between tasks), or generic units (which define parameterized forms of packages and subprograms). Each program unit normally consists of two parts: a specification, containing the information that must be visible to other units, and a body, containing the implementation details, which need not be visible to other units. Most program units can be compiled separately. 12 This distinction of the specification and body, and the ability to compile units separately, allows a program to be designed, written, and tested as a set of largely independent software components. 13 An Ada program will normally make use of a library of program units of general utility. The language provides means whereby individual organizations can construct their own libraries. All libraries are structured in a hierarchical manner; this enables the logical decomposition of a subsystem into individual components. The text of a separately compiled program unit must name the library units it requires. 14 Program Units 15 A subprogram is the basic unit for expressing an algorithm. There are two kinds of subprograms: procedures and functions. A procedure is the means of invoking a series of actions. For example, it may read data, update variables, or produce some output. It may have parameters, to provide a controlled means of passing information between the procedure and the point of call. A function is the means of invoking the computation of a value. It is similar to a procedure, but in addition will return a result. 16 A package is the basic unit for defining a collection of logically related entities. For example, a package can be used to define a set of type declarations and associated operations. Portions of a package can be hidden from the user, thus allowing access only to the logical properties expressed by the package specification. 17 Subprogram and package units may be compiled separately and arranged in hierarchies of parent and child units giving fine control over visibility of the logical properties and their detailed implementation. 18 A task unit is the basic unit for defining a task whose sequence of actions may be executed concurrently with those of other tasks. Such tasks may be implemented on multicomputers, multiprocessors, or with interleaved execution on a single processor. A task unit may define either a single executing task or a task type permitting the creation of any number of similar tasks. 19 A protected unit is the basic unit for defining protected operations for the coordinated use of data shared between tasks. Simple mutual exclusion is provided automatically, and more elaborate sharing protocols can be defined. A protected operation can either be a subprogram or an entry. A protected entry specifies a Boolean expression (an entry barrier) that must be true before the body of the entry is executed. A protected unit may define a single protected object or a protected type permitting the creation of several similar objects. 20 Declarations and Statements 21 The body of a program unit generally contains two parts: a declarative part, which defines the logical entities to be used in the program unit, and a sequence of statements, which defines the execution of the program unit. 22 The declarative part associates names with declared entities. For example, a name may denote a type, a constant, a variable, or an exception. A declarative part also introduces the names and parameters of other nested subprograms, packages, task units, protected units, and generic units to be used in the program unit. 23 The sequence of statements describes a sequence of actions that are to be performed. The statements are executed in succession (unless a transfer of control causes execution to continue from another place). 24 An assignment statement changes the value of a variable. A procedure call invokes execution of a procedure after associating any actual parameters provided at the call with the corresponding formal parameters. 25 Case statements and if statements allow the selection of an enclosed sequence of statements based on the value of an expression or on the value of a condition. 26 The loop statement provides the basic iterative mechanism in the language. A loop statement specifies that a sequence of statements is to be executed repeatedly as directed by an iteration scheme, or until an exit statement is encountered. 27 A block statement comprises a sequence of statements preceded by the declaration of local entities used by the statements. 28 Certain statements are associated with concurrent execution. A delay statement delays the execution of a task for a specified duration or until a specified time. An entry call statement is written as a procedure call statement; it requests an operation on a task or on a protected object, blocking the caller until the operation can be performed. A called task may accept an entry call by executing a corresponding accept statement, which specifies the actions then to be performed as part of the rendezvous with the calling task. An entry call on a protected object is processed when the corresponding entry barrier evaluates to true, whereupon the body of the entry is executed. The requeue statement permits the provision of a service as a number of related activities with preference control. One form of the select statement allows a selective wait for one of several alternative rendezvous. Other forms of the select statement allow conditional or timed entry calls and the asynchronous transfer of control in response to some triggering event. 29 Execution of a program unit may encounter error situations in which normal program execution cannot continue. For example, an arithmetic computation may exceed the maximum allowed value of a number, or an attempt may be made to access an array component by using an incorrect index value. To deal with such error situations, the statements of a program unit can be textually followed by exception handlers that specify the actions to be taken when the error situation arises. Exceptions can be raised explicitly by a raise statement. 30 Data Types 31 Every object in the language has a type, which characterizes a set of values and a set of applicable operations. The main classes of types are elementary types (comprising enumeration, numeric, and access types) and composite types (including array and record types). 32 An enumeration type defines an ordered set of distinct enumeration literals, for example a list of states or an alphabet of characters. The enumeration types Boolean, Character, and Wide_Character are predefined. 33 Numeric types provide a means of performing exact or approximate numerical computations. Exact computations use integer types, which denote sets of consecutive integers. Approximate computations use either fixed point types, with absolute bounds on the error, or floating point types, with relative bounds on the error. The numeric types Integer, Float, and Duration are predefined. 34 Composite types allow definitions of structured objects with related components. The composite types in the language include arrays and records. An array is an object with indexed components of the same type. A record is an object with named components of possibly different types. Task and protected types are also forms of composite types. The array types String and Wide_String are predefined. 35 Record, task, and protected types may have special components called discriminants which parameterize the type. Variant record structures that depend on the values of discriminants can be defined within a record type. 36 Access types allow the construction of linked data structures. A value of an access type represents a reference to an object declared as aliased or to an object created by the evaluation of an allocator. Several variables of an access type may designate the same object, and components of one object may designate the same or other objects. Both the elements in such linked data structures and their relation to other elements can be altered during program execution. Access types also permit references to subprograms to be stored, passed as parameters, and ultimately dereferenced as part of an indirect call. 37 Private types permit restricted views of a type. A private type can be defined in a package so that only the logically necessary properties are made visible to the users of the type. The full structural details that are externally irrelevant are then only available within the package and any child units. 38 From any type a new type may be defined by derivation. A type, together with its derivatives (both direct and indirect) form a derivation class. Class-wide operations may be defined that accept as a parameter an operand of any type in a derivation class. For record and private types, the derivatives may be extensions of the parent type. Types that support these object-oriented capabilities of class-wide operations and type extension must be tagged, so that the specific type of an operand within a derivation class can be identified at run time. When an operation of a tagged type is applied to an operand whose specific type is not known until run time, implicit dispatching is performed based on the tag of the operand. 39 The concept of a type is further refined by the concept of a subtype, whereby a user can constrain the set of allowed values of a type. Subtypes can be used to define subranges of scalar types, arrays with a limited set of index values, and records and private types with particular discriminant values. 40 Other Facilities 41 Representation clauses can be used to specify the mapping between types and features of an underlying machine. For example, the user can specify that objects of a given type must be represented with a given number of bits, or that the components of a record are to be represented using a given storage layout. Other features allow the controlled use of low level, nonportable, or implementation-dependent aspects, including the direct insertion of machine code. 42 The predefined environment of the language provides for input-output and other capabilities (such as string manipulation and random number generation) by means of standard library packages. Input-output is supported for values of user-defined as well as of predefined types. Standard means of representing values in display form are also provided. Other standard library packages are defined in annexes of the standard to support systems with specialized requirements. 43 Finally, the language provides a powerful means of parameterization of program units, called generic program units. The generic parameters can be types and subprograms (as well as objects and packages) and so allow general algorithms and data structures to be defined that are applicable to all types of a given class. Language Changes 44 This International Standard replaces the first edition of 1987. In this edition, the following major language changes have been incorporated: 45 Support for standard 8-bit and 16-bit character sets. See Section 2, 3.5.2, 3.6.3, A.1, A.3, and A.4. 46 Object-oriented programming with run-time polymorphism. See the discussions of classes, derived types, tagged types, record extensions, and private extensions in clauses 3.4, 3.9, and 7.3. See also the new forms of generic formal parameters that are allowed by 12.5.1, ``Formal Private and Derived Types'' and 12.7, ``Formal Packages''. 47 Access types have been extended to allow an access value to designate a subprogram or an object declared by an object declaration (as opposed to just a heap-allocated object). See 3.10. 48 Efficient data-oriented synchronization is provided via protected types. See Section 9. 49 The library units of a library may be organized into a hierarchy of parent and child units. See Section 10. 50 Additional support has been added for interfacing to other languages. See Annex B. 51 The Specialized Needs Annexes have been added to provide specific support for certain application areas: 52 Annex C, ``Systems Programming'' 53 Annex D, ``Real-Time Systems'' 54 Annex E, ``Distributed Systems'' 55 Annex F, ``Information Systems'' 56 Annex G, ``Numerics'' 57 Annex H, ``Safety and Security'' Instructions for Comment Submission 58 {instructions for comment submission} {comments, instructions for submission} Informal comments on this International Standard may be sent via e-mail to ada-comment@sw-eng.falls-church.va.us. If appropriate, the Project Editor will initiate the defect correction procedure. 59 Comments should use the following format: 60 !topic Title summarizing comment !reference RM95-ss.ss(pp) !from Author Name yy-mm-dd !keywords keywords related to topic !discussion text of discussion 61 where ss.ss is the section, clause or subclause number, pp is the paragraph number where applicable, and yy-mm-dd is the date the comment was sent. The date is optional, as is the !keywords line. 62 Multiple comments per e-mail message are acceptable. Please use a descriptive ``Subject'' in your e-mail message. 63 When correcting typographical errors or making minor wording suggestions, please put the correction directly as the topic of the comment; use square brackets [ ] to indicate text to be omitted and curly braces { } to indicate text to be added, and provide enough context to make the nature of the suggestion self-evident or put additional information in the body of the comment, for example: 64 !topic [c]{C}haracter !topic it[']s meaning is not defined 65 Formal requests for interpretations and for reporting defects in this International Standard may be made in accordance with the ISO/IEC JTC1 Directives and the ISO/IEC JTC1/SC22 policy for interpretations. National Bodies may submit a Defect Report to ISO/IEC JTC1/SC22 for resolution under the JTC1 procedures. A response will be provided and, if appropriate, a Technical Corrigendum will be issued in accordance with the procedures. Acknowledgements 66 This International Standard was prepared by the Ada 9X Mapping/Revision Team based at Intermetrics, Inc., which has included: W. Carlson, Program Manager; T. Taft, Technical Director; J. Barnes (consultant); B. Brosgol (consultant); R. Duff (Oak Tree Software); M. Edwards; C. Garrity; R. Hilliard; O. Pazy (consultant); D. Rosenfeld; L. Shafer; W. White; M. Woodger. 67 The following consultants to the Ada 9X Project contributed to the Specialized Needs Annexes: T. Baker (Real-Time/Systems Programming -- SEI, FSU); K. Dritz (Numerics -- Argonne National Laboratory); A. Gargaro (Distributed Systems -- Computer Sciences); J. Goodenough (Real-Time/Systems Programming -- SEI); J. McHugh (Secure Systems -- consultant); B. Wichmann (Safety-Critical Systems -- NPL: UK). 68 This work was regularly reviewed by the Ada 9X Distinguished Reviewers and the members of the Ada 9X Rapporteur Group (XRG): E. Ploedereder, Chairman of DRs and XRG (University of Stuttgart: Germany); B. Bardin (Hughes); J. Barnes (consultant: UK); B. Brett (DEC); B. Brosgol (consultant); R. Brukardt (RR Software); N. Cohen (IBM); R. Dewar (NYU); G. Dismukes (TeleSoft); A. Evans (consultant); A. Gargaro (Computer Sciences); M. Gerhardt (ESL); J. Goodenough (SEI); S. Heilbrunner (University of Salzburg: Austria); P. Hilfinger (UC/Berkeley); B. Kaellberg (CelsiusTech: Sweden); M. Kamrad II (Unisys); J. van Katwijk (Delft University of Technology: The Netherlands); V. Kaufman (Russia); P. Kruchten (Rational); R. Landwehr (CCI: Germany); C. Lester (Portsmouth Polytechnic: UK); L. Mansson (TELIA Research: Sweden); S. Michell (Multiprocessor Toolsmiths: Canada); M. Mills (US Air Force); D. Pogge (US Navy); K. Power (Boeing); O. Roubine (Verdix: France); A. Strohmeier (Swiss Fed Inst of Technology: Switzerland); W. Taylor (consultant: UK); J. Tokar (Tartan); E. Vasilescu (Grumman); J. Vladik (Prospeks s.r.o.: Czech Republic); S. Van Vlierberghe (OFFIS: Belgium). 69 Other valuable feedback influencing the revision process was provided by the Ada 9X Language Precision Team (Odyssey Research Associates), the Ada 9X User/Implementer Teams (AETECH, Tartan, TeleSoft), the Ada 9X Implementation Analysis Team (New York University) and the Ada community-at-large. 70 Special thanks go to R. Mathis, Convenor of ISO/IEC JTC1/SC22 Working Group 9. 71 The Ada 9X Project was sponsored by the Ada Joint Program Office. Christine M. Anderson at the Air Force Phillips Laboratory (Kirtland AFB, NM) was the project manager. Changes 72 The International Standard is the same as this version of the Reference Manual, except: 73 This list of Changes is not included in the International Standard. 74 The ``Acknowledgements'' page is not included in the International Standard. 75 The text in the running headers and footers on each page is slightly different in the International Standard. 76 The title page(s) are different in the International Standard. 77 This document is formatted for 8.5-by-11-inch paper, whereas the International Standard is formatted for A4 paper (210-by-297mm); thus, the page breaks are in different places. ---------------------- INTERNATIONAL STANDARD ---------------------- Information technology -- Programming Languages -- Ada Section 1: General 1 Ada is a programming language designed to support the construction of long-lived, highly reliable software systems. The language includes facilities to define packages of related types, objects, and operations. The packages may be parameterized and the types may be extended to support the construction of libraries of reusable, adaptable software components. The operations may be implemented as subprograms using conventional sequential control structures, or as entries that include synchronization of concurrent threads of control as part of their invocation. The language treats modularity in the physical sense as well, with a facility to support separate compilation. 2 The language includes a complete facility for the support of real-time, concurrent programming. Errors can be signaled as exceptions and handled explicitly. The language also covers systems programming; this requires precise control over the representation of data and access to system-dependent properties. Finally, a predefined environment of standard packages is provided, including facilities for, among others, input-output, string manipulation, numeric elementary functions, and random number generation. 2.a Discussion: This Annotated Ada Reference Manual (AARM) contains the entire text of the Ada Reference Manual (RM9X), plus certain annotations. The annotations give a more in-depth analysis of the language. They describe the reason for each non-obvious rule, and point out interesting ramifications of the rules and interactions among the rules (interesting to language lawyers, that is). Differences between Ada 83 and Ada 9X are listed. (The text you are reading now is an annotation.) 2.b The AARM stresses detailed correctness and uniformity over readability and understandability. We're not trying to make the language ``appear'' simple here; on the contrary, we're trying to expose hidden complexities, so we can more easily detect language bugs. The RM9X, on the other hand, is intended to be a more readable document for programmers. 2.c The annotations in the AARM are as follows: 2.d Text that is logically redundant is shown [in square brackets, like this]. Technically, such text could be written as a Note in the RM9X, since it is really a theorem that can be proven from the non-redundant rules of the language. We use the square brackets instead when it seems to make the RM9X more readable. 2.e The rules of the language (and some AARM-only text) are categorized, and placed under certain sub-headings that indicate the category. For example, the distinction between Name Resolution Rules and Legality Rules is particularly important, as explained in 8.6. 2.f Text under the following sub-headings appears in both documents: 2.g The unlabeled text at the beginning of each clause or subclause, 2.h Syntax, 2.i Name Resolution Rules, 2.j Legality Rules, 2.k Static Semantics, 2.l Post-Compilation Rules, 2.m Dynamic Semantics, 2.n Bounded (Run-Time) Errors, 2.o Erroneous Execution, 2.p Implementation Requirements, 2.q Documentation Requirements, 2.r Metrics, 2.s Implementation Permissions, 2.t Implementation Advice, 2.u NOTES, 2.v Examples. 2.w Text under the following sub-headings does not appear in the RM9X: 2.x Language Design Principles, 2.y Inconsistencies With Ada 83, 2.z Incompatibilities With Ada 83, 2.aa Extensions to Ada 83, 2.bb Wording Changes From Ada 83. 2.cc The AARM also includes the following kinds of annotations. These do not necessarily annotate the immediately preceding rule, although they often do. 2.dd Reason: An explanation of why a certain rule is necessary, or why it is worded in a certain way. 2.ee Ramification: An obscure ramification of the rules that is of interest only to language lawyers. (If a ramification of the rules is of interest to programmers, then it appears under NOTES.) 2.ff Proof: An informal proof explaining how a given Note or [marked-as-redundant] piece of text follows from the other rules of the language. 2.gg Implementation Note: A hint about how to implement a feature, or a particular potential pitfall that an implementer needs to be aware of. 2.hh Discussion: Other annotations not covered by the above. 2.ii To be honest: A rule that is considered logically necessary to the definition of the language, but which is so obscure or pedantic that only a language lawyer would care. These are the only annotations that could be considered part of the language definition. 2.jj Glossary entry: The text of a Glossary entry -- this text will also appear in Annex N, ``Glossary''. 2.kk Discussion: In general, RM9X text appears in the normal font, whereas AARM-only text appears in a smaller font. Notes also appear in the smaller font, as recommended by ISO/IEC style guidelines. Ada examples are also usually printed in a smaller font. 2.ll If you have trouble finding things, be sure to use the index. {italics, like this} Each defined term appears there, and also in italics, like this. Syntactic categories defined in BNF are also indexed. 2.mm A definition marked ``[distributed]'' is the main definition for a term whose complete definition is given in pieces distributed throughout the document. The pieces are marked ``[partial]'' or with a phrase explaining what cases the partial definition applies to. 1.1 Scope 1 This International Standard specifies the form and meaning of programs written in Ada. Its purpose is to promote the portability of Ada programs to a variety of data processing systems. 1.1.1 Extent 1 This International Standard specifies: 2 The form of a program written in Ada; 3 The effect of translating and executing such a program; 4 The manner in which program units may be combined to form Ada programs; 5 The language-defined library units that a conforming implemen- tation is required to supply; 6 The permissible variations within the standard, and the manner in which they are to be documented; 7 Those violations of the standard that a conforming implementation is required to detect, and the effect of attempting to translate or execute a program containing such violations; 8 Those violations of the standard that a conforming implementation is not required to detect. 9 This International Standard does not specify: 10 The means whereby a program written in Ada is transformed into object code executable by a processor; 11 The means whereby translation or execution of programs is invoked and the executing units are controlled; 12 The size or speed of the object code, or the relative execution speed of different language constructs; 13 The form or contents of any listings produced by implementations; in particular, the form or contents of error or warning messages; 14 The effect of unspecified execution. 15 The size of a program or program unit that will exceed the capacity of a particular conforming implementation. 1.1.2 Structure 1 This International Standard contains thirteen sections, fourteen annexes, and an index. 2 {core language} The core of the Ada language consists of: 3 Sections 1 through 13 4 Annex A, ``Predefined Language Environment'' 5 Annex B, ``Interface to Other Languages'' 6 Annex J, ``Obsolescent Features'' 7 {Specialized Needs Annexes} {Annex (Specialized Needs)} {application areas} The following Specialized Needs Annexes define features that are needed by certain application areas: 8 Annex C, ``Systems Programming'' 9 Annex D, ``Real-Time Systems'' 10 Annex E, ``Distributed Systems'' 11 Annex F, ``Information Systems'' 12 Annex G, ``Numerics'' 13 Annex H, ``Safety and Security'' 14 {normative} {Annex (normative)} The core language and the Specialized Needs Annexes are normative, except that the material in each of the items listed below is informative: 15 Text under a NOTES or Examples heading. 16 Each clause or subclause whose title starts with the word ``Example'' or ``Examples''. 17 All implementations shall conform to the core language. In addition, an implementation may conform separately to one or more Specialized Needs Annexes. 18 {informative} {non-normative: see informative} {Annex (informative)} The following Annexes are informative: 19 Annex K, ``Language-Defined Attributes'' 20 Annex L, ``Language-Defined Pragmas'' 21 Annex M, ``Implementation-Defined Characteristics'' 22 Annex N, ``Glossary'' 23 Annex P, ``Syntax Summary'' 23.a Discussion: The idea of the Specialized Needs Annexes is that implementations can choose to target certain application areas. For example, an implementation specifically targeted to embedded machines might support the application-specific features for Real-time Systems, but not the application-specific features for Information Systems. 23.b The Specialized Needs Annexes extend the core language only in ways that users, implementations, and standards bodies are allowed to extend the language; for example, via additional library units, attributes, representation items (see 13.1), pragmas, and constraints on semantic details that are left unspecified by the core language. Many implementations already provide much of the functionality defined by Specialized Needs Annexes; our goal is to increase uniformity among implementations by defining standard ways of providing the functionality. 23.c We recommend that the validation procedures allow implemen- tations to validate the core language, plus any set of the Specialized Needs Annexes. We recommend that implementations not be allowed to validate a portion of one of the Specialized Needs Annexes, although implementations can, of course, provide unvalidated support for such portions. We have designed the Specialized Needs Annexes assuming that this recommendation is followed. Thus, our decisions about what to include and what not to include in those annexes are based on the assumption that each annex is validated in an ``all-or-nothing'' manner. 23.d An implementation may, of course, support extensions that are different from (but possibly related to) those defined by one of the Specialized Needs Annexes. We recommend that, where appropriate, implementations do this by adding library units that are children of existing language-defined library packages. 23.e An implementation should not provide extensions that conflict with those defined in the Specialized Needs Annexes, in the following sense: Suppose an implementation supports a certain error-free program that uses only functionality defined in the core and in the Specialized Needs Annexes. The implementation should ensure that that program will still be error free in some possible full implementation of all of the Specialized Needs Annexes, and that the semantics of the program will not change. For example, an implementation should not provide a package with the same name as one defined in one of the Specialized Needs Annexes, but that behaves differently, even if that implementation does not claim conformance to that Annex. 23.f Note that the Specialized Needs Annexes do not conflict with each other; it is the intent that a single implementation can conform to all of them. 24 Each section is divided into clauses and subclauses that have a common structure. Each section, clause, and subclause first introduces its subject. After the introductory text, text is labeled with the following headings: Language Design Principles 24.a These are not rules of the language, but guiding principles or goals used in defining the rules of the language. In some cases, the goal is only partially met; such cases are explained. 24.b This is not part of the definition of the language, and does not appear in the RM9X. Syntax 25 {syntax (under Syntax heading)} {grammar (under Syntax heading)} {context free grammar (under Syntax heading)} {BNF (Backus-Naur Form) (under Syntax heading)} {Backus-Naur Form (BNF) (under Syntax heading)} Syntax rules (indented). Name Resolution Rules 26 {name resolution rules} {overloading rules} {resolution rules} Compile-time rules that are used in name resolution, including overload resolution. 26.a Discussion: These rules are observed at compile time. (We say ``observed'' rather than ``checked,'' because these rules are not individually checked. They are really just part of the Legality Rules in Section 8 that require exactly one interpretation of each constituent of a complete context.) The only rules used in overload resolution are the Syntax Rules and the Name Resolution Rules. 26.b When dealing with non-overloadable declarations it sometimes makes no semantic difference whether a given rule is a Name Resolution Rule or a Legality Rule, and it is sometimes difficult to decide which it should be. We generally make a given rule a Name Resolution Rule only if it has to be. For example, ``The name, if any, in a raise_statement shall be the name of an exception.'' is under ``Legality Rules.'' Legality Rules 27 {legality rules} {compile-time error} {error (compile-time)} Rules that are enforced at compile time. {legal (construct)} {illegal (construct)} A construct is legal if it obeys all of the Legality Rules. 27.a Discussion: These rules are not used in overload resolution. 27.b Note that run-time errors are always attached to exceptions; for example, it is not ``illegal'' to divide by zero, it just raises an exception. Static Semantics 28 {static semantics} {compile-time semantics} A definition of the compile-time effect of each construct. 28.a Discussion: The most important compile-time effects represent the effects on the symbol table associated with declarations (implicit or explicit). In addition, we use this heading as a bit of a grab bag for equivalences, package specifications, etc. For example, this is where we put statements like so-and-so is equivalent to such-and-such. (We ought to try to really mean it when we say such things!) Similarly, statements about magically-generated implicit declarations go here. These rules are generally written as statements of fact about the semantics, rather than as a you-shall-do-such-and-such sort of thing. Post-Compilation Rules 29 {post-compilation rules} {post-compilation error} {post-compilation rules} {link-time error: see post-compilation error} {error (link-time)} Rules that are enforced before running a partition. {legal (partition)} {illegal (partition)} A partition is legal if its compilation units are legal and it obeys all of the Post-Compilation Rules. 29.a Discussion: It is not specified exactly when these rules are checked, so long as they are checked for any given partition before that partition starts running. An implementation may choose to check some such rules at compile time, and reject compilation_units accordingly. Alternatively, an implementation may check such rules when the partition is created (usually known as ``link time''), or when the partition is mapped to a particular piece of hardware (but before the partition starts running). Dynamic Semantics 30 {dynamic semantics} {run-time semantics} {run-time error} {error (run-time)} A definition of the run-time effect of each construct. 30.a Discussion: This heading describes what happens at run time. Run-time checks, which raise exceptions upon failure, are described here. Each item that involves a run-time check is marked with the name of the check -- these are the same check names that are used in a pragma Suppress. Principle: Every check should have a name, usable in a pragma Suppress. Bounded (Run-Time) Errors 31 {bounded error} {bounded error} Situations that result in bounded (run-time) errors (see 1.1.5). 31.a Discussion: The ``bounds'' of each such error are described here -- that is, we characterize the set of all possible behaviors that can result from a bounded error occurring at run time. Erroneous Execution 32 {erroneous execution} {erroneous execution} Situations that result in erroneous execution (see 1.1.5). Implementation Requirements 33 {implementation requirements} Additional requirements for conforming implementations. 33.a Discussion: ...as opposed to rules imposed on the programmer. An example might be, ``The smallest representable duration, Duration'Small, shall not be greater than twenty milliseconds.'' 33.b It's really just an issue of how the rule is worded. We could write the same rule as ``The smallest representable duration is an implementation-defined value less than or equal to 20 milliseconds'' and then it would be under ``Static Semantics.'' Documentation Requirements 34 {documentation requirements} {documentation requirements} Documentation requirements for conforming implementations. 34.a Discussion: These requirements are beyond those that are implicitly specified by the phrase ``implementation defined''. The latter require documentation as well, but we don't repeat these cases under this heading. Usually this heading is used for when the description of the documentation requirement is longer and does not correspond directly to one, narrow normative sentence. Metrics 35 {metrics} {metrics} Metrics that are specified for the time/space properties of the execution of certain language constructs. Implementation Permissions 36 {implementation permissions} Additional permissions given to the implementer. 36.a Discussion: For example, ``The implementation is allowed to impose further restrictions on the record aggregates allowed in code statements.'' When there are restrictions on the permission, those restrictions are given here also. For example, ``An implementation is allowed to restrict the kinds of subprograms that are allowed to be main subprograms. However, it shall support at least parameterless procedures.'' -- we don't split this up between here and ``Implementation Requirements.'' Implementation Advice 37 {implementation advice} {advice} Optional advice given to the implementer. The word ``should'' is used to indicate that the advice is a recommendation, not a requirement. It is implementation defined whether or not a given recommendation is obeyed. 37.a Implementation defined: Whether or not each recommendation given in Implementation Advice is followed. 37.b Discussion: The advice generally shows the intended implementation, but the implementer is free to ignore it. The implementer is the sole arbiter of whether or not the advice has been obeyed, if not, whether the reason is a good one, and whether the required documentation is sufficient. {ACVC [Ada Compiler Validation Capability]} {Ada Compiler Validation Capability [ACVC]} It would be wrong for the ACVC to enforce any of this advice. 37.c For example, ``Whenever possible, the implementation should choose a value no greater than fifty microseconds for the smallest representable duration, Duration'Small.'' 37.d We use this heading, for example, when the rule is so low level or implementation-oriented as to be untestable. We also use this heading when we wish to encourage implementations to behave in a certain way in most cases, but we do not wish to burden implementations by requiring the behavior. NOTES 38 (1) {notes} Notes emphasize consequences of the rules described in the (sub)clause or elsewhere. This material is informative. Examples 39 Examples illustrate the possible forms of the constructs described. This material is informative. 39.a Discussion: The next three headings list all language changes between Ada 83 and Ada 9X. Language changes are any change that changes the set of text strings that are legal Ada programs, or changes the meaning of any legal program. Wording changes, such as changes in terminology, are not language changes. Each language change falls into one of the following three categories: Inconsistencies With Ada 83 39.b {inconsistencies with Ada 83} {inconsistencies with Ada 83} This heading lists all of the upward inconsistencies between Ada 83 and Ada 9X. Upward inconsistencies are situations in which a legal Ada 83 program is a legal Ada 9X program with different semantics. This type of upward incompatibility is the worst type for users, so we only tolerate it in rare situations. 39.c (Note that the semantics of a program is not the same thing as the behavior of the program. Because of Ada's indeterminacy, the ``semantics'' of a given feature describes a set of behaviors that can be exhibited by that feature. The set can contain more than one allowed behavior. Thus, when we ask whether the semantics changes, we are asking whether the set of behaviors changes.) 39.d This is not part of the definition of the language, and does not appear in the RM9X. Incompatibilities With Ada 83 39.e {incompatibilities with Ada 83} {incompatibilities with Ada 83} This heading lists all of the upward incompatibilities between Ada 83 and Ada 9X, except for the ones listed under ``Inconsistencies With Ada 83'' above. These are the situations in which a legal Ada 83 program is illegal in Ada 9X. We do not generally consider a change that turns erroneous execution into an exception, or into an illegality, to be upwardly incompatible. 39.f This is not part of the definition of the language, and does not appear in the RM9X. Extensions to Ada 83 39.g {extensions to Ada 83} {extensions to Ada 83} This heading is used to list all upward compatible language changes; that is, language extensions. These are the situations in which a legal Ada 9X program is not a legal Ada 83 program. The vast majority of language changes fall into this category. 39.h This is not part of the definition of the language, and does not appear in the RM9X. 39.i As explained above, the next heading does not represent any language change: Wording Changes From Ada 83 39.j {wording changes from Ada 83} This heading lists some of the non-semantic changes between RM83 and the RM9X. It is incomplete; we have not attempted to list all wording changes, but only the ``interesting'' ones. 39.k This is not part of the definition of the language, and does not appear in the RM9X. 1.1.3 Conformity of an Implementation with the Standard Implementation Requirements 1 {conformance (of an implementation with the Standard)} A conforming implementation shall: 1.a Discussion: {implementation} The implementation is the software and hardware that implements the language. This includes compiler, linker, operating system, hardware, etc. 1.b We first define what it means to ``conform'' in general -- basically, the implementation has to properly implement the normative rules given throughout the standard. Then we define what it means to conform to a Specialized Needs Annex -- the implementation must support the core features plus the features of that Annex. Finally, we define what it means to ``conform to the Standard'' -- this requires support for the core language, and allows partial (but not conflicting) support for the Specialized Needs Annexes. 2 Translate and correctly execute legal programs written in Ada, provided that they are not so large as to exceed the capacity of the implementation; 3 Identify all programs or program units that are so large as to exceed the capacity of the implementation (or raise an appropriate exception at run time); 3.a Implementation defined: Capacity limitations of the implementation. 4 Identify all programs or program units that contain errors whose detection is required by this International Standard; 4.a Discussion: Note that we no longer use the term ``rejection'' of programs or program units. We require that programs or program units with errors or that exceed some capacity limit be ``identified.'' The way in which errors or capacity problems are reported is not specified. 4.b An implementation is allowed to use standard error-recovery techniques. We do not disallow such techniques from being used across compilation_unit or compilation boundaries. 4.c See also the Implementation Requirements of 10.2, which disallow the execution of illegal partitions. 5 Supply all language-defined library units required by this International Standard; 5.a Implementation Note: An implementation cannot add to or modify the visible part of a language-defined library unit, except where such permission is explicitly granted, unless such modifications are semantically neutral with respect to the client compilation units of the library unit. An implementation defines the contents of the private part and body of language-defined library units. 5.b An implementation can add with_clauses and use_clauses, since these modifications are semantically neutral to clients. (The implementation might need with_clauses in order to implement the private part, for example.) Similarly, an implementation can add a private part even in cases where a private part is not shown in the standard. Explicit declarations can be provided implicitly or by renaming, provided the changes are semantically neutral. 5.c {italics (implementation-defined)} Wherever in the standard the text of a language-defined library unit contains an italicized phrase starting with ``implementation-defined'', the implementation's version will replace that phrase with some implementation-defined text that is syntactically legal at that place, and follows any other applicable rules. 5.d Note that modifications are permitted, even if there are other tools in the environment that can detect the changes (such as a program library browser), so long as the modifications make no difference with respect to the static or dynamic semantics of the resulting programs, as defined by the standard. 6 Contain no variations except those explicitly permitted by this International Standard, or those that are impossible or impractical to avoid given the implementation's execution environment; 6.a Implementation defined: Variations from the standard that are impractical to avoid given the implementation's execution environment. 6.b Reason: The ``impossible or impractical'' wording comes from AI-325. It takes some judgement and common sense to interpret this. Restricting compilation units to less than 4 lines is probably unreasonable, whereas restricting them to less than 4 billion lines is probably reasonable (at least given today's technology). We do not know exactly where to draw the line, so we have to make the rule vague. 7 Specify all such variations in the manner prescribed by this International Standard. 8 {external effect (of the execution of an Ada program)} {effect (external)} The external effect of the execution of an Ada program is defined in terms of its interactions with its external environment. {external interaction} The following are defined as external interactions: 9 Any interaction with an external file (see A.7); 10 The execution of certain code_statements (see 13.8); which code_ statements cause external interactions is implementation defined. 10.a Implementation defined: Which code_statements cause external interactions. 11 Any call on an imported subprogram (see Annex B), including any parameters passed to it; 12 Any result returned or exception propagated from a main subprogram (see 10.2) or an exported subprogram (see Annex B) to an external caller; 12.a Discussion: By ``result returned'' we mean to include function results and values returned in [in] out parameters. 13 [Any read or update of an atomic or volatile object (see C.6);] 14 The values of imported and exported objects (see Annex B) at the time of any other interaction with the external environment. 14.a To be honest: Also other uses of imported and exported entities, as defined by the implementation, if the implementation supports such pragmas. 15 A conforming implementation of this International Standard shall produce for the execution of a given Ada program a set of interactions with the external environment whose order and timing are consistent with the definitions and requirements of this International Standard for the semantics of the given program. 15.a Ramification: There is no need to produce any of the ``internal effects'' defined for the semantics of the program -- all of these can be optimized away -- so long as an appropriate sequence of external interactions is produced. 15.b Discussion: See also 11.6 which specifies various liberties associated with optimizations in the presence of language-defined checks, that could change the external effects that might be produced. These alternative external effects are still consistent with the standard, since 11.6 is part of the standard. 15.c Note also that we only require ``an appropriate sequence of external interactions'' rather than ``the same sequence...'' An optimizer may cause a different sequence of external interactions to be produced than would be produced without the optimizer, so long as the new sequence still satisfies the requirements of the standard. For example, optimization might affect the relative rate of progress of two concurrent tasks, thereby altering the order in which two external interactions occur. 15.d Note that RM83 explicitly mentions the case of an ``exact effect'' of a program, but since so few programs have their effects defined that exactly, we don't even mention this ``special'' case. In particular, almost any program that uses floating point or tasking has to have some level of inexactness in the specification of its effects. And if one includes aspects of the timing of the external interactions in the external effect of the program (as is appropriate for a real-time language), no ``exact effect'' can be specified. For example, if two external interactions initiated by a single task are separated by a ``delay 1.0;'' then the language rules imply that the two external interactions have to be separated in time by at least one second, as defined by the clock associated with the delay_ relative_statement. This in turn implies that the time at which an external interaction occurs is part of the characterization of the external interaction, at least in some cases, again making the specification of the required ``exact effect'' impractical. 16 An implementation that conforms to this Standard shall support each capability required by the core language as specified. In addition, an implementation that conforms to this Standard may conform to one or more Specialized Needs Annexes (or to none). Conformance to a Specialized Needs Annex means that each capability required by the Annex is provided as specified. 16.a Discussion: The last sentence defines what it means to say that an implementation conforms to a Specialized Needs Annex, namely, only by supporting all capabilities required by the Annex. 17 An implementation conforming to this International Standard may provide additional attributes, library units, and pragmas. However, it shall not provide any attribute, library unit, or pragma having the same name as an attribute, library unit, or pragma (respectively) specified in a Specialized Needs Annex unless the provided construct is either as specified in the Specialized Needs Annex or is more limited in capability than that required by the Annex. A program that attempts to use an unsupported capability of an Annex shall either be identified by the implementation before run time or shall raise an exception at run time. 17.a Discussion: The last sentence of the preceding paragraph defines what an implementation is allowed to do when it does not "conform" to a Specialized Needs Annex. In particular, the sentence forbids implementations from providing a construct with the same name as a corresponding construct in a Specialized Needs Annex but with a different syntax (e.g., an extended syntax) or quite different semantics. The phrase concerning "more limited in capability" is intended to give permission to provide a partial implementation, such as not implementing a subprogram in a package or having a restriction not permitted by an implementation that conforms to the Annex. For example, a partial implementation of the package Ada.Decimal might have Decimal.Max_Decimal_Digits as 15 (rather than the required 18). This allows a partial implementation to grow to a fully conforming implementation. 17.b A restricted implementation might be restricted by not providing some subprograms specified in one of the packages defined by an Annex. In this case, a program that tries to use the missing subprogram will usually fail to compile. Alternatively, the implementation might declare the subprogram as abstract, so it cannot be called. {Program_Error (raised by failure of run-time check)} Alternatively, a subprogram body might be implemented just to raise Program_Error. The advantage of this approach is that a program to be run under a fully conforming Annex implementation can be checked syntactically and semantically under an implementation that only partially supports the Annex. Finally, an implementation might provide a package declaration without the corresponding body, so that programs can be compiled, but partitions cannot be built and executed. 17.c To ensure against wrong answers being delivered by a partial implementation, implementers are required to raise an exception when a program attempts to use an unsupported capability and this can be detected only at run time. For example, a partial implementation of Ada.Decimal might require the length of the Currency string to be 1, and hence, an exception would be raised if a subprogram were called in the package Edited_Output with a length greater than 1. Documentation Requirements 18 {documentation requirements} {implementation defined} {unspecified} {specified (not!)} {implementation-dependent: see unspecified} {documentation (required of an implementation)} Certain aspects of the semantics are defined to be either implementation defined or unspecified. In such cases, the set of possible effects is specified, and the implementation may choose any effect in the set. Implementations shall document their behavior in implementation-defined situations, but documentation is not required for unspecified situations. The implementation-defined characteristics are summarized in Annex M. 18.a Discussion: We used to use the term ``implementation dependent'' instead of ``unspecified''. However, that sounded too much like ``implementation defined''. Furthermore, the term ``unspecified'' is used in the ANSI C and POSIX standards for this purpose, so that is another advantage. We also use ``not specified'' and ``not specified by the language'' as synonyms for ``unspecified.'' The documentation requirement is the only difference between implementation defined and unspecified. 18.b Note that the ``set of possible effects'' can be ``all imaginable effects'', as is the case with erroneous execution. 19 The implementation may choose to document implementation-defined behavior either by documenting what happens in general, or by providing some mechanism for the user to determine what happens in a particular case. 19.a Discussion: For example, if the standard says that library unit elaboration order is implementation defined, the implementation might describe (in its user's manual) the algorithm it uses to determine the elaboration order. On the other hand, the implementation might provide a command that produces a description of the elaboration order for a partition upon request from the user. It is also acceptable to provide cross references to existing documentation (for example, a hardware manual), where appropriate. 19.b Note that dependence of a program on implementation-defined or unspecified functionality is not defined to be an error; it might cause the program to be less portable, however. Implementation Advice 20 {Program_Error (raised by failure of run-time check)} If an implementation detects the use of an unsupported Specialized Needs Annex feature at run time, it should raise Program_Error if feasible. 20.a Reason: The reason we don't require Program_Error is that there are situations where other exceptions might make sense. For example, if the Real Time Systems Annex requires that the range of System.Priority include at least 30 values, an implementation could conform to the Standard (but not to the Annex) if it supported only 12 values. Since the rules of the language require Constraint_Error to be raised for out-of-range values, we cannot require Program_Error to be raised instead. 21 If an implementation wishes to provide implementation-defined extensions to the functionality of a language-defined library unit, it should normally do so by adding children to the library unit. 21.a Implementation Note: If an implementation has support code (``run-time system code'') that is needed for the execution of user-defined code, it can put that support code in child packages of System. Otherwise, it has to use some trick to avoid polluting the user's namespace. It is important that such tricks not be available to user-defined code (not in the standard mode, at least) -- that would defeat the purpose. NOTES 22 (2) The above requirements imply that an implementation conforming to this Standard may support some of the capabilities required by a Specialized Needs Annex without supporting all required capabilities. 22.a Discussion: A conforming implementation can partially support a Specialized Needs Annex. Such an implementation does not conform to the Annex, but it does conform to the Standard. 1.1.4 Method of Description and Syntax Notation 1 The form of an Ada program is described by means of a context-free syntax together with context-dependent requirements expressed by narrative rules. 2 The meaning of Ada programs is described by means of narrative rules defining both the effects of each construct and the composition rules for constructs. 3 {syntax (notation)} {grammar (notation)} {context free grammar (notation)} {BNF (Backus-Naur Form) (notation)} {Backus-Naur Form (BNF) (notation)} The context-free syntax of the language is described using a simple variant of Backus-Naur Form. In particular: 4 Lower case words in a sans-serif font, some containing embedded underlines, are used to denote syntactic categories, for example: 5 case_statement 6 Boldface words are used to denote reserved words, for example: 7 array 8 Square brackets enclose optional items. Thus the two following rules are equivalent. 9 return_statement ::= return [expression]; return_statement ::= return; | return expression; 10 Curly brackets enclose a repeated item. The item may appear zero or more times; the repetitions occur from left to right as with an equivalent left-recursive rule. Thus the two following rules are equivalent. 11 term ::= factor {multiplying_operator factor} term ::= factor | term multiplying_operator factor 12 A vertical line separates alternative items unless it occurs immediately after an opening curly bracket, in which case it stands for itself: 13 constraint ::= scalar_constraint | composite_constraint discrete_choice_list ::= discrete_choice {| discrete_choice} 14 {italics (syntax rules)} If the name of any syntactic category starts with an italicized part, it is equivalent to the category name without the italicized part. The italicized part is intended to convey some semantic information. For example subtype_name and task_name are both equivalent to name alone. 14.a Discussion: {LR(1)} {ambiguous grammar} {grammar (resolution of ambiguity)} {grammar (ambiguous)} The grammar given in the RM9X is not LR(1). In fact, it is ambiguous; the ambiguities are resolved by the overload resolution rules (see 8.6). 14.b We often use ``if'' to mean ``if and only if'' in definitions. For example, if we define ``photogenic'' by saying, ``A type is photogenic if it has the following properties...,'' we mean that a type is photogenic if and only if it has those properties. It is usually clear from the context, and adding the ``and only if'' seems too cumbersome. 14.c When we say, for example, ``a declarative_item of a declarative_part'', we are talking about a declarative_item immediately within that declarative_part. When we say ``a declarative_item in, or within, a declarative_part'', we are talking about a declarative_item anywhere in the declarative_part, possibly deeply nested within other declarative_parts. (This notation doesn't work very well for names, since the name ``of'' something also has another meaning.) 14.d When we refer to the name of a language-defined entity (for example, Duration), we mean the language-defined entity even in programs where the declaration of the language-defined entity is hidden by another declaration. For example, when we say that the expected type for the expression of a delay_relative_statement is Duration, we mean the language-defined type Duration that is declared in Standard, not some type Duration the user might have declared. 15 {syntactic category} A syntactic category is a nonterminal in the grammar defined in BNF under ``Syntax.'' Names of syntactic categories are set in a different font, like_this. 16 {Construct} [glossary entry]A construct is a piece of text (explicit or implicit) that is an instance of a syntactic category defined under ``Syntax.'' 16.a Ramification: For example, an expression is a construct. A declaration is a construct, whereas the thing declared by a declaration is an ``entity.'' 16.b Discussion: ``Explicit'' and ``implicit'' don't mean exactly what you might think they mean: The text of an instance of a generic is considered explicit, even though it does not appear explicitly (in the non-technical sense) in the program text, and even though its meaning is not defined entirely in terms of that text. 17 {constituent (of a construct)} A constituent of a construct is the construct itself, or any construct appearing within it. 18 {arbitrary order} Whenever the run-time semantics defines certain actions to happen in an arbitrary order, this means that the implementation shall arrange for these actions to occur in a way that is equivalent to some sequential order, following the rules that result from that sequential order. When evaluations are defined to happen in an arbitrary order, with conversion of the results to some subtypes, or with some run-time checks, the evaluations, conversions, and checks may be arbitrarily interspersed, so long as each expression is evaluated before converting or checking its value. {type conversion [arbitrary order]} {conversion [arbitrary order]} [Note that the effect of a program can depend on the order chosen by the implementation. This can happen, for example, if two actual parameters of a given call have side effects.] 18.a Discussion: Programs will be more portable if their external effect does not depend on the particular order chosen by an implementation. 18.b Ramification: Additional reordering permissions are given in 11.6, ``Exceptions and Optimization''. 18.c There is no requirement that the implementation always choose the same order in a given kind of situation. In fact, the implementation is allowed to choose a different order for two different executions of the same construct. However, we expect most implementations will behave in a relatively predictable manner in most situations. 18.d Reason: The ``sequential order'' wording is intended to allow the programmer to rely on ``benign'' side effects. For example, if F is a function that returns a unique integer by incrementing some global and returning the result, a call such as P(F, F) is OK if the programmer cares only that the two results of F are unique; the two calls of F cannot be executed in parallel, unless the compiler can prove that parallel execution is equivalent to some sequential order. NOTES 19 (3) The syntax rules describing structured constructs are presented in a form that corresponds to the recommended paragraphing. For example, an if_statement is defined as: 20 if_statement ::= if condition then sequence_of_statements {elsif condition then sequence_of_statements} [else sequence_of_statements] end if; 21 (4) The line breaks and indentation in the syntax rules indicate the recommended line breaks and indentation in the corresponding constructs. The preferred places for other line breaks are after semicolons. 1.1.5 Classification of Errors Implementation Requirements 1 The language definition classifies errors into several different categories: 2 Errors that are required to be detected prior to run time by every Ada implementation; 3 These errors correspond to any violation of a rule given in this International Standard, other than those listed below. In particular, violation of any rule that uses the terms shall, allowed, permitted, legal, or illegal belongs to this category. Any program that contains such an error is not a legal Ada program; on the other hand, the fact that a program is legal does not mean, per se, that the program is free from other forms of error. 4 {compile-time error} {error (compile-time)} {link-time error: see post-compilation error} {error (link-time)} The rules are further classified as either compile time rules, or post compilation rules, depending on whether a violation has to be detected at the time a compilation unit is submitted to the compiler, or may be postponed until the time a compilation unit is incorporated into a partition of a program. 4.a Ramification: See, for example, 10.1.3, ``Subunits of Compilation Units'', for some errors that are detected only after compilation. Implementations are allowed, but not required, to detect post compilation rules at compile time when possible. 5 Errors that are required to be detected at run time by the execution of an Ada program; 6 {run-time error} {error (run-time)} The corresponding error situations are associated with the names of the predefined exceptions. Every Ada compiler is required to generate code that raises the corresponding exception if such an error situation arises during program execution. [If such an error situation is certain to arise in every execution of a construct, then an implementation is allowed (although not required) to report this fact at compilation time.] 7 Bounded errors; 8 The language rules define certain kinds of errors that need not be detected either prior to or during run time, but if not detected, the range of possible effects shall be bounded. {bounded error} The errors of this category are called bounded errors. {Program_Error (raised by failure of run-time check)} The possible effects of a given bounded error are specified for each such error, but in any case one possible effect of a bounded error is the raising of the exception Program_Error. 9 Erroneous execution. 10 {erroneous execution} In addition to bounded errors, the language rules define certain kinds of errors as leading to erroneous execution. Like bounded errors, the implementation need not detect such errors either prior to or during run time. Unlike bounded errors, there is no language-specified bound on the possible effect of erroneous execution; the effect is in general not predictable. 10.a Ramification: Executions are erroneous, not programs or parts of programs. Once something erroneous happens, the execution of the entire program is erroneous from that point on, and potentially before given possible reorderings permitted by 11.6 and elsewhere. We cannot limit it to just one partition, since partitions are not required to live in separate address spaces. (But implementations are encouraged to limit it as much as possible.) 10.b Suppose a program contains a pair of things that will be executed ``in an arbitrary order.'' It is possible that one order will result in something sensible, whereas the other order will result in erroneous execution. If the implementation happens to choose the first order, then the execution is not erroneous. This may seem odd, but it is not harmful. 10.c Saying that something is erroneous is semantically equivalent to saying that the behavior is unspecified. However, ``erroneous'' has a slightly more disapproving flavor. Implementation Permissions 11 [{mode of operation (nonstandard)} {nonstandard mode} An implementation may provide nonstandard modes of operation. Typically these modes would be selected by a pragma or by a command line switch when the compiler is invoked. When operating in a nonstandard mode, the implementation may reject compilation_units that do not conform to additional requirements associated with the mode, such as an excessive number of warnings or violation of coding style guidelines. Similarly, in a nonstandard mode, the implementation may apply special optimizations or alternative algorithms that are only meaningful for programs that satisfy certain criteria specified by the implementation. {mode of operation (standard)} {standard mode} In any case, an implementation shall support a standard mode that conforms to the requirements of this International Standard; in particular, in the standard mode, all legal compilation_units shall be accepted.] 11.a Discussion: These permissions are designed to authorize explicitly the support for alternative modes. Of course, nothing we say can prevent them anyway, but this (redundant) paragraph is designed to indicate that such alternative modes are in some sense ``approved'' and even encouraged where they serve the specialized needs of a given user community, so long as the standard mode, designed to foster maximum portability, is always available. Implementation Advice 12 {Program_Error (raised by failure of run-time check)} If an implementation detects a bounded error or erroneous execution, it should raise Program_Error. Wording Changes From Ada 83 12.a Some situations that are erroneous in Ada 83 are no longer errors at all. For example, depending on the parameter passing mechanism when unspecified is possibly non-portable, but not erroneous. 12.b Other situations that are erroneous in Ada 83 are changed to be bounded errors. In particular, evaluating an uninitialized scalar variable is a bounded error. {Program_Error (raised by failure of run-time check)} The possible results are to raise Program_Error (as always), or to produce a machine-representable value (which might not be in the subtype of the variable). {Constraint_Error (raised by failure of run-time check)} Violating a Range_Check or Overflow_Check raises Constraint_Error, even if the value came from an uninitialized variable. This means that optimizers can no longer ``assume'' that all variables are initialized within their subtype's range. Violating a check that is suppressed remains erroneous. 12.c The ``incorrect order dependences'' category of errors is removed. All such situations are simply considered potential non-portabilities. This category was removed due to the difficulty of defining what it means for two executions to have a ``different effect.'' For example, if a function with a side-effect is called twice in a single expression, it is not in principle possible for the compiler to decide whether the correctness of the resulting program depends on the order of execution of the two function calls. A compile time warning might be appropriate, but raising of Program_ Error at run time would not be. 1.2 Normative References 1 {references} {bibliography} The following standards contain provisions which, through reference in this text, constitute provisions of this International Standard. At the time of publication, the editions indicated were valid. All standards are subject to revision, and parties to agreements based on this International Standard are encouraged to investigate the possibility of applying the most recent editions of the standards indicated below. Members of IEC and ISO maintain registers of currently valid International Standards. 2 {ISO/IEC 646:1991} {646:1991, ISO/IEC standard} {character set standard (7-bit)} ISO/IEC 646:1991, Information technology -- ISO 7-bit coded character set for information interchange. 3 {ISO/IEC 1539:1991} {1539:1991, ISO/IEC standard} {FORTRAN standard} ISO/IEC 1539:1991, Information technology -- Programming languages -- FORTRAN. 4 {ISO 1989:1985} {1989:1985, ISO standard} {COBOL standard} ISO 1989:1985, Programming languages -- COBOL. 5 {ISO/IEC 6429:1992} {6429:1992, ISO/IEC standard} {character set standard (control functions)} ISO/IEC 6429:1992, Information technology -- Control functions for coded graphic character sets. 6 {ISO/IEC 8859-1:1987} {8859-1:1987, ISO/IEC standard} {character set standard (8-bit)} ISO/IEC 8859-1:1987, Information processing -- 8-bit single-byte coded character sets -- Part 1: Latin alphabet No. 1. 7 {ISO/IEC 9899:1990} {9899:1990, ISO/IEC standard} {C standard} ISO/IEC 9899:1990, Programming languages -- C. 8 {ISO/IEC 10646-1:1993} {10646-1:1993, ISO/IEC standard} {character set standard (16-bit)} ISO/IEC 10646-1:1993, Information technology -- Universal Multiple-Octet Coded Character Set (UCS) -- Part 1: Architecture and Basic Multilingual Plane. 8.a Discussion: {POSIX} POSIX, Portable Operating System Interface (POSIX) -- Part 1: System Application Program Interface (API) [C Language], The Institute of Electrical and Electronics Engineers, 1990. 1.3 Definitions 1 {italics (terms introduced or defined)} Terms are defined throughout this International Standard, indicated by italic type. Terms explicitly defined in this International Standard are not to be presumed to refer implicitly to similar terms defined elsewhere. Terms not defined in this International Standard are to be interpreted according to the Webster's Third New International Dictionary of the English Language. Informal descriptions of some terms are also given in Annex N, ``Glossary''. 1.a Discussion: The index contains an entry for every defined term. 1.b Glossary entry: Each term defined in Annex N is marked like this. 1.c Discussion: Here are some AARM-only definitions: {Ada Rapporteur Group (ARG)} {ARG} The Ada Rapporteur Group (ARG) interprets the RM83. {Ada Issue (AI)} {AI} An Ada Issue (AI) is a numbered ruling from the ARG. {Ada Commentary Integration Document (ACID)} {ACID} The Ada Commentary Integration Document (ACID) is an edition of RM83 in which clearly marked insertions and deletions indicate the effect of integrating the approved AIs. {Uniformity Rapporteur Group (URG)} {URG} The Uniformity Rapporteur Group (URG) issues recommendations intended to increase uniformity across Ada implementations. {Uniformity Issue (UI)} {UI} A Uniformity Issue (UI) is a numbered recommendation from the URG. Section 2: Lexical Elements 1 [The text of a program consists of the texts of one or more compilations. The text of a compilation is a sequence of lexical elements, each composed of characters; the rules of composition are given in this section. Pragmas, which provide certain information for the compiler, are also described in this section.] 2.1 Character Set 1 {character set} The only characters allowed outside of comments are the graphic_characters and format_effectors. 1.a Ramification: Any character, including an other_control_ function, is allowed in a comment. 1.b Note that this rule doesn't really have much force, since the implementation can represent characters in the source in any way it sees fit. For example, an implementation could simply define that what seems to be a non-graphic, non-format-effector character is actually a representation of the space character. 1.c Discussion: It is our intent to follow the terminology of ISO 10646 BMP where appropriate, and to remain compatible with the character classifications defined in A.3, ``Character Handling''. Note that our definition for graphic_character is more inclusive than that of ISO 10646-1. Syntax 2 character ::= graphic_character | format_effector | other_control_function 3 graphic_character ::= identifier_letter | digit | space_character | special\ _character Static Semantics 4 The character repertoire for the text of an Ada program consists of the collection of characters called the Basic Multilingual Plane (BMP) of the ISO 10646 Universal Multiple-Octet Coded Character Set, plus a set of format_ effectors and, in comments only, a set of other_control_functions; the coded representation for these characters is implementation defined [(it need not be a representation defined within ISO-10646-1)]. 4.a Implementation defined: The coded representation for the text of an Ada program. 5 The description of the language definition in this International Standard uses the graphic symbols defined for Row 00: Basic Latin and Row 00: Latin-1 Supplement of the ISO 10646 BMP; these correspond to the graphic symbols of ISO 8859-1 (Latin-1); no graphic symbols are used in this International Standard for characters outside of Row 00 of the BMP. The actual set of graphic symbols used by an implementation for the visual representation of the text of an Ada program is not specified. {unspecified [partial]} 6 The categories of characters are defined as follows: 7 {identifier_letter} identifier_letter upper_case_identifier_letter | lower_case_identifier_letter 7.a Discussion: We use identifier_letter instead of simply letter because ISO 10646 BMP includes many other characters that would generally be considered "letters." 8 {upper_case_identifier_letter} upper_case_identifier_letter Any character of Row 00 of ISO 10646 BMP whose name begins ``Latin Capital Letter''. 9 {lower_case_identifier_letter} lower_case_identifier_letter Any character of Row 00 of ISO 10646 BMP whose name begins ``Latin Small Letter''. 9.a To be honest: The above rules do not include the ligatures AE and ae. However, the intent is to include these characters as identifier letters. This problem was pointed out by a comment from the Netherlands. 10 {digit} digit One of the characters 0, 1, 2, 3, 4, 5, 6, 7, 8, or 9. 11 {space_character} space_character The character of ISO 10646 BMP named ``Space''. 12 {special_character} special_character Any character of the ISO 10646 BMP that is not reserved for a control function, and is not the space_character, an identifier_letter, or a digit. 12.a Ramification: Note that the no break space and soft hyphen are special_characters, and therefore graphic_characters. They are not the same characters as space and hyphen-minus. 13 {format_effector} format_effector The control functions of ISO 6429 called character tabulation (HT), line tabulation (VT), carriage return (CR), line feed (LF), and form feed (FF). {control character: see also format_effector} 14 {other_control_function} other_control_function Any control function, other than a format_effector, that is allowed in a comment; the set of other_control_functions allowed in comments is implementation defined. 14.a Implementation defined: The control functions allowed in comments. {control character: see also other_control_function} 15 {names of special_characters} {special_character (names)} The following names are used when referring to certain special_characters: {quotation mark} {number sign} {ampersand} {apostrophe} {tick} {left parenthesis} {right parenthesis} {asterisk} {multiply} {plus sign} {comma} {hyphen-minus} {minus} {full stop} {dot} {point} {solidus} {divide} {colon} {semicolon} {less-than sign} {equals sign} {greater-than sign} {low line} {underline} {vertical line} {left square bracket} {right square bracket} {left curly bracket} {right curly bracket} 15.a Discussion: These are the ones that play a special role in the syntax of Ada 9X, or in the syntax rules; we don't bother to define names for all characters. The first name given is the name from ISO 10646-1; the subsequent names, if any, are those used within the standard, depending on context. symbol name symbol name " quotation mark : colon # number sign ; semicolon & ampersand < less-than sign ' apostrophe, tick = equals sign ( left parenthesis > greater-than sign ) right parenthesis _ low line, underline * asterisk, multiply | vertical line + plus sign [ left square bracket , comma ] right square bracket - hyphen-minus, minus { left curly bracket . full stop, dot, point } right curly bracket / solidus, divide Implementation Permissions 16 In a nonstandard mode, the implementation may support a different character repertoire[; in particular, the set of characters that are considered identifier_letters can be extended or changed to conform to local conventions]. 16.a Ramification: If an implementation supports other character sets, it defines which characters fall into each category, such as ``identifier_letter,'' and what the corresponding rules of this section are, such as which characters are allowed in the text of a program. NOTES 17 (1) Every code position of ISO 10646 BMP that is not reserved for a control function is defined to be a graphic_character by this International Standard. This includes all code positions other than 0000 - 001F, 007F - 009F, and FFFE - FFFF. 18 (2) The language does not specify the source representation of programs. 18.a Discussion: Any source representation is valid so long as the implementer can produce an (information-preserving) algorithm for translating both directions between the representation and the standard character set. (For example, every character in the standard character set has to be representable, even if the output devices attached to a given computer cannot print all of those characters properly.) From a practical point of view, every implementer will have to provide some way to process the ACVC. It is the intent to allow source representations, such as parse trees, that are not even linear sequences of characters. It is also the intent to allow different fonts: reserved words might be in bold face, and that should be irrelevant to the semantics. Extensions to Ada 83 18.b {extensions to Ada 83} Ada 9X allows 8-bit and 16-bit characters, as well as implementation-specified character sets. Wording Changes From Ada 83 18.c The syntax rules in this clause are modified to remove the emphasis on basic characters vs. others. (In this day and age, there is no need to point out that you can write programs without using (for example) lower case letters.) In particular, character (representing all characters usable outside comments) is added, and basic_graphic_character, other_special_character, and basic_character are removed. Special_character is expanded to include Ada 83's other_special_character, as well as new 8-bit characters not present in Ada 83. Note that the term ``basic letter'' is used in A.3, ``Character Handling'' to refer to letters without diacritical marks. 18.d Character names now come from ISO 10646. 18.e We use identifier_letter rather than letter since ISO 10646 BMP includes many "letters' that are not permitted in identifiers (in the standard mode). 2.2 Lexical Elements, Separators, and Delimiters Static Semantics 1 {text of a program} The text of a program consists of the texts of one or more compilations. {lexical element} {token: see lexical element} The text of each compilation is a sequence of separate lexical elements. Each lexical element is formed from a sequence of characters, and is either a delimiter, an identifier, a reserved word, a numeric_literal, a character_literal, a string_literal, or a comment. The meaning of a program depends only on the particular sequences of lexical elements that form its compilations, excluding comments. 2 The text of a compilation is divided into {line} lines. {end of a line} In general, the representation for an end of line is implementation defined. 2.a Implementation defined: The representation for an end of line. However, a sequence of one or more format_effectors other than character tabulation (HT) signifies at least one end of line. 3 {separator} [In some cases an explicit separator is required to separate adjacent lexical elements.] A separator is any of a space character, a format effector, or the end of a line, as follows: 3.a Discussion: It might be useful to define ``white space'' and use it here. 4 A space character is a separator except within a comment, a string_literal, or a character_literal. 5 Character tabulation (HT) is a separator except within a comment. 6 The end of a line is always a separator. 7 One or more separators are allowed between any two adjacent lexical elements, before the first of each compilation, or after the last. At least one separator is required between an identifier, a reserved word, or a numeric_literal and an adjacent identifier, reserved word, or numeric_ literal. 8 {delimiter} A delimiter is either one of the following special characters 9 & ' ( ) * + , - . / : ; < = > | 10 {compound delimiter} or one of the following compound delimiters each composed of two adjacent special characters 11 => .. ** := /= >= <= << >> <> 12 Each of the special characters listed for single character delimiters is a single delimiter except if this character is used as a character of a compound delimiter, or as a character of a comment, string_literal, character_literal, or numeric_literal. 13 The following names are used when referring to compound delimiters: 14 delimiter name => arrow .. double dot ** double star, exponentiate := assignment (pronounced: ``becomes'') /= inequality (pronounced: ``not equal'') >= greater than or equal <= less than or equal << left label bracket >> right label bracket <> box Implementation Requirements 15 An implementation shall support lines of at least 200 characters in length, not counting any characters used to signify the end of a line. An implementation shall support lexical elements of at least 200 characters in length. The maximum supported line length and lexical element length are implementation defined. 15.a Implementation defined: Maximum supported line length and lexical element length. 15.b Discussion: From URG recommendation. 2.3 Identifiers 1 Identifiers are used as names. Syntax 2 identifier ::= identifier_letter {[underline] letter_or_digit} 3 letter_or_digit ::= identifier_letter | digit 4 An identifier shall not be a reserved word. Static Semantics 5 All characters of an identifier are significant, including any underline character. {case insensitive} Identifiers differing only in the use of corresponding upper and lower case letters are considered the same. 5.a Discussion: Two of the letters of ISO 8859-1 appear only as lower case, "sharp s" and "y with diaeresis." These two letters have no corresponding upper case letter (in particular, they are not considered equivalent to one another). Implementation Permissions 6 In a nonstandard mode, an implementation may support other upper/lower case equivalence rules for identifiers[, to accommodate local conventions]. Examples 7 Examples of identifiers: 8 Count X Get_Symbol Ethelyn Marion Snobol_4 X1 Page_Count Store_Next_Item Wording Changes From Ada 83 8.a We no longer include reserved words as identifiers. This is not a language change. In Ada 83, identifier included reserved words. However, this complicated several other rules (for example, regarding implementation-defined attributes and pragmas, etc.). We now explicitly allow certain reserved words for attribute designators, to make up for the loss. 8.b Ramification: Because syntax rules are relevant to overload resolution, it means that if it looks like a reserved word, it is not an identifier. As a side effect, implementations cannot use reserved words as implementation-defined attributes or pragma names. 2.4 Numeric Literals 1 {literal (numeric)} There are two kinds of numeric_literals, real literals and integer literals. {real literal} A real literal is a numeric_ literal that includes a point; {integer literal} an integer literal is a numeric_literal without a point. Syntax 2 numeric_literal ::= decimal_literal | based_literal NOTES 3 (3) The type of an integer literal is universal_integer. The type of a real literal is universal_real. 2.4.1 Decimal Literals 1 {literal (decimal)} A decimal_literal is a numeric_literal in the conventional decimal notation (that is, the base is ten). Syntax 2 decimal_literal ::= numeral [.numeral] [exponent] 3 numeral ::= digit {[underline] digit} 4 exponent ::= E [+] numeral | E - numeral 5 An exponent for an integer literal shall not have a minus sign. 5.a Ramification: Although this rule is in this subclause, it applies also to the next subclause. Static Semantics 6 An underline character in a numeric_literal does not affect its meaning. The letter E of an exponent can be written either in lower case or in upper case, with the same meaning. 6.a Ramification: Although these rules are in this subclause, they apply also to the next subclause. 7 An exponent indicates the power of ten by which the value of the decimal_ literal without the exponent is to be multiplied to obtain the value of the decimal_literal with the exponent. Examples 8 Examples of decimal literals: 9 12 0 1E6 123_456 -- integer literals 12.0 0.0 0.456 3.14159_26 -- real literals Wording Changes From Ada 83 9.a We have changed the syntactic category name integer to be numeral. We got this idea from ACID. It avoids the confusion between this and integers. (Other places don't offer similar confusions. For example, a string_literal is different from a string.) 2.4.2 Based Literals 1 [{literal (based)} {binary literal} {base 2 literal} {binary (literal)} {octal literal} {base 8 literal} {octal (literal)} {hexadecimal literal} {base 16 literal} {hexadecimal (literal)} A based_literal is a numeric_ literal expressed in a form that specifies the base explicitly.] Syntax 2 based_literal ::= base # based_numeral [.based_numeral] # [exponent] 3 base ::= numeral 4 based_numeral ::= extended_digit {[underline] extended_digit} 5 extended_digit ::= digit | A | B | C | D | E | F Legality Rules 6 {base} The base (the numeric value of the decimal numeral preceding the first #) shall be at least two and at most sixteen. The extended_digits A through F represent the digits ten through fifteen, respectively. The value of each extended_digit of a based_literal shall be less than the base. Static Semantics 7 The conventional meaning of based notation is assumed. An exponent indicates the power of the base by which the value of the based_literal without the exponent is to be multiplied to obtain the value of the based_ literal with the exponent. The base and the exponent, if any, are in decimal notation. 8 The extended_digits A through F can be written either in lower case or in upper case, with the same meaning. Examples 9 Examples of based literals: 10 2#1111_1111# 16#FF# 016#0ff# -- integer literal\ s of value 255 16#E#E1 2#1110_0000# -- integer literal\ s of value 224 16#F.FF#E+2 2#1.1111_1111_1110#E11 -- real literals o\ f value 4095.0 Wording Changes From Ada 83 10.a The rule about which letters are allowed is now encoded in BNF, as suggested by Mike Woodger. This is clearly more readable. 2.5 Character Literals 1 [A character_literal is formed by enclosing a graphic character between two apostrophe characters.] Syntax 2 character_literal ::= 'graphic_character' NOTES 3 (4) A character_literal is an enumeration literal of a character type. See 3.5.2. Examples 4 Examples of character literals: 5 'A' '*' ''' ' ' Wording Changes From Ada 83 5.a The definitions of the values of literals are in Sections 3 and 4, rather than here, since it requires knowledge of types. 2.6 String Literals 1 [A string_literal is formed by a sequence of graphic characters (possibly none) enclosed between two quotation marks used as string brackets. They are used to represent operator_symbols (see 6.1), values of a string type (see 4.2), and array subaggregates (see 4.3.3). {quoted string: see string_ literal}] Syntax 2 string_literal ::= "{string_element}" 3 string_element ::= "" | non_quotation_mark_graphic_character 4 A string_element is either a pair of quotation marks (""), or a single graphic_character other than a quotation mark. Static Semantics 5 {sequence of characters (of a string_literal)} The sequence of characters of a string_literal is formed from the sequence of string_elements between the bracketing quotation marks, in the given order, with a string_element that is "" becoming a single quotation mark in the sequence of characters, and any other string_element being reproduced in the sequence. 6 {null string literal} A null string literal is a string_literal with no string_elements between the quotation marks. NOTES 7 (5) An end of line cannot appear in a string_literal. Examples 8 Examples of string literals: 9 "Message of the day:" "" -- a null string literal " " "A" """" -- three string literals of length 1 "Characters such as $, %, and } are allowed in string literals" Wording Changes From Ada 83 9.a The wording has been changed to be strictly lexical. No mention is made of string or character values, since string_literals are also used to represent operator_symbols, which don't have a defined value. 9.b The syntax is described differently. 2.7 Comments 1 A comment starts with two adjacent hyphens and extends up to the end of the line. Syntax 2 comment ::= --{non_end_of_line_character} 3 A comment may appear on any line of a program. Static Semantics 4 The presence or absence of comments has no influence on whether a program is legal or illegal. Furthermore, comments do not influence the meaning of a program; their sole purpose is the enlightenment of the human reader. Examples 5 Examples of comments: 6 -- the last sentence above echoes the Algol 68 report end; -- processing of Line is complete -- a long comment may be split onto -- two or more consecutive lines ---------------- the first two hyphens start the comment 2.8 Pragmas 1 {Pragma} [glossary entry]A pragma is a compiler directive. There are language-defined pragmas that give instructions for optimization, listing control, etc. An implementation may support additional (implementation- defined) pragmas. Syntax 2 pragma ::= pragma identifier [(pragma_argument_association {, pragma_argument_assoc\ iation})]; 3 pragma_argument_association ::= [pragma_argument_identifier =>] name | [pragma_argument_identifier =>] expression 4 In a pragma, any pragma_argument_associations without a pragma_ argument_identifier shall precede any associations with a pragma_ argument_identifier. 5 Pragmas are only allowed at the following places in a program: 6 After a semicolon delimiter, but not within a formal_part or discriminant_part. 7 At any place where the syntax rules allow a construct defined by a syntactic category whose name ends with "declaration", "statement", "clause", or "alternative", or one of the syntactic categories variant or exception_handler; but not in place of such a construct. Also at any place where a compilation_unit would be allowed. 8 Additional syntax rules and placement restrictions exist for specific pragmas. 8.a Discussion: The above rule is written in text, rather than in BNF; the syntactic category pragma is not used in any BNF syntax rule. 8.b Ramification: A pragma is allowed where a generic_formal_ parameter_declaration is allowed. 9 {name (of a pragma)} {pragma name} The name of a pragma is the identifier following the reserved word pragma. {pragma argument} {argument of a pragma} The name or expression of a pragma_argument_association is a pragma argument. 10 {identifier specific to a pragma} {pragma, identifier specific to} An identifier specific to a pragma is an identifier that is used in a pragma argument with special meaning for that pragma. 10.a To be honest: Whenever the syntax rules for a given pragma allow "identifier" as an argument of the pragma, that identifier is an identifier specific to that pragma. Static Semantics 11 If an implementation does not recognize the name of a pragma, then it has no effect on the semantics of the program. Inside such a pragma, the only rules that apply are the Syntax Rules. 11.a To be honest: This rule takes precedence over any other rules that imply otherwise. 11.b Ramification: Note well: this rule applies only to pragmas whose name is not recognized. If anything else is wrong with a pragma (at compile time), the pragma is illegal. This is true whether the pragma is language defined or implementation defined. 11.c For example, an expression in an unrecognized pragma does not cause freezing, even though the rules in 13.14, ``Freezing Rules'' say it does; the above rule overrules those other rules. On the other hand, an expression in a recognized pragma causes freezing, even if this makes something illegal. 11.d For another example, an expression that would be ambiguous is not illegal if it is inside an unrecognized pragma. 11.e Note, however, that implementations have to recognize pragma Inline(Foo) and freeze things accordingly, even if they choose to never do inlining. 11.f Obviously, the contradiction needs to be resolved one way or the other. The reasons for resolving it this way are: The implementation is simple -- the compiler can just ignore the pragma altogether. The interpretation of constructs appearing inside implementation-defined pragmas is implementation defined. For example: ``pragma Mumble(X);''. If the current implementation has never heard of Mumble, then it doesn't know whether X is a name, an expression, or an identifier specific to the pragma Mumble. 11.g To be honest: The syntax of individual pragmas overrides the general syntax for pragma. 11.h Ramification: Thus, an identifier specific to a pragma is not a name, syntactically; if it were, the visibility rules would be invoked, which is not what we want. 11.i This also implies that named associations do not allow one to give the arguments in an arbitrary order -- the order given in the syntax rule for each individual pragma must be obeyed. However, it is generally possible to leave out earlier arguments when later ones are given; for example, this is allowed by the syntax rule for pragma Import (see B.1, ``Interfacing Pragmas''). As for subprogram calls, positional notation precedes named notation. 11.j Note that Ada 83 had no pragmas for which the order of named associations mattered, since there was never more than one argument that allowed named associations. 11.k To be honest: The interpretation of the arguments of implementation-defined pragmas is implementation defined. However, the syntax rules have to be obeyed. Dynamic Semantics 12 {execution [pragma]} {elaboration [pragma]} Any pragma that appears at the place of an executable construct is executed. Unless otherwise specified for a particular pragma, this execution consists of the evaluation of each evaluable pragma argument in an arbitrary order. 12.a Ramification: For a pragma that appears at the place of an elaborable construct, execution is elaboration. 12.b An identifier specific to a pragma is neither a name nor an expression -- such identifiers are not evaluated (unless an implementation defines them to be evaluated in the case of an implementation-defined pragma). 12.c The ``unless otherwise specified'' part allows us (and implementations) to make exceptions, so a pragma can contain an expression that is not evaluated. Note that pragmas in type_ definitions may contain expressions that depend on discriminants. 12.d When we wish to define a pragma with some run-time effect, we usually make sure that it appears in an executable context; otherwise, special rules are needed to define the run-time effect and when it happens. Implementation Requirements 13 The implementation shall give a warning message for an unrecognized pragma name. 13.a Ramification: An implementation is also allowed to have modes in which a warning message is suppressed, or in which the presence of an unrecognized pragma is a compile-time error. Implementation Permissions 14 An implementation may provide implementation-defined pragmas; the name of an implementation-defined pragma shall differ from those of the language-defined pragmas. 14.a Implementation defined: Implementation-defined pragmas. 14.b Ramification: The semantics of implementation-defined pragmas, and any associated rules (such as restrictions on their placement or arguments), are, of course, implementation defined. Implementation-defined pragmas may have run-time effects. 15 An implementation may ignore an unrecognized pragma even if it violates some of the Syntax Rules, if detecting the syntax error is too complex. 15.a Reason: Many compilers use extra post-parsing checks to enforce the syntax rules, since the Ada syntax rules are not LR(k) (for any k). (The grammar is ambiguous, in fact.) This paragraph allows them to ignore an unrecognized pragma, without having to perform such post-parsing checks. Implementation Advice 16 Normally, implementation-defined pragmas should have no semantic effect for error-free programs; that is, if the implementation-defined pragmas are removed from a working program, the program should still be legal, and should still have the same semantics. 16.a Ramification: Note that ``semantics'' is not the same as ``effect;'' as explained in 1.1.3, the semantics defines a set of possible effects. 16.b Note that adding a pragma to a program might cause an error (either at compile time or at run time). On the other hand, if the language-specified semantics for a feature are in part implementation defined, it makes sense to support pragmas that control the feature, and that have real semantics; thus, this paragraph is merely a recommendation. 17 Normally, an implementation should not define pragmas that can make an illegal program legal, except as follows: 18 A pragma used to complete a declaration, such as a pragma Import; 19 A pragma used to configure the environment by adding, removing, or replacing library_items. 19.a Ramification: For example, it is OK to support Interface, System_Name, Storage_Unit, and Memory_Size pragmas for upward compatibility reasons, even though all of these pragmas can make an illegal program legal. (The latter three can affect legality in a rather subtle way: They affect the value of named numbers in System, and can therefore affect the legality in cases where static expressions are required.) 19.b On the other hand, adding implementation-defined pragmas to a legal program can make it illegal. For example, a common kind of implementation-defined pragma is one that promises some property that allows more efficient code to be generated. If the promise is a lie, it is best if the user gets an error message. Incompatibilities With Ada 83 19.c {incompatibilities with Ada 83} In Ada 83, ``bad'' pragmas are ignored. In Ada 9X, they are illegal, except in the case where the name of the pragma itself is not recognized by the implementation. Extensions to Ada 83 19.d {extensions to Ada 83} Implementation-defined pragmas may affect the legality of a program. Wording Changes From Ada 83 19.e Implementation-defined pragmas may affect the run-time semantics of the program. This was always true in Ada 83 (since it was not explicitly forbidden by RM83), but it was not clear, because there was no definition of ``executing'' or ``elaborating'' a pragma. Syntax 20 The forms of List, Page, and Optimize pragmas are as follows: 21 pragma List(identifier); 22 pragma Page; 23 pragma Optimize(identifier); 24 [Other pragmas are defined throughout this International Standard, and are summarized in Annex L.] 24.a Ramification: The language-defined pragmas are supported by every implementation, although ``supporting'' some of them (for example, Inline) requires nothing more than checking the arguments, since they act only as advice to the implementation. Static Semantics 25 A pragma List takes one of the identifiers On or Off as the single argument. This pragma is allowed anywhere a pragma is allowed. It specifies that listing of the compilation is to be continued or suspended until a List pragma with the opposite argument is given within the same compilation. The pragma itself is always listed if the compiler is producing a listing. 26 A pragma Page is allowed anywhere a pragma is allowed. It specifies that the program text which follows the pragma should start on a new page (if the compiler is currently producing a listing). 27 A pragma Optimize takes one of the identifiers Time, Space, or Off as the single argument. This pragma is allowed anywhere a pragma is allowed, and it applies until the end of the immediately enclosing declarative region, or for a pragma at the place of a compilation_unit, to the end of the compilation. It gives advice to the implementation as to whether time or space is the primary optimization criterion, or that optional optimizations should be turned off. [It is implementation defined how this advice is followed.] 27.a Implementation defined: Effect of pragma Optimize. 27.b Discussion: For example, a compiler might use Time vs. Space to control whether generic instantiations are implemented with a macro-expansion model, versus a shared-generic-body model. 27.c We don't define what constitutes an ``optimization'' -- in fact, it cannot be formally defined in the context of Ada. One compiler might call something an optional optimization, whereas another compiler might consider that same thing to be a normal part of code generation. Thus, the programmer cannot rely on this pragma having any particular portable effect on the generated code. Some compilers might even ignore the pragma altogether. Examples 28 Examples of pragmas: 29 pragma List(Off); -- turn off listing generation pragma Optimize(Off); -- turn off optional optimizations pragma Inline(Set_Mask); -- generate code for Set_Mask inline pragma Suppress(Range_Check, On => Index); -- turn off range checking on In\ dex Extensions to Ada 83 29.a {extensions to Ada 83} The Optimize pragma now allows the identifier Off to request that normal optimization be turned off. 29.b An Optimize pragma may appear anywhere pragmas are allowed. Wording Changes From Ada 83 29.c We now describe the pragmas Page, List, and Optimize here, to act as examples, and to remove the normative material from Annex L, ``Language-Defined Pragmas'', so it can be entirely an informative annex. 2.9 Reserved Words Syntax 1 2 {reserved word} The following are the reserved words (ignoring upper/lower case distinctions): 2.a Discussion: Reserved words have special meaning in the syntax. In addition, certain reserved words are used as attribute names. 2.b The syntactic category identifier no longer allows reserved words. We have added the few reserved words that are legal explicitly to the syntax for attribute_reference. Allowing identifier to include reserved words has been a source of confusion for some users, and differs from the way they are treated in the C and Pascal language definitions. abort else new return abs elsif not reverse abstract end null accept entry select access exception separate aliased exit of subtype all or and for others tagged array function out task at terminate generic package then begin goto pragma type body private if procedure case in protected until constant is use raise declare range when delay limited record while delta loop rem with digits renames do mod requeue xor NOTES 3 (6) The reserved words appear in lower case boldface in this International Standard, except when used in the designator of an attribute (see 4.1.4). Lower case boldface is also used for a reserved word in a string_literal used as an operator_symbol. This is merely a convention -- programs may be written in whatever typeface is desired and available. Incompatibilities With Ada 83 3.a {incompatibilities with Ada 83} The following words are not reserved in Ada 83, but are reserved in Ada 9X: abstract, aliased, protected, requeue, tagged, until. Wording Changes From Ada 83 3.b The clause entitled ``Allowed Replacements of Characters'' has been moved to Annex J, ``Obsolescent Features''. Section 3: Declarations and Types 1 This section describes the types in the language and the rules for declaring constants, variables, and named numbers. 3.1 Declarations 1 {entity [partial]} The language defines several kinds of named entities that are declared by declarations. {name [partial]} The entity's name is defined by the declaration, usually by a defining_identifier, but sometimes by a defining_character_literal or defining_operator_symbol. 2 There are several forms of declaration. A basic_declaration is a form of declaration defined as follows. Syntax 3 basic_declaration ::= type_declaration | subtype_declaration | object_declaration | number_declaration | subprogram_declaration | abstract_subprogram_declaration | package_declaration | renaming_declaration | exception_declaration | generic_declaration | generic_instantiation 4 defining_identifier ::= identifier Static Semantics 5 {Declaration} [glossary entry]A declaration is a language construct that associates a name with (a view of) an entity. {explicit declaration} {implicit declaration} A declaration may appear explicitly in the program text (an explicit declaration), or may be supposed to occur at a given place in the text as a consequence of the semantics of another construct (an implicit declaration). 5.a Discussion: An implicit declaration generally declares a predefined or inherited operation associated with the definition of a type. This term is used primarily when allowing explicit declarations to override implicit declarations, as part of a type declaration. 6 {declaration} Each of the following is defined to be a declaration: any basic_declaration; an enumeration_literal_specification; a discriminant_ specification; a component_declaration; a loop_parameter_specification; a parameter_specification; a subprogram_body; an entry_declaration; an entry_ index_specification; a choice_parameter_specification; a generic_formal_ parameter_declaration. 6.a Discussion: This list (when basic_declaration is expanded out) contains all syntactic categories that end in "_declaration" or "_specification", except for program unit _specifications. Moreover, it contains subprogram_body. A subprogram_body is a declaration, whether or not it completes a previous declaration. This is a bit strange, subprogram_body is not part of the syntax of basic_ declaration or library_unit_declaration. A renaming-as-body is considered a declaration. An accept_statement is not considered a declaration. Completions are sometimes declarations, and sometimes not. 7 {Definition} [glossary entry]{view} All declarations contain a definition for a view of an entity. A view consists of an identification of the entity (the entity of the view), plus view-specific characteristics that affect the use of the entity through that view (such as mode of access to an object, formal parameter names and defaults for a subprogram, or visibility to components of a type). In most cases, a declaration also contains the definition for the entity itself (a renaming_declaration is an example of a declaration that does not define a new entity, but instead defines a view of an existing entity (see 8.5)). 7.a Glossary entry: {View} (See Definition.) 7.b Discussion: Most declarations define a view (of some entity) whose view-specific characteristics are unchanging for the life of the view. However, subtypes are somewhat unusual in that they inherit characteristics from whatever view of their type is currently visible. Hence, a subtype is not a view of a type; it is more of an indirect reference. By contrast, a private type provides a single, unchanging (partial) view of its full type. 8 {scope [informal definition]} For each declaration, the language rules define a certain region of text called the scope of the declaration (see 8.2). Most declarations associate an identifier with a declared entity. Within its scope, and only there, there are places where it is possible to use the identifier to refer to the declaration, the view it defines, and the associated entity; these places are defined by the visibility rules (see 8.3). {name (of (a view of) an entity)} At such places the identifier is said to be a name of the entity (the direct_name or selector_name); {denote [informal definition]} the name is said to denote the declaration, the view, and the associated entity (see 8.6). {declare} The declaration is said to declare the name, the view, and in most cases, the entity itself. 9 As an alternative to an identifier, an enumeration literal can be declared with a character_literal as its name (see 3.5.1), and a function can be declared with an operator_symbol as its name (see 6.1). 10 {defining name} The syntax rules use the terms defining_identifier, defining_character_literal, and defining_operator_symbol for the defining occurrence of a name; these are collectively called defining names. {usage name} The terms direct_name and selector_name are used for usage occurrences of identifiers, character_literals, and operator_symbols. These are collectively called usage names. 10.a To be honest: The terms identifier, character_literal, and operator_symbol are used directly in contexts where the normal visibility rules do not apply (such as the identifier that appears after the end of a task_body). Analogous conventions apply to the use of designator, which is the collective term for identifier and operator_symbol. Dynamic Semantics 11 {execution [distributed]} The process by which a construct achieves its run-time effect is called execution. {elaboration [distributed]} {evaluation [distributed]} This process is also called elaboration for declarations and evaluation for expressions. One of the terms execution, elaboration, or evaluation is defined by this International Standard for each construct that has a run-time effect. 11.a Glossary entry: {Execution} The process by which a construct achieves its run-time effect is called execution. {elaboration} {evaluation} Execution of a declaration is also called elaboration. Execution of an expression is also called evaluation. 11.b To be honest: The term elaboration is also used for the execution of certain constructs that are not declarations, and the term evaluation is used for the execution of certain constructs that are not expressions. For example, subtype_indications are elaborated, and ranges are evaluated. 11.c For bodies, execution and elaboration are both explicitly defined. When we refer specifically to the execution of a body, we mean the explicit definition of execution for that kind of body, not its elaboration. 11.d Discussion: Technically, "the execution of a declaration" and "the elaboration of a declaration" are synonymous. We use the term "elaboration" of a construct when we know the construct is elaborable. When we are talking about more arbitrary constructs, we use the term "execution". For example, we use the term "erroneous execution", to refer to any erroneous execution, including erroneous elaboration or evaluation. 11.e When we explicitly define evaluation or elaboration for a construct, we are implicitly defining execution of that construct. 11.f We also use the term "execution" for things like statements, which are executable, but neither elaborable nor evaluable. We considered using the term "execution" only for non-elaborable, non-evaluable constructs, and defining the term "action" to mean what we have defined "execution" to mean. We rejected this idea because we thought three terms that mean the same thing was enough -- four would be overkill. Thus, the term "action" is used only informally in the standard (except where it is defined as part of a larger term, such as "protected action"). 11.g To be honest: {elaborable} A construct is elaborable if elaboration is defined for it. {evaluable} A construct is evaluable if evaluation is defined for it. {executable} A construct is executable if execution is defined for it. 11.h Discussion: Don't confuse ``elaborable'' with ``preelaborable'' (defined in 10.2.1). 11.i Evaluation of an evaluable construct produces a result that is either a value, a denotation, or a range. The following are evaluable: expression; name prefix; range; entry_list_iterator; and possibly discrete_range. The last one is curious -- RM83 uses the term ``evaluation of a discrete_range,'' but never defines it. One might presume that the evaluation of a discrete_range consists of the evaluation of the range or the subtype_indication, depending on what it is. But subtype_indications are not evaluated; they are elaborated. 11.j Intuitively, an executable construct is one that has a defined run-time effect (which may be null). Since execution includes elaboration and evaluation as special cases, all elaborable and all evaluable constructs are also executable. Hence, most constructs in Ada are executable. An important exception is that the constructs inside a generic unit are not executable directly, but rather are used as a template for (generally) executable constructs in instances of the generic. NOTES 12 (1) {declare} At compile time, the declaration of an entity declares the entity. {create} At run time, the elaboration of the declaration creates the entity. 12.a Ramification: Syntactic categories for declarations are named either entity_declaration (if they include a trailing semicolon) or entity_specification (if not). 12.b {entity} The various kinds of named entities that can be declared are as follows: an object (including components and parameters), a named number, a type (the name always refers to its first subtype), a subtype, a subprogram (including enumeration literals and operators), a single entry, an entry family, a package, a protected or task unit (which corresponds to either a type or a single object), an exception, a generic unit, a label, and the name of a statement. 12.c Identifiers are also associated with names of pragmas, arguments to pragmas, and with attributes, but these are not user-definable. Wording Changes From Ada 83 12.d The syntax rule for defining_identifier is new. It is used for the defining occurrence of an identifier. Usage occurrences use the direct_name or selector_name syntactic categories. Each occurrence of an identifier (or simple_name), character_literal, or operator_symbol in the Ada 83 syntax rules is handled as follows in Ada 9X: 12.e It becomes a defining_identifier, defining_character_ literal, or defining_operator_symbol (or some syntactic category composed of these), to indicate a defining occurrence; 12.f It becomes a direct_name, in usage occurrences where the usage is required (in Section 8) to be directly visible; 12.g It becomes a selector_name, in usage occurrences where the usage is required (in Section 8) to be visible but not necessarily directly visible; 12.h It remains an identifier, character_literal, or operator_ symbol, in cases where the visibility rules do not apply (such as the designator that appears after the end of a subprogram_body). 12.i For declarations that come in ``two parts'' (program unit declaration plus body, private or incomplete type plus full type, deferred constant plus full constant), we consider both to be defining occurrences. Thus, for example, the syntax for package_body uses defining_identifier after the reserved word body, as opposed to direct_name. 12.j The defining occurrence of a statement name is in its implicit declaration, not where it appears in the program text. Considering the statement name itself to be the defining occurrence would complicate the visibility rules. 12.k The phrase ``visible by selection'' is not used in Ada 9X. It is subsumed by simply ``visible'' and the Name Resolution Rules for selector_names. 12.l (Note that in Ada 9X, a declaration is visible at all places where one could have used a selector_name, not just at places where a selector_name was actually used. Thus, the places where a declaration is directly visible are a subset of the places where it is visible. See Section 8 for details.) 12.m We use the term ``declaration'' to cover _specifications that declare (views of) objects, such as parameter_specifications. In Ada 83, these are referred to as a ``form of declaration,'' but it is not entirely clear that they are considered simply ``declarations.'' 12.n RM83 contains an incomplete definition of "elaborated" in this clause: it defines "elaborated" for declarations, declarative_parts, declarative_items and compilation_units, but "elaboration" is defined elsewhere for various other constructs. To make matters worse, Ada 9X has a different set of elaborable constructs. Instead of correcting the list, it is more maintainable to refer to the term "elaborable," which is defined in a distributed manner. 12.o RM83 uses the term ``has no other effect'' to describe an elaboration that doesn't do anything except change the state from not-yet-elaborated to elaborated. This was a confusing wording, because the answer to ``other than what?'' was to be found many pages away. In Ada 9X, we change this wording to ``has no effect'' (for things that truly do nothing at run time), and ``has no effect other than to establish that so-and-so can happen without failing the Elaboration_Check'' (for things where it matters). 12.p We make it clearer that the term "execution" covers elaboration and evaluation as special cases. This was implied in RM83. For example, "erroneous execution" can include any execution, and RM83-9.4(3) has, "The task designated by any other task object depends on the master whose execution creates the task object;" the elaboration of the master's declarative_part is doing the task creation. 3.2 Types and Subtypes Static Semantics 1 {type} {primitive operation [partial]} A type is characterized by a set of values, and a set of primitive operations which implement the fundamental aspects of its semantics. {object [partial]} An object of a given type is a run-time entity that contains (has) a value of the type. 1.a Glossary entry: {Type} Each object has a type. A type has an associated set of values, and a set of primitive operations which implement the fundamental aspects of its semantics. Types are grouped into classes. The types of a given class share a set of primitive operations. {closed under derivation} Classes are closed under derivation; that is, if a type is in a class, then all of its derivatives are in that class. 1.b Glossary entry: {Subtype} A subtype is a type together with a constraint, which constrains the values of the subtype to satisfy a certain condition. The values of a subtype are a subset of the values of its type. 2 {class (of types)} Types are grouped into classes of types, reflecting the similarity of their values and primitive operations. {language-defined class (of types)} There exist several language-defined classes of types (see NOTES below). {elementary type} Elementary types are those whose values are logically indivisible; {composite type} {component} composite types are those whose values are composed of component values. {aggregate: see also composite type} 2.a Glossary entry: {Class} {closed under derivation} A class is a set of types that is closed under derivation, which means that if a given type is in the class, then all types derived from that type are also in the class. The set of types of a class share common properties, such as their primitive operations. 2.b Glossary entry: {Elementary type} An elementary type does not have components. 2.c Glossary entry: {Composite type} A composite type has components. 2.d Glossary entry: {Scalar type} A scalar type is either a discrete type or a real type. 2.e Glossary entry: {Access type} An access type has values that designate aliased objects. Access types correspond to ``pointer types'' or ``reference types'' in some other languages. 2.f Glossary entry: {Discrete type} A discrete type is either an integer type or an enumeration type. Discrete types may be used, for example, in case_statements and as array indices. 2.g Glossary entry: {Real type} A real type has values that are approximations of the real numbers. Floating point and fixed point types are real types. 2.h Glossary entry: {Integer type} Integer types comprise the signed integer types and the modular types. A signed integer type has a base range that includes both positive and negative numbers, and has operations that may raise an exception when the result is outside the base range. A modular type has a base range whose lower bound is zero, and has operations with ``wraparound'' semantics. Modular types subsume what are called ``unsigned types'' in some other languages. 2.i Glossary entry: {Enumeration type} An enumeration type is defined by an enumeration of its values, which may be named by identifiers or character literals. 2.j Glossary entry: {Character type} A character type is an enumeration type whose values include characters. 2.k Glossary entry: {Record type} A record type is a composite type consisting of zero or more named components, possibly of different types. 2.l Glossary entry: {Record extension} A record extension is a type that extends another type by adding additional components. 2.m Glossary entry: {Array type} An array type is a composite type whose components are all of the same type. Components are selected by indexing. 2.n Glossary entry: {Task type} A task type is a composite type whose values are tasks, which are active entities that may execute concurrently with other tasks. The top-level task of a partition is called the environment task. 2.o Glossary entry: {Protected type} A protected type is a composite type whose components are protected from concurrent access by multiple tasks. 2.p Glossary entry: {Private type} A private type is a partial view of a type whose full view is hidden from its clients. 2.q Glossary entry: {Private extension} A private extension is like a record extension, except that the components of the extension part are hidden from its clients. 3 {scalar type} The elementary types are the scalar types (discrete and real) and the access types (whose values provide access to objects or subprograms). {discrete type} {enumeration type} Discrete types are either integer types or are defined by enumeration of their values (enumeration types). {real type} Real types are either floating point types or fixed point types. 4 The composite types are the record types, record extensions, array types, task types, and protected types. {private type} {private extension} A private type or private extension represents a partial view (see 7.3) of a type, providing support for data abstraction. A partial view is a composite type. 4.a To be honest: The set of all record types do not form a class (because tagged record types can have private extensions), though the set of untagged record types do. In any case, what record types had in common in Ada 83 (component selection) is now a property of the composite class, since all composite types (other than array types) can have discriminants. Similarly, the set of all private types do not form a class (because tagged private types can have record extensions), though the set of untagged private types do. Nevertheless, the set of untagged private types is not particularly ``interesting'' -- more interesting is the set of all nonlimited types, since that is what a generic formal (nonlimited) private type matches. 5 {discriminant} Certain composite types (and partial views thereof) have special components called discriminants whose values affect the presence, constraints, or initialization of other components. Discriminants can be thought of as parameters of the type. 6 {subcomponent} The term subcomponent is used in this International Standard in place of the term component to indicate either a component, or a component of another subcomponent. Where other subcomponents are excluded, the term component is used instead. {part (of an object or value)} Similarly, a part of an object or value is used to mean the whole object or value, or any set of its subcomponents. 6.a Discussion: The definition of ``part'' here is designed to simplify rules elsewhere. By design, the intuitive meaning of ``part'' will convey the correct result to the casual reader, while this formalistic definition will answer the concern of the compiler-writer. 6.b We use the term ``part'' when talking about the parent part, ancestor part, or extension part of a type extension. In contexts such as these, the part might represent an empty set of subcomponents (e.g. in a null record extension, or a nonnull extension of a null record). We also use ``part'' when specifying rules such as those that apply to an object with a ``controlled part'' meaning that it applies if the object as a whole is controlled, or any subcomponent is. 7 {constraint [partial]} The set of possible values for an object of a given type can be subjected to a condition that is called a constraint {null constraint} (the case of a null constraint that specifies no restriction is also included)[; the rules for which values satisfy a given kind of constraint are given in 3.5 for range_constraints, 3.6.1 for index_ constraints, and 3.7.1 for discriminant_constraints]. 8 {subtype} A subtype of a given type is a combination of the type, a constraint on values of the type, and certain attributes specific to the subtype. The given type is called the type of the subtype. Similarly, the associated constraint is called the constraint of the subtype. The set of values of a subtype consists of the values of its type that satisfy its constraint. {belong (to a subtype)} Such values belong to the subtype. 8.a Discussion: We make a strong distinction between a type and its subtypes. In particular, a type is not a subtype of itself. There is no constraint associated with a type (not even a null one), and type-related attributes are distinct from subtype-specific attributes. 8.b Discussion: We no longer use the term "base type." All types were "base types" anyway in Ada 83, so the term was redundant, and occasionally confusing. In the RM9X we say simply "the type of the subtype" instead of "the base type of the subtype." 8.c Ramification: The value subset for a subtype might be empty, and need not be a proper subset. 8.d To be honest: Any name of a class of types (such as ``discrete'' or ``real''), or other category of types (such as ``limited'' or ``incomplete'') is also used to qualify its subtypes, as well as its objects, values, declarations, and definitions, such as an ``integer type declaration'' or an ``integer value.'' In addition, if a term such as ``parent subtype'' or ``index subtype'' is defined, then the corresponding term for the type of the subtype is ``parent type'' or ``index type.'' 8.e Discussion: We use these corresponding terms without explicitly defining them, when the meaning is obvious. 9 {constrained} {unconstrained} {constrained (subtype)} {unconstrained (subtype)} A subtype is called an unconstrained subtype if its type has unknown discriminants, or if its type allows range, index, or discriminant constraints, but the subtype does not impose such a constraint; otherwise, the subtype is called a constrained subtype (since it has no unconstrained characteristics). 9.a Discussion: In an earlier version of Ada 9X, "constrained" meant "has a non-null constraint." However, we changed to this definition since we kept having to special case composite non-array/non-discriminated types. It also corresponds better to the (now obsolescent) attribute 'Constrained. 9.b For scalar types, ``constrained'' means ``has a non-null constraint''. For composite types, in implementation terms, ``constrained'' means that the size of all objects of the subtype is the same, assuming a typical implementation model. 9.c Class-wide subtypes are always unconstrained. NOTES 10 (2) Any set of types that is closed under derivation (see 3.4) can be called a ``class'' of types. However, only certain classes are used in the description of the rules of the language -- generally those that have their own particular set of primitive operations (see 3.2.3), or that correspond to a set of types that are matched by a given kind of generic formal type (see 12.5). {language-defined class [partial]} The following are examples of ``interesting'' language-defined classes: elementary, scalar, discrete, enumeration, character, boolean, integer, signed integer, modular, real, floating point, fixed point, ordinary fixed point, decimal fixed point, numeric, access, access-to-object, access-to-subprogram, composite, array, string, (untagged) record, tagged, task, protected, nonlimited. Special syntax is provided to define types in each of these classes. 10.a Discussion: {value} A value is a run-time entity with a given type which can be assigned to an object of an appropriate subtype of the type. {operation} An operation is a program entity that operates on zero or more operands to produce an effect, or yield a result, or both. 10.b Ramification: Note that a type's class depends on the place of the reference -- a private type is composite outside and possibly elementary inside. It's really the view that is elementary or composite. Note that although private types are composite, there are some properties that depend on the corresponding full view -- for example, parameter passing modes, and the constraint checks that apply in various places. 10.c Not every property of types represents a class. For example, the set of all abstract types does not form a class, because this set is not closed under derivation. 10.d The set of limited types forms a class in the sense that it is closed under derivation, but the more interesting class, from the point of generic formal type matching, is the set of all types, limited and nonlimited, since that is what matches a generic formal ``limited'' private type. Note also that a limited type can ``become nonlimited'' under certain circumstances, which makes ``limited'' somewhat problematic as a class of types. 11 These language-defined classes are organized like this: 12 all types elementary scalar discrete enumeration character boolean other enumeration integer signed integer modular integer real floating point fixed point ordinary fixed point decimal fixed point access access-to-object access-to-subprogram composite array string other array untagged record tagged task protected 13 The classes ``numeric'' and ``nonlimited'' represent other classification dimensions and do not fit into the above strictly hierarchical picture. Wording Changes From Ada 83 13.a This clause and its subclauses now precede the clause and subclauses on objects and named numbers, to cut down on the number of forward references. 13.b We have dropped the term "base type" in favor of simply "type" (all types in Ada 83 were "base types" so it wasn't clear when it was appropriate/necessary to say "base type"). Given a subtype S of a type T, we call T the "type of the subtype S." 3.2.1 Type Declarations 1 A type_declaration declares a type and its first subtype. Syntax 2 type_declaration ::= full_type_declaration | incomplete_type_declaration | private_type_declaration | private_extension_declaration 3 full_type_declaration ::= type defining_identifier [known_discriminant_part] is type_definition; | task_type_declaration | protected_type_declaration 4 type_definition ::= enumeration_type_definition | integer_type_definition | real_type_definition | array_type_definition | record_type_definition | access_type_definition | derived_type_definition Legality Rules 5 A given type shall not have a subcomponent whose type is the given type itself. Static Semantics 6 {first subtype} The defining_identifier of a type_declaration denotes the first subtype of the type. The known_discriminant_part, if any, defines the discriminants of the type (see 3.7, ``Discriminants''). The remainder of the type_declaration defines the remaining characteristics of (the view of) the type. 7 {named type} A type defined by a type_declaration is a named type; such a type has one or more nameable subtypes. {anonymous type} Certain other forms of declaration also include type definitions as part of the declaration for an object (including a parameter or a discriminant). The type defined by such a declaration is anonymous -- it has no nameable subtypes. {italics (pseudo-names of anonymous types)} For explanatory purposes, this International Standard sometimes refers to an anonymous type by a pseudo-name, written in italics, and uses such pseudo-names at places where the syntax normally requires an identifier. For a named type whose first subtype is T, this International Standard sometimes refers to the type of T as simply ``the type T.'' 7.a Ramification: The only user-defined types that can be anonymous in the above sense are array, access, task, and protected types. An anonymous array, task, or protected type can be defined as part of an object_declaration. An anonymous access type can be defined as part of a parameter or discriminant specification. 8 {full type} A named type that is declared by a full_type_declaration, or an anonymous type that is defined as part of declaring an object of the type, is called a full type. {full type definition} The type_definition, task_ definition, protected_definition, or access_definition that defines a full type is called a full type definition.[Types declared by other forms of type_ declaration are not separate types; they are partial or incomplete views of some full type.] 8.a To be honest: Class-wide, universal, and root numeric types are full types. 9 {predefined operator [partial]} The definition of a type implicitly declares certain predefined operators that operate on the type, according to what classes the type belongs, as specified in 4.5, ``Operators and Expression Evaluation''. 9.a Discussion: We no longer talk about the implicit declaration of basic operations. These are treated like an if_statement -- they don't need to be declared, but are still applicable to only certain classes of types. 10 {predefined type} The predefined types [(for example the types Boolean, Wide_Character, Integer, root_integer, and universal_integer)] are the types that are defined in [a predefined library package called] Standard[; this package also includes the [(implicit)] declarations of their predefined operators]. [The package Standard is described in A.1.] 10.a Ramification: We use the term ``predefined'' to refer to entities declared in the visible part of Standard, to implicitly declared operators of a type whose semantics are defined by the language, to Standard itself, and to the ``predefined environment''. We do not use this term to refer to library packages other than Standard. For example Text_IO is a language-defined package, not a predefined package, and Text_IO.Put_Line is not a predefined operation. Dynamic Semantics 11 {elaboration [full_type_declaration]} The elaboration of a full_type_ declaration consists of the elaboration of the full type definition. {elaboration [full type definition]} Each elaboration of a full type definition creates a distinct type and its first subtype. 11.a Reason: The creation is associated with the type definition, rather than the type declaration, because there are types that are created by full type definitions that are not immediately contained within a type declaration (e.g. an array object declaration, a singleton task declaration, etc.). 11.b Ramification: Any implicit declarations that occur immediately following the full type definition are elaborated where they (implicitly) occur. Examples 12 Examples of type definitions: 13 (White, Red, Yellow, Green, Blue, Brown, Black) range 1 .. 72 array(1 .. 10) of Integer 14 Examples of type declarations: 15 type Color is (White, Red, Yellow, Green, Blue, Brown, Black); type Column is range 1 .. 72; type Table is array(1 .. 10) of Integer; NOTES 16 (3) Each of the above examples declares a named type. The identifier given denotes the first subtype of the type. Other named subtypes of the type can be declared with subtype_declarations (see 3.2.2). Although names do not directly denote types, a phrase like ``the type Column'' is sometimes used in this International Standard to refer to the type of Column, where Column denotes the first subtype of the type. For an example of the definition of an anonymous type, see the declaration of the array Color_Table in 3.3.1; its type is anonymous -- it has no nameable subtypes. Wording Changes From Ada 83 16.a The syntactic category full_type_declaration now includes task and protected type declarations. 16.b We have generalized the concept of first-named subtype (now called simply ``first subtype'') to cover all kinds of types, for uniformity of description elsewhere. RM83 defined first-named subtype in Section 13. We define first subtype here, because it is now a more fundamental concept. We renamed the term, because in Ada 9X some first subtypes have no name. 16.c We no longer elaborate discriminant_parts, because there is nothing to do, and it was complex to say that you only wanted to elaborate it once for a private or incomplete type. This is also consistent with the fact that subprogram specifications are not elaborated (neither in Ada 83 nor in Ada 9X). Note, however, that an access_definition appearing in a discriminant_part is elaborated when an object with such a discriminant is created. 3.2.2 Subtype Declarations 1 A subtype_declaration declares a subtype of some previously declared type, as defined by a subtype_indication. Syntax 2 subtype_declaration ::= subtype defining_identifier is subtype_indication; 3 subtype_indication ::= subtype_mark [constraint] 4 subtype_mark ::= subtype_name 4.a Ramification: Note that name includes attribute_reference; thus, S'Base can be used as a subtype_mark. 4.b Reason: We considered changing subtype_mark to subtype_name. However, existing users are used to the word "mark," so we're keeping it. 5 constraint ::= scalar_constraint | composite_constraint 6 scalar_constraint ::= range_constraint | digits_constraint | delta_constraint 7 composite_constraint ::= index_constraint | discriminant_constraint Name Resolution Rules 8 A subtype_mark shall resolve to denote a subtype. {determines (a type by a subtype_mark)} The type determined by a subtype_mark is the type of the subtype denoted by the subtype_mark. 8.a Ramification: Types are never directly named; all subtype_ marks denote subtypes -- possibly an unconstrained (base) subtype, but never the type. When we use the term anonymous type we really mean a type with no namable subtypes. Dynamic Semantics 9 {elaboration [subtype_declaration]} The elaboration of a subtype_ declaration consists of the elaboration of the subtype_indication. {elaboration [subtype_indication]} The elaboration of a subtype_indication creates a new subtype. If the subtype_indication does not include a constraint, the new subtype has the same (possibly null) constraint as that denoted by the subtype_mark. The elaboration of a subtype_indication that includes a constraint proceeds as follows: 10 The constraint is first elaborated. 11 {Range_Check [partial]} {check, language-defined (Range_Check)} A check is then made that the constraint is compatible with the subtype denoted by the subtype_mark. 11.a Ramification: The checks associated with constraint compatibility are all Range_Checks. Discriminant_Checks and Index_Checks are associated only with checks that a value satisfies a constraint. 12 The condition imposed by a constraint is the condition obtained after elaboration of the constraint. {compatibility (constraint with a subtype) [distributed]} The rules defining compatibility are given for each form of constraint in the appropriate subclause. These rules are such that if a constraint is compatible with a subtype, then the condition imposed by the constraint cannot contradict any condition already imposed by the subtype on its values. {Constraint_Error (raised by failure of run-time check)} The exception Constraint_Error is raised if any check of compatibility fails. 12.a To be honest: The condition imposed by a constraint is named after it -- a range_constraint imposes a range constraint, etc. 12.b Ramification: A range_constraint causes freezing of its type. Other constraints do not. NOTES 13 (4) A scalar_constraint may be applied to a subtype of an appropriate scalar type (see 3.5, 3.5.9, and J.3), even if the subtype is already constrained. On the other hand, a composite_constraint may be applied to a composite subtype (or an access-to-composite subtype) only if the composite subtype is unconstrained (see 3.6.1 and 3.7.1). Examples 14 Examples of subtype declarations: 15 subtype Rainbow is Color range Red .. Blue; -- see 3.2.1 subtype Red_Blue is Rainbow; subtype Int is Integer; subtype Small_Int is Integer range -10 .. 10; subtype Up_To_K is Column range 1 .. K; -- see 3.2.1 subtype Square is Matrix(1 .. 10, 1 .. 10); -- see 3.6 subtype Male is Person(Sex => M); -- see 3.10.1 Incompatibilities With Ada 83 15.a {incompatibilities with Ada 83} In Ada 9X, all range_ constraints cause freezing of their type. Hence, a type-related representation item for a scalar type has to precede any range_ constraints whose type is the scalar type. Wording Changes From Ada 83 15.b Subtype_marks allow only subtype names now, since types are never directly named. There is no need for RM83-3.3.2(3), which says a subtype_mark can denote both the type and the subtype; in Ada 9X, you denote an unconstrained (base) subtype if you want, but never the type. 15.c The syntactic category type_mark is now called subtype_mark, since it always denotes a subtype. 3.2.3 Classification of Operations Static Semantics 1 {operates on a type} An operation operates on a type T if it yields a value of type T, if it has an operand whose expected type (see 8.6) is T, or if it has an access parameter (see 6.1) designating T. {predefined operation (of a type)} A predefined operator, or other language-defined operation such as assignment or a membership test, that operates on a type, is called a predefined operation of the type. {primitive operations (of a type)} The primitive operations of a type are the predefined operations of the type, plus any user-defined primitive subprograms. 1.a Glossary entry: {Primitive operations} The primitive operations of a type are the operations (such as subprograms) declared together with the type declaration. They are inherited by other types in the same class of types. For a tagged type, the primitive subprograms are dispatching subprograms, providing run-time polymorphism. A dispatching subprogram may be called with statically tagged operands, in which case the subprogram body invoked is determined at compile time. Alternatively, a dispatching subprogram may be called using a dispatching call, in which case the subprogram body invoked is determined at run time. 1.b To be honest: Protected subprograms are not considered to be ``primitive subprograms,'' even though they are subprograms, and they are inherited by derived types. 1.c Discussion: We use the term ``primitive subprogram'' in most of the rest of the manual. The term ``primitive operation'' is used mostly in conceptual discussions. 2 {primitive subprograms (of a type)} The primitive subprograms of a specific type are defined as follows: 3 The predefined operators of the type (see 4.5); 4 For a derived type, the inherited (see 3.4) user-defined subprograms; 5 For an enumeration type, the enumeration literals (which are considered parameterless functions -- see 3.5.1); 6 For a specific type declared immediately within a package_ specification, any subprograms (in addition to the enumeration literals) that are explicitly declared immediately within the same package_specification and that operate on the type; 7 {override (a primitive subprogram)} Any subprograms not covered above [that are explicitly declared immediately within the same declarative region as the type] and that override (see 8.3) other implicitly declared primitive subprograms of the type. 7.a Discussion: In Ada 83, only subprograms declared in the visible part were ``primitive'' (i.e. derivable). In Ada 9X, mostly because of child library units, we include all operations declared in the private part as well, and all operations that override implicit declarations. 7.b Ramification: It is possible for a subprogram to be primitive for more than one type, though it is illegal for a subprogram to be primitive for more than one tagged type. See 3.9. 7.c Discussion: The order of the implicit declarations when there are both predefined operators and inherited subprograms is described in 3.4, ``Derived Types and Classes''. 8 {primitive operator (of a type)} A primitive subprogram whose designator is an operator_symbol is called a primitive operator. Incompatibilities With Ada 83 8.a {incompatibilities with Ada 83} The attribute S'Base is no longer defined for non-scalar subtypes. Since this was only permitted as the prefix of another attribute, and there are no interesting non-scalar attributes defined for an unconstrained composite or access subtype, this should not affect any existing programs. Extensions to Ada 83 8.b {extensions to Ada 83} The primitive subprograms (derivable subprograms) include subprograms declared in the private part of a package specification as well, and those that override implicitly declared subprograms, even if declared in a body. Wording Changes From Ada 83 8.c We have dropped the confusing term operation of a type in favor of the more useful primitive operation of a type and the phrase operates on a type. 8.d The description of S'Base has been moved to 3.5, ``Scalar Types'' because it is now defined only for scalar types. 3.3 Objects and Named Numbers 1 [Objects are created at run time and contain a value of a given type. {creation (of an object)} An object can be created and initialized as part of elaborating a declaration, evaluating an allocator, aggregate, or function_ call, or passing a parameter by copy. Prior to reclaiming the storage for an object, it is finalized if necessary (see 7.6.1).] Static Semantics 2 {object} All of the following are objects: 2.a Glossary entry: {Object} An object is either a constant or a variable. An object contains a value. An object is created by an object_declaration or by an allocator. A formal parameter is (a view of) an object. A subcomponent of an object is an object. 3 the entity declared by an object_declaration; 4 a formal parameter of a subprogram, entry, or generic subprogram; 5 a generic formal object; 6 a loop parameter; 7 a choice parameter of an exception_handler; 8 an entry index of an entry_body; 9 the result of dereferencing an access-to-object value (see 4.1); 10 the result of evaluating a function_call (or the equivalent operator invocation -- see 6.6); 11 the result of evaluating an aggregate; 12 a component, slice, or view conversion of another object. 13 {constant} {variable} {constant object} {variable object} {constant view} {variable view} An object is either a constant object or a variable object. The value of a constant object cannot be changed between its initialization and its finalization, whereas the value of a variable object can be changed. Similarly, a view of an object is either a constant or a variable. All views of a constant object are constant. A constant view of a variable object cannot be used to modify the value of the variable. The terms constant and variable by themselves refer to constant and variable views of objects. 14 {read (the value of an object)} The value of an object is read when the value of any part of the object is evaluated, or when the value of an enclosing object is evaluated. {update (the value of an object)} The value of a variable is updated when an assignment is performed to any part of the variable, or when an assignment is performed to an enclosing object. 14.a Ramification: Reading and updating are intended to include read/write references of any kind, even if they are not associated with the evaluation of a particular construct. Consider, for example, the expression ``X.all(F)'', where X is an access-to-array object, and F is a function. The implementation is allowed to first evaluate ``X.all'' and then F. Finally, a read is performed to get the value of the F'th component of the array. Note that the array is not necessarily read as part of the evaluation of ``X.all''. This is important, because if F were to free X using Unchecked_Deallocation, we want the execution of the final read to be erroneous. 15 Whether a view of an object is constant or variable is determined by the definition of the view. The following (and no others) represent constants: 16 an object declared by an object_declaration with the reserved word constant; 17 a formal parameter or generic formal object of mode in; 18 a discriminant; 19 a loop parameter, choice parameter, or entry index; 20 the dereference of an access-to-constant value; 21 the result of evaluating a function_call or an aggregate; 22 a selected_component, indexed_component, slice, or view conversion of a constant. 22.a To be honest: A noninvertible view conversion to a general access type is also defined to be a constant -- see 4.6. 23 {nominal subtype} At the place where a view of an object is defined, a nominal subtype is associated with the view. {actual subtype} {subtype (of an object): see actual subtype of an object} The object's actual subtype (that is, its subtype) can be more restrictive than the nominal subtype of the view; it always is if the nominal subtype is an indefinite subtype. {indefinite subtype} {definite subtype} A subtype is an indefinite subtype if it is an unconstrained array subtype, or if it has unknown discriminants or unconstrained discriminants without defaults (see 3.7); otherwise the subtype is a definite subtype [(all elementary subtypes are definite subtypes)].[A class-wide subtype is defined to have unknown discriminants, and is therefore an indefinite subtype. An indefinite subtype does not by itself provide enough information to create an object; an additional constraint or explicit initialization expression is necessary (see 3.3.1). A component cannot have an indefinite nominal subtype.] 24 {named number} A named number provides a name for a numeric value known at compile time. It is declared by a number_declaration. NOTES 25 (5) A constant cannot be the target of an assignment operation, nor be passed as an in out or out parameter, between its initialization and finalization, if any. 26 (6) The nominal and actual subtypes of an elementary object are always the same. For a discriminated or array object, if the nominal subtype is constrained then so is the actual subtype. Extensions to Ada 83 26.a {extensions to Ada 83} There are additional kinds of objects (choice parameters and entry indices of entry bodies). 26.b The result of a function and of evaluating an aggregate are considered (constant) objects. This is necessary to explain the action of finalization on such things. Because a function_call is also syntactically a name (see 4.1), the result of a function_call can be renamed, thereby allowing repeated use of the result without calling the function again. Wording Changes From Ada 83 26.c This clause and its subclauses now follow the clause and subclauses on types and subtypes, to cut down on the number of forward references. 26.d The term nominal subtype is new. It is used to distinguish what is known at compile time about an object's constraint, versus what its "true" run-time constraint is. 26.e The terms definite and indefinite (which apply to subtypes) are new. They are used to aid in the description of generic formal type matching, and to specify when an explicit initial value is required in an object_declaration. 26.f We have moved the syntax for object_declaration and number_ declaration down into their respective subclauses, to keep the syntax close to the description of the associated semantics. 26.g We talk about variables and constants here, since the discussion is not specific to object_declarations, and it seems better to have the list of the kinds of constants juxtaposed with the kinds of objects. 26.h We no longer talk about indirect updating due to parameter passing. Parameter passing is handled in 6.2 and 6.4.1 in a way that there is no need to mention it here in the definition of read and update. Reading and updating now includes the case of evaluating or assigning to an enclosing object. 3.3.1 Object Declarations 1 {stand-alone object} {explicit initial value} {initialization expression} An object_declaration declares a stand-alone object with a given nominal subtype and, optionally, an explicit initial value given by an initialization expression. {anonymous array type} {anonymous task type} {anonymous protected type} For an array, task, or protected object, the object_ declaration may include the definition of the (anonymous) type of the object. Syntax 2 object_declaration ::= defining_identifier_list : [aliased] [constant] subtype_indication [:= \ expression]; | defining_identifier_list : [aliased] [constant] array_type_definition [\ := expression]; | single_task_declaration | single_protected_declaration 3 defining_identifier_list ::= defining_identifier {, defining_identifier} Name Resolution Rules 4 {expected type [object_declaration initialization expression]} For an object_declaration with an expression following the compound delimiter :=, the type expected for the expression is that of the object. {initialization expression} This expression is called the initialization expression. {constructor: see initialization expression} Legality Rules 5 An object_declaration without the reserved word constant declares a variable object. If it has a subtype_indication or an array_type_definition that defines an indefinite subtype, then there shall be an initialization expression. An initialization expression shall not be given if the object is of a limited type. Static Semantics 6 An object_declaration with the reserved word constant declares a constant object. {full constant declaration} If it has an initialization expression, then it is called a full constant declaration. {deferred constant declaration} Otherwise it is called a deferred constant declaration. The rules for deferred constant declarations are given in clause 7.4. The rules for full constant declarations are given in this subclause. 7 Any declaration that includes a defining_identifier_list with more than one defining_identifier is equivalent to a series of declarations each containing one defining_identifier from the list, with the rest of the text of the declaration copied for each declaration in the series, in the same order as the list. The remainder of this International Standard relies on this equivalence; explanations are given for declarations with a single defining_identifier. 8 {nominal subtype} The subtype_indication or full type definition of an object_declaration defines the nominal subtype of the object. The object_ declaration declares an object of the type of the nominal subtype. 8.a Discussion: The phrase ``full type definition'' here includes the case of an anonymous array, task, or protected type. Dynamic Semantics 9 {constraint (of an object)} If a composite object declared by an object_ declaration has an unconstrained nominal subtype, then if this subtype is indefinite or the object is constant or aliased (see 3.10) the actual subtype of this object is constrained. The constraint is determined by the bounds or discriminants (if any) of its initial value; {constrained by its initial value} the object is said to be constrained by its initial value. {actual subtype (of an object)} {subtype (of an object): see actual subtype of an object} [In the case of an aliased object, this initial value may be either explicit or implicit; in the other cases, an explicit initial value is required.] When not constrained by its initial value, the actual and nominal subtypes of the object are the same. {constrained (object)} {unconstrained (object)} If its actual subtype is constrained, the object is called a constrained object. 10 {implicit initial values (for a subtype)} For an object_declaration without an initialization expression, any initial values for the object or its subcomponents are determined by the implicit initial values defined for its nominal subtype, as follows: 11 The implicit initial value for an access subtype is the null value of the access type. 12 The implicit initial (and only) value for each discriminant of a constrained discriminated subtype is defined by the subtype. 13 For a (definite) composite subtype, the implicit initial value of each component with a default_expression is obtained by evaluation of this expression and conversion to the component's nominal subtype (which might raise Constraint_Error -- see 4.6, ``Type Conversions''), unless the component is a discriminant of a constrained subtype (the previous case), or is in an excluded variant (see 3.8.1). {implicit subtype conversion [component defaults]} For each component that does not have a default_ expression, any implicit initial values are those determined by the component's nominal subtype. 14 For a protected or task subtype, there is an implicit component (an entry queue) corresponding to each entry, with its implicit initial value being an empty queue. 14.a Implementation Note: The implementation may add implicit components for its own use, which might have implicit initial values. For a task subtype, such components might represent the state of the associated thread of control. For a type with dynamic-sized components, such implicit components might be used to hold the offset to some explicit component. 15 {elaboration [object_declaration]} The elaboration of an object_ declaration proceeds in the following sequence of steps: 16 The subtype_indication, array_type_definition, single_task_ declaration, or single_protected_declaration is first elaborated. This creates the nominal subtype (and the anonymous type in the latter three cases). 17 If the object_declaration includes an initialization expression, the (explicit) initial value is obtained by evaluating the expression and converting it to the nominal subtype (which might raise Constraint_Error -- see 4.6). {implicit subtype conversion [initialization expression]} 18 The object is created, and, if there is not an initialization expression, any per-object expressions (see 3.8) are evaluated and any implicit initial values for the object or for its subcomponents are obtained as determined by the nominal subtype. 18.a Discussion: For a per-object constraint that contains some per-object expressions and some non-per-object expressions, the values used for the constraint consist of the values of the non-per-object expressions evaluated at the point of the type_ declaration, and the values of the per-object expressions evaluated at the point of the creation of the object. 18.b The elaboration of per-object constraints was presumably performed as part of the dependent compatibility check in Ada 83. If the object is of a limited type with an access discriminant, the access_definition is elaborated at this time (see 3.7). 18.c Reason: The reason we say that evaluating an explicit initialization expression happens before creating the object is that in some cases it is impossible to know the size of the object being created until its initial value is known, as in ``X: String := Func_Call(...);''. The implementation can create the object early in the common case where the size can be known early, since this optimization is semantically neutral. 19 {initialization (of an object)} {assignment operation (during elaboration of an object_declaration)} Any initial values (whether explicit or implicit) are assigned to the object or to the corresponding subcomponents. As described in 5.2 and 7.6, Initialize and Adjust procedures can be called. {constructor: see initialization} 19.a Ramification: Since the initial values have already been converted to the appropriate nominal subtype, the only Constraint_Errors that might occur as part of these assignments are for values outside their base range that are used to initialize unconstrained numeric subcomponents. See 3.5. 20 For the third step above, the object creation and any elaborations and evaluations are performed in an arbitrary order, except that if the default_ expression for a discriminant is evaluated to obtain its initial value, then this evaluation is performed before that of the default_expression for any component that depends on the discriminant, and also before that of any default_expression that includes the name of the discriminant. The evaluations of the third step and the assignments of the fourth step are performed in an arbitrary order, except that each evaluation is performed before the resulting value is assigned. 20.a Reason: For example: 20.b type R(D : Integer := F) is record S : String(1..D) := (others => G); end record; 20.c X : R; 20.d For the elaboration of the declaration of X, it is important that F be evaluated before the aggregate. 21 [There is no implicit initial value defined for a scalar subtype.] {uninitialized variables [partial]} In the absence of an explicit initialization, a newly created scalar object might have a value that does not belong to its subtype (see 13.9.1 and H.1). 21.a To be honest: It could even be represented by a bit pattern that doesn't actually represent any value of the type at all, such as an invalid internal code for an enumeration type, or a NaN for a floating point type. It is a generally a bounded error to reference scalar objects with such ``invalid representations'', as explained in 13.9.1, ``Data Validity''. 21.b Ramification: There is no requirement that two objects of the same scalar subtype have the same implicit initial ``value'' (or representation). It might even be the case that two elaborations of the same object_declaration produce two different initial values. However, any particular uninitialized object is default-initialized to a single value (or invalid representation). Thus, multiple reads of such an uninitialized object will produce the same value each time (if the implementation chooses not to detect the error). NOTES 22 (7) Implicit initial values are not defined for an indefinite subtype, because if an object's nominal subtype is indefinite, an explicit initial value is required. 23 (8) {stand-alone constant} {stand-alone variable} As indicated above, a stand-alone object is an object declared by an object_declaration. Similar definitions apply to ``stand-alone constant'' and ``stand-alone variable.'' A subcomponent of an object is not a stand-alone object, nor is an object that is created by an allocator. An object declared by a loop_parameter_specification, parameter_specification, entry_index_ specification, choice_parameter_specification, or a formal_object_ declaration is not called a stand-alone object. 24 (9) The type of a stand-alone object cannot be abstract (see 3.9.3). Examples 25 Example of a multiple object declaration: 26 -- the multiple object declaration 27 John, Paul : Person_Name := new Person(Sex => M); -- see 3.10.1 28 -- is equivalent to the two single object declarations in the order given 29 John : Person_Name := new Person(Sex => M); Paul : Person_Name := new Person(Sex => M); 30 Examples of variable declarations: 31 Count, Sum : Integer; Size : Integer range 0 .. 10_000 := 0; Sorted : Boolean := False; Color_Table : array(1 .. Max) of Color; Option : Bit_Vector(1 .. 10) := (others => True); Hello : constant String := "Hi, world."; 32 Examples of constant declarations: 33 Limit : constant Integer := 10_000; Low_Limit : constant Integer := Limit/10; Tolerance : constant Real := Dispersion(1.15); Extensions to Ada 83 33.a {extensions to Ada 83} The syntax rule for object_declaration is modified to allow the aliased reserved word. 33.b A variable declared by an object_declaration can be constrained by its initial value; that is, a variable of a nominally unconstrained array subtype, or discriminated type without defaults, can be declared so long as it has an explicit initial value. In Ada 83, this was permitted for constants, and for variables created by allocators, but not for variables declared by object_declarations. This is particularly important for tagged class-wide types, since there is no way to constrain them explicitly, and so an initial value is the only way to provide a constraint. It is also important for generic formal private types with unknown discriminants. 33.c We now allow an unconstrained_array_definition in an object_ declaration. This allows an object of an anonymous array type to have its bounds determined by its initial value. This is for uniformity: If one can write ``X: constant array(Integer range 1..10) of Integer := ...;'' then it makes sense to also allow ``X: constant array(Integer range <>) of Integer := ...;''. (Note that if anonymous array types are ever sensible, a common situation is for a table implemented as an array. Tables are often constant, and for constants, there's usually no point in forcing the user to count the number of elements in the value.) Wording Changes From Ada 83 33.d We have moved the syntax for object_declarations into this subclause. 33.e Deferred constants no longer have a separate syntax rule, but rather are incorporated in object_declaration as constants declared without an initialization expression. 3.3.2 Number Declarations 1 A number_declaration declares a named number. 1.a Discussion: {static} If a value or other property of a construct is required to be static that means it is required to be determined prior to execution. A static expression is an expression whose value is computed at compile time and is usable in contexts where the actual value might affect the legality of the construct. This is fully defined in clause 4.9. Syntax 2 number_declaration ::= defining_identifier_list : constant := static_expression; Name Resolution Rules 3 {expected type [number_declaration expression]} The static_expression given for a number_declaration is expected to be of any numeric type. Legality Rules 4 The static_expression given for a number declaration shall be a static expression, as defined by clause 4.9. Static Semantics 5 The named number denotes a value of type universal_integer if the type of the static_expression is an integer type. The named number denotes a value of type universal_real if the type of the static_expression is a real type. 6 The value denoted by the named number is the value of the static_expression, converted to the corresponding universal type. {implicit subtype conversion [named number value]} Dynamic Semantics 7 {elaboration [number_declaration]} The elaboration of a number_ declaration has no effect. 7.a Proof: Since the static_expression was evaluated at compile time. Examples 8 Examples of number declarations: 9 Two_Pi : constant := 2.0*Ada.Numerics.Pi; -- a real number (see A.\ 5) 10 Max : constant := 500; -- an integer number Max_Line_Size : constant := Max/6 -- the integer 83 Power_16 : constant := 2**16; -- the integer 65_536 One, Un, Eins : constant := 1; -- three different names\ for 1 Extensions to Ada 83 10.a {extensions to Ada 83} We now allow a static expression of any numeric type to initialize a named number. For integer types, it was possible in Ada 83 to use 'Pos to define a named number, but there was no way to use a static expression of some non-universal real type to define a named number. This change is upward compatible because of the preference rule for the operators of the root numeric types. Wording Changes From Ada 83 10.b We have moved the syntax rule into this subclause. 10.c AI-00263 describes the elaboration of a number declaration in words similar to that of an object_declaration. However, since there is no expression to be evaluated and no object to be created, it seems simpler to say that the elaboration has no effect. 3.4 Derived Types and Classes 1 {derived type} A derived_type_definition defines a new type (and its first subtype) whose characteristics are derived from those of a parent type. 1.a Glossary entry: {Derived type} A derived type is a type defined in terms of another type, which is the parent type of the derived type. Each class containing the parent type also contains the derived type. The derived type inherits properties such as components and primitive operations from the parent. A type together with the types derived from it (directly or indirectly) form a derivation class. {inheritance: see derived types and classes} Syntax 2 derived_type_definition ::= [abstract] new parent_subtype_indication [recor\ d_extension_part] Legality Rules 3 {parent subtype} {parent type} The parent_subtype_indication defines the parent subtype; its type is the parent type. 4 A type shall be completely defined (see 3.11.1) prior to being specified as the parent type in a derived_type_definition -- [the full_type_ declarations for the parent type and any of its subcomponents have to precede the derived_type_definition.] 4.a Discussion: This restriction does not apply to the ancestor type of a private extension -- see 7.3; such a type need not be completely defined prior to the private_extension_declaration. However, the restriction does apply to record extensions, so the ancestor type will have to be completely defined prior to the full_ type_declaration corresponding to the private_extension_declaration. 4.b Reason: We originally hoped we could relax this restriction. However, we found it too complex to specify the rules for a type derived from an incompletely defined limited type that subsequently became nonlimited. 5 {record extension} If there is a record_extension_part, the derived type is called a record extension of the parent type. A record_extension_part shall be provided if and only if the parent type is a tagged type. 5.a Implementation Note: We allow a record extension to inherit discriminants; a previous version of Ada 9X did not. If the parent subtype is unconstrained, it can be implemented as though its discriminants were repeated in a new known_discriminant_part and then used to constrain the old ones one-for-one. However, in an extension aggregate, the discriminants in this case do not appear in the component association list. 5.b Ramification: This rule needs to be rechecked in the visible part of an instance of a generic unit. Static Semantics 6 {constrained (subtype)} {unconstrained (subtype)} The first subtype of the derived type is unconstrained if a known_discriminant_part is provided in the declaration of the derived type, or if the parent subtype is unconstrained. {corresponding constraint} Otherwise, the constraint of the first subtype corresponds to that of the parent subtype in the following sense: it is the same as that of the parent subtype except that for a range constraint (implicit or explicit), the value of each bound of its range is replaced by the corresponding value of the derived type. 6.a Discussion: A digits_constraint in a subtype_indication for a decimal fixed point subtype always imposes a range constraint, implicitly if there is no explicit one given. See 3.5.9, ``Fixed Point Types''. 7 The characteristics of the derived type are defined as follows: 8 Each class of types that includes the parent type also includes the derived type. 8.a Discussion: This is inherent in our notion of a ``class'' of types. It is not mentioned in the initial definition of ``class'' since at that point type derivation has not been defined. In any case, this rule ensures that every class of types is closed under derivation. 9 If the parent type is an elementary type or an array type, then the set of possible values of the derived type is a copy of the set of possible values of the parent type. For a scalar type, the base range of the derived type is the same as that of the parent type. 9.a Discussion: The base range of a type defined by an integer_ type_definition or a real_type_definition is determined by the _definition, and is not necessarily the same as that of the corresponding root numeric type from which the newly defined type is implicitly derived. Treating numerics types as implicitly derived from one of the two root numeric types is simply to link them into a type hierarchy; such an implicit derivation does not follow all the rules given here for an explicit derived_type_definition. 10 If the parent type is a composite type other than an array type, then the components, protected subprograms, and entries that are declared for the derived type are as follows: 11 The discriminants specified by a new known_discriminant_ part, if there is one; otherwise, each discriminant of the parent type (implicitly declared in the same order with the same specifications) -- {inherited discriminant} {inherited component} in the latter case, the dis- criminants are said to be inherited, or if unknown in the parent, are also unknown in the derived type; 12 Each nondiscriminant component, entry, and protected subprogram of the parent type, implicitly declared in the same order with the same declarations; {inherited component} {inherited protected subprogram} {inherited entry} these components, entries, and protected sub- programs are said to be inherited; 12.a Ramification: The profiles of entries and protected subprograms do not change upon type derivation, although the type of the ``implicit'' parameter identified by the prefix of the name in a call does. 12.b To be honest: Any name in the parent type_declaration that denotes the current instance of the type is replaced with a name denoting the current instance of the derived type, converted to the parent type. 13 Each component declared in a record_extension_part, if any. 14 Declarations of components, protected subprograms, and entries, whether implicit or explicit, occur immediately within the declarative region of the type, in the order indicated above, following the parent subtype_indication. 14.a Discussion: The order of declarations within the region matters for record_aggregates and extension_aggregates. 14.b Ramification: In most cases, these things are implicitly declared immediately following the parent subtype_indication. However, 7.3.1, ``Private Operations'' defines some cases in which they are implicitly declared later, and some cases in which the are not declared at all. 14.c Discussion: The place of the implicit declarations of inherited components matters for visibility -- they are not visible in the known_discriminant_part nor in the parent subtype_indication, but are usually visible within the record_ extension_part, if any (although there are restrictions on their use). Note that a discriminant specified in a new known_ discriminant_part is not considered ``inherited'' even if it has the same name and subtype as a discriminant of the parent type. 15 The derived type is limited if and only if the parent type is limited. 15.a To be honest: The derived type can become nonlimited if the derivation takes place in the visible part of a child package, and the parent type is nonlimited as viewed from the private part of the child package -- see 7.5. 16 [For each predefined operator of the parent type, there is a corresponding predefined operator of the derived type.] 16.a Proof: This is a ramification of the fact that each class that includes the parent type also includes the derived type, and the fact that the set of predefined operators that is defined for a type, as described in 4.5, is determined by the classes to which it belongs. 16.b Reason: Predefined operators are handled separately because they follow a slightly different rule than user-defined primitive subprograms. In particular the systematic replacement described below does not apply fully to the relational operators for Boolean and the exponentiation operator for Integer. The relational operators for a type derived from Boolean still return Standard.Boolean. The exponentiation operator for a type derived from Integer still expects Standard.Integer for the right operand. In addition, predefined operators "reemerge" when a type is the actual type corresponding to a generic formal type, so they need to be well defined even if hidden by user-defined primitive subprograms. 17 {inherited subprogram} For each user-defined primitive subprogram (other than a user-defined equality operator -- see below) of the parent type that already exists at the place of the derived_type_ definition, there exists a corresponding inherited primitive subprogram of the derived type with the same defining name. {equality operator (special inheritance rule for tagged types)} Primitive user-defined equality operators of the parent type are also inherited by the derived type, except when the derived type is a nonlimited record extension, and the inherited operator would have a profile that is type conformant with the profile of the corresponding predefined equality operator; in this case, the user-defined equality operator is not inherited, but is rather incorporated into the implementation of the predefined equality operator of the record extension (see 4.5.2). {type conformance [partial]} 17.a Ramification: We say ``...already exists...'' rather than ``is visible'' or ``has been declared'' because there are certain operations that are declared later, but still exist at the place of the derived_type_definition, and there are operations that are never declared, but still exist. These cases are explained in 7.3.1. 17.b Note that nonprivate extensions can appear only after the last primitive subprogram of the parent -- the freezing rules ensure this. 17.c Reason: A special case is made for the equality operators on nonlimited record extensions because their predefined equality operators are already defined in terms of the primitive equality operator of their parent type (and of the tagged components of the extension part). Inheriting the parent's equality operator as is would be undesirable, because it would ignore any components of the extension part. On the other hand, if the parent type is limited, then any user-defined equality operator is inherited as is, since there is no predefined equality operator to take its place. 17.d Ramification: Because user-defined equality operators are not inherited by record extensions, the formal parameter names of = and /= revert to Left and Right, even if different formal parameter names were used in the user-defined equality operators of the parent type. 18 The profile of an inherited subprogram (including an inherited enumeration literal) is obtained from the profile of the corresponding (user-defined) primitive subprogram of the parent type, after systematic replacement of each subtype of its profile (see 6.1) that is of the parent type with a corresponding subtype of the derived type. {corresponding subtype} For a given subtype of the parent type, the corresponding subtype of the derived type is defined as follows: 19 If the declaration of the derived type has neither a known_discriminant_part nor a record_extension_part, then the corresponding subtype has a constraint that corresponds (as defined above for the first subtype of the derived type) to that of the given subtype. 20 If the derived type is a record extension, then the corresponding subtype is the first subtype of the derived type. 21 If the derived type has a new known_discriminant_part but is not a record extension, then the corresponding subtype is constrained to those values that when converted to the parent type belong to the given subtype (see 4.6). {implicit subtype conversion [derived type discriminants]} 21.a Reason: An inherited subprogram of an untagged type has an Intrinsic calling convention, which precludes the use of the Access attribute. We preclude 'Access because correctly performing all required constraint checks on an indirect call to such an inherited subprogram was felt to impose an undesirable implementation burden. 22 The same formal parameters have default_expressions in the profile of the inherited subprogram. [Any type mismatch due to the systematic replacement of the parent type by the derived type is handled as part of the normal type conversion associated with parameter passing -- see 6.4.1.] 22.a Reason: We don't introduce the type conversion explicitly here since conversions to record extensions or on access parameters are not generally legal. Furthermore, any type conversion would just be "undone" since the parent's subprogram is ultimately being called anyway. 23 If a primitive subprogram of the parent type is visible at the place of the derived_type_definition, then the corresponding inherited subprogram is implicitly declared immediately after the derived_type_definition. Other- wise, the inherited subprogram is implicitly declared later or not at all, as explained in 7.3.1. 24 {derived type [partial]} A derived type can also be defined by a private_extension_declaration (see 7.3) or a formal_derived_type_definition (see 12.5.1). Such a derived type is a partial view of the corresponding full or actual type. 25 All numeric types are derived types, in that they are implicitly derived from a corresponding root numeric type (see 3.5.4 and 3.5.6). Dynamic Semantics 26 {elaboration [derived_type_definition]} The elaboration of a derived_ type_definition creates the derived type and its first subtype, and consists of the elaboration of the subtype_indication and the record_extension_part, if any. If the subtype_indication depends on a discriminant, then only those expressions that do not depend on a discriminant are evaluated. 27 {execution [call on an inherited subprogram]} For the execution of a call on an inherited subprogram, a call on the corresponding primitive subprogram of the parent type is performed; the normal conversion of each actual parameter to the subtype of the corresponding formal parameter (see 6.4.1) performs any necessary type conversion as well. If the result type of the inherited subprogram is the derived type, the result of calling the parent's subprogram is converted to the derived type. {implicit subtype conversion [result of inherited function]} 27.a Discussion: If an inherited function returns the derived type, and the type is a record extension, then the inherited function is abstract, and (unless overridden) cannot be called except via a dispatching call. See 3.9.3. NOTES 28 (10) {closed under derivation} Classes are closed under derivation -- any class that contains a type also contains its derivatives. Operations available for a given class of types are available for the derived types in that class. 29 (11) Evaluating an inherited enumeration literal is equivalent to evaluating the corresponding enumeration literal of the parent type, and then converting the result to the derived type. This follows from their equivalence to parameterless functions. {implicit subtype conversion [inherited enumeration literal]} 30 (12) A generic subprogram is not a subprogram, and hence cannot be a primitive subprogram and cannot be inherited by a derived type. On the other hand, an instance of a generic subprogram can be a primitive subprogram, and hence can be inherited. 31 (13) If the parent type is an access type, then the parent and the derived type share the same storage pool; there is a null access value for the derived type and it is the implicit initial value for the type. See 3.10. 32 (14) If the parent type is a boolean type, the predefined relational operators of the derived type deliver a result of the predefined type Boolean (see 4.5.2). If the parent type is an integer type, the right operand of the predefined exponentiation operator is of the predefined type Integer (see 4.5.6). 33 (15) Any discriminants of the parent type are either all inherited, or completely replaced with a new set of discriminants. 34 (16) For an inherited subprogram, the subtype of a formal parameter of the derived type need not have any value in common with the first subtype of the derived type. 34.a Proof: This happens when the parent subtype is constrained to a range that does not overlap with the range of a subtype of the parent type that appears in the profile of some primitive subprogram of the parent type. For example: 34.b type T1 is range 1..100; subtype S1 is T1 range 1..10; procedure P(X : in S1); -- P is a primitive subprogram type T2 is new T1 range 11..20; -- implicitly declared: -- procedure P(X : in T2'Base range 1..10); -- X cannot be in T2'First .. T2'Last 35 (17) If the reserved word abstract is given in the declaration of a type, the type is abstract (see 3.9.3). Examples 36 Examples of derived type declarations: 37 type Local_Coordinate is new Coordinate; -- two different types type Midweek is new Day range Tue .. Thu; -- see 3.5.1 type Counter is new Positive; -- same range as Positive 38 type Special_Key is new Key_Manager.Key; -- see 7.3.1 -- the inherited subprograms have the following specifications: -- procedure Get_Key(K : out Special_Key); -- function "<"(X,Y : Special_Key) return Boolean; Inconsistencies With Ada 83 38.a {inconsistencies with Ada 83} When deriving from a (nonprivate, nonderived) type in the same visible part in which it is defined, if a predefined operator had been overridden prior to the derivation, the derived type will inherit the user-defined operator rather than the predefined operator. The work-around (if the new behavior is not the desired behavior) is to move the definition of the derived type prior to the overriding of any predefined operators. Incompatibilities With Ada 83 38.b {incompatibilities with Ada 83} When deriving from a (nonprivate, nonderived) type in the same visible part in which it is defined, a primitive subprogram of the parent type declared before the derived type will be inherited by the derived type. This can cause upward incompatibilities in cases like this: 38.c package P is type T is (A, B, C, D); function F( X : T := A ) return Integer; type NT is new T; -- inherits F as -- function F( X : NT := A ) return Integer; -- in Ada 9X only ... end P; ... use P; -- Only one declaration of F from P is use-visible in -- Ada 83; two declarations of F are use-visible in -- Ada 9X. begin ... if F > 1 then ... -- legal in Ada 83, ambiguous in Ada 9X Extensions to Ada 83 38.d {extensions to Ada 83} The syntax for a derived_type_ definition is amended to include an optional record_extension_part (see 3.9.1). 38.e A derived type may override the discriminants of the parent by giving a new discriminant_part. 38.f The parent type in a derived_type_definition may be a derived type defined in the same visible part. 38.g When deriving from a type in the same visible part in which it is defined, the primitive subprograms declared prior to the derivation are inherited as primitive subprograms of the derived type. See 3.2.3. Wording Changes From Ada 83 38.h We now talk about the classes to which a type belongs, rather than a single class. 38.i As explained in Section 13, the concept of "storage pool" replaces the Ada 83 concept of "collection." These concepts are similar, but not the same. 3.4.1 Derivation Classes 1 In addition to the various language-defined classes of types, types can be grouped into derivation classes. Static Semantics 2 {derived from (directly or indirectly)} A derived type is derived from its parent type directly; it is derived indirectly from any type from which its parent type is derived. {derivation class (for a type)} {root type (of a class)} {rooted at a type} The derivation class of types for a type T (also called the class rooted at T) is the set consisting of T (the root type of the class) and all types derived from T (directly or indirectly) plus any associated universal or class-wide types (defined below). 2.a Discussion: Note that the definition of ``derived from'' is a recursive definition. We don't define a root type for all interesting language-defined classes, though presumably we could. 2.b To be honest: By the class-wide type ``associated'' with a type T, we mean the type T'Class. Similarly, the universal type associated with root_integer, root_real, and root_fixed are universal_integer, universal_real, and universal_fixed, respectively. 3 Every type is either a specific type, a class-wide type, or a universal type. {specific type} A specific type is one defined by a type_declaration, a formal_type_declaration, or a full type definition embedded in a declaration for an object. Class-wide and universal types are implicitly defined, to act as representatives for an entire class of types, as follows: 3.a To be honest: The root types root_integer, root_real, and root_fixed are also specific types. They are declared in the specification of package Standard. 4 {class-wide type} Class-wide types Class-wide types are defined for [(and belong to)] each derivation class rooted at a tagged type (see 3.9). Given a subtype S of a tagged type T, S'Class is the subtype_mark for a corresponding subtype of the tagged class-wide type T'Class. Such types are called ``class-wide'' because when a formal parameter is defined to be of a class-wide type T'Class, an actual parameter of any type in the derivation class rooted at T is acceptable (see 8.6). 5 {first subtype} The set of values for a class-wide type T'Class is the discriminated union of the set of values of each specific type in the derivation class rooted at T (the tag acts as the implicit discriminant -- see 3.9). Class-wide types have no primitive subprograms of their own. However, as explained in 3.9.2, operands of a class-wide type T'Class can be used as part of a dispatching call on a primitive subprogram of the type T. The only components [(including discriminants)] of T'Class that are visible are those of T. If S is a first subtype, then S'Class is a first subtype. 5.a Reason: We want S'Class to be a first subtype when S is, so that an attribute_definition_clause like ``for S'Class'Output use ...;'' will be legal. 6 {universal type} Universal types Universal types are defined for [(and belong to)] the integer, real, and fixed point classes, and are referred to in this standard as respectively, universal_integer, universal_real, and universal_fixed. These are analogous to class-wide types for these language-defined numeric classes. As with class-wide types, if a formal parameter is of a universal type, then an actual parameter of any type in the corresponding class is acceptable. In addition, a value of a universal type (including an integer or real numeric_literal) is ``universal'' in that it is acceptable where some particular type in the class is expected (see 8.6). 7 The set of values of a universal type is the undiscriminated union of the set of values possible for any definable type in the associated class. Like class-wide types, universal types have no primitive subprograms of their own. However, their ``universality'' allows them to be used as operands with the primitive subprograms of any type in the corresponding class. 7.a Discussion: A class-wide type is only class-wide in one direction, from specific to class-wide, whereas a universal type is class-wide (universal) in both directions, from specific to universal and back. 7.b We considered defining class-wide or perhaps universal types for all derivation classes, not just tagged classes and these three numeric classes. However, this was felt to overly weaken the strong-typing model in some situations. Tagged types preserve strong type distinctions thanks to the run-time tag. Class-wide or universal types for untagged types would weaken the compile-time type distinctions without providing a compensating run-time-checkable distinction. 7.c We considered defining standard names for the universal numeric types so they could be used in formal parameter specifications. However, this was felt to impose an undue implementation burden for some implementations. 7.d To be honest: Formally, the set of values of a universal type is actually a copy of the undiscriminated union of the values of the types in its class. This is because we want each value to have exactly one type, with explicit or implicit conversion needed to go between types. An alternative, consistent model would be to associate a class, rather than a particular type, with a value, even though any given expression would have a particular type. In that case, implicit type conversions would not generally need to change the value, although an associated subtype conversion might need to. 8 {root_integer [partial]} {root_real [partial]} The integer and real numeric classes each have a specific root type in addition to their universal type, named respectively root_integer and root_real. 9 {cover (a type)} A class-wide or universal type is said to cover all of the types in its class. A specific type covers only itself. 10 {descendant (of a type)} A specific type T2 is defined to be a descendant of a type T1 if T2 is the same as T1, or if T2 is derived (directly or indirectly) from T1. A class-wide type T2'Class is defined to be a descendant of type T1 if T2 is a descendant of T1. Similarly, the universal types are defined to be descendants of the root types of their classes. {ancestor (of a type)} If a type T2 is a descendant of a type T1, then T1 is called an ancestor of T2. {ultimate ancestor (of a type)} {ancestor (ultimate)} The ultimate ancestor of a type is the ancestor of the type that is not a descendant of any other type. 10.a Ramification: A specific type is a descendant of itself. Class-wide types are considered descendants of the corresponding specific type, and do not have any descendants of their own. 10.b A specific type is an ancestor of itself. The root of a derivation class is an ancestor of all types in the class, including any class-wide types in the class. 10.c Discussion: The terms root, parent, ancestor, and ultimate ancestor are all related. For example: 10.d Each type has at most one parent, and one or more ancestor types; each type has exactly one ultimate ancestor. In Ada 83, the term ``parent type'' was sometimes used more generally to include any ancestor type (e.g. RM83-9.4(14)). In Ada 9X, we restrict parent to mean the immediate ancestor. 10.e A class of types has at most one root type; a derivation class has exactly one root type. 10.f The root of a class is an ancestor of all of the types in the class (including itself). 10.g The type root_integer is the root of the integer class, and is the ultimate ancestor of all integer types. A similar statement applies to root_real. 11 {inherited (from an ancestor type)} An inherited component [(including an inherited discriminant)] of a derived type is inherited from a given ancestor of the type if the corresponding component was inherited by each derived type in the chain of derivations going back to the given ancestor. NOTES 12 (18) Because operands of a universal type are acceptable to the predefined operators of any type in their class, ambiguity can result. For universal_integer and universal_real, this potential ambiguity is resolved by giving a preference (see 8.6) to the predefined operators of the corresponding root types (root_integer and root_real, respectively). Hence, in an apparently ambiguous expression like 13 1 + 4 < 7 14 where each of the literals is of type universal_integer, the predefined operators of root_integer will be preferred over those of other specific integer types, thereby resolving the ambiguity. 14.a Ramification: Except for this preference, a root numeric type is essentially like any other specific type in the associated numeric class. In particular, the result of a predefined operator of a root numeric type is not ``universal'' (implicitly convertible) even if both operands were. 3.5 Scalar Types 1 {scalar type} Scalar types comprise enumeration types, integer types, and real types. {discrete type} Enumeration types and integer types are called discrete types; {position number} each value of a discrete type has a position number which is an integer value. {numeric type} Integer types and real types are called numeric types. [All scalar types are ordered, that is, all relational operators are predefined for their values.] Syntax 2 range_constraint ::= range range 3 range ::= range_attribute_reference | simple_expression .. simple_expression 3.a Discussion: These need to be simple_expressions rather than more general expressions because ranges appear in membership tests and other contexts where expression .. expression would be ambiguous. 4 {range} {lower bound (of a range)} {upper bound (of a range)} {type of a range} A range has a lower bound and an upper bound and specifies a subset of the values of some scalar type (the type of the range). A range with lower bound L and upper bound R is described by ``L .. R''. {null range} If R is less than L, then the range is a null range, and specifies an empty set of values. Otherwise, the range specifies the values of the type from the lower bound to the upper bound, inclusive. {belong (to a range)} A value belongs to a range if it is of the type of the range, and is in the subset of values specified by the range. {satisfies [a range constraint]} A value satisfies a range constraint if it belongs to the associated range. {included (one range in another)} One range is included in another if all values that belong to the first range also belong to the second. Name Resolution Rules 5 {expected type [range_constraint range]} For a subtype_indication containing a range_constraint, either directly or as part of some other scalar_constraint, the type of the range shall resolve to that of the type determined by the subtype_mark of the subtype_indication. {expected type [range simple_expressions]} For a range of a given type, the simple_ expressions of the range (likewise, the simple_expressions of the equivalent range for a range_attribute_reference) are expected to be of the type of the range. 5.a Discussion: In Ada 9X, constraints only appear within subtype_ indications; things that look like constraints that appear in type declarations are called something else like range_specifications. 5.b We say "the expected type is ..." or "the type is expected to be ..." depending on which reads better. They are fundamentally equivalent, and both feed into the type resolution rules of clause 8.6. 5.c In some cases, it doesn't work to use expected types. For example, in the above rule, we say that the ``type of the range shall resolve to ...'' rather than ``the expected type for the range is ...''. We then use ``expected type'' for the bounds. If we used ``expected'' at both points, there would be an ambiguity, since one could apply the rules of 8.6 either on determining the type of the range, or on determining the types of the individual bounds. It is clearly important to allow one bound to be of a universal type, and the other of a specific type, so we need to use ``expected type'' for the bounds. Hence, we used ``shall resolve to'' for the type of the range as a whole. There are other situations where ``expected type'' is not quite right, and we use ``shall resolve to'' instead. Static Semantics 6 {base range (of a scalar type) [distributed]} The base range of a scalar type is the range of finite values of the type that can be represented in every unconstrained object of the type; it is also the range supported at a minimum for intermediate values during the evaluation of expressions involving predefined operators of the type. 6.a Implementation Note: Note that in some machine architectures intermediates in an expression (particularly if static), and register-resident variables might accommodate a wider range. The base range does not include the values of this wider range that are not assignable without overflow to memory-resident objects. 6.b Ramification: {base range [of an enumeration type]} The base range of an enumeration type is the range of values of the enumeration type. 6.c Reason: If the representation supports infinities, the base range is nevertheless restricted to include only the representable finite values, so that 'Base'First and 'Base'Last are always guaranteed to be finite. 6.d To be honest: By a "value that can be assigned without overflow" we don't mean to restrict ourselves to values that can be represented exactly. Values between machine representable values can be assigned, but on subsequent reading, a slightly different value might be retrieved, as (partially) determined by the number of digits of precision of the type. 7 {constrained (subtype)} {unconstrained (subtype)} [A constrained scalar subtype is one to which a range constraint applies.] {range (of a scalar subtype)} The range of a constrained scalar subtype is the range associated with the range constraint of the subtype. The range of an unconstrained scalar subtype is the base range of its type. Dynamic Semantics 8 {compatibility [range with a scalar subtype]} A range is compatible with a scalar subtype if and only if it is either a null range or each bound of the range belongs to the range of the subtype. {compatibility [range_ constraint with a scalar subtype]} A range_constraint is compatible with a scalar subtype if and only if its range is compatible with the subtype. 8.a Ramification: Only range_constraints (explicit or implicit) impose conditions on the values of a scalar subtype. The other scalar_constraints, digit_constraints and delta_constraints impose conditions on the subtype denoted by the subtype_mark in a subtype_ indication, but don't impose a condition on the values of the subtype being defined. Therefore, a scalar subtype is not called constrained if all that applies to it is a digits_constraint. Decimal subtypes are subtle, because a digits_constraint without a range_constraint nevertheless includes an implicit range_constraint. 9 {elaboration [range_constraint]} The elaboration of a range_constraint consists of the evaluation of the range. {evaluation [range]} The evaluation of a range determines a lower bound and an upper bound. If simple_ expressions are given to specify bounds, the evaluation of the range evaluates these simple_expressions in an arbitrary order, and converts them to the type of the range. {implicit subtype conversion [bounds of a range]} If a range_attribute_reference is given, the evaluation of the range consists of the evaluation of the range_attribute_reference. 10 Attributes 11 For every scalar subtype S, the following attributes are defined: 12 S'First S'First denotes the lower bound of the range of S. The value of this attribute is of the type of S. 12.a Ramification: Evaluating S'First never raises Constraint_Error. 13 S'Last S'Last denotes the upper bound of the range of S. The value of this attribute is of the type of S. 13.a Ramification: Evaluating S'Last never raises Constraint_Error. 14 S'Range S'Range is equivalent to the range S'First .. S'Last. 15 {base subtype (of a type)} S'Base S'Base denotes an unconstrained subtype of the type of S. This unconstrained subtype is called the base subtype of the type. 16 S'Min S'Min denotes a function with the following specification: 17 function S'Min(Left, Right : S'Base) return S'Base 18 The function returns the lesser of the values of the two parameters. 18.a Discussion: {italics (formal parameters of attribute functions)} The formal parameter names are italicized because they cannot be used in calls -- see 6.4. Such a specification cannot be written by the user because an attribute_reference is not permitted as the designator of a user-defined function, nor can its formal parameters be anonymous. 19 S'Max S'Max denotes a function with the following specification: 20 function S'Max(Left, Right : S'Base) return S'Base 21 The function returns the greater of the values of the two parameters. 22 S'Succ S'Succ denotes a function with the following specification: 23 function S'Succ(Arg : S'Base) return S'Base 24 {Constraint_Error (raised by failure of run-time check)} For an enumeration type, the function returns the value whose position number is one more than that of the value of Arg; {Range_Check [partial]} {check, language-defined (Range_ Check)} Constraint_Error is raised if there is no such value of the type. For an integer type, the function returns the result of adding one to the value of Arg. For a fixed point type, the function returns the result of adding small to the value of Arg. For a floating point type, the function returns the machine number (as defined in 3.5.7) immediately above the value of Arg; {Range_Check [partial]} {check, language-defined (Range_Check)} Constraint_Error is raised if there is no such machine number. 24.a Ramification: S'Succ for a modular integer subtype wraps around if the value of Arg is S'Base'Last. S'Succ for a signed integer subtype might raise Constraint_Error if the value of Arg is S'Base'Last, or it might return the out-of-base-range value S'Base'Last+1, as is permitted for all predefined numeric operations. 25 S'Pred S'Pred denotes a function with the following specification: 26 function S'Pred(Arg : S'Base) return S'Base 27 {Constraint_Error (raised by failure of run-time check)} For an enumeration type, the function returns the value whose position number is one less than that of the value of Arg; {Range_Check [partial]} {check, language-defined (Range_ Check)} Constraint_Error is raised if there is no such value of the type. For an integer type, the function returns the result of subtracting one from the value of Arg. For a fixed point type, the function returns the result of subtracting small from the value of Arg. For a floating point type, the function returns the machine number (as defined in 3.5.7) immediately below the value of Arg; {Range_Check [partial]} {check, language-defined (Range_Check)} Constraint_Error is raised if there is no such machine number. 27.a Ramification: S'Pred for a modular integer subtype wraps around if the value of Arg is S'Base'First. S'Pred for a signed integer subtype might raise Constraint_Error if the value of Arg is S'Base'First, or it might return the out-of-base-range value S'Base'First-1, as is permitted for all predefined numeric operations. 28 S'Wide_Image S'Wide_Image denotes a function with the following specification: 29 function S'Wide_Image(Arg : S'Base) return Wide_String 30 {image (of a value)} The function returns an image of the value of Arg, that is, a sequence of characters representing the value in display form. The lower bound of the result is one. 31 The image of an integer value is the corresponding decimal literal, without underlines, leading zeros, exponent, or trailing spaces, but with a single leading character that is either a minus sign or a space. 31.a Implementation Note: If the machine supports negative zeros for signed integer types, it is not specified whether "-0" or " 0" should be returned for negative zero. We don't have enough experience with such machines to know what is appropriate, and what other languages do. In any case, the implementation should be consistent. 32 {nongraphic character} The image of an enumeration value is either the corresponding identifier in upper case or the corresponding character literal (including the two apostrophes); neither leading nor trailing spaces are included. For a nongraphic character (a value of a character type that has no enumeration literal associated with it), the result is a corresponding language-defined or implementation- defined name in upper case (for example, the image of the nongraphic character identified as nul is ``NUL'' -- the quotes are not part of the image). 32.a Implementation Note: For an enumeration type T that has ``holes'' (caused by an enumeration_representation_clause), {Program_ Error (raised by failure of run-time check)} T'Wide_Image should raise Program_Error if the value is one of the holes (which is a bounded error anyway, since holes can be generated only via uninitialized variables and similar things. 33 The image of a floating point value is a decimal real literal best approximating the value (rounded away from zero if halfway between) with a single leading character that is either a minus sign or a space, a single digit (that is nonzero unless the value is zero), a decimal point, S'Digits-1 (see 3.5.8) digits after the decimal point (but one if S'Digits is one), an upper case E, the sign of the exponent (either + or -), and two or more digits (with leading zeros if necessary) representing the exponent. If S'Signed_Zeros is True, then the leading character is a minus sign for a negatively signed zero. 33.a To be honest: Leading zeros are present in the exponent only if necessary to make the exponent at least two digits. 33.b Reason: This image is intended to conform to that produced by Text_IO.Float_IO.Put in its default format. 33.c Implementation Note: The rounding direction is specified here to ensure portability of output results. 34 The image of a fixed point value is a decimal real literal best approximating the value (rounded away from zero if halfway between) with a single leading character that is either a minus sign or a space, one or more digits before the decimal point (with no redundant leading zeros), a decimal point, and S'Aft (see 3.5.10) digits after the decimal point. 34.a Reason: This image is intended to conform to that produced by Text_IO.Fixed_IO.Put. 34.b Implementation Note: The rounding direction is specified here to ensure portability of output results. 34.c Implementation Note: For a machine that supports negative zeros, it is not specified whether "-0.000" or " 0.000" is returned. See corresponding comment above about integer types with signed zeros. 35 S'Image S'Image denotes a function with the following specification: 36 function S'Image(Arg : S'Base) return String 37 The function returns an image of the value of Arg as a String. The lower bound of the result is one. The image has the same sequence of graphic characters as that defined for S'Wide_Image if all the graphic characters are defined in Character; otherwise the sequence of characters is implementation defined (but no shorter than that of S'Wide_ Image for the same value of Arg). 37.a Implementation defined: The sequence of characters of the value returned by S'Image when some of the graphic characters of S'Wide_Image are not defined in Character. 38 S'Wide_Width S'Wide_Width denotes the maximum length of a Wide_String returned by S'Wide_Image over all values of the subtype S. It denotes zero for a subtype that has a null range. Its type is universal_integer. 39 S'Width S'Width denotes the maximum length of a String returned by S'Image over all values of the subtype S. It denotes zero for a subtype that has a null range. Its type is universal_ integer. 40 S'Wide_Value S'Wide_Value denotes a function with the following specification: 41 function S'Wide_Value(Arg : Wide_String) return S'Base 42 This function returns a value given an image of the value as a Wide_String, ignoring any leading or trailing spaces. 43 {evaluation [Wide_Value]} {Constraint_Error (raised by failure of run-time check)} For the evaluation of a call on S'Wide_Value for an enumeration subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an enumeration literal and if it corresponds to a literal of the type of S (or corresponds to the result of S'Wide_Image for a nongraphic character of the type), the result is the corresponding enumeration value; {Range_Check [partial]} {check, language-defined (Range_ Check)} otherwise Constraint_Error is raised. 43.a Discussion: It's not crystal clear that Range_Check is appropriate here, but it doesn't seem worthwhile to invent a whole new check name just for this weird case, so we decided to lump it in with Range_Check. 44 {Constraint_Error (raised by failure of run-time check)} For the evaluation of a call on S'Wide_Value (or S'Value) for an integer subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an integer literal, with an optional leading sign character (plus or minus for a signed type; only plus for a modular type), and the corresponding numeric value belongs to the base range of the type of S, then that value is the result; {Range_Check [partial]} {check, language-defined (Range_Check)} otherwise Constraint_Error is raised. 44.a Discussion: We considered allowing 'Value to return a representable but out-of-range value without a Constraint_Error. However, we currently require (see 4.9) in an assignment_statement like "X := ;" that the value of the numeric-literal be in X's base range (at compile time), so it seems unfriendly and confusing to have a different range allowed for 'Value. Furthermore, for modular types, without the requirement for being in the base range, 'Value would have to handle arbitrarily long literals (since overflow never occurs for modular types). 45 For the evaluation of a call on S'Wide_Value (or S'Value) for a real subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of one of the following: 46 numeric_literal 47 numeral.[exponent] 48 .numeral[exponent] 49 base#based_numeral.#[exponent] 50 base#.based_numeral#[exponent] 51 {Constraint_Error (raised by failure of run-time check)} with an optional leading sign character (plus or minus), and if the corresponding numeric value belongs to the base range of the type of S, then that value is the result; {Range_Check [partial]} {check, language-defined (Range_Check)} otherwise Constraint_Error is raised. The sign of a zero value is preserved (positive if none has been specified) if S'Signed_ Zeros is True. 52 S'Value S'Value denotes a function with the following specification: 53 function S'Value(Arg : String) return S'Base 54 This function returns a value given an image of the value as a String, ignoring any leading or trailing spaces. 55 {evaluation [Value]} {Constraint_Error (raised by failure of run-time check)} For the evaluation of a call on S'Value for an enumeration subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an enumeration literal and if it corresponds to a literal of the type of S (or corresponds to the result of S'Image for a value of the type), the result is the corresponding enumeration value; {Range_Check [partial]} {check, language-defined (Range_Check)} otherwise Constraint_ Error is raised. For a numeric subtype S, the evaluation of a call on S'Value with Arg of type String is equivalent to a call on S'Wide_Value for a corresponding Arg of type Wide_ String. 55.a Reason: S'Value is subtly different from S'Wide_Value for enumeration subtypes since S'Image might produce a different sequence of characters than S'Wide_Image if the enumeration literal uses characters outside of the predefined type Character. That is why we don't just define S'Value in terms of S'Wide_Value for enumeration subtypes. S'Value and S'Wide_Value for numeric subtypes yield the same result given the same sequence of characters. Implementation Permissions 56 An implementation may extend the Wide_Value, [Value, Wide_Image, and Image] attributes of a floating point type to support special values such as infinities and NaNs. 56.a Proof: The permission is really only necessary for Wide_ Value, because Value is defined in terms of Wide_Value, and because the behavior of Wide_Image and Image is already unspecified for things like infinities and NaNs. 56.b Reason: This is to allow implementations to define full support for IEEE arithmetic. See also the similar permission for Get in A.10.9. NOTES 57 (19) The evaluation of S'First or S'Last never raises an exception. If a scalar subtype S has a nonnull range, S'First and S'Last belong to this range. These values can, for example, always be assigned to a variable of subtype S. 57.a Discussion: This paragraph addresses an issue that came up with Ada 83, where for fixed point types, the end points of the range specified in the type definition were not necessarily within the base range of the type. However, it was later clarified (and we reconfirm it in 3.5.9, ``Fixed Point Types'') that the First and Last attributes reflect the true bounds chosen for the type, not the bounds specified in the type definition (which might be outside the ultimately chosen base range). 58 (20) For a subtype of a scalar type, the result delivered by the attributes Succ, Pred, and Value might not belong to the subtype; similarly, the actual parameters of the attributes Succ, Pred, and Image need not belong to the subtype. 59 (21) For any value V (including any nongraphic character) of an enumeration subtype S, S'Value(S'Image(V)) equals V, as does S'Wide_ Value(S'Wide_Image(V)). Neither expression ever raises Constraint_ Error. Examples 60 Examples of ranges: 61 -10 .. 10 X .. X + 1 0.0 .. 2.0*Pi Red .. Green -- see 3.5.1 1 .. 0 -- a null range Table'Range -- a range attribute reference (see 3.6) 62 Examples of range constraints: 63 range -999.0 .. +999.0 range S'First+1 .. S'Last-1 Incompatibilities With Ada 83 63.a {incompatibilities with Ada 83} S'Base is no longer defined for nonscalar types. One conceivable existing use of S'Base for nonscalar types is S'Base'Size where S is a generic formal private type. However, that is not generally useful because the actual subtype corresponding to S might be a constrained array or discriminated type, which would mean that S'Base'Size might very well overflow (for example, S'Base'Size where S is a constrained subtype of String will generally be 8 * (Integer'Last + 1)). For derived discriminated types that are packed, S'Base'Size might not even be well defined if the first subtype is constrained, thereby allowing some amount of normally required ``dope'' to have been squeezed out in the packing. Hence our conclusion is that S'Base'Size is not generally useful in a generic, and does not justify keeping the attribute Base for nonscalar types just so it can be used as a prefix. Extensions to Ada 83 63.b {extensions to Ada 83} The attribute S'Base for a scalar subtype is now permitted anywhere a subtype_mark is permitted. S'Base'First .. S'Base'Last is the base range of the type. Using an attribute_definition_clause, one cannot specify any subtype-specific attributes for the subtype denoted by S'Base (the base subtype). 63.c The attribute S'Range is now allowed for scalar subtypes. 63.d The attributes S'Min and S'Max are now defined, and made available for all scalar types. 63.e The attributes S'Succ, S'Pred, S'Image, S'Value, and S'Width are now defined for real types as well as discrete types. 63.f Wide_String versions of S'Image and S'Value are defined. These are called S'Wide_Image and S'Wide_Value to avoid introducing ambiguities involving uses of these attributes with string literals. Wording Changes From Ada 83 63.g We now use the syntactic category range_attribute_reference since it is now syntactically distinguished from other attribute references. 63.h The definition of S'Base has been moved here from 3.3.3 since it now applies only to scalar types. 63.i More explicit rules are provided for nongraphic characters. 3.5.1 Enumeration Types 1 [{enumeration type} An enumeration_type_definition defines an enumeration type.] Syntax 2 enumeration_type_definition ::= (enumeration_literal_specification {, enumeration_literal_specification}) 3 enumeration_literal_specification ::= defining_identifier | defining_chara\ cter_literal 4 defining_character_literal ::= character_literal Legality Rules 5 [The defining_identifiers and defining_character_literals listed in an enumeration_type_definition shall be distinct.] 5.a Proof: This is a ramification of the normal disallowance of homographs explicitly declared immediately in the same declarative region. Static Semantics 6 {enumeration literal} Each enumeration_literal_specification is the explicit declaration of the corresponding enumeration literal: it declares a parameterless function, whose defining name is the defining_identifier or defining_character_literal, and whose result type is the enumeration type. 6.a Reason: This rule defines the profile of the enumeration literal, which is used in the various types of conformance. 6.b Ramification: The parameterless function associated with an enumeration literal is fully defined by the enumeration_type_ definition; a body is not permitted for it, and it never fails the Elaboration_Check when called. 7 Each enumeration literal corresponds to a distinct value of the enumeration type, and to a distinct position number. {position number [of an enumeration value]} The position number of the value of the first listed enumeration literal is zero; the position number of the value of each subsequent enumeration literal is one more than that of its predecessor in the list. 8 [The predefined order relations between values of the enumeration type follow the order of corresponding position numbers.] 9 [{overloaded [enumeration literal]} If the same defining_identifier or defining_character_literal is specified in more than one enumeration_type_ definition, the corresponding enumeration literals are said to be overloaded. At any place where an overloaded enumeration literal occurs in the text of a program, the type of the enumeration literal has to be determinable from the context (see 8.6).] Dynamic Semantics 10 {elaboration [enumeration_type_definition]} {constrained (subtype)} {unconstrained (subtype)} The elaboration of an enumeration_type_definition creates the enumeration type and its first subtype, which is constrained to the base range of the type. 10.a Ramification: The first subtype of a discrete type is always constrained, except in the case of a derived type whose parent subtype is Whatever'Base. 11 When called, the parameterless function associated with an enumeration literal returns the corresponding value of the enumeration type. NOTES 12 (22) If an enumeration literal occurs in a context that does not otherwise suffice to determine the type of the literal, then qualification by the name of the enumeration type is one way to resolve the ambiguity (see 4.7). Examples 13 Examples of enumeration types and subtypes: 14 type Day is (Mon, Tue, Wed, Thu, Fri, Sat, Sun); type Suit is (Clubs, Diamonds, Hearts, Spades); type Gender is (M, F); type Level is (Low, Medium, Urgent); type Color is (White, Red, Yellow, Green, Blue, Brown, Black); type Light is (Red, Amber, Green); -- Red and Green are overloaded 15 type Hexa is ('A', 'B', 'C', 'D', 'E', 'F'); type Mixed is ('A', 'B', '*', B, None, '?', '%'); 16 subtype Weekday is Day range Mon .. Fri; subtype Major is Suit range Hearts .. Spades; subtype Rainbow is Color range Red .. Blue; -- the Color Red, not the Lig\ ht Wording Changes From Ada 83 16.a The syntax rule for defining_character_literal is new. It is used for the defining occurrence of a character_literal, analogously to defining_identifier. Usage occurrences use the name or selector_ name syntactic categories. 16.b We emphasize the fact that an enumeration literal denotes a function, which is called to produce a value. 3.5.2 Character Types Static Semantics 1 {character type} An enumeration type is said to be a character type if at least one of its enumeration literals is a character_literal. 2 {Latin-1} {BMP} {ISO 10646} {Character} The predefined type Character is a character type whose values correspond to the 256 code positions of Row 00 (also known as Latin-1) of the ISO 10646 Basic Multilingual Plane (BMP). Each of the graphic characters of Row 00 of the BMP has a corresponding character_literal in Character. Each of the nongraphic positions of Row 00 (0000-001F and 007F-009F) has a corresponding language-defined name, which is not usable as an enumeration literal, but which is usable with the attributes (Wide_)Image and (Wide_)Value; these names are given in the definition of type Character in A.1, ``The Package Standard'', but are set in italics. {italics (nongraphic characters)} 3 {Wide_Character} {BMP} {ISO 10646} The predefined type Wide_Character is a character type whose values correspond to the 65536 code positions of the ISO 10646 Basic Multilingual Plane (BMP). Each of the graphic characters of the BMP has a corresponding character_literal in Wide_Character. The first 256 values of Wide_Character have the same character_literal or language-defined name as defined for Character. The last 2 values of Wide_ Character correspond to the nongraphic positions FFFE and FFFF of the BMP, and are assigned the language-defined names FFFE and FFFF. As with the other language-defined names for nongraphic characters, the names FFFE and FFFF are usable only with the attributes (Wide_)Image and (Wide_)Value; they are not usable as enumeration literals. All other values of Wide_Character are considered graphic characters, and have a corresponding character_literal. 3.a Reason: The language-defined names are not usable as enumeration literals to avoid "polluting" the name space. Since Wide_Character is defined in Standard, if the names FFFE and FFFF were usable as enumeration literals, they would hide other nonoverloadable declarations with the same names in use-d packages. 3.b ISO 10646 has not defined the meaning of all of the code positions from 0100 through FFFD, but they are all considered graphic characters by Ada to simplify the implementation, and to allow for revisions to ISO 10646. In ISO 10646, FFFE and FFFF are special, and will never be associated with graphic characters in any revision. Implementation Permissions 4 {localization} In a nonstandard mode, an implementation may provide other interpretations for the predefined types Character and Wide_Character[, to conform to local conventions]. Implementation Advice 5 {localization} If an implementation supports a mode with alternative interpretations for Character and Wide_Character, the set of graphic characters of Character should nevertheless remain a proper subset of the set of graphic characters of Wide_Character. Any character set ``localizations'' should be reflected in the results of the subprograms defined in the language-defined package Characters.Handling (see A.3) available in such a mode. In a mode with an alternative interpretation of Character, the implementation should also support a corresponding change in what is a legal identifier_letter. NOTES 6 (23) The language-defined library package Characters.Latin_1 (see A.3.3) includes the declaration of constants denoting control characters, lower case characters, and special characters of the predefined type Character. 6.a To be honest: The package ASCII does the same, but only for the first 128 characters of Character. Hence, it is an obsolescent package, and we no longer mention it here. 7 (24) A conventional character set such as EBCDIC can be declared as a character type; the internal codes of the characters can be specified by an enumeration_representation_clause as explained in clause 13.4. Examples 8 Example of a character type: 9 type Roman_Digit is ('I', 'V', 'X', 'L', 'C', 'D', 'M'); Inconsistencies With Ada 83 9.a {inconsistencies with Ada 83} The declaration of Wide_Character in package Standard hides use-visible declarations with the same defining identifier. In the unlikely event that an Ada 83 program had depended on such a use-visible declaration, and the program remains legal after the substitution of Standard.Wide_Character, the meaning of the program will be different. Incompatibilities With Ada 83 9.b {incompatibilities with Ada 83} The presence of Wide_Character in package Standard means that an expression such as 9.c 'a' = 'b' 9.d is ambiguous in Ada 9X, whereas in Ada 83 both literals could be resolved to be of type Character. 9.e The change in visibility rules (see 4.2) for character literals means that additional qualification might be necessary to resolve expressions involving overloaded subprograms and character literals. Extensions to Ada 83 9.f {extensions to Ada 83} The type Character has been extended to have 256 positions, and the type Wide_Character has been added. Note that this change was already approved by the ARG for Ada 83 conforming compilers. 9.g The rules for referencing character literals are changed (see 4.2), so that the declaration of the character type need not be directly visible to use its literals, similar to null and string literals. Context is used to resolve their type. 3.5.3 Boolean Types Static Semantics 1 {Boolean} There is a predefined enumeration type named Boolean, [declared in the visible part of package Standard]. {False} {True} It has the two enumeration literals False and True ordered with the relation False < True. {boolean type} Any descendant of the predefined type Boolean is called a boolean type. 1.a Implementation Note: An implementation is not required to support enumeration representation clauses on boolean types that impose an unacceptable implementation burden. See 13.4, ``Enumeration Representation Clauses''. However, it is generally straightforward to support representations where False is zero and True is 2**n - 1 for some n. 3.5.4 Integer Types 1 {integer type} {signed integer type} {modular type} An integer_type_ definition defines an integer type; it defines either a signed integer type, or a modular integer type. The base range of a signed integer type includes at least the values of the specified range. A modular type is an integer type with all arithmetic modulo a specified positive modulus; such a type corresponds to an unsigned type with wrap-around semantics. {unsigned type: see modular type} Syntax 2 integer_type_definition ::= signed_integer_type_definition | modular_type_d\ efinition 3 signed_integer_type_definition ::= range static_simple_expression .. static\ _simple_expression 3.a Discussion: We don't call this a range_constraint, because it is rather different -- not only is it required to be static, but the associated overload resolution rules are different than for normal range constraints. A similar comment applies to real_range_ specification. This used to be integer_range_specification but when we added support for modular types, it seemed overkill to have three levels of syntax rules, and just calling these signed_integer_range_ specification and modular_range_specification loses the fact that they are defining different classes of types, which is important for the generic type matching rules. 4 modular_type_definition ::= mod static_expression Name Resolution Rules 5 {expected type [signed_integer_type_definition simple_expression]} Each simple_expression in a signed_integer_type_definition is expected to be of any integer type; they need not be of the same type. {expected type [modular_type_definition expression]} The expression in a modular_type_ definition is likewise expected to be of any integer type. Legality Rules 6 The simple_expressions of a signed_integer_type_definition shall be static, and their values shall be in the range System.Min_Int .. System.Max_ Int. 7 {modulus (of a modular type)} {Max_Binary_Modulus} {Max_Nonbinary_ Modulus} The expression of a modular_type_definition shall be static, and its value (the modulus) shall be positive, and shall be no greater than System.Max_Binary_Modulus if a power of 2, or no greater than System.Max_ Nonbinary_Modulus if not. 7.a Reason: For a 2's-complement machine, supporting nonbinary moduli greater than System.Max_Int can be quite difficult, whereas essentially any binary moduli are straightforward to support, up to 2*System.Max_Int+2, so this justifies having two separate limits. Static Semantics 8 The set of values for a signed integer type is the (infinite) set of mathematical integers[, though only values of the base range of the type are fully supported for run-time operations]. The set of values for a modular integer type are the values from 0 to one less than the modulus, inclusive. 9 {base range [of a signed integer type]} A signed_integer_type_definition defines an integer type whose base range includes at least the values of the simple_expressions and is symmetric about zero, excepting possibly an extra negative value. {constrained (subtype)} {unconstrained (subtype)} A signed_ integer_type_definition also defines a constrained first subtype of the type, with a range whose bounds are given by the values of the simple_expressions, converted to the type being defined. {implicit subtype conversion [bounds of signed integer type]} 9.a Implementation Note: The base range of a signed integer type might be much larger than is necessary to satisfy the aboved requirements. 10 {base range [of a modular type]} A modular_type_definition defines a modular type whose base range is from zero to one less than the given modulus. {constrained (subtype)} {unconstrained (subtype)} A modular_type_ definition also defines a constrained first subtype of the type with a range that is the same as the base range of the type. 11 {Integer} There is a predefined signed integer subtype named Integer[, declared in the visible part of package Standard]. It is constrained to the base range of its type. 11.a Reason: Integer is a constrained subtype, rather than an unconstrained subtype. This means that on assignment to an object of subtype Integer, a range check is required. On the other hand, an object of subtype Integer'Base is unconstrained, and no range check (only overflow check) is required on assignment. For example, if the object is held in an extended-length register, its value might be outside of Integer'First .. Integer'Last. All parameter and result subtypes of the predefined integer operators are of such unconstrained subtypes, allowing extended-length registers to be used as operands or for the result. In an earlier version of Ada 9X, Integer was unconstrained. However, the fact that certain Constraint_Errors might be omitted or appear elsewhere was felt to be an undesirable upward inconsistency in this case. Note that for Float, the opposite conclusion was reached, partly because of the high cost of performing range checks when not actually necessary. Objects of subtype Float are unconstrained, and no range checks, only overflow checks, are performed for them. 12 {Natural} {Positive} Integer has two predefined subtypes, [declared in the visible part of package Standard:] 13 subtype Natural is Integer range 0 .. Integer'Last; subtype Positive is Integer range 1 .. Integer'Last; 14 {root_integer} {Min_Int} {Max_Int} A type defined by an integer_type_ definition is implicitly derived from root_integer, an anonymous predefined (specific) integer type, whose base range is System.Min_Int .. System.Max_ Int. However, the base range of the new type is not inherited from root_ integer, but is instead determined by the range or modulus specified by the integer_type_definition. {universal_integer [partial]} {integer literals} [Integer literals are all of the type universal_integer, the universal type (see 3.4.1) for the class rooted at root_integer, allowing their use with the operations of any integer type.] 14.a Discussion: This implicit derivation is not considered exactly equivalent to explicit derivation via a derived_type_ definition. In particular, integer types defined via a derived_type_ definition inherit their base range from their parent type. A type defined by an integer_type_definition does not necessarily inherit its base range from root_integer. It is not specified whether the implicit derivation from root_integer is direct or indirect, not that it really matters. All we want is for all integer types to be descendants of root_integer. 14.b Implementation Note: It is the intent that even nonstandard integer types (see below) will be descendants of root_integer, even though they might have a base range that exceeds that of root_ integer. This causes no problem for static calculations, which are performed without range restrictions (see 4.9). However for run-time calculations, it is possible that Constraint_Error might be raised when using an operator of root_integer on the result of 'Val applied to a value of a nonstandard integer type. 15 {position number [of an integer value]} The position number of an integer value is equal to the value. 16 For every modular subtype S, the following attribute is defined: 17 S'Modulus S'Modulus yields the modulus of the type of S, as a value of the type universal_integer. Dynamic Semantics 18 {elaboration [integer_type_definition]} The elaboration of an integer_ type_definition creates the integer type and its first subtype. 19 For a modular type, if the result of the execution of a predefined operator (see 4.5) is outside the base range of the type, the result is reduced modulo the modulus of the type to a value that is within the base range of the type. 20 {Overflow_Check [partial]} {check, language-defined (Overflow_Check)} {Constraint_Error (raised by failure of run-time check)} For a signed integer type, the exception Constraint_Error is raised by the execution of an operation that cannot deliver the correct result because it is outside the base range of the type.[{Division_Check [partial]} {check, language-defined (Division_Check)} {Constraint_Error (raised by failure of run-time check)} For any integer type, Constraint_Error is raised by the operators "/", "rem", and "mod" if the right operand is zero.] Implementation Requirements 21 {Integer} In an implementation, the range of Integer shall include the range -2**15+1 .. +2**15-1. 22 {Long_Integer} If Long_Integer is predefined for an implementation, then its range shall include the range -2**31+1 .. +2**31-1. 23 System.Max_Binary_Modulus shall be at least 2**16. Implementation Permissions 24 For the execution of a predefined operation of a signed integer type, the implementation need not raise Constraint_Error if the result is outside the base range of the type, so long as the correct result is produced. 24.a Discussion: Constraint_Error is never raised for operations on modular types, except for divide-by-zero (and rem/mod-by-zero). 25 {Long_Integer} {Short_Integer} An implementation may provide additional predefined signed integer types[, declared in the visible part of Standard], whose first subtypes have names of the form Short_Integer, Long_Integer, Short_Short_Integer, Long_Long_Integer, etc. Different predefined integer types are allowed to have the same base range. However, the range of Integer should be no wider than that of Long_Integer. Similarly, the range of Short_ Integer (if provided) should be no wider than Integer. Corresponding recommendations apply to any other predefined integer types. There need not be a named integer type corresponding to each distinct base range supported by an implementation. The range of each first subtype should be the base range of its type. 25.a Implementation defined: The predefined integer types declared in Standard. 26 {nonstandard integer type} An implementation may provide nonstandard integer types, descendants of root_integer that are declared outside of the specification of package Standard, which need not have all the standard characteristics of a type defined by an integer_type_definition. For example, a nonstandard integer type might have an asymmetric base range or it might not be allowed as an array or loop index (a very long integer). Any type descended from a nonstandard integer type is also nonstandard. An implementation may place arbitrary restrictions on the use of such types; it is implementation defined whether operators that are predefined for ``any integer type'' are defined for a particular nonstandard integer type. [In any case, such types are not permitted as explicit_generic_actual_parameters for formal scalar types -- see 12.5.2.] 26.a Implementation defined: Any nonstandard integer types and the operators defined for them. 27 {one's complement [modular types]} For a one's complement machine, the high bound of the base range of a modular type whose modulus is one less than a power of 2 may be equal to the modulus, rather than one less than the modulus. It is implementation defined for which powers of 2, if any, this permission is exercised. Implementation Advice 28 {Long_Integer} An implementation should support Long_Integer in addition to Integer if the target machine supports 32-bit (or longer) arithmetic. No other named integer subtypes are recommended for package Standard. Instead, appropriate named integer subtypes should be provided in the library package Interfaces (see B.2). 28.a Implementation Note: To promote portability, implementations should explicitly declare the integer (sub)types Integer and Long_ Integer in Standard, and leave other predefined integer types anonymous. For implementations that already support Byte_Integer, etc., upward compatibility argues for keeping such declarations in Standard during the transition period, but perhaps generating a warning on use. A separate package Interfaces in the predefined environment is available for pre-declaring types such as Integer_8, Integer_16, etc. See B.2. In any case, if the user declares a subtype (first or not) whose range fits in, for example, a byte, the implementation can store variables of the subtype in a single byte, even if the base range of the type is wider. 29 {two's complement [modular types]} An implementation for a two's complement machine should support modular types with a binary modulus up to System.Max_Int*2+2. An implementation should support a nonbinary modulus up to Integer'Last. 29.a Reason: Modular types provide bit-wise "and", "or", "xor", and "not" operations. It is important for systems programming that these be available for all integer types of the target hardware. 29.b Ramification: Note that on a one's complement machine, the largest supported modular type would normally have a nonbinary modulus. On a two's complement machine, the largest supported modular type would normally have a binary modulus. 29.c Implementation Note: Supporting a nonbinary modulus greater than Integer'Last can impose an undesirable implementation burden on some machines. NOTES 30 (25) {universal_integer} {integer literals} Integer literals are of the anonymous predefined integer type universal_integer. Other integer types have no literals. However, the overload resolution rules (see 8.6, ``The Context of Overload Resolution'') allow expressions of the type universal_integer whenever an integer type is expected. 31 (26) The same arithmetic operators are predefined for all signed integer types defined by a signed_integer_type_definition (see 4.5, ``Operators and Expression Evaluation''). For modular types, these same operators are predefined, plus bit-wise logical operators (and, or, xor, and not). In addition, for the unsigned types declared in the language-defined package Interfaces (see B.2), functions are defined that provide bit-wise shifting and rotating. 32 (27) Modular types match a generic_formal_parameter_declaration of the form "type T is mod <>;"; signed integer types match "type T is range <>;" (see 12.5.2). Examples 33 Examples of integer types and subtypes: 34 type Page_Num is range 1 .. 2_000; type Line_Size is range 1 .. Max_Line_Size; 35 subtype Small_Int is Integer range -10 .. 10; subtype Column_Ptr is Line_Size range 1 .. 10; subtype Buffer_Size is Integer range 0 .. Max; 36 type Byte is mod 256; -- an unsigned byte type Hash_Index is mod 97; -- modulus is prime Extensions to Ada 83 36.a {extensions to Ada 83} An implementation is allowed to support any number of distinct base ranges for integer types, even if fewer integer types are explicitly declared in Standard. 36.b Modular (unsigned, wrap-around) types are new. Wording Changes From Ada 83 36.c Ada 83's integer types are now called "signed" integer types, to contrast them with "modular" integer types. 36.d Standard.Integer, Standard.Long_Integer, etc., denote con- strained subtypes of predefined integer types, consistent with the Ada 9X model that only subtypes have names. 36.e We now impose minimum requirements on the base range of Integer and Long_Integer. 36.f We no longer explain integer type definition in terms of an equivalence to a normal type derivation, except to say that all integer types are by definition implicitly derived from root_integer. This is for various reasons. 36.g First of all, the equivalence with a type derivation and a subtype declaration was not perfect, and was the source of various AIs (for example, is the conversion of the bounds static? Is a numeric type a derived type with respect to other rules of the language?) 36.h Secondly, we don't want to require that every integer size supported shall have a corresponding named type in Standard. Adding named types to Standard creates nonportabilities. 36.i Thirdly, we don't want the set of types that match a formal derived type "type T is new Integer;" to depend on the particular underlying integer representation chosen to implement a given user-defined integer type. Hence, we would have needed anonymous integer types as parent types for the implicit derivation anyway. We have simply chosen to identify only one anonymous integer type -- root_integer, and stated that every integer type is derived from it. 36.j Finally, the ``fiction'' that there were distinct preexisting predefined types for every supported representation breaks down for fixed point with arbitrary smalls, and was never exploited for enumeration types, array types, etc. Hence, there seems little benefit to pushing an explicit equivalence between integer type definition and normal type derivation. 3.5.5 Operations of Discrete Types Static Semantics 1 For every discrete subtype S, the following attributes are defined: 2 S'Pos S'Pos denotes a function with the following specification: 3 function S'Pos(Arg : S'Base) return universal_integer 4 This function returns the position number of the value of Arg, as a value of type universal_integer. 5 S'Val S'Val denotes a function with the following specification: 6 function S'Val(Arg : universal_integer) return S'Base 7 {evaluation [Val]} {Constraint_Error (raised by failure of run-time check)} This function returns a value of the type of S whose position number equals the value of Arg. {Range_ Check [partial]} {check, language-defined (Range_Check)} For the evaluation of a call on S'Val, if there is no value in the base range of its type with the given position number, Constraint_Error is raised. 7.a Ramification: By the overload resolution rules, a formal parameter of type universal_integer allows an actual parameter of any integer type. 7.b Reason: We considered allowing S'Val for a signed integer subtype S to return an out-of-range value, but since checks were required for enumeration and modular types anyway, the allowance didn't seem worth the complexity of the rule. Implementation Advice 8 For the evaluation of a call on S'Pos for an enumeration subtype, if the value of the operand does not correspond to the internal code for any enumeration literal of its type [(perhaps due to an uninitialized variable)], then the implementation should raise Program_Error. {Program_Error (raised by failure of run-time check)} This is particularly important for enumeration types with noncontiguous internal codes specified by an enumeration_ representation_clause. 8.a Reason: We say Program_Error here, rather than Constraint_ Error, because the main reason for such values is uninitialized variables, and the normal way to indicate such a use (if detected) is to raise Program_Error. (Other reasons would involve the misuse of low-level features such as Unchecked_Conversion.) NOTES 9 (28) Indexing and loop iteration use values of discrete types. 10 (29) {predefined operations [of a discrete type]} The predefined operations of a discrete type include the assignment operation, qualification, the membership tests, and the relational operators; for a boolean type they include the short-circuit control forms and the logical operators; for an integer type they include type conversion to and from other numeric types, as well as the binary and unary adding operators - and +, the multiplying operators, the unary operator abs, and the exponentiation operator. The assignment operation is described in 5.2. The other predefined operations are described in Section 4. 11 (30) As for all types, objects of a discrete type have Size and Address attributes (see 13.3). 12 (31) For a subtype of a discrete type, the result delivered by the attribute Val might not belong to the subtype; similarly, the actual parameter of the attribute Pos need not belong to the subtype. The following relations are satisfied (in the absence of an exception) by these attributes: 13 S'Val(S'Pos(X)) = X S'Pos(S'Val(N)) = N Examples 14 Examples of attributes of discrete subtypes: 15 -- For the types and subtypes declared in subclause 3.5.1 the following ho\ ld: 16 -- Color'First = White, Color'Last = Black -- Rainbow'First = Red, Rainbow'Last = Blue 17 -- Color'Succ(Blue) = Rainbow'Succ(Blue) = Brown -- Color'Pos(Blue) = Rainbow'Pos(Blue) = 4 -- Color'Val(0) = Rainbow'Val(0) = White Extensions to Ada 83 17.a {extensions to Ada 83} The attributes S'Succ, S'Pred, S'Width, S'Image, and S'Value have been generalized to apply to real types as well (see 3.5, ``Scalar Types''). 3.5.6 Real Types 1 {real type} Real types provide approximations to the real numbers, with relative bounds on errors for floating point types, and with absolute bounds for fixed point types. Syntax 2 real_type_definition ::= floating_point_definition | fixed_point_definition Static Semantics 3 {root_real} A type defined by a real_type_definition is implicitly derived from root_real, an anonymous predefined (specific) real type. [Hence, all real types, whether floating point or fixed point, are in the derivation class rooted at root_real.] 3.a Ramification: It is not specified whether the derivation from root_real is direct or indirect, not that it really matters. All we want is for all real types to be descendants of root_real. 4 [{universal_real [partial]} {real literals} Real literals are all of the type universal_real, the universal type (see 3.4.1) for the class rooted at root_real, allowing their use with the operations of any real type. {universal_fixed [partial]} Certain multiplying operators have a result type of universal_fixed (see 4.5.5), the universal type for the class of fixed point types, allowing the result of the multiplication or division to be used where any specific fixed point type is expected.] Dynamic Semantics 5 {elaboration [real_type_definition]} The elaboration of a real_type_ definition consists of the elaboration of the floating_point_definition or the fixed_point_definition. Implementation Requirements 6 An implementation shall perform the run-time evaluation of a use of a predefined operator of root_real with an accuracy at least as great as that of any floating point type definable by a floating_point_definition. 6.a Ramification: Static calculations using the operators of root_ real are exact, as for all static calculations. See 4.9. 6.b Implementation Note: The Digits attribute of the type used to represent root_real at run time is at least as great as that of any other floating point type defined by a floating_point_definition, and its safe range includes that of any such floating point type with the same Digits attribute. On some machines, there might be real types with less accuracy but a wider range, and hence run-time calculations with root_real might not be able to accommodate all values that can be represented at run time in such floating point or fixed point types. Implementation Permissions 7 [For the execution of a predefined operation of a real type, the implementation need not raise Constraint_Error if the result is outside the base range of the type, so long as the correct result is produced, or the Machine_Overflows attribute of the type is false (see G.2).] 8 {nonstandard real type} 8.a Implementation defined: Any nonstandard real types and the operators defined for them. An implementation may provide nonstandard real types, descendants of root_ real that are declared outside of the specification of package Standard, which need not have all the standard characteristics of a type defined by a real_type_definition. For example, a nonstandard real type might have an asymmetric or unsigned base range, or its predefined operations might wrap around or ``saturate'' rather than overflow (modular or saturating arithmetic), or it might not conform to the accuracy model (see G.2). Any type descended from a nonstandard real type is also nonstandard. An implementation may place arbitrary restrictions on the use of such types; it is implementation defined whether operators that are predefined for ``any real type'' are defined for a particular nonstandard real type. [In any case, such types are not permitted as explicit_generic_actual_parameters for formal scalar types -- see 12.5.2.] NOTES 9 (32) As stated, real literals are of the anonymous predefined real type universal_real. Other real types have no literals. However, the overload resolution rules (see 8.6) allow expressions of the type universal_real whenever a real type is expected. Wording Changes From Ada 83 9.a The syntax rule for real_type_definition is modified to use the new syntactic categories floating_point_definition and fixed_point_ definition, instead of floating_point_constraint and fixed_point_ constraint, because the semantics of a type definition are significantly different than the semantics of a constraint. 9.b All discussion of model numbers, safe ranges, and machine numbers is moved to 3.5.7, 3.5.8, and G.2. Values of a fixed point type are now described as being multiples of the small of the fixed point type, and we have no need for model numbers, safe ranges, etc. for fixed point types. 3.5.7 Floating Point Types 1 {floating point type} For floating point types, the error bound is specified as a relative precision by giving the required minimum number of significant decimal digits. Syntax 2 floating_point_definition ::= digits static_expression [real_range_specification] 3 real_range_specification ::= range static_simple_expression .. static_simple_expression Name Resolution Rules 4 {requested decimal precision (of a floating point type)} The requested decimal precision, which is the minimum number of significant decimal digits required for the floating point type, is specified by the value of the expression given after the reserved word digits. {expected type [requested decimal precision]} This expression is expected to be of any integer type. 5 {expected type [real_range_specification bounds]} Each simple_expression of a real_range_specification is expected to be of any real type[; the types need not be the same]. Legality Rules 6 {Max_Base_Digits} The requested decimal precision shall be specified by a static expression whose value is positive and no greater than System.Max_ Base_Digits. Each simple_expression of a real_range_specification shall also be static. {Max_Digits} If the real_range_specification is omitted, the requested decimal precision shall be no greater than System.Max_Digits. 6.a Reason: We have added Max_Base_Digits to package System. It corresponds to the requested decimal precision of root_real. System.Max_Digits corresponds to the maximum value for Digits that may be specified in the absence of a real_range_specification, for upward compatibility. These might not be the same if root_real has a base range that does not include +/- 10.0**(4*Max_Base_Digits). 7 A floating_point_definition is illegal if the implementation does not support a floating point type that satisfies the requested decimal precision and range. 7.a Implementation defined: What combinations of requested decimal precision and range are supported for floating point types. Static Semantics 8 The set of values for a floating point type is the (infinite) set of rational numbers. {machine numbers (of a floating point type)} The machine numbers of a floating point type are the values of the type that can be represented exactly in every unconstrained variable of the type. {base range [of a floating point type]} The base range (see 3.5) of a floating point type is symmetric around zero, except that it can include some extra negative values in some implementations. 8.a Implementation Note: For example, if a 2's complement representation is used for the mantissa rather than a sign-mantissa or 1's complement representation, then there is usually one extra negative machine number. 8.b To be honest: If the Signed_Zeros attribute is True, then minus zero could in a sense be considered a value of the type. However, for most purposes, minus zero behaves the same as plus zero. 9 {base decimal precision (of a floating point type)} The base decimal precision of a floating point type is the number of decimal digits of precision representable in objects of the type. {safe range (of a floating point type)} The safe range of a floating point type is that part of its base range for which the accuracy corresponding to the base decimal precision is preserved by all predefined operations. 9.a Implementation Note: In most cases, the safe range and base range are the same. However, for some hardware, values near the boundaries of the base range might result in excessive inaccuracies or spurious overflows when used with certain predefined operations. For such hardware, the safe range would omit such values. 10 {base decimal precision [of a floating point type]} A floating_point_ definition defines a floating point type whose base decimal precision is no less than the requested decimal precision. {safe range [of a floating point type]} {base range [of a floating point type]} If a real_range_specification is given, the safe range of the floating point type (and hence, also its base range) includes at least the values of the simple expressions given in the real_range_specification. If a real_range_specification is not given, the safe (and base) range of the type includes at least the values of the range -10.0**(4*D) .. +10.0**(4*D) where D is the requested decimal precision. [The safe range might include other values as well. The attributes Safe_ First and Safe_Last give the actual bounds of the safe range.] 11 A floating_point_definition also defines a first subtype of the type. {constrained (subtype)} {unconstrained (subtype)} If a real_range_ specification is given, then the subtype is constrained to a range whose bounds are given by a conversion of the values of the simple_expressions of the real_range_specification to the type being defined. {implicit subtype conversion [bounds of a floating point type]} Otherwise, the subtype is unconstrained. 12 {Float} There is a predefined, unconstrained, floating point subtype named Float[, declared in the visible part of package Standard]. Dynamic Semantics 13 {elaboration [floating_point_definition]} [The elaboration of a floating_point_definition creates the floating point type and its first subtype.] Implementation Requirements 14 {Float} In an implementation that supports floating point types with 6 or more digits of precision, the requested decimal precision for Float shall be at least 6. 15 {Long_Float} If Long_Float is predefined for an implementation, then its requested decimal precision shall be at least 11. Implementation Permissions 16 {Short_Float} {Long_Float} An implementation is allowed to provide additional predefined floating point types[, declared in the visible part of Standard], whose (unconstrained) first subtypes have names of the form Short_ Float, Long_Float, Short_Short_Float, Long_Long_Float, etc. Different predefined floating point types are allowed to have the same base decimal precision. However, the precision of Float should be no greater than that of Long_Float. Similarly, the precision of Short_Float (if provided) should be no greater than Float. Corresponding recommendations apply to any other predefined floating point types. There need not be a named floating point type corresponding to each distinct base decimal precision supported by an implementation. 16.a Implementation defined: The predefined floating point types declared in Standard. Implementation Advice 17 {Long_Float} An implementation should support Long_Float in addition to Float if the target machine supports 11 or more digits of precision. No other named floating point subtypes are recommended for package Standard. Instead, appropriate named floating point subtypes should be provided in the library package Interfaces (see B.2). 17.a Implementation Note: To promote portability, implementations should explicitly declare the floating point (sub)types Float and Long_Float in Standard, and leave other predefined float types anonymous. For implementations that already support Short_Float, etc., upward compatibility argues for keeping such declarations in Standard during the transition period, but perhaps generating a warning on use. A separate package Interfaces in the predefined environment is available for pre-declaring types such as Float_32, IEEE_Float_64, etc. See B.2. NOTES 18 (33) If a floating point subtype is unconstrained, then assignments to variables of the subtype involve only Overflow_Checks, never Range_ Checks. Examples 19 Examples of floating point types and subtypes: 20 type Coefficient is digits 10 range -1.0 .. 1.0; 21 type Real is digits 8; type Mass is digits 7 range 0.0 .. 1.0E35; 22 subtype Probability is Real range 0.0 .. 1.0; -- a subtype with a small\ er range Inconsistencies With Ada 83 22.a {inconsistencies with Ada 83} No Range_Checks, only Overflow_ Checks, are performed on variables (or parameters) of an unconstrained floating point subtype. This is upward compatible for programs that do not raise Constraint_Error. For those that do raise Constraint_Error, it is possible that the exception will be raised at a later point, or not at all, if extended range floating point registers are used to hold the value of the variable (or parameter). 22.b Reason: This change was felt to be justified by the possibility of improved performance on machines with extended-range floating point registers. An implementation need not take advantage of this relaxation in the range checking; it can hide completely the use of extended range registers if desired, presumably at some run-time expense. Wording Changes From Ada 83 22.c The syntax rules for floating_point_constraint and floating_ accuracy_definition are removed. The syntax rules for floating_ point_definition and real_range_specification are new. 22.d A syntax rule for digits_constraint is given in 3.5.9, ``Fixed Point Types''. In J.3 we indicate that a digits_constraint may be applied to a floating point subtype_mark as well (to be compatible with Ada 83's floating_point_constraint). 22.e Discussion of model numbers is postponed to 3.5.8 and G.2. The concept of safe numbers has been replaced by the concept of the safe range of values. The bounds of the safe range are given by T'Safe_First .. T'Safe_Last, rather than -T'Safe_Large .. T'Safe_ Large, since on some machines the safe range is not perfectly symmetric. The concept of machine numbers is new, and is relevant to the definition of Succ and Pred for floating point numbers. 3.5.8 Operations of Floating Point Types Static Semantics 1 The following attribute is defined for every floating point subtype S: 2 S'Digits S'Digits denotes the requested decimal precision for the subtype S. The value of this attribute is of the type universal_integer. The requested decimal precision of the base subtype of a floating point type T is defined to be the largest value of d for which ceiling(d * log(10) / log(T'Machine_Radix)) + 1 <= T'Model_Mantissa. NOTES 3 (34) {predefined operations [of a floating point type]} The predefined operations of a floating point type include the assignment operation, qualification, the membership tests, and explicit conversion to and from other numeric types. They also include the relational operators and the following predefined arithmetic operators: the binary and unary adding operators - and +, certain multiplying operators, the unary operator abs, and the exponentiation operator. 4 (35) As for all types, objects of a floating point type have Size and Address attributes (see 13.3). Other attributes of floating point types are defined in A.5.3. 3.5.9 Fixed Point Types 1 {fixed point type} {ordinary fixed point type} {decimal fixed point type} A fixed point type is either an ordinary fixed point type, or a decimal fixed point type. {delta (of a fixed point type)} The error bound of a fixed point type is specified as an absolute value, called the delta of the fixed point type. Syntax 2 fixed_point_definition ::= ordinary_fixed_point_definition | decimal_fixed_\ point_definition 3 ordinary_fixed_point_definition ::= delta static_expression real_range_specification 4 decimal_fixed_point_definition ::= delta static_expression digits static_expression [real_range_specificati\ on] 5 digits_constraint ::= digits static_expression [range_constraint] Name Resolution Rules 6 {expected type [fixed point type delta]} For a type defined by a fixed_ point_definition, the delta of the type is specified by the value of the expression given after the reserved word delta; this expression is expected to be of any real type. {expected type [decimal fixed point type digits]} {digits (of a decimal fixed point subtype)} {decimal fixed point type} For a type defined by a decimal_fixed_point_definition (a decimal fixed point type), the number of significant decimal digits for its first subtype (the digits of the first subtype) is specified by the expression given after the reserved word digits; this expression is expected to be of any integer type. Legality Rules 7 In a fixed_point_definition or digits_constraint, the expressions given after the reserved words delta and digits shall be static; their values shall be positive. 8 {small (of a fixed point type)} The set of values of a fixed point type comprise the integral multiples of a number called the small of the type. {ordinary fixed point type} For a type defined by an ordinary_fixed_point_ definition (an ordinary fixed point type), the small may be specified by an attribute_definition_clause (see 13.3); if so specified, it shall be no greater than the delta of the type. If not specified, the small of an ordinary fixed point type is an implementation-defined power of two less than or equal to the delta. 8.a Implementation defined: The small of an ordinary fixed point type. 9 For a decimal fixed point type, the small equals the delta; the delta shall be a power of 10. If a real_range_specification is given, both bounds of the range shall be in the range -(10**digits-1)*delta .. +(10**digits-1)*delta. 10 A fixed_point_definition is illegal if the implementation does not support a fixed point type with the given small and specified range or digits. 10.a Implementation defined: What combinations of small, range, and digits are supported for fixed point types. 11 For a subtype_indication with a digits_constraint, the subtype_mark shall denote a decimal fixed point subtype. 11.a To be honest: Or, as an obsolescent feature, a floating point subtype is permitted -- see J.3. Static Semantics 12 {base range [of a fixed point type]} The base range (see 3.5) of a fixed point type is symmetric around zero, except possibly for an extra negative value in some implementations. 13 {base range [of an ordinary fixed point type]} An ordinary_fixed_point_ definition defines an ordinary fixed point type whose base range includes at least all multiples of small that are between the bounds specified in the real_range_specification. The base range of the type does not necessarily include the specified bounds themselves. {constrained (subtype)} {unconstrained (subtype)} An ordinary_fixed_point_definition also defines a constrained first subtype of the type, with each bound of its range given by the closer to zero of: 14 the value of the conversion to the fixed point type of the corresponding expression of the real_range_specification; {implicit subtype conversion [bounds of a fixed point type]} 15 the corresponding bound of the base range. 16 {base range [of a decimal fixed point type]} A decimal_fixed_point_ definition defines a decimal fixed point type whose base range includes at least the range -(10**digits-1)*delta .. +(10**digits-1)*delta. {constrained (subtype)} {unconstrained (subtype)} A decimal_fixed_point_definition also defines a constrained first subtype of the type. If a real_range_ specification is given, the bounds of the first subtype are given by a conversion of the values of the expressions of the real_range_specification. {implicit subtype conversion [bounds of a decimal fixed point type]} Otherwise, the range of the first subtype is -(10**digits-1)*delta .. +(10**digits-1)*delta. Dynamic Semantics 17 {elaboration [fixed_point_definition]} The elaboration of a fixed_point_ definition creates the fixed point type and its first subtype. 18 For a digits_constraint on a decimal fixed point subtype with a given delta, if it does not have a range_constraint, then it specifies an implicit range -(10**D-1)*delta .. +(10**D-1)*delta, where D is the value of the expression. {compatibility (digits_constraint with a decimal fixed point subtype)} A digits_constraint is compatible with a decimal fixed point subtype if the value of the expression is no greater than the digits of the subtype, and if it specifies (explicitly or implicitly) a range that is compatible with the subtype. 18.a Discussion: Except for the requirement that the digits specified be no greater than the digits of the subtype being constrained, a digits_constraint is essentially equivalent to a range_constraint. 18.b Consider the following example: 18.c type D is delta 0.01 digits 7 range -0.00 .. 9999.99; 18.d The compatibility rule implies that the digits_constraint "digits 6" specifies an implicit range of "- 99.9999 .. 99.9999". Thus, "digits 6" is not compatible with the constraint of D, but "digits 6 range 0.00 .. 9999.99" is compatible. 18.e A value of a scalar type belongs to a constrained subtype of the type if it belongs to the range of the subtype. Attributes like Digits and Delta have no affect on this fundamental rule. So the obsolescent forms of digits_constraints and delta_constraints that are called ``accuracy constraints'' in RM83 don't really represent constraints on the values of the subtype, but rather primarily affect compatibility of the ``constraint'' with the subtype being ``constrained.'' In this sense, they might better be called ``subtype assertions'' rather than ``constraints.'' 18.f Note that the digits_constraint on a decimal fixed point subtype is a combination of an assertion about the digits of the subtype being further constrained, and a constraint on the range of the subtype being defined, either explicit or implicit. 19 {elaboration [digits_constraint]} The elaboration of a digits_constraint consists of the elaboration of the range_constraint, if any. {Range_Check [partial]} {check, language-defined (Range_Check)} If a range_constraint is given, a check is made that the bounds of the range are both in the range -(10**D-1)*delta .. +(10**D-1)*delta, where D is the value of the (static) expression given after the reserved word digits. {Constraint_Error (raised by failure of run-time check)} If this check fails, Constraint_Error is raised. Implementation Requirements 20 The implementation shall support at least 24 bits of precision (including the sign bit) for fixed point types. 20.a Reason: This is sufficient to represent Standard.Duration with a small no more than 50 milliseconds. Implementation Permissions 21 Implementations are permitted to support only smalls that are a power of two. In particular, all decimal fixed point type declarations can be disallowed. Note however that conformance with the Information Systems Annex requires support for decimal smalls, and decimal fixed point type declarations with digits up to at least 18. 21.a Implementation Note: The accuracy requirements for multiplication, division, and conversion (see G.2.1, ``Model of Floating Point Arithmetic'') are such that support for arbitrary smalls should be practical without undue implementation effort. Therefore, implementations should support fixed point types with arbitrary values for small (within reason). One reasonable limitation would be to limit support to fixed point types that can be converted to the most precise floating point type without loss of precision (so that Fixed_IO is implementable in terms of Float_IO). NOTES 22 (36) The base range of an ordinary fixed point type need not include the specified bounds themselves so that the range specification can be given in a natural way, such as: 23 type Fraction is delta 2.0**(-15) range -1.0 .. 1.0; 24 With 2's complement hardware, such a type could have a signed 16-bit representation, using 1 bit for the sign and 15 bits for fraction, resulting in a base range of -1.0 .. 1.0-2.0**(-15). Examples 25 Examples of fixed point types and subtypes: 26 type Volt is delta 0.125 range 0.0 .. 255.0; 27 -- A pure fraction which requires all the available -- space in a word can be declared as the type Fraction: type Fraction is delta System.Fine_Delta range -1.0 .. 1.0; -- Fraction'Last = 1.0 - System.Fine_Delta 28 type Money is delta 0.01 digits 15; -- decimal fixed point subtype Salary is Money digits 10; -- Money'Last = 10.0**13 - 0.01, Salary'Last = 10.0**8 - 0.01 Inconsistencies With Ada 83 28.a {inconsistencies with Ada 83} In Ada 9X, S'Small always equals S'Base'Small, so if an implementation chooses a small for a fixed point type smaller than required by the delta, the value of S'Small in Ada 9X might not be the same as it was in Ada 83. Extensions to Ada 83 28.b {extensions to Ada 83} Decimal fixed point types are new, though their capabilities are essentially similar to that available in Ada 83 with a fixed point type whose small equals its delta equals a power of 10. However, in the Information Systems Annex, additional requirements are placed on the support of decimal fixed point types (e.g. a minimum of 18 digits of precision). Wording Changes From Ada 83 28.c The syntax rules for fixed_point_constraint and fixed_ accuracy_definition are removed. The syntax rule for fixed_point_ definition is new. A syntax rule for delta_constraint is included in the Obsolescent features (to be compatible with Ada 83's fixed_point_ constraint). 3.5.10 Operations of Fixed Point Types Static Semantics 1 The following attributes are defined for every fixed point subtype S: 2 S'Small S'Small denotes the small of the type of S. The value of this attribute is of the type universal_real. {specifiable [of Small for fixed point types]} {Small clause} Small may be specified for nonderived fixed point types via an attribute_ definition_clause (see 13.3); the expression of such a clause shall be static. 3 S'Delta S'Delta denotes the delta of the fixed point subtype S. The value of this attribute is of the type universal_real. 3.a Reason: The delta is associated with the subtype as opposed to the type, because of the possibility of an (obsolescent) delta_ constraint. 4 S'Fore S'Fore yields the minimum number of characters needed before the decimal point for the decimal representation of any value of the subtype S, assuming that the representation does not include an exponent, but includes a one-character prefix that is either a minus sign or a space. (This minimum number does not include superfluous zeros or underlines, and is at least 2.) The value of this attribute is of the type universal_ integer. 5 S'Aft S'Aft yields the number of decimal digits needed after the decimal point to accommodate the delta of the subtype S, unless the delta of the subtype S is greater than 0.1, in which case the attribute yields the value one. [(S'Aft is the smallest positive integer N for which (10**N)*S'Delta is greater than or equal to one.)] The value of this attribute is of the type universal_integer. 6 The following additional attributes are defined for every decimal fixed point subtype S: 7 S'Digits S'Digits denotes the digits of the decimal fixed point subtype S, which corresponds to the number of decimal digits that are representable in objects of the subtype. The value of this attribute is of the type universal_integer. Its value is determined as follows: {digits (of a decimal fixed point subtype)} 8 For a first subtype or a subtype defined by a subtype_indication with a digits_constraint, the digits is the value of the expression given after the reserved word digits; 9 For a subtype defined by a subtype_indication without a digits_constraint, the digits of the subtype is the same as that of the subtype denoted by the subtype_mark in the subtype_ indication. 9.a Implementation Note: Although a decimal subtype can be both range-constrained and digits-constrained, the digits constraint is intended to control the Size attribute of the subtype. For decimal types, Size can be important because input/output of decimal types is so common. 10 The digits of a base subtype is the largest integer D such that the range -(10**D-1)*delta .. +(10**D-1)*delta is included in the base range of the type. 11 S'Scale S'Scale denotes the scale of the subtype S, defined as the value N such that S'Delta = 10.0**(-N). {scale (of a decimal fixed point subtype)} [The scale indicates the position of the point relative to the rightmost significant digits of values of subtype S.] The value of this attribute is of the type universal_integer. 11.a Ramification: S'Scale is negative if S'Delta is greater than one. By contrast, S'Aft is always positive. 12 S'Round S'Round denotes a function with the following specification: 13 function S'Round(X : universal_real) return S'Base 14 The function returns the value obtained by rounding X (away from 0, if X is midway between two values of the type of S). NOTES 15 (37) All subtypes of a fixed point type will have the same value for the Delta attribute, in the absence of delta_constraints (see J.3). 16 (38) S'Scale is not always the same as S'Aft for a decimal subtype; for example, if S'Delta = 1.0 then S'Aft is 1 while S'Scale is 0. 17 (39) {predefined operations [of a fixed point type]} The predefined operations of a fixed point type include the assignment operation, qualification, the membership tests, and explicit conversion to and from other numeric types. They also include the relational operators and the following predefined arithmetic operators: the binary and unary adding operators - and +, multiplying operators, and the unary operator abs. 18 (40) As for all types, objects of a fixed point type have Size and Address attributes (see 13.3). Other attributes of fixed point types are defined in A.5.4. 3.6 Array Types 1 {array} {array type} An array object is a composite object consisting of components which all have the same subtype. The name for a component of an array uses one or more index values belonging to specified discrete types. The value of an array object is a composite value consisting of the values of the components. Syntax 2 array_type_definition ::= unconstrained_array_definition | constrained_array_definition 3 unconstrained_array_definition ::= array(index_subtype_definition {, index_subtype_definition}) of componen\ t_definition 4 index_subtype_definition ::= subtype_mark range <> 5 constrained_array_definition ::= array (discrete_subtype_definition {, discrete_subtype_definition}) of c\ omponent_definition 6 discrete_subtype_definition ::= discrete_subtype_indication | range 7 component_definition ::= [aliased] subtype_indication Name Resolution Rules 8 {expected type [discrete_subtype_definition range]} For a discrete_ subtype_definition that is a range, the range shall resolve to be of some specific discrete type[; which discrete type shall be determined without using any context other than the bounds of the range itself (plus the preference for root_integer -- see 8.6).] Legality Rules 9 {index subtype} Each index_subtype_definition or discrete_subtype_ definition in an array_type_definition defines an index subtype; {index type} its type (the index type) shall be discrete. 9.a Discussion: {index (of an array)} An index is a discrete quantity used to select along a given dimension of an array. A component is selected by specifying corresponding values for each of the indices. 10 {component subtype} The subtype defined by the subtype_indication of a component_definition (the component subtype) shall be a definite subtype. 10.a Ramification: This applies to all uses of component_ definition, including in record_type_definitions and protected_ definitions. 11 Within the definition of a nonlimited composite type (or a limited composite type that later in its immediate scope becomes nonlimited -- see 7.3.1 and 7.5), if a component_definition contains the reserved word aliased and the type of the component is discriminated, then the nominal subtype of the component shall be constrained. 11.a Reason: If we allowed the subtype to be unconstrained, then the discriminants might change because of an assignment to the containing (nonlimited) object, thus causing a potential violation of an access subtype constraint of an access value designating the aliased component. 11.b Note that the rule elsewhere defining all aliased discriminated objects to be constrained does not help -- that rule prevents assignments to the component itself from doing any harm, but not assignments to the containing object. 11.c We allow this for components within limited types since assignment to the enclosing object is not a problem. Furthermore, it is important to be able to use a default expression for a discriminant in arrays of limited components, since that is the only way to give the components different values for their discriminants. For example: 11.d protected type Counter_Type(Initial_Value : Integer := 1) is procedure Get_Next(Next_Value : out Integer); -- Returns the next value on each call, bumping Count -- before returning. private Count : Integer := Initial_Value; end Counter_Type; protected body Counter_Type is ... 11.e function Next_Id(Counter : access Counter_Type) return Integer is Result : Integer; begin Counter.Get_Next(Result); return Result; end Next_Id; 11.f C : aliased Counter_Type; task type T(Who_Am_I : Integer := Next_Id(C'Access)); task body T is ... 11.g Task_Array : array(1..100) of aliased T; -- Array of task elements, each with its own unique ID. -- We specify "aliased" so we can use Task_Array(I)'Access. -- This is safe because Task_Array is of a limited type, -- so there is no way an assignment to it could change -- the discriminants of one of its components. 11.h Ramification: Note that this rule applies to array components and record components, but not to protected type components (since they are always limited). Static Semantics 12 {dimensionality (of an array)} {one-dimensional array} {multi- dimensional array} An array is characterized by the number of indices (the dimensionality of the array), the type and position of each index, the lower and upper bounds for each index, and the subtype of the components. The order of the indices is significant. 13 A one-dimensional array has a distinct component for each possible index value. A multidimensional array has a distinct component for each possible sequence of index values that can be formed by selecting one value for each index position (in the given order). The possible values for a given index are all the values between the lower and upper bounds, inclusive; {index range} this range of values is called the index range. {bounds (of an array)} The bounds of an array are the bounds of its index ranges. {length (of a dimension of an array)} The length of a dimension of an array is the number of values of the index range of the dimension (zero for a null range). {length (of a one-dimensional array)} The length of a one-dimensional array is the length of its only dimension. 14 An array_type_definition defines an array type and its first subtype. For each object of this array type, the number of indices, the type and position of each index, and the subtype of the components are as in the type definition[; the values of the lower and upper bounds for each index belong to the corresponding index subtype of its type, except for null arrays (see 3.6.1)]. 15 {constrained (subtype)} {unconstrained (subtype)} An unconstrained_ array_definition defines an array type with an unconstrained first subtype. Each index_subtype_definition defines the corresponding index subtype to be the subtype denoted by the subtype_mark.[{box [compound delimiter]} The compound delimiter <> (called a box) of an index_subtype_definition stands for an undefined range (different objects of the type need not have the same bounds).] 16 {constrained (subtype)} {unconstrained (subtype)} A constrained_array_ definition defines an array type with a constrained first subtype. Each discrete_subtype_definition defines the corresponding index subtype, as well as the corresponding index range for the constrained first subtype. {constraint [of a first array subtype]} The constraint of the first subtype consists of the bounds of the index ranges. 16.a Discussion: Although there is no namable unconstrained array subtype in this case, the predefined slicing and concatenation operations can operate on and yield values that do not necessarily belong to the first array subtype. This is also true for Ada 83. 17 The discrete subtype defined by a discrete_subtype_definition is either that defined by the subtype_indication, or a subtype determined by the range as follows: 18 If the type of the range resolves to root_integer, then the discrete_subtype_definition defines a subtype of the predefined type Integer with bounds given by a conversion to Integer of the bounds of the range; {implicit subtype conversion [bounds of a range]} 18.a Reason: This ensures that indexing over the discrete subtype can be performed with regular Integers, rather than only universal_integers. 18.b Discussion: We considered doing this by simply creating a ``preference'' for Integer when resolving the range. {Beaujolais effect [partial]} However, this can introduce Beaujolais effects when the simple_expressions involve calls on functions visible due to use clauses. 19 Otherwise, the discrete_subtype_definition defines a subtype of the type of the range, with the bounds given by the range. 20 {nominal subtype [of a component]} The component_definition of an array_ type_definition defines the nominal subtype of the components. If the reserved word aliased appears in the component_definition, then each component of the array is aliased (see 3.10). 20.a Ramification: In this case, the nominal subtype cannot be an unconstrained discriminated subtype. See 3.8. Dynamic Semantics 21 {elaboration [array_type_definition]} The elaboration of an array_type_ definition creates the array type and its first subtype, and consists of the elaboration of any discrete_subtype_definitions and the component_definition. 22 {elaboration [discrete_subtype_definition]} The elaboration of a discrete_subtype_definition creates the discrete subtype, and consists of the elaboration of the subtype_indication or the evaluation of the range. {elaboration [component_definition]} The elaboration of a component_ definition in an array_type_definition consists of the elaboration of the subtype_indication. The elaboration of any discrete_subtype_definitions and the elaboration of the component_definition are performed in an arbitrary order. NOTES 23 (41) All components of an array have the same subtype. In particular, for an array of components that are one-dimensional arrays, this means that all components have the same bounds and hence the same length. 24 (42) Each elaboration of an array_type_definition creates a distinct array type. A consequence of this is that each object whose object_ declaration contains an array_type_definition is of its own unique type. Examples 25 Examples of type declarations with unconstrained array definitions: 26 type Vector is array(Integer range <>) of Real; type Matrix is array(Integer range <>, Integer range <>) of Real; type Bit_Vector is array(Integer range <>) of Boolean; type Roman is array(Positive range <>) of Roman_Digit; -- see 3.5.2 27 Examples of type declarations with constrained array definitions: 28 type Table is array(1 .. 10) of Integer; type Schedule is array(Day) of Boolean; type Line is array(1 .. Max_Line_Size) of Character; 29 Examples of object declarations with array type definitions: 30 Grid : array(1 .. 80, 1 .. 100) of Boolean; Mix : array(Color range Red .. Green) of Boolean; Page : array(Positive range <>) of Line := -- an array of arrays (1 | 50 => Line'(1 | Line'Last => '+', others => '-'), -- see 4.3.3 2 .. 49 => Line'(1 | Line'Last => '|', others => ' ')); -- Page is constrained by its initial value to (1..50) Extensions to Ada 83 30.a {extensions to Ada 83} The syntax rule for component_ definition is modified to allow the reserved word aliased. 30.b The syntax rules for unconstrained_array_definition and constrained_array_definition are modified to use component_definition (instead of component_subtype_indication). The effect of this change is to allow the reserved word aliased before the component subtype_ indication. 30.c A range in a discrete_subtype_definition may use arbitrary universal expressions for each bound (e.g. -1 .. 3+5), rather than strictly "implicitly convertible" operands. The subtype defined will still be a subtype of Integer. Wording Changes From Ada 83 30.d We introduce a new syntactic category, discrete_subtype_ definition, as distinct from discrete_range. These two constructs have the same syntax, but their semantics are quite different (one defines a subtype, with a preference for Integer subtypes, while the other just selects a subrange of an existing subtype). We use this new syntactic category in for loops and entry families. 30.e The syntax for index_constraint and discrete_range have been moved to their own subclause, since they are no longer used here. 30.f The syntax rule for component_definition (formerly component_ subtype_definition) is moved here from RM83-3.7. 3.6.1 Index Constraints and Discrete Ranges 1 An index_constraint determines the range of possible values for every index of an array subtype, and thereby the corresponding array bounds. Syntax 2 index_constraint ::= (discrete_range {, discrete_range}) 3 discrete_range ::= discrete_subtype_indication | range Name Resolution Rules 4 {type of a discrete_range} The type of a discrete_range is the type of the subtype defined by the subtype_indication, or the type of the range. {expected type [index_constraint discrete_range]} For an index_constraint, each discrete_range shall resolve to be of the type of the corresponding index. 4.a Discussion: In Ada 9X, index_constraints only appear in a subtype_indication; they no longer appear in constrained_array_ definitions. Legality Rules 5 An index_constraint shall appear only in a subtype_indication whose subtype_mark denotes either an unconstrained array subtype, or an unconstrained access subtype whose designated subtype is an unconstrained array subtype; in either case, the index_constraint shall provide a discrete_ range for each index of the array type. Static Semantics 6 {bounds (of a discrete_range)} A discrete_range defines a range whose bounds are given by the range, or by the range of the subtype defined by the subtype_indication. Dynamic Semantics 7 {compatibility [index constraint with a subtype]} An index_constraint is compatible with an unconstrained array subtype if and only if the index range defined by each discrete_range is compatible (see 3.5) with the corresponding index subtype. {null array} If any of the discrete_ranges defines a null range, any array thus constrained is a null array, having no components. {satisfies [an index constraint]} An array value satisfies an index_ constraint if at each index position the array value and the index_constraint have the same index bounds. 7.a Ramification: There is no need to define compatibility with a constrained array subtype, because one is not allowed to constrain it again. 8 {elaboration [index_constraint]} The elaboration of an index_constraint consists of the evaluation of the discrete_range(s), in an arbitrary order. {evaluation [discrete_range]} The evaluation of a discrete_range consists of the elaboration of the subtype_indication or the evaluation of the range. NOTES 9 (43) The elaboration of a subtype_indication consisting of a subtype_ mark followed by an index_constraint checks the compatibility of the index_constraint with the subtype_mark (see 3.2.2). 10 (44) Even if an array value does not satisfy the index constraint of an array subtype, Constraint_Error is not raised on conversion to the array subtype, so long as the length of each dimension of the array value and the array subtype match. See 4.6. Examples 11 Examples of array declarations including an index constraint: 12 Board : Matrix(1 .. 8, 1 .. 8); -- see 3.6 Rectangle : Matrix(1 .. 20, 1 .. 30); Inverse : Matrix(1 .. N, 1 .. N); -- N need not be static 13 Filter : Bit_Vector(0 .. 31); 14 Example of array declaration with a constrained array subtype: 15 My_Schedule : Schedule; -- all arrays of type Schedule have the same boun\ ds 16 Example of record type with a component that is an array: 17 type Var_Line(Length : Natural) is record Image : String(1 .. Length); end record; 18 Null_Line : Var_Line(0); -- Null_Line.Image is a null array Extensions to Ada 83 18.a {extensions to Ada 83} We allow the declaration of a variable with a nominally unconstrained array subtype, so long as it has an initialization expression to determine its bounds. Wording Changes From Ada 83 18.b We have moved the syntax for index_constraint and discrete_ range here since they are no longer used in constrained_array_ definitions. We therefore also no longer have to describe the (special) semantics of index_constraints and discrete_ranges that appear in constrained_array_definitions. 18.c The rules given in RM83-3.6.1(5,7-10), which define the bounds of an array object, are redundant with rules given elsewhere, and so are not repeated here. RM83-3.6.1(6), which requires that the (nominal) subtype of an array variable be constrained, no longer applies, so long as the variable is explicitly initialized. 3.6.2 Operations of Array Types Legality Rules 1 [The argument N used in the attribute_designators for the N-th dimension of an array shall be a static expression of some integer type.] The value of N shall be positive (nonzero) and no greater than the dimensionality of the array. Static Semantics 2 The following attributes are defined for a prefix A that is of an array type [(after any implicit dereference)], or denotes a constrained array subtype: 2.a Ramification: These attributes are not defined if A is a subtype-mark for an access-to-array subtype. They are defined (by implicit dereference) for access-to-array values. 3 A'First A'First denotes the lower bound of the first index range; its type is the corresponding index type. 4 A'First(N) A'First(N) denotes the lower bound of the N-th index range; its type is the corresponding index type. 5 A'Last A'Last denotes the upper bound of the first index range; its type is the corresponding index type. 6 A'Last(N) A'Last(N) denotes the upper bound of the N-th index range; its type is the corresponding index type. 7 A'Range A'Range is equivalent to the range A'First .. A'Last, except that the prefix A is only evaluated once. 8 A'Range(N) A'Range(N) is equivalent to the range A'First(N) .. A'Last(N), except that the prefix A is only evaluated once. 9 A'Length A'Length denotes the number of values of the first index range (zero for a null range); its type is universal_integer. 10 A'Length(N) A'Length(N) denotes the number of values of the N-th index range (zero for a null range); its type is universal_integer. Implementation Advice 11 An implementation should normally represent multidimensional arrays in row-major order, consistent with the notation used for multidimensional array aggregates (see 4.3.3). However, if a pragma Convention(Fortran, ...) applies to a multidimensional array type, then column-major order should be used instead (see B.5, ``Interfacing with Fortran''). NOTES 12 (45) The attribute_references A'First and A'First(1) denote the same value. A similar relation exists for the attribute_references A'Last, A'Range, and A'Length. The following relation is satisfied (except for a null array) by the above attributes if the index type is an integer type: 13 A'Length(N) = A'Last(N) - A'First(N) + 1 14 (46) An array type is limited if its component type is limited (see 7.5). 15 (47) {predefined operations [of an array type]} The predefined operations of an array type include the membership tests, qualification, and explicit conversion. If the array type is not limited, they also include assignment and the predefined equality operators. For a one-dimensional array type, they include the predefined concatenation operators (if nonlimited) and, if the component type is discrete, the predefined relational operators; if the component type is boolean, the predefined logical operators are also included. 16 (48) A component of an array can be named with an indexed_component. A value of an array type can be specified with an array_aggregate, unless the array type is limited. For a one-dimensional array type, a slice of the array can be named; also, string literals are defined if the component type is a character type. Examples 17 Examples (using arrays declared in the examples of subclause 3.6.1): 18 -- Filter'First = 0 Filter'Last = 31 Filter'Length =\ 32 -- Rectangle'Last(1) = 20 Rectangle'Last(2) = 30 3.6.3 String Types Static Semantics 1 {string type} A one-dimensional array type whose component type is a character type is called a string type. 2 [There are two predefined string types, String and Wide_String, each indexed by values of the predefined subtype Positive; these are declared in the visible part of package Standard: 3 subtype Positive is Integer range 1 .. Integer'Last; 4 type String is array(Positive range <>) of Character; type Wide_String is array(Positive range <>) of Wide_Character; ] NOTES 5 (49) String literals (see 2.6 and 4.2) are defined for all string types. The concatenation operator & is predefined for string types, as for all nonlimited one-dimensional array types. The ordering operators <, <=, >, and >= are predefined for string types, as for all one-dimensional discrete array types; these ordering operators correspond to lexicographic order (see 4.5.2). Examples 6 Examples of string objects: 7 Stars : String(1 .. 120) := (1 .. 120 => '*' ); Question : constant String := "How many characters?"; -- Question'First = 1, Ques\ tion'Last = 20 -- Question'Length = 20 (th\ e number of characters) 8 Ask_Twice : String := Question & Question; -- constrained to (1..40) Ninety_Six : constant Roman := "XCVI"; -- see 3.5.2 and 3.6 Inconsistencies With Ada 83 8.a {inconsistencies with Ada 83} The declaration of Wide_String in Standard hides a use-visible declaration with the same defining_ identifier. In rare cases, this might result in an inconsistency between Ada 83 and Ada 9X. Incompatibilities With Ada 83 8.b {incompatibilities with Ada 83} Because both String and Wide_ String are always directly visible, an expression like 8.c "a" < "bc" 8.d is now ambiguous, whereas in Ada 83 both string literals could be resolved to type String. Extensions to Ada 83 8.e {extensions to Ada 83} The type Wide_String is new (though it was approved by ARG for Ada 83 compilers as well). Wording Changes From Ada 83 8.f We define the term string type as a natural analogy to the term character type. 3.7 Discriminants 1 [{discriminant} {type parameter: see discriminant} {parameter: see also discriminant} A composite type (other than an array type) can have discriminants, which parameterize the type. A known_discriminant_part specifies the discriminants of a composite type. A discriminant of an object is a component of the object, and is either of a discrete type or an access type. An unknown_discriminant_part in the declaration of a partial view of a type specifies that the discriminants of the type are unknown for the given view; all subtypes of such a partial view are indefinite subtypes.] 1.a Glossary entry: {Discriminant} A discriminant is a parameter of a composite type. It can control, for example, the bounds of a component of the type if that type is an array type. A discriminant of a task type can be used to pass data to a task of the type upon creation. 1.b Discussion: {unknown discriminants [partial]} {discriminants [unknown]} A type, and all of its subtypes, have unknown discriminants when the number or names of the discriminants, if any, are unknown at the point of the type declaration. A discriminant_ part of (<>) is used to indicate unknown discriminants. Syntax 2 discriminant_part ::= unknown_discriminant_part | known_discriminant_part 3 unknown_discriminant_part ::= (<>) 4 known_discriminant_part ::= (discriminant_specification {; discriminant_specification}) 5 discriminant_specification ::= defining_identifier_list : subtype_mark [:= default_expression] | defining_identifier_list : access_definition [:= default_expression] 6 default_expression ::= expression Name Resolution Rules 7 {expected type [discriminant default_expression]} The expected type for the default_expression of a discriminant_specification is that of the corresponding discriminant. Legality Rules 8 A known_discriminant_part is only permitted in a declaration for a composite type that is not an array type [(this includes generic formal types)]; {discriminated type} a type declared with a known_discriminant_part is called a discriminated type, as is a type that inherits (known) discriminants. 8.a Implementation Note: Discriminants on array types were considered, but were omitted to ease (existing) implementations. 8.b Discussion: Note that the above definition for ``discriminated type'' does not include types declared with an unknown_discriminant_ part. This seems consistent with Ada 83, where such types (in a generic formal part) would not be considered discriminated types. Furthermore, the full type for a type with unknown discriminants need not even be composite, much less have any discriminants. 9 The subtype of a discriminant may be defined by a subtype_mark, in which case the subtype_mark shall denote a discrete or access subtype, or it may be defined by an access_definition [(in which case the subtype_mark of the access_definition may denote any kind of subtype)]. {access discriminant} A discriminant that is defined by an access_definition is called an access discriminant and is of an anonymous general access-to-variable type whose designated subtype is denoted by the subtype_mark of the access_definition. 9.a Reason: In an earlier version of Ada 9X, we allowed access discriminants on nonlimited types, but this created unpleasant complexities. It turned out to be simpler and more uniform to allow discriminants of a named access type on any discriminated type, and keep access discriminants just for limited types. 9.b Note that discriminants of a named access type are not considered ``access discriminants.'' Similarly, ``access parameter'' only refers to a formal parameter defined by an access_definition. 10 A discriminant_specification for an access discriminant shall appear only in the declaration for a task or protected type, or for a type with the reserved word limited in its [(full)] definition or in that of one of its ancestors. In addition to the places where Legality Rules normally apply (see 12.3), this rule applies also in the private part of an instance of a generic unit. 10.a Discussion: This rule implies that a type can have an access discriminant if the type is limited, but not if the only reason it's limited is because of a limited component. Compare with the definition of limited type in 7.5. 10.b Ramification: It is a consequence of this rule that only a return-by-reference type can have an access discriminant (see 6.5). This is important to avoid dangling references to local variables. 10.c Reason: We also considered the following rules: 10.d If a type has an access discriminant, this automatically makes it limited, just like having a limited component automatically makes a type limited. This was rejected because it decreases program readability, and because it seemed error prone (two bugs in a previous version of the RM9X were attributable to this rule). 10.e A type with an access discriminant shall be limited. This is equivalent to the rule we actually chose, except that it allows a type to have an access discriminant if it is limited just because of a limited component. For example, any record containing a task would be allowed to have an access discriminant, whereas the actual rule requires ``limited record''. This rule was also rejected due to readability concerns, and because would interact badly with the rules for limited types that ``become nonlimited''. 11 Default_expressions shall be provided either for all or for none of the discriminants of a known_discriminant_part. No default_expressions are permitted in a known_discriminant_part in a declaration of a tagged type [or a generic formal type]. 11.a Reason: The all-or-none rule is related to the rule that a discriminant constraint shall specify values for all discriminants. One could imagine a different rule that allowed a constraint to specify only some of the discriminants, with the others provided by default. Having defaults for discriminants has a special significance -- it allows objects of the type to be unconstrained, with the discriminants alterable as part of assigning to the object. 11.b Defaults for discriminants of tagged types are disallowed so that every object of a tagged type is constrained, either by an explicit constraint, or by its initial discriminant values. This substantially simplifies the semantic rules and the implementation of inherited dispatching operations. For generic formal types, the restriction simplifies the type matching rules. If one simply wants a "default" value for the discriminants, a constrained subtype can be declared for future use. 12 For a type defined by a derived_type_definition, if a known_ discriminant_part is provided in its declaration, then: 13 The parent subtype shall be constrained; 14 If the parent type is not a tagged type, then each discriminant of the derived type shall be used in the constraint defining the parent subtype; 14.a Implementation Note: This ensures that the new discriminant can share storage with an existing discriminant. 15 If a discriminant is used in the constraint defining the parent subtype, the subtype of the discriminant shall be statically compatible (see 4.9.1) with the subtype of the corresponding parent discriminant. 15.a Reason: This ensures that on conversion (or extension via an extension aggregate) to a distantly related type, if the discriminants satisfy the target type's requirements they satisfy all the intermediate types' requirements as well. 15.b Ramification: There is no requirement that the new discriminant have the same (or any) default_expression as the parent's discriminant. 16 The type of the default_expression, if any, for an access discriminant shall be convertible to the anonymous access type of the discriminant (see 4.6). {convertible [required]} 16.a Ramification: This requires convertibility of the designated subtypes. Static Semantics 17 A discriminant_specification declares a discriminant; the subtype_mark denotes its subtype unless it is an access discriminant, in which case the discriminant's subtype is the anonymous access-to-variable subtype defined by the access_definition. 18 [For a type defined by a derived_type_definition, each discriminant of the parent type is either inherited, constrained to equal some new discriminant of the derived type, or constrained to the value of an expression.] {corresponding discriminants} When inherited or constrained to equal some new discriminant, the parent discriminant and the discriminant of the derived type are said to correspond. Two discriminants also correspond if there is some common discriminant to which they both correspond. A discriminant corresponds to itself as well. {specified discriminant} If a discriminant of a parent type is constrained to a specific value by a derived_type_definition, then that discriminant is said to be specified by that derived_type_definition. 18.a Ramification: The correspondence relationship is transitive, symmetric, and reflexive. That is, if A corresponds to B, and B corresponds to C, then A, B, and C each corresponds to A, B, and C in all combinations. 19 {depend on a discriminant (for a constraint or component_definition)} A constraint that appears within the definition of a discriminated type depends on a discriminant of the type if it names the discriminant as a bound or discriminant value. A component_definition depends on a discriminant if its constraint depends on the discriminant, or on a discriminant that corresponds to it. 19.a Ramification: A constraint in a task_body is not considered to depend on a discriminant of the task type, even if it names it. It is only the constraints in the type definition itself that are considered dependents. Similarly for protected types. 20 {depend on a discriminant (for a component)} A component depends on a discriminant if: 21 Its component_definition depends on the discriminant; or 21.a Ramification: A component does not depend on a discriminant just because its default_expression refers to the discriminant. 22 It is declared in a variant_part that is governed by the discriminant; or 23 It is a component inherited as part of a derived_type_definition, and the constraint of the parent_subtype_indication depends on the discriminant; or 23.a Reason: When the parent subtype depends on a discriminant, the parent part of the derived type is treated like a discriminant-dependent component. 23.b Ramification: Because of this rule, we don't really need to worry about ``corresponding'' discriminants, since all the inherited components will be discriminant-dependent if there is a new known_discriminant_part whose discriminants are used to constrain the old discriminants. 24 It is a subcomponent of a component that depends on the discriminant. 24.a Reason: The concept of discriminant-dependent (sub)components is primarily used in various rules that disallow renaming or 'Access, or specify that certain discriminant-changing assignments are erroneous. The goal is to allow implementations to move around or change the size of discriminant-dependent subcomponents upon a discriminant-changing assignment to an enclosing object. The above definition specifies that all subcomponents of a discriminant- dependent component or parent part are themselves discriminant- dependent, even though their presence or size does not in fact depend on a discriminant. This is because it is likely that they will move in a discriminant-changing assignment if they are a component of one of several discriminant-dependent parts of the same record. 25 Each value of a discriminated type includes a value for each component of the type that does not depend on a discriminant[; this includes the discriminants themselves]. The values of discriminants determine which other component values are present in the value of the discriminated type. 25.a To be honest: Which values are present might depend on discriminants of some ancestor type that are constrained in an intervening derived_type_definition. That's why we say "values of discriminants" instead of "values of the discriminants" -- a subtle point. 26 {known discriminants} {discriminants (known)} {constrained (subtype)} {unconstrained (subtype)} A type declared with a known_discriminant_part is said to have known discriminants; its first subtype is unconstrained. {unknown discriminants} {discriminants (unknown)} A type declared with an unknown_discriminant_part is said to have unknown discriminants. A type declared without a discriminant_part has no discriminants, unless it is a derived type; if derived, such a type has the same sort of discriminants (known, unknown, or none) as its parent (or ancestor) type. A tagged class-wide type also has unknown discriminants. {class-wide type} {indefinite subtype} [Any subtype of a type with unknown discriminants is an unconstrained and indefinite subtype (see 3.2 and 3.3).] 26.a Discussion: An unknown_discriminant_part ``(<>)'' is only permitted in the declaration of a (generic or nongeneric) private type, private extension, or formal derived type. Hence, only such types, descendants thereof, and class-wide types can have unknown discriminants. An unknown_discriminant_part is used to indicate that the corresponding actual or full type might have discriminants without defaults, or be an unconstrained array subtype. Tagged class-wide types are also considered to have unknown discriminants because discriminants can be added by type extensions, so the total number of discriminants of any given value of a tagged class-wide type is not known at compile time. 26.b A subtype with unknown discriminants is indefinite, and hence an object of such a subtype needs explicit initialization. If the subtype is limited, no (stand-alone) objects can be declared since initialization is not permitted (though formal parameters are permitted, and objects of the actual/full type will generally be declarable). A limited private type with unknown discriminants is ``extremely'' limited; such a type is useful for keeping complete control over object creation within the package declaring the type. 26.c A partial view of a type might have unknown discriminants, while the full view of the same type might have known, unknown, or no discriminants, Dynamic Semantics 27 An access_definition is elaborated when the value of a corresponding access discriminant is defined, either by evaluation of its default_ expression or by elaboration of a discriminant_constraint. [The elaboration of an access_definition creates the anonymous access type. When the expression defining the access discriminant is evaluated, it is converted to this anonymous access type (see 4.6).] {implicit subtype conversion [access discriminant]} 27.a Ramification: This conversion raises Constraint_Error if the initial value is null, or, for an object created by an allocator of an access type T, if the initial value is an access parameter that designates a view whose accessibility level is deeper than that of T. NOTES 28 (50) If a discriminated type has default_expressions for its discriminants, then unconstrained variables of the type are permitted, and the values of the discriminants can be changed by an assignment to such a variable. If defaults are not provided for the discriminants, then all variables of the type are constrained, either by explicit constraint or by their initial value; the values of the discriminants of such a variable cannot be changed after initialization. 28.a Discussion: This connection between discriminant defaults and unconstrained variables can be a source of confusion. For Ada 9X, we considered various ways to break the connection between defaults and unconstrainedness, but ultimately gave up for lack of a sufficiently simple and intuitive alternative. 28.b {mutable} An unconstrained discriminated subtype with defaults is called a mutable subtype, and a variable of such a subtype is called a mutable variable, because the discriminants of such a variable can change. There are no mutable arrays (that is, the bounds of an array object can never change), because there is no way in the language to define default values for the bounds. Similarly, there are no mutable class-wide subtypes, because there is no way to define the default tag, and defaults for discriminants are not allowed in the tagged case. Mutable tags would also require a way for the maximum possible size of such a class-wide subtype to be known. (In some implementations, all mutable variables are allocated with the maximum possible size. This approach is appropriate for real-time applications where implicit use of the heap is inappropriate.) 29 (51) The default_expression for a discriminant of a type is evaluated when an object of an unconstrained subtype of the type is created. 30 (52) Assignment to a discriminant of an object (after its initialization) is not allowed, since the name of a discriminant is a constant; neither assignment_statements nor assignments inherent in passing as an in out or out parameter are allowed. Note however that the value of a discriminant can be changed by assigning to the enclosing object, presuming it is an unconstrained variable. 30.a Discussion: An unknown_discriminant_part is permitted only in the declaration of a private type (including generic formal private), private extension, or generic formal derived type. These are the things that will have a corresponding completion or generic actual, which will either define the discriminants, or say there are none. The (<>) indicates that the actual/full subtype might be an indefinite subtype. An unknown_discriminant_part is not permitted in a normal untagged derived type declaration, because there is no separate full type declaration for such a type. Note that (<>) allows unconstrained array bounds; those are somewhat like undefaulted discriminants. 30.b For a derived type, either the discriminants are inherited as is, or completely respecified in a new discriminant_part. In this latter case, each discriminant of the parent type shall be constrained, either to a specific value, or to equal one of the new discriminants. Constraining a parent type's discriminant to equal one of the new discriminants is like a renaming of the discriminant, except that the subtype of the new discriminant can be more restrictive than that of the parent's one. In any case, the new discriminant can share storage with the parent's discriminant. 31 (53) A discriminant that is of a named access type is not called an access discriminant; that term is used only for discriminants defined by an access_definition. Examples 32 Examples of discriminated types: 33 type Buffer(Size : Buffer_Size := 100) is -- see 3.5.4 record Pos : Buffer_Size := 0; Value : String(1 .. Size); end record; 34 type Matrix_Rec(Rows, Columns : Integer) is record Mat : Matrix(1 .. Rows, 1 .. Columns); -- see 3.6 end record; 35 type Square(Side : Integer) is new Matrix_Rec(Rows => Side, Columns => Side\ ); 36 type Double_Square(Number : Integer) is record Left : Square(Number); Right : Square(Number); end record; 37 type Item(Number : Positive) is record Content : Integer; -- no component depends on the discriminant end record; Extensions to Ada 83 37.a {extensions to Ada 83} The syntax for a discriminant_ specification is modified to allow an access discriminant, with a type specified by an access_definition (see 3.10). 37.b Discriminants are allowed on all composite types other than array types. 37.c Discriminants may be of an access type. Wording Changes From Ada 83 37.d Discriminant_parts are not elaborated, though an access_ definition is elaborated when the discriminant is initialized. 3.7.1 Discriminant Constraints 1 A discriminant_constraint specifies the values of the discriminants for a given discriminated type. Language Design Principles 1.a The rules in this clause are intentionally parallel to those given in Record Aggregates. Syntax 2 discriminant_constraint ::= (discriminant_association {, discriminant_association}) 3 discriminant_association ::= [discriminant_selector_name {| discriminant_selector_name} =>] expression 4 {named discriminant association} A discriminant_association is said to be named if it has one or more discriminant_selector_names; {positional discriminant association} it is otherwise said to be positional. In a discriminant_constraint, any positional associations shall precede any named associations. Name Resolution Rules 5 Each selector_name of a named discriminant_association shall resolve to denote a discriminant of the subtype being constrained; {associated discriminants (of a named discriminant_association)} the discriminants so named are the associated discriminants of the named association. {associated discriminants (of a positional discriminant_association)} For a positional association, the associated discriminant is the one whose discriminant_ specification occurred in the corresponding position in the known_ discriminant_part that defined the discriminants of the subtype being constrained. 6 {expected type [discriminant_association expression]} The expected type for the expression in a discriminant_association is that of the associated discriminant(s). Legality Rules 7 A discriminant_constraint is only allowed in a subtype_indication whose subtype_mark denotes either an unconstrained discriminated subtype, or an unconstrained access subtype whose designated subtype is an unconstrained discriminated subtype. 8 A named discriminant_association with more than one selector_name is allowed only if the named discriminants are all of the same type. A discriminant_constraint shall provide exactly one value for each discriminant of the subtype being constrained. 9 The expression associated with an access discriminant shall be of a type convertible to the anonymous access type. {convertible [required]} 9.a Ramification: This implies both convertibility of designated types, and static accessibility. This implies that if an object of type T with an access discriminant is created by an allocator for an access type A, then it requires that the type of the expression associated with the access discriminant have an accessibility level that is not statically deeper than that of A. This is to avoid dangling references. Dynamic Semantics 10 {compatibility [discriminant constraint with a subtype]} A discriminant_ constraint is compatible with an unconstrained discriminated subtype if each discriminant value belongs to the subtype of the corresponding discriminant. 10.a Ramification: The "dependent compatibility check" has been eliminated in Ada 9X. Any checking on subcomponents is performed when (and if) an object is created. 10.b Discussion: There is no need to define compatibility with a constrained discriminated subtype, because one is not allowed to constrain it again. 11 {satisfies [a discriminant constraint]} A composite value satisfies a discriminant constraint if and only if each discriminant of the composite value has the value imposed by the discriminant constraint. 12 {elaboration [discriminant_constraint]} For the elaboration of a discriminant_constraint, the expressions in the discriminant_associations are evaluated in an arbitrary order and converted to the type of the associated discriminant (which might raise Constraint_Error -- see 4.6); the expression of a named association is evaluated (and converted) once for each associated discriminant. {implicit subtype conversion [discriminant values]} The result of each evaluation and conversion is the value imposed by the constraint for the associated discriminant. 12.a Reason: We convert to the type, not the subtype, so that the definition of compatibility of discriminant constraints is not vacuous. NOTES 13 (54) The rules of the language ensure that a discriminant of an object always has a value, either from explicit or implicit initialization. 13.a Discussion: Although it is illegal to constrain a class-wide tagged subtype, it is possible to have a partially constrained class-wide subtype: If the subtype S is defined by T(A => B), then S'Class is partially constrained in the sense that objects of subtype S'Class have to have discriminants corresponding to A equal to B, but there can be other discriminants defined in extensions that are not constrained to any particular value. Examples 14 Examples (using types declared above in clause 3.7): 15 Large : Buffer(200); -- constrained, always 200 characters -- (explicit discriminant value) Message : Buffer; -- unconstrained, initially 100 characters -- (default discriminant value) Basis : Square(5); -- constrained, always 5 by 5 Illegal : Square; -- illegal, a Square has to be constrained Inconsistencies With Ada 83 15.a {inconsistencies with Ada 83} Dependent compatibility checks are no longer performed on subtype declaration. Instead they are deferred until object creation (see 3.3.1). This is upward compatible for a program that does not raise Constraint_Error. Wording Changes From Ada 83 15.b Everything in RM83-3.7.2(7-12), which specifies the initial values for discriminants, is now redundant with 3.3.1, 6.4.1, 8.5.1, and 12.4. Therefore, we don't repeat it here. Since the material is largely intuitive, but nevertheless complicated to state formally, it doesn't seem worth putting it in a "NOTE." 3.7.2 Operations of Discriminated Types 1 [If a discriminated type has default_expressions for its discriminants, then unconstrained variables of the type are permitted, and the discriminants of such a variable can be changed by assignment to the variable. For a formal parameter of such a type, an attribute is provided to determine whether the corresponding actual parameter is constrained or unconstrained.] Static Semantics 2 For a prefix A that is of a discriminated type [(after any implicit dereference)], the following attribute is defined: 3 A'Constrained Yields the value True if A denotes a constant, a value, or a constrained variable, and False otherwise. 3.a Implementation Note: This attribute is primarily used on parameters, to determine whether the discriminants can be changed as part of an assignment. The Constrained attribute is statically True for in parameters. For in out and out parameters of a discriminated type, the value of this attribute needs to be passed as an implicit parameter, in general. However, if the type does not have defaults for its discriminants, the attribute is statically True, so no implicit parameter is needed. Parameters of a limited type with defaulted discriminants need this implicit parameter, unless there are no nonlimited views, because they might be passed to a subprogram whose body has visibility on a nonlimited view of the type, and hence might be able to assign to the object and change its discriminants. Erroneous Execution 4 {erroneous execution} The execution of a construct is erroneous if the construct has a constituent that is a name denoting a subcomponent that depends on discriminants, and the value of any of these discriminants is changed by this execution between evaluating the name and the last use (within this execution) of the subcomponent denoted by the name. 4.a Ramification: This rule applies to assignment_statements, calls (except when the discriminant-dependent subcomponent is an in parameter passed by copy), indexed_components, and slices. Ada 83 only covered the first two cases. AI-00585 pointed out the situation with the last two cases. The cases of object_renaming_declarations and generic formal in out objects are handled differently, by disallowing the situation at compile time. Extensions to Ada 83 4.b {extensions to Ada 83} For consistency with other attributes, we are allowing the prefix of Constrained to be a value as well as an object of a discriminated type, and also an implicit dereference. These extensions are not important capabilities, but there seems no reason to make this attribute different from other similar attributes. We are curious what most Ada 83 compilers do with F(1).X'Constrained. 4.c We now handle in a general way the cases of erroneousness identified by AI-585, where the prefix of an indexed_component or slice is discriminant-dependent, and the evaluation of the index or discrete range changes the value of a discriminant. Wording Changes From Ada 83 4.d We have moved all discussion of erroneous use of names that denote discriminant-dependent subcomponents to this subclause. In Ada 83, it used to appear separately under assignment_statements and subprogram calls. 3.8 Record Types 1 {record} {record type} A record object is a composite object consisting of named components. The value of a record object is a composite value consisting of the values of the components. {structure: see record type} Syntax 2 record_type_definition ::= [[abstract] tagged] [limited] record_definition 3 record_definition ::= record component_list end record | null record 4 component_list ::= component_item {component_item} | {component_item} variant_part | null; 5 component_item ::= component_declaration | representation_clause 6 component_declaration ::= defining_identifier_list : component_definition [:= default_expression]; Name Resolution Rules 7 {expected type [component_declaration default_expression]} The expected type for the default_expression, if any, in a component_declaration is the type of the component. Legality Rules 8 A default_expression is not permitted if the component is of a limited type. 9 {components [of a record type]} Each component_declaration declares a component of the record type. Besides components declared by component_ declarations, the components of a record type include any components declared by discriminant_specifications of the record type declaration. [The identifiers of all components of a record type shall be distinct.] 9.a Proof: The identifiers of all components of a record type have to be distinct because they are all declared immediately within the same declarative region. See Section 8. 10 Within a type_declaration, a name that denotes a component, protected subprogram, or entry of the type is allowed only in the following cases: 11 A name that denotes any component, protected subprogram, or entry is allowed within a representation item that occurs within the declaration of the composite type. 12 A name that denotes a noninherited discriminant is allowed within the declaration of the type, but not within the discriminant_ part. If the discriminant is used to define the constraint of a component, the bounds of an entry family, or the constraint of the parent subtype in a derived_type_definition then its name shall appear alone as a direct_name (not as part of a larger expression or expanded name). 12.a Reason: This restriction simplifies implementation, and allows the outer discriminant and the inner discriminant or bound to possibly share storage. 12.b Ramification: Other rules prevent such a discriminant from being an inherited one. A discriminant shall not be used to define the constraint of a scalar component. 12.c Reason: This restriction is inherited from Ada 83. The restriction is not really necessary from a language design point of view, but we did not remove it, in order to avoid unnecessary changes to existing compilers. 12.d Discussion: Note that a discriminant can be used to define the constraint for a component that is of an access-to-composite type. 12.e Reason: The above rules, and a similar one in 6.1 for formal parameters, are intended to allow initializations of components or parameters to occur in an arbitrary order -- whatever order is most efficient, since one default_expression cannot depend on the value of another one. It also prevent circularities. 12.f Ramification: Inherited discriminants are not allowed to be denoted, except within representation items. However, the discriminant_selector_name of the parent subtype_indication is allowed to denote a discriminant of the parent. 13 If the name of the current instance of a type (see 8.6) is used to define the constraint of a component, then it shall appear as a direct_name that is the prefix of an attribute_reference whose result is of an access type, and the attribute_reference shall appear alone. 13.a Reason: This rule allows T'Access or T'Unchecked_Access, but disallows, for example, a range constraint (1..T'Size). Allowing things like (1..T'Size) would mean that a per-object constraint could affect the size of the object, which would be bad. Static Semantics 14 {nominal subtype [of a record component]} The component_definition of a component_declaration defines the (nominal) subtype of the component. If the reserved word aliased appears in the component_definition, then the component is aliased (see 3.10). 14.a Ramification: In this case, the nominal subtype cannot be an unconstrained discriminated subtype. See 3.6. 15 {null record} If the component_list of a record type is defined by the reserved word null and there are no discriminants, then the record type has no components and all records of the type are null records. A record_ definition of null record is equivalent to record null; end record. 15.a Ramification: This short-hand is available both for declaring a record type and a record extension -- see 3.9.1. Dynamic Semantics 16 {elaboration [record_type_definition]} The elaboration of a record_type_ definition creates the record type and its first subtype, and consists of the elaboration of the record_definition. {elaboration [record_definition]} The elaboration of a record_definition consists of the elaboration of its component_list, if any. 17 {elaboration [component_list]} The elaboration of a component_list consists of the elaboration of the component_items and variant_part, if any, in the order in which they appear. {elaboration [component_declaration]} The elaboration of a component_declaration consists of the elaboration of the component_definition. 17.a Discussion: If the defining_identifier_list has more than one defining_identifier, we presume here that the transformation explained in 3.3.1 has already taken place. Alternatively, we could say that the component_definition is elaborated once for each defining_identifier in the list. 18 {per-object expression} {per-object constraint} {entry index subtype} Within the definition of a composite type, if a component_definition or discrete_subtype_definition (see 9.5.2) includes a name that denotes a discriminant of the type, or that is an attribute_reference whose prefix denotes the current instance of the type, the expression containing the name is called a per-object expression, and the constraint being defined is called a per-object constraint. 18.a Discussion: The evaluation of other expressions that appear in component_definitions and discrete_subtype_definitions is per- formed when the type definition is elaborated. The evaluation of expressions that appear as default_expressions is postponed until an object is created. Expressions in representation items that appear within a composite type definition are evaluated according to the rules of the particular representation item. {elaboration [component_definition]} For the elaboration of a component_ definition of a component_declaration, if the constraint of the subtype_ indication is not a per-object constraint, then the subtype_indication is elaborated. On the other hand, if the constraint is a per-object constraint, then the elaboration consists of the evaluation of any included expression that is not part of a per-object expression. NOTES 19 (55) A component_declaration with several identifiers is equivalent to a sequence of single component_declarations, as explained in 3.3.1. 20 (56) The default_expression of a record component is only evaluated upon the creation of a default-initialized object of the record type (presuming the object has the component, if it is in a variant_part -- see 3.3.1). 21 (57) The subtype defined by a component_definition (see 3.6) has to be a definite subtype. 22 (58) If a record type does not have a variant_part, then the same components are present in all values of the type. 23 (59) A record type is limited if it has the reserved word limited in its definition, or if any of its components are limited (see 7.5). 24 (60) {predefined operations [of a record type]} The predefined operations of a record type include membership tests, qualification, and explicit conversion. If the record type is nonlimited, they also include assignment and the predefined equality operators. 25 (61) A component of a record can be named with a selected_component. A value of a record can be specified with a record_aggregate, unless the record type is limited. Examples 26 Examples of record type declarations: 27 type Date is record Day : Integer range 1 .. 31; Month : Month_Name; Year : Integer range 0 .. 4000; end record; 28 type Complex is record Re : Real := 0.0; Im : Real := 0.0; end record; 29 Examples of record variables: 30 Tomorrow, Yesterday : Date; A, B, C : Complex; 31 -- both components of A, B, and C are implicitly initialized to zero Extensions to Ada 83 31.a {extensions to Ada 83} The syntax rule for component_ declaration is modified to use component_definition (instead of component_subtype_definition). The effect of this change is to allow the reserved word aliased before the component_subtype_definition. 31.b A short-hand is provided for defining a null record type (and a null record extension), as these will be more common for abstract root types (and derived types without additional components). 31.c The syntax rule for record_type_definition is modified to allow the reserved words tagged and limited. Tagging is new. Limitedness is now orthogonal to privateness. In Ada 83 the syntax implied that limited private was sort of more private than private. However, limitedness really has nothing to do with privateness; limitedness simply indicates the lack of assignment capabilities, and makes perfect sense for nonprivate types such as record types. Wording Changes From Ada 83 31.d The syntax rules now allow representation_clauses to appear in a record_definition. This is not a language extension, because Legality Rules prevent all language-defined representation clauses from appearing there. However, an implementation-defined attribute_ definition_clause could appear there. The reason for this change is to allow the rules for representation_clauses and representation pragmas to be as similar as possible. 3.8.1 Variant Parts and Discrete Choices 1 A record type with a variant_part specifies alternative lists of components. Each variant defines the components for the value or values of the discriminant covered by its discrete_choice_list. 1.a Discussion: {cover a value [distributed]} Discrete_choice_ lists and discrete_choices are said to cover values as defined below; which discrete_choice_list covers a value determines which of various alternatives is chosen. These are used in variant_parts, array_ aggregates, and case_statements. Language Design Principles 1.b The definition of ``cover'' in this subclause and the rules about discrete choices are designed so that they are also appropriate for array aggregates and case statements. 1.c The rules of this subclause intentionally parallel those for case statements. Syntax 2 variant_part ::= case discriminant_direct_name is variant {variant} end case; 3 variant ::= when discrete_choice_list => component_list 4 discrete_choice_list ::= discrete_choice {| discrete_choice} 5 discrete_choice ::= expression | discrete_range | others Name Resolution Rules 6 {discriminant (of a variant_part)} The discriminant_direct_name shall resolve to denote a discriminant (called the discriminant of the variant_ part) specified in the known_discriminant_part of the full_type_declaration that contains the variant_part. {expected type [variant_part discrete_ choice]} The expected type for each discrete_choice in a variant is the type of the discriminant of the variant_part. 6.a Ramification: A full_type_declaration with a variant_part has to have a (new) known_discriminant_part; the discriminant of the variant_part cannot be an inherited discriminant. Legality Rules 7 The discriminant of the variant_part shall be of a discrete type. 7.a Ramification: It shall not be of an access type, named or anonymous. 8 The expressions and discrete_ranges given as discrete_choices in a variant_part shall be static. The discrete_choice others shall appear alone in a discrete_choice_list, and such a discrete_choice_list, if it appears, shall be the last one in the enclosing construct. 9 {cover a value [by a discrete_choice]} A discrete_choice is defined to cover a value in the following cases: 10 A discrete_choice that is an expression covers a value if the value equals the value of the expression converted to the expected type. 11 A discrete_choice that is a discrete_range covers all values (possibly none) that belong to the range. 12 The discrete_choice others covers all values of its expected type that are not covered by previous discrete_choice_lists of the same construct. 12.a Ramification: For case_statements, this includes values outside the range of the static subtype (if any) to be covered by the choices. It even includes values outside the base range of the case expression's type, since values of numeric types (and undefined values of any scalar type?) can be outside their base range. 13 {cover a value [by a discrete_choice_list]} A discrete_choice_list covers a value if one of its discrete_choices covers the value. 14 The possible values of the discriminant of a variant_part shall be covered as follows: 15 If the discriminant is of a static constrained scalar subtype, then each non-others discrete_choice shall cover only values in that subtype, and each value of that subtype shall be covered by some discrete_choice [(either explicitly or by others)]; 16 If the type of the discriminant is a descendant of a generic formal scalar type then the variant_part shall have an others discrete_choice; 16.a Reason: The base range is not known statically in this case. 17 Otherwise, each value of the base range of the type of the discriminant shall be covered [(either explicitly or by others)]. 18 Two distinct discrete_choices of a variant_part shall not cover the same value. Static Semantics 19 If the component_list of a variant is specified by null, the variant has no components. 20 {govern a variant_part} {govern a variant} The discriminant of a variant_part is said to govern the variant_part and its variants. In addition, the discriminant of a derived type governs a variant_part and its variants if it corresponds (see 3.7) to the discriminant of the variant_part. Dynamic Semantics 21 A record value contains the values of the components of a particular variant only if the value of the discriminant governing the variant is covered by the discrete_choice_list of the variant. This rule applies in turn to any further variant that is, itself, included in the component_list of the given variant. 22 {elaboration [variant_part]} The elaboration of a variant_part consists of the elaboration of the component_list of each variant in the order in which they appear. Examples 23 Example of record type with a variant part: 24 type Device is (Printer, Disk, Drum); type State is (Open, Closed); 25 type Peripheral(Unit : Device := Disk) is record Status : State; case Unit is when Printer => Line_Count : Integer range 1 .. Page_Size; when others => Cylinder : Cylinder_Index; Track : Track_Number; end case; end record; 26 Examples of record subtypes: 27 subtype Drum_Unit is Peripheral(Drum); subtype Disk_Unit is Peripheral(Disk); 28 Examples of constrained record variables: 29 Writer : Peripheral(Unit => Printer); Archive : Disk_Unit; Extensions to Ada 83 29.a {extensions to Ada 83} In Ada 83, the discriminant of a variant_part is not allowed to be of a generic formal type. This restriction is removed in Ada 9X; an others discrete_choice is required in this case. Wording Changes From Ada 83 29.b The syntactic category choice is removed. The syntax rules for variant, array_aggregate, and case_statement now use discrete_ choice_list or discrete_choice instead. The syntax rule for record_ aggregate now defines its own syntax for named associations. 29.c We have added the term Discrete Choice to the title since this is where they are talked about. This is analogous to the name of the subclause "Index Constraints and Discrete Ranges" in the clause on Array Types. 29.d The rule requiring that the discriminant denote a discriminant of the type being defined seems to have been left implicit in RM83. 3.9 Tagged Types and Type Extensions 1 [{dispatching operation [partial]} {polymorphism} {dynamic binding: see dispatching operation} {generic unit: see also dispatching operation} {variant: see also tagged type} Tagged types and type extensions support object-oriented programming, based on inheritance with extension and run-time polymorphism via dispatching operations. {object-oriented programming (OOP): see tagged types and type extensions} {OOP (object-oriented programming): see tagged types and type extensions} {inheritance: see also tagged types and type extension}] Language Design Principles 1.a The intended implementation model is for a tag to be represented as a pointer to a statically allocated and link-time initialized type descriptor. The type descriptor contains the address of the code for each primitive operation of the type. It probably also contains other information, such as might make membership tests convenient and efficient. 1.b The primitive operations of a tagged type are known at its first freezing point; the type descriptor is laid out at that point. It contains linker symbols for each primitive operation; the linker fills in the actual addresses. 1.c Other implementation models are possible. 1.d The rules ensure that ``dangling dispatching'' is impossible; that is, when a dispatching call is made, there is always a body to execute. This is different from some other object-oriented languages, such as Smalltalk, where it is possible to get a run-time error from a missing method. 1.e Dispatching calls should be efficient, and should have a bounded worst-case execution time. This is important in a language intended for real-time applications. In the intended implementation model, a dispatching call involves calling indirect through the appropriate slot in the dispatch table. No complicated "method lookup" is involved. 1.f The programmer should have the choice at each call site of a dispatching operation whether to do a dispatching call or a statically determined call (i.e. whether the body executed should be determined at run time or at compile time). 1.g The same body should be executed for a call where the tag is statically determined to be T'Tag as for a dispatching call where the tag is found at run time to be T'Tag. This allows one to test a given tagged type with statically determined calls, with some confidence that run-time dispatching will produce the same behavior. 1.h All views of a type should share the same type descriptor and the same tag. 1.i The visibility rules determine what is legal at compile time; they have nothing to do with what bodies can be executed at run time. Thus, it is possible to dispatch to a subprogram whose declaration is not visible at the call site. In fact, this is one of the primary facts that gives object-oriented programming its power. The subprogram that ends up being dispatched to by a given call might even be designed long after the call site has been coded and compiled. 1.j Given that Ada has overloading, determining whether a given subprogram overrides another is based both on the names and the type profiles of the operations. 1.k When a type extension is declared, if there is any place within its immediate scope where a certain subprogram of the parent is visible, then a matching subprogram should override. If there is no such place, then a matching subprogram should be totally unrelated, and occupy a different slot in the type descriptor. This is important to preserve the privacy of private parts; when an operation declared in a private part is inherited, the inherited version can be overridden only in that private part, in the package body, and in any children of the package. 1.l If an implementation shares code for instances of generic bodies, it should be allowed to share type descriptors of tagged types declared in the generic body, so long as they are not extensions of types declared in the specification of the generic unit. Static Semantics 2 {tagged type} A record type or private type that has the reserved word tagged in its declaration is called a tagged type. [When deriving from a tagged type, additional components may be defined. As for any derived type, additional primitive subprograms may be defined, and inherited primitive subprograms may be overridden.] {type extension} {extension (of a type)} The derived type is called an extension of the ancestor type, or simply a type extension. {extension (of a record type)} {private extension} {extension (of a private type)} Every type extension is also a tagged type, and is either a record extension or a private extension of some other tagged type. A record extension is defined by a derived_type_definition with a record_extension_ part. A private extension, which is a partial view of a record extension, can be declared in the visible part of a package (see 7.3) or in a generic formal part (see 12.5.1). 2.a Glossary entry: {Tagged type} The objects of a tagged type have a run-time type tag, which indicates the specific type with which the object was originally created. An operand of a class-wide tagged type can be used in a dispatching call; the tag indicates which subprogram body to invoke. Nondispatching calls, in which the subprogram body to invoke is determined at compile time, are also allowed. Tagged types may be extended with additional components. 2.b Ramification: If a tagged type is declared other than in a package_specification, it is impossible to add new primitive subprograms for that type, although it can inherit primitive subprograms, and those can be overridden. If the user incorrectly thinks a certain subprogram is primitive when it is not, and tries to call it with a dispatching call, an error message will be given at the call site. 2.c Note that the accessibility rules imply that a tagged type declared in a library package_specification cannot be extended in a nested subprogram or task body. 3 {tag of an object} An object of a tagged type has an associated (run-time) tag that identifies the specific tagged type used to create the object originally. [The tag of an operand of a class-wide tagged type T'Class controls which subprogram body is to be executed when a primitive subprogram of type T is applied to the operand (see 3.9.2); {dispatching} using a tag to control which body to execute is called dispatching.] {type tag: see tag} {run-time type: see tag} {type: see also tag} {class: see also tag} 4 The tag of a specific tagged type identifies the full_type_declaration of the type. If a declaration for a tagged type occurs within a generic_ package_declaration, then the corresponding type declarations in distinct instances of the generic package are associated with distinct tags. For a tagged type that is local to a generic package body, the language does not specify whether repeated instantiations of the generic body result in distinct tags. 4.a Reason: This eases generic code sharing. 4.b Implementation Note: The language does not specify whether repeated elaborations of the same full_type_declaration correspond to distinct tags. In most cases, we expect that all elaborations will correspond to the same tag, since the tag will frequently be the address (or index) of a statically allocated type descriptor. However, with shared generics, the type descriptor might have to be allocated on a per-instance basis, which in some implementation models implies per-elaboration of the instantiation. 5 The following language-defined library package exists: 6 package Ada.Tags is type Tag is private; 7 function Expanded_Name(T : Tag) return String; function External_Tag(T : Tag) return String; function Internal_Tag(External : String) return Tag; 8 Tag_Error : exception; 9 private ... -- not specified by the language end Ada.Tags; 9.a Reason: Tag is a nonlimited, definite subtype, because it needs the equality operators, so that tag checking makes sense. Also, equality, assignment, and object declaration are all useful capabilities for this subtype. 9.b For an object X and a type T, ``X'Tag = T'Tag'' is not needed, because a membership test can be used. However, comparing the tags of two objects cannot be done via membership. This is one reason to allow equality for type Tag. 10 The function Expanded_Name returns the full expanded name of the first subtype of the specific type identified by the tag, in upper case, starting with a root library unit. The result is implementation defined if the type is declared within an unnamed block_statement. 10.a To be honest: This name, as well as each prefix of it, does not denote a renaming_declaration. 10.b Implementation defined: The result of Tags.Expanded_Name for types declared within an unnamed block_statement. 11 The function External_Tag returns a string to be used in an external representation for the given tag. The call External_Tag(S'Tag) is equivalent to the attribute_reference S'External_Tag (see 13.3). 11.a Reason: It might seem redundant to provide both the function External_Tag and the attribute External_Tag. The function is needed because the attribute can't be applied to values of type Tag. The attribute is needed so that it can be specifiable via an attribute_ definition_clause. 12 The function Internal_Tag returns the tag that corresponds to the given external tag, or raises Tag_Error if the given string is not the external tag for any specific type of the partition. 13 For every subtype S of a tagged type T (specific or class-wide), the following attributes are defined: 14 S'Class S'Class denotes a subtype of the class-wide type (called T'Class in this International Standard) for the class rooted at T (or if S already denotes a class-wide subtype, then S'Class is the same as S). 15 {unconstrained (subtype)} {constrained (subtype)} S'Class is unconstrained. However, if S is constrained, then the values of S'Class are only those that when converted to the type T belong to S. 15.a Ramification: This attribute is defined for both specific and class-wide subtypes. The definition is such that S'Class'Class is the same as S'Class. 15.b Note that if S is constrained, S'Class is only partially constrained, since there might be additional discriminants added in descendants of T which are not constrained. 15.c Reason: The Class attribute is not defined for untagged subtypes (except for incomplete types and private types whose full view is tagged -- see 3.10.1 and 7.3.1) so as to preclude implicit conversion in the absence of run-time type information. If it were defined for untagged subtypes, it would correspond to the concept of universal types provided for the predefined numeric classes. 16 S'Tag S'Tag denotes the tag of the type T (or if T is class-wide, the tag of the root type of the corresponding class). The value of this attribute is of type Tag. 16.a Reason: S'Class'Tag equals S'Tag, to avoid generic contract model problems when S'Class is the actual type associated with a generic formal derived type. 17 Given a prefix X that is of a class-wide tagged type [(after any implicit dereference)], the following attribute is defined: 18 X'Tag X'Tag denotes the tag of X. The value of this attribute is of type Tag. 18.a Reason: X'Tag is not defined if X is of a specific type. This is primarily to avoid confusion that might result about whether the Tag attribute should reflect the tag of the type of X, or the tag of X. No such confusion is possible if X is of a class-wide type. Dynamic Semantics 19 The tag associated with an object of a tagged type is determined as follows: 20 {tag of an object [stand-alone object, component, or aggregate]} The tag of a stand-alone object, a component, or an aggregate of a specific tagged type T identifies T. 20.a Discussion: The tag of a formal parameter of type T is not necessarily the tag of T, if, for example, the actual was a type conversion. 21 {tag of an object [object created by an allocator]} The tag of an object created by an allocator for an access type with a specific designated tagged type T, identifies T. 21.a Discussion: The tag of an object designated by a value of such an access type might not be T, if, for example, the access value is the result of a type conversion. 22 {tag of an object [class-wide object]} The tag of an object of a class-wide tagged type is that of its initialization expression. 22.a Ramification: The tag of an object (even a class-wide one) cannot be changed after it is initialized, since a ``class-wide'' assignment_statement raises Constraint_Error if the tags don't match, and a ``specific'' assignment_statement does not affect the tag. 23 {tag of an object [returned by a function]} The tag of the result returned by a function whose result type is a specific tagged type T identifies T. 23.a Implementation Note: This requires a run-time check for limited tagged types, since they are returned "by-reference." For a nonlimited type, a new anonymous object with the appropriate tag is created as part of the function return, and then assigned the value of the return expression. See 6.5, ``Return Statements''. 24 {tag of an object [returned by a function]} The tag of the result returned by a function with a class-wide result type is that of the return expression. 25 {tag of an object [preserved by type conversion and parameter passing]} The tag is preserved by type conversion and by parameter passing. The tag of a value is the tag of the associated object (see 6.2). Implementation Permissions 26 The implementation of the functions in Ada.Tags may raise Tag_Error if no specific type corresponding to the tag passed as a parameter exists in the partition at the time the function is called. 26.a Reason: In most implementations, repeated elaborations of the same type_declaration will all produce the same tag. In such an implementation, Tag_Error will be raised in cases where the internal or external tag was passed from a different partition. However, some implementations might create a new tag value at run time for each elaboration of a type_declaration. In that case, Tag_Error could also be raised if the created type no longer exists because the subprogram containing it has returned, for example. We don't require the latter behavior; hence the word ``may'' in this rule. NOTES 27 (62) A type declared with the reserved word tagged should normally be declared in a package_specification, so that new primitive subprograms can be declared for it. 28 (63) Once an object has been created, its tag never changes. 29 (64) Class-wide types are defined to have unknown discriminants (see 3.7). This means that objects of a class-wide type have to be explicitly initialized (whether created by an object_declaration or an allocator), and that aggregates have to be explicitly qualified with a specific type when their expected type is class-wide. 30 (65) If S denotes an untagged private type whose full type is tagged, then S'Class is also allowed before the full type definition, but only in the private part of the package in which the type is declared (see 7.3.1). Similarly, the Class attribute is defined for incomplete types whose full type is tagged, but only within the library unit in which the incomplete type is declared (see 3.10.1). Examples 31 Examples of tagged record types: 32 type Point is tagged record X, Y : Real := 0.0; end record; 33 type Expression is tagged null record; -- Components will be added by each extension Extensions to Ada 83 33.a {extensions to Ada 83} Tagged types are a new concept. 3.9.1 Type Extensions 1 [{type extension} {extension (of a type)} {record extension} {extension (of a record type)} {private extension} {extension (of a private type)} Every type extension is a tagged type, and is either a record extension or a private extension of some other tagged type.] Language Design Principles 1.a We want to make sure that we can extend a generic formal tagged type, without knowing its discriminants. 1.b We don't want to allow components in an extension aggregate to depend on discriminants inherited from the parent value, since such dependence requires staticness in aggregates, at least for variants. Syntax 2 record_extension_part ::= with record_definition Legality Rules 3 The parent type of a record extension shall not be a class-wide type. If the parent type is nonlimited, then each of the components of the record_ extension_part shall be nonlimited. {accessibility rule [record extension]} The accessibility level (see 3.10.2) of a record extension shall not be statically deeper than that of its parent type. {generic contract issue [partial]} In addition to the places where Legality Rules normally apply (see 12.3), these rules apply also in the private part of an instance of a generic unit. 3.a Reason: If the parent is a limited formal type, then the actual might be nonlimited. 3.b A similar accessibility rule is not needed for private extensions, because in a package, the rule will apply to the full_ type_declaration, and for a generic formal private extension, the actual is all that matters. 4 A type extension shall not be declared in a generic body if the parent type is declared outside that body. 4.a Reason: This paragraph ensures that a dispatching call will never attempt to execute an inaccessible subprogram body. 4.b The part about generic bodies is necessary in order to preserve the contract model. 4.c Since a generic unit can be instantiated at a deeper accessibility level than the generic unit, it is necessary to prevent type extensions whose parent is declared outside the generic unit. The same is true if the parent is a formal of the generic unit. If the parent is declared in the generic_declaration (but is not a formal), we don't run afoul of the accessibility rules, because we know that the instance declaration and body will be at the same accessibility level. However, we still have a problem in that case, because it might have an unknown number of abstract subprograms, as in the following example: 4.d package P is type T is tagged null record; function F return T; -- Inherited versions will be abstract. end P; 4.e generic type TT is tagged private; package Gp is type NT is abstract new TT with null record; procedure Q(X : in NT) is abstract; end Gp; 4.f package body Gp is type NT2 is new NT with null record; -- Illegal! procedure Q(X : in NT2) is begin null; end Q; -- Is this legal or not? Can't decide because -- we don't know whether TT had any functions that go abstract -- on extension. end Gp; 4.g package I is new Gp(TT => P.T); 4.h I.NT is an abstract type with two abstract subprograms: F (inherited as abstract) and Q (explicitly declared as abstract). But the generic body doesn't know about F, so we don't know that it needs to be overridden to make a nonabstract extension of NT. Furthermore, a formal tagged limited private type can be extended with limited components, but the actual might not be limited, which would allow assignment of limited types, which is bad. Hence, we have to disallow this case as well. 4.i If TT were declared as abstract, then we could have the same problem with abstract procedures. 4.j We considered disallowing all tagged types in a generic body, for simplicity. We decided not to go that far, in order to avoid unnecessary restrictions. 4.k {accessibility rule [not part of generic contract]} We also considered trying make the accessibility level part of the contract; i.e. invent some way of saying (in the generic_declaration) ``all instances of this generic unit will have the same accessibility level as the generic_declaration.'' Unfortunately, that doesn't solve the part of the problem having to do with abstract types. 4.l Children of generic units obviate the need for extension in the body somewhat. Dynamic Semantics 5 {elaboration [record_extension_part]} The elaboration of a record_ extension_part consists of the elaboration of the record_definition. NOTES 6 (66) The term ``type extension'' refers to a type as a whole. The term ``extension part'' refers to the piece of text that defines the additional components (if any) the type extension has relative to its specified ancestor type. 6.a Discussion: We considered other terminology, such as ``extended type.'' However, the terms ``private extended type'' and ``record extended type'' did not convey the proper meaning. Hence, we have chosen to uniformly use the term ``extension'' as the type resulting from extending a type, with ``private extension'' being one produced by privately extending the type, and ``record extension'' being one produced by extending the type with an additional record-like set of components. Note also that the term ``type extension'' refers to the result of extending a type in the language Oberon as well (though there the term ``extended type'' is also used, interchangeably, perhaps because Oberon doesn't have the concept of a ``private extension''). 7 (67) The accessibility rules imply that a tagged type declared in a library package_specification can be extended only at library level or as a generic formal. When the extension is declared immediately within a package_body, primitive subprograms are inherited and are overridable, but new primitive subprograms cannot be added. 8 (68) A name that denotes a component (including a discriminant) of the parent type is not allowed within the record_extension_part. Similarly, a name that denotes a component defined within the record_extension_part is not allowed within the record_extension_part. It is permissible to use a name that denotes a discriminant of the record extension, providing there is a new known_discriminant_part in the enclosing type declaration. (The full rule is given in 3.8.) 8.a Reason: The restriction against depending on discriminants of the parent is to simplify the definition of extension aggregates. The restriction against using parent components in other ways is methodological; it presumably simplifies implementation as well. 9 (69) Each visible component of a record extension has to have a unique name, whether the component is (visibly) inherited from the parent type or declared in the record_extension_part (see 8.3). Examples 10 Examples of record extensions (of types defined above in 3.9): 11 type Painted_Point is new Point with record Paint : Color := White; end record; -- Components X and Y are inherited 12 Origin : constant Painted_Point := (X | Y => 0.0, Paint => Black); 13 type Literal is new Expression with record -- a leaf in an Expression tree Value : Real; end record; 14 type Expr_Ptr is access all Expression'Class; -- see 3.10 15 type Binary_Operation is new Expression with record -- an internal node in an Expression tree Left, Right : Expr_Ptr; end record; 16 type Addition is new Binary_Operation with null record; type Subtraction is new Binary_Operation with null record; -- No additional components needed for these extensions 17 Tree : Expr_Ptr := -- A tree representation of ``5.0 + (13.0-7.0)'' new Addition'( Left => new Literal'(Value => 5.0), Right => new Subtraction'( Left => new Literal'(Value => 13.0), Right => new Literal'(Value => 7.0))); Extensions to Ada 83 17.a {extensions to Ada 83} Type extension is a new concept. 3.9.2 Dispatching Operations of Tagged Types 1 {dispatching operation [distributed]} {dispatching call (on a dispatching operation)} {nondispatching call (on a dispatching operation)} {statically determined tag} {dynamically determined tag} {polymorphism} {run-time polymorphism} {controlling tag (for a call on a dispatching operation)} The primitive subprograms of a tagged type are called dispatching operations. [A dispatching operation can be called using a statically determined controlling tag, in which case the body to be executed is determined at compile time. Alternatively, the controlling tag can be dynamically determined, in which case the call dispatches to a body that is determined at run time;] such a call is termed a dispatching call. [As explained below, the properties of the operands and the context of a particular call on a dispatching operation determine how the controlling tag is determined, and hence whether or not the call is a dispatching call. Run-time polymorphism is achieved when a dispatching operation is called by a dispatching call.] {object-oriented programming (OOP): see dispatching operations of tagged types} {OOP (object-oriented programming): see dispatching operations of tagged types} {message: see dispatching call} {method: see dispatching subprogram} {virtual function: see dispatching subprogram} Language Design Principles 1.a The controlling tag determination rules are analogous to the overload resolution rules, except they deal with run-time type identification (tags) rather than compile-time type resolution. As with overload resolution, controlling tag determination may depend on operands or result context. Static Semantics 2 {call on a dispatching operation} {dispatching operation} A call on a dispatching operation is a call whose name or prefix denotes the declaration of a primitive subprogram of a tagged type, that is, a dispatching operation. 2.a Ramification: This definition implies that a call through the dereference of an access-to-subprogram value is never considered a call on a dispatching operation. Note also that if the prefix denotes a renaming_declaration, the place where the renaming occurs determines whether it is primitive; the thing being renamed is irrelevant. {controlling operand} A controlling operand in a call on a dispatching operation of a tagged type T is one whose corresponding formal parameter is of type T or is of an anonymous access type with designated type T; {controlling formal parameter} the corresponding formal parameter is called a controlling formal parameter. If the controlling formal parameter is an access parameter, the controlling operand is the object designated by the actual parameter, rather than the actual parameter itself. {controlling result} If the call is to a (primitive) function with result type T, then the call has a controlling result -- the context of the call can control the dispatching. 3 A name or expression of a tagged type is either statically tagged, dynamically tagged, or tag indeterminate, according to whether, when used as a controlling operand, the tag that controls dispatching is determined statically by the operand's (specific) type, dynamically by its tag at run time, or from context. A qualified_expression or parenthesized expression is statically, dynamically, or indeterminately tagged according to its operand. For other kinds of names and expressions, this is determined as follows: 4 {statically tagged} The name or expression is statically tagged if it is of a specific tagged type and, if it is a call with a controlling result, it has at least one statically tagged controlling operand; 4.a Discussion: It is illegal to have both statically tagged and dynamically tagged controlling operands in the same call -- see below. 5 {dynamically tagged} The name or expression is dynamically tagged if it is of a class-wide type, or it is a call with a controlling result and at least one dynamically tagged controlling operand; 6 {tag indeterminate} The name or expression is tag indeterminate if it is a call with a controlling result, all of whose controlling operands (if any) are tag indeterminate. 7 [A type_conversion is statically or dynamically tagged according to whether the type determined by the subtype_mark is specific or class-wide, respectively.] For a controlling operand that is designated by an actual parameter, the controlling operand is statically or dynamically tagged according to whether the designated type of the actual parameter is specific or class-wide, respectively. 7.a Ramification: A type_conversion is never tag indeterminate, even if its operand is. A designated object is never tag indeterminate. Legality Rules 8 A call on a dispatching operation shall not have both dynamically tagged and statically tagged controlling operands. 8.a Reason: This restriction is intended to minimize confusion between whether the dynamically tagged operands are implicitly converted to, or tag checked against the specific type of the statically tagged operand(s). 9 If the expected type for an expression or name is some specific tagged type, then the expression or name shall not be dynamically tagged unless it is a controlling operand in a call on a dispatching operation. Similarly, if the expected type for an expression is an anonymous access-to-specific tagged type, then the expression shall not be of an access-to-class-wide type unless it designates a controlling operand in a call on a dispatching operation. 9.a Reason: This prevents implicit "truncation" of a dynamically-tagged value to the specific type of the target object/formal. An explicit conversion is required to request this truncation. 9.b Ramification: This rule applies to all expressions or names with a specific expected type, not just those that are actual parameters to a dispatching call. This rule does not apply to a membership test whose expression is class-wide, since any type that covers the tested type is explicitly allowed. See 4.5.2. 10 In the declaration of a dispatching operation of a tagged type, everywhere a subtype of the tagged type appears as a subtype of the profile (see 6.1), it shall statically match the first subtype of the tagged type. {statically matching [required]} If the dispatching operation overrides an inherited subprogram, it shall be subtype conformant with the inherited subprogram. {subtype conformance (required)} A dispatching operation shall not be of convention Intrinsic. If a dispatching operation overrides the predefined equals operator, then it shall be of convention Ada [(either explicitly or by default -- see 6.3.1)]. 10.a Reason: These rules ensure that constraint checks can be performed by the caller in a dispatching call, and parameter passing conventions match up properly. A special rule on aggregates prevents values of a tagged type from being created that are outside of its first subtype. 11 The default_expression for a controlling formal parameter of a dispatching operation shall be tag indeterminate. A controlling formal parameter that is an access parameter shall not have a default_expression. 11.a Reason: The first part ensures that the default_expression always produces the "correct" tag when called with or without dispatching, or when inherited by a descendant. If it were statically tagged, the default would be useless for a dispatching call; if it were dynamically tagged, the default would be useless for a nondispatching call. 11.b The second part is consistent with the first part, since designated objects are never tag-indeterminate. 12 A given subprogram shall not be a dispatching operation of two or more distinct tagged types. 12.a Reason: This restriction minimizes confusion since multiple dispatching is not provided. The normal solution is to replace all but one of the tagged types with their class-wide types. 13 The explicit declaration of a primitive subprogram of a tagged type shall occur before the type is frozen (see 13.14). [For example, new dispatching operations cannot be added after objects or values of the type exist, nor after deriving a record extension from it, nor after a body.] 13.a Reason: This rule is needed because (1) we don't want people dispatching to things that haven't been declared yet, and (2) we want to allow tagged type descriptors to be static (allocated statically, and initialized to link-time-known symbols). Suppose T2 inherits primitive P from T1, and then overrides P. Suppose P is called before the declaration of the overriding P. What should it dispatch to? If the answer is the new P, we've violated the first principle above. If the answer is the old P, we've violated the second principle. (A call to the new one necessarily raises Program_Error, but that's beside the point.) 13.b Note that a call upon a dispatching operation of type T will freeze T. 13.c We considered applying this rule to all derived types, for uniformity. However, that would be upward incompatible, so we rejected the idea. As in Ada 83, for an untagged type, the above call upon P will call the old P (which is arguably confusing). 13.d Implementation Note: Because of this rule, the type descriptor can be created (presumably containing linker symbols pointing at the not-yet-compiled bodies) at the first freezing point of the type. It also prevents, for a tagged type declared in a package_specification, overriding in the body or by a child subprogram. 13.e Ramification: A consequence is that for a derived_type_ declaration in a declarative_part, only the first primitive subprogram can be declared by a subprogram_body. Dynamic Semantics 14 {execution [call on a dispatching operation]} {controlling tag value} For the execution of a call on a dispatching operation of a type T, the controlling tag value determines which subprogram body is executed. The controlling tag value is defined as follows: 15 {statically determined tag [partial]} If one or more controlling operands are statically tagged, then the controlling tag value is statically determined to be the tag of T. 16 If one or more controlling operands are dynamically tagged, then the controlling tag value is not statically determined, but is rather determined by the tags of the controlling operands. {Tag_ Check [partial]} {check, language-defined (Tag_Check)} If there is more than one dynamically tagged controlling operand, a check is made that they all have the same tag. {Constraint_Error (raised by failure of run-time check)} If this check fails, Constraint_Error is raised unless the call is a function_call whose name denotes the declaration of an equality operator (predefined or user defined) that returns Boolean, in which case the result of the call is defined to indicate inequality, and no subprogram_body is executed. This check is performed prior to evaluating any tag-indeterminate controlling operands. 16.a Reason: Tag mismatch is considered an error (except for "=" and "/=") since the corresponding primitive subprograms in each specific type expect all controlling operands to be of the same type. For tag mismatch with an equality operator, rather than raising an exception, "=" returns False and "/=" returns True. No equality operator is actually invoked, since there is no common tag value to control the dispatch. Equality is a special case to be consistent with the existing Ada 83 principle that equality comparisons, even between objects with different constraints, never raise Constraint_Error. 17 If all of the controlling operands are tag-indeterminate, then: 18 If the call has a controlling result and is itself a (possibly parenthesized or qualified) controlling operand of an enclosing call on a dispatching operation of type T, then its controlling tag value is determined by the controlling tag value of this enclosing call; 19 {statically determined tag [partial]} Otherwise, the controlling tag value is statically determined to be the tag of type T. 19.a Ramification: This includes the cases of a tag-indeterminate procedure call, and a tag-indeterminate function_call that is used to initialize a class-wide formal parameter or class-wide object. 20 For the execution of a call on a dispatching operation, the body executed is the one for the corresponding primitive subprogram of the specific type identified by the controlling tag value. The body for an explicitly declared dispatching operation is the corresponding explicit body for the subprogram. The body for an implicitly declared dispatching operation that is overridden is the body for the overriding subprogram, [even if the overriding occurs in a private part.] The body for an inherited dispatching operation that is not overridden is the body of the corresponding subprogram of the parent or ancestor type. 20.a To be honest: In the unusual case in which a dispatching subprogram is explicitly declared (overridden) by a body (with no preceding subprogram_declaration), the body for that dispatching subprogram is that body; that is, the ``corresponding explicit body'' in the above rule is the body itself. 20.b Reason: The wording of the above rule is intended to ensure that the same body is executed for a given tag, whether that tag is determined statically or dynamically. For a type declared in a package, it doesn't matter whether a given subprogram is overridden in the visible part or the private part, and it doesn't matter whether the call is inside or outside the package. For example: 20.c package P1 is type T1 is tagged null record; procedure Op_A(Arg : in T1); procedure Op_B(Arg : in T1); end P1; 20.d with P1; use P1; package P2 is type T2 is new T1 with null record; procedure Op_A(Param : in T2); private procedure Op_B(Param : in T2); end P2; 20.e with P1; with P2; procedure Main is X : T2; Y : T1'Class := X; begin P2.Op_A(Param => X); -- Nondispatching call. P1.Op_A(Arg => Y); -- Dispatching call. P2.Op_B(Arg => X); -- Nondispatching call. P1.Op_B(Arg => Y); -- Dispatching call. end Main; 20.f The two calls to Op_A both execute the body of Op_A that has to occur in the body of package P2. Similarly, the two calls to Op_B both execute the body of Op_B that has to occur in the body of package P2, even though Op_B is overridden in the private part of P2. Note, however, that the formal parameter names are different for P2.Op_A versus P2.Op_B. The overriding declaration for P2.Op_B is not visible in Main, so the name in the call actually denotes the implicit declaration of Op_B inherited from T1. 20.g If a call occurs in the program text before an overriding, which can happen only if the call is part of a default expression, the overriding will still take effect for that call. 20.h Implementation Note: Even when a tag is not statically determined, a compiler might still be able to figure it out and thereby avoid the overhead of run-time dispatching. NOTES 21 (70) The body to be executed for a call on a dispatching operation is determined by the tag; it does not matter whether that tag is determined statically or dynamically, and it does not matter whether the subprogram's declaration is visible at the place of the call. 22 (71) This subclause covers calls on primitive subprograms of a tagged type. Rules for tagged type membership tests are described in 4.5.2. Controlling tag determination for an assignment_statement is described in 5.2. 23 (72) A dispatching call can dispatch to a body whose declaration is not visible at the place of the call. 24 (73) A call through an access-to-subprogram value is never a dispatching call, even if the access value designates a dispatching operation. Similarly a call whose prefix denotes a subprogram_renaming_declaration cannot be a dispatching call unless the renaming itself is the declaration of a primitive subprogram. Extensions to Ada 83 24.a {extensions to Ada 83} The concept of dispatching operations is new. 3.9.3 Abstract Types and Subprograms 1 [{abstract type} {abstract data type (ADT): see also abstract type} {ADT (abstract data type): see also abstract type} {concrete type: see nonabstract type} An abstract type is a tagged type intended for use as a parent type for type extensions, but which is not allowed to have objects of its own. {abstract subprogram} {concrete subprogram: see nonabstract subprogram} An abstract subprogram is a subprogram that has no body, but is intended to be overridden at some point when inherited. Because objects of an abstract type cannot be created, a dispatching call to an abstract subprogram always dispatches to some overriding body.] Language Design Principles 1.a An abstract subprogram has no body, so the rules in this clause are designed to ensure (at compile time) that the body will never be invoked. We do so primarily by disallowing the creation of values of the abstract type. Therefore, since type conversion and parameter passing don't change the tag, we know we will never get a class-wide value with a tag identifying an abstract type. This means that we only have to disallow nondispatching calls on abstract subprograms (dispatching calls will never reach them). Legality Rules 2 {abstract type} {type (abstract)} An abstract type is a specific type that has the reserved word abstract in its declaration. Only a tagged type is allowed to be declared abstract. 2.a Ramification: Untagged types are never abstract, even though they can have primitive abstract subprograms. Such subprograms cannot be called, unless they also happen to be dispatching operations of some tagged type, and then only via a dispatching call. 2.b Class-wide types are never abstract. If T is abstract, then it is illegal to declare a stand-alone object of type T, but it is OK to declare a stand-alone object of type T'Class; the latter will get a tag from its initial value, and this tag will necessarily be different from T'Tag. 3 {abstract subprogram} {subprogram (abstract)} A subprogram declared by an abstract_subprogram_declaration (see 6.1) is an abstract subprogram. If it is a primitive subprogram of a tagged type, then the tagged type shall be abstract. 3.a Ramification: Note that for a private type, this applies to both views. The following is illegal: 3.b package P is type T is abstract tagged private; function Foo (X : T) return Boolean is abstract; -- Illegal! private type T is tagged null record; -- Illegal! X : T; Y : Boolean := Foo (T'Class (X)); end P; 3.c The full view of T is not abstract, but has an abstract operation Foo, which is illegal. The two lines marked "-- Illegal!" are illegal when taken together. 3.d Reason: We considered disallowing untagged types from having abstract primitive subprograms. However, we rejected that plan, because it introduced some silly anomalies, and because such subprograms are harmless (if not terribly useful). For example: 3.e package P is type Field_Size is range 0..100; type T is abstract tagged null record; procedure Print(X : in T; F : in Field_Size := 0) is abstract; . . . package Q is type My_Field_Size is new Field_Size; -- implicit declaration of Print(X : T; F : My_Field_Size := 0) \ is abstract; end Q; 3.f It seemed silly to make the derivative of My_Field_Size illegal, just because there was an implicitly declared abstract subprogram that was not primitive on some tagged type. Other rules could be formulated to solve this problem, but the current ones seem like the simplest. 4 For a derived type, if the parent or ancestor type has an abstract primitive subprogram, or a primitive function with a controlling result, then: 5 If the derived type is abstract or untagged, the inherited subprogram is abstract. 5.a Ramification: Note that it is possible to override a concrete subprogram with an abstract one. 6 Otherwise, the subprogram shall be overridden with a nonabstract subprogram; [for a type declared in the visible part of a package, the overriding may be either in the visible or the private part.] However, if the type is a generic formal type, the subprogram need not be overridden for the formal type itself; [a nonabstract version will necessarily be provided by the actual type.] 6.a Reason: A function that returns the parent type becomes abstract for an abstract type extension (if not overridden) because conversion from a parent type to a type extension is not defined, and function return semantics is defined in terms of conversion. (Note that parameters of mode in out or out do not have this problem, because the tag of the actual is not changed.) 6.b Note that the overriding required above can be in the private part, which allows the following: 6.c package Pack1 is type Ancestor is abstract ...; procedure Do_Something(X : in Ancestor) is abstract; end Pack1; 6.d with Pack1; use Pack1; package Pack2 is type T1 is new Ancestor with record ...; -- A concrete type. procedure Do_Something(X : in T1); -- Have to override. end Pack2; 6.e with Pack1; use Pack1; with Pack2; use Pack2; package Pack3 is type T2 is new Ancestor with private; -- A concrete type. private type T2 is new T1 with -- Parent different from ancestor. record ... end record; -- Here, we inherit Pack2.Do_Something. end Pack3; 6.f T2 inherits an abstract Do_Something, but T is not abstract, so Do_Something has to be overridden. However, it is OK to override it in the private part. In this case, we override it by inheriting a concrete version from a different type. Nondispatching calls to Pack3.Do_Something are allowed both inside and outside package Pack3. 7 A call on an abstract subprogram shall be a dispatching call; [nondispatching calls to an abstract subprogram are not allowed.] 7.a Ramification: If an abstract subprogram is not a dispatching operation of some tagged type, then it cannot be called at all. 8 The type of an aggregate, or of an object created by an object_ declaration or an allocator, or a generic formal object of mode in, shall not be abstract. The type of the target of an assignment operation (see 5.2) shall not be abstract. The type of a component shall not be abstract. If the result type of a function is abstract, then the function shall be abstract. 8.a Reason: This ensures that values of an abstract type cannot be created, which ensures that a dispatching call to an abstract subprogram will not try to execute the nonexistent body. 8.b Generic formal objects of mode in are like constants; therefore they should be forbidden for abstract types. Generic formal objects of mode in out are like renamings; therefore, abstract types are OK for them, though probably not terribly useful. 9 If a partial view is not abstract, the corresponding full view shall not be abstract. If a generic formal type is abstract, then for each primitive subprogram of the formal that is not abstract, the corresponding primitive subprogram of the actual shall not be abstract. 9.a Discussion: By contrast, we allow the actual type to be nonabstract even if the formal type is declared abstract. Hence, the most general formal tagged type possible is "type T(<>) is abstract tagged limited private;". 9.b For an abstract private extension declared in the visible part of a package, it is only possible for the full type to be nonabstract if the private extension has no abstract dispatching operations. 10 For an abstract type declared in a visible part, an abstract primitive subprogram shall not be declared in the private part, unless it is overriding an abstract subprogram implicitly declared in the visible part. For a tagged type declared in a visible part, a primitive function with a controlling result shall not be declared in the private part, unless it is overriding a function implicitly declared in the visible part. 10.a Reason: The ``visible part'' could be that of a package or a generic package. This rule is needed because a non-abstract type extension declared outside the package would not know about any abstract primitive subprograms or primitive functions with controlling results declared in the private part, and wouldn't know that they need to be overridden with non-abstract subprograms. The rule applies to a tagged record type or record extension declared in a visible part, just as to a tagged private type or private extension. The rule applies to explicitly and implicitly declared abstract subprograms: 10.b package Pack is type T is abstract new T1 with private; private type T is abstract new T2 with record ... end record; ... end Pack; 10.c The above example would be illegal if T1 has a non-abstract primitive procedure P, but T2 overrides P with an abstract one; the private part should override P with a non-abstract version. On the other hand, if the P were abstract for both T1 and T2, the example would be legal as is. 11 A generic actual subprogram shall not be an abstract subprogram. The prefix of an attribute_reference for the Access, Unchecked_Access, or Address attributes shall not denote an abstract subprogram. 11.a Ramification: An abstract_subprogram_declaration is not syntactically a subprogram_declaration. Nonetheless, an abstract subprogram is a subprogram, and an abstract_subprogram_declaration is a declaration of a subprogram. 11.b The part about generic actual subprograms includes those given by default. NOTES 12 (74) Abstractness is not inherited; to declare an abstract type, the reserved word abstract has to be used in the declaration of the type extension. 12.a Ramification: A derived type can be abstract even if its parent is not. Similarly, an inherited concrete subprogram can be overridden with an abstract subprogram. 13 (75) A class-wide type is never abstract. Even if a class is rooted at an abstract type, the class-wide type for the class is not abstract, and an object of the class-wide type can be created; the tag of such an object will identify some nonabstract type in the class. Examples 14 Example of an abstract type representing a set of natural numbers: 15 package Sets is subtype Element_Type is Natural; type Set is abstract tagged null record; function Empty return Set is abstract; function Union(Left, Right : Set) return Set is abstract; function Intersection(Left, Right : Set) return Set is abstract; function Unit_Set(Element : Element_Type) return Set is abstract; procedure Take(Element : out Element_Type; From : in out Set) is abstra\ ct; end Sets; NOTES 16 (76) Notes on the example: Given the above abstract type, one could then derive various (nonabstract) extensions of the type, representing alternative implementations of a set. One might use a bit vector, but impose an upper bound on the largest element representable, while another might use a hash table, trading off space for flexibility. 16.a Discussion: One way to export a type from a package with some components visible and some components private is as follows: 16.b package P is type Public_Part is abstract tagged record ... end record; type T is new Public_Part with private; ... private type T is new Public_Part with record ... end record; end P; 16.c The fact that Public_Part is abstract tells clients they have to create objects of type T instead of Public_Part. Note that the public part has to come first; it would be illegal to declare a private type Private_Part, and then a record extension T of it, unless T were in the private part after the full declaration of Private_Part, but then clients of the package would not have visibility to T. 3.10 Access Types 1 {access type} {access value} {designate} A value of an access type (an access value) provides indirect access to the object or subprogram it designates. Depending on its type, an access value can designate either subprograms, objects created by allocators (see 4.8), or more generally aliased objects of an appropriate type. {pointer: see access value} {pointer type: see access type} 1.a Discussion: A name denotes an entity; an access value designates an entity. The ``dereference'' of an access value X, written ``X.all'', is a name that denotes the entity designated by X. Language Design Principles 1.b Access values should always be well defined (barring uses of certain unchecked features of Section 13). In particular, uninitialized access variables should be prevented by compile-time rules. Syntax 2 access_type_definition ::= access_to_object_definition | access_to_subprogram_definition 3 access_to_object_definition ::= access [general_access_modifier] subtype_indication 4 general_access_modifier ::= all | constant 5 access_to_subprogram_definition ::= access [protected] procedure parameter_profile | access [protected] function parameter_and_result_profile 6 access_definition ::= access subtype_mark Static Semantics 7 {access-to-object type} {access-to-subprogram type} {pool-specific access type} {general access type} There are two kinds of access types, access-to-object types, whose values designate objects, and access-to-subprogram types, whose values designate subprograms. {storage pool} Associated with an access-to-object type is a storage pool; several access types may share the same storage pool. {pool element} A storage pool is an area of storage used to hold dynamically allocated objects (called pool elements) created by allocators[; storage pools are described further in 13.11, ``Storage Management'']. 8 {pool-specific access type} {general access type} Access-to-object types are further subdivided into pool-specific access types, whose values can designate only the elements of their associated storage pool, and general access types, whose values can designate the elements of any storage pool, as well as aliased objects created by declarations rather than allocators, and aliased subcomponents of other objects. 8.a Implementation Note: The value of an access type will typically be a machine address. However, a value of a pool-specific access type can be represented as an offset (or index) relative to its storage pool, since it can point only to the elements of that pool. 9 {aliased} A view of an object is defined to be aliased if it is defined by an object_declaration or component_definition with the reserved word aliased, or by a renaming of an aliased view. In addition, the dereference of an access-to-object value denotes an aliased view, as does a view conversion (see 4.6) of an aliased view. Finally, the current instance of a limited type, and a formal parameter or generic formal object of a tagged type are defined to be aliased. [Aliased views are the ones that can be designated by an access value.] {constrained (object)} {unconstrained (object)} {constrained by its initial value} If the view defined by an object_declaration is aliased, and the type of the object has discriminants, then the object is constrained; if its nominal subtype is unconstrained, then the object is constrained by its initial value. [Similarly, if the object created by an allocator has discriminants, the object is constrained, either by the designated subtype, or by its initial value.] 9.a Glossary entry: {Aliased} An aliased view of an object is one that can be designated by an access value. Objects allocated by allocators are aliased. Objects can also be explicitly declared as aliased with the reserved word aliased. The Access attribute can be used to create an access value designating an aliased object. 9.b Ramification: The current instance of a nonlimited type is not aliased. 9.c The object created by an allocator is aliased, but not its subcomponents, except of course for those that themselves have aliased in their component_definition. 9.d The renaming of an aliased object is aliased. 9.e Slices are never aliased. See 4.1.2 for more discussion. 9.f Reason: The current instance of a limited type is defined to be aliased so that an access discriminant of a component can be initialized with T'Access inside the definition of T. 9.g A formal parameter of a tagged type is defined to be aliased so that a (tagged) parameter X may be passed to an access parameter P by using P => X'Access. Access parameters are most important for tagged types because of dispatching-on-access-parameters (see 3.9.2). By restricting this to formal parameters, we minimize problems associated with allowing components that are not declared aliased to be pointed-to from within the same record. 9.h A view conversion of an aliased view is aliased so that the type of an access parameter can be changed without first converting to a named access type. For example: 9.i type T1 is tagged ...; procedure P(X : access T1); 9.j type T2 is new T1 with ...; procedure P(X : access T2) is begin P(T1(X.all)'Access); -- hand off to T1's P . . . -- now do extra T2-specific processing end P; 9.k The rule about objects with discriminants is necessary because values of a constrained access subtype can designate an object whose nominal subtype is unconstrained; without this rule, a check on every use of such values would be required to ensure that the discriminants of the object had not changed. With this rule (among others), we ensure that if there might exist aliased views of a discriminated object, then the object is necessarily constrained. Note that this rule is necessary only for untagged types, since a discriminant of a tagged type can't have a default, so all tagged discriminated objects are always constrained anyway. 9.l We considered making more kinds of objects aliased by default. In particular, any object of a by-reference type will pretty much have to be allocated at an addressable location, so it can be passed by reference without using bit-field pointers. Therefore, one might wish to allow the Access and and Unchecked_Access attributes for such objects. However, private parts are transparent to the definition of ``by-reference type'', so if we made all objects of a by-reference type aliased, we would be violating the privacy of private parts. Instead, we would have to define a concept of ``visibly by-reference'' and base the rule on that. This seemed to complicate the rules more than it was worth, especially since there is no way to declare an untagged limited private type to be by-reference, since the full type might by nonlimited. 9.m Discussion: Note that we do not use the term ``aliased'' to refer to formal parameters that are referenced through multiple access paths (see 6.2). 10 An access_to_object_definition defines an access-to-object type and its first subtype; {designated subtype (of a named access type)} {designated type (of a named access type)} the subtype_indication defines the designated subtype of the access type. If a general_access_modifier appears, then the access type is a general access type. {access-to-constant type} If the modifier is the reserved word constant, then the type is an access-to-constant type[; a designated object cannot be updated through a value of such a type]. {access-to-variable type} If the modifier is the reserved word all, then the type is an access-to-variable type[; a designated object can be both read and updated through a value of such a type]. If no general_access_modifier appears in the access_to_object_definition, the access type is a pool-specific access-to-variable type. 10.a To be honest: The type of the designated subtype is called the designated type. 10.b Reason: The modifier all was picked to suggest that values of a general access type could point into ``all'' storage pools, as well as to objects declared aliased, and that ``all'' access (both read and update) to the designated object was provided. We couldn't think of any use for pool-specific access-to-constant types, so any access type defined with the modifier constant is considered a general access type, and can point into any storage pool or at other (appropriate) aliased objects. 10.c Implementation Note: The predefined generic Unchecked_ Deallocation can be instantiated for any named access-to-variable type. There is no (language-defined) support for deallocating objects designated by a value of an access-to-constant type. Because of this, an allocator for an access-to-constant type can allocate out of a storage pool with no support for deallocation. Frequently, the allocation can be done at link-time, if the size and initial value are known then. 10.d Discussion: For the purpose of generic formal type matching, the relevant subclasses of access types are access-to-subprogram types, access-to-constant types, and (named) access-to-variable types, with its subclass (named) general access-to-variable types. Pool-specific access-to-variable types are not a separately matchable subclass of types, since they don't have any ``extra'' operations relative to all (named) access-to-variable types. 11 {access-to-subprogram type} An access_to_subprogram_definition defines an access-to-subprogram type and its first subtype; {designated profile (of an access-to-subprogram type)} the parameter_profile or parameter_and_result_ profile defines the designated profile of the access type. {calling convention (associated with a designated profile)} There is a calling convention associated with the designated profile[; only subprograms with this calling convention can be designated by values of the access type.] By default, the calling convention is ``protected'' if the reserved word protected appears, and ``Ada'' otherwise. [See Annex B for how to override this default.] 11.a Ramification: The calling convention protected is in italics to emphasize that it cannot be specified explicitly by the user. This is a consequence of it being a reserved word. 11.b Implementation Note: For an access-to-subprogram type, the representation of an access value might include implementation- defined information needed to support up-level references -- for example, a static link. The accessibility rules (see 3.10.2) ensure that in a "global-display-based" implementation model (as opposed to a static-link-based model), an access-to-(unprotected)-subprogram value need consist only of the address of the subprogram. The global display is guaranteed to be properly set up any time the designated subprogram is called. Even in a static-link-based model, the only time a static link is definitely required is for an access-to-subprogram type declared in a scope nested at least two levels deep within subprogram or task bodies, since values of such a type might designate subprograms nested a smaller number of levels. For the normal case of an access-to-subprogram type declared at the outermost (library) level, a code address by itself should be sufficient to represent the access value in many implementations. 11.c For access-to-protected-subprogram, the access values will necessarily include both an address (or other identification) of the code of the subprogram, as well as the address of the associated protected object. This could be thought of as a static link, but it will be needed even for global-display-based implementation models. It corresponds to the value of the ``implicit parameter'' that is passed into every call of a protected operation, to identify the current instance of the protected type on which they are to operate. 11.d Any Elaboration_Check is performed when a call is made through an access value, rather than when the access value is first "created" via a 'Access. For implementation models that normally put that check at the call-site, an access value will have to point to a separate entry point that does the check. Alternatively, the access value could point to a "subprogram descriptor" that consisted of two words (or perhaps more), the first being the address of the code, the second being the elaboration bit. Or perhaps more efficiently, just the address of the code, but using the trick that the descriptor is initialized to point to a Raise-Program-Error routine initially, and then set to point to the "real" code when the body is elaborated. 11.e For implementations that share code between generic instantiations, the extra level of indirection suggested above to support Elaboration_Checks could also be used to provide a pointer to the per-instance data area normally required when calling shared code. The trick would be to put a pointer to the per-instance data area into the subprogram descriptor, and then make sure that the address of the subprogram descriptor is loaded into a "known" register whenever an indirect call is performed. Once inside the shared code, the address of the per-instance data area can be retrieved out of the subprogram descriptor, by indexing off the "known" register. 11.f Essentially the same implementation issues arise for calls on dispatching operations of tagged types, except that the static link is always known "statically." 11.g Note that access parameters of an anonymous access-to- subprogram type are not permitted. If there were such parameters, full ``downward'' closures would be required, meaning that in an implementation that uses a per-task (global) display, the display would have to be passed as a hidden parameter, and reconstructed at the point of call. This was felt to be an undue implementation burden, given that an equivalent (actually, more general) capability is available via formal subprogram parameters to a generic. 12 {anonymous access type} {designated subtype (of an anonymous access type)} {designated type (of an anonymous access type)} An access_definition defines an anonymous general access-to-variable type; the subtype_mark denotes its designated subtype. [An access_definition is used in the specification of an access discriminant (see 3.7) or an access parameter (see 6.1).] 13 {null value (of an access type)} For each (named) access type, there is a literal null which has a null access value designating no entity at all. [The null value of a named access type is the default initial value of the type.] Other values of an access type are obtained by evaluating an attribute_reference for the Access or Unchecked_Access attribute of an aliased view of an object or non-intrinsic subprogram, or, in the case of a named access-to-object type, an allocator[, which returns an access value designating a newly created object (see 3.10.2)]. 13.a Ramification: A value of an anonymous access type (that is, the value of an access parameter or access discriminant) cannot be null. 13.b Reason: Access parameters allow dispatching on the tag of the object designated by the actual parameter (which gets converted to the anonymous access type as part of the call). In order for dispatching to work properly, there had better be such an object. Hence, the type conversion will raise Constraint_Error if the value of the actual parameter is null. 14 {constrained [subtype]} {unconstrained [subtype]} [All subtypes of an access-to-subprogram type are constrained.] The first subtype of a type defined by an access_type_definition or an access_to_object_definition is unconstrained if the designated subtype is an unconstrained array or discriminated type; otherwise it is constrained. 14.a Proof: The Legality Rules on range_constraints (see 3.5) do not permit the subtype_mark of the subtype_indication to denote an access-to-scalar type, only a scalar type. The Legality Rules on index_constraints (see 3.6.1) and discriminant_constraints (see 3.7.1) both permit access-to-composite types in a subtype_indication with such _constraints. Note that an access-to-access-to-composite is never permitted in a subtype_indication with a constraint. 14.b Reason: Only composite_constraints are permitted for an access type, and only on access-to-composite types. A constraint on an access-to-scalar or access-to-access type might be violated due to assignments via other access paths that were not so constrained. By contrast, if the designated subtype is an array or discriminated type, the constraint could not be violated by unconstrained assignments, since array objects are always constrained, and aliased discriminated objects are also constrained (by fiat, see Static Semantics). Dynamic Semantics 15 {compatibility [composite_constraint with an access subtype]} A composite_constraint is compatible with an unconstrained access subtype if it is compatible with the designated subtype. {satisfies [for an access value]} An access value satisfies a composite_constraint of an access subtype if it equals the null value of its type or if it designates an object whose value satisfies the constraint. 16 {elaboration [access_type_definition]} The elaboration of an access_ type_definition creates the access type and its first subtype. For an access-to-object type, this elaboration includes the elaboration of the subtype_indication, which creates the designated subtype. 17 {elaboration [access_definition]} The elaboration of an access_ definition creates an anonymous general access-to-variable type [(this happens as part of the initialization of an access parameter or access discriminant)]. NOTES 18 (77) Access values are called ``pointers'' or ``references'' in some other languages. 19 (78) Each access-to-object type has an associated storage pool; several access types can share the same pool. An object can be created in the storage pool of an access type by an allocator (see 4.8) for the access type. A storage pool (roughly) corresponds to what some other languages call a ``heap.'' See 13.11 for a discussion of pools. 20 (79) Only index_constraints and discriminant_constraints can be applied to access types (see 3.6.1 and 3.7.1). Examples 21 Examples of access-to-object types: 22 type Peripheral_Ref is access Peripheral; -- see 3.8.1 type Binop_Ptr is access all Binary_Operation'Class; -- general access-to-class-wide,\ see 3.9.1 23 Example of an access subtype: 24 subtype Drum_Ref is Peripheral_Ref(Drum); -- see 3.8.1 25 Example of an access-to-subprogram type: 26 type Message_Procedure is access procedure (M : in String := "Error!"); procedure Default_Message_Procedure(M : in String); Give_Message : Message_Procedure := Default_Message_Procedure'Access; ... procedure Other_Procedure(M : in String); ... Give_Message := Other_Procedure'Access; ... Give_Message("File not found."); -- call with parameter (.all is optional) Give_Message.all; -- call with no parameters Extensions to Ada 83 26.a {extensions to Ada 83} The syntax for access_type_definition is changed to support general access types (including access-to- constants) and access-to-subprograms. The syntax rules for general_ access_modifier and access_definition are new. Wording Changes From Ada 83 26.b We use the term "storage pool" to talk about the data area from which allocation takes place. The term "collection" is no longer used. ("Collection" and "storage pool" are not the same thing because multiple unrelated access types can share the same storage pool; see 13.11 for more discussion.) 3.10.1 Incomplete Type Declarations 1 There are no particular limitations on the designated type of an access type. In particular, the type of a component of the designated type can be another access type, or even the same access type. This permits mutually dependent and recursive access types. An incomplete_type_declaration can be used to introduce a type to be used as a designated type, while deferring its full definition to a subsequent full_type_declaration. Syntax 2 incomplete_type_declaration ::= type defining_identifier [discriminant_part\ ]; Legality Rules 3 {requires a completion [incomplete_type_declaration]} An incomplete_type_ declaration requires a completion, which shall be a full_type_declaration. [If the incomplete_type_declaration occurs immediately within either the visible part of a package_specification or a declarative_part, then the full_ type_declaration shall occur later and immediately within this visible part or declarative_part. If the incomplete_type_declaration occurs immediately within the private part of a given package_specification, then the full_type_ declaration shall occur later and immediately within either the private part itself, or the declarative_part of the corresponding package_body.] 3.a Proof: This is implied by the next AARM-only rule, plus the rules in 3.11.1, ``Completions of Declarations'' which require a completion to appear later and immediately within the same declarative region. 3.b To be honest: If the incomplete_type_declaration occurs immediately within the visible part of a package_specification, then the full_type_declaration shall occur immediately within this visible part. 3.c To be honest: If the implementation supports it, an incomplete_type_declaration can be completed by a pragma Import. 4 If an incomplete_type_declaration has a known_discriminant_part, then a full_type_declaration that completes it shall have a fully conforming (explicit) known_discriminant_part (see 6.3.1). {full conformance (required)} [If an incomplete_type_declaration has no discriminant_part (or an unknown_discriminant_part), then a corresponding full_type_declaration is nevertheless allowed to have discriminants, either explicitly, or inherited via derivation.] 5 The only allowed uses of a name that denotes an incomplete_type_ declaration are as follows: 5.a Discussion: No need to say "prior to the end of the full_type_ declaration" since the name would not denote the incomplete_type_ declaration after the end of the full_type_declaration. Also, with child library units, it would not be well defined whether they come before or after the full_type_declaration for deferred incomplete types. 6 as the subtype_mark in the subtype_indication of an access_to_ object_definition; [the only form of constraint allowed in this subtype_indication is a discriminant_constraint;] 6.a Implementation Note: We now allow discriminant_constraints even if the full type is deferred to the package body. However, there is no particular implementation burden because we have dropped the concept of the dependent compatibility check. In other words, we have effectively repealed AI-00007. 7 as the subtype_mark defining the subtype of a parameter or result of an access_to_subprogram_definition; 7.a Reason: This allows, for example, a record to have a component designating a subprogram that takes that same record type as a parameter. 8 as the subtype_mark in an access_definition; 9 as the prefix of an attribute_reference whose attribute_ designator is Class; such an attribute_reference is similarly restricted to the uses allowed here; when used in this way, the corresponding full_type_declaration shall declare a tagged type, and the attribute_reference shall occur in the same library unit as the incomplete_type_declaration. 9.a Reason: This is to prevent children from imposing requirements on their ancestor library units for deferred incomplete types. 10 A dereference (whether implicit or explicit -- see 4.1) shall not be of an incomplete type. Static Semantics 11 {incomplete type} An incomplete_type_declaration declares an incomplete type and its first subtype; the first subtype is unconstrained if a known_ discriminant_part appears. 11.a Reason: If an unknown_discriminant_part or no discriminant_ part appears, then the constrainedness of the first subtype doesn't matter for any other rules or semantics, so we don't bother defining it. The case with a known_discriminant_part is the only case in which a constraint could later be given in a subtype_indication naming the incomplete type. Dynamic Semantics 12 {elaboration [incomplete_type_declaration]} The elaboration of an incomplete_type_declaration has no effect. 12.a Reason: An incomplete type has no real existence, so it doesn't need to be "created" in the usual sense we do for other types. It is roughly equivalent to a "forward;" declaration in Pascal. Private types are different, because they have a different set of characteristics from their full type. NOTES 13 (80) {completion legality [partial]} Within a declarative_part, an incomplete_type_declaration and a corresponding full_type_declaration cannot be separated by an intervening body. This is because a type has to be completely defined before it is frozen, and a body freezes all types declared prior to it in the same declarative_part (see 13.14). Examples 14 Example of a recursive type: 15 type Cell; -- incomplete type declaration type Link is access Cell; 16 type Cell is record Value : Integer; Succ : Link; Pred : Link; end record; 17 Head : Link := new Cell'(0, null, null); Next : Link := Head.Succ; 18 Examples of mutually dependent access types: 19 type Person(<>); -- incomplete type declaration type Car; -- incomplete type declaration 20 type Person_Name is access Person; type Car_Name is access all Car; 21 type Car is record Number : Integer; Owner : Person_Name; end record; 22 type Person(Sex : Gender) is record Name : String(1 .. 20); Birth : Date; Age : Integer range 0 .. 130; Vehicle : Car_Name; case Sex is when M => Wife : Person_Name(Sex => F); when F => Husband : Person_Name(Sex => M); end case; end record; 23 My_Car, Your_Car, Next_Car : Car_Name := new Car; -- see 4.8 George : Person_Name := new Person(M); ... George.Vehicle := Your_Car; Extensions to Ada 83 23.a {extensions to Ada 83} The full_type_declaration that completes an incomplete_type_declaration may have a known_ discriminant_part even if the incomplete_type_declaration does not. 23.b A discriminant_constraint may be applied to an incomplete type, even if it its completion is deferred to the package body, because there is no ``dependent compatibility check'' required any more. Of course, the constraint can be specified only if a known_ discriminant_part was given in the incomplete_type_declaration. As mentioned in the previous paragraph, that is no longer required even when the full type has discriminants. Wording Changes From Ada 83 23.c Dereferences producing incomplete types were not explicitly disallowed in RM83, though AI-00039 indicated that it was not strictly necessary since troublesome cases would result in Constraint_Error at run time, since the access value would necessarily be null. However, this introduces an undesirable implementation burden, as illustrated by Example 4 of AI-00039: 23.d package Pack is type Pri is private; private type Sep; type Pri is access Sep; X : Pri; end Pack; 23.e package body Pack is -- Could be separately compiled! type Sep is ...; X := new Sep; end Pack; 23.f pragma Elaborate(Pack); private package Pack.Child is I : Integer := X.all'Size; -- Legal, by AI-00039. end Pack.Child; 23.g Generating code for the above example could be a serious implementation burden, since it would require all aliased objects to store size dope, and for that dope to be in the same format for all kinds of types (or some other equivalently inefficient implemen- tation). On the contrary, most implementations allocate dope differently (or not at all) for different designated subtypes. 3.10.2 Operations of Access Types 1 [The attribute Access is used to create access values designating aliased objects and non-intrinsic subprograms. The ``accessibility'' rules prevent dangling references (in the absence of uses of certain unchecked features -- see Section 13). ] Language Design Principles 1.a It should be possible for an access value to designate an object declared by an object declaration, or a subcomponent thereof. In implementation terms, this means pointing at stack-allocated and statically allocated data structures. However, dangling references should be prevented, primarily via compile-time rules, so long as features like Unchecked_Access and Unchecked_Deallocation are not used. 1.b In order to create such access values, we require that the access type be a general access type, that the designated object be aliased, and that the accessibility rules be obeyed. Name Resolution Rules 2 {expected type [access attribute_reference]} For an attribute_reference with attribute_designator Access (or Unchecked_Access -- see 13.10), the expected type shall be a single access type[; the prefix of such an attribute_reference is never interpreted as an implicit_dereference]. {expected profile [Access attribute_reference prefix]} If the expected type is an access-to-subprogram type, then the expected profile of the prefix is the designated profile of the access type. 2.a Discussion: Saying that the expected type shall be a "single access type" is our "new" way of saying that the type has to be determinable from context using only the fact that it is an access type. See 4.2 and 8.6. Specifying the expected profile only implies type conformance. The more stringent subtype conformance is required by a Legality Rule. This is the only Resolution Rule that applies to the name in a prefix of an attribute_reference. In all other cases, the name has to be resolved without using context. See 4.1.4. Static Semantics 3 {accessibility level} {level (accessibility)} {deeper (accessibility level)} {depth (accessibility level)} {dangling references (prevention via accessibility rules)} {lifetime} [The accessibility rules, which prevent dangling references, are written in terms of accessibility levels, which reflect the run-time nesting of masters. As explained in 7.6.1, a master is the execution of a task_body, a block_statement, a subprogram_body, an entry_ body, or an accept_statement. An accessibility level is deeper than another if it is more deeply nested at run time. For example, an object declared local to a called subprogram has a deeper accessibility level than an object declared local to the calling subprogram. The accessibility rules for access types require that the accessibility level of an object designated by an access value be no deeper than that of the access type. This ensures that the object will live at least as long as the access type, which in turn ensures that the access value cannot later designate an object that no longer exists. The Unchecked_Access attribute may be used to circumvent the accessibility rules.] 4 {statically deeper} {deeper (statically)} [A given accessibility level is said to be statically deeper than another if the given level is known at compile time (as defined below) to be deeper than the other for all possible executions. In most cases, accessibility is enforced at compile time by Legality Rules. Run-time accessibility checks are also used, since the Legality Rules do not cover certain cases involving access parameters and generic packages.] 5 Each master, and each entity and view created by it, has an accessibility level: 6 The accessibility level of a given master is deeper than that of each dynamically enclosing master, and deeper than that of each master upon which the task executing the given master directly depends (see 9.3). 7 An entity or view created by a declaration has the same accessibility level as the innermost enclosing master, except in the cases of renaming and derived access types described below. A parameter of a master has the same accessibility level as the master. 8 The accessibility level of a view of an object or subprogram defined by a renaming_declaration is the same as that of the renamed view. 9 The accessibility level of a view conversion is the same as that of the operand. 10 For a function whose result type is a return-by-reference type, the accessibility level of the result object is the same as that of the master that elaborated the function body. For any other function, the accessibility level of the result object is that of the execution of the called function. 11 The accessibility level of a derived access type is the same as that of its ultimate ancestor. 12 The accessibility level of the anonymous access type of an access discriminant is the same as that of the containing object or associated constrained subtype. 13 The accessibility level of the anonymous access type of an access parameter is the same as that of the view designated by the actual. If the actual is an allocator, this is the accessibility level of the execution of the called subprogram. 14 The accessibility level of an object created by an allocator is the same as that of the access type. 15 The accessibility level of a view of an object or subprogram denoted by a dereference of an access value is the same as that of the access type. 16 The accessibility level of a component, protected subprogram, or entry of (a view of) a composite object is the same as that of (the view of) the composite object. 17 {statically deeper} {deeper (statically)} One accessibility level is defined to be statically deeper than another in the following cases: 18 For a master that is statically nested within another master, the accessibility level of the inner master is statically deeper than that of the outer master. 18.a To be honest: Strictly speaking, this should talk about the constructs (such as subprogram_bodies) being statically nested within one another; the masters are really the executions of those constructs. 18.b To be honest: If a given accessibility level is statically deeper than another, then each level defined to be the same as the given level is statically deeper than each level defined to be the same as the other level. 19 The statically deeper relationship does not apply to the accessibility level of the anonymous type of an access parameter; that is, such an accessibility level is not considered to be statically deeper, nor statically shallower, than any other. 20 For determining whether one level is statically deeper than another when within a generic package body, the generic package is presumed to be instantiated at the same level as where it was declared; run-time checks are needed in the case of more deeply nested instantiations. 21 For determining whether one level is statically deeper than another when within the declarative region of a type_declaration, the current instance of the type is presumed to be an object created at a deeper level than that of the type. 21.a Ramification: In other words, the rules are checked at compile time of the type_declaration, in an assume-the-worst manner. 22 {library level} {level (library)} The accessibility level of all library units is called the library level; a library-level declaration or entity is one whose accessibility level is the library level. 22.a Ramification: Library_unit_declarations are library level. Nested declarations are library level if they are nested only within packages (possibly more than one), and not within subprograms, tasks, etc. 22.b To be honest: The definition of the accessibility level of the anonymous type of an access parameter cheats a bit, since it refers to the view designated by the actual, but access values designate objects, not views of objects. What we really mean is the view that ``would be'' denoted by an expression ``X.all'', where X is the actual, even though such an expression is a figment of our imagination. The definition is intended to be equivalent to the following more verbose version: The accessibility level of the anonymous type of an access parameter is as follows: 22.c if the actual is an expression of a named access type -- the accessibility level of that type; 22.d if the actual is an allocator -- the accessibility level of the execution of the called subprogram; 22.e if the actual is a reference to the Access attribute -- the accessibility level of the view denoted by the prefix; 22.f if the actual is a reference to the Unchecked_Access attribute -- library accessibility level; 22.g if the actual is an access parameter -- the accessibility level of its type. 22.h Note that the allocator case is explicitly mentioned in the RM9X, because otherwise the definition would be circular: the level of the anonymous type is that of the view designated by the actual, which is that of the access type. 22.i Discussion: A deeper accessibility level implies a shorter maximum lifetime. Hence, when a rule requires X to have a level that is ``not deeper than'' Y's level, this requires that X has a lifetime at least as long as Y. (We say ``maximum lifetime'' here, because the accessibility level really represents an upper bound on the lifetime; an object created by an allocator can have its lifetime prematurely ended by an instance of Unchecked_Deallocation.) 22.j Package elaborations are not masters, and are therefore invisible to the accessibility rules: an object declared immediately within a package has the same accessibility level as an object declared immediately within the declarative region containing the package. This is true even in the body of a package; it jibes with the fact that objects declared in a package_body live as long as objects declared outside the package, even though the body objects are not visible outside the package. 22.k Note that the level of the view denoted by X.all can be different from the level of the object denoted by X.all. The former is determined by the type of X; the latter is determined either by the type of the allocator, or by the master in which the object was declared. The former is used in several Legality Rules and run-time checks; the latter is used to define when X.all gets finalized. The level of a view reflects what we can conservatively ``know'' about the object of that view; for example, due to type_conversions, an access value might designate an object that was allocated by an allocator for a different access type. 22.l Similarly, the level of the view denoted by X.all.Comp can be different from the level of the object denoted by X.all.Comp. 22.m If Y is statically deeper than X, this implies that Y will be (dynamically) deeper than X in all possible executions. 22.n Most accessibility checking is done at compile time; the rules are stated in terms of ``statically deeper than''. The exceptions are: 22.o Checks involving access parameters. The fact that ``statically deeper than'' is not defined for the anonymous access type of an access parameter implies that any rule saying ``shall not be statically deeper than'' does not apply to such a type, nor to anything defined to have ``the same'' level as such a type. 22.p Checks involving entities and views within generic packages. This is because an instantiation can be at a level that is more deeply nested than the generic package itself. In implementations that use a macro-expansion model of generics, these violations can be detected at macro-expansion time. For implementations that share generics, run-time code is needed to detect the error. 22.q Checks during function return. 22.r Note that run-time checks are not required for access discriminants, because their accessibility is determined statically by the accessibility level of the enclosing object. 22.s The accessibility level of the result object of a function reflects the time when that object will be finalized; we don't allow pointers to the object to survive beyond that time. 22.t We sometimes use the terms ``accessible'' and ``inaccessible'' to mean that something has an accessibility level that is not deeper, or deeper, respectively, than something else. 22.u Implementation Note: If an accessibility Legality Rule is satisfied, then the corresponding run-time check (if any) cannot fail (and a reasonable implementation will not generate any checking code) unless access parameters or shared generic bodies are involved. 22.v Accessibility levels are defined in terms of the relations ``the same as'' and ``deeper than''. To make the discussion more concrete, we can assign actual numbers to each level. Here, we assume that library-level accessibility is level 0, and each level defined as ``deeper than'' is one level deeper. Thus, a subprogram directly called from the environment task (such as the main subprogram) would be at level 1, and so on. 22.w Accessibility is not enforced at compile time for access parameters. The ``obvious'' implementation of the run-time checks would be inefficient, and would involve distributed overhead; therefore, an efficient method is given below. The ``obvious'' implementation would be to pass the level of the caller at each subprogram call, task creation, etc. This level would be incremented by 1 for each dynamically nested master. An Accessibility_Check would be implemented as a simple comparison -- checking that X is not deeper than Y would involve checking that X <= Y. 22.x A more efficient method is based on passing static nesting levels (within constructs that correspond at run time to masters -- packages don't count). Whenever an access parameter is passed, an implicit extra parameter is passed with it. The extra parameter represents (in an indirect way) the accessibility level of the anonymous access type, and, therefore, the level of the view denoted by a dereference of the access parameter. This is analogous to the implicit ``Constrained'' bit associated with certain formal parameters of an unconstrained but definite composite subtype. In this method, we avoid distributed overhead: it is not necessary to pass any extra information to subprograms that have no access parameters. For anything other than an access parameter and its anonymous type, the static nesting level is known at compile time, and is defined analogously to the RM9X definition of accessibility level (e.g. derived access types get their nesting level from their parent). Checking ``not deeper than'' is a "<=" test on the levels. 22.y For each access parameter, the static depth passed depends on the actual, as follows: 22.z If the actual is an expression of a named access type, pass the static nesting level of that type. 22.aa If the actual is an allocator, pass the static nesting level of the caller, plus one. 22.bb If the actual is a reference to the Access attribute, pass the level of the view denoted by the prefix. 22.cc If the actual is a reference to the Unchecked_Access attribute, pass 0 (the library accessibility level). 22.dd If the actual is an access parameter, usually just pass along the level passed in. However, if the static nesting level of the formal (access) parameter is greater than the static nesting level of the actual (access) parameter, the level to be passed is the minimum of the static nesting level of the access parameter and the actual level passed in. 22.ee For the Accessibility_Check associated with a type_conversion of an access parameter of a given subprogram to a named access type, if the target type is statically nested within the subprogram, do nothing; the check can't fail in this case. Otherwise, check that the value passed in is <= the static nesting depth of the target type. The other Accessibility_Checks are handled in a similar manner. 22.ff This method, using statically known values most of the time, is efficient, and, more importantly, avoids distributed overhead. 22.gg Discussion: Examples of accessibility: 22.hh package body Lib_Unit is type T is tagged ...; type A0 is access all T; Global: A0 := ...; procedure P(X: T) is Y: aliased T; type A1 is access all T; Ptr0: A0 := Global; -- OK. Ptr1: A1 := X'Access; -- OK. begin Ptr1 := Y'Access; -- OK; Ptr0 := A0(Ptr1); -- Illegal type conversion! Ptr0 := X'Access; -- Illegal reference to Access attribute! Ptr0 := Y'Access; -- Illegal reference to Access attribute! Global := Ptr0; -- OK. end P; end Lib_Unit; 22.ii The above illegal statements are illegal because the accessibility level of X and Y are statically deeper than the accessibility level of A0. In every possible execution of any program including this library unit, if P is called, the accessibility level of X will be (dynamically) deeper than that of A0. Note that the accessibility levels of X and Y are the same. 22.jj Here's an example involving access parameters: 22.kk procedure Main is type Level_1_Type is access all Integer; 22.ll procedure P(X: access Integer) is type Nested_Type is access all Integer; begin ... Nested_Type(X) ... -- (1) ... Level_1_Type(X) ... -- (2) end P; 22.mm procedure Q(X: access Integer) is procedure Nested(X: access Integer) is begin P(X); end Nested; begin Nested(X); end Q; 22.nn procedure R is Level_2: aliased Integer; begin Q(Level_2'Access); -- (3) end R; 22.oo Level_1: aliased Integer; begin Q(Level_1'Access); -- (4) R; end Main; 22.pp The run-time Accessibility_Check at (1) can never fail, and no code should be generated to check it. The check at (2) will fail when called from (3), but not when called from (4). 22.qq Within a type_declaration, the rules are checked in an assume-the-worst manner. For example: 22.rr package P is type Int_Ptr is access all Integer; type Rec(D: access Integer) is limited private; private type Rec_Ptr is access all Rec; function F(X: Rec_Ptr) return Boolean; function G(X: access Rec) return Boolean; type Rec(D: access Integer) is record C1: Int_Ptr := Int_Ptr(D); -- Illegal! C2: Rec_Ptr := Rec'Access; -- Illegal! C3: Boolean := F(Rec'Access); -- Illegal! C4: Boolean := G(Rec'Access); end record; end P; 22.ss C1, C2, and C3 are all illegal, because one might declare an object of type Rec at a more deeply nested place than the declaration of the type. C4 is legal, but the accessibility level of the object will be passed to function G, and constraint checks within G will prevent it from doing any evil deeds. 22.tt Note that we cannot defer the checks on C1, C2, and C3 until compile-time of the object creation, because that would cause violation of the privacy of private parts. Furthermore, the problems might occur within a task or protected body, which the compiler can't see while compiling an object creation. 23 The following attribute is defined for a prefix X that denotes an aliased view of an object: 24 X'Access X'Access yields an access value that designates the object denoted by X. The type of X'Access is an access-to-object type, as determined by the expected type. The expected type shall be a general access type. {Unchecked_Access attribute: see also Access attribute} X shall denote an aliased view of an object[, including possibly the current i