Errors in Co-array Fortran

program error_handling
  use iso_fortran_env, only: error_unit
  implicit none

  integer :: i, result
  logical :: success

  ! Sentinel errors
  character(len=*), parameter :: ERR_OUT_OF_TEA = "no more tea available"
  character(len=*), parameter :: ERR_POWER = "can't boil water"

  do i = 1, 2
    call f(i * 35, result, success)
    if (.not. success) then
      write(error_unit, *) "f failed: can't work with 42"
    else
      print *, "f worked:", result
    end if
  end do

  do i = 0, 4
    call make_tea(i, success)
    if (.not. success) then
      call handle_tea_error(i)
    else
      print *, "Tea is ready!"
    end if
  end do

contains

  subroutine f(arg, result, success)
    integer, intent(in) :: arg
    integer, intent(out) :: result
    logical, intent(out) :: success

    if (arg == 42) then
      success = .false.
      return
    end if

    result = arg + 3
    success = .true.
  end subroutine f

  subroutine make_tea(arg, success)
    integer, intent(in) :: arg
    logical, intent(out) :: success

    success = .true.
    if (arg == 2) then
      success = .false.
    else if (arg == 4) then
      success = .false.
    end if
  end subroutine make_tea

  subroutine handle_tea_error(arg)
    integer, intent(in) :: arg

    if (arg == 2) then
      print *, "We should buy new tea!"
    else if (arg == 4) then
      print *, "Now it is dark."
    else
      print *, "Unknown error occurred while making tea"
    end if
  end subroutine handle_tea_error

end program error_handling

In Co-array Fortran, error handling is typically done through the use of status variables and conditional checks. This example demonstrates how to implement error handling similar to the Go example, adapted to Fortran’s conventions.

Key points in this translation:

  1. We use subroutines with output parameters to simulate functions that return multiple values.

  2. Instead of an error type, we use a logical success flag to indicate whether an operation was successful.

  3. Sentinel errors are represented as character constants.

  4. Error messages are written to the error_unit, which is similar to writing to stderr in other languages.

  5. The errors.Is functionality is simulated in the handle_tea_error subroutine, where we check the input argument to determine the type of error.

  6. We use Fortran’s contains keyword to define internal procedures, which is similar to defining helper functions in the same scope in other languages.

This code structure allows for explicit error checking and handling, similar to the Go example, while adhering to Fortran’s procedural programming paradigm. The main program flow remains similar, demonstrating error handling in loops and conditional statements.

To run this program, you would typically save it in a file with a .f90 extension (e.g., error_handling.f90), compile it with a Fortran compiler that supports Co-array features, and then execute the resulting binary.

$ gfortran -fcoarray=single error_handling.f90 -o error_handling
$ ./error_handling

This example showcases how to implement structured error handling in Co-array Fortran, providing a similar flow and functionality to the original Go code.