module A uses module B because it calls a routine in module B
module B uses module A because it calls a routine in module A
neither compiles because each needs the other mod file.
So in A I comment out the use of B and the calls to B. I compile A. Then I compile B. Then I uncomment the use of B and the calls to B in A. Then I compile A. From then on I can compile each as long as I dont change the calling sequences and I dont make clean.
Gene Wagenbreth <genewxxx@isi-OS4> wrote: > module A uses module B because it calls a routine in module B
> module B uses module A because it calls a routine in module A
> neither compiles because each needs the other mod file.
> So in A I comment out the use of B and the calls to B. I compile > A. Then I compile B. Then I uncomment the use of B and the calls to > B in A. Then I compile A. From then on I can compile each as long > as I dont change the calling sequences and I dont make clean.
> This is silly, ugly, etc, but it works.
> What am I missing ?
Only the fact that the code is nonstandard and that such hacks are highly compiler dependent. The "it works" is a bit of an overstatement, which needs to be qualified with particular compiler details, possibly including the version number. Which is to say that this is asking for future trouble.
I'm trying to recall the ways for working around this problem. Of course, one "obvious" way is to reorganize things so that it doesn't come up, but I understand that isn't always practical.
Another way is to throw an external procedure into the mix. That's a bit of a hack, but at least it can be standard conforming. There isn't a limitation on invoking module procedures circularly like that - just on having circularity in the USE statements. So having an external procedure breaks the USE circularity.
-- Richard Maine | Good judgement comes from experience; email: last name at domain . net | experience comes from bad judgement. domain: summertriangle | -- Mark Twain
> module A uses module B because it calls a routine in module B
> module B uses module A because it calls a routine in module A
> neither compiles because each needs the other mod file.
> So in A I comment out the use of B and the calls to B. I compile > A. Then I compile B. Then I uncomment the use of B and the calls to > B in A. Then I compile A. From then on I can compile each as long > as I dont change the calling sequences and I dont make clean.
> This is silly, ugly, etc, but it works.
> What am I missing ?
You appear to by missing a clean seperation on the purpose of each module. There are a few possible solutions:
1) Move the routines in module A required by module B into B. Move the routines in module B required by module A into A.
2) If 1) does not work, then combine A and B into one module.
3) If 1) and 2) don't work, then move the routines in A that are required by B into a module C and move the routines in B required by A into a module D. Use C and D where needed in A and B.
On May 8, 12:02 pm, Gene Wagenbreth <genewxxx@isi-OS4> wrote:
> module A uses module B because it calls a routine in module B
> module B uses module A because it calls a routine in module A
If the procedures are actually mutually recursive, they should be in the same module. That is, if procedure pA1 (in module A) calls procedure pB1 (in B) and pB1 also calls pA1, they really should be in the same module anyway.
Otherwise, splitting one or other module should suffice. Say you decide to split B. Put all the stuff that A uses into MB1 and all the rest into MB2. Now, given the assumption that no routines are mutually recursive, A can USE MB1. Then MB2 can USE both A and MB1. The only hitch is that there may be things that routines on MB1 reference that you wanted to be PRIVATE in B, yet they now have to be public so that MB2 can see them. You can't have everything.
Note that only other kinds of mutual dependency that make any sense at all would be data types that, through pointers, have components of other data types, etc. But those kinds of things also belong in the same module together.
-- J. Giles
"I conclude that there are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiencies." -- C. A. R. Hoare
> which is a chapter of his Agile Software Development, Principles, Patterns, > and Practices book.
Ah. And I recognize Fortran submodules (F2003 submodules TR) in one of the suggested ways to break such loops. It doesn't use that term, but I recognize the concept. I should have thought of that one.
-- Richard Maine | Good judgement comes from experience; email: last name at domain . net | experience comes from bad judgement. domain: summertriangle | -- Mark Twain
> module A uses module B because it calls a routine in module B
> module B uses module A because it calls a routine in module A
> neither compiles because each needs the other mod file.
> So in A I comment out the use of B and the calls to B. I compile > A. Then I compile B. Then I uncomment the use of B and the calls to > B in A. Then I compile A. From then on I can compile each as long > as I dont change the calling sequences and I dont make clean.
> This is silly, ugly, etc, but it works.
> What am I missing ?
> G
Fortran 2003 provides an alternative devised by my collaborator Jim Xia: if the desired routines are type-bound procedures, circular references can be accomplished by introducing a third module, say C. Module A uses module C and the type defined in A extends the type defined in C. The type defined in C can later serve as a substitute for the type defined in A.
The following describes a specific case in which we were able to get this to work with the IBM XL Fortran 11.1 compiler. Possibly there are simpler examples where the inheritance hierarchies are not so deep:
In our example, the types in modules A, B, and C are all abstract types in an inheritance hierarchy that involves additional modules D and E containing "concrete" types to use C++ terminology (is the proper Fortran term "ultimate" types?). The hierarchy can be described by
D -> A -> C E -> B
where "->" reads as "extends". The use relationships are
A uses B,C B uses C E uses A,B D uses A,B
Inside module A, references to entities defined in B are direct references. Inside module B, any desired references to the type defined in A are replaced with the parent type defined in C. Inside E, extensions of the type defined in B get access to the entities in both A and B without circular references. Similarly, inside D, extensions of the type defined in A get access to entities defined in both A and B without circular references.