(j3.2006) (SC22WG5.3461) Paper on macro feature

Aleksandar Donev donev1
Tue Jul 17 13:22:22 EDT 2007


To: WG5
From: Aleksandar Donev
Date: 7/14/2007
Subject: Macros should be a TR to F2008

This paper expresses my personal view that the macro feature, as
it appears in the F2008 draft, is not sufficiently developed to be
included in the standard. I propose that they be made a TR to be
published shortly after the standard. This will allow for additional
development time, and since they are almost entirely disjoint from
the rest of the standard (and in fact macros can be implemented by
an external pre-processor) this removal is almost trivial.

I will give several reasons why the macro feature is inadequate as
it is, and explain each of them in turn:

1) Macro functions are lacking
2) The design was not subject to sufficient debate and input
3) The original goal of "generic programming" is not truly met

1. Macro functions are lacking
----------------

The current macro design only covers statement-level macros, that is,
macros that expand to a sequence of statements. In particular, there
are no macros that can expand to a token or a token sequence. This
design decision was made hastily and without much input from
users and the committee, partly because of the rush to finish a
preliminary design and partially because the claim was made that
to satisfy the "generic programming" requirement statement-level
macros were sufficient. The lack of time should not be a constraint
for us because this feature can neatly fit in a TR, giving time to
develop it further. And the so-called "generic programming" features
are severely lacking, and in fact, all we have is a Fortran-aware
macro feature. Macros can be used to support some forms of generic
programming (albeit not the best way to do so), but at the very least
we ought to design the feature so that it is at least as good as
something various external macro preprocessors provide.

The existing macros are what I would call macro subroutines. The
EXPAND statement is like a CALL statement. It is natural to also ask
for macro functions, that is, macros that simply expand to a token or
a sequence of tokens inside statements. I cannot think of any macro
preprocessor in use that does not support macro expansion inside
statements, for example, to expand

TypeSpec(kind), DIMENSION(10) :: x

into

INTEGER(KIND=kind), DIMENSION(10) :: x

or

TYPE(LongInteger(PRECISION=kind)), DIMENSION(10) :: x

depending on a macro function definition of TypeSpec. As another
example, constructing a constant of kind precision, where precision
is, for example, a macro DO variable, requires:

MACRO INTEGER :: prec=precision ! Force evaluation to an integer
constant
x=1.0_&&prec ! Concatenate

If we had macro functions, one can write (this is fake syntax of
course) this function once in a module:

MACRO FUNCTION Evaluate(integer) RESULT(constant)
   MACRO INTEGER :: constant
   constant=integer
END MACRO

and then write:

x=1.0_ && Evaluate(precision)

whenever forced evaluation is needed.

I consider the decision to only provide statement-level macros a
fundamental flaw that makes the macro feature soo incomplete that is
simply unusable. I would not stop using an external preprocessor to
switch to built-in macros, and I wouldn't expect anyone to. I am not
saying that there won't be some technical issues to be worked out in
order to support macro functions. But, we should not rush a useless
"feature" for lack of time.

2. The design was not subject to sufficient debate and input
----------------

There are many small or medium features missing from our macro
facility that users will expect. Examples include macro token quoting
mechanisms (suppression of macro evaluation), variable-argument macro
lists, commas and semicolons in macro actual arguments. Most of
these are missing because of lack of time to allow suggestions for
improvements from committee members and the community. Whenever I
proposed something, for example, mechanisms for allowing commas and
semicolons in actual arguments, the answer was that the feature was
useful but it is too late (i.e., it was "feature creep"). Considering
how late in the process even the basic design of macros was rolled out
before we closed gaps for "feature creep", it was simply impossible,
even for those that read the draft and cared to comment, to affect
the design in any meaningful way. This is not the way a committee
should work. The point is to work as a group and thus achieve a more
complete product than one person would design based on their own
(undoubtedly incomplete) experience.

I will note that in contrast, co-arrays were around for a long
long time, and they still changed in important ways based on
input from others. For example, memory consistency model, teams,
intrinsic coroutines, additional synchronization primitives, the
termination model, and many other important features changed or were
added. Similarly for BITS, although I was less involved in that so
I am not that familiar with the process.

3. The original goal of "generic programming" is not truly met
----------------

The original justification for adding macros to the language was
not to add macros but to support (some limited form of) generic
programming. I believe that this goal has barely been achieved. What
we have is a lexical token manipulation facility. The "intelligence"
of the macros goes only so much as to recognize Fortran syntax (lexical
tokens, continuation of lines, comments, etc.), and more importantly,
proper scoping. The latter is very important, but does not contribute
to generic programming per se.

We were still adding features only two J3 meetings ago to support
even the most basic generic programming example: Writing a routine
that operates on different precisions of reals or different integer
kinds. We provide an example for this in the draft, and looking at this
(and the other examples) reveals how ugly and cumbersome using macros
to do this is. Why can't macros know the set of intrinsic kinds of
integers or the supported set of REAL kinds? Can't we have features
that actually directly support generic programming instead of using
token manipulation to get there? It is one thing to foresake error
checking (this is the most difficult aspect of generic programming),
but to foresake ease of programming is not acceptable. We are left
with too little.



More information about the J3 mailing list