3 ! Copyright 2015 NVIDIA Corporation
5 ! Test case for unlimited polymorphism that is derived from the article
6 ! by Mark Leair, in the 'PGInsider':
7 ! https://www.pgroup.com/lit/articles/insider/v3n2a2.htm
8 ! Note that 'addValue' has been removed from the generic 'add' because
9 ! gfortran asserts that this is ambiguous. See
10 ! https://gcc.gnu.org/ml/fortran/2015-03/msg00002.html for a discussion.
14 public :: link, output, index
15 character(6) :: output (14)
19 class(*), pointer :: value => null() ! value stored in link
20 type(link), pointer :: next => null()! next link in list
22 procedure :: getValue ! return value pointer
23 procedure :: printLinks ! print linked list starting with this link
24 procedure :: nextLink ! return next pointer
25 procedure :: setNextLink ! set next pointer
29 procedure constructor ! construct/initialize a link
34 function nextLink(this)
36 class(link), pointer :: nextLink
40 subroutine setNextLink(this,next)
42 class(link), pointer :: next
44 end subroutine setNextLink
46 function getValue(this)
48 class(*), pointer :: getValue
49 getValue => this%value
52 subroutine printLink(this)
57 select type(v => this%value)
59 write (output(index), '(i6)') v
60 type is (character(*))
61 write (output(index), '(a6)') v
63 write (output(index), '(f6.2)') v
65 stop 'printLink: unexepected type for link'
68 end subroutine printLink
70 subroutine printLinks(this)
72 class(link), pointer :: curr
76 do while(associated(curr))
83 function constructor(value, next)
84 class(link),pointer :: constructor
86 class(link), pointer :: next
88 constructor%next => next
89 allocate(constructor%value, source=value)
90 end function constructor
100 class(link),pointer :: firstLink => null() ! first link in list
101 class(link),pointer :: lastLink => null() ! last link in list
103 procedure :: printValues ! print linked list
104 procedure :: addInteger ! add integer to linked list
105 procedure :: addChar ! add character to linked list
106 procedure :: addReal ! add real to linked list
107 procedure :: addValue ! add class(*) to linked list
108 procedure :: firstValue ! return value associated with firstLink
109 procedure :: isEmpty ! return true if list is empty
110 generic :: add => addInteger, addChar, addReal
115 subroutine printValues(this)
118 if (.not.this%isEmpty()) then
119 call this%firstLink%printLinks()
121 end subroutine printValues
123 subroutine addValue(this, value)
126 class(link), pointer :: newLink
128 if (.not. associated(this%firstLink)) then
129 this%firstLink => link(value, this%firstLink)
130 this%lastLink => this%firstLink
132 newLink => link(value, this%lastLink%nextLink())
133 call this%lastLink%setNextLink(newLink)
134 this%lastLink => newLink
137 end subroutine addValue
139 subroutine addInteger(this, value)
142 class(*), allocatable :: v
143 allocate(v,source=value)
144 call this%addValue(v)
145 end subroutine addInteger
147 subroutine addChar(this, value)
149 character(*) :: value
150 class(*), allocatable :: v
152 allocate(v,source=value)
153 call this%addValue(v)
154 end subroutine addChar
156 subroutine addReal(this, value)
159 class(*), allocatable :: v
161 allocate(v,source=value)
162 call this%addValue(v)
163 end subroutine addReal
165 function firstValue(this)
167 class(*), pointer :: firstValue
169 firstValue => this%firstLink%getValue()
171 end function firstValue
173 function isEmpty(this)
177 if (associated(this%firstLink)) then
187 use link_mod, only : output
191 type(list) :: my_list
196 call my_list%add(1.23)
197 call my_list%add('A')
198 call my_list%add('BC')
199 call my_list%add('DEF')
200 call my_list%printvalues()
204 read (output(i), '(i6)') j
207 if (output(i) .ne. " 1.23") STOP 2
209 if (output(i) .ne. " A") STOP 3
211 if (output(i) .ne. " BC") STOP 4
213 if (output(i) .ne. " DEF") STOP 5