To compile it out you'd need the compiler to generate an object file (or .c/.o file) for every possible value of i. So module B.scm would generate B0.o1, B1.o1, B2.o1, etc (obviously in a lazy way for above a certain level) and the system would load the one appropriate for a particular level. However this would be very wasteful since the code would be duplicated.
Lately I have been working on some tools in black hole for batch compilation, that is, compiling several modules into one shared library file. For that I use the ##load-object-file procedure you sent a mail to this list about earlier. Now my French isn't the very best, but as far as I understand it from your description, this function allows the user to choose when to initialize the module by providing a function to call that initializes the module.
Also, it provides some facilities to see the globals that are not bound. Is it possible to hack something here? I'm thinking adding some options to how those unbound globals are resolved.
And another thing: It should be very doable to reduce this problem to two levels: Run-time and compilation.
When compiling, it seems safest to have a fresh initialization of every used module, and to do this once for each compiled file. And, when compiling, the "higher" levels (the ones with high numbers) are always processed strictly before the levels below. This means that for compilation, only one set of globals is needed at any time, because all modules can just be re-initialized and overwrite the levels above. Is this correct? (This solution obviously kills thread safety, but is that really a problem?)
This leads me to think that this isn't such a great problem after all, because when the problem is reduced to this point, one "solution" could simply be to say that compile-time code is always interpreted. With that limitation, it's easy to give all compile-time instances of modules a separate namespace from the run-time instances, because the code is re-loaded and hygienified (which is where namespaces are chosen) every time anyways.
Loading interpreted code is significantly slower than loading compiled code, but in practise I find that macros rarely use very many libraries. Obviously it would be even cooler to have real compiled macros, but I think it's not as important as having a correct and working solution.
This interpreted "solution" probably doesn't extend to the Gambit base libraries though. But is it really needed to have multiple instances of them? They don't have much global state do they?
/Per