From maine@altair.dfrc.nasa.gov  Mon Jan 13 23:42:00 1997
Received: from altair.dfrc.nasa.gov ([130.134.34.72]) by dkuug.dk (8.6.12/8.6.12) with ESMTP id XAA11958 for <sc22wg5@dkuug.dk>; Mon, 13 Jan 1997 23:41:55 +0100
Received: by altair.dfrc.nasa.gov (SMI-8.6/SMI-SVR4)
	id OAA06195; Mon, 13 Jan 1997 14:41:31 -0800
Date: Mon, 13 Jan 1997 14:41:31 -0800
Message-Id: <199701132241.OAA06195@altair.dfrc.nasa.gov>
From: Richard Maine <maine@altair.dfrc.nasa.gov>
To: sc22wg5@dkuug.dk
Subject: Specs and syntax for R.5, PDTs (X3J3/97-104)
Mime-Version: 1.0 (generated by tm-edit 7.92)
Content-Type: text/plain; charset=US-ASCII

Mallory,

Please add this to the mtg140 premeeting as paper X3J3/97-104.

--
Richard Maine
maine@altair.dfrc.nasa.gov

-------------------------------------------------------------------
                                                      X3J3 / 97-104

Date:        Jan 13, 1997
To:          X3J3
From:        R. Maine
Subject:     Specs and syntax for R.5, PDTs

This paper summarizes the specifications and syntax for parameterized
derived types, item R.5 on the F2k requirements list of X3J3/97-010.

Paper X3J3/96-141R1 was passed by X3J3 as the specifications for
this requirement.  That paper also had some illustrative syntax,
which was not adopted at that time.  Paper X3J3/96-176 was passed
by X3J3 as the syntax for this requirement; it mostly just cited
the illustrative syntax of the previous paper and made a few
modifications.

The current paper collects the previously passed specifications and
syntax into a single document.  There is almost new material of
substance (the one exception is explicitly noted below).  It mostly
consists of paper X3J3/96-141R1, modified in accordance with
X3J3/96-176, and with some of the discussion of previous papers
(notably WG5 D28 and X3J3/96-125) shortened or omitted.


1. Type-definition statement

  An optional list of type parameter names may be added in parens
  following the type-name in a type-definition statement.

  Example:
    type matrix(kind, dim)

2. Type parameter typing

  All type parameters are of type integer.  This may be confirmed
  by an explicit INTEGER declaration in the derived type
  definition.  An explicit declaration can also be used to
  declare a type parameter to be of an integer kind other than
  default integer.

  Any explicit declarations of type parameters shall precede any
  component declarations for the derived type.

  Paper X3J3/96-176 also specified that any explicit type parameter
  declarations shall appear in the same order as the parameters listed
  on the TYPE statement.  A straw vote on whether to retain that
  restriction was very indecisive (5 yes, 5 no, 7 undecided).  In
  subsequent discussions, it was pointed out that this needlessly
  disallows some reasonable styles (such as declaring all of the kind
  parameters in one statement and all of the non-kind ones in
  another).  I would now propose to drop that restriction; its purpose
  was only to avoid potential user confusion about the correct order
  for writing the parameters in a constructor, but the current
  proposal for constructor syntax lessens the potential for confusion
  by separating the parameters from the components.

  Examples:

    type matrix(kind, dim)
      !-- kind and dim are implicitly default integer
      real(kind) :: element(dim, dim)
    end type

    type humogous_matrix(kind, dim)
      integer :: kind  !-- Confirms kind as default integer
      integer(selected_int_kind(12)) :: dim
           !--  Specify a non-default kind for dim
      real(kind) :: element(dim, dim)
    end type

3. Kind vs non-kind parameters

  Type parameters are either kind type parameters on non-kind
  type parameters.  Kind type parameters participate in overload
  resolution and may appear in initialization expressions
  (particularly, in kind expressions for components) and in
  specification expressions.  Non-kind type parameters do not
  participate in overload resolution and may not appear in
  initialization expressions; they may appear in specification
  expressions.  A kind type parameter is said to have the KIND
  attribute.

  A type parameter may be declared to have the KIND attribute by
  using a KIND attribute on the INTEGER declaration of the
  parameter.  It may also be declared to not have the KIND
  attribute by using a NO_KIND attribute.  If a type parameter
  does not explicitly or implicitly (see below) have the KIND
  attribute, then it has the NO_KIND attribute by default;
  it is never required to explicitly specify the NO_KIND
  attribute, but it is allowed as a confirmation.

  Example:

    type stuff(kind, dim)
      integer, kind :: kind
      integer, no_kind :: dim
      real(kind) :: element(dim, dim)
      real(kind+1) :: scratch(2*dim)
        !-- kind is used as a primary in initialization exprs.
        !-- dim is used as a primary in specification exprs.
    end type

4. Implicit kind declaration

  With the exception mentioned below, appearance of a type parameter
  in a context requiring an initialization expression implicitly
  declares it to have the kind attribute.  This implicit declaration
  may be confirmed by an explicit declaration.  If a type parameter
  was declared with the NO_KIND attribute, it is an error for it to
  appear in a context that requires an initialization expression.

  Example:

    type matrix(kind, dim)
      real(kind) :: element(dim, dim)
    end type
    !-- kind is implicitly a kind type parameter because
    !-- it appears in an initialization expr.
    !-- dim is implicitly no_kind.

  If a derived type MY_TYPE has a component COMP that is a
  pointer to a (possibly different) derived type, the appearance
  of a type parameter of MY_TYPE in the expressions for the kind
  type parameter values of COMP implicitly declares it to be a
  kind type parameter of MY_TYPE only if the type definition for
  COMP precedes that of MY_TYPE.  For example

      type type_1(a)
        integer, kind :: a  !-- required because we don't yet know
                            !-- whether type_2 has a kind type parameter.
        type(type_2(a)), pointer :: comp
      end type

      type type_2(b)
        !-- No explicit declaration of b needed here.
        type(type_1(b)), pointer :: comp
      end type

  Note that this is never at issue except with pointer components
  because a non-pointer component is never allowed to be of subsequently
  defined type.

5. Object declaration.

  The syntax for declaring an object of parameterized derived type
  closely follows that of intrinsic parameterized types.  The type
  parameter values are specified in parens after the type name, in
  either keyword or positional form.  For positional form, the order
  corresponds to the paramer list of the type definition statement.
  There are no optional type parameters for derived types, so there is
  no concept of a default type-parameter value.

  The expression for a kind type parameter shall be an integer
  initialization expression.  The expression for a non-kind type
  parameter may be either a specification expression or assumed.
  The expressions for type parameter values need not be of the
  same integer kind as the type parameter.

  Examples:
    type(matrix(4,1000)) :: a
    type(matrix(kind=4,dim=1000) :: b

    subroutine sub(c, d, n)
      integer :: n
      type(matrix(kind=8, dim=*)) :: c
      type(matrix(kind=8, dim=2*n)) :: d

6. Constructors

  A constructor for a parameterized derived type has the same
  form as the constructor for the existing derived types, with
  the addition of the type parameters at the end of the list.

  The form of all derived type constructors (parameterized or not) is
  enhanced to allow a keyword form syntactically identical to that of
  a function call.  However, we avoid for now the extra complications
  of actually defining these constructors to be functions.

  The constructor for a parameterized derived type has, in parens
  after the type name, specifications of the type parameter values, in
  either keyword or positional form.  The syntax for the type and
  type parameters is then the same in a constructor as in an
  object declaration.

  Examples:

    type stock_item  !-- Note this is *not* a pdt.
      integer :: id, holding, buy_level
      character(len=20) :: desc
      real :: buy_price, sell_price
    end type
    type(stock_item) :: &
         s = stock_item(12345,75,10,"pencils", 1.5, 2.4)
    ...
    s = stock_item(desc="pencils", id=12345, &
                   holding=75, sell_price=2.4, &
                   buy_level=10, buy_price=1.5)

    type node(key_len)  !-- This one is a pdt
      character(key_len) :: desc
      type(node(keylen)), pointer :: next
    end type
    type (node(16)) :: word
    ...
    word = node(16)("ralph", null())

7. Type parameter inquiry

  Component selection syntax is used to inquire about type
  parameter values.  An inquiry about a kind type parameter can
  appear as a primary in an initialization expression; an inquiry
  about a non-kind type parameter can appear as a primary in an
  initialization expression if the actual value inquired about
  was defined as a constant expression.  an inquiry about any
  type parameter can appear as a primary in a specification
  expression.

  This directly follows the existing rules for how the existing
  intrinsic inquiry functions can be used.

  Examples:
     word%key_len  !-- word declared as above.

  The component selection syntax is also extended to the
  intrinsic types.

  Examples:
    real(4) :: a
    character*20 :: c
    write (*,*) a%kind, c%len  !-- i.e. 4 and 20

8. Intrinsic assignment

  Intrinsic assigment for parameterized derived types is defined
  only when the variable and expression have the same type and type
  parameter values


9. Argument association and overload rules

  The argument association rules follow those for objects of
  intrinsic types.  The actual and dummy arguments must agree in
  type and type parameters.  For non-kind parameters, the dummy
  argument may assume the value from the actual argument.
  Kind-type parameters may not be assumed.  Kind type parameters
  may be used to resolve generic overloads.

  Examples:

      type(matrix(kind=4, dim=100)) :: a
      call sub(a)
      ...
    subroutine sub(b)
      type(matrix(kind=4, dim=*)) :: b  !-- dim is assumed.

    module matrix_manipulation

      type matrix(kind, dim)
        real(kind) :: element(dim, dim)
      end type

      interface invert_in_place
        module procedure invert_single, invert_double
      end interface

    contains

      subroutine invert_single(a)
        type(matrix(kind=4, dim=*)), intent(inout) :: a
        ...
      end subroutine invert_single

      subroutine invert_double(a)
        type(matrix(kind=8, dim=*)), intent(inout) :: a
        ...
      end subroutine invert_double

    end module matrix_manipulation

10. Visibility and scoping

  The type parameter names are useable as keywords in object
  declarations even when the derived type has private components.
  Likewise, the parameter values can be inquired about even when
  the components of the derived type are private.  Type parameter
  names are not subject to renaming; they never appear in
  contexts where their names might conflict or be ambiguous with
  other names except for component names of their corresponding
  derived type.  It is not allowed for a component name to be
  the same as a type parameter name for the same derived type.

  Thus the type parameter names have more visibility than the
  component names.  This is consistent with the usage with
  intrinsic types.

11. Sequence

  Parameterized derived types may have the SEQUENCE property.
  A parameterized derived type is never considered a numeric
  or character sequence type even if all of its ultimate
  components are numeric or character.

  Sequence parameterized derived types may appear in common
  and equivalence provided that all of the type parameter
  values are constants.  This follows the existing rules for
  character.
