[Home] [Prev] [Next] [Index]

3.8 Record Types

3.8 Record Types

1
A record object is a composite object consisting of named components. The value of a record object is a composite value consisting of the values of the components.

Syntax

2
record_type_definition ::= [[abstract] tagged] [limited] record_definition

3
record_definition ::=
    record
       component_list
    end record
  | null record

4
component_list ::=
      component_item {component_item}
   | {component_item} variant_part
   |  null;

5
component_item ::= component_declaration | representation_clause

6
component_declaration ::=
   defining_identifier_list : component_definition [:= default_expression];

Name Resolution Rules

7
The expected type for the default_expression, if any, in a component_declaration is the type of the component.

Legality Rules

8
A default_expression is not permitted if the component is of a limited type.

9
Each component_declaration declares a component of the record type.  Besides components declared by component_declarations, the components of a record type include any components declared by discriminant_specifications of the record type declaration. [The identifiers of all components of a record type shall be distinct.]

9.a
Proof: The identifiers of all components of a record type have to be distinct because they are all declared immediately within the same declarative region.  See Section 8.

10
Within a type_declaration, a name that denotes a component, protected subprogram, or entry of the type is allowed only in the following cases:

11 ·
A name that denotes any component, protected subprogram, or entry is allowed within a representation item that occurs within the declaration of the composite type.

12 ·
A name that denotes a noninherited discriminant is allowed within the declaration of the type, but not within the discriminant_part. If the discriminant is used to define the constraint of a component, the bounds of an entry family, or the constraint of the parent subtype in a derived_type_definition then its name shall appear alone as a direct_name (not as part of a larger expression or expanded name).

12.a
Reason: This restriction simplifies implementation, and allows the outer discriminant and the inner discriminant or bound to possibly share storage.

12.b
Ramification: Other rules prevent such a discriminant from being an inherited one.

A discriminant shall not be used to define the constraint of a scalar component.

12.c
Reason: This restriction is inherited from Ada 83. The restriction is not really necessary from a language design point of view, but we did not remove it, in order to avoid unnecessary changes to existing compilers.

12.d
Note that a discriminant can be used to define the constraint for a component that is of an access-to-composite type.

12.e
Reason: The above rules, and a similar one in 6.1 for formal parameters, are intended to allow initializations of components or parameters to occur in an arbitrary order - whatever order is most efficient, since one default_expression cannot depend on the value of another one. It also prevent circularities.

12.f
Ramification: Inherited discriminants are not allowed to be denoted, except within representation items. However, the discriminant_selector_name of the parent subtype_indication is allowed to denote a discriminant of the parent.

13
If the name of the current instance of a type (see 8.6) is used to define the constraint of a component, then it shall appear as a direct_name that is the prefix of an attribute_reference whose result is of an access type, and the attribute_reference shall appear alone.

13.a
Reason: This rule allows T'Access or T'Unchecked_Access, but disallows, for example, a range constraint (1..T'Size). Allowing things like (1..T'Size) would mean that a per-object constraint could affect the size of the object, which would be bad.

Static Semantics

14
The component_definition of a component_declaration defines the (nominal) subtype of the component. If the reserved word aliased appears in the component_definition, then the component is aliased (see 3.10).

14.a
Ramification: In this case, the nominal subtype cannot be an unconstrained discriminated subtype. See 3.6.

15
If the component_list of a record type is defined by the reserved word null and there are no discriminants, then the record type has no components and all records of the type are null records. A record_definition of null record is equivalent to record null; end record.

15.a
Ramification: This short-hand is available both for declaring a record type and a record extension - see 3.9.1.

Dynamic Semantics

16
The elaboration of a record_type_definition creates the record type and its first subtype, and consists of the elaboration of the record_definition. The elaboration of a record_definition consists of the elaboration of its component_list, if any.

17
The elaboration of a component_list consists of the elaboration of the component_items and variant_part, if any, in the order in which they appear. The elaboration of a component_declaration consists of the elaboration of the component_definition.

17.a
Discussion:  If the defining_identifier_list has more than one defining_identifier, we presume here that the transformation explained in 3.3.1 has already taken place.  Alternatively, we could say that the component_definition is elaborated once for each defining_identifier in the list.

18
Within the definition of a composite type, if a component_definition or discrete_subtype_definition (see 9.5.2) includes a name that denotes a discriminant of the type, or that is an attribute_reference whose prefix denotes the current instance of the type, the expression containing the name is called a per-object expression, and the constraint being defined is called a per-object constraint.

18.a
Discussion:  The evaluation of other expressions that appear in component_definitions and discrete_subtype_definitions is performed when the type definition is elaborated. The evaluation of expressions that appear as default_expressions is postponed until an object is created. Expressions in representation items that appear within a composite type definition are evaluated according to the rules of the particular representation item.

For the elaboration of a component_definition of a component_declaration, if the constraint of the subtype_indication is not a per-object constraint, then the subtype_indication is elaborated. On the other hand, if the constraint is a per-object constraint, then the elaboration consists of the evaluation of any included expression that is not part of a per-object expression.

NOTES

19 55
A component_declaration with several identifiers is equivalent to a sequence of single component_declarations, as explained in 3.3.1.

20 56
The default_expression of a record component is only evaluated upon the creation of a default-initialized object of the record type (presuming the object has the component, if it is in a variant_part -see 3.3.1).

21 57
The subtype defined by a component_definition (see 3.6) has to be a definite subtype.

22 58
If a record type does not have a variant_part, then the same components are present in all values of the type.

23 59
A record type is limited if it has the reserved word limited in its definition, or if any of its components are limited (see 7.5).

24 60
The predefined operations of a record type include membership tests, qualification, and explicit conversion.  If the record type is nonlimited, they also include assignment and the predefined equality operators.

25 61
A component of a record can be named with a selected_component. A value of a record can be specified with a record_aggregate, unless the record type is limited.

Examples

26
Examples of record type declarations:

27
type Date is
   record
      Day   : Integer range 1 .. 31;
      Month : Month_Name;
      Year  : Integer range 0 .. 4000;
   end record;

28
type Complex is
   record
      Re : Real := 0.0;
      Im : Real := 0.0;
   end record;

29
Examples of record variables:

30
Tomorrow, Yesterday : Date;
A, B, C : Complex;

31
-- both components of A, B, and C are implicitly initialized to zero

Extensions to Ada 83

31.a
The syntax rule for component_declaration is modified to use component_definition (instead of component_subtype_definition).  The effect of this change is to allow the reserved word aliased before the component_subtype_definition.

31.b
A short-hand is provided for defining a null record type (and a null record extension), as these will be more common for abstract root types (and derived types without additional components).

31.c
The syntax rule for record_type_definition is modified to allow the reserved words tagged and limited. Tagging is new. Limitedness is now orthogonal to privateness. In Ada 83 the syntax implied that limited private was sort of more private than private. However, limitedness really has nothing to do with privateness; limitedness simply indicates the lack of assignment capabilities, and makes perfect sense for nonprivate types such as record types.

Wording Changes From Ada 83

31.d
The syntax rules now allow representation_clauses to appear in a record_definition. This is not a language extension, because Legality Rules prevent all language-defined representation clauses from appearing there. However, an implementation-defined attribute_definition_clause could appear there. The reason for this change is to allow the rules for representation_clauses and representation pragmas to be as similar as possible.

3.8.1 Variant Parts and Discrete Choices

1
A record type with a variant_part specifies alternative lists of components.  Each variant defines the components for the value or values of the discriminant covered by its discrete_choice_list.

1.a
Discussion:  Discrete_choice_lists and discrete_choices are said to cover values as defined below; which discrete_choice_list covers a value determines which of various alternatives is chosen.  These are used in variant_parts, array_aggregates, and case_statements.

Language Design Principles

1.b
The definition of "cover" in this subclause and the rules about discrete choices are designed so that they are also appropriate for array aggregates and case statements.

1.c
The rules of this subclause intentionally parallel those for case statements.

Syntax

2
variant_part ::=
   case discriminant_direct_name is
       variant
      {variant}
   end case;

3
variant ::=
   when discrete_choice_list =>
      component_list

4
discrete_choice_list ::= discrete_choice {| discrete_choice}

5
discrete_choice ::= expression | discrete_range | others

Name Resolution Rules

6
The discriminant_direct_name shall resolve to denote a discriminant (called the discriminant of the variant_part) specified in the known_discriminant_part of the full_type_declaration that contains the variant_part. The expected type for each discrete_choice in a variant is the type of the discriminant of the variant_part.

6.a
Ramification: A full_type_declaration with a variant_part has to have a (new) known_discriminant_part; the discriminant of the variant_part cannot be an inherited discriminant.

Legality Rules

7
The discriminant of the variant_part shall be of a discrete type.

7.a
Ramification: It shall not be of an access type, named or anonymous.

8
The expressions and discrete_ranges given as discrete_choices in a variant_part shall be static. The discrete_choice others shall appear alone in a discrete_choice_list, and such a discrete_choice_list, if it appears, shall be the last one in the enclosing construct.

9
A discrete_choice is defined to cover a value in the following cases:

10 ·
A discrete_choice that is an expression covers a value if the value equals the value of the expression converted to the expected type.

11 ·
A discrete_choice that is a discrete_range covers all values (possibly none) that belong to the range.

12 ·
The discrete_choice others covers all values of its expected type that are not covered by previous discrete_choice_lists of the same construct.

12.a
Ramification: For case_statements, this includes values outside the range of the static subtype (if any) to be covered by the choices. It even includes values outside the base range of the case expression's type, since values of numeric types (and undefined values of any scalar type?) can be outside their base range.

13
A discrete_choice_list covers a value if one of its discrete_choices covers the value.

14
The possible values of the discriminant of a variant_part shall be covered as follows:

15 ·
If the discriminant is of a static constrained scalar subtype, then each non-others discrete_choice shall cover only values in that subtype, and each value of that subtype shall be covered by some discrete_choice [(either explicitly or by others)];

16 ·
If the type of the discriminant is a descendant of a generic formal scalar type then the variant_part shall have an others discrete_choice;

16.a
Reason: The base range is not known statically in this case.

17 ·
Otherwise, each value of the base range of the type of the discriminant shall be covered [(either explicitly or by others)].

18
Two distinct discrete_choices of a variant_part shall not cover the same value.

Static Semantics

19
If the component_list of a variant is specified by null, the variant has no components.

20
The discriminant of a variant_part is said to govern the variant_part and its variants.  In addition, the discriminant of a derived type governs a variant_part and its variants if it corresponds (see 3.7) to the discriminant of the variant_part.

Dynamic Semantics

21
A record value contains the values of the components of a particular variant only if the value of the discriminant governing the variant is covered by the discrete_choice_list of the variant. This rule applies in turn to any further variant that is, itself, included in the component_list of the given variant.

22
The elaboration of a variant_part consists of the elaboration of the component_list of each variant in the order in which they appear.

Examples

23
Example of record type with a variant part:

24
type Device is (Printer, Disk, Drum);
type State  is (Open, Closed);

25
type Peripheral(Unit : Device := Disk) is
   record
      Status : State;
      case Unit is
         when Printer =>
            Line_Count : Integer range 1 .. Page_Size;
         when others =>
            Cylinder   : Cylinder_Index;
            Track      : Track_Number;
         end case;
      end record;

26
Examples of record subtypes:

27
subtype Drum_Unit is Peripheral(Drum);
subtype Disk_Unit is Peripheral(Disk);

28
Examples of constrained record variables:

29
Writer   : Peripheral(Unit  => Printer);
Archive  : Disk_Unit;

Extensions to Ada 83

29.a
In Ada 83, the discriminant of a variant_part is not allowed to be of a generic formal type. This restriction is removed in Ada 9X; an others discrete_choice is required in this case.

Wording Changes From Ada 83

29.b
The syntactic category choice is removed. The syntax rules for variant, array_aggregate, and case_statement now use discrete_choice_list or discrete_choice instead. The syntax rule for record_aggregate now defines its own syntax for named associations.

29.c
We have added the term Discrete Choice to the title since this is where they are talked about. This is analogous to the name of the subclause "Index Constraints and Discrete Ranges" in the clause on Array Types.

29.d
The rule requiring that the discriminant denote a discriminant of the type being defined seems to have been left implicit in RM83.



[Home] [Prev] [Next] [Index]

documentation@rational.com
Copyright © 1993-1998, Rational Software Corporation.   All rights reserved.