From owner-sc22wg5@open-std.org  Tue Dec  9 23:31:34 2008
Return-Path: <owner-sc22wg5@open-std.org>
X-Original-To: sc22wg5-dom7
Delivered-To: sc22wg5-dom7@www2.open-std.org
Received: by www2.open-std.org (Postfix, from userid 521)
	id D80D5C178DA; Tue,  9 Dec 2008 23:31:34 +0100 (CET)
X-Original-To: sc22wg5@open-std.org
Delivered-To: sc22wg5@open-std.org
Received: from mailrelay2.lrz-muenchen.de (mailrelay2.lrz-muenchen.de [129.187.254.102])
	by www2.open-std.org (Postfix) with ESMTP id 161AEC178D6
	for <sc22wg5@open-std.org>; Tue,  9 Dec 2008 23:31:33 +0100 (CET)
Received: from [129.187.48.222] ([129.187.48.222] [129.187.48.222]) by mailout.lrz-muenchen.de with ESMTP for sc22wg5@open-std.org; Tue, 9 Dec 2008 23:31:18 +0100
Message-Id: <493EF1B6.5080201@lrz.de>
Date: Tue, 09 Dec 2008 23:31:18 +0100
From: Reinhold Bader <Reinhold.Bader@lrz.de>
User-Agent: Thunderbird 2.0.0.18 (Windows/20081105)
MIME-Version: 1.0
To: WG5 <sc22wg5@open-std.org>
Subject: Re: (j3.2006) (SC22WG5.3792)  Response on the TR29113 draft N1761
Content-Type: text/plain; charset=ISO-8859-15; format=flowed
Content-Transfer-Encoding: 7bit
Sender: owner-sc22wg5@open-std.org
Precedence: bulk

Aleksandar Donev schrieb:
 > Hi,
 >
 > Thanks to train travel downtime, I was able to go through Reinhold's
 > missive. Some comments below.
 >
 > Reinhold Bader wrote:
 >> Issue 5 - RANK intrinsic:
 >> ~~~~~~~~~~~~~~~~~~~~~~~~~~
 >> Is this really needed considering we already have SIZE(SHAPE(X))?
 > Is AINT really necessary since you can write it so easily? I see no
 > reason not to add RANK just because it can be awkwardly handled already.
 >
 >> Issue 6 - referencing or defining assumed rank entities:
 >> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 >> It might also be feasible to allow a pointer of rank 1
 >> to point at such an object:
 > No, this is not technically possible. Assumed-rank dummies can be
 > non-contiguous. So a rank-1 pointer cannot describe their memory layout.
 > For the same reason, we only allow rank remapping when the target is
 > contiguous.

Understood. I suspected that you'd need to require the user to
know the "holes" in such a pointer if it were allowed.
So either we totally forbid referencing/defining from Fortran or we need
SELECT RANK for the general case.

 >
 >> Issue 7 - non-interoperable types:
 >> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 >> So, if the type definition from example 1 above were replaced by
 >>
 >>   type :: foo
 >>     integer(c_int) :: i
 >>     real(c_float), allocatable :: r(:)
 >>     character(c_int) :: c
 >>   end type
 >>
 >> the unpacking process in C would need to use a type definition
 >>
 >> typedef struct {
 >>   int i;
 >>   void *fdesc;
 >>   char c;
 >> } Foo;
 > No! The component of the type is the descriptor itself, not a pointer to
 > the descriptor. And the programmer is not actually given a way to
 > declare and directly manipulate Fortran descriptors, by design.

Thanks for making this clear.

 > They
 > manipulate a C "descriptor of a descriptor" and the Fortran one is
 > hidden. For example, it can even be different for assumed-shape vs.
 > pointer vs. allocatable, it can even be different for different ranks
 > vs. assumed-rank vs. scalar, etc.

Does the Fortran descriptor have the same basic structure (and hence an
invariant size), with only internal data varying or are you talking about
definitively different types used for the various cases?

In any case the issue here is not so much that "we must have this" but
rather "let's design the stuff within the scope of the TR so that we can
easily extend it later should we have reason to do so". See also my earlier
mail wishing for interoperability as a characteristic for dummy arguments.

 >
 >> Issue 8 - C variable argument lists:
 >> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 >> with the changes introduced in 08-295 it should now also be possible
 >> to provide support for vararg interfaces by matching to specifics of
 >> a Fortran generic interface.
 > But this is not really vararg, i.e., the ability to pass an arbitrary
 > collection of arguments at runtime.

I agree that this could only be called "limited interoperability". The point
is that the absolute interdiction still in 08-007r2 wrt interoperating with
vararg calls could be dropped. Words are needed in the standard on how
to proceed in using this, of course.

 >
 >> Suggestion 1 (design change interface creation):
 >> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 >> the processor is in principle
 >> capable of disambiguating interfaces using these features from those
 >> previously available for C interoperation. Hence I do not consider it
 >> necessary to provide a separate attribute with the BIND statement.
 > What "separate attribute" are we talking about?

Nick Maclaren wanted the ability to bind by ADDRESS vs. DESCRIPTOR, and
on the level of the complete interface. If the
design is done right, the processor should be able to automatically decide
for each dummy what to use.
 
 >
 >> (A) C calling a Fortran implementation:
 >> It would be the responsibility of the processor to
 >> * automatically generate a wrapper which performs any updates covered by
 >>   CFI_update_fdesc in the present design, unwraps the entity CFI_desc_t
 >>   and hands on the Fortran descriptor field to the Fortran-local 
procedure
 >>   call.
 > Sounds nice (for the user). If you can convince the vendors it is a good
 > idea :-)

Some of the arguments I gave might even do the job (?)

 >
 >> A direct call from Fortran to the global C name is non-conforming
 >>   since no type matching CFI_desc_t is available within Fortran; the
 >> processor
 >>   should prevent an interface attempting this from being created.
 > I don't see how or why the processor should prevent this. It is already
 > illegal if the type of the descriptor argument does not match. If there
 > is indeed a Fortran equivalent of CFI_desc_t by whatever means, than
 > what's wrong with calling the wrapper instead of the direct procedure?

Without the interdiction it would be possible to define an interface 
which is
interoperable in the F2003 sense

(referring to example 1 again)

  subroutine construct_foo_c(cdesc_this, n, i, r, c) bind(c, 
name='construct_foo')
    type(c_ptr), value :: cdesc_this
    integer(c_int), intent(in) :: n, i(n)
    real(c_float), intent(in) :: r(3, n)
    character(c_char), intent(in) :: c(n)
  end subroutine

which is much less safe to use, and is not at all needed from a practical
point of view. Calls from Fortran always use the local Fortran name.
Fortran implementations are written in Fortran without using any
descriptor shenanigans. You only need to add BIND(C) to let the processor
generate the wrapper, which allows access from C.


 >
 >> It is further suggested to provide a constructor (and associated
 >> destructor)
 >> function for the descriptor itself which has as its arguments those
 >> entities
 >> the programmer is responsible for.
 > Originally we did have that but we decided against it because the
 > argument lists were getting long and some of them had to be ignored (say
 > for allocatables the strides did not make sense), so it seemed nicer and
 > easier and more efficient to simply let the user directly set the fields
 > in the descriptor. Perhaps both methods can be provided for instead of
 > just one?

But note that the programmer needs to generate a Fortran descriptor
in some cases. So if we remove the update_?desc(), the constructor
must provide it in those cases where the processor does not do so
automatically. (Some additional thought on when exactly a fdesc
must be created for the various cases may be in order).

 >
 >> In contrast to statically determined Fortran code the constructor 
sets the
 >> attribute, type and rank of an object at run time.
 >> Do we oblige the processor to update this information if inconsistent
 >> with the defined Fortran interface?
 > It is illegal to pass a descriptor of the wrong type/rank. The processor
 > may insert some check (say in debug mode) and issue an informative
 > message, but it is certainly not obliged to "correct" (impossible!) the
 > wrong fields.

OK, from my point of view it mainly must become clearer than is now
*  who is (typically) responsible for the various items in the descriptor
*  what the usual usage pattern will be
If this can be described in terms of accessor functions, it provides a
convenience to the users. It is not a "must". Additional examples
will be helpful in better understanding this issue ...

 >
 >> (B) Fortran calling a C implementation:
 >> The wrapper generated from the interface
 > Where is this wrapper intended to be generated--in the scoping unit
 > where the BIND(C) interface appears? What if it is an interface for a
 > BIND(C) procedure that is actually written in Fortran.
 > With your design,
 > if I understand, Fortran calling that Fortran procedure would call one
 > wrapper to generate C descriptors, then the actual procedure will be
 > called, and then another wrapper will be called to convert back to
 > Fortran.

You are referring to the case I described above ('construct_foo_c'),
suppressing which seems to make excellent sense at this point.


 > Seems to me like a BIND(C,LANG="C") would be a good idea.
 >
 >> A C program calling the C interface (untypical) would need to perform
 >> the construction and allocation, deallocation and destruction of
 >> descriptors
 >> manually before and after the call, respectively.
 > How? I thought you wanted to remove those API calls?

only the CFI_update_?desc() which are not referred to here.

 >
 >> Note that this also illustrates that OPTIONAL arguments can also be
 >> handled by the wrapping process
 > What does the C function pass to the wrapper for arguments not present?

If the C function call passes NULL, the wrapper needs to translate this
to PRESENT(X) == .FALSE. - or am I misunderstanding your question?

 >
 >> Suggestion 2 (add assumed-rank-and-size):
 >> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 >> in analogy to assumed rank (DIMENSION(::)), which one might also call
 >> assumed-rank-and-shape, a dummy variable can be declared with
 >> type(foo), DIMENSION(**) :: dummy
 > I don't quite see the point in this. We already have DIMENSION(*).

True. But we'd then need to change the semantics of DIMENSION(*)
in *generic interfaces*, and I don't see how this can be done while
maintaining backward compatibility, *especially* if the scalar case
is included. Some existing code could become invalid.

 > If
 > the only thing we gain is the ability to pass a scalar actual, why can't
 > we focus on this instead of adding an exponential dimension statement?
 > Probably the reason that is not allowed with DIMENSION(*) is because in
 > the old days they would pass an array element as the actual to pass a
 > section. But I don't see an actual problem with passing a single scalar
 > or even an array element by itself. Perhaps some of the old timers can
 > explain?
 >
 > Best,
 > Aleks


Best Regards
Reinhold

