To: J3 J3/23-102r3 From: T. Clune & subgroup generics Subject: Formal syntax for generics Date: 2023-February-24 Reference: 22-120r5, 22-151r3, 22-154r5, 23-007 1. Introduction =============== This paper contains the syntax for generic programming features. Section 2 contains a succinct, non-pedagogical example that exercises most of the proposed syntax. Section 3 provides the formal syntax and is further broken into the following subsections: 3.1 Deferred entities 3.1.1 Syntax for deferred arguments 3.1.2 Deferred argument association 3.2 Syntax for the REQUIREMENT construct 3.2.1 Requirement interface body 3.3 Syntax for the REQUIRES statement 3.4 Syntax for the TEMPLATE construct 3.4.1 Template specification part 3.4.2 Template subprogram part 3.4.3 Additional constraint 3.5 Syntax for the INSTANTIATE statement Section 4 provides other miscellaneous changes. 2. Example ========== MODULE A REQUIREMENT R(T,F) TYPE, DEFERRED :: T FUNCTION F(x, i) RESULT(y) TYPE(T) :: y TYPE(T), INTENT(IN) :: x INTEGER, INTENT(IN) :: i END FUNCTION F END REQUIREMENT R TEMPLATE B(T,F,C) REQUIRES R(T,F) ! provides interface for deferred F TYPE, DEFERRED :: T ! redundant decl of deferred type T INTEGER, CONSTANT :: C(..) ! deferred rank constant CONTAINS SUBROUTINE SUB1(x) TYPE(T), INTENT(INOUT) :: x x = F(x, SUM(C)) END SUBROUTINE SUB1 SUBROUTINE SUB2(x) TYPE(T), INTENT(INOUT) :: x x = F(x, MAXVAL(C)) END SUBROUTINE SUB2 END TEMPLATE B END MODULE A MODULE B USE MODULE A INSTANTIATE B(REAL, OPERATOR(*), [3,4]), ONLY: & & tot_sub1 => sub1 INSTANTIATE B(REAL, OPERATOR(+), [3,4]), ONLY: & ! different instance & max_sub1 => sub2 CONTAINS SUBROUTINE DO_SOMETHING(x) REAL, INTENT(INOUT) :: x x = 2. CALL tot_sub(x) PRINT*,'TOT: ', x ! expect 2. * (3+4) = 14. x = 3. CALL max_sub(x) PRINT*,'MAX: ', x ! expect 3. + max(3,4) = 7. END SUBROUTINE DO_SOMETHING END MODULE B 3. Formal Syntax ================ 3.1 Deferred entities -------------------- A deferred argument is an entity that takes some of its characteristics from its ultimate instantiation argument. A deferred argument can be a constant, type, or procedure and can appear in a REQUIREMENT or TEMPLATE construct (3.2, 3.4). Association with instantiation arguments occurs in the REQUIRES and INSTANTIATE statements. A deferred constant is a deferred argument that can appear in constant expressions with a REQUIREMENT or TEMPLATE construct. A deferred type is a deferred argument that can appear as a type-spec within a REQUIREMENT or TEMPLATE construct. A deferred procedure is a deferred argument that can appear in procedure references within a REQUIREMENT or TEMPLATE construct. A deferred procedure's interface shall be defined by that REQUIREMENT or TEMPLATE construct, possibly in terms of deferred types and constants. 3.1.1 Syntax for deferred arguments ----------------------------------- A deferred argument declaration construct is used to declare REQUIREMENT or TEMPLATE arguments. <> <> <> <> <> <> , :: <> [,]... CONSTANT [,]... <> CONTIGUOUS <> <> Constraint: An entity declared in shall be INTEGER, LOGICAL, or assumed-length character. <> [ ( ) ] Contraint: If appears in , it shall not be , , or . <> Constraint: Each shall appear in of the innermost scoping unit. A is a deferred constant. <> PROCEDURE[()] :: <> Constraint: Each that appears in a shall appear in of the innermost scoping unit. Constraint: Each shall appear in a or as a or within an or a . A is a deferred procedure. A that appears as the or in an or a is a deferred procedure. <> TYPE, DEFERRED :: <> Constraint: Each shall appear in of the innermost scoping unit. Constraint: A declaration shall not have an nor shall it appear in a PUBLIC statement. A is a deferred type. Note: Deferred arguments are local identifiers and are not externally accessible. 3.1.2 Deferred argument association ----------------------------------- Instantiation arguments are specified by either an INSTANTIATE or a REQUIRES statement. <> [ = ] Constraint: Each shall be the name of a in the referenced requirement or template. In the absence of an argument keyword, an instantiation argument corresponds to the deferred argument occupying the corresponding position in ; that is, the first instantiation argument corresponds to the first deferred argument in the reduced list, the second instantiation argument corresponds to the second deferred argument in the reduced list, etc. <> <> <> <> Constraint: shall be type INTEGER, LOGICAL or CHARACTER. Constraint: An that is a shall correspond to a that is declared as a in the referenced template or requirement. Constraint: The type and kind of an that is a shall have the same type and kind of the declaration of the corresponding in the referenced template or requirement. Constraint: If the shape of the corresponding in the referenced template or requirement is not assumed, then shall have the same shape. Constraint: If the rank of the corresponding in the referenced template or requirement is not assumed, then shall have the same rank. Constraint: An that is a shall correspond to a that is declared as a in the referenced template or requirement. Constraint: If an is a , it shall be allowed for a variable of that type to appear in a variable definition context. Constraint: A shall only appear as an instantiation argument if a variable of that type is permitted in a variable definition context. Constraint: A shall only appear as an instantiation argument if a variable of that type is permitted in an allocate statement. Constraint: If an is a , it shall not specify a type that has a coarray potential subobject component. Constraint: An that is a or shall correspond to a that is declared as a in the referenced template or requirement. Constraint: An that is a shall have the same characteristics as the corresponding in the referenced template or requirement. Constraint: An that is a shall have one specific procedure that has the same characteristics as the corresponding in the referenced template or requirement. Note: The previous two constraints constitute what is referred to as "weak constraints" in other languages. The shall be associated with the specific procedure that is consistent with the characteristics. 3.2 Syntax for the REQUIREMENT construct ---------------------------------------- A REQUIREMENT is a named collection of deferred argument declarations intended to facilitate reuse of common patterns within templates and other requirements. <> REQUIREMENT ( [] ) [ ] ... ... END [REQUIREMENT []] <> <> Constraint: Each shall appear in a . Note: A is a scoping unit that allows use and host association. Each is local to the REQUIREMENT construct. 3.2.1 Requirement interface body -------------------------------- A declares a as a deferred procedure and defines its interface. <> [ ] <> [ ] Constraint: Each and in a shall be a . <> [ ] ... [ ] ... <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> [ [ , ] ... :: ] <> ALLOCATABLE <> ASYNCHRONOUS <> CODIMENSION <> CONTIGUOUS <> DIMENSION ( ) <> INTENT ( ) <> OPTIONAL <> PARAMETER <> POINTER <> <> TARGET <> VALUE <> VOLATILE A is a scoping unit that has use and host association. Note: Unlike of the or , allows access to host scope entities by default, and does not allow using the IMPORT statement. 3.3 Syntax for the REQUIRES statement ------------------------------------- A REQUIRES statement provides declarations of deferred arguments by associating them with the deferred arguments of a REQUIREMENT. <> REQUIRES [::] ( [] ) Constraint: shall be the name of a previously defined . <> [ = ] Constraint: Each shall be the name of a in the referenced requirement. 3.4 Syntax for the TEMPLATE construct ------------------------------------- A template is a set of declarations, specifications and definitions that are enabled by instantiation. A TEMPLATE construct defines a template. A template is a scoping unit to which use and host association and template argument association can be applied. A template can be defined in the specification section of a program unit other than a block data program unit.