Re: Are procedure dummy arguments ignored in generic procedure resolution?

From: James Van Buskirk (not_valid_at_comcast.net)
Date: 12/10/04


Date: Fri, 10 Dec 2004 21:34:52 GMT


"James Van Buskirk" <not_valid@comcast.net> wrote in message
news:Qsmud.238685$R05.24113@attbi_s53...

> the funky stuff in section 14.1.2.3. Well, I've got a student
> waiting just now, so no time for any examples...

Student dispatched, so here's an example. Since it's a bit long,
permit me to preface it with some explanation:

In ISO/IEC 1539-1:1997(E), section 12.3.2.1 we read:
"Constraint: An interface-block in a subprogram shall not contain
             an interface-body for a procedure defined by that
             subprogram."

>From this I take it to mean that for a recursive procedure to
invoke itself generically, the interface block that defines the
generic name, operator, or assignment must use the module
procedure statement where its interface-body would otherwise
have gone. So here's my example:

module mykinds
   implicit none
   integer, parameter :: ik1 = selected_int_kind(2)
   integer, parameter :: ik2 = selected_int_kind(4)
   integer, parameter :: ik4 = selected_int_kind(9)
   integer, parameter :: ik8 = selected_int_kind(18)
   integer, parameter :: ik(0:3) = (/ik1,ik2,ik4,ik8/)
end module mykinds

recursive subroutine step_up(x,y,grid)
   use mykinds
   implicit none
   integer(ik(0)), intent(in) :: x
   integer, intent(in) :: y
   character, intent(inout) :: grid(0:10)*11
   real harvest
   integer direction
   interface step
      module procedure step_up

      recursive subroutine step_right(x,y,grid)
         use mykinds
         implicit none
         integer(ik(1)), intent(in) :: x
         integer, intent(in) :: y
         character, intent(inout) :: grid(0:10)*11
      end subroutine step_right

      recursive subroutine step_down(x,y,grid)
         use mykinds
         implicit none
         integer(ik(2)), intent(in) :: x
         integer, intent(in) :: y
         character, intent(inout) :: grid(0:10)*11
      end subroutine step_down

      recursive subroutine step_left(x,y,grid)
         use mykinds
         implicit none
         integer(ik(3)), intent(in) :: x
         integer, intent(in) :: y
         character, intent(inout) :: grid(0:10)*11
      end subroutine step_left
   end interface step

   grid(y)(x:x) = 'X'
   if(any(x==(/1,len(grid)/)).OR.any(y==(/0,ubound(grid,1)/))) return
   call random_number(harvest)
   direction = 4*harvest
   select case(direction)
   case(0)
      call step(int(x,ik(0)),y+1,grid)
   case(1)
      call step(int(x+1,ik(1)),y,grid)
   case(2)
      call step(int(x,ik(2)),y-1,grid)
   case(3)
      call step(int(x-1,ik(3)),y,grid)
   end select
end subroutine step_up

recursive subroutine step_right(x,y,grid)
   use mykinds
   implicit none
   integer(ik(1)), intent(in) :: x
   integer, intent(in) :: y
   character, intent(inout) :: grid(0:10)*11
   real harvest
   integer direction
   interface step
      recursive subroutine step_up(x,y,grid)
         use mykinds
         implicit none
         integer(ik(0)), intent(in) :: x
         integer, intent(in) :: y
         character, intent(inout) :: grid(0:10)*11
      end subroutine step_up

      module procedure step_right

      recursive subroutine step_down(x,y,grid)
         use mykinds
         implicit none
         integer(ik(2)), intent(in) :: x
         integer, intent(in) :: y
         character, intent(inout) :: grid(0:10)*11
      end subroutine step_down

      recursive subroutine step_left(x,y,grid)
         use mykinds
         implicit none
         integer(ik(3)), intent(in) :: x
         integer, intent(in) :: y
         character, intent(inout) :: grid(0:10)*11
      end subroutine step_left
   end interface step

   grid(y)(x:x) = 'X'
   if(any(x==(/1,len(grid)/)).OR.any(y==(/0,ubound(grid,1)/))) return
   call random_number(harvest)
   direction = 4*harvest
   select case(direction)
   case(0)
      call step(int(x,ik(0)),y+1,grid)
   case(1)
      call step(int(x+1,ik(1)),y,grid)
   case(2)
      call step(int(x,ik(2)),y-1,grid)
   case(3)
      call step(int(x-1,ik(3)),y,grid)
   end select
end subroutine step_right

recursive subroutine step_down(x,y,grid)
   use mykinds
   implicit none
   integer(ik(2)), intent(in) :: x
   integer, intent(in) :: y
   character, intent(inout) :: grid(0:10)*11
   real harvest
   integer direction
   interface step
      recursive subroutine step_up(x,y,grid)
         use mykinds
         implicit none
         integer(ik(0)), intent(in) :: x
         integer, intent(in) :: y
         character, intent(inout) :: grid(0:10)*11
      end subroutine step_up

      recursive subroutine step_right(x,y,grid)
         use mykinds
         implicit none
         integer(ik(1)), intent(in) :: x
         integer, intent(in) :: y
         character, intent(inout) :: grid(0:10)*11
      end subroutine step_right

      module procedure step_down

      recursive subroutine step_left(x,y,grid)
         use mykinds
         implicit none
         integer(ik(3)), intent(in) :: x
         integer, intent(in) :: y
         character, intent(inout) :: grid(0:10)*11
      end subroutine step_left
   end interface step

   grid(y)(x:x) = 'X'
   if(any(x==(/1,len(grid)/)).OR.any(y==(/0,ubound(grid,1)/))) return
   call random_number(harvest)
   direction = 4*harvest
   select case(direction)
   case(0)
      call step(int(x,ik(0)),y+1,grid)
   case(1)
      call step(int(x+1,ik(1)),y,grid)
   case(2)
      call step(int(x,ik(2)),y-1,grid)
   case(3)
      call step(int(x-1,ik(3)),y,grid)
   end select
end subroutine step_down

recursive subroutine step_left(x,y,grid)
   use mykinds
   implicit none
   integer(ik(3)), intent(in) :: x
   integer, intent(in) :: y
   character, intent(inout) :: grid(0:10)*11
   real harvest
   integer direction
   interface step
      recursive subroutine step_up(x,y,grid)
         use mykinds
         implicit none
         integer(ik(0)), intent(in) :: x
         integer, intent(in) :: y
         character, intent(inout) :: grid(0:10)*11
      end subroutine step_up

      recursive subroutine step_right(x,y,grid)
         use mykinds
         implicit none
         integer(ik(1)), intent(in) :: x
         integer, intent(in) :: y
         character, intent(inout) :: grid(0:10)*11
      end subroutine step_right

      recursive subroutine step_down(x,y,grid)
         use mykinds
         implicit none
         integer(ik(2)), intent(in) :: x
         integer, intent(in) :: y
         character, intent(inout) :: grid(0:10)*11
      end subroutine step_down

      module procedure step_left
   end interface step

   grid(y)(x:x) = 'X'
   if(any(x==(/1,len(grid)/)).OR.any(y==(/0,ubound(grid,1)/))) return
   call random_number(harvest)
   direction = 4*harvest
   select case(direction)
   case(0)
      call step(int(x,ik(0)),y+1,grid)
   case(1)
      call step(int(x+1,ik(1)),y,grid)
   case(2)
      call step(int(x,ik(2)),y-1,grid)
   case(3)
      call step(int(x-1,ik(3)),y,grid)
   end select
end subroutine step_left

program generic_recurse
   use mykinds
   implicit none
   interface step
      recursive subroutine step_up(x,y,grid)
         use mykinds
         implicit none
         integer(ik(0)), intent(in) :: x
         integer, intent(in) :: y
         character, intent(inout) :: grid(0:10)*11
      end subroutine step_up

      recursive subroutine step_right(x,y,grid)
         use mykinds
         implicit none
         integer(ik(1)), intent(in) :: x
         integer, intent(in) :: y
         character, intent(inout) :: grid(0:10)*11
      end subroutine step_right

      recursive subroutine step_down(x,y,grid)
         use mykinds
         implicit none
         integer(ik(2)), intent(in) :: x
         integer, intent(in) :: y
         character, intent(inout) :: grid(0:10)*11
      end subroutine step_down

      recursive subroutine step_left(x,y,grid)
         use mykinds
         implicit none
         integer(ik(3)), intent(in) :: x
         integer, intent(in) :: y
         character, intent(inout) :: grid(0:10)*11
      end subroutine step_left
   end interface step
   real harvest
   integer direction
   character(11), dimension(0:10) :: grid
   integer, parameter :: x = 6
   integer, parameter :: y = 5

   grid = repeat(".",len(grid))
   grid(y)(x:x) = 'X'
   call random_seed()
   call random_number(harvest)
   direction = 4*harvest
   select case(direction)
   case(0)
      call step(int(x,ik(0)),y+1,grid)
   case(1)
      call step(int(x+1,ik(1)),y,grid)
   case(2)
      call step(int(x,ik(2)),y-1,grid)
   case(3)
      call step(int(x-1,ik(3)),y,grid)
   end select
   write(*,'(1x,a)') grid
end program generic_recurse

But the whole world hates my example!

C:\g95_stuff\clf\generic_recurse>lf95 -f95 generic_recurse
[snip]
Compiling file generic_recurse.f90.
Compiling program unit mykinds at line 1:
Compiling program unit step_up at line 9:
  1711-S: "generic_recurse.f90", line 19, column 24: step_up already used as
an
external subroutine name.
  2516-S: "generic_recurse.f90", line 52, column 12: Reference to step not
consi
stent with any specific interface of the generic interface.
Compiling program unit step_right at line 61:
  1711-S: "generic_recurse.f90", line 79, column 24: step_right already used
as
an external subroutine name.
  2516-S: "generic_recurse.f90", line 106, column 12: Reference to step not
cons
istent with any specific interface of the generic interface.
Compiling program unit step_down at line 113:
  1711-S: "generic_recurse.f90", line 139, column 24: step_down already used
as
an external subroutine name.
  2516-S: "generic_recurse.f90", line 160, column 12: Reference to step not
cons
istent with any specific interface of the generic interface.
Compiling program unit step_left at line 165:
  1711-S: "generic_recurse.f90", line 199, column 24: step_left already used
as
an external subroutine name.
  2516-S: "generic_recurse.f90", line 214, column 12: Reference to step not
cons
istent with any specific interface of the generic interface.
Compiling program unit generic_recurse at line 217:
Encountered 8 errors, 0 warnings in file generic_recurse.f90.

C:\g95_stuff\clf\generic_recurse>df generic_recurse
[snip]
generic_recurse
generic_recurse.F90(19) : Error: Conflicting attributes or multiple
declaration
of name. [STEP_UP]
      module procedure step_up
-----------------------^
generic_recurse.F90(52) : Error: There is no matching specific subroutine
for th
is generic subroutine call. [STEP]
      call step(int(x,ik(0)),y+1,grid)
-----------^
generic_recurse.F90(79) : Error: Conflicting attributes or multiple
declaration
of name. [STEP_RIGHT]
      module procedure step_right
-----------------------^
generic_recurse.F90(106) : Error: There is no matching specific subroutine
for t
his generic subroutine call. [STEP]
      call step(int(x+1,ik(1)),y,grid)
-----------^
generic_recurse.F90(139) : Error: Conflicting attributes or multiple
declaration
 of name. [STEP_DOWN]
      module procedure step_down
-----------------------^
generic_recurse.F90(160) : Error: There is no matching specific subroutine
for t
his generic subroutine call. [STEP]
      call step(int(x,ik(2)),y-1,grid)
-----------^
generic_recurse.F90(199) : Error: Conflicting attributes or multiple
declaration
 of name. [STEP_LEFT]
      module procedure step_left
-----------------------^
generic_recurse.F90(214) : Error: There is no matching specific subroutine
for t
his generic subroutine call. [STEP]
      call step(int(x-1,ik(3)),y,grid)
-----------^

So does the whole world hate my example simple because that's
just what is to be expected, or is my code in error, or is the
whole world just plain wrong, as I often think?

Wait! I do seem to have one friend left in the world:

C:\g95_stuff\clf\generic_recurse>g95 generic_recurse.f90 -ogeneric_recurse

C:\g95_stuff\clf\generic_recurse>generic_recurse
 ........X..
 ...XXXXXX..
 .XXX.X.....
 ...X.X.....
 ...XXX.....
 ...XXX.....
 ...XX......
 ....X......
 ...........
 ...........
 ...........

C:\g95_stuff\clf\generic_recurse>generic_recurse
 ...........
 ...........
 ...........
 ...........
 ...........
 .....X.....
 .....X.....
 ...XXX.....
 ...XX......
 ...X.......
 ...X.......

g95 rejected the first version of my example because it
actually did have a mistake. Now it's OK and does a
random walk from the center to the edge of the grid as
planned, but lf95 and cvf still hate it as shown above.
So is g95 right when both lf95 and cvf are wrong here?
Such a outcome might risk damaging Andy's humility...

-- 
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


Relevant Pages

  • Re: compiler switch -c
    ... All methods must be exposed by interface. ... module procedure fruit_summary_ ... end subroutine init_fruit_ ... character, intent, optional:: message ...
    (comp.lang.fortran)
  • TRANSFER arbitrary data ? (long)
    ... subroutine to minimize a function of n variables, ... end interface ... that to an integer array and back. ... subroutine minimize(Func, x, context) ...
    (comp.lang.fortran)
  • Re: Copy-in/Copy-out
    ... Compiling program unit SubNormal at line 90: ... procedure definition and A in interface body shall be the same. ... -|> declared as a target or pointer, it should be safe to assign a pointer ... -| Subroutine SubTarget! ...
    (comp.lang.fortran)
  • Re: Error message from random number generation
    ... and then determine the Cholesky decomposition. ... subroutine that generates MVN values. ... Parameter 1 was incorrect on entry to vslDeleteStr ... Do you need an interface to ...
    (comp.lang.fortran)
  • Re: Assumed-shape arrays and dummy procedures
    ... dummy procedure. ... so there is no way for the caller to check its interface. ... subroutine callthru ... implicit logical ...
    (comp.lang.fortran)