blob: 06a61a519e063340bc79ece47ccdf1c29c8f1c58 [file] [log] [blame]
! { dg-do run }
!
! Contributed by by Richard Maine
! http://coding.derkeiler.com/Archive/Fortran/comp.lang.fortran/2006-10/msg00104.html
!
module poly_list
!-- Polymorphic lists using type extension.
implicit none
type, public :: node_type
private
class(node_type), pointer :: next => null()
end type node_type
type, public :: list_type
private
class(node_type), pointer :: head => null(), tail => null()
end type list_type
contains
subroutine append_node (list, new_node)
!-- Append a node to a list.
!-- Caller is responsible for allocating the node.
!---------- interface.
type(list_type), intent(inout) :: list
class(node_type), target :: new_node
!---------- executable code.
if (.not.associated(list%head)) list%head => new_node
if (associated(list%tail)) list%tail%next => new_node
list%tail => new_node
return
end subroutine append_node
function first_node (list)
!-- Get the first node of a list.
!---------- interface.
type(list_type), intent(in) :: list
class(node_type), pointer :: first_node
!---------- executable code.
first_node => list%head
return
end function first_node
function next_node (node)
!-- Step to the next node of a list.
!---------- interface.
class(node_type), target :: node
class(node_type), pointer :: next_node
!---------- executable code.
next_node => node%next
return
end function next_node
subroutine destroy_list (list)
!-- Delete (and deallocate) all the nodes of a list.
!---------- interface.
type(list_type), intent(inout) :: list
!---------- local.
class(node_type), pointer :: node, next
!---------- executable code.
node => list%head
do while (associated(node))
next => node%next
deallocate(node)
node => next
end do
nullify(list%head, list%tail)
return
end subroutine destroy_list
end module poly_list
program main
use poly_list
implicit none
integer :: cnt
type, extends(node_type) :: real_node_type
real :: x
end type real_node_type
type, extends(node_type) :: integer_node_type
integer :: i
end type integer_node_type
type, extends(node_type) :: character_node_type
character(1) :: c
end type character_node_type
type(list_type) :: list
class(node_type), pointer :: node
type(integer_node_type), pointer :: integer_node
type(real_node_type), pointer :: real_node
type(character_node_type), pointer :: character_node
!---------- executable code.
!----- Build the list.
allocate(real_node)
real_node%x = 1.23
call append_node(list, real_node)
allocate(integer_node)
integer_node%i = 42
call append_node(list, integer_node)
allocate(node)
call append_node(list, node)
allocate(character_node)
character_node%c = "z"
call append_node(list, character_node)
allocate(real_node)
real_node%x = 4.56
call append_node(list, real_node)
!----- Retrieve from it.
node => first_node(list)
cnt = 0
do while (associated(node))
cnt = cnt + 1
select type (node)
type is (real_node_type)
write (*,*) node%x
if (.not.( (cnt == 1 .and. node%x == 1.23) &
.or. (cnt == 5 .and. node%x == 4.56))) then
STOP 1
end if
type is (integer_node_type)
write (*,*) node%i
if (cnt /= 2 .or. node%i /= 42) STOP 2
type is (node_type)
write (*,*) "Node with no data."
if (cnt /= 3) STOP 3
class default
Write (*,*) "Some other node type."
if (cnt /= 4) STOP 4
end select
node => next_node(node)
end do
if (cnt /= 5) STOP 5
call destroy_list(list)
stop
end program main