fix expand of `#%variable-reference' on local variable

Closes PR 12231
This commit is contained in:
Matthew Flatt 2011-09-27 18:53:28 -06:00
parent ec49225112
commit 2ae6d0c55f
2 changed files with 38 additions and 8 deletions

View File

@ -547,6 +547,25 @@
(syntax-local-bind-syntaxes (list 'q) #'1 context))) (syntax-local-bind-syntaxes (list 'q) #'1 context)))
(test 'ok 'ok (foo))) (test 'ok 'ok (foo)))
;; ----------------------------------------
;; Check `#%variable-reference' expansion to make sure
;; a lexically bound identifier is made consistent with
;; its binding
(module m-check-varref-expand racket
(define-syntax (m stx)
(syntax-case stx ()
[(_ e)
;; use `local-expand' to trigger re-expansion:
(local-expand #'e 'expression null)]))
(m
(let ([x 10])
(define-syntax-rule (q) (#%variable-reference x))
;; `q' introduces a marked `x' under `#%variable-reference':
(q))))
(require 'm-check-varref-expand)
;; ---------------------------------------- ;; ----------------------------------------
(report-errs) (report-errs)

View File

@ -1326,7 +1326,7 @@ static Scheme_Object *
ref_syntax (Scheme_Object *form, Scheme_Comp_Env *env, Scheme_Compile_Info *rec, int drec) ref_syntax (Scheme_Object *form, Scheme_Comp_Env *env, Scheme_Compile_Info *rec, int drec)
{ {
Scheme_Env *menv = NULL; Scheme_Env *menv = NULL;
Scheme_Object *var, *name, *rest, *dummy; Scheme_Object *var, *name, *rest, *dummy, *lex_id = NULL;
int l, ok; int l, ok;
form = scheme_stx_taint_disarm(form, NULL); form = scheme_stx_taint_disarm(form, NULL);
@ -1378,6 +1378,7 @@ ref_syntax (Scheme_Object *form, Scheme_Comp_Env *env, Scheme_Compile_Info *rec,
else else
var = scheme_expand_expr(name, env, rec, drec); var = scheme_expand_expr(name, env, rec, drec);
} else { } else {
lex_id = NULL;
var = scheme_lookup_binding(name, env, var = scheme_lookup_binding(name, env,
SCHEME_REFERENCING SCHEME_REFERENCING
+ SCHEME_GLOB_ALWAYS_REFERENCE + SCHEME_GLOB_ALWAYS_REFERENCE
@ -1388,7 +1389,7 @@ ref_syntax (Scheme_Object *form, Scheme_Comp_Env *env, Scheme_Compile_Info *rec,
? SCHEME_RESOLVE_MODIDS ? SCHEME_RESOLVE_MODIDS
: 0), : 0),
env->in_modidx, env->in_modidx,
&menv, NULL, NULL); &menv, NULL, &lex_id);
if (SAME_TYPE(SCHEME_TYPE(var), scheme_variable_type) if (SAME_TYPE(SCHEME_TYPE(var), scheme_variable_type)
|| SAME_TYPE(SCHEME_TYPE(var), scheme_module_variable_type)) { || SAME_TYPE(SCHEME_TYPE(var), scheme_module_variable_type)) {
@ -1418,20 +1419,30 @@ ref_syntax (Scheme_Object *form, Scheme_Comp_Env *env, Scheme_Compile_Info *rec,
SCHEME_PTR1_VAL(o) = (Scheme_Object *)var; SCHEME_PTR1_VAL(o) = (Scheme_Object *)var;
SCHEME_PTR2_VAL(o) = (Scheme_Object *)dummy; SCHEME_PTR2_VAL(o) = (Scheme_Object *)dummy;
return o; return o;
} else } else {
return scheme_void; if (lex_id) {
form = SCHEME_STX_CAR(form);
return scheme_make_pair(form, scheme_make_pair(lex_id, scheme_null));
}
return NULL;
}
} }
static Scheme_Object * static Scheme_Object *
ref_expand(Scheme_Object *form, Scheme_Comp_Env *env, Scheme_Expand_Info *erec, int drec) ref_expand(Scheme_Object *form, Scheme_Comp_Env *env, Scheme_Expand_Info *erec, int drec)
{ {
Scheme_Object *naya;
SCHEME_EXPAND_OBSERVE_PRIM_VARREF(erec[drec].observer); SCHEME_EXPAND_OBSERVE_PRIM_VARREF(erec[drec].observer);
/* Error checking: */ /* Error checking, and lexical variable update: */
ref_syntax(form, env, erec, drec); naya = ref_syntax(form, env, erec, drec);
/* No change: */ if (!naya)
return form; /* No change: */
return form;
return scheme_datum_to_syntax(naya, form, form, 0, 2);
} }
/**********************************************************************/ /**********************************************************************/