Enums in Fortran

Our enum type ServerState has an underlying integer type.

MODULE ServerModule
  IMPLICIT NONE

  INTEGER, PARAMETER :: StateIdle = 0
  INTEGER, PARAMETER :: StateConnected = 1
  INTEGER, PARAMETER :: StateError = 2
  INTEGER, PARAMETER :: StateRetrying = 3

CONTAINS

  FUNCTION StateToString(state) RESULT(stateStr)
    IMPLICIT NONE
    INTEGER, INTENT(IN) :: state
    CHARACTER(LEN=10) :: stateStr

    SELECT CASE (state)
    CASE (StateIdle)
      stateStr = "idle"
    CASE (StateConnected)
      stateStr = "connected"
    CASE (StateError)
      stateStr = "error"
    CASE (StateRetrying)
      stateStr = "retrying"
    CASE DEFAULT
      stateStr = "unknown"
    END SELECT
  END FUNCTION StateToString

  FUNCTION Transition(state) RESULT(newState)
    IMPLICIT NONE
    INTEGER, INTENT(IN) :: state
    INTEGER :: newState

    SELECT CASE (state)
    CASE (StateIdle)
      newState = StateConnected
    CASE (StateConnected, StateRetrying)
      newState = StateIdle
    CASE (StateError)
      newState = StateError
    CASE DEFAULT
      PRINT *, "Error: unknown state"
      STOP
    END SELECT
  END FUNCTION Transition

END MODULE ServerModule

To use the ServerState type and demonstrate state transitions, we can create a simple program:

PROGRAM TestServerState
  USE ServerModule
  IMPLICIT NONE

  INTEGER :: ns, ns2

  ns = Transition(StateIdle)
  PRINT *, StateToString(ns)

  ns2 = Transition(ns)
  PRINT *, StateToString(ns2)

END PROGRAM TestServerState

When running the program, it will emulate a state transition for a server and prints the state in string format:

$ gfortran -o server_test ServerModule.f90 TestServerState.f90
$ ./server_test
connected
idle

By implementing the StateToString function and using a SELECT CASE construct, we ensure a similar behavior to enums in languages with native enum support. The Transition function handles state transitions safely, mimicking some level of type safety.