From J.L.Schonfelder@liverpool.ac.uk Fri Mar 18 10:52:28 1994
Received: from mailhub.liverpool.ac.uk (mail.liv.ac.uk) by dkuug.dk with SMTP id AA03351
  (5.65c8/IDA-1.4.4j for <SC22WG5@dkuug.dk>); Fri, 18 Mar 1994 11:52:43 +0100
Received: from liverpool.ac.uk by mailhub.liverpool.ac.uk with SMTP (PP) 
          id <19287-0@mailhub.liverpool.ac.uk>; Fri, 18 Mar 1994 10:52:29 +0000
From: "Dr.J.L.Schonfelder" <J.L.Schonfelder@liverpool.ac.uk>
Message-Id: <9403181052.AA19631@uxh.liv.ac.uk>
Subject: Parameterised Datatypes
To: SC22WG5@dkuug.dk (SC22/WG5 members)
Date: Fri, 18 Mar 1994 10:52:28 +0000 (GMT)
X-Mailer: ELM [version 2.4 PL23]
Mime-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Content-Length: 24783
X-Charset: ASCII
X-Char-Esc: 29

Here is the updated version of this proposal. The changes since meeting
128 of x3j3 reflect the votes taken at that meeting. I am sending two
versions. the attached ascii version and a second mail with a postscript
version. (David, The post script would probably be better in the paper
distribution. Do you also want a paper copy on A4 posted to you?)
-----------------------------------------------------------------
                                                          X3J3-129/94-xxx
 To: X3J3 and WG5 (14 March 1994)
 From: Lawrie Schonfelder 
     (on behalf of the UK panel IST/5/-/5)
  
                       Parameterised Derived Types
 
 1 Introduction     
 This paper is an further update of the paper X3J3/94-042r2 in
 the light of X3J3 committee and the OOF subgroup input at
 meeting 128, in particular the approach covered in this paper
 reflects the positive straw votes taken at that meeting. The
 paper has again been discussed by the BSI Fortran panel and
 is presented with their recommendation that it should be
 adopted for Fortran 95.
     There are six main areas of language design where an
 extension such as this impacts the existing langauge and
 where syntax and semantics must be defined. These are:
    the definition of the type,
    declaration of objects of such a type,
    constructing a value of such a type,
    inquiring as to the value of a type-parameter for an
      existing object of such a type,
    intrinsic assignment for objects of such a type, and
    argument association and overload resolution.
 Syntactic forms and semantic rules exist covering the use of
 parameterised intrinsic types in all but the first of these
 areas; for obvious reasons there is no type definition for an
 intrinsic type. The aim of all of the following proposals is
 to extend the notion of type parameterisation to user defined
 types in such a way as to make the manipulation of derived
 types and intrinsic types as consistent and as similar as
 possible. 
 
 2 Technical Description 
 In this section the technical nature of the proposal in each
 of the above areas is covered with sufficient detail to
 indicate the essential nature of the proposed syntax and
 semantics. This is done informally with the approach
 illustrated by example rather than with detailed syntactic
 and semantic rules. These formal rules will be defined in
 subsequent sections in the form of proposed edits to the
 current standard which would implement the proposed
 extensions. In a few places some indication as to how this
 extension integrates with other interacting extensions
 currently under discussion is given. However, the integrating
 edits are not defined. The editorial processing on X3J3 will
 need to check carefully the interaction between this proposal
 and other proposals in the data types area, in particular the
 extensions proposed for the definition of type defaults and
 object initialisation.
     The intrinsic types have two quite different parameters. 
 There are the static parameters that determine the nature of
 the machine representation. These are all characterised for
 the intrinsic types by the same keyword, KIND, being used for
 such a parameter.  The other parameter variety, where the
 value is not necessarily static, only applies intrinsically
 for the character type.  Here the parameter, LEN, determines
 the length or the number of characters in the datum.  These
 names KIND and LEN are also the generic names of inquiry
 functions used to find the values for these parameters for
 appropriate data objects. A full parameterised data type
 proposal must allow for any number of both sorts of type
 parameter for user defined types and for a general mechanism
 of inquiring as to the actual type parameter values for any
 given object of a parameterised type.
 
 2.1 The Type Definition
 The view is that at this stage we allow only integer type
 parameters in a type definition. This covers 99% or more of
 the important cases where such functionality is required. 
 {   Note, this does not rule out parameters of other types being permitted in some future
      extension, but it does require that any such parameter be explicitly declared. }
 The proposed syntax is to allow a list of dummy type
 parameter names to be added to the type name in the type
 definition statement; rather like the list of dummy arguments
 that are added to a subroutine name on the subroutine
 statement. These dummy type parameters would be permitted as
 primaries in the expressions used to specify the attributes
 of the various components. For example this would allow a
 type definition such as, 
 
 TYPE MATRIX(wkp,dim)
   KIND :: wkp 
   REAL(wkp),DIMENSION(dim,dim) :: element
 ENDTYPE MATRIX
 
 Where wkp and dim are dummy type parameters. The one used to
 determine the kind of the matrix elements and the other the
 order of the matrix.
     The subgroup was convinced that since all type
 definition information is fully available at compile time the
 processor would in fact be able to distinguish which
 parameters were used as "kind" parameters and which are used
 as "len" style, provided kind parameters were always used to
 determine the actual value of a component kind parameter.
 However, it was pointed out in full committee that in some
 cases the type designer may wish to define a type with a
 static parameter that is not actually used in this way. A
 static parameter that was actually used to determine the
 bound of an array and not a component kind might be useful.
 For example, 
 
 TYPE EXTENDED(REPRN)
   KIND :: REPRN
   INTEGER :: power
   INTEGER :: digits(0:REPRN)
 ENDTYPE EXTENDED
  
 In such a type we have chosen to make the parameter which
 effectively determines the precision static. As a static
 parameter this parameter could be used to resolve overloads.
 This is probably the most significant functional difference
 between the static (KIND) parameters and the dynamic
 (nonKIND) parameters. This could not be expressed without the
 explicit declaration of the nature of the parameter. It is
 therefore proposed that explicit declaration of all kind type
 parameters be required.      Semantic restrictions need to be
 defined such that any parameter used to determine the kind of
 a component must be declared as a static "kind" parameter and
 any actual value provided for such a parameter would have to
 be the result of evaluating a scalar integer initialisation
 expression. We also need a restriction which prohibits
 parameters not declared to be kind type parameters being used
 to determine the kind of components. The rules for
 expressions used to declare the attributes of components of
 a parameterised type are that they may be constant
 expressions possibly involving the type parameters as
 primaries. 
     In the light of committee comment it is proposed to
 allow SEQUENCE to be specified for such types. However, the
 rules for using objects of such types in COMMON and
 EQUIVALENCE contexts will be so phrased to ensure that two
 objects of such types can only become storage associated when
 their sequence types are the same and have the same
 parameters with the same values. It will also be required
 that two sequence types are the same if and only if they have
 the same name, define the same type parameters of the same
 kind in the same order and define the same components with
 the same names and the same dependencies on the type
 parameters.
     Note, the above syntax integrates well with the
 initialisation and defined default value proposals. It would
 be possible for a matrix type to be defined with a default
 value of say zero.
 
 TYPE MATRIX(wkp,dim)
   KIND :: wkp
   REAL(wkp),DIMENSION(dim,dim)::element=0.0_wkp
 ENDTYPE MATRIX
 
 This depends on the broadcast of the scalar initialisation
 epression in the array context to be conformant and it uses
 the type parameter to force the correct kind for the value.
 A less realistic but nevertheless perfectly comprehensible
 and implementable alternative which would also be allowed
 could be
 
 TYPE MATRIX(wkp,dim)
   KIND :: wkp
   REAL(wkp),DIMENSION(dim,dim)::element= &
     (/((i*j,i=1,dim),j=1,dim)/)
 ENDTYPE MATRIX
 
 2.2 Object declaration
 Objects of a parameterised type will be declared in ways
 entirely analogous to those used for intrinsic types. For
 example, objects of the above matrix type could be declared,
 
 type(MATRIX(4,3)) :: rotate,trans
 type(MATRIX(KIND(0.0),4)) :: metric
 type(MATRIX(wkp=8,dim=n)) :: weight
 type(MATRIX(wkp=8,dim=*)) :: hessian
 type(MATRIX(dim=2*n+1,wkp=4)) :: distance
 
 where the last statement would be declaring an automatic or
 dummy object and the next to last would be declaring a dummy
 argument that was to assume the type parameter value from the
 associated actual argument, c.f. similar usage with the
 length parameter for characters.
     Where a type is defined with parameters, the type-spec
 in an object  declaration must specify actual values to be
 used to supply values for the dummy type parameters that will
 be used to determine the attributes of the components as
 defined in the type definition. These actual type parameter
 values must be specified as if they were an actual argument
 list following the type name. The association between actual
 and dummy type parameters may be positional or keyword and
 the same rules as for argument association apply.
     Any value that becomes associated with a type parameter
 declared to be a kind type must be specified by an integer
 scalar initialisation expression. The handling from a
 descriptional point of view such LEN-style parameters is
 quite straight forward. Much of the necessary text already
 exists in IS 1539 : 1991 as it applies to the character
 length parameter; in particular the actual values for such
 parameters are provided by specification expressions or are
 assumed.  If such an object is to appear in a common or
 equivalence context the type must have the sequence property
 and the actual type parameter values must be constant.
 
 2.3 The form of the Constructor
 The approach recommended by the subgroup is to follow the
 style set for the intrinsic functions where the type
 parameters of the result need to be set.  The model of the
 REAL type conversion function is proposed. In this case the
 extended form of the constructor reference would be to
 include the parameters as an extra set of arguments following
 the list of component expressions.  The analogy with
 
 REAL(A,KIND)
 
 for  the matrix type would be
 
 MATRIX(element,wkp,dim)
 
 where the expression associated with the element component
 would need to be assignment conformant with a rank 2 array of
 shape (/dim,dim/) and type real of KIND=wkp. 
     The general form is therefore,
 
 type-name(component-expr-list,type-param-expr-list)
 
 {   OOF subgroup has additional proposals to greatly improve the friendliness of the
      value constructor which will make this form more usable. The simpler of the two
      improvements is to allow keywords to be used to indicate the association between
      expression and component, and between parameter and value. This would allow the
      matrix constructor to be referenced in the following form
 
     MATRIX(element=0.0, wkp=4, dim=12)                                 }
 
 2.4 Type parameter value inquiry  
 Because of the objections to allowing the parameter names to
 enter the programs class 1 names space inherent in
 generalising the intrinsic inquiry function approach, the
 subgroup is recommending that for any object of a
 parameterised type, the value of a parameter can be obtained
 by a "type parameter value selector", for example,
 
 rotate%%wkp = 4
 rotate%%dim = 3
 hessian%%dim = the value for the assumed dim parameter
 
 It is also proposed that to ensure regularity between the
 intrinsic and derived type facilities that this form of
 inquiry also be permitted for the intrinsic types. It should
 be possible to write for a variable of a type CHARACTER, say,
 char
 
 char%%LEN
 
 and have this deliver the same value as
 
 LEN(char)
 
 and similarly for the type parameter kind and any of the 
 intrinsic types.
     Note, the form of this inquiry should be
 
 parameterised-type-object%%type-parameter-name
 
 Where the %% selector selects the value for the named type
 parameter for the named object.. Note, the rank of the object
 is not relevant only the type.
     Where these inquiries relate to kind parameters they
 would need to be allowed in initialisation expressions. Where
 they applied to nonkind parameters they would need to be
 allowed in specification expressions. Their primary use, as
 with KIND() and LEN(), will be for the declaration of local
 objects which have the same type and type parameters as for
 other objects; frequently these other objects will be dummy
 arguments with, for nonkind parameters, assumed values for
 their type parameters. 
 
 2.5 Intrinsic assignment     
 Intrinsic assignment is to be defined only when the variable
 and expression have the same type, type parameter values.
 There is no attempt to define default coercions between
 differing type parameter values. If the user requires such
 assignments they must provide an assignment procedure to
 extend and override this default.
 
 2.6 Argument association and overload rules
 The rules for argument association should be that dummy
 argument and actual argument must match in type and type-
 parameters as for objects of intrinsic types. This matching
 of parameters may be achieved for nonkind parameters by the
 dummy argument assuming its type-parameter values from the
 associated actual argument. The kind type parameters cannot
 be assumed they must always be explicitly and statically
 specified, but as with intrinsic kind parameters these may be
 used to disambiguate generic overloads.
 
 
 3 Edits to IS 1539 : 1991    
 The following are an attempt at providing edits to the
 current document to implement the above functionality. They
 are proposed as an aid to the editorial committee in
 incorporating these technical proposals into the document. 
     Note, where new syntax rules are inserted they are
 numbered with a decimal addition to the rule number that
 precedes them. In the actual document these will have to be
 properly numbered in the revised sequence.
 
 Rationale
 Parameterised derived types are required for two main
 reasons. Firstly, there are many circumstances where a
 derived type is required to work together with intrinsic
 types where the ability to parameterise the kind of the
 latter and not the former causes very considerable problems.
 In one case different versions of the program can be selected
 by the use of the parameter but to enable the derived type to
 properly interwork a different type with a different name
 must be used. This results in very clumsy and inflexible
 programs and a significant program maintenance overhead,
 significantly defeating the object of the kind
 parameterisation.  Secondly, there are a large number of
 types where there is a need to manipulate objects where the
 only difference between various entities is in the size of
 some internal component. For example, there are entities like
 vectors that may differ in the dimensionality of the space
 they span and therefore in the number of reals that are
 involved in their representation, or in matrices that differ
 in their order. These are very like the intrinsic character
 data type where data objects may differ in the number of
 characters in the string and where this is specified by a
 length parameter on the type. This is clearly preferrable to
 having multiple separate types which differ only in such a
 size determining property.  
     Both these requirements are met by the addition of
 parameterised derived types to the language.
 end of rationale
 
 3.1 2.4.1.2   [13/22]
     before "agreement" add "and type parameter"
 
 3.2 4    [25/14]
     replace "Intrinsic data-types are" by "Data types may
 be"
 
 3.3 4.3.1.1   [27/8],
     4.3.1.2   [28/25], 
     4.3.2.1   [30/21], 
     4.3.2.2   [32/11]   
     After  "(13.13.51)" add "or by a type parameter value
 selector (4.4.1)"
 
 3.4 4.3.1.3   [29/30]
     Add sentance "The kind type parameter of an
 approximation method used for the parts of a complex value
 are returned by the intrinsic inquiry function KIND
 (13.13.51) or by a type parameter value selector (4.4.1)."
 
 3.5 4.4.1     [32/41]
     Add line following 
                         [param-spec-stmt]...
 
 3.6 4.4.1     [33/3]
     Add to end of R424 "[(dummy-type-param-list)]"
 
     Add new rule
 R424.1  dummy-type-param      is       type-param-name
 
 3.7 4.4.1     [33/16]
     Add following
 R425.1   param-spec-stmt     is   KIND [::] dummy-type-
 param-list
 
 A dummy type parameter that is specified in a param-spec-stmt
 with a KIND attribute is a kind type parameter. Any other
 dummy type parameter is a nonkind type parameter, and must
 not be used to determine the  values of actual kind type
 parameters of components.
 
 3.8 4.4.1     [33/26]
     Add constraints
 Constraint:   If the type-spec specifies a value for a kind
                type parameter, this must be a scalar integer
                initialisation expression, possibly involving
                as primaries the names of one or more dummy
                kind type parameters specified on the
                derived-type-stmt.
 Constraint:   If the type-spec specifies a value for a
                nonkind type parameter, this must be a scalar
                integer constant expression, possibly
                involving as primaries dummy type parameter
                names specified on the derived-type-stmt.
 
 3.9 4.4.1     [33/36 & 38]
     After ")" add ", possibly involving as primaries dummy
 type parameter names specified on the derived-type-stmt."
 
 3.10 4.4.1    [33/38+]
     Add following paragraph
 If the type has type parameters, actual values for these must
 be specified when an entity of this type is declared or
 constructed. These values may be used via the associated
 dummy type parameter names to specify array bounds and type
 parameter values for components of the type.
 
 3.11 4.4.1    [34/34]
     Add following paragraph
 Examples of type definitions with type parameters are:
 
 TYPE VECTOR(WP, ORDER)
 
   KIND :: WP
   REAL(KIND=WP) :: comp(1:ORDER)
 ENDTYPE VECTOR
 
 Objects of type VECTOR could be declared:
 
 TYPE(VECTOR(WP=KIND(0.0),ORDER=3)) :: rotation
 TYPE(VECTOR(WP=KIND(0.0D0),ORDER=100)) :: steepest
 
 The scalar variable rotation is a three-vector with each
 component represented by a default real. The scalar vector
 steepest is vector in a 100 dimension space and each
 component is represented by a double precision  real.
 
 For each type parameter specified there is a type parameter
 value selector of the form,
 
 R429.1   type-param-value-selector     is   object-name %%
 type-param-name 
 
 Constraint:   The sobject-name must be of a type that has
                type-param-name as a type parameter.
 
 The type parameter selector delivers the value of the named
 type parameter for the named object. For example,
 rotation%%WP would evaluate to 4 on a system where 4 was the
 default real kind and steepest%%ORDER would evaluate to 100.
 The  object may be of any rank.  
 
 3.12 4.4.4    [37/3]
     Replace "value of" by "value of the"
 
 3.13 4.4.4    [37/5]
     Replace "expr-list" by "expr-list[,type-param-expr-
 list]"
     Add constraint
 Constraint:   If the derived type has one or more type
                parameters, the type-param-expr-list must be
                present with the same number of expressions.
                If the derived type has no parameters, the
                type-param-expr-list must not be present.
 Constraint:   If the derived type has one or more kind type
                parameters, each corresponding
                type-param-expr must be an initialisation expression.
 
 3.14 4.4.4    [37/10]
     Before "A structure" add
 The type parameter expressions, if present, provide values
 for the type parameters of the type and hence control the
 shapes and type parameters of the components.
 
 3.15 4.4.4    [37/16]
     Add the following paragraph
 An example of a constructor for a parameterised type is:
 
 VECTOR(0.0,KIND(0.0D0),3)
 
 This would construct a three-vector whose components were all
 zero and of double precision.
 
 3.16 5.1 [39/24]
     Replace "type-name" by "type-name[type-selector]"
 
 3.17 5.1 [39/39]
     Add constraint
 Constraint:   The type-selector must appear if the type is
                parameterised and must not appear otherwise.
 
 3.18 5.1.1.7  [43/23]
     Add rules and constraints
 R509.1   type-selector  is   (type-param-selector-list)
 
 R509.2   type-param-selector      is   [type-param-
 name=]type-param-expr
 
 R509.3   type-param-expr      is  scalar-int-initialisation-
 expr
                          or  type-param-value
 
 Constraint:   There must be one and only one type-param-
                selector corresponding to each type parameter
                of the type.
 
 Constraint:   The type-param-expr must be a scalar-int-
                initialisation-expr if the corresponding type
                parameter is a kind type parameter.
 
 Constraint:   The type-param-name= may be omitted if it was
                omitted from all previous type-param-selector
                in the list.
 
 The type selector, if present, specifies values for the type
 parameters of the type and hence the type parameters and
 shapes of the components of the type.
 
 {{{{Note for the editor: The rules associated with type-
 param-values, in particular automatic and assumed type
 parameters, appear to be covered in the description for
 character length. A reordering of this material might read
 better but I think the current text is actually correct even
 though it now has extended effect. It is probably now in the
 wrong place in the chapter.}}}}
 
 3.19 5.5.2.3  [59/37]
     After "type" add "and type parameters"
 
 3.20 7.1.1.1  [70/40]
     Add line
               or   type-param-value-selector
 
 3.21 7.1.4.2  [76/24]
     After the second "The type" add "and type parameters."
 
 3.22 7.1.6.1  [77/25 & 78/7 ]
     After "KIND" add
     ", a type parameter value selector"
 
 3.23 7.1.6.2  [79/12]   
     After "KIND" add
     ", a type parameter value selector"
 
 {{{{Note for the editor: Given the difficulty with this text
 and the fact that it is the process of being totally
 rewritten these above edits may well not be appropriate or
 correct. The intent is to allow type parameter value
 selectors in initialisation and specification expressions in
 the same way as for KIND() and LEN(), in particular it should
 be possible to write
 FUNCTION F(v)
 TYPE(VECTOR(WP=4,ORD=*)):: v
 TYPE(VECTOR(WP=v%%WP,ORD=v%%ORD))::F
 where this has the obvious meaning.}}}}  
 
 3.24 7.1.7         [80/29]
     Add paragraph
 The appearance of a structure constructor requires the
 evaluation of the component expressions and may require the
 evaluation of type parameter expressions. The type of an
 expression in which a structure constructor appears does not
 affect, and is not effected by, the evaluation of such
 expressions, except that evaluation of the kind type
 parameters may affect the resolution of a generic reference
 to a defined operation or function and hence may affect the
 expression type.
 
 3.25 7.5.1.2  [89/28]
     Replace "type," by "type and the same type parameter
 values,"
 
 3.26 7.5.1.2  [89/41]
     Replace "type as" by "type and the same type parameter
 values as"
 
 3.27 12.2.1.1 [166/6]
     Replace "or character length" by " character length, or
 nonkind type parameter"
 
 3.28 12.3.1.1 [167/2]
     Replace "that" by "that assumes the value for a nonkind
 derived type parameter or that"
  
 3.29 12.3.1.1 [167/4]
     Add additional item to list and renumber list
     (e)  A result with a nonconstant type parameter value
           (derived type functions only)
 
 3.30 12.4.1.1 [172/41]
     Add sentence
 The value of a type parameter of an actual argument of a
 derived type must agree with the corresponding value for the
 dummy argument.
 
 3.31 14.1.2   [241/26]
     Replace ", in" by " and type parameters, in"
 
 
 4 Proposal    
 That facilities for parameterising derived types as set out
 above be added to Fortran at the 1995 revision.
  

-----------------------------------------------------------------
-- 
Dr.J.L.Schonfelder
Director, Computing Services Dept.
University of Liverpool, UK
Phone: +44(51)794 3716
FAX  : +44(51)794 3759
email: jls@liv.ac.uk   

