Go to the first, previous, next, last section, table of contents.

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.


  2. variant_part ::=
       case discriminant_direct_name is
       end case;
  3. variant ::=
       when discrete_choice_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.

    Legality Rules

  7. The discriminant of the variant_part shall be of a discrete type.
  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:
    1. A discrete_choice that is an expression covers a value if the value equals the value of the expression converted to the expected type.
    2. A discrete_choice that is a discrete_range covers all values (possibly none) that belong to the range.
    3. The discrete_choice others covers all values of its expected type that are not covered by previous discrete_choice_lists of the same construct.

  1. A discrete_choice_list covers a value if one of its discrete_choices covers the value.
  2. The possible values of the discriminant of a variant_part shall be covered as follows:
    1. 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);
    2. 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;
    3. Otherwise, each value of the base range of the type of the discriminant shall be covered (either explicitly or by others).

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

    Static Semantics

  2. If the component_list of a variant is specified by null, the variant has no components.
  3. 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 section 3.7 Discriminants, to the discriminant of the variant_part.

    Dynamic Semantics

  4. 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.
  5. The elaboration of a variant_part consists of the elaboration of the component_list of each variant in the order in which they appear.


  6. Example of record type with a variant part:
  7. type Device is (Printer, Disk, Drum);
    type State  is (Open, Closed);
  8. type Peripheral(Unit : Device := Disk) is
          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;
  9. Examples of record subtypes:
  10. subtype Drum_Unit is Peripheral(Drum);
    subtype Disk_Unit is Peripheral(Disk);
  11. Examples of constrained record variables:
  12. Writer   : Peripheral(Unit  => Printer);
    Archive  : Disk_Unit;

Go to the first, previous, next, last section, table of contents.