j3-fortran / fortran_proposals

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

Constant Expression Value Arguments for Generic Resolution #320

Open everythingfunctional opened 11 months ago

everythingfunctional commented 11 months ago

It has so far been impossible to write user defined functions that can mimic the behavior of various intrinsic functions. I.e.

function real(A, KIND)
  real, intent(in) :: A
  integer, intent(in) :: KIND
  real(KIND) :: real
end function

But if we had some mechanism to define a constant expression value that must be one of the arguments we could do it. I.e. some suggestive syntax

interface real
  module function str_to_real128(A, KIND, STAT)
    character(len=*), intent(in) :: A
    integer, parameter, intent(in) :: KIND = real128
    integer, intent(out), optional :: STAT
    real(real128) :: str_to_real128
  end function
  ...
end interface
...
real(real128) :: my_val
my_val = real("1.234", KIND=real128)
certik commented 11 months ago

Nice idea. I modified your example to say interface str instead of interface real, since I think that's what you meant.

everythingfunctional commented 11 months ago

Actually I did mean real. The example is intending to extend the real intrinsic to work for converting strings to real numbers.

jacobwilliams commented 11 months ago

Same as #91 I think?

everythingfunctional commented 11 months ago

Same as #91 I think?

Very similar, yes, but I think the solution I propose is different.

certik commented 11 months ago

@everythingfunctional I see --- you had there "str" in the function call, but "real" as the interface. Everything is clear now after your edit.

shahmoradi commented 11 months ago

A mechanism like the optional kind type parameter (with kind attribute) of parameterized derived types would be ideal. So instead of

integer, parameter, intent(in) :: KIND = real128

we'd write,

integer, kind :: kind = real128

similar to PDTs. I have so far bypassed this issue by introducing a like dummy argument for type resolution. But then one has to live with endless compiler warnings about unused dummy arguments and, more importantly, an interface inconsistent with intrinsic procedures of the same name and functionality. There is a clear need for this facility in the language from a user's perspective.

everythingfunctional commented 11 months ago

My idea was more along the lines of that argument being required and required to have the given value (so the compiler can actually do the code generation), but it can then be used for generic resolution. This is a bit with an eye towards one of the generics features being worked on so you could do something like:

generic function real(A, KIND, STAT)
  use iso_fortran_env, only: real_kinds
  character(len=*, kind=*), intent(in) :: A
  integer, parameter, intent(in) :: KIND = real_kinds
  integer(*), intent(out), optional :: STAT
  real(KIND) :: real
  ...
end function
generic function real(A, STAT)
  character(len=*, kind=*), intent(in) :: A
  integer(*), intent(out), optional :: STAT
  real :: real
  real = real(A, kind(real), STAT)
end function

You could also use a feature like this to disambiguate between allocatable or not like a bunch of people seem to want to lately. I.e.

interface foo
  module subroutine foo_alloc(A, WHICH)
    integer, allocatable, intent(inout) :: A(:)
    character(len=*), parameter, intent(in) :: WHICH = "allocatable"
  end subroutine
  module subroutine foo_static(A, WHICH)
    integer, intent(inout) :: A(:)
    character(len=*), parameter, intent(in) :: WHICH = "static"
  end subroutine
end interface
integer, allocatable :: x(:)
call foo(x, "allocatable")
FortranFan commented 11 months ago

.. interface real module function str_to_real128(A, KIND, STAT) character(len=*), intent(in) :: A integer, parameter, intent(in) :: KIND = real128 integer, intent(out), optional :: STAT real(real128) :: str_to_real128 ..

A typo here? Was the following that was meant?


..
 real(KIND) :: str_to_real128
..
everythingfunctional commented 11 months ago

Given my idea, and that interface, they're equivalent.

FortranFan commented 11 months ago

So instead of

integer, parameter, intent(in) :: KIND = real128

we'd write,

integer, kind :: kind = real128

Agree totally.

The clause (or call it an attribute if one prefer) of , KIND implies compile-time semantics for the processor. The , parameter doesn't jive with what is in the language since the 2003 revision.

KHUSHIJAIN910 commented 10 months ago

user defined function can be achieved here by adding libraries of different languages here.