From maine@altair.dfrc.nasa.gov  Mon Jan 27 18:11:42 1997
Received: from altair.dfrc.nasa.gov ([130.134.34.72]) by dkuug.dk (8.6.12/8.6.12) with ESMTP id SAA21695 for <sc22wg5@dkuug.dk>; Mon, 27 Jan 1997 18:11:36 +0100
Received: by altair.dfrc.nasa.gov (SMI-8.6/SMI-SVR4)
	id JAA13215; Mon, 27 Jan 1997 09:11:17 -0800
Date: Mon, 27 Jan 1997 09:11:17 -0800
Message-Id: <199701271711.JAA13215@altair.dfrc.nasa.gov>
From: Richard Maine <maine@altair.dfrc.nasa.gov>
To: sc22wg5@dkuug.dk
Subject: X3J3/97-103
Mime-Version: 1.0 (generated by tm-edit 7.92)
Content-Type: text/plain; charset=US-ASCII

Mallory,

  Here is X3J3/97-103 (a bit later than I had hoped to get it done,
it is still Monday).  Please add it to the premeeting and put it
on the server.

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


-------------------------------------------------------------------
                                                      X3J3 / 97-103

Date:        Jan 24, 1997
To:          X3J3
From:        R. Maine
Subject:     Specs and preliminary syntax for R.3, procedure pointers

This paper summarizes the specifications and preliminary syntax
for procedure pointers, item R.3 on the F2k requirements list of
X3J3/97-010.

Papers X3J3/96-142 and X3J3/96-146 were passed by X3J3 as the
specifications for this requirement.  The actual specifications
are in paper X3J3/96-142.  Paper X3J3/96-146 supplements these
specifications with some illustrative example syntax, but the
syntax was not part of the motion that passed.

Paper X3J3/96-174 further developed the syntax, but was not yet a
complete syntax proposal.  No formal vote was taken on that
paper.  A straw vote on the concept of a named interface block
(though not necessarily the exact syntax) was unanimously in
favor.  The proposal in X3J3/96-174 allowed procedure pointers
with both explicit and implicit interfaces, but the subgroup was
also directed to "reconsider whether to add a requirement that
procedure pointers should require an explicit interface."  Note
that this direction did not say that such a requirement should be
added, but just that the subgroup should reconsider the question.

The current paper collects the material from papers X3J3/96-142,
X3J3/96-146, and X3J3/96-174 into a single document.  This
includes both specifications and preliminary parts of the syntax.
Most of the material about pointers with implicit interfaces has
been segregated to make it easy to identify which portions would
be affected by that issue.  The subgroup has not yet had time to
collectively consider its recommendation on this question;
presumably such reconsideration will be done at meeting 140.


1. SPECIFICATIONS

1.1 Procedure pointers vs. procedure variables

Proposals for procedure pointers and procedure variables offer
similar functionality.  After much discussion, /data is
recommending the procedure pointer formulation because it more
naturally offers the null pointer or null association concept.

1.2 Simillar existing features

Specifications for this facility are based on analogies with two
existing language features.
     
1.2.1 Dummy procedures.

If a set of declarations of a name in conjunction with that name
appearing in a dummy argument world make that name the name of a
dummy procedure, then that same set of declarations in
conjunction with that name being declared with the POINTER
attribute will make that name the name of a procedure pointer.
The class of procedures which can then be associated with that
procedure pointer is exactly the class of procedures which could
have been supplied as the corresponding actual argument in the
dummy procedure case.  Thus, procedure pointers cannot be
associated with internal procedures, statement functions, generic
procedures, most intrinsic procedures, etc.  If the interface of
the procedure pointer is explicit, the interface of the procedure
being associated must also be explicit (with matching
characteristics).

This analogy with dummy procedures is what drove the initial
proposal that procedure pointers with implicit interfaces be
allowed.  Disallowing implicit interface procedure pointers would
constitute an exception to this analogy.  It might be interpreted
as suggesting that implicit interface dummy procedures are a
deprecated concept.

1.2.2 Data-object pointers.

The mechanism for establishing an association is the pointer
assignment statement, a disassociated status can be created with
the NULLIFY statement or the NULL intrinsic function, the
one-argument form of the ASSOCIATED intrinsic function can be
used to test for a null association status, and the two-argument
form of the ASSOCIATED intrinsic function can be used to test for
a particular association.  However, we do not proposed to allow
one to ALLOCATE or DEALLOCATE a procedure pointer.
     
As with data object pointers, the default initial status for such
pointers is "undefined".  Just as a data-object pointer can
become undefined if it is associated with a module variable and
the module goes out of scope, a procedure pointer can become
undefined if it is associated with a module procedure and the
module goes out of scope.
     
Procedure-pointer dummy arguments, function results, and derived
type components would be allowed analogous with the data-object
pointers.
     
There are no arrays of procedure pointers, but the usual
workaround of having arrays of a derived type with pointer
components works as well for procedure pointers as for data-
object-pointers.


2. SYNTAX (EXPLICIT INTERFACE)

2.1 Existing declaration syntax

One syntax for declaring variables as pointers to explicit
interface procedures already exists if we just assign a meaning
to the previously meaningless combination of an interface body
and a POINTER statement for the same name.  An example is
    INTERFACE
      SUBROUTINE E(X,Y)
        REAL :: X,Y
      END SUBROUTINE
    END INTERFACE
    POINTER :: E
This declares E to be a pointer to an explicit interface
procedure.

2.2 Named explicit interfaces

It is less obvious how to declare some forms of procedure pointer
components.  This is because the existing syntax requires at
least 2 separate constructs (the interface block and the pointer
statement) to declare a procedure pointer with an explicit
interface.

All other derived type components are declared with a single
statement rather than with multiple attribute statements.  Even
if the interface body syntax is expanded to allow the pointer
specification, this approach would result in interface bodied
nested inside of derived type definitions, which is arguably
objectionable.

An additional problem with the existing syntax is that it does
not provide a reasonable way to declare multiple pointers with
the same interface.  For the non-pointer case, this was not too
much of an issue because there were not often large numbers of
essentially identical interface bodies in a single scope.  There
might be at most one for each procedure dummy argument and one
for each specific external procedure referenced; those for
external procedures could potentially be automaticaly generated.
In contrast, it is plausible for there could be an arbitrarily
large number of procedure pointers with the same interface in a
scoping unit and there is no obvious way to automatically
generate the interface bodies.

We propose a mechanism to assign a symbolic name to an interface
so that procedure pointers can be declared to have this interface
by name rather than requiring the matching interfaces to be
repeatedly declared in detail.  We will refer to this symbolic
name as a procedure interface name, at least for now.

Note that the procedure interface name is purely syntactic.
We specifically avoid attaching semantic significance to
the name.  In particular, it does not act like a type.
You can declare two different procedure pointers with
different procedure interface names and they are still
compatable as long as the charactersitics of the interfaces
are the same.  It would be difficult to disallow this without
changing the feature of f90/f95 that allows a procedure to
have different interface bodies in different scopes, as long
as their characteristics agree.  (In particular, the dummy
argument names need not agree).

Interface names can be imported by USE or host association.

2.2.1 Interface block syntax alternative 1

This alternative is as presented in paper X3J3/96-174.

To define a named procedure interface while introducing as little
new syntax as practical, we propose a third form of interface
block.  The existing interface blocks either have a generic-spec
in the interface statement or not.  The proposed third form of
interface block would have an interface statement with the syntax

     INTERFACE NAME(<interface-name>)

Such a interface block must contain exactly one interface body.
The syntax of the interface body is unchanged from the existing
interface body syntax, but there is one semantic difference.
This kind of interface body defines the characteristics of an
interface, but it does not in itself attach those characteristics
to any object.  The procedure name in such an interface body has
scope of only the procedure body; it is not the name of an
external or dummy procedure.  The procedure name is basically a
placeholder that has no significance outside of the interface
body.  The procedure name could possibly be omitted completely
(in which case, a result clause would be needed if it were a
function).  We don't currently propose allowing the procedure
name to be omitted because it seems simpler to leave the syntax
of interface bodies completely unchanged, but it would be a
concievable syntax variation.

An example of a named interface definition for a subroutine is

   INTERFACE NAME(sub)
     SUBROUTINE this_name_is_irrelevant(x,y)
       REAL :: x,y
     END SUBROUTINE
   END INTERFACE

and one for a function is

   INTERFACE NAME(fun)
     FUNCTION so_is_this(x) result(f)
       REAL :: x,f
     END FUNCTION
   END INTERFACE

2.2.2 Interface block syntax alternative 2

Although no vote was taken, several reservations were expressed
about the placeholder names in the above syntax.  It is also
anomalous that the above form of interface block syntax allows
1only one interface body in the block.  Therefore, the following
syntax is presented as an alternative possibility.

The interface statement remains as in the f90/f95 standard.

One addition is made to the interface body syntax.  We
define a new <prefix-spec> (R1219) tentatively called MODEL.
This prefix may appear only on a subroutine and function
statement in an interface body, never in the subroutine
or function statement of a subprogram.

I'm receptive to better terms than "model".  The notion is that
this defines an abstract interface template rather than the
interface of a specific procedure.  I've heard objection to
the term "template" as having too many other conotations.
Terms like "type", "class", and "kind" seem bad for
simillar reasons.  There is unlikely to be any confusion
between model numbers and procedure interface models.
I suppose "abstract" might work.

When this <prefix-spec> is present, the interface body defines a
named interface rather than the interface of a specific
procedure.  The interface name is the <function-name> or
<subroutine-name> in the interface body.

An example of an interface block using this syntax alternative is

   INTERFACE
     MODEL SUBROUTINE sub(x,y)
       REAL :: x,y
     END SUBROUTINE
     MODEL FUNCTION fun(x) result(f)
       REAL :: x,f
     END FUNCTION
   END INTERFACE

This example is equivalent to the examples shown for syntax
alternative 1.

2.3 Procedure declaration statement

A procedure declaration statement has a syntax modeled after a
type declaration statement for a derived type.  The keyword
PROCEDURE is used instead of TYPE and an interface name is used
instead of a derived type name.  For example, the statement

  PROCEDURE(fun), POINTER :: a => NULL(), b, c

declares three procedure pointers, all having the interface named
fun.  Possibly relevant attributes are POINTER, SAVE, OPTIONAL,
and INTENT.  Note that EXTERNAL is not allowed (because it would
be a form of redundancy that we already disallow elsewhere).

Although it was the requirements of procedure pointers that most
motivated the need for named interfaces and the corresponding
procedure declaration statements, there are some non-pointer
cases where a procedure declaration statement could naturally be
used.  We propose to allow these cases.  Specifically, a
procedure declaration statement without the pointer attribute can
be used to declare a dummy or external procedure.

2.4 Procedure pointer component definition

Component definition statements would be enhanced to add the form

   PROCEDURE(<interface-name>), POINTER :: <component-decl-list>

The POINTER attribute is required and no other attributes are
allowed.

Example:

  TYPE my_object_type
    TYPE(my_type) :: x
    PROCEDURE(my_interface) :: my_procedure
  END TYPE

2.5 NULLIFY and NULL()

Procedure pointers may appear in the NULLIFY statement.  The
NULL() intrinsic can return a null procedure pointer; the
optional argument of NULL() may be a procedure pointer.

2.6. ASSOCIATED()

The one-argument form of associated can be used with procedure
pointers.
     
The two-argument form of ASSOCIATED is also allowed, but note
that two pointers are nominally different if they are associated
with the same module procedure but from different instances of
the host module.  However, it appears that such queries must
always involve at least one pointer that is really undefined, so
implementations are not required to track this.

2.7 Pointer assignment

Pointer assignment for procedure pointers has the same syntax
as other pointer assignments.  Note that the target for
procedure pointer assignment may be a procedure (how else
are they going to get associated with anything non-null),
but that we do not propose to require that procedures be
explicitly declared to have the target attribute.

For example

  INTERFACE
    FUNCTION RFP(x), RESULT(y)
      REAL :: x,y
    END FUNCTION RFP
  END INTERFACE
  POINTER RFP
  INTRINSIC SIN
  RFP => SIN

associates RFP with the (specific) intrinsic function SIN.

2.8 Procedure pointer references

Just as with data pointers, procedure pointers are automatically
dereferenced when used in an appropriate context.  In particular,
if RFP is a pointer to a real function and SP is a pointer to
a subroutine, then the forms

  x = rfp(y)
  CALL sp(z)

invoke the function that is associated with rfp and the subroutine
that is associated with sp.  Execution of these statements is illegal
if rfp or sp is not associated.
     
We recommend that procedure reference syntax be extended to allow
the procedure to be specified as a structure component, e.g.
     CALL PARENT%PROC_POINTER(ARGS)
On the other hand, we do not recommend a similar extension for
functions that return procedure pointers.  E.g., we would require
     PP=>PPF(ARGS1)
     CALL PP(ARGS2)
rather than extending to allow
     CALL PPF(ARGS1)(ARGS2)
This is consistent with data-object pointers, which can be
subscripted, substringed, etc.  as components, but not as
function results.

3. SYNTAX (IMPLICIT INTERFACE)

3.1 Existing declaration syntax

A syntax for declaring variables as pointers to implicit
interface procedures already exists if we just drop the
prohibition against a name having both the POINTER and EXTERNAL
attribute.  Sample declarations are:

  REAL, EXTERNAL, POINTER :: FP => NULL()
  EXTERNAL :: SP
  POINTER :: SP

Implicit interface function pointers can be declared either with
a single statement, as illustrated above, or with separate
attribute statements.  For explicit interface subroutine
pointers, there is no way to specify both the external and
pointer attributes in one statement with the existing syntax.

As with the non-pointer case, the distinction between implicit interface
subroutines and functions can
type of an implicit interface
function pointer may be determined by implicit typing rules.

3.2 Implicit inference of attributes

As in the non-pointer case, the distinction between implicit
interface function and subroutine pointers can be inferred by the
use of the name in a call statement or function reference.  A
pointer to an implicit interface external function can be
implicitly typed following the same rules as the non-pointer
case.  For example, in the following, sp is a subroutine pointer
and fp is a real function pointer.

  external sp, fp
  pointer sp, fp
  ...
  call sp
  y = fp(x)


In the non-pointer case, the external attribute can also be
implicitly inferred by the use of the name in a subroutine call
or a function reference.  However, a procedure name passed as an
actual argument must be explicitly declared to have the external
attribute (even if it also appears in a context that implies the
external attribute - I didn't know that, but see 12.3.2.2).  For
procedure pointers, we certainly want the external attribute to
be at least as explicit as for the non-pointer case.  I would
propose that a procedure pointer used on either side of a
pointer assigment statement must also be explicitly given the
external attribute.  I don't think we want the compiler to have
to infer that B is a procedure pointer in cases like the
following
    POINTER :: A, B
    ...
    B => A
    ...
    A => S
    ...
    CALL S
Because a procedure pointer cannot be referenced unless it is
first associated, and since most ways of associating it would
require that the externalness be explicit, there aren't very
many cases left in which implicit externalness is useful.  Note
that this is very different from the non-pointer case, where the
large majority of the usage is in cases where the externalness
is implicitly obvious.  Therefore, we recommend that the
external attribute must be explicitly declared for procedure
pointers.

Of course, the pointer attribute must always be explicitly
declared.

3.3 Named implicit interfaces

The above sections define syntax adequate for declaring all
cases of procedure pointers except for one.  The missing case is
a derived type component that is a pointer to an implicit
interface subroutine.

For pointers to explicit interface procedures, we have syntax like
  PROCEDURE(sub), POINTER :: a
For pointers to implicit interface functions, we have syntax like
  REAL, EXTERNAL, POINTER :: a
These forms work for both structure component definitions and
for variable definitions.

But the only syntax we have for pointers to implicit interface
subroutines uses two separate attribute statements as in
  POINTER :: s
  EXTERNAL :: s
This doesn't "work" well for component definitions because it is
two separate statements.  We could possibly allow a syntax like
  EXTERNAL, POINTER :: s
but this would introduce several confusing inconsistencies.
(Would you also allow a POINTER specification in the EXTERNAL
attribute statement, or in other attribute statements?  Would
you allow a function component to be specified in a syntax
like "EXTERNAL, REAL, POINTER :: f"?)

The basic problem is that subroutines don't have a type, so they
can't be declared in a type declaration statement.  We propose
to address this problem by extending the syntax of named
interface definitions to include implicit interfaces as well as
explicit ones.  An interface block to define a name for an
implicit interface subroutine would look like

  INTERFACE NAME(sub), EXTERNAL
  END INTERFACE

Such an interface block can have no interface bodies, which
makes the END INTERFACE look a bit pointless, but it is probably
best to retain it for consistency.

For completeness, we might as well also provide for named
interface definitions for implicit interface functions.  A
sample syntax for such an interface block would be

  INTERFACE NAME(func), EXTERNAL, REAL
  END INTERFACE

These forms correspond to interface block syntax alternative 1.
If interface block syntax alternative 2 is selected, and named
implicit interfaces are also desired, corresponding syntaxes
would be needed, but are not yet proposed here.

None of the syntaxes for named implicit interfaces look
particularly "clean", although they are certainly workable.  If
implicit interface pointers are disallowed, the issue becomes
moot.  Even if we allow implicit interface pointers, it would be
concievable to do so without defining named implicit interfaces.
The only real substantial consequence of this would be that there
would be no syntax for declaring implicit interface pointer
subroutine components.
