This is akin to implementing closures like this:
;;; source code (define (f x) (lambda (y) (+ y (* x y)))) (define a (f 11)) (define b (f 22)) (define c (f 33))
;;; generated code (define (f x) (lambda (y) (+ y (* x y)))) (define a (lambda (y) (+ y (* 11 y)))) (define b (lambda (y) (+ y (* 22 y)))) (define c (lambda (y) (+ y (* 33 y))))
Of course in the case of modules the "code" part of the "closure" is much larger than in the above example.
So a more space efficient approach is to add to each functional object (closure, primitive or return address) a pointer to the "global environment" of that module. When a module is "loaded" (in other words instantiated) a new global environment would be allocated, and all of its functional objects would be created and setup with a pointer to that instance's global environment. At run time an additional indirection would be required to get to the content of a module's global variables. Moreover, there is an overhead when calling functions because the "module environment" of the target function has to be read.
I see what you mean, but I was hoping that after all of the macro expansion is finished, we could forego that step of indirection. I'll have to think more about this though, but I'm willing to sacrifice correctness for efficiency if that helps.