Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow a contained procedure to exit the calling procedure #337

Open
jacobwilliams opened this issue Sep 2, 2024 · 11 comments
Open

Allow a contained procedure to exit the calling procedure #337

jacobwilliams opened this issue Sep 2, 2024 · 11 comments

Comments

@jacobwilliams
Copy link

jacobwilliams commented Sep 2, 2024

Here's a little thing that I have frequently wanted: some syntax to allow a contained procedure (say in a subroutine) to have a return statement that applies to the calling procedure. This is to replace something like this:

subroutine main()

! do some stuff
if (error) then
  call raise_error()
  return   !<--- have to remember to put this everywhere this routine is called
end if
! some other stuff

contains
  subroutine raise_error()
   ! do some error handling stuff
 end subroutine raise_error
end subroutine main

with:

subroutine main()

! do some stuff
if (error) call raise_error()   <---- calling this returns from main
! some other stuff

contains
  subroutine raise_error()
   ! do some error handling stuff
   return main  ! <- some kind of new syntax
 end subroutine raise_error
end subroutine main
@ivan-pi
Copy link

ivan-pi commented Sep 20, 2024

I have also wanted this for the same reason.

The best alternative I can think of is putting the body in a block and then branching out:

subroutine main()

try: block
   ! some stuff
   if (error) exit try
   ! some other stuff

   return     !<--- have to remember to put this here
end block try

call raise_error()
contains
   ! ...
end subroutine

The other way would be goto but I hope we all agree this isn't pretty:

subroutine main()
! some stuff
if (error) goto 999
! some other stuff

return   !<--- have to remember to put this here

999 call raise_error()

contains
   ! ...
end subroutine

The numeric labels feel anachronistic (even C has named labels!) plus they completely mess up formatting in free-form.

I've been meaning to submit a paper to expand the rules for goto to allow named labels:

subroutine main()
! do stuff
if (error) goto error_handling
! do other stuff

return   !<--- still have to remember to put this here

error_handling: block
    call raise_error()
end block error_handling

contains
   ! ...
end subroutine

This would also be useful for I/O procedures which allow jumping to numeric label upon error, so it can be pursued independently of what you are proposing here.

@klausler
Copy link

subroutine outer
  call other(inner)
 contains
  subroutine inner
    return outer
  end
end

subroutine other(e)
  call e
end

@certik
Copy link
Member

certik commented Sep 20, 2024

@klausler I can't even wrap my head around this example, let me try:

subroutine outer
  call other(inner)
 contains
  subroutine inner
    return outer
  end
end

subroutine other(e)
  call e
end

Let's inline other:

subroutine outer
  call inner
 contains
  subroutine inner
    return outer
  end
end

Ok, so this should just return from outer it seems.

Is your point how to do this when other can be defined in another module, or linked later?

@ivan-pi
Copy link

ivan-pi commented Sep 20, 2024

Couldn't one just add a rule that a procedure returning from outer cannot be passed as a procedure argument or associated to a procedure pointer, but only used via a direct call in the applicable scope?

@certik
Copy link
Member

certik commented Sep 20, 2024

@ivan-pi it's a useful pattern that I use quite often to pass the inner procedure as a callback into some solver. It allows me to "pass the context" that way.

@ivan-pi
Copy link

ivan-pi commented Sep 20, 2024

That is useful indeed. I meant only for the case where the inner procedure would return to somewhere else than the place where it was called itself.

@jacobwilliams
Copy link
Author

I have no idea what these outer/inner examples are trying to show here. I think it's too late in the day on Friday or something.

@jacobwilliams
Copy link
Author

@ivan-pi Yes the block thing is as good as we have now I think. But it would be annoying to have to put a block and indent every single subroutine we write.

@jacobwilliams
Copy link
Author

In reality, what we really need is some kind of actual exception handling feature in Fortran. But I fear we will never get that.

@klausler
Copy link

In reality, what we really need is some kind of actual exception handling feature in Fortran. But I fear we will never get that.

I know that they are disapproved, and work only for subroutines, but alternate returns are somewhat adjacent to a decent procedure-scoped exception mechanism that exists today. Perhaps they could be rehabilitated and lightly extended (to work with functions, and to permit forwarding of inbound alternate return arguments to outgoing calls).

@jwmwalrus
Copy link

Hi.

(This post is a bit self-promoting, but...)

A while ago I proposed an exception handing mechanism, and today I posted an updated version ---which I think covers the issue here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants