The main documentation of the Superclass m4 Macros contains additional explanation of this code listing.
dnl
dnl Author: Michael L. Hall
dnl P.O. Box 1663, MS-D409, LANL
dnl Los Alamos, NM 87545
dnl ph: 505-665-4312
dnl email: hall@lanl.gov
dnl
dnl Created on: 1/20/99
dnl Date: 03/21/00, 17:19:14
dnl Version: 4.6
dnl The MAKE_INTERFACES macro expands into standard interface
dnl specifications using the arguments:
dnl
dnl $1 - Specific Class Suffix
dnl $2 - Generic Interface Names (separated by spaces)
define([MAKE_INTERFACES],[
public :: m4_patsubst(m4_shift($@), [ ], [, ])
fortext([BASENAME], m4_shift($@), [
interface BASENAME
module procedure BASENAME[]_[]$1
end interface
]) ])
dnl MAKE_INTERFACES([One], [Initialize Verify_State Finalize])
dnl The SUPERCLASS_USE_ASSOCIATIONS macro outputs the needed "use
dnl association" statements based on the definition of SUBCLASSES,
dnl which should be a space-delimited list of the subclasses.
define([SUPERCLASS_USE_ASSOCIATIONS],[
fortext([subclass], SUBCLASSES, [
use subclass[]_Class
]) ])
dnl The SUPERCLASS_TYPE macro outputs a standard superclass type
dnl definition. It requires the following definitions:
dnl
dnl - SUPERCLASS should already be defined to be the name of the
dnl superclass.
dnl
dnl - SUBCLASSES should already be defined to be a space-delimited
dnl list of the subclasses.
define([SUPERCLASS_TYPE],[
type SUPERCLASS[]_type
type(character,80) :: Subclass
fortext([subclass], SUBCLASSES, [
type(subclass[]_type) :: subclass
])
end type SUPERCLASS[]_type
])
dnl Define the SUPERCLASS_DECLARATIONS macro, which is used internally
dnl by the SUPERCLASS_ROUTINE and SUPERCLASS_FUNCTION macros. This macro
dnl takes each group of three arguments, expands them in a declaration
dnl form like so:
dnl
dnl $1 :: $2 ! $3
dnl
dnl and shifts them off the stack. It then continues with the next
dnl group of three arguments until there are no more arguments.
define([SUPERCLASS_DECLARATIONS],[
ifelse($#, 0, ,
$#, 1, [$1],
$#, 2, [$1 :: $2],
$#, 3, [$1 :: $2 [!] $3],
[$1 :: $2 [!] $3 SUPERCLASS_DECLARATIONS(m4_shift(m4_shift(m4_shift($@))))]
)])
dnl Define the SUPERCLASS_ARGUMENTS macro, which is used internally
dnl by the SUPERCLASS_ROUTINE and SUPERCLASS_FUNCTION macros. This macro
dnl takes each group of three arguments (in the same form as the
dnl SUPERCLASS_DECLARATIONS argument list) and pulls out the second
dnl argument (the actual variable) only, like so:
dnl
dnl , $2
dnl
dnl and shifts the original three arguments off the stack. It then
dnl continues with the next group of three arguments until there are
dnl no more arguments. At the end of this operation, a variable list
dnl has been extracted in this form:
dnl
dnl , var1, var2, var3, var4
define([SUPERCLASS_ARGUMENTS],
[ifelse($#, 0, ,
$#, 1, ,
$#, 2, [, $2],
$#, 3, [, $2],
[, $2[]SUPERCLASS_ARGUMENTS(m4_shift(m4_shift(m4_shift($@))))])])
dnl Define the SUPERCLASS_ROUTINE macro, which expands into a complete
dnl subroutine for the superclass. This subroutine dynamically
dnl dispatches calls to the superclass to the correct subclass routine.
dnl There are some restrictions that must be true for this macro to
dnl behave correctly:
dnl
dnl - SUPERCLASS should already be defined to be the name of the
dnl superclass.
dnl
dnl - SUBCLASSES should already be defined to be a space-delimited
dnl list of the subclasses.
dnl
dnl - The argument list for the superclass subroutine call must be the
dnl same as the argument list for all of the subclass subroutine calls,
dnl with the exception that the subclass calls are passed a component
dnl of the superclass derived type corresponding to that subclass
dnl instead of the entire superclass derived type.
dnl
dnl - The superclass type must correspond to the type generated by the
dnl the SUPERCLASS_TYPE macro.
dnl
dnl The arguments for the SUPERCLASS_ROUTINE macro are:
dnl
dnl $1 - Generic Routine (and Interface) Name.
dnl $(2 + n*3) - Type declaration for an additional variable to be added
dnl to the argument list.
dnl $(3 + n*3) - Variable name for an additional variable to be added
dnl to the argument list.
dnl $(4 + n*3) - Comment for an additional variable to be added to the
dnl argument list.
dnl
dnl where n may be 0, 1, 2, etc., and the only required macro argument is
dnl the first one.
define([SUPERCLASS_ROUTINE],[
pushdef([ROUT_NAME], [$1_[]SUPERCLASS])
pushdef([VARLIST], [m4_shift($@)])
pushdef([ARGS], [SUPERCLASS_ARGUMENTS(VARLIST)])
subroutine ROUT_NAME (SUPERCLASS[]ARGS)
type(SUPERCLASS[]_type) SUPERCLASS
SUPERCLASS_DECLARATIONS(VARLIST)
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
select case (SUPERCLASS%Subclass)
fortext([subclass], SUBCLASSES, [
case ("subclass")
call $1 (SUPERCLASS%subclass[]ARGS)
])
case default
write (6,*) 'Error: no ', SUPERCLASS%Subclass, ' in SUPERCLASS[]_Class.'
end select
end subroutine ROUT_NAME
popdef([ROUT_NAME])
popdef([VARLIST])
popdef([ARGS])
])
dnl Define the SUPERCLASS_FUNCTION macro, which expands into a complete
dnl function for the superclass. This subroutine dynamically
dnl dispatches calls to the superclass to the correct subclass function.
dnl There are some restrictions that must be true for this macro to
dnl behave correctly:
dnl
dnl - SUPERCLASS should already be defined to be the name of the
dnl superclass.
dnl
dnl - SUBCLASSES should already be defined to be a space-delimited
dnl list of the subclasses.
dnl
dnl - The argument list for the superclass function call must be the
dnl same as the argument list for all of the subclass function calls,
dnl with the exception that the subclass calls are passed a component
dnl of the superclass derived type corresponding to that subclass
dnl instead of the entire superclass derived type.
dnl
dnl - The superclass type must correspond to the type generated by the
dnl the SUPERCLASS_TYPE macro.
dnl
dnl The arguments for the SUPERCLASS_FUNCTION macro are:
dnl
dnl $1 - Generic Function (and Interface) Name.
dnl $2 - Type declaration for the function.
dnl $(3 + n*3) - Type declaration for an additional variable to be added
dnl to the argument list.
dnl $(4 + n*3) - Variable name for an additional variable to be added
dnl to the argument list.
dnl $(5 + n*3) - Comment for an additional variable to be added to the
dnl argument list.
dnl
dnl where n may be 0, 1, 2, etc., and the only required macro arguments are
dnl the first two.
define([SUPERCLASS_FUNCTION],[
pushdef([FNCT_NAME], [$1_[]SUPERCLASS])
pushdef([VARLIST], [m4_shift(m4_shift($@))])
pushdef([ARGS], [SUPERCLASS_ARGUMENTS(VARLIST)])
function FNCT_NAME (SUPERCLASS[]ARGS)
type(SUPERCLASS[]_type) SUPERCLASS
$2 :: $1, FNCT_NAME
SUPERCLASS_DECLARATIONS(VARLIST)
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
select case (SUPERCLASS%Subclass)
fortext([subclass], SUBCLASSES, [
case ("subclass")
FNCT_NAME = $1 (SUPERCLASS%subclass[]ARGS)
])
case default
write (6,*) 'Error: no ', SUPERCLASS%Subclass, ' in SUPERCLASS[]_Class.'
end select
end function FNCT_NAME
popdef([FNCT_NAME])
popdef([VARLIST])
popdef([ARGS])
])
dnl Input text used to generate documentation:
dnl define([SUPERCLASS],[Matrix])
dnl define([SUBCLASSES],[One Two Three])
dnl
dnl module SUPERCLASS[]_Class
dnl
dnl SUPERCLASS_USE_ASSOCIATIONS
dnl SUPERCLASS_TYPE
dnl
dnl contains
dnl
dnl SUPERCLASS_ROUTINE([Initialize],
dnl [type(real)], [a], [The a variable],
dnl [type(integer), intent(in)], [b], [The b variable])
dnl
dnl SUPERCLASS_FUNCTION([Verify_State], [type(logical)],
dnl [type(real)], [b], [The b variable])
dnl
dnl SUPERCLASS_ROUTINE([Finalize],
dnl [type(real)], [c], [The c variable],
dnl [type(real)], [d], [The d variable])
dnl
dnl end module SUPERCLASS[]_Class