fix variable-reference->namespace for phase > 0

Set up bindings and shift phases as needed to make
`variable-reference->namespace` work in a run-time position when the
enclosing module is instantiated at a phase other than 0.

Thanks to Rohin Shah for the bug report.
This commit is contained in:
Matthew Flatt 2017-01-16 08:17:52 -07:00
parent b138c340e1
commit 3f2de918d8
3 changed files with 75 additions and 2 deletions

View File

@ -1937,6 +1937,74 @@ case of module-leve bindings; it doesn't cover local bindings.
(provide x))
(require 'a-submod)))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Make sure that `variable-reference->namespace` works
;; with phase shifts
(module evaluate-using-module-namespace racket/base
(provide go)
(define x 'x)
(define (go)
(define ns (variable-reference->namespace (#%variable-reference)))
(list (namespace-base-phase ns)
(eval '(list x) ns))))
(test '(0 (x)) (dynamic-require ''evaluate-using-module-namespace 'go))
(module evaluate-using-module-namespace-at-phase-1 racket/base
(require (for-syntax 'evaluate-using-module-namespace
racket/base))
(provide went)
(define-syntax (m stx)
#`(quote #,(go)))
(define (went) (m)))
(test '(1 (x)) (dynamic-require ''evaluate-using-module-namespace-at-phase-1 'went))
(module evaluate-using-module-namespace/saved-context racket/base
(provide go)
(define x 'x/sc)
;; Macro-introduced definition triggers saving the module's bindings
(define-syntax-rule (force-save-context) (define x 1))
(force-save-context)
(define (go)
(define ns (variable-reference->namespace (#%variable-reference)))
(list (namespace-base-phase ns)
(eval '(list x) ns))))
(test '(0 (x/sc)) (dynamic-require ''evaluate-using-module-namespace/saved-context 'go))
(module evaluate-using-module-namespace-at-phase-1/saved-context racket/base
(require (for-syntax 'evaluate-using-module-namespace/saved-context
racket/base))
(provide went)
(define-syntax (m stx)
#`(quote #,(go)))
(define (went) (m)))
(test '(1 (x/sc)) (dynamic-require ''evaluate-using-module-namespace-at-phase-1/saved-context 'went))
(module defines-a-variable-x-in-its-body racket/base
(define x 'defined))
(module uses-defines-a-variable-x-in-its-body-at-phase-1 racket/base
(require (for-syntax racket/base))
(provide out)
(define-syntax (m stx)
(dynamic-require ''defines-a-variable-x-in-its-body #f)
#`(quote #,(eval 'x (module->namespace ''defines-a-variable-x-in-its-body))))
(define out (m)))
(test 'defined dynamic-require ''uses-defines-a-variable-x-in-its-body-at-phase-1 'out)
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(report-errs)

View File

@ -2121,7 +2121,7 @@ static Scheme_Object *do_variable_namespace(const char *who, int tl, int argc, S
return env->access_insp;
} else if (tl) {
/* return env directly; need to set up */
if (!env->phase && env->module)
if (!env->mod_phase && env->module)
scheme_prep_namespace_rename(env);
env->interactive_bindings = 1;
} else {

View File

@ -3237,6 +3237,7 @@ void scheme_prep_namespace_rename(Scheme_Env *menv)
}
rns = scheme_module_context_to_stx(rns, NULL);
m->rn_stx = rns;
} else if (SCHEME_PAIRP(m->rn_stx)) {
/* Delayed shift: */
@ -3257,7 +3258,11 @@ void scheme_prep_namespace_rename(Scheme_Env *menv)
m->rn_stx = rn_stx;
}
rns = scheme_stx_to_module_context(m->rn_stx);
rns = m->rn_stx;
if (menv->phase)
rns = scheme_stx_shift(rns, scheme_make_integer(menv->phase), NULL, NULL, NULL, NULL, NULL);
rns = scheme_stx_to_module_context(rns);
menv->stx_context = rns;
menv->rename_set_ready = 1;