The ``superclass'' set of m4 macros is used to automatically create a superclass module that will dynamically dispatch superclass calls to the correct subclass routine or function. This achieves run-time polymorphism, which is commonly considered to be too much effort in Fortran 90, in an easily implemented fashion.
To use the ``superclass'' set of m4 macros certain naming and coding conventions must be followed. Assuming that the superclass name is ``Matrix'', that three subclasses exist named ``One'', ``Two'', and ``Three'', and that the routine to be dynamically dispatched is named ``Solve'', the following names must be used:
| superclass derived type: | Matrix_type |
| subclass derived types: | One_type, Two_type, Three_type |
| subclass module names: | One_Class, Two_Class, Three_Class |
| superclass module name: | Matrix_Class |
| superclass routine name: | Solve_Matrix |
| superclass interface name: | Solve |
| subclass routine names: | Solve_One, Solve_Two, Solve_Three |
| subclass interface name: | Solve |
In addition, the superclass derived type must be:
type Matrix_type
character (len=80) :: Subclass
type(One_type) :: One
type(Two_type) :: Two
type(Three_type) :: Three
end type Matrix_type
To use the superclass macros in the CÆSAR Code Package,
Take the following code segment as an example:
define([SUPERCLASS],[Matrix])
define([SUBCLASSES],[One Two Three])
module SUPERCLASS[]_Class
SUPERCLASS_USE_ASSOCIATIONS
SUPERCLASS_TYPE
contains
SUPERCLASS_ROUTINE([Initialize],
[type(real)], [a], [The a variable],
[type(integer), intent(in)], [b], [The b variable])
SUPERCLASS_FUNCTION([Verify_State], [type(logical)],
[type(real)], [b], [The b variable])
SUPERCLASS_ROUTINE([Finalize],
[type(real)], [c], [The c variable],
[type(real)], [d], [The d variable])
end module SUPERCLASS[]_Class
This code is expanded by Gnu m4 into the following valid F90 code:
module Matrix_Class
use One_Class
use Two_Class
use Three_Class
type Matrix_type
character (len=80) :: Subclass
type(One_type) :: One
type(Two_type) :: Two
type(Three_type) :: Three
end type Matrix_type
contains
subroutine Initialize_Matrix (Matrix, a, b)
type(Matrix_type) Matrix
real (kind=KIND(1.0d0)) :: a ! The a variable
integer (kind=KIND(1)), intent(in) :: b ! The b variable
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
select case (Matrix%Subclass)
case ("One")
call Initialize (Matrix%One, a, b)
case ("Two")
call Initialize (Matrix%Two, a, b)
case ("Three")
call Initialize (Matrix%Three, a, b)
case default
write (6,*) 'Error: no ', Matrix%Subclass, ' in Matrix_Class.'
end select
end subroutine Initialize_Matrix
function Verify_State_Matrix (Matrix, b)
type(Matrix_type) Matrix
logical (kind=KIND(.true.)) :: Verify_State, Verify_State_Matrix
real (kind=KIND(1.0d0)) :: b ! The b variable
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
select case (Matrix%Subclass)
case ("One")
Verify_State_Matrix = Verify_State (Matrix%One, b)
case ("Two")
Verify_State_Matrix = Verify_State (Matrix%Two, b)
case ("Three")
Verify_State_Matrix = Verify_State (Matrix%Three, b)
case default
write (6,*) 'Error: no ', Matrix%Subclass, ' in Matrix_Class.'
end select
end function Verify_State_Matrix
subroutine Finalize_Matrix (Matrix, c, d)
type(Matrix_type) Matrix
real (kind=KIND(1.0d0)) :: c ! The c variable
real (kind=KIND(1.0d0)) :: d ! The d variable
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
select case (Matrix%Subclass)
case ("One")
call Finalize (Matrix%One, c, d)
case ("Two")
call Finalize (Matrix%Two, c, d)
case ("Three")
call Finalize (Matrix%Three, c, d)
case default
write (6,*) 'Error: no ', Matrix%Subclass, ' in Matrix_Class.'
end select
end subroutine Finalize_Matrix
end module Matrix_Class
Note that this set of m4 macros depends on the m4 commands in the settings.m4 file and on the SUPERCLASS and SUBCLASSES macro definitions.
m4 macros defined in the include/superclass.m4 file:
| SUPERCLASS_ARGUMENTS | Used internally by the SUPERCLASS_ROUTINE and SUPERCLASS_FUNCTION macros. | ||
| SUPERCLASS_DECLARATIONS | Used internally by the SUPERCLASS_ROUTINE and SUPERCLASS_FUNCTION macros. | ||
| SUPERCLASS_FUNCTION | Expands into a complete function for the superclass. This function dynamically dispatches calls to the superclass to the correct subclass function. | ||
| SUPERCLASS_ROUTINE | Expands into a complete subroutine for the superclass. This subroutine dynamically dispatches calls to the superclass to the correct subclass routine. | ||
| SUPERCLASS_TYPE | Outputs a standard superclass type definition. | ||
| SUPERCLASS_USE_ASSOCIATIONS | Outputs the correct use associations for the superclass. |
The Superclass m4 Macros code listing contains additional documentation.
Michael L. Hall