private components in module files
Andrew Benson
abenson@carnegiescience.edu
Mon Oct 28 23:50:00 GMT 2019
On Thursday, October 24, 2019 11:26:27 AM PDT Janne Blomqvist wrote:
> On Wed, Oct 23, 2019 at 7:07 PM Andrew Benson
>
> <abenson@carnegiescience.edu> wrote:
> > Hi all,
> >
> > I've been slowly trying to educate myself about the structure of gfortran
> > module files, in the hope that I can eventually work on making some
> > improvements (I'm particularly interested in anything that would reduce
> > the
> > file size or speed up parsing).
>
> AFAICS the big improvements, thought absolutely not low-hanging fruit
> (which is why it hasn't been done), is
>
> 1) Not including transitive dependencies in .mod files. Implying that
> .mod files would need to have the equivalent of USE statements, so
> that the module parser knows it might need to parse other modules to
> resolve all symbols.
>
> 2) Caching parsed module files. This is likely necessary to get (1) to
> work decently.
>
> AFAIK the NAG Fortran compiler does something like this.
>
> See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=40958#c13
>
> Also see previous discussion in
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25708
I spent an hour or two today working to understand how caching of parsed
module files might be implemented. Following the ideas in:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25708#c5
I was able to implement a linked list of namespaces for modules, and then add
symbols to a symtree within that namespace as the module is parsed and, if the
same module is parsed again, return that cached symbol. (This is a very
crude implementation so far - I'm mostly just trying things to improve my
understanding - I expect I'll end up re-writing this multiple times as I learn
from my mistakes....)
This seems to work in some simple cases, but I have a few questions:
I'm considering a simple case such as this:
module a
type aa
integer :: ab
end type aa
end module a
module b
contains
subroutine b1()
use a
type(aa) :: ba
end subroutine b1
subroutine b2()
use a
type(aa) :: ba
end subroutine b2
end module b
program test
use b
call b1()
end program test
I had initially attempted to return a pointer to the symbol for type(aa) in
the module namespace on the second use of the module. If I do this though then
the second "type(aa) :: ba" triggers an error:
tmp.F90:20:12:
20 | type(aa) :: ba
| 1
Error: Cannot change attributes of USE-associated symbol aa at (1)
This occurs in gfc_match_decl_type_spec() in decl.c at the line:
if (dt_sym->attr.flavor != FL_DERIVED && dt_sym->attr.flavor != FL_STRUCT
&& !gfc_add_flavor (&dt_sym->attr, FL_DERIVED, sym->name, NULL))
return MATCH_ERROR;
Therefore I've instead opted to return a copy of the symbol for type(aa) from
the module namespace, which avoids this problem. It's not clear to me if this
is the best solution though, or if there is a way to return just a pointer to
the symbol and avoid this "change attributes" error?
A second question: To add each symbol to the module namespace I need to give
it a unique name. I've tried to construct such a name by concatenating the
"proc_name" of the symbol's namespace with the "true_name" associated with the
symbol. This works in most cases, but fails for symbols such as the "src" and
"dst" symbols that get created - there can be many of these and they all share
the same "proc_name" (the module itself). So, I'm not sure on how best to
generate a unique name. (Each of these "src" and "dst" symbols belong to a
unique namespace within the load_needed() function - I could similarly put
them in unique namespaces within the module namespace. But then I'd need some
way to assign a unique name to each of those namespaces, so this wouldn't
resolve the problem.)
I can post the patch for my modifications if it's useful (although I should
probably clean it up first to make it more comprehensible).
Thanks,
Andrew
--
* Andrew Benson: http://users.obs.carnegiescience.edu/abenson/contact.html
* Galacticus: https://github.com/galacticusorg/galacticus
More information about the Fortran
mailing list