To: J3 J3/18-114 From: Van Snyder Subject: Enumeration types Date: 2018-February-05 Reference: 98-194r1 Number ====== TBD Submitted by ============ J3 Status ====== For consideration. Basic Functionality =================== Provide for definition of enumeration types, not just names for C-interoperable integer named constants. Rationale ========= Enumerators are sufficiently useful that we added them, but in a crippled form suitable only for C interoperability. Enumeration types could be used for generic resolution, argument and result type safety for procedure reference, and array bounds. Estimated Impact on Standard ============================ Minor to moderate. Detailed Specification ====================== Specify syntax to define enumeration types and their enumerators. The type definition specifies whether enumerators are ordered or unordered. Unordered enumerators are not significantly different from named integer constants or BIND(C) enums, and therefore might not be sufficiently useful. An enumeration type definition may specify a kind type parameter value. This is not a kind type parameter that may be specified differently in the declarations of objects of the type, because the enumeration type definition declares objects that are its enumerators. If an enumeration type is parameterized, the parameter specifies the kind of integer that represents the numeric values of its enumerators, and all variables of the type. Whether the kind is otherwise default integer, or processor dependent, can be decided in due course. Polymorphism might require to standardize the kind if no kind type parameter is specified. Alternatives are a non-extensibility attribute, or prohibiting extension if a kind type parameter value is not specified and the kind in that case is processor dependent, which would allow a processor to choose a representation smaller than default integer, for example eight bits, without fear that enumerators of an extension would require more bits. An enumeration type definition can specify an accessibility attribute, which applies to the type name. An enumeration type that is not an extension type can be declared to be interoperable using the BIND(C) attribute. If a kind type parameter value is specified, it shall be one that is specified in Table 18.2 in 17-007r2. Type-bound procedures are not proposed. Example: ENUMERATION, ORDERED :: T ENUMERATOR :: RED, ORANGE, YELLOW, GREEN, BLUE END ENUMERATION T An ordered enumeration type is extensible. The extension type includes the enumerators of its parent. An enumerator of an extension type cannot have the same name as an enumerator of its parent type. An extension type is interoperable if and only if its parent type is interoperable. The extension type has the same kind type parameter value as the parent type, and the kind cannot be specified in its definition. The usual type compatibility rules concerning type extension apply, except that a nonpolymorphic expression of ancestor type may be assigned to a polymorphic or nonpolymorphic variable of descendant type. Assignment is not a problem because all enumerators of an ancestor type are also enumerators of a descendant type. Example: ENUMERATION, EXTENDS(T) :: U ! U is an ordered enumeration type ENUMERATOR :: ULTRAVIOLET, XRAY, GAMMA END ENUMERATION U An enumerator of enumeration type is a literal constant that is an object of that type. An accessibility attribute may be specified for enumerators. Whether a default accessibility attribute may be specified, as can be done for derived type component declarations, can be decided in due course. If an enumeration type name is accessed by use association, all its public enumerators are also accessible, and their local names are the same as their declared names. If an enumerator is accessed by use association with ONLY, its type name is also accessible, but enumerators that are not accessed by use association are not accessible. It might be useful to provide a syntax of use association that specifies whether only an enumeration type name is accessible, or the type name and its enumerators are accessible. Example: USE M, ONLY: T ! Only the type name is accessible USE M, ONLY: T() ! The type name and enumerator names are accessible Enumerators of enumeration types can be renamed during use association. The declared type of a data object of enumeration type can be specified using the ordinary type declaration syntax, i.e., TYPE() :: or CLASS() :: . A kind type parameter cannot be specified in the declaration of an object of enumeration type; it is specified only by the type definition. Objects of BIND(C) enumeration types cannot appear in EQUIVALENCE. A numeric sequence type may have components of an enumeration type with default integer kind. A numeric value may be specified for any enumerator of an unordered enumeration type. If a numeric value is not specified for the first enumerator of an unordered enumeration type, its numeric value is zero. It is possible for two enumerators of an unordered enumeration type to have the same numeric representation. A numeric value may be specified for the first enumerator of an ordered enumeration type that is not an extension type. Otherwise, the numeric value of the first enumerator of an ordered enumeration type, that is not an extension, is zero. The numeric value of the first enumerator of an ordered enumeration type, that is an extension, is one more than the numeric value of the last enumerator of the parent type. The numeric value of an enumerator of an ordered enumeration type, other than the first one, cannot be specified; it is one more than the value of the previously declared enumerator of that type. The numeric value of an enumerator of an unordered enumeration type for which a numeric value is not specified, other than the first one, is one more than the value of the previously declared enumerator of that type. The numeric value of an enumerator shall be representable by an integer of the kind specified or implied by the declaration of its type. This might cause an extension definition to fail. The numeric value of an enumerator or object of enumeration type may be inquired using the INT intrinsic function. An object of ordered enumeration type may be an actual argument in a reference to the intrinsic function TINY. The result value is the first enumerator of the declared type of that object (which includes all enumerators of all ancestor types). The value of a variable of an ordered enumeration type might be less than the result of TINY with that variable as an argument, if its type is an extension, because every enumerator of a parent enumeration type is an enumerator of all of its extension types. An object of ordered enumeration type may be an actual argument in a reference to the intrinsic function HUGE. Its value is the last enumerator of the dynamic type of that object. Definition of an ordered enumeration type defines an elemental constructor function of the same name. An actual argument shall be an integer expression, an enumerator of the same declared type, or a variable of the same declared type. The value of an integer argument shall be within the range of numeric representations of enumerators of the specified type. References to the constructor function may appear in constant expressions, provided their arguments are constant expressions. A function with the same generic name as the type is allowed, provided it is distinguishable from the constructor, but it cannot appear in constant expressions. Definition of an unordered enumeration type defines an elemental constructor function of the same name. The argument shall be an enumerator of the same declared type or a variable of the same declared type. An integer argument is not allowed because there might be numeric values between the smallest and largest numeric representations of enumerators of the type that do not represent enumerators of the type. References to the constructor function may appear in constant expressions, provided their arguments are constant expressions. A function with the same generic name as the type is allowed, provided it is distinguishable from the constructor, but it cannot appear in constant expressions. Enumerators are local identifiers in class (1) in subclause 19.3.1 of 17-007r2. An enumerator of an enumeration type may have the same name as an enumerator of a different ordered enumeration type that is not an ancestor type. If several enumerators having the same name are accessible, the can appear only as arguments to constuctors of their types. Example: ENUMERATION, ORDERED :: COLORS ENUMERATOR :: WHITE, BROWN, GREEN END ENUMERATION COLORS ENUMERATION, ORDERED :: NAMES ENUMERATOR :: GREEN, BROWN, WHITE END ENUMERATION NAMES NAMES(GREEN) is a value of type NAMES. COLORS(GREEN) is a value of type COLORS. Their numeric representations are different. GREEN alone is prohibited because its type is ambiguous. An object of enumeration type may have any attribute allowed for data objects of other types. The name of an ordered enumeration type may be used to specify the bounds of an array dimension or the cobounds of a coarray codimension, either in a declaration or an . An enumerator of an ordered enumeration type may be used to specify the upper bound of an array dimension or cobound of a coarray codimension , either in a declaration or an . Two enumerators of an ordered enumeration type may be used, with colon notation, to specify the bounds of an array dimension or the cobounds of a coarray codimension, either in a declaration or an . If the upper bound precedes the lower bound in the definition of the bounds' type, the extent in that dimension is zero. The upper cobound shall not precede the lower cobound. If colon notation is not used, the effect is as if the lower bound or cobound were specified by reference to the intrinsic function TINY with an object of the type of the bounds or cobounds as its actual argument. If bounds or cobounds are specified using an ordered enumeration type name, or by a range of enumerators, a subscript or cosubscript for that dimension or codimension, including a subscript in a section subscript, shall be a nonpolymorphic expression of the same type. If appears, it shall be nonzero and of integer type. If the lower subscript is omitted, it is as if it were specified by reference to the intrinsic function TINY with an object of the type of the bounds as its actual argument. If the upper subscript is omitted, it is as if it were specified by reference to the intrinsic function HUGE with a nonpolymorphic object of the type of the bounds as its actual argument. If the bound or cobound is specified by an ordered enumeration type name that is not an extension type, the value of a nonpolymorphic subscript or cosubscript of that declared type is necessarily within the bounds of that dimension or codimension because it must be a value of that type. Subscript bounds checking has no runtime cost, provided the result value of a constructor is checked, and the value of a variable of enumeration type read by unformatted input is checked if numeric representation is used for unformatted input/output. A , , or may be a nonpolymorphic variable of an ordered enumeration type. The first and second expressions in the loop control shall be specified by nonpolymorphic expressions of that type. If the third expression appears, it shall be nonzero and of integer type. An may be a nonpolymorphic variable of an ordered enumeration type. The first and second expressions shall be specified by nonpolymorphic expressions of that type. If appears, it shall be nonzero and of integer type. The intrinsic function KIND may be used to inquire the kind of integer used to represent a value of an enumeration type. The only intrinsic operations defined for objects of unordered enumeration types are equality and inequality. All numeric relational operations are defined for objects of ordered enumeration types, using the numeric representations of the objects. The operands shall be of the same declared type, or the type of one shall be an extension of the type of the other. No other intrinsic operations are provided for objects of enumeration types. Assignment and operations may be defined for enumeration types. A in SELECT CASE may be a scalar expression of ordered enumeration type. A in a CASE statement shall be a scalar constant expression of the same declared type if is not polymorphic, or may be of an extension type if is polymorphic. Elemental intrinsic functions shall provide the successor and predecessor objects of values of ordered enumeration types. Whether the successor (predecessor) of the last (first) value is the first (last) value, or an error, or an undefined value, can be decided in due course. Formatted input and output of values of enumeration types shall be provided, using the local names of the enumerators. Whether the "A" format descriptor is used, or a new edit descriptor is defined, can be decided in due course. Input shall not be case sensitive. Case of output could be specified by the standard or processor dependent, but a changeable mode to specify the case (upper case, lower case, or the case in the type definition or renaming in use association) would be preferable. Unformatted input and output of values of enumeration types shall be provided. Whether numeric or text representation is used can be decided in due course, or might be processor dependent. If an object of enumeration type is an actual argument, the referenced procedure shall have explicit interface. If a procedure has a dummy argument of enumeration type, its interface shall be explicit where it is referenced. Existing rules for argument type compatibility are reversed because the value of an actual argument that is of an extension of the type of the dummy argument might not be an enumerator of the dummy argument type.