To: J3 J3/22-124 From: Tom Clune & generics subgroup Subject: Generics formal specs Date: 2022-February-21 Reference: 22-120r1, 21-144r4 1. Introduction =============== Paper 21-144r4 provided use cases for Fortran generics feature, and paper 22-120r1 provided formal requirements. This paper provides formal specifications. 2. Formal specs =============== A. TEMPLATE is a named scoping unit. B1. A TEMPLATE definition has the following elements: - TEMPLATE name - list of TEMPLATE dummy parameters - specification section (possibly empty) - optional procedure section begining with a CONTAINS statement Aside: I.e., this looks very much like a module in most respects. Suggestive syntax: TEMPLATE T([param1[, param2[, ...]]]) ! specification section CONTAINS ! procedure definitions END TEMPLATE T B2. The permitted order of statements in a TEMPLATE is the same as that for modules. B3. A TEMPLATE dummy parameter declaration must appear before any reference to that parameter and must appear after any USE, IMPORT, and IMPLICIT NONE statements in the TEMPLATE. Suggestive syntax: TEMPLATE TMPL(T, FLAG, sub) TYPE :: T; END TYPE ! dummy type parameter LOGICAL :: FLAG ! dummy constant (logical) parameter INTERFACE SUBROUTINE sub(x, y) ! dummy subroutine parameter TYPE(T), INTENT(IN) :: x TYPE(T), INTENT(OUT) :: y END SUBROUTINE END INTERFACE C. A TEMPLATE can be defined in the specification section of: - PROGRAM - MODULE - SUBMODULE - procedure (including internal subprogram) - BLOCK construct - another TEMPLATE Aside: Basically any place that a TYPE can be defined. Straw Vote 1: Should a TEMPLATE be permitted to contain an internal TEMPLATE definition? YES-NO-UNDECIDED D. A TEMPLATE may only be referenced by host association or use association. E1. There shall be a nonexecutable specification construct INSTANTIATE for instantiating templates by providing the means by which a scoping unit defines named entities provided by a TEMPLATE. E2. An INSTANTIATE statement must provide the name of an accessible TEMPLATE and a list of TEMPLATE actual parameters corresponding to the TEMPLATE dummy parameters of the specified TEMPLATE. Suggestive syntax: TEMPLATE MY_TMPL(U, V, S) ... END TEMPLATE MY_TMPL ... ! Host association ... INSTANTIATE MY_TMPL(MY_U, MY_V, MY_SUBR) E4. The INSTANTIATE statement can appear only in the specification section in any of: - PROGRAM - MODULE - SUBMODULE - another TEMPLATE - procedure - BLOCK construct Aside: I.e., any place one could declare a variable. E5. The INSTANTIATE feature must allow functionality analogous to the ONLY and rename clauses of module USE statements to enable disambiguation of provided entities. Suggestive syntax: USE my_module, ONLY: T ! T is a TEMPLATE ... ! The following statement provides access to the entity S ! defined inside TEMPLATE T, but using the name S_1 INSTANTIATE :: T(param1, param2), ONLY: S_1 => S F1. A RESTRICTION is a specifier that establishes a set of relations among its dummy parameters. F3. A relation is an interface body defined in a RESTRICTION. F4. A RESTRICTION definition has the following elements: - RESTRICTION name - nonempty list of RESTRICTION dummy parameters - specification section that consists of * declaration of RESTRICTION dummy parameters * interface blocks that define relations among the dummy parameters * REQUIRES statements (see below) Rationale: Allowing REQUIRES within a RESTRICTION provides the ability to assemble complex RESTRICTIONS and reduces duplication. Aside: This looks a bit like a TEMPLATE in terms of its parameters, but is much narrower in terms of what is allowed in the contents. Suggestive syntax: RESTRICTION C(T, U, FUNC) TYPE :: T; END TYPE TYPE :: U; END TYPE INTERFACE END INTERFACE END RESTRICTION C F5. Declarations of a RESTRICTION dummy parameter must precede any reference to that parameter. G. A RESTRICTION can be defined in the specification section of: - PROGRAM - MODULE - SUBMODULE - TEMPLATE - procedure (including internal subprogram) - BLOCK construct H. A RESTRICTION can only be referenced by host association or use association. Suggestive syntax: RESTRICTION R(...) ... END RESTRICTION TEMPLATE T(...) REQUIRES R(...) ! host association END TEMPLATE I. Each relation in a RESTRICTION establishes the interface of a single SUBROUTINE, FUNCTION, or OPERATOR corresponding to a RESTRICTION dummy parameter. NOTE: Further generalization is possible and possibly desirable, but the above satisfies the current use cases driving this design. J1. There shall be a nonexecutable specification statement REQUIRES which is used to enforce a RESTRICTION during the instantiation of a TEMPLATE as well as to limit permitted operations used within the template. See UTI-8 J2. A REQUIRES statement must provide the name of an accessible named RESTRICTION and a list of RESTRICTION actual parameters corresponding to the RESTRICTION dummy parameters. Suggestive syntax: RESTRICTION MAGMA(T, binaryop) TYPE :: T; END TYPE INTERFACE PURE FUNCTION binaryop(x, y) RESULT(z) TYPE(T) :: z TYPE(T), INTENT(IN) :: x, y END FUNCTION END INTERFACE END RESTRICTION MAGMA TEMPLATE MY_TMPL2(U, V, plus, times) ... REQUIRES MAGMA(U, plus) ! U = plus(u,u) REQUIRES MAGMA(V, times) ! V = times(v,v) ... END TEMPLATE J3. A REQUIRES statement may be placed only in the specification section of a TEMPLATE. See UTI-8 L. A TEMPLATE may be instantiated only if all of the relations established by the REQUIRES statements hold for the TEMPLATE actual parameters. This is referred to as "weak" constraints/concepts. M1. A TEMPLATE may only reference a dummy parameter that is a SUBROUTINE, FUNCTION, or OPERATOR if the relevant interface is defined in a REQUIRES statement within the TEMPLATE. This is referred to as "strong" constraints/concepts. A example with suggestive syntax: MODULE M1 ... public :: T1, F TEMPLATE T1(T, G) END TEMPLATE END MODULE M1 ... TEMPLATE T2(...) USE M1, ONLY :: F, T1 END TEMPLATE Straw vote: May a TEMPLATE definition use intrinsic assignment for TEMPLATE dummy parameters without a corresponding RESTRICTION? YES-NO-undecided PRO: This is a common situation and virtually all Fortran types satisfy this property. Adding the appropriate RESTRICTION will be a bit tedious and may confuse some developers. CONS: This creates a small hole in the intent of "strong" constraints. M2. A TEMPLATE dummy parameter that is a SUBROUTINE, FUNCTION or OPERATOR must appear in exactly one REQUIRES statement. M3. A RESTRICTION dummy parameter that is a SUBROUTINE, FUNCTION or OPERATOR must be given a single interface. E.g., the following pseudocode is illegal because F is given 2 different interfaces. RESTRICTION R(T, U, F) TYPE :: T; END TYPE TYPE :: U; END TYPE INTERFACE FUNCTION F(x,y) RESULT(z) TYPE(T) :: x, y, z END FUNCTION FUNCTION F(x,y) RESULT(z) TYPE(U) :: x, y, z END FUNCTION END INTERFACE END RESTRICTION M4. No variable of a type corresponding to a TEMPLATE dummy parameter may be used as an actual argument to a SUBROUTINE, FUNCTION, or OPERATOR unless the corresponding dummy argument is declared with the same TEMPLATE dummy parameter type. M5. A TEMPLATE dummy parameter which is a type name is indistinguishable from any other type in a procedure characteristic for the purposes of generic interface definition. For example the following is illegal: TEMPLATE TMPL(T, U) PUBLIC :: BAR INTERFACE BAR MODULE SUBROUTINE BAR_T(x) TYPE(T) :: x END SUBROUTINE MODULE SUBROUTINE BAR_i(x)! Ambiguous: what if T is integer? TYPE(integer) :: x END SUBROUTINE MODULE SUBROUTINE BAR_U(x)! Ambiguous: what if U is same as T? TYPE(U) :: x END SUBROUTINE END INTERFACE END TEMPLATE M6. A TEMPLATE dummy parameter which is a type name may not be extended within the template. E.g., TEMPLATE TMPL(T) TYPE :: T; END T TYPE, EXTENDS(T) :: CHILD ! Illegal END TYPE END TEMPLATE 3. Unresolved technical issues ============================== UTI-8: Where can a REQUIRES statement go? Something analogous might be useful in terms of expressing programmers intent in satisfying a REQUIREMENT in non TEMPLATE contexts; possibly with a different syntax term for clarity. ===END===