The Ada Joint Program Office does not guarantee the accuracy of this file, as compared with the contents of ANSI/MIL-STD-1815A-1983, the Reference Manual for the Ada Programming Language. If errors or discrepancies are found in this machine-readable version, please forward comments via the Defense Data Network (DDN) to: ACTION@AJPO.SEI.CMU.EDU or via conventional mail to Ada Information Clearinghouse 3D139 (1211 S. Fern, C-107) The Pentagon Washington, D.C. 20301-3081 ----------------------------------------------------------------------- Copyright 1980, 1982, 1983 owned by the United States Government as represented by the Under Secretary of Defense, Research and Engineering. All rights reserved. Provided that notice of copyright is included on the first page, this document may be copied in its entirety without alteration or as altered by (1) adding text that is clearly marked as an insertion; (2) shading or highlighting existing text; (3) deleting examples. Permission to publish other excerpts should be obtained from the Ada Joint Program Office, OUSDRE (R&AT), The Pentagon, Washington, DC 20301-2081, U.S.A. 3. Declarations and Types This chapter describes the types in the language and the rules for declaring constants, variables, and named numbers. 3.1 Declarations The language defines several kinds of entities that are declared, either explicitly or implicitly, by declarations. Such an entity can be a numeric literal, an object, a discriminant, a record component, a loop parameter, an exception, a type, a subtype, a subprogram, a package, a task unit, a generic unit, a single entry, an entry family, a formal parameter (of a subprogram, entry, or generic subprogram), a generic formal parameter, a named block or loop, a labeled statement, or an operation (in particular, an attribute or an enumeration literal; see 3.3.3). There are several forms of declaration. A basic declaration is a form of declaration defined as follows. basic_declaration ::= object_declaration | number_declaration | type_declaration | subtype_declaration | subprogram_declaration | package_declaration | task_declaration | generic_declaration | exception_declaration | generic_instantiation | renaming_declaration | deferred_constant_declaration Certain forms of declaration always occur (explicitly) as part of a basic declaration; these forms are discriminant specifications, component declarations, entry declarations, parameter specifications, generic parameter declarations, and enumeration literal specifications. A loop parameter specification is a form of declaration that occurs only in certain forms of loop statement. The remaining forms of declaration are implicit: the name of a block, the name of a loop, and a statement label are implicitly declared. Certain operations are implicitly declared (see 3.3.3). For each form of declaration the language rules define a certain region of text called the scope of the declaration (see 8.2). Several forms of declaration 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 associated declared entity; these places are defined by the visibility rules (see 8.3). At such places the identifier is said to be a name of the entity (its simple name); the name is said to denote the associated entity. Certain forms of enumeration literal specification associate a character literal with the corresponding declared entity. Certain forms of declaration associate an operator symbol or some other notation with an explicitly or implicitly declared operation. The process by which a declaration achieves its effect is called the elaboration of the declaration; this process happens during program execution. After its elaboration, a declaration is said to be elaborated. Prior to the completion of its elaboration (including before the elaboration), the declaration is not yet elaborated. The elaboration of any declaration has always at least the effect of achieving this change of state (from not yet elaborated to elaborated). The phrase "the elaboration has no other effect" is used in this manual whenever this change of state is the only effect of elaboration for some form of declaration. An elaboration process is also defined for declarative parts, declarative items, and compilation units (see 3.9 and 10.5). Object, number, type, and subtype declarations are described here. The remaining basic declarations are described in later chapters. Note: The syntax rules use the term identifier for the first occurrence of an identifier in some form of declaration; the term simple name is used for any occurrence of an identifier that already denotes some declared entity. References: attribute 4.1.4, block name 5.6, block statement 5.6, character literal 2.5, component declaration 3.7, declarative item 3.9, declarative part 3.9, deferred constant declaration 7.4, discriminant specification 3.7.1, elaboration 3.9, entry declaration 9.5, enumeration literal specification 3.5.1, exception declaration 11.1, generic declaration 12.1, generic instantiation 12.3, generic parameter declaration 12.1, identifier 2.3, label 5.1, loop name 5.5, loop parameter specification 5.5, loop statement 5.5, name 4.1, number declaration 3.2.2, numeric literal 2.4, object declaration 3.2.1, operation 3.3, operator symbol 6.1, package declaration 7.1, parameter specification 6.1, record component 3.7, renaming declaration 8.5, representation clause 13.1, scope 8.2, simple name 4.1, subprogram body 6.3, subprogram declaration 6.1, subtype declaration 3.3.2, task declaration 9.1, type declaration 3.3.1, visibility 8.3 3.2 Objects and Named Numbers An object is an entity that contains (has) a value of a given type. An object is one of the following: - an object declared by an object declaration or by a single task declaration, - a formal parameter of a subprogram, entry, or generic subprogram, - a generic formal object, - a loop parameter, - an object designated by a value of an access type, - a component or a slice of another object. A number declaration is a special form of object declaration that associates an identifier with a value of type universal_integer or universal_real. object_declaration ::= identifier_list : [constant] subtype_indication [:= expression]; | identifier_list : [constant] constrained_array_definition [:= expression]; number_declaration ::= identifier_list : constant := universal_static_expression; identifier_list ::= identifier {, identifier} An object declaration is called a single object declaration if its identifier list has a single identifier; it is called a multiple object declaration if the identifier list has two or more identifiers. A multiple object declaration is equivalent to a sequence of the corresponding number of single object declarations. For each identifier of the list, the equivalent sequence has a single object declaration formed by this identifier, followed by a colon and by whatever appears at the right of the colon in the multiple object declaration; the equivalent sequence is in the same order as the identifier list. A similar equivalence applies also for the identifier lists of number declarations, component declarations, discriminant specifications, parameter specifications, generic parameter declarations, exception declarations, and deferred constant declarations. In the remainder of this reference manual, explanations are given for declarations with a single identifier; the corresponding explanations for declarations with several identifiers follow from the equivalence stated above. Example: -- the multiple object declaration JOHN, PAUL : PERSON_NAME := new PERSON(SEX => M); -- see 3.8.1 -- is equivalent to the two single object declarations in the order given JOHN : PERSON_NAME := new PERSON(SEX => M); PAUL : PERSON_NAME := new PERSON(SEX => M); References: access type 3.8, constrained array definition 3.6, component 3.3, declaration 3.1, deferred constant declaration 7.4, designate 3.8, discriminant specification 3.7.1, entry 9.5, exception declaration 11.1, expression 4.4, formal parameter 6.1, generic formal object 12.1.1, generic parameter declaration 12.1, generic unit 12, generic subprogram 12.1, identifier 2.3, loop parameter 5.5, numeric type 3.5, parameter specification 6.1, scope 8.2, simple name 4.1, single task declaration 9.1, slice 4.1.2, static expression 4.9, subprogram 6, subtype indication 3.3.2, type 3.3, universal_integer type 3.5.4, universal_real type 3.5.6 3.2.1 Object Declarations An object declaration declares an object whose type is given either by a subtype indication or by a constrained array definition. If the object declaration includes the assignment compound delimiter followed by an expression, the expression specifies an initial value for the declared object; the type of the expression must be that of the object. The declared object is a constant if the reserved word constant appears in the object declaration; the declaration must then include an explicit initialization. The value of a constant cannot be modified after initialization. Formal parameters of mode in of subprograms and entries, and generic formal parameters of mode in, are also constants; a loop parameter is a constant within the corresponding loop; a subcomponent or slice of a constant is a constant. An object that is not a constant is called a variable (in particular, the object declared by an object declaration that does not include the reserved word constant is a variable). The only ways to change the value of a variable are either directly by an assignment, or indirectly when the variable is updated (see 6.2) by a procedure or entry call statement (this action can be performed either on the variable itself, on a subcomponent of the variable, or on another variable that has the given variable as subcomponent). The elaboration of an object declaration proceeds as follows: (a) The subtype indication or the constrained array definition is first elaborated. This establishes the subtype of the object. (b) If the object declaration includes an explicit initialization, the initial value is obtained by evaluating the corresponding expression. Otherwise any implicit initial values for the object or for its subcomponents are evaluated. (c) The object is created. (d) Any initial value (whether explicit or implicit) is assigned to the object or to the corresponding subcomponent. Implicit initial values are defined for objects declared by object declarations, and for components of such objects, in the following cases: - If the type of an object is an access type, the implicit initial value is the null value of the access type. - If the type of an object is a task type, the implicit initial (and only) value designates a corresponding task. - If the type of an object is a type with discriminants and the subtype of the object is constrained, the implicit initial (and only) value of each discriminant is defined by the subtype of the object. - If the type of an object is a composite type, the implicit initial value of each component that has a default expression is obtained by evaluation of this expression, unless the component is a discriminant of a constrained object (the previous case). In the case of a component that is itself a composite object and whose value is defined neither by an explicit initialization nor by a default expression, any implicit initial values for components of the composite object are defined by the same rules as for a declared object. The steps (a) to (d) are performed in the order indicated. For step (b), if the default expression for a discriminant is evaluated, then this evaluation is performed before that of default expressions for subcomponents that depend on discriminants, and also before that of default expressions that include the name of the discriminant. Apart from the previous rule, the evaluation of default expressions is performed in some order that is not defined by the language. The initialization of an object (the declared object or one of its subcomponents) checks that the initial value belongs to the subtype of the object; for an array object declared by an object declaration, an implicit subtype conversion is first applied as for an assignment statement, unless the object is a constant whose subtype is an unconstrained array type. The exception CONSTRAINT_ERROR is raised if this check fails. The value of a scalar variable is undefined after elaboration of the corresponding object declaration unless an initial value is assigned to the variable by an initialization (explicitly or implicitly). If the operand of a type conversion or qualified expression is a variable that has scalar subcomponents with undefined values, then the values of the corresponding subcomponents of the result are undefined. The execution of a program is erroneous if it attempts to evaluate a scalar variable with an undefined value. Similarly, the execution of a program is erroneous if it attempts to apply a predefined operator to a variable that has a scalar subcomponent with an undefined value. Examples of variable declarations: COUNT, SUM : INTEGER; SIZE : INTEGER range 0 .. 10_ := 0; SORTED : BOOLEAN := FALSE; COLOR_TABLE : array(1 .. N) of COLOR; OPTION : BIT_VECTOR(1 .. 10) := (others => TRUE); Examples of constant declarations: LIMIT : constant INTEGER := 10_ LOW_LIMIT : constant INTEGER := LIMIT/10; TOLERANCE : constant REAL := DISPERSION(1.15); Note: The expression initializing a constant object need not be a static expression (see 4.9). In the above examples, LIMIT and LOW_LIMIT are initialized with static expressions, but TOLERANCE is not if DISPERSION is a user-defined function. References: access type 3.8, assignment 5.2, assignment compound delimiter 5.2, component 3.3, composite type 3.3, constrained array definition 3.6, constrained subtype 3.3, constraint_error exception 11.1, conversion 4.6, declaration 3.1, default expression for a discriminant 3.7, default initial value for an access type 3.8, depend on a discriminant 3.7.1, designate 3.8, discriminant 3.3, elaboration 3.9, entry 9.5, evaluation 4.5, expression 4.4, formal parameter 6.1, generic formal parameter 12.1 12.3, generic unit 12, in some order 1.6, limited type 7.4.4, mode in 6.1, package 7, predefined operator 4.5, primary 4.4, private type 7.4, qualified expression 4.7, reserved word 2.9, scalar type 3.5, slice 4.1.2, subcomponent 3.3, subprogram 6, subtype 3.3, subtype indication 3.3.2, task 9, task type 9.2, type 3.3, visible part 7.2 3.2.2 Number Declarations A number declaration is a special form of constant declaration. The type of the static expression given for the initialization of a number declaration must be either the type universal_integer or the type universal_real. The constant declared by a number declaration is called a named number and has the type of the static expression. Note: The rules concerning expressions of a universal type are explained in section 4.10. It is a consequence of these rules that if every primary contained in the expression is of the type universal_integer, then the named number is also of this type. Similarly, if every primary is of the type universal_real, then the named number is also of this type. Examples of number declarations: PI : constant := 3.14159_26536; -- a real number TWO_PI : constant := 2.0*PI; -- a real number MAX : constant := 5 -- an integer number POWER_16 : constant := 2**16; -- the integer 65_536 ONE, UN, EINS : constant := 1; -- three different names for 1 References: identifier 2.3, primary 4.4, static expression 4.9, type 3.3, universal_integer type 3.5.4, universal_real type 3.5.6, universal type 4.1 4 3.3 Types and Subtypes A type is characterized by a set of values and a set of operations. There exist several classes of types. Scalar types are integer types, real types, and types defined by enumeration of their values; values of these types have no components. Array and record types are composite; a value of a composite type consists of component values. An access type is a type whose values provide access to objects. Private types are types for which the set of possible values is well defined, but not directly available to the users of such types. Finally, there are task types. (Private types are described in chapter 7, task types are described in chapter 9, the other classes of types are described in this chapter.) Certain record and private types have special components called discriminants whose values distinguish alternative forms of values of one of these types. If a private type has discriminants, they are known to users of the type. Hence a private type is only known by its name, its discriminants if any, and by the corresponding set of operations. The set of possible values for an object of a given type can be subjected to a condition that is called a constraint (the case where the constraint imposes no restriction is also included); a value is said to satisfy a constraint if it satisfies the corresponding condition. A subtype is a type together with a constraint; a value is said to belong to a subtype of a given type if it belongs to the type and satisfies the constraint; the given type is called the base type of the subtype. A type is a subtype of itself; such a subtype is said to be unconstrained: it corresponds to a condition that imposes no restriction. The base type of a type is the type itself. The set of operations defined for a subtype of a given type includes the operations that are defined for the type; however the assignment operation to a variable having a given subtype only assigns values that belong to the subtype. Additional operations, such as qualification (in a qualified expression), are implicitly defined by a subtype declaration. Certain types have default initial values defined for objects of the type; certain other types have default expressions defined for some or all of their components. Certain operations of types and subtypes are called attributes; these operations are denoted by the form of name described in section 4.1.4. The term subcomponent is used in this manual in place of the term component to indicate either a component, or a component of another component or subcomponent. Where other subcomponents are excluded, the term component is used instead. A given type must not have a subcomponent whose type is the given type itself. The name of a class of types is used in this manual as a qualifier for objects and values that have a type of the class considered. For example, the term "array object" is used for an object whose type is an array type; similarly, the term "access value" is used for a value of an access type. Note: The set of values of a subtype is a subset of the values of the base type. This subset need not be a proper subset; it can be an empty subset. References: access type 3.8, array type 3.6, assignment 5.2, attribute 4.1.4, component of an array 3.6, component of a record 3.7, discriminant constraint 3.7.2, enumeration type 3.5.1, integer type 3.5.4, object 3.2.1, private type 7.4, qualified expression 4.7, real type 3.5.6, record type 3.7, subtype declaration 3.3.2, task type 9.1, type declaration 3.3.1 3.3.1 Type Declarations A type declaration declares a type. type_declaration ::= full_type_declaration | incomplete_type_declaration | private_type_declaration full_type_declaration ::= type identifier [discriminant_part] is type_definition; type_definition ::= enumeration_type_definition | integer_type_definition | real_type_definition | array_type_definition | record_type_definition | access_type_definition | derived_type_definition The elaboration of a full type declaration consists of the elaboration of the discriminant part, if any (except in the case of the full type declaration for an incomplete or private type declaration), and of the elaboration of the type definition. The types created by the elaboration of distinct type definitions are distinct types. Moreover, the elaboration of the type definition for a numeric or derived type creates both a base type and a subtype of the base type; the same holds for a constrained array definition (one of the two forms of array type definition). The simple name declared by a full type declaration denotes the declared type, unless the type declaration declares both a base type and a subtype of the base type, in which case the simple name denotes the subtype, and the base type is anonymous. A type is said to be anonymous if it has no simple name. For explanatory purposes, this reference manual 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. Examples of type definitions: (WHITE, RED, YELLOW, GREEN, BLUE, BROWN, BLACK) range1 .. 72 array(1 .. 10) of INTEGER Examples of type declarations: 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: Two type definitions always define two distinct types, even if they are textually identical. Thus, the array type definitions given in the declarations of A and B below define distinct types. A : array(1 .. 10) of BOOLEAN; B : array(1 .. 10) of BOOLEAN; If A and B are declared by a multiple object declaration as below, their types are nevertheless different, since the multiple object declaration is equivalent to the above two single object declarations. A, B : array(1 .. 10) of BOOLEAN; Incomplete type declarations are used for the definition of recursive and mutually dependent types (see 3.8.1). Private type declarations are used in package specifications and in generic parameter declarations (see 7.4 and 12.1). References: access type definition 3.8, array type definition 3.6, base type 3.3, constrained array definition 3.6, constrained subtype 3.3, declaration 3.1, derived type 3.4, derived type definition 3.4, discriminant part 3.7.1, elaboration 3.9, enumeration type definition 3.5.1, identifier 2.3, incomplete type declaration 3.8.1, integer type definition 3.5.4, multiple object declaration 3.2, numeric type 3.5, private type declaration 7.4, real type definition 3.5.6, reserved word 2.9, type 3.3 3.3.2 Subtype Declarations A subtype declaration declares a subtype. subtype_declaration ::= subtype identifier is subtype_indication; subtype_indication ::= type_mark [constraint] type_mark ::= type_name | subtype_name constraint ::= range_constraint | floating_point_constraint | fixed_point_constraint | index_constraint | discriminant_constraint A type mark denotes a type or a subtype. If a type mark is the name of a type, the type mark denotes this type and also the corresponding unconstrained subtype. The base type of a type mark is, by definition, the base type of the type or subtype denoted by the type mark. A subtype indication defines a subtype of the base type of the type mark. If an index constraint appears after a type mark in a subtype indication, the type mark must not already impose an index constraint. Likewise for a discriminant constraint, the type mark must not already impose a discriminant constraint. The elaboration of a subtype declaration consists of the elaboration of the subtype indication. The elaboration of a subtype indication creates a subtype. If the subtype indication does not include a constraint, the subtype is the same as that denoted by the type mark. The elaboration of a subtype indication that includes a constraint proceeds as follows: (a) The constraint is first elaborated. (b) A check is then made that the constraint is compatible with the type or subtype denoted by the type mark. The condition imposed by a constraint is the condition obtained after elaboration of the constraint. (The rules of constraint elaboration are such that the expressions and ranges of constraints are evaluated by the elaboration of these constraints.) The rules defining compatibility are given for each form of constraint in the appropriate section. 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. The exception CONSTRAINT_ERROR is raised if any check of compatibility fails. Examples of subtype declarations: subtype RAINBOW is COLOR range RED .. BLUE; -- see 3.3.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.3.1 subtype SQUARE is MATRIX(1 .. 10, 1 .. 10); -- see 3.6 subtype MALE is PERSON(SEX => M); -- see 3.8 Note: A subtype declaration does not define a new type. References: base type 3.3, compatibility of discriminant constraints 3.7.2, compatibility of fixed point constraints 3.5.9, compatibility of floating point constraints 3.5.7, compatibility of index constraints 3.6.1, compatibility of range constraints 3.5, constraint_error exception 11.1, declaration 3.1, discriminant 3.3, discriminant constraint 3.7.2, elaboration 3.9, evaluation 4.5, expression 4.4, floating point constraint 3.5.7, fixed point constraint 3.5.9, index constraint 3.6.1, range constraint 3.5, reserved word 2.9, subtype 3.3, type 3.3, type name 3.3.1, unconstrained subtype 3.3 3.3.3 Classification of Operations The set of operations of a type includes the explicitly declared subprograms that have a parameter or result of the type; such subprograms are necessarily declared after the type declaration. The remaining operations are each implicitly declared for a given type declaration, immediately after the type definition. These implicitly declared operations comprise the basic operations, the predefined operators (see 4.5), and enumeration literals. In the case of a derived type declaration, the implicitly declared operations include any derived subprograms. The operations implicitly declared for a given type declaration occur after the type declaration and before the next explicit declaration, if any. The implicit declarations of derived subprograms occur last. A basic operation is an operation that is inherent in one of the following: - An assignment (in assignment statements and initializations), an allocator, a membership test, or a short-circuit control form. - A selected component, an indexed component, or a slice. - A qualification (in qualified expressions), an explicit type conversion, or an implicit type conversion of a value of type universal_integer or universal_real to the corresponding value of another numeric type. - A numeric literal (for a universal type), the literal null (for an access type), a string literal, an aggregate, or an attribute. For every type or subtype T, the following attribute is defined: T'BASE The base type of T. This attribute is allowed only as the prefix of the name of another attribute: for example, T'BASE'FIRST. Note: Each literal is an operation whose evaluation yields the corresponding value (see 4.2). Likewise, an aggregate is an operation whose evaluation yields a value of a composite type (see 4.3). Some operations of a type operate on values of the type, for example, predefined operators and certain subprograms and attributes. The evaluation of some operations of a type returns a value of the type, for example, literals and certain functions, attributes, and predefined operators. Assignment is an operation that operates on an object and a value. The evaluation of the operation corresponding to a selected component, an indexed component, or a slice, yields the object or value denoted by this form of name. References: aggregate 4.3, allocator 4.8, assignment 5.2, attribute 4.1.4, character literal 2.5, composite type 3.3, conversion 4.6, derived subprogram 3.4, enumeration literal 3.5.1, formal parameter 6.1, function 6.5, indexed component 4.1.1, initial value 3.2.1, literal 4.2, membership test 4.5 4.5.2, null literal 3.8, numeric literal 2.4, numeric type 3.5, object 3.2.1, 6.1, predefined operator 4.5, qualified expression 4.7, selected component 4.1.3, short-circuit control form 4.5 4.5.1, slice 4.1.2, string literal 2.6, subprogram 6, subtype 3.3, type 3.3, type declaration 3.3.1, universal_integer type 3.5.4, universal_real type 3.5.6, universal type 4.1 4 3.4 Derived Types A derived type definition defines a new (base) type whose characteristics are derived from those of a parent type; the new type is called a derived type. A derived type definition further defines a derived subtype, which is a subtype of the derived type. derived_type_definition ::= new subtype_indication The subtype indication that occurs after the reserved word new defines the parent subtype. The parent type is the base type of the parent subtype. If a constraint exists for the parent subtype, a similar constraint exists for the derived subtype; the only difference is that for a range constraint, and likewise for a floating or fixed point constraint that includes a range constraint, the value of each bound is replaced by the corresponding value of the derived type. The characteristics of the derived type are defined as follows: - The derived type belongs to the same class of types as the parent type. The set of possible values for the derived type is a copy of the set of possible values for the parent type. If the parent type is composite, then the same components exist for the derived type, and the subtype of corresponding components is the same. - For each basic operation of the parent type, there is a corresponding basic operation of the derived type. Explicit type conversion of a value of the parent type into the corresponding value of the derived type is allowed and vice versa as explained in section 4.6. - For each enumeration literal or predefined operator of the parent type there is a corresponding operation for the derived type. - If the parent type is a task type, then for each entry of the parent type there is a corresponding entry for the derived type. - If a default expression exists for a component of an object having the parent type, then the same default expression is used for the corresponding component of an object having the derived type. - If the parent type is an access type, then the parent and the derived type share the same collection; there is a null access value for the derived type and it is the default initial value of that type. - If an explicit representation clause exists for the parent type and if this clause appears before the derived type definition, then there is a corresponding representation clause (an implicit one) for the derived type. - Certain subprograms that are operations of the parent type are said to be derivable. For each derivable subprogram of the parent type, there is a corresponding derived subprogram for the derived type. Two kinds of derivable subprograms exist. First, if the parent type is declared immediately within the visible part of a package, then a subprogram that is itself explicitly declared immediately within the visible part becomes derivable after the end of the visible part, if it is an operation of the parent type. (The explicit declaration is by a subprogram declaration, a renaming declaration, or a generic instantiation.) Second, if the parent type is itself a derived type, then any subprogram that has been derived by this parent type is further derivable, unless the parent type is declared in the visible part of a package and the derived subprogram is hidden by a derivable subprogram of the first kind. Each operation of the derived type is implicitly declared at the place of the derived type declaration. The implicit declarations of any derived subprograms occur last. The specification of a derived subprogram is obtained implicitly by systematic replacement of the parent type by the derived type in the specification of the derivable subprogram. Any subtype of the parent type is likewise replaced by a subtype of the derived type with a similar constraint (as for the transformation of a constraint of the parent subtype into the corresponding constraint of the derived subtype). Finally, any expression of the parent type is made to be the operand of a type conversion that yields a result of the derived type. Calling a derived subprogram is equivalent to calling the corresponding subprogram of the parent type, in which each actual parameter that is of the derived type is replaced by a type conversion of this actual parameter to the parent type (this means that a conversion to the parent type happens before the call for the modes in and in out; a reverse conversion to the derived type happens after the call for the modes in out and out, see 6.4.1). In addition, if the result of a called function is of the parent type, this result is converted to the derived type. If a derived or private type is declared immediately within the visible part of a package, then, within this visible part, this type must not be used as the parent type of a derived type definition. (For private types, see also section 7.4.1.) For the elaboration of a derived type definition, the subtype indication is first elaborated, the derived type is then created, and finally, the derived subtype is created. Examples: 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 type SPECIAL_KEY is new KEY_MANAGER.KEY; -- see 7.4.2 -- the derived subprograms have the following specifications: -- procedure GET_KEY(K : out SPECIAL_KEY); -- function "<"(X,Y : SPECIAL_KEY) return BOOLEAN; Notes: The rules of derivation of basic operations and enumeration literals imply that the notation for any literal or aggregate of the derived type is the same as for the parent type; such literals and aggregates are said to be overloaded. Similarly, it follows that the notation for denoting a component, a discriminant, an entry, a slice, or an attribute is the same for the derived type as for the parent type. Hiding of a derived subprogram is allowed even within the same declarative region (see 8.3). A derived subprogram hides a predefined operator that has the same parameter and result type profile (see 6.6). A generic subprogram declaration is not derivable since it declares a generic unit rather than a subprogram. On the other hand, an instantiation of a generic subprogram is a (nongeneric) subprogram, which is derivable if it satisfies the requirements for derivability of subprograms. 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 a representation clause is given for the parent type but appears after the derived type declaration, then no corresponding representation clause applies to the derived type; hence an explicit representation clause for such a derived type is allowed. For a derived subprogram, if a parameter belongs to the derived type, the subtype of this parameter need not have any value in common with the derived subtype. References: access value 3.8, actual parameter 6.4.1, aggregate 4.3, attribute 4.1.4, base type 3.3, basic operation 3.3.3, boolean type 3.5.3, bound of a range 3.5, class of type 3.3, collection 3.8, component 3.3, composite type 3.3, constraint 3.3, conversion 4.6, declaration 3.1, declarative region 8.1, default expression 3.2.1, default initial value for an access type 3.8, discriminant 3.3, elaboration 3.9, entry 9.5, enumeration literal 3.5.1, floating point constraint 3.5.7, fixed point constraint 3.5.9, formal parameter 6.1, function call 6.4, generic declaration 12.1, immediately within 8.1, implicit declaration 3.1, literal 4.2, mode 6.1, overloading 6.6 8.7, package 7, package specification 7.1, parameter association 6.4, predefined operator 4.5, private type 7.4, procedure 6, procedure call statement 6.4, range constraint 3.5, representation clause 13.1, reserved word 2.9, slice 4.1.2, subprogram 6, subprogram specification 6.1, subtype indication 3.3.2, subtype 3.3, type 3.3, type definition 3.3.1, visible part 7.2 3.5 Scalar Types Scalar types comprise enumeration types, integer types, and real types. Enumeration types and integer types are called discrete types; each value of a discrete type has a position number which is an integer value. Integer types and real types are called numeric types. All scalar types are ordered, that is, all relational operators are predefined for their values. range_constraint ::= range range range ::= range_attribute | simple_expression .. simple_expression A range specifies a subset of values of a scalar type. The range L .. R specifies the values from L to R inclusive if the relation L <= R is true. The values L and R are called the lower bound and upper bound of the range, respectively. A value V is said to satisfy a range constraint if it belongs to the range; the value V is said to belong to the range if the relations L <= V and V <= R are both TRUE. A null range is a range for which the relation R < L is TRUE; no value belongs to a null range. The operators <= and < in the above definitions are the predefined operators of the scalar type. If a range constraint is used in a subtype indication, either directly or as part of a floating or fixed point constraint, the type of the simple expressions (likewise, of the bounds of a range attribute) must be the same as the base type of the type mark of the subtype indication. A range constraint is compatible with a subtype if each bound of the range belongs to the subtype, or if the range constraint defines a null range; otherwise the range constraint is not compatible with the subtype. The elaboration of a range constraint consists of the evaluation of the range. The evaluation of a range defines its lower bound and its upper bound. If simple expressions are given to specify the bounds, the evaluation of the range evaluates these simple expressions in some order that is not defined by the language. Attributes For any scalar type T or for any subtype T of a scalar type, the following attributes are defined: T'FIRST Yields the lower bound of T. The value of this attribute has the same type as T. T'LAST Yields the upper bound of T. The value of this attribute has the same type as T. Note: Indexing and iteration rules use values of discrete types. References: attribute 4.1.4, constraint 3.3, enumeration type 3.5.1, erroneous 1.6, evaluation 4.5, fixed point constraint 3.5.9, floating point constraint 3.5.7, index 3.6, integer type 3.5.4, loop statement 5.5, range attribute 3.6.2, real type 3.5.6, relational operator 4.5 4.5.2, satisfy a constraint 3.3, simple expression 4.4, subtype indication 3.3.2, type mark 3.3.2 3.5.1 Enumeration Types An enumeration type definition defines an enumeration type. enumeration_type_definition ::= (enumeration_literal_specification {, enumeration_literal_specification}) enumeration_literal_specification ::= enumeration_literal enumeration_literal ::= identifier | character_literal The identifiers and character literals listed by an enumeration type definition must be distinct. Each enumeration literal specification is the declaration of the corresponding enumeration literal: this declaration is equivalent to the declaration of a parameterless function, the designator being the enumeration literal, and the result type being the enumeration type. The elaboration of an enumeration type definition creates an enumeration type; this elaboration includes that of every enumeration literal specification. Each enumeration literal yields a different enumeration value. The predefined order relations between enumeration values follow the order of corresponding position numbers. The position number of the value of the first listed enumeration literal is zero; the position number for each other enumeration literal is one more than for its predecessor in the list. If the same identifier or character literal is specified in more than one enumeration type definition, the corresponding 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 must be determinable from the context (see 8.7). Examples: 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 type HEXA is ('A', 'B', 'C', 'D', 'E', 'F'); type MIXED is ('A', 'B', '*', B, NONE, '?', '%'); 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 light Note: 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 8.7). References: character literal 2.5, declaration 3.1, designator 6.1, elaboration 3.9, 6.1, function 6.5, identifier 2.3, name 4.1, overloading 6.6 8.7, position number 3.5, qualified expression 4.7, relational operator 4.5 4.5.2, type 3.3, type definition 3.3.1 3.5.2 Character Types An enumeration type is said to be a character type if at least one of its enumeration literals is a character literal. The predefined type CHARACTER is a character type whose values are the 128 characters of the ASCII character set. Each of the 95 graphic characters of this character set is denoted by the corresponding character literal. Example: type ROMAN_DIGIT is ('I', 'V', 'X', 'L', 'C', 'D', 'M'); Notes: The predefined package ASCII includes the declaration of constants denoting control characters and of constants denoting graphic characters that are not in the basic character set. 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 section 13.3. References: ascii predefined package C, basic character 2.1, character literal 2.5, constant 3.2.1, declaration 3.1, enumeration type 3.5.1, graphic character 2.1, identifier 2.3, literal 4.2, predefined type C, type 3.3 3.5.3 Boolean Types There is a predefined enumeration type named BOOLEAN. It contains the two literals FALSE and TRUE ordered with the relation FALSE < TRUE. A boolean type is either the type BOOLEAN or a type that is derived, directly or indirectly, from a boolean type. References: derived type 3.4, enumeration literal 3.5.1, enumeration type 3.5.1, relational operator 4.5 4.5.2, type 3.3 3.5.4 Integer Types An integer type definition defines an integer type whose set of values includes at least those of the specified range. integer_type_definition ::= range_constraint If a range constraint is used as an integer type definition, each bound of the range must be defined by a static expression of some integer type, but the two bounds need not have the same integer type. (Negative bounds are allowed.) A type declaration of the form: type T is range L .. R; is, by definition, equivalent to the following declarations: type integer_type is new predefined_integer_type; subtype T is integer_type range integer_type(L) .. integer_type(R); where integer_type is an anonymous type, and where the predefined integer type is implicitly selected by the implementation, so as to contain the values L to R inclusive. The integer type declaration is illegal if none of the predefined integer types satisfies this requirement, excepting universal_integer. The elaboration of the declaration of an integer type consists of the elaboration of the equivalent type and subtype declarations. The predefined integer types include the type INTEGER. An implementation may also have predefined types such as SHORT_INTEGER and LONG_INTEGER, which have (substantially) shorter and longer ranges, respectively, than INTEGER. The range of each of these types must be symmetric about zero, excepting an extra negative value which may exist in some implementations. The base type of each of these types is the type itself. Integer literals are the literals of an anonymous predefined integer type that is called universal_integer in this reference manual. Other integer types have no literals. However, for each integer type there exists an implicit conversion that converts a universal_integer value into the corresponding value (if any) of the integer type. The circumstances under which these implicit conversions are invoked are described in section 4.6. The position number of an integer value is the corresponding value of the type universal_integer. The same arithmetic operators are predefined for all integer types (see 4.5). The exception NUMERIC_ERROR is raised by the execution of an operation (in particular an implicit conversion) that cannot deliver the correct result (that is, if the value corresponding to the mathematical result is not a value of the integer type). However, an implementation is not required to raise the exception NUMERIC_ERROR if the operation is part of a larger expression whose result can be computed correctly, as described in section 11.6. Examples: type PAGE_NUM is range 1 .. 2_ type LINE_SIZE is range 1 .. MAX_LINE_SIZE; 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; Notes: The name declared by an integer type declaration is a subtype name. On the other hand, the predefined operators of an integer type deliver results whose range is defined by the parent predefined type; such a result need not belong to the declared subtype, in which case an attempt to assign the result to a variable of the integer subtype raises the exception CONSTRAINT_ERROR. The smallest (most negative) value supported by the predefined integer types of an implementation is the named number SYSTEM.MIN_INT and the largest (most positive) value is SYSTEM.MAX_INT (see 13.7). References: anonymous type 3.3.1, belong to a subtype 3.3, bound of a range 3.5, constraint_error exception 11.1, conversion 4.6, identifier 2.3, integer literal 2.4, literal 4.2, numeric_error exception 11.1, parent type 3.4, predefined operator 4.5, range constraint 3.5, static expression 4.9, subtype declaration 3.3.2, system predefined package 13.7, type 3.3, type declaration 3.3.1, type definition 3.3.1, universal type 4.1 4 3.5.5 Operations of Discrete Types The basic operations of a discrete type include the operations involved in assignment, the membership tests, and qualification; for a boolean type they include the short-circuit control forms; for an integer type they include the explicit conversion of values of other numeric types to the integer type, and the implicit conversion of values of the type universal_integer to the type. Finally, for every discrete type or subtype T, the basic operations include the attributes listed below. In this presentation, T is referred to as being a subtype (the subtype T) for any property that depends on constraints imposed by T; other properties are stated in terms of the base type of T. The first group of attributes yield characteristics of the subtype T. This group includes the attribute BASE (see 3.3.2), the attributes FIRST and LAST (see 3.5), the representation attribute SIZE (see 13.7.2), and the attribute WIDTH defined as follows: T'WIDTH Yields the maximum image length over all values of the subtype T (the image is the sequence of characters returned by the attribute IMAGE, see below). Yields zero for a null range. The value of this attribute is of the type universal_integer. All attributes of the second group are functions with a single parameter. The corresponding actual parameter is indicated below by X. T'POS This attribute is a function. The parameter X must be a value of the base type of T. The result type is the type universal_integer. The result is the position number of the value of the parameter. T'VAL This attribute is a special function with a single parameter which can be of any integer type. The result type is the base type of T. The result is the value whose position number is the universal_integer value corresponding to X. The exception CONSTRAINT_ERROR is raised if the universal_integer value corresponding to X is not in the range T'POS(T'BASE'FIRST) .. T'POS(T'BASE'LAST). T'SUCC This attribute is a function. The parameter X must be a value of the base type of T. The result type is the base type of T. The result is the value whose position number is one greater than that of X. The exception CONSTRAINT_ERROR is raised if X equals T'BASE'LAST. T'PRED This attribute is a function. The parameter X must be a value of the base type of T. The result type is the base type of T. The result is the value whose position number is one less than that of X. The exception CONSTRAINT_ERROR is raised if X equals T'BASE'FIRST. T'IMAGE This attribute is a function. The parameter X must be a value of the base type of T. The result type is the predefined type STRING. The result is the image of the value of X, that is, a sequence of characters representing the value in display form. 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. The lower bound of the image is one. 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. The image of a character C, other than a graphic character, is implementation-defined; the only requirement is that the image must be such that C equals CHARACTER'VALUE(CHARACTER'IMAGE(C)). T'VALUE This attribute is a function. The parameter X must be a value of the predefined type STRING. The result type is the base type of T. Any leading and any trailing spaces of the sequence of characters that corresponds to the parameter are ignored. For an enumeration type, if the sequence of characters has the syntax of an enumeration literal and if this literal exists for the base type of T, the result is the corresponding enumeration value. For an integer type, if the sequence of characters has the syntax of an integer literal, with an optional single leading character that is a plus or minus sign, and if there is a corresponding value in the base type of T, the result is this value. In any other case, the exception CONSTRAINT_ERROR is raised. In addition, the attributes A'SIZE and A'ADDRESS are defined for an object A of a discrete type (see 13.7.2). Besides the basic operations, the operations of a discrete type include the predefined relational operators. For enumeration types, operations include enumeration literals. For boolean types, operations include the predefined unary logical negation operator not, and the predefined logical operators. For integer types, operations include the predefined arithmetic operators: these are the binary and unary adding operators - and +, all multiplying operators, the unary operator abs, and the exponentiating operator. The operations of a subtype are the corresponding operations of its base type except for the following: assignment, membership tests, qualification, explicit type conversions, and the attributes of the first group; the effect of each of these operations depends on the subtype (assignments, membership tests, qualifications, and conversions involve a subtype check; attributes of the first group yield a characteristic of the subtype). Notes: For a subtype of a discrete type, the results delivered by the attributes SUCC, PRED, VAL, and VALUE need not belong to the subtype; similarly, the actual parameters of the attributes POS, SUCC, PRED, and IMAGE need not belong to the subtype. The following relations are satisfied (in the absence of an exception) by these attributes: T'POS(T'SUCC(X)) = T'POS(X) + 1 T'POS(T'PRED(X)) = T'POS(X) - 1 T'VAL(T'POS(X)) = X T'POS(T'VAL(N)) = N Examples: -- For the types and subtypes declared in section 3.5.1 we have: -- COLOR'FIRST = WHITE, COLOR'LAST = BLACK -- RAINBOW'FIRST = RED, RAINBOW'LAST = BLUE -- COLOR'SUCC(BLUE) = RAINBOW'SUCC(BLUE) = BROWN -- COLOR'POS(BLUE) = RAINBOW'POS(BLUE) = 4 -- COLOR'VAL(0) = RAINBOW'VAL(0) = WHITE References: abs operator 4.5 4.5.6, assignment 5.2, attribute 4.1.4, base type 3.3, basic operation 3.3.3, binary adding operator 4.5 4.5.3, boolean type 3.5.3, bound of a range 3.5, character literal 2.5, constraint 3.3, constraint_error exception 11.1, conversion 4.6, discrete type 3.5, enumeration literal 3.5.1, exponentiating operator 4.5 4.5.6, function 6.5, graphic character 2.1, identifier 2.3, integer type 3.5.4, logical operator 4.5 4.5.1, membership test 4.5 4.5.2, multiplying operator 4.5 4.5.5, not operator 4.5 4.5.6, numeric literal 2.4, numeric type 3.5, object 3.2, operation 3.3, position number 3.5, predefined operator 4.5, predefined type C, qualified expression 4.7, relational operator 4.5 4.5.2, short-circuit control form 4.5 4.5.1, string type 3.6.3, subtype 3.3, type 3.3, unary adding operator 4.5 4.5.4, universal_integer type 3.5.4, universal type 4.1 4 3.5.6 Real Types 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. real_type_definition ::= floating_point_constraint | fixed_point_constraint A set of numbers called model numbers is associated with each real type. Error bounds on the predefined operations are given in terms of the model numbers. An implementation of the type must include at least these model numbers and represent them exactly. An implementation-dependent set of numbers, called the safe numbers, is also associated with each real type. The set of safe numbers of a real type must include at least the set of model numbers of the type. The range of safe numbers is allowed to be larger than the range of model numbers, but error bounds on the predefined operations for safe numbers are given by the same rules as for model numbers. Safe numbers therefore provide guaranteed error bounds for operations on an implementation-dependent range of numbers; in contrast, the range of model numbers depends only on the real type definition and is therefore independent of the implementation. Real literals are the literals of an anonymous predefined real type that is called universal_real in this reference manual. Other real types have no literals. However, for each real type, there exists an implicit conversion that converts a universal_real value into a value of the real type. The conditions under which these implicit conversions are invoked are described in section 4.6. If the universal_real value is a safe number, the implicit conversion delivers the corresponding value; if it belongs to the range of safe numbers but is not a safe number, then the converted value can be any value within the range defined by the safe numbers next above and below the universal_real value. The execution of an operation that yields a value of a real type may raise the exception NUMERIC_ERROR, as explained in section 4.5.7, if it cannot deliver a correct result (that is, if the value corresponding to one of the possible mathematical results does not belong to the range of safe numbers); in particular, this exception can be raised by an implicit conversion. However, an implementation is not required to raise the exception NUMERIC_ERROR if the operation is part of a larger expression whose result can be computed correctly (see 11.6). The elaboration of a real type definition includes the elaboration of the floating or fixed point constraint and creates a real type. Note: An algorithm written to rely only upon the minimum numerical properties guaranteed by the type definition for model numbers will be portable without further precautions. References: conversion 4.6, elaboration 3.9, fixed point constraint 3.5.9, floating point constraint 3.5.7, literal 4.2, numeric_error exception 11.1, predefined operation 3.3.3, real literal 2.4, type 3.3, type definition 3.3.1, universal type 4.10 3.5.7 Floating Point Types For floating point types, the error bound is specified as a relative precision by giving the required minimum number of significant decimal digits. floating_point_constraint ::= floating_accuracy_definition [range_constraint] floating_accuracy_definition ::= digits static_simple_expression The minimum number of significant decimal digits is specified by the value of the static simple expression of the floating accuracy definition. This value must belong to some integer type and must be positive (nonzero); it is denoted by D in the remainder of this section. If the floating point constraint is used as a real type definition and includes a range constraint, then each bound of the range must be defined by a static expression of some real type, but the two bounds need not have the same real type. For a given radix, the following canonical form is defined for any floating point model number other than zero: sign * mantissa * (radix ** exponent) In this form: sign is either +1 or -1; mantissa is expressed in a number base given by radix; and exponent is an integer number (possibly negative) such that the integer part of mantissa is zero and the first digit of its fractional part is not a zero. The specified number D is the minimum number of decimal digits required after the point in the decimal mantissa (that is, if radix is ten). The value of D in turn determines a corresponding number B that is the minimum number of binary digits required after the point in the binary mantissa (that is, if radix is two). The number B associated with D is the smallest value such that the relative precision of the binary form is no less than that specified for the decimal form. (The number B is the integer next above (D*log(10)/log(2)) + 1.) The model numbers defined by a floating accuracy definition comprise zero and all numbers whose binary canonical form has exactly B digits after the point in the mantissa and an exponent in the range -4*B .. +4*B. The guaranteed minimum accuracy of operations of a floating point type is defined in terms of the model numbers of the floating point constraint that forms the corresponding real type definition (see 4.5.7). The predefined floating point types include the type FLOAT. An implementation may also have predefined types such as SHORT_FLOAT and LONG_FLOAT, which have (substantially) less and more accuracy, respectively, than FLOAT. The base type of each predefined floating point type is the type itself. The model numbers of each predefined floating point type are defined in terms of the number D of decimal digits returned by the attribute DIGITS (see 3.5.8). For each predefined floating point type (consequently also for each type derived therefrom), a set of safe numbers is defined as follows. The safe numbers have the same number B of mantissa digits as the model numbers of the type and have an exponent in the range -E .. +E where E is implementation-defined and at least equal to the 4*B of model numbers. (Consequently, the safe numbers include the model numbers.) The rules defining the accuracy of operations with model and safe numbers are given in section 4.5.7. The safe numbers of a subtype are those of its base type. A floating point type declaration of one of the two forms (that is, with or without the optional range constraint indicated by the square brackets): type T is digits D [range L .. R]; is, by definition, equivalent to the following declarations: type floating_point_type is new predefined_floating_point_type; subtype T is floating_point_type digits D [range floating_point_type(L) .. floating_point_type(R)]; where floating_point_type is an anonymous type, and where the predefined floating point type is implicitly selected by the implementation so that its model numbers include the model numbers defined by D; furthermore, if a range L .. R is supplied, then both L and R must belong to the range of safe numbers. The floating point declaration is illegal if none of the predefined floating point types satisfies these requirements, excepting universal_real. The maximum number of digits that can be specified in a floating accuracy definition is given by the system-dependent named number SYSTEM.MAX_DIGITS (see 13.7.1). The elaboration of a floating point type declaration consists of the elaboration of the equivalent type and subtype declarations. If a floating point constraint follows a type mark in a subtype indication, the type mark must denote a floating point type or subtype. The floating point constraint is compatible with the type mark only if the number D specified in the floating accuracy definition is not greater than the corresponding number D for the type or subtype denoted by the type mark. Furthermore, if the floating point constraint includes a range constraint, the floating point constraint is compatible with the type mark only if the range constraint is, itself, compatible with the type mark. The elaboration of such a subtype indication includes the elaboration of the range constraint, if there is one; it creates a floating point subtype whose model numbers are defined by the corresponding floating accuracy definition. A value of a floating point type belongs to a floating point subtype if and only if it belongs to the range defined by the subtype. The same arithmetic operators are predefined for all floating point types (see 4.5). Notes: A range constraint is allowed in a floating point subtype indication, either directly after the type mark, or as part of a floating point constraint. In either case the bounds of the range must belong to the base type of the type mark (see 3.5). The imposition of a floating point constraint on a type mark in a subtype indication cannot reduce the allowed range of values unless it includes a range constraint (the range of model numbers that correspond to the specified number of digits can be smaller than the range of numbers of the type mark). A value that belongs to a floating point subtype need not be a model number of the subtype. Examples: type COEFFICIENT is digits 10 range -1.0 .. 1.0; type REAL is digits 8; type MASS is digits 7 range 0.0 .. 1.0E35; subtype SHORT_COEFF is COEFFICIENT digits 5; -- a subtype with less accuracy subtype PROBABILITY is REAL range 0.0 .. 1.0; -- a subtype with a smaller range Notes on the examples: The implemented accuracy for COEFFICIENT is that of a predefined type having at least 10 digits of precision. Consequently the specification of 5 digits of precision for the subtype SHORT_COEFF is allowed. The largest model number for the type MASS is approximately 1.27E30 and hence less than the specified upper bound (1.0E35). Consequently the declaration of this type is legal only if this upper bound is in the range of the safe numbers of a predefined floating point type having at least 7 digits of precision. References: anonymous type 3.3.1, arithmetic operator 3.5.5 4.5, based literal 2.4.2, belong to a subtype 3.3, bound of a range 3.5, compatible 3.3.2, derived type 3.4, digit 2.1, elaboration 3.1 3.9, error bound 3.5.6, exponent 2.4.1 integer type 3.5.4, model number 3.5.6, operation 3.3, predefined operator 4.5, predefined type C, range constraint 3.5, real type 3.5.6, real type definition 3.5.6, safe number 3.5.6, simple expression 4.4, static expression 4.9, subtype declaration 3.3.2, subtype indication 3.3.2, subtype 3.3, type 3.3, type declaration 3.3.1, type mark 3.3.2 3.5.8 Operations of Floating Point Types The basic operations of a floating point type include the operations involved in assignment, membership tests, qualification, the explicit conversion of values of other numeric types to the floating point type, and the implicit conversion of values of the type universal_real to the type. In addition, for every floating point type or subtype T, the basic operations include the attributes listed below. In this presentation, T is referred to as being a subtype (the subtype T) for any property that depends on constraints imposed by T; other properties are stated in terms of the base type of T. The first group of attributes yield characteristics of the subtype T. The attributes of this group are the attribute BASE (see 3.3.2), the attributes FIRST and LAST (see 3.5), the representation attribute SIZE (see 13.7.2), and the following attributes: T'DIGITS Yields the number of decimal digits in the decimal mantissa of model numbers of the subtype T. (This attribute yields the number D of section 3.5.7.) The value of this attribute is of the type universal_integer. T'MANTISSA Yields the number of binary digits in the binary mantissa of model numbers of the subtype T. (This attribute yields the number B of section 3.5.7.) The value of this attribute is of the type universal_integer. T'EPSILON Yields the absolute value of the difference between the model number 1.0 and the next model number above, for the subtype T. The value of this attribute is of the type universal_real. T'EMAX Yields the largest exponent value in the binary canonical form of model numbers of the subtype T. (This attribute yields the product 4*B of section 3.5.7.) The value of this attribute is of the type universal_integer. T'SMALL Yields the smallest positive (nonzero) model number of the subtype T. The value of this attribute is of the type universal_real. T'LARGE Yields the largest positive model number of the subtype T. The value of this attribute is of the type universal_real. The attributes of the second group include the following attributes which yield characteristics of the safe numbers: T'SAFE_EMAX Yields the largest exponent value in the binary canonical form of safe numbers of the base type of T. (This attribute yields the number E of section 3.5.7.) The value of this attribute is of the type universal_integer. T'SAFE_SMALL Yields the smallest positive (nonzero) safe number of the base type of T. The value of this attribute is of the type universal_real. T'SAFE_LARGE Yields the largest positive safe number of the base type of T. The value of this attribute is of the type universal_real. In addition, the attributes A'SIZE and A'ADDRESS are defined for an object A of a floating point type (see 13.7.2). Finally, for each floating point type there are machine-dependent attributes that are not related to model numbers and safe numbers. They correspond to the attribute designators MACHINE_RADIX, MACHINE_MANTISSA, MACHINE_EMAX, MACHINE_EMIN, MACHINE_ROUNDS, and MACHINE_OVERFLOWS (see 13.7.3). Besides the basic operations, the operations of a floating point type include the relational operators, and the following predefined arithmetic operators: the binary and unary adding operators - and +, the multiplying operators * and /, the unary operator abs, and the exponentiating operator. The operations of a subtype are the corresponding operations of the type except for the following: assignment, membership tests, qualification, explicit conversion, and the attributes of the first group; the effects of these operations are redefined in terms of the subtype. Notes: The attributes EMAX, SMALL, LARGE, and EPSILON are provided for convenience. They are all related to MANTISSA by the following formulas: T'EMAX = 4*T'MANTISSA T'EPSILON = 2.0**(1 - T'MANTISSA) T'SMALL = 2.0**(-T'EMAX - 1) T'LARGE = 2.0**T'EMAX * (1.0 - 2.0**(-T'MANTISSA)) The attribute MANTISSA, giving the number of binary digits in the mantissa, is itself related to DIGITS. The following relations hold between the characteristics of the model numbers and those of the safe numbers: T'BASE'EMAX <= T'SAFE_EMAX T'BASE'SMALL >= T'SAFE_SMALL T'BASE'LARGE <= T'SAFE_LARGE The attributes T'FIRST and T'LAST need not yield model or safe numbers. If a certain number of digits is specified in the declaration of a type or subtype T, the attribute T'DIGITS yields this number. References: abs operator 4.5 4.5.6, arithmetic operator 3.5.5 4.5, assignment 5.2, attribute 4.1.4, base type 3.3, basic operation 3.3.3, binary adding operator 4.5 4.5.3, bound of a range 3.5, constraint 3.3, conversion 4.6, digit 2.1, exponentiating operator 4.5 4.5.6, floating point type 3.5.7, membership test 4.5 4.5.2, model number 3.5.6, multiplying operator 4.5 4.5.5, numeric type 3.5, object 3.2, operation 3.3, predefined operator 4.5, qualified expression 4.7, relational operator 4.5 4.5.2, safe number 3.5.6, subtype 3.3, type 3.3, unary adding operator 4.5 4.5.4, universal type 4.10, universal_integer type 3.5.4, universal_real type 3.5.6 3.5.9 Fixed Point Types For fixed point types, the error bound is specified as an absolute value, called the delta of the fixed point type. fixed_point_constraint ::= fixed_accuracy_definition [range_constraint] fixed_accuracy_definition ::= delta static_simple_expression The delta is specified by the value of the static simple expression of the fixed accuracy definition. This value must belong to some real type and must be positive (nonzero). If the fixed point constraint is used as a real type definition, then it must include a range constraint; each bound of the specified range must be defined by a static expression of some real type but the two bounds need not have the same real type. If the fixed point constraint is used in a subtype indication, the range constraint is optional. A canonical form is defined for any fixed point model number other than zero. In this form: sign is either +1 or -1; mantissa is a positive (nonzero) integer; and any model number is a multiple of a certain positive real number called small, as follows: sign * mantissa * small For the model numbers defined by a fixed point constraint, the number small is chosen as the largest power of two that is not greater than the delta of the fixed accuracy definition. Alternatively, it is possible to specify the value of small by a length clause (see 13.2), in which case model numbers are multiples of the specified value. The guaranteed minimum accuracy of operations of a fixed point type is defined in terms of the model numbers of the fixed point constraint that forms the corresponding real type definition (see 4.5.7). For a fixed point constraint that includes a range constraint, the model numbers comprise zero and all multiples of small whose mantissa can be expressed using exactly B binary digits, where the value of B is chosen as the smallest integer number for which each bound of the specified range is either a model number or lies at most small distant from a model number. For a fixed point constraint that does not include a range constraint (this is only allowed after a type mark, in a subtype indication), the model numbers are defined by the delta of the fixed accuracy definition and by the range of the subtype denoted by the type mark. An implementation must have at least one anonymous predefined fixed point type. The base type of each such fixed point type is the type itself. The model numbers of each predefined fixed point type comprise zero and all numbers for which mantissa (in the canonical form) has the number of binary digits returned by the attribute MANTISSA, and for which the number small has the value returned by the attribute SMALL. A fixed point type declaration of the form: type T is delta D range L .. R; is, by definition, equivalent to the following declarations: type fixed_point_type is new predefined_fixed_point_type; subtype T is fixed_point_type range fixed_point_type(L) .. fixed_point_type(R); In these declarations, fixed_point_type is an anonymous type, and the predefined fixed point type is implicitly selected by the implementation so that its model numbers include the model numbers defined by the fixed point constraint (that is, by D, L, and R, and possibly by a length clause specifying small). The fixed point declaration is illegal if no predefined type satisfies these requirements. The safe numbers of a fixed point type are the model numbers of its base type. The elaboration of a fixed point type declaration consists of the elaboration of the equivalent type and subtype declarations. If the fixed point constraint follows a type mark in a subtype indication, the type mark must denote a fixed point type or subtype. The fixed point constraint is compatible with the type mark only if the delta specified by the fixed accuracy definition is not smaller than the delta for the type or subtype denoted by the type mark. Furthermore, if the fixed point constraint includes a range constraint, the fixed point constraint is compatible with the type mark only if the range constraint is, itself, compatible with the type mark. The elaboration of such a subtype indication includes the elaboration of the range constraint, if there is one; it creates a fixed point subtype whose model numbers are defined by the corresponding fixed point constraint and also by the length clause specifying small, if there is one. A value of a fixed point type belongs to a fixed point subtype if and only if it belongs to the range defined by the subtype. The same arithmetic operators are predefined for all fixed point types (see 4.5). Multiplication and division of fixed point values deliver results of an anonymous predefined fixed point type that is called universal_fixed in this reference manual; the accuracy of this type is arbitrarily fine. The values of this type must be converted explicitly to some numeric type. Notes: If S is a subtype of a fixed point type or subtype T, then the set of model numbers of S is a subset of those of T. If a length clause has been given for T, then both S and T have the same value for small. Otherwise, since small is a power of two, the small of S is equal to the small of T multiplied by a nonnegative power of two. A range constraint is allowed in a fixed point subtype indication, either directly after the type mark, or as part of a fixed point constraint. In either case the bounds of the range must belong to the base type of the type mark (see 3.5). Examples: type VOLT is delta 0.125 range 0.0 .. 255.0; subtype ROUGH_VOLTAGE is VOLT delta 1.0; -- same range as VOLT -- A pure fraction which requires all the available space in a word -- on a two's complement machine can be declared as the type FRACTION: DEL : constant := 1.0/2**(WORD_LENGTH - 1); type FRACTION is delta DEL range -1.0 .. 1.0 - DEL; References: anonymous type 3.3.1, arithmetic operator 3.5.5 4.5, base type 3.3, belong to a subtype 3.3, bound of a range 3.5, compatible 3.3.2, conversion 4.6, elaboration 3.9, error bound 3.5.6, length clause 13.2, model number 3.5.6, numeric type 3.5, operation 3.3, predefined operator 4.5, range constraint 3.5, real type 3.5.6, real type definition 3.5.6, safe number 3.5.6, simple expression 4.4, static expression 4.9, subtype 3.3, subtype declaration 3.3.2, subtype indication 3.3.2, type 3.3, type declaration 3.3.1, type mark 3.3.2 3.5.10 Operations of Fixed Point Types The basic operations of a fixed point type include the operations involved in assignment, membership tests, qualification, the explicit conversion of values of other numeric types to the fixed point type, and the implicit conversion of values of the type universal_real to the type. In addition, for every fixed point type or subtype T the basic operations include the attributes listed below. In this presentation T is referred to as being a subtype (the subtype T) for any property that depends on constraints imposed by T; other properties are stated in terms of the base type of T. The first group of attributes yield characteristics of the subtype T. The attributes of this group are the attributes BASE (see 3.3.2), the attributes FIRST and LAST (see 3.5), the representation attribute SIZE (see 13.7.2) and the following attributes: T'DELTA Yields the value of the delta specified in the fixed accuracy definition for the subtype T. The value of this attribute is of the type universal_real. T'MANTISSA Yields the number of binary digits in the mantissa of model numbers of the subtype T. (This attribute yields the number B of section 3.5.9.) The value of this attribute is of the type universal_integer. T'SMALL Yields the smallest positive (nonzero) model number of the subtype T. The value of this attribute is of the type universal_real. T'LARGE Yields the largest positive model number of the subtype T. The value of this attribute is of the type universal_real. T'FORE Yields the minimum number of characters needed for the integer part of the decimal representation of any value of the subtype T, 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 two.) The value of this attribute is of the type universal_integer. T'AFT Yields the number of decimal digits needed after the point to accommodate the precision of the subtype T, unless the delta of the subtype T is greater than 0.1, in which case the attribute yields the value one. (T'AFT is the smallest positive integer N for which (10**N)*T'DELTA is greater than or equal to one.) The value of this attribute is of the type universal_integer. The attributes of the second group include the following attributes which yield characteristics of the safe numbers: T'SAFE_SMALL Yields the smallest positive (nonzero) safe number of the base type of T. The value of this attribute is of the type universal_real. T'SAFE_LARGE Yields the largest positive safe number of the base type of T. The value of this attribute is of the type universal_real. In addition, the attributes A'SIZE and A'ADDRESS are defined for an object A of a fixed point type (see 13.7.2). Finally, for each fixed point type or subtype T, there are the machine-dependent attributes T'MACHINE_ROUNDS and T'MACHINE_OVERFLOWS (see 13.7.3). Besides the basic operations, the operations of a fixed point type include the relational operators, and the following predefined arithmetic operators: the binary and unary adding operators - and +, the multiplying operators * and /, and the operator abs. The operations of a subtype are the corresponding operations of the type except for the following: assignment, membership tests, qualification, explicit conversion, and the attributes of the first group; the effects of these operations are redefined in terms of the subtype. Notes: The value of the attribute T'FORE depends only on the range of the subtype T. The value of the attribute T'AFT depends only on the value of T'DELTA. The following relations exist between attributes of a fixed point type: T'LARGE = (2**T'MANTISSA - 1) * T'SMALL T'SAFE_LARGE = T'BASE'LARGE T'SAFE_SMALL = T'BASE'SMALL References: abs operator 4.5 4.5.6, arithmetic operator 3.5.5 4.5, assignment 5.2, base type 3.3, basic operation 3.3.3, binary adding operator 4.5 4.5.3, bound of a range 3.5, conversion 4.6, delta 3.5.9, fixed point type 3.5.9, membership test 4.5 4.5.2, model number 3.5.6, multiplying operator 4.5 4.5.5, numeric type 3.5, object 3.2, operation 3.3, qualified expression 4.7, relational operator 4.5 4.5.2, safe number 3.5.6, subtype 3.3, unary adding operator 4.5 4.5.4, universal_integer type 3.5.4, universal_real type 3.5.6 3.6 Array Types An array object is a composite object consisting of components that 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 its components. array_type_definition ::= unconstrained_array_definition | constrained_array_definition unconstrained_array_definition ::= array(index_subtype_definition {, index_subtype_definition}) of component_subtype_indication constrained_array_definition ::= array index_constraint of component_subtype_indication index_subtype_definition ::= type_mark range <> index_constraint ::= (discrete_range {, discrete_range}) discrete_range ::= discrete_subtype_indication | range An array object 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 type and possible constraint of the components. The order of the indices is significant. 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; this range of values is called the index range. An unconstrained array definition defines an array type. For each object that has the 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, except for null arrays as explained in section 3.6.1. The index subtype for a given index position is, by definition, the subtype denoted by the type mark of the corresponding index subtype definition. 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). The elaboration of an unconstrained array definition creates an array type; this elaboration includes that of the component subtype indication. A constrained array definition defines both an array type and a subtype of this type: - The array type is an implicitly declared anonymous type; this type is defined by an (implicit) unconstrained array definition, in which the component subtype indication is that of the constrained array definition, and in which the type mark of each index subtype definition denotes the subtype defined by the corresponding discrete range. - The array subtype is the subtype obtained by imposition of the index constraint on the array type. If a constrained array definition is given for a type declaration, the simple name declared by this declaration denotes the array subtype. The elaboration of a constrained array definition creates the corresponding array type and array subtype. For this elaboration, the index constraint and the component subtype indication are elaborated. The evaluation of each discrete range of the index constraint and the elaboration of the component subtype indication are performed in some order that is not defined by the language. Examples of type declarations with unconstrained array definitions: 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; Examples of type declarations with constrained array definitions: 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; Examples of object declarations with constrained array definitions: GRID : array(1 .. 80, 1 .. 100) of BOOLEAN; MIX : array(COLOR range RED .. GREEN) of BOOLEAN; PAGE : array(1 .. 50) of LINE; -- an array of arrays Note: For a one-dimensional array, the rule given means that a type declaration with a constrained array definition such as type T is array(POSITIVE range MIN .. MAX) of COMPONENT; is equivalent (in the absence of an incorrect order dependence) to the succession of declarations subtype index_subtype is POSITIVE range MIN .. MAX; type array_type is array(index_subtype range <>) of COMPONENT; subtype T is array_type (index_subtype); where index_subtype and array_type are both anonymous. Consequently, T is the name of a subtype and all objects declared with this type mark are arrays that have the same bounds. Similar transformations apply to multidimensional arrays. A similar transformation applies to an object whose declaration includes a constrained array definition. A consequence of this is that no two such objects have the same type. References: anonymous type 3.3.1, bound of a range 3.5, component 3.3, constraint 3.3, discrete type 3.5, elaboration 3.1 3.9, in some order 1.6, name 4.1, object 3.2, range 3.5, subtype 3.3, subtype indication 3.3.2, type 3.3, type declaration 3.3.1, type definition 3.3.1, type mark 3.3.2 3.6.1 Index Constraints and Discrete Ranges An index constraint determines the range of possible values for every index of an array type, and thereby the corresponding array bounds. For a discrete range used in a constrained array definition and defined by a range, an implicit conversion to the predefined type INTEGER is assumed if each bound is either a numeric literal, a named number, or an attribute, and the type of both bounds (prior to the implicit conversion) is the type universal_integer. Otherwise, both bounds must be of the same discrete type, other than universal_integer; this type must be determinable independently of the context, but using the fact that the type must be discrete and that both bounds must have the same type. These rules apply also to a discrete range used in an iteration rule (see 5.5) or in the declaration of a family of entries (see 9.5). If an index constraint follows a type mark in a subtype indication, then the type or subtype denoted by the type mark must not already impose an index constraint. The type mark must denote either an unconstrained array type or an access type whose designated type is such an array type. In either case, the index constraint must provide a discrete range for each index of the array type and the type of each discrete range must be the same as that of the corresponding index. An index constraint is compatible with the type denoted by the type mark if and only if the constraint defined by each discrete range is compatible with the corresponding index subtype. If any of the discrete ranges defines a null range, any array thus constrained is a null array, having no components. An array value satisfies an index constraint if at each index position the array value and the index constraint have the same index bounds. (Note, however, that assignment and certain other operations on arrays involve an implicit subtype conversion.) The bounds of each array object are determined as follows: - For a variable declared by an object declaration, the subtype indication of the corresponding object declaration must define a constrained array subtype (and, thereby, the bounds). The same requirement exists for the subtype indication of a component declaration, if the type of the record component is an array type; and for the component subtype indication of an array type definition, if the type of the array components is itself an array type. - For a constant declared by an object declaration, the bounds of the constant are defined by the initial value if the subtype of the constant is unconstrained; they are otherwise defined by this subtype (in the latter case, the initial value is the result of an implicit subtype conversion). The same rule applies to a generic formal parameter of mode in. - For an array object designated by an access value, the bounds must be defined by the allocator that creates the array object. (The allocated object is constrained with the corresponding values of the bounds.) - For a formal parameter of a subprogram or entry, the bounds are obtained from the corresponding actual parameter. (The formal parameter is constrained with the corresponding values of the bounds.) - For a renaming declaration and for a generic formal parameter of mode in out, the bounds are those of the renamed object or of the corresponding generic actual parameter. For the elaboration of an index constraint, the discrete ranges are evaluated in some order that is not defined by the language. Examples of array declarations including an index constraint: 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 FILTER : BIT_VECTOR(0 .. 31); Example of array declaration with a constrained array subtype: MY_SCHEDULE : SCHEDULE; -- all arrays of type SCHEDULE have the same bounds Example of record type with a component that is an array: type VAR_LINE(LENGTH : INTEGER) is record IMAGE : STRING(1 .. LENGTH); end record; NULL_LINE : VAR_LINE(0); -- NULL_LINE.IMAGE is a null array Notes: The elaboration of a subtype indication consisting of a type mark followed by an index constraint checks the compatibility of the index constraint with the type mark (see 3.3.2). 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. References: access type 3.8, access type definition 3.8, access value 3.8, actual parameter 6.4.1, allocator 4.8, array bound 3.6, array component 3.6, array type 3.6, array type definition 3.6, bound of a range 3.5, compatible 3.3.2, component declaration 3.7, constant 3.2.1, constrained array definition 3.6, constrained array subtype 3.6, conversion 4.6, designate 3.8, designated type 3.8, discrete range 3.6, entry 9.5, entry family declaration 9.5, expression 4.4, formal parameter 6.1, function 6.5, generic actual parameter 12.3, generic formal parameter 12.1 12.3, generic parameter 12.1, index 3.6, index constraint 3.6.1, index subtype 3.6, initial value 3.2.1, integer literal 2.4, integer type 3.5.4, iteration rule 5.5, mode 12.1.1, name 4.1, null range 3.5, object 3.2, object declaration 3.2.1, predefined type C, range 3.5, record component 3.7, renaming declaration 8.5, result subtype 6.1, satisfy 3.3, subprogram 6, subtype conversion 4.6, subtype indication 3.3.2, type mark 3.3.2, unconstrained array type 3.6, unconstrained subtype 3.3, universal type 4.10, universal_integer type 3.5.4, variable 3.2.1 3.6.2 Operations of Array Types The basic operations of an array type include the operations involved in assignment and aggregates (unless the array type is limited), membership tests, indexed components, qualification, and explicit conversion; for one-dimensional arrays the basic operations also include the operations involved in slices, and also string literals if the component type is a character type. If A is an array object, an array value, or a constrained array subtype, the basic operations also include the attributes listed below. These attributes are not allowed for an unconstrained array type. The argument N used in the attribute designators for the N-th dimension of an array must be a static expression of type universal_integer. The value of N must be positive (nonzero) and no greater than the dimensionality of the array. A'FIRST Yields the lower bound of the first index range. The value of this attribute has the same type as this lower bound. A'FIRST(N) Yields the lower bound of the N-th index range. The value of this attribute has the same type as this lower bound. A'LAST Yields the upper bound of the first index range. The value of this attribute has the same type as this upper bound. A'LAST(N) Yields the upper bound of the N-th index range. The value of this attribute has the same type as this upper bound. A'RANGE Yields the first index range, that is, the range A'FIRST .. A'LAST. A'RANGE(N) Yields the N-th index range, that is, the range A'FIRST(N) .. A'LAST(N). A'LENGTH Yields the number of values of the first index range (zero for a null range). The value of this attribute is of the type universal_integer. A'LENGTH(N) Yields the number of values of the N-th index range (zero for a null range). The value of this attribute is of the type universal_integer. In addition, the attribute T'BASE is defined for an array type or subtype T (see 3.3.3); the attribute T'SIZE is defined for an array type or subtype T, and the attributes A'SIZE and A'ADDRESS are defined for an array object A (see 13.7.2). Besides the basic operations, the operations of an array type include the predefined comparison for equality and inequality, unless the array type is limited. For one-dimensional arrays, the operations include catenation, unless the array type is limited; if the component type is a discrete type, the operations also include all predefined relational operators; if the component type is a boolean type, then the operations also include the unary logical negation operator not, and the logical operators. Examples (using arrays declared in the examples of section 3.6.1): -- FILTER'FIRST = 0 FILTER'LAST = 31 FILTER'LENGTH = 32 -- RECTANGLE'LAST(1) = 20 RECTANGLE'LAST(2) = 30 Notes: The attributes A'FIRST and A'FIRST(1) yield the same value. A similar relation exists for the attributes A'LAST, A'RANGE, and A'LENGTH. The following relations are satisfied (except for a null array) by the above attributes if the index type is an integer type: A'LENGTH = A'LAST - A'FIRST + 1 A'LENGTH(N) = A'LAST(N) - A'FIRST(N) + 1 An array type is limited if its component type is limited (see 7.4.4). References: aggregate 4.3, array type 3.6, assignment 5.2, attribute 4.1.4, basic operation 3.3.3, bound of a range 3.5, catenation operator 4.5 4.5.3, character type 3.5.2, constrained array subtype 3.6, conversion 4.6, designator 6.1, dimension 3.6, index 3.6, indexed component 4.1.1, limited type 7.4.4, logical operator 4.5 4.5.1, membership test 4.5 4.5.2, not operator 4.5 4.5.6, null range 3.5, object 3.2, operation 3.3, predefined operator 4.5, qualified expression 4.7, relational operator 4.5 4.5.2, slice 4.1.2, static expression 4.9, string literal 2.6, subcomponent 3.3, type 3.3, unconstrained array type 3.6, universal type 4.10, universal_integer type 3.5.4 3.6.3 The Type String The values of the predefined type STRING are one-dimensional arrays of the predefined type CHARACTER, indexed by values of the predefined subtype POSITIVE: subtype POSITIVE is INTEGER range 1 .. INTEGER'LAST; type STRING is array(POSITIVE range <>) of CHARACTER; Examples: STARS : STRING(1 .. 120) := (1 .. 120 => '*' ); QUESTION : constant STRING := "HOW MANY CHARACTERS?"; -- QUESTION'FIRST = 1, QUESTION'LAST = 20 (the number of characters) ASK_TWICE : constant STRING := QUESTION & QUESTION; NINETY_SIX : constant ROMAN := "XCVI"; -- see 3.6 Notes: String literals (see 2.6 and 4.2) are basic operations applicable to the type STRING and to any other one-dimensional array type whose component type is a character type. The catenation operator is a predefined operator for the type STRING and for one-dimensional array types; it is represented as &. The relational operators <, <=, >, and >= are defined for values of these types, and correspond to lexicographic order (see 4.5.2). References: aggregate 4.3, array 3.6, catenation operator 4.5 4.5.3, character type 3.5.2, component type (of an array) 3.6, dimension 3.6, index 3.6, lexicographic order 4.5.2, positional aggregate 4.3, predefined operator 4.5, predefined type C, relational operator 4.5 4.5.2, string literal 2.6, subtype 3.3, type 3.3 3.7 Record Types 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 its components. record_type_definition ::= record component_list end record component_list ::= component_declaration {component_declaration} | {component_declaration} variant_part | null; component_declaration ::= identifier_list : component_subtype_definition [:= expression]; component_subtype_definition ::= subtype_indication 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 must be distinct. The use of a name that denotes a record component other than a discriminant is not allowed within the record type definition that declares the component. A component declaration with several identifiers is equivalent to a sequence of single component declarations, as explained in section 3.2. Each single component declaration declares a record component whose subtype is specified by the component subtype definition. If a component declaration includes the assignment compound delimiter followed by an expression, the expression is the default expression of the record component; the default expression must be of the type of the component. Default expressions are not allowed for components that are of a limited type. If a record type does not have a discriminant part, the same components are present in all values of the type. If the component list of a record type is defined by the reserved word null and there is no discriminant part, then the record type has no components and all records of the type are null records. The elaboration of a record type definition creates a record type; it consists of the elaboration of any corresponding (single) component declarations, in the order in which they appear, including any component declaration in a variant part. The elaboration of a component declaration consists of the elaboration of the component subtype definition. For the elaboration of a component subtype definition, if the constraint does not depend on a discriminant (see 3.7.1), then the subtype indication is elaborated. If, on the other hand, the constraint depends on a discriminant, then the elaboration consists of the evaluation of any included expression that is not a discriminant. Examples of record type declarations: type DATE is record DAY : INTEGER range 1 .. 31; MONTH : MONTH_NAME; YEAR : INTEGER range 0 .. 4000; end record; type COMPLEX is record RE : REAL := 0.0; IM : REAL := 0.0; end record; Examples of record variables: TOMORROW, YESTERDAY : DATE; A, B, C : COMPLEX; -- both components of A, B, and C are implicitly initialized to zero Notes: The default expression of a record component is implicitly evaluated by the elaboration of the declaration of a record object, in the absence of an explicit initialization (see 3.2.1). If a component declaration has several identifiers, the expression is evaluated once for each such component of the object (since the declaration is equivalent to a sequence of single component declarations). Unlike the components of an array, the components of a record need not be of the same type. References: assignment compound delimiter 2.2, component 3.3, composite value 3.3, constraint 3.3, declaration 3.1, depend on a discriminant 3.7.1, discriminant 3.3, discriminant part 3.7 3.7.1, elaboration 3.9, expression 4.4, identifier 2.3, identifier list 3.2, limited type 7.4.4, name 4.1, object 3.2, subtype 3.3, type 3.3, type mark 3.3.2, variant part 3.7.3 3.7.1 Discriminants A discriminant part specifies the discriminants of a type. A discriminant of a record is a component of the record. The type of a discriminant must be discrete. discriminant_part ::= (discriminant_specification {; discriminant_specification}) discriminant_specification ::= identifier_list : type_mark [:= expression] A discriminant part is only allowed in the type declaration for a record type, in a private type declaration or an incomplete type declaration (the corresponding full declaration must then declare a record type), and in the generic parameter declaration for a formal private type. A discriminant specification with several identifiers is equivalent to a sequence of single discriminant specifications, as explained in section 3.2. Each single discriminant specification declares a discriminant. If a discriminant specification includes the assignment compound delimiter followed by an expression, the expression is the default expression of the discriminant; the default expression must be of the type of the discriminant. Default expressions must be provided either for all or for none of the discriminants of a discriminant part. The use of the name of a discriminant is not allowed in default expressions of a discriminant part if the specification of the discriminant is itself given in the discriminant part. Within a record type definition the only allowed uses of the name of a discriminant of the record type are: in the default expressions for record components; in a variant part as the discriminant name; and in a component subtype definition, either as a bound in an index constraint, or to specify a discriminant value in a discriminant constraint. A discriminant name used in these component subtype definitions must appear by itself, not as part of a larger expression. Such component subtype definitions and such constraints are said to depend on a discriminant. A component is said to depend on a discriminant if it is a record component declared in a variant part, or a record component whose component subtype definition depends on a discriminant, or finally, one of the subcomponents of a component that itself depends on a discriminant. Each record value includes a value for each discriminant specified for the record type; it also includes a value for each record component that does not depend on a discriminant. The values of the discriminants determine which other component values are in the record value. Direct assignment to a discriminant of an object is not allowed; furthermore a discriminant is not allowed as an actual parameter of mode in out or out, or as a generic actual parameter of mode in out. The only allowed way to change the value of a discriminant of a variable is to assign a (complete) value to the variable itself. Similarly, an assignment to the variable itself is the only allowed way to change the constraint of one of its components, if the component subtype definition depends on a discriminant of the variable. The elaboration of a discriminant part has no other effect. Examples: type BUFFER(SIZE : BUFFER_SIZE := 100) is -- see 3.5.4 record POS : BUFFER_SIZE := 0; VALUE : STRING(1 .. SIZE); end record; type SQUARE(SIDE : INTEGER) is record MAT : MATRIX(1 .. SIDE, 1 .. SIDE); -- see 3.6 end record; type DOUBLE_SQUARE(NUMBER : INTEGER) is record LEFT : SQUARE(NUMBER); RIGHT : SQUARE(NUMBER); end record; type ITEM(NUMBER : POSITIVE) is record CONTENT : INTEGER; -- no component depends on the discriminant end record; References: assignment 5.2, assignment compound delimiter 2.2, bound of a range 3.5, component 3.3, component declaration 3.7, component of a record 3.7, declaration 3.1, discrete type 3.5, discriminant 3.3, discriminant constraint 3.7.2, elaboration 3.9, expression 4.4, generic formal type 12.1, generic parameter declaration 12.1, identifier 2.3, identifier list 3.2, incomplete type declaration 3.8.1, index constraint 3.6.1, name 4.1, object 3.2, private type 7.4, private type declaration 7.4, record type 3.7, scope 8.2, simple name 4.1, subcomponent 3.3, subtype indication 3.3.2, type declaration 3.3.1, type mark 3.3.2, variant part 3.7.3 3.7.2 Discriminant Constraints A discriminant constraint is only allowed in a subtype indication, after a type mark. This type mark must denote either a type with discriminants, or an access type whose designated type is a type with discriminants. A discriminant constraint specifies the values of these discriminants. discriminant_constraint ::= (discriminant_association {, discriminant_association}) discriminant_association ::= [discriminant_simple_name {| discriminant_simple_name} =>] expression Each discriminant association associates an expression with one or more discriminants. A discriminant association is said to be named if the discriminants are specified explicitly by their names; it is otherwise said to be positional. For a positional association, the (single) discriminant is implicitly specified by position, in textual order. Named associations can be given in any order, but if both positional and named associations are used in the same discriminant constraint, then positional associations must occur first, at their normal position. Hence once a named association is used, the rest of the discriminant constraint must use only named associations. For a named discriminant association, the discriminant names must denote discriminants of the type for which the discriminant constraint is given. A discriminant association with more than one discriminant name is only allowed if the named discriminants are all of the same type. Furthermore, for each discriminant association (whether named or positional), the expression and the associated discriminants must have the same type. A discriminant constraint must provide exactly one value for each discriminant of the type. A discriminant constraint is compatible with the type denoted by a type mark, if and only if each discriminant value belongs to the subtype of the corresponding discriminant. In addition, for each subcomponent whose component subtype specification depends on a discriminant, the discriminant value is substituted for the discriminant in this component subtype specification and the compatibility of the resulting subtype indication is checked. 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. The initial values of the discriminants of an object of a type with discriminants are determined as follows: - For a variable declared by an object declaration, the subtype indication of the corresponding object declaration must impose a discriminant constraint unless default expressions exist for the discriminants; the discriminant values are defined either by the constraint or, in its absence, by the default expressions. The same requirement exists for the subtype indication of a component declaration, if the type of the record component has discriminants; and for the component subtype indication of an array type, if the type of the array components is a type with discriminants. - For a constant declared by an object declaration, the values of the discriminants are those of the initial value if the subtype of the constant is unconstrained; they are otherwise defined by this subtype (in the latter case, an exception is raised if the initial value does not belong to this subtype). The same rule applies to a generic parameter of mode in. - For an object designated by an access value, the discriminant values must be defined by the allocator that creates the object. (The allocated object is constrained with the corresponding discriminant values.) - For a formal parameter of a subprogram or entry, the discriminants of the formal parameter are initialized with those of the corresponding actual parameter. (The formal parameter is constrained if the corresponding actual parameter is constrained, and in any case if the mode is in or if the subtype of the formal parameter is constrained.) - For a renaming declaration and for a generic formal parameter of mode in out, the discriminants are those of the renamed object or of the corresponding generic actual parameter. For the elaboration of a discriminant constraint, the expressions given in the discriminant associations are evaluated in some order that is not defined by the language; the expression of a named association is evaluated once for each named discriminant. Examples (using types declared in the previous section): 01 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 must be constrained Note: The above rules and the rules defining the elaboration of an object declaration (see 3.2) ensure that discriminants always have a value. In particular, if a discriminant constraint is imposed on an object declaration, each discriminant is initialized with the value specified by the constraint. Similarly, if the subtype of a component has a discriminant constraint, the discriminants of the component are correspondingly initialized. References: access type 3.8, access type definition 3.8, access value 3.8, actual parameter 6.4.1, allocator 4.8, array type definition 3.6, bound of a range 3.5, compatible 3.3.2, component 3.3, component declaration 3.7, component subtype indication 3.7, composite value 3.3, constant 3.2.1, constrained subtype 3.3, constraint 3.3, declaration 3.1, default expression for a discriminant 3.7, depend on a discriminant 3.7.1, designate 3.8, designated type 3.8, discriminant 3.3, elaboration 3.9, entry 9.5, evaluation 4.5, expression 4.4, formal parameter 6.1, generic actual parameter 12.3, generic formal parameter 12.1 12.3, mode in 6.1, mode in out 6.1, name 4.1, object 3.2, object declaration 3.2.1, renaming declaration 8.5, reserved word 2.9, satisfy 3.3, simple name 4.1, subcomponent 3.3, subprogram 6, subtype 3.3, subtype indication 3.3.2, type 3.3, type mark 3.3.2, variable 3.2.1 3.7.3 Variant Parts A record type with a variant part specifies alternative lists of components. Each variant defines the components for the corresponding value or values of the discriminant. variant_part ::= case discriminant_simple_name is variant {variant} end case; variant ::= when choice {| choice} => component_list choice ::= simple_expression | discrete_range | others | component_simple_name Each variant starts with a list of choices which must be of the same type as the discriminant of the variant part. The type of the discriminant of a variant part must not be a generic formal type. If the subtype of the discriminant is static, then each value of this subtype must be represented once and only once in the set of choices of the variant part, and no other value is allowed. Otherwise, each value of the (base) type of the discriminant must be represented once and only once in the set of choices. The simple expressions and discrete ranges given as choices in a variant part must be static. A choice defined by a discrete range stands for all values in the corresponding range (none if a null range). The choice others is only allowed for the last variant and as its only choice; it stands for all values (possibly none) not given in the choices of previous variants. A component simple name is not allowed as a choice of a variant (although it is part of the syntax of choice). A record value contains the values of the components of a given variant if and only if the discriminant value is equal to one of the values specified by the choices of the variant. This rule applies in turn to any further variant that is, itself, included in the component list of the given variant. If the component list of a variant is specified by null, the variant has no components. Example of record type with a variant part: type DEVICE is (PRINTER, DISK, DRUM); type STATE is (OPEN, CLOSED); 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; Examples of record subtypes: subtype DRUM_UNIT is PERIPHERAL(DRUM); subtype DISK_UNIT is PERIPHERAL(DISK); Examples of constrained record ariables: WRITER : PERIPHERAL(UNIT => PRINTER); ARCHIVE : DISK_UNIT; Note: Choices with discrete values are also used in case statements and in array aggregates. Choices with component simple names are used in record aggregates. References: array aggregates 4.3.2, base type 3.3, component 3.3, component list 3.7, discrete range 3.6, discriminant 3.3, generic formal type 12.1.2, null range 3.5, record aggregate 4.3.1, range 3.5, record type 3.7, simple expression 4.4, simple name 4.1, static discrete range 4.9, static expression 4.9, static subtype 4.9, subtype 3.3 3.7.4 Operations of Record Types The basic operations of a record type include the operations involved in assignment and aggregates (unless the type is limited), membership tests, selection of record components, qualifications, and type conversion (for derived types) For any object A of a type with discriminants, the basic operations also include the following attribute: A'CONSTRAINED Yields the value TRUE if the discriminant constraint applies to the object A, or if the object is a constant (including a formal parameter or generic formal parameter of mode in); yields the value FALSE otherwise. If A is a generic formal parameter of mode in out, or if A is a formal parameter of mode in out or out and the type mark given in the corresponding parameter specification denotes an unconstrained type with discriminants, then the value of this attribute is obtained from that of the corresponding actual parameter. The value of this attri- bute is of the predefined type BOOLEAN. In addition, the attributes T'BASE and T'SIZE are defined for a record type or subtype T (see 3.3.3); the attributes A'SIZE and A'ADDRESS are defined for a record object A (see 13.7.2). Besides the basic operations, the operations of a record type include the predefined comparison for equality and inequality, unless the type is limited. Note: A record type is limited if the type of any of its components is limited (see 7.4.2). References: actual parameter 6.4.1, appregate 4.3, assignment 5.2, attribute 4.1.4, basic operation 3.3.3, boolean type 3.5.3, constant 3.2.1, conversion 4.6, derived type 3.4, discriminant 3.3, discriminant constraint 3.7.2, formal parameter 6.1, generic actual parameter 12.3, generic formal parameter 12.1 12.3, limited type 7.4.4, membership test 4.5 4.5.2, mode 6.1, object 3.2.1, operation 3.3, predefined operator 4.5, predefined type C, qualified expression 4.7, record type 3.7, relational operator 4.5 4.5.2, selected component 4.1.3, subcomponent 3.3, subtype 3.3, type 3.3 3.8 Acess Types An object declared by an object declaration is created by the elaboration of the object declaration and is denoted by a simple name or by some other form of name. In contrast, there are objects that are created by the eval- uation of allocators (see 4.8) and that have no simple name. Access to such an object is achieved by an access value returned by an allocator; the access value is said to designate the object. access_type_definition ::= access subtype_indication For each access type, there is a literal null which has a null access value designating no object at all. The null value of an access type is the default initial value of the type. Other values of an access type are obtained by evaluation of a special operation of the type called an allocator. Each such access value designates an object of the subtype defined by the subtype indication of the access type definition; this subtype is called the designated subtype; the base type of this subtype is called the designated type. The objects designated by the values of an access type form a collection implicitly associated with the type. The elaboration of an access type definition consists of the elaboration of the subtype indication and creates an access type. If an access object is constant, the constrained access value cannot be changed and always designates the same object. On the other hand, the value of the designated object need not remain the same (assignment to the designated object is allowed unless the designated type is limited). The only forms of contraint that are allowed after the name of an access type in a subtype indication are index constraints and discriminant constraints. (See sections 3.6.1 and 3.7.2 for the rules applicable to these subtype indications.) An access value belongs to a corresponding subtype of an access type either if the access value is the null value or if the value of the designated object satisfies the constraint. Examples: type FRAME is access MATRIX; -- see 3.6 type BUFFER_NAME is access BUFFER -- see 3.7.1 Notes: An access value delivered by an allocator can be assigned to several access objects. Hence it is possible for an object created by an allocator to be designated by more than one variable or constant of the access type. An access value can only designate an object created by an allocator; in particular, it cannot designate an object declared by an object declaration. If the type of the objects designated by the access values is an array type or a type with discriminants, these objects are constrained with either the array bounds or the discriminant values supplied implicitly or explicity for the corresponding allocators (see 4.8). Access values are called pointers of references in some other languages. References: allocator 4.8, array type 3.6, assignment 5.2, belong to a subtype 3.3, constant 3.2.1, constraint 3.3, discriminant constraint 3.7.2, elaboration 3.9, index constraint 3.6.1, index specification 3.6, limited type 7.4.4, literal 4.2, name 4.1, object 3.2.1, object declaration 3.2.1, reserved word 2.9, satisfy 3.3, simple name 4.1, subcomponent 3.3, subtype 3.3, subtype indication 3.3.2, type 3.3 variable 3.2.1 3.8.1 Incomplete Type Declarations 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. Their declarations require a prior incomplete (or private) type declaration for one or more types. incomplete_type_declaration ::= type identifier [discriminant_part]; For each incomplete type declaration, there must be a corresponding declaration of a type with the same identifier. The corresponding declaration must be either a full type declaration or the declarations of a task type. In the rest of this section, explanations are given in terms of full type declarations; the same rules apply also to declarations of task types. If the incomplete type declaration occurs immediately within either a declarative part or the visible part of a package specification, then the full type declaration must occur later and immediately within this declarative part or visible part. If the incomplete type declaration occurs immediately within private part of a package, then the full type declaration must occur later and immediately within either the private part itself, or the declarative part of the corresponding package body. A discriminant part must be given in the full type declaration if and only if one is given in the incomplete type declaration; if discriminant parts are given, then they must conform (see 6.3.1 for the conformance rules). Prior to the end of the full type declaration, the only allowed use of a name that denotes a type declared by an incomplete type declaration is as the type mark in the subtype indication of an access type definition; the only form of constraint allowed in this subtype indication is a discriminant constraint. The elaboration of an incomplete type declaration creates a type. If the incomplete type declaration has a discriminant part, this elaboration includes that of the discriminant part: in such a case, the discriminant part of the full type declaration is not elaborated. Example of a recursive type: type CELL; -- incomplete type declaration type LINK is access CELL; type CELL is record VALUE : INTEGER; SUCC : LINK; PRED : LINK; end record; HEAD : LINK := new CELL'(O, null, null); NEXT : LINK := HEAD.SUCC; Examples of mutually dependent access types: type PERSON(SEX : GENDER); -- incomplete type declaration type CAR; -- incomplete type declaration type PERSON_NAME is access PERSON; type CAR_NAME is access CAR; type CAR is record NUMBER : INTEGER; OWNER :PERSON_NAME; end record; 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; MY_CAR, YOUR_CAR, NEXT_CAR : CAR_NAME; -- implicitly initialized with null value References: access type 3.8, access type definition 3.8, component 3.3, conform 6.3.1, constraint 3.3, declaraton 3.1, declarative item 3.9, designate 3.8, discriminant constraint 3.7.2, discriminant part 3.7.1, elaboration 3.9, identifier 2.3, name 4.1, subtype indication 3.3.2, type 3.3, type mark 3.3.2 3.8.2 Operations of Access Types The basic operations of an access type include the operations involved in assignment, allocators for the access type, membership tests, qualification, explicit conversion, and the literal null. If the designated type is a type with discriminants, the basic operations include the selection of the corresponding discriminants; if the designated type is a record type, they include the selection of the corresponding components; if the designated type is an array type, they include the formation of indexed components and slices; if the designated type is a task type, they include selection of entries and entry families. Furthermore, the basic operations include the formation of a selected component with the reserved word all (see 4.1.3). If the designated type is an array type, the basic operations include the attributes that have the attribute designators FIRST, LAST, RANGE, and LENGTH (likewise, the attribute designators of the N-th dimension). The prefix of each of these attributes must be a value of the access type. These attributes yield the corresponding characteristics of the designated object (see 3.6.2). If the designated type is a task type, the basic operations include the attributes that have the attribute designators TERMINATED and CALLABLE (see 9.9). The prefix of each of these attributes must be a value of the access type. These attributes yield the corresponding characteristics of the designated task objects. In addition, the attribute T'BASE (see 3.3.3) and the representation attributes T'SIZE and T'STORAGE_SIZE (see 13.7.2) are defined for an access type or subtype T; the attributes A'SIZE and A'ADDRESS are defined for an access object A (see 13.7.2). Besides the basic operations, the operations of an access type include the predefined comparison for equality and inequality. References: access type 3.8, allocator 4.8, array type 3.6, assignment 5.2, attribute 4.1.4, attribute designator 4.1.4, base type 3.3, basic operation 3.3.3, collection 3.8, constrained array subtype 3.6, conversion 4.6, designate 3.8, designated subtype 3.8, designated type 3.8, discriminant 3.3, indexed component 4.1.1, literal 4.2, membership test 4.5 4.5.2, object 3.2.1, operation 3.3, private type 7.4, qualified expression 4.7, record type 3.7, selected component 4.1.3, slice 4.1.2, subtype 3.3, task type 9.1, type 3.3 3.9 Declarative Parts A declarative part contains declarative items (possibly none). declarative_part ::= {basic_declarative_item} {later_declarative_item} basic_declarative_item ::= basic_declaration | representation_clause | use_clause later_declarative_item ::= body | subprogram_declaration | package_declaration | task_declaration | generic_declaration | use_clause | generic_instantiation body ::= proper_body | body_stub proper_body ::= subprogram_body | package_body | task_body The elaboration of a declarative part consists of the elaboration of the declarative items, if any, in the order in which they are given in the declarative part. After its elaboration, a declarative item is said to be elaborated. Prior to the completion of its elaboration (including before the elaboration), the declarative item is not yet elaborated. For several forms of declarative item, the language rules (in particular scope and visibility rules) are such that it is either impossible or illegal to use an entity before the elaboration of the declarative item that declares this entity. For example, it is not possible to use the name of a type for an object declaration if the corresponding type declaration is not yet elaborated. In the case of bodies, the following checks are performed: - For a subprogram call, a check is made that the body of the subprogram is already elaborated. - For the activation of a task, a check is made that the body of the corresponding task unit is already elaborated. - For the instantiation of a generic unit that has a body, a check is made that this body is already elaborated. The exception PROGRAM_ERROR is raised if any of these checks fails. If a subprogram declaration, a package declaration, a task declaration, or a generic declaration is a declarative item of a given declarative part, then the body (if there is one) of the program unit declared by the declarative item must itself be a declarative item of this declarative part (and must appear later). If the body is a body stub, then a separately compiled subunit containing the corresponding proper body is required for the program unit (see 10.2). References: activation 9.3, instantiation 12.3, program_error exception 11.1, scope 8.2, subprogram call 6.4, type 3.3, visibility 8.3 Elaboration of declarations: 3.1, component declaration 3.7, deferred constant declaration 7.4.3, discriminant specification 3.7.1, entry declaration 9.5, enumeration literal specification 3.5.1, generic declaration 12.1, generic instantiation 12.3, incomplete type declaration 3.8.1, loop parameter specification 5.5, number declaration 3.2.2, object declaration 3.2.1, package declaration 7.2, parameter specification 6.1, private type declaration 7.4.1, renaming declaration 8.5, subprogram declaration 6.1, subtype declaration 3.3.2, task declaration 9.1, type declaration 3.3.1 Elaboration of type definitions: 3.3.1, access type definition 3.8, array type definition 3.6, derived type definition 3.4, enumeration type definition 3.5.1, integer type definition 3.5.4, real type definition 3.5.6, record type definition 3.7 Elaboration of other constructs: context clause 10.1, body stub 10.2, compilation unit 10.1, discriminant part 3.7.1, generic body 12.2, generic formal parameter 12.1 12.3, library unit 10.5, package body 7.1, representation clause 13.1, subprogram body 6.3, subunit 10.2, task body 9.1, task object 9.2, task specification 9.1, use clause 8.4, with clause 10.1.1