One day while I was wandering the aisles of my local grocery store, a woman beckoned me over to a table and asked if I would like to “try some imported chocolate?” Neatly arrayed on the table were packages of LindtToblerone, and… Ghiradelli? I asked the woman if California had seceded from the Union, as Ghiradelli, despite its Italian name, hails from San Francisco. I suppose that from the vantage point of New Hampshire, California might as well be another country, much as depicted in that famous Saul Steinberg 1976 cover for The New Yorker, “View of the World from 9th Avenue“.

(I’ve been warned that my blogs don’t have enough arbitrary links – this should hold ’em for a while.)

Similarly, in Fortran (I’ll bet you were wondering when I’d get to that), something can be so near yet seem so far away. A short time ago, I was writing a new module for Intel Visual Fortran to provide declarations for the Win32 Process Status API. This would contain declarations of types and constants as well as interface blocks for the API routines, some of which take arguments of the new type. The natural inclination is to write something like this:

MODULE psapi
TYPE sometype
some component
END TYPE sometype
INTERFACE
FUNCTION newroutine (arg)
INTEGER :: newroutine
TYPE (sometype) :: arg
END FUNCTION newroutine
END INTERFACE
END MODULE psapi

If you did and compiled it, you’d get an error that type sometype is undefined in the declaration of arg. “What? It’s not undeclared, I can see it right above in the same module!” Well, yes and no. Yes, it’s declared in the module and could be used anywhere in the module, except.. Except in interface blocks!

The problem is that interface blocks are a “window into the external routine” – they essentially duplicate the declarations you would see in the actual external routine, assuming that routine were written in Fortran. As such, they do not “host associate” any symbols from the enclosing scoping unit (the module in this case.)

In Fortran 90 and Fortran 95, the typical solution for this was to create a separate module, say, “psapi_types”, containing all of the types and constants to be used, You’d then add a USE statement inside each function, just as you would have to in the hypothetical external routine written in Fortran. (If it were written in Fortran, the Doctor would slap your wrist with a wet punchcard and tell you to make the routine a module procedure, and then you wouldn’t need to worry about this nonsense.) So you would end up with something like this:

MODULE psapi
USE psapi_types ! This is for the benefit of users of module psapi
INTERFACE
FUNCTION newroutine (arg)
USE psapi_types
INTEGER :: newroutine
TYPE (sometype) :: arg
...

Those of you who use Intel Visual Fortran know that in fact there’s a giant module IFWINTY for this purpose, containing all of the types and constants for the other Win32 APIs. It’s messy and inelegant, but that’s what you have to do. Until now…

Fortran 2003 attempts to restore some elegance to this sorry situation, but to preserve compatibility with older sources, it couldn’t just declare that interface blocks participate in host association. Instead, a new statement was created, IMPORT. IMPORT is allowed to appear in interface blocks only and it tells the compiler to import names visible in the host scope.

IMPORT is placed following any USE statements but before any IMPLICIT statements in an interface body (the FUNCTION or SUBROUTINE declaration). IMPORT can have an optional import-name-list, much like USE. Without one, all entities accessible in the host become visible inside the interface body. With a list, only the named entities are visible.

With IMPORT, my PSAPI module can look like the first example with the following change:

...
FUNCTION newroutine (arg)
IMPORT
INTEGER :: newroutine
TYPE(sometype) :: arg
...

I could, if I wanted to, use:

IMPORT :: sometype

to say that I wanted only that one name imported. Nice and neat and all in one module!

“But why are you telling me this?”, you might ask, “That’s a Fortran 2003 feature and Intel Fortran doesn’t yet do all of Fortran 2003.” True enough, but we keep adding more and more F2003 features to the compiler and IMPORT made it in back in August! So if you are keeping reasonbly current, you can now IMPORT to your heart’s content and do away with the mess of a separate module for your types and constants.

If you want to know what other F2003 goodies are available to you, just check the Release Notes for each update. A full list of supported F2003 features is in each issue. Collect ’em all!

(Originally posted at Intel Developer Zone, copied with permission)

Write Your Comments

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Subscribe to Doctor Fortran

Subscribe to Doctor Fortran

Loading