- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I get a syntax error when a use-association rename targets a specific member of a derived type variable, as opposed to the entire derived type variable.
For example, this works:
use legacy_interface, x => global_data
But this gives a syntax error:
use legacy_interface, x => global_data%x
The error is:
error #5802: Syntax error: found '%' when expecting one of: , <END-OF-STATEMENT> ;
This seems to indicate renaming specific members of a derived type is not allowed. Is that true?
Are there good workarounds?
I'm using Intel Fortran 19.0.5.281 for Linux.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Correct - you can rename only module-level entities, not subcomponents.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
bring in the whole derived type and then have an associate construct to make a local name for the sub-element
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm trying to reuse legacy code that relied on common blocks to share data. I was hoping to remove all the common blocks, then populate data from a C struct into a Fortran derived type in a module, then rename each member of the derived type variable to the original variable name from the common block. That way I would not have to change code in the executable lines of the legacy code, but only at the top.
I think to use an associate construct to do this, the entire legacy subroutine would need to be enclosed within the associate construct, is that right?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
wrote:
I'm trying to reuse legacy code that relied on common blocks to share data. I was hoping to remove all the common blocks, then populate data from a C struct into a Fortran derived type in a module, then rename each member of the derived type variable to the original variable name from the common block. That way I would not have to change code in the executable lines of the legacy code, but only at the top.
I think to use an associate construct to do this, the entire legacy subroutine would need to be enclosed within the associate construct, is that right?
Yes, you would need to enclose the code within the construct.
You may really want to think through this and decide what how you want to proceed with your legacy code: "let sleeping dogs lie" is always an option, or you can refactor your code in any number of ways to something modern.
There are several options (online search will help) including the dreaded one of resorting to POINTERs if the much safer alternative of ASSOCIATE with a similar concept is unworkable for you. Here's an example:
module m
type :: t
integer :: n = 0
real :: x = 0.0
end type
type(t), target, save :: foo = t() !<-- Derived type instance 'simulated' as save'd module variable
integer, pointer, save :: n => foo%n !<-- POINTER to one component
real, pointer, save :: x => foo%x !<-- POINTER to another component
contains
subroutine output()
print *, "In m::output:"
print *, "foo%n = ", foo%n
print *, "foo%x = ", foo%x
end subroutine
end module
module legacy_code_m
use m, only : n, x !<-- Note this USE statement
contains
subroutine legacy_sub()
n = 42
x = 99.0
end subroutine
end module
program p
use legacy_code_m, only : legacy_sub
use m, only : output
call legacy_sub()
call output()
end program
Read through the whole snippet if you're keen on using such an approach involving POINTER. Upon execution of this simple case, you should get:
In m::output:
foo%n = 42
foo%x = 99.0000000
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
well you could also just replace the common with a module with the same entities in it as the common. So long as your code does not do any of the old style "sharing" of the common space type hacks. That is a very minimal code change.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What you describe is exactly what we did with another code base a few years back -- a direct swap of commons for modules with all the same variable names. Worked beyond our wildest dreams.
However, in this case the motivation for using a derived type is to take advantage the C binding features to pass data to and from a C structure in the calling function. I suppose one approach is to create a setter routine that copies all the members into separate variables. I was just hoping to avoid that.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You have several ways available, I guess the detail of what you do depends on the amount of work needed and what you want to do in the future. For what it's worth the associate idea looks like:
subroutine example
use mymodule, only: myType
implicit none (external)
!real :: x,y,z
!common /mytype / x,y,z
associate ( x => mytype%x, &
y => mytype%y, &
z => mytype%z )
...
...
end associate
end subroutine example
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks @andrew_4619, that makes it very clear. Looks like applying associate constructs to avoid changing the operational code would be relatively light weight.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Correct - you can rename only module-level entities, not subcomponents.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you Doctor.
Is there an underlying technical reason this should not be possible as a future language feature?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You're really not asking for a rename, which would be something like renaming global_data%x to global_data%y. If you want x to stand in for global_data%x, then @andrew_4619 has exactly the right solution - use ASSOCIATE. That's what it's for and it's already in the language.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page