j3-fortran / fortran_proposals

Proposals for the Fortran Standard Committee
178 stars 15 forks source link

Implementing Integer-based Enumerations with an Inheritance Hierarchy #110

Open MichaelSiehl opened 4 years ago

MichaelSiehl commented 4 years ago

Implementing Integer-based Enumerations with an Inheritance Hierarchy

Fortran (2018) does allow to implement kind of integer-based enumerations, something like this (code snippets):

module xx
..
type, private :: SyncStatus_EnumDef
  integer :: Enum_StepWidth ! = 1
  integer :: WaitingForEventPost ! = 2
  integer :: DoSynchronizationAbort ! = 3
end type SyncStatus_EnumDef
!
type (SyncStatus_EnumDef), public, parameter :: Enum_SyncStatus &
     = SyncStatus_EnumDef (1,2,3)
..
end module xx

We can easily access the enumeration outside our module xx by USE association.
Fortran (gfortran) does also allow to declare our enum type as a component within an abstract type and to use it with an inheritance hierarchy.

module xx
..
type, abstract, public :: EventScalarSync
  private
  ! enumeration type:
  type (SyncStatus_EnumDef), public :: Enum_SyncStatus &
     = SyncStatus_EnumDef (1,2,3)
..
end type EventScalarSync

The advantage of this usage of our enum type is a clean OOP interface and no need for USE association (USE statement) to access the enum type at higher levels of our inheritance hierarchy.
This works already very well with today's Fortran 2018. (I did testing with gfortran).

Suggestion for Improvement

Within an (abstract) type we can't declare the enum type component as PARAMETER (constant). (I did my testing with recent gfortran, which issues a compile time error message).
Thus, it is still possible to do silly changes of the values of our enum type component later in our codes and raise unwanted runtime behavior.
Thus, my question: Are there any reason too not allow to declare components as PARAMETER types (constants) with (abstract) types in future Fortran? (Or is this already allowed and I did just overlook it?)

Regards

klausler commented 4 years ago

You could use defaulted KIND type parameters instead of components.

module m
type, private :: SyncStatusEnumDef(Enum_StepWidth, WaitingForEventPost, DoSynchronizationAbort)
  integer, kind :: Enum_StepWidth = 1, WaitingForEventPost = 2, DoSynchronizationAbort = 3
end type
type(SyncStatusEnumDef), parameter :: Enum_SyncStatus

and then access the values of the "enumerators" via type parameter inquiries e.g. Enum_SyncStatus%WaitingForEventPost.

certik commented 4 years ago

Note: other enumeration proposals are at #11.

MichaelSiehl commented 4 years ago

Thanks for your comments. @klausler I did just check your suggestion with my "production" code (experimental PGAS programming) but it gives an ICE with recent gfortran (without the PARAMETER statement). Anyway, it would only be a slightly different syntax for the same thing. The problem with the PARAMETER statement remains: compile time error "parameter statement is not allowed in TYPE definition".
Maybe my above second code snippet was somewhat incomplete thus, this may help for better understanding:

module xx
...
type, private :: SyncStatus_EnumDef
  integer :: Enum_StepWidth ! = 1
  integer :: WaitingForEventPost ! = 2
  integer :: DoSynchronizationAbort ! = 3
end type SyncStatus_EnumDef
...
type, abstract, public :: EventScalarSync
  private
  ! enumeration type:
  type (SyncStatus_EnumDef), public :: Enum_SyncStatus &  ! we can't use PARAMETER here
     = SyncStatus_EnumDef (1,2,3)
...
end type EventScalarSync
...
end module xx

Personally, I don't need the parameter statement necessarily within a TYPE definition for my programming, and I can't tell if this would break with some other rules of OOP. But in case it does not break with the rules, it could make (experimental) parallel programming more safe (in the future).

MichaelSiehl commented 4 years ago

@certik Thanks for that hint. I was aware that there is a proposal that seeks to implement enumerations as 'true type' but did not see it was already here. I am not against such and don't want to argue against such.
Nevertheless, the language and compilers do already support a sort of integer-based enums (since F9x). The importance of integer-based enums remains for (experimental) PGAS programming because of atomics supporting this data type: integer-based enums can be used with atomics.

certik commented 4 years ago

@MichaelSiehl yes, I only posted it so that you and others can easily find it, I didn't mean to suggest that your proposal is not worth it. Thanks for getting involved here and feel free to engage in other discussions here also.

FortranFan commented 4 years ago

..

Suggestion for Improvement

Within an (abstract) type we can't declare the enum type component as PARAMETER (constant). .. Thus, my question: Are there any reason too not allow to declare components as PARAMETER types (constants) with (abstract) types in future Fortran? (Or is this already allowed and I did just overlook it?) ..

Re: "is this already allowed?" - my read of the current Fortran standard suggests the answer is no.

See issue #16 which can satisfy the use case mentioned here to some extent.