expander: fix body scope for letrec-syntax
An extra scope is needed to separate the bindings of a `letrec` from the `letrec` body, in case a macro moves right-hand-side expressions to the body. Michael Ballantyne and William Hatch reported this problem and its solution in December 2016, but I forgot to add the repair. Relevant to #2237
This commit is contained in:
parent
1d65a89f53
commit
37c9169874
|
@ -2310,4 +2310,35 @@
|
||||||
|
|
||||||
;; ----------------------------------------
|
;; ----------------------------------------
|
||||||
|
|
||||||
|
(test 'ok 'scope-for-letrec
|
||||||
|
(let ([x 'ok])
|
||||||
|
(letrec-syntax ([foo (lambda (stx)
|
||||||
|
#'x)])
|
||||||
|
(define x 2)
|
||||||
|
(foo))))
|
||||||
|
|
||||||
|
|
||||||
|
(test 1 'scope-for-letrec
|
||||||
|
(let ()
|
||||||
|
(define-syntaxes (stash restore)
|
||||||
|
(let ([stash #f])
|
||||||
|
(values
|
||||||
|
;; stash
|
||||||
|
(lambda (stx)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(_ arg)
|
||||||
|
(begin (set! stash (syntax-local-introduce #'arg))
|
||||||
|
#'arg)]))
|
||||||
|
;; restore
|
||||||
|
(lambda (stx)
|
||||||
|
(syntax-local-introduce stash)))))
|
||||||
|
|
||||||
|
(define x 1)
|
||||||
|
|
||||||
|
(letrec-values ([(foo) (stash x)])
|
||||||
|
(define x 2)
|
||||||
|
(restore))))
|
||||||
|
|
||||||
|
;; ----------------------------------------
|
||||||
|
|
||||||
(report-errs)
|
(report-errs)
|
||||||
|
|
|
@ -171,6 +171,7 @@
|
||||||
'(let-values ([(id:val ...) val-rhs] ...)
|
'(let-values ([(id:val ...) val-rhs] ...)
|
||||||
body ...+))
|
body ...+))
|
||||||
(define sc (new-scope 'local))
|
(define sc (new-scope 'local))
|
||||||
|
(define body-sc (and rec? (new-scope 'letrec-body)))
|
||||||
(define phase (expand-context-phase ctx))
|
(define phase (expand-context-phase ctx))
|
||||||
(define frame-id (and syntaxes?
|
(define frame-id (and syntaxes?
|
||||||
(make-reference-record))) ; accumulates info on referenced variables
|
(make-reference-record))) ; accumulates info on referenced variables
|
||||||
|
@ -205,7 +206,10 @@
|
||||||
(add-local-binding! id phase counter #:frame-id frame-id #:in s))))
|
(add-local-binding! id phase counter #:frame-id frame-id #:in s))))
|
||||||
;; Add new scope to body:
|
;; Add new scope to body:
|
||||||
(define bodys (for/list ([body (in-list (if syntaxes? (stx-m 'body) (val-m 'body)))])
|
(define bodys (for/list ([body (in-list (if syntaxes? (stx-m 'body) (val-m 'body)))])
|
||||||
(add-scope body sc)))
|
(define new-body (add-scope body sc))
|
||||||
|
(if rec?
|
||||||
|
(add-scope new-body body-sc)
|
||||||
|
new-body)))
|
||||||
(log-expand... ctx (lambda (obs)
|
(log-expand... ctx (lambda (obs)
|
||||||
(log-let-renames obs renames-log-tag val-idss val-rhss bodys
|
(log-let-renames obs renames-log-tag val-idss val-rhss bodys
|
||||||
trans-idss (and syntaxes? (stx-m 'trans-rhs)) sc)))
|
trans-idss (and syntaxes? (stx-m 'trans-rhs)) sc)))
|
||||||
|
@ -241,7 +245,10 @@
|
||||||
(define orig-rrs (expand-context-reference-records expr-ctx))
|
(define orig-rrs (expand-context-reference-records expr-ctx))
|
||||||
(define rec-ctx (struct*-copy expand-context expr-ctx
|
(define rec-ctx (struct*-copy expand-context expr-ctx
|
||||||
[env rec-env]
|
[env rec-env]
|
||||||
[scopes (cons sc (expand-context-scopes ctx))]
|
[scopes (let ([scopes (cons sc (expand-context-scopes ctx))])
|
||||||
|
(if rec?
|
||||||
|
(cons body-sc scopes)
|
||||||
|
scopes))]
|
||||||
[reference-records (if split-by-reference?
|
[reference-records (if split-by-reference?
|
||||||
(cons frame-id orig-rrs)
|
(cons frame-id orig-rrs)
|
||||||
orig-rrs)]
|
orig-rrs)]
|
||||||
|
|
|
@ -65093,6 +65093,7 @@ static const char *startup_source =
|
||||||
"(values #t let-values127_0 id:val128_0 val-rhs129_0 body130_0)))"
|
"(values #t let-values127_0 id:val128_0 val-rhs129_0 body130_0)))"
|
||||||
"(values #f #f #f #f #f)))))"
|
"(values #f #f #f #f #f)))))"
|
||||||
"(let-values(((sc_0)(new-scope 'local)))"
|
"(let-values(((sc_0)(new-scope 'local)))"
|
||||||
|
"(let-values(((body-sc_0)(if rec?_0(new-scope 'letrec-body) #f)))"
|
||||||
"(let-values(((phase_0)(expand-context-phase ctx_0)))"
|
"(let-values(((phase_0)(expand-context-phase ctx_0)))"
|
||||||
"(let-values(((frame-id_0)(if syntaxes?_0(make-reference-record) #f)))"
|
"(let-values(((frame-id_0)(if syntaxes?_0(make-reference-record) #f)))"
|
||||||
"(let-values(((trans-idss_0)"
|
"(let-values(((trans-idss_0)"
|
||||||
|
@ -65108,7 +65109,8 @@ static const char *startup_source =
|
||||||
" 'for-loop"
|
" 'for-loop"
|
||||||
"(if(pair? lst_1)"
|
"(if(pair? lst_1)"
|
||||||
"(let-values(((ids_0)(unsafe-car lst_1))"
|
"(let-values(((ids_0)(unsafe-car lst_1))"
|
||||||
"((rest_0)(unsafe-cdr lst_1)))"
|
"((rest_0)"
|
||||||
|
"(unsafe-cdr lst_1)))"
|
||||||
"(let-values(((fold-var_1)"
|
"(let-values(((fold-var_1)"
|
||||||
"(let-values(((fold-var_1)"
|
"(let-values(((fold-var_1)"
|
||||||
" fold-var_0))"
|
" fold-var_0))"
|
||||||
|
@ -65163,7 +65165,8 @@ static const char *startup_source =
|
||||||
" null"
|
" null"
|
||||||
" lst_2)))))"
|
" lst_2)))))"
|
||||||
" fold-var_1))))"
|
" fold-var_1))))"
|
||||||
"(values fold-var_2)))))"
|
"(values"
|
||||||
|
" fold-var_2)))))"
|
||||||
"(if(not #f)"
|
"(if(not #f)"
|
||||||
"(for-loop_0 fold-var_1 rest_0)"
|
"(for-loop_0 fold-var_1 rest_0)"
|
||||||
" fold-var_1)))"
|
" fold-var_1)))"
|
||||||
|
@ -65183,7 +65186,8 @@ static const char *startup_source =
|
||||||
"(begin"
|
"(begin"
|
||||||
" 'for-loop"
|
" 'for-loop"
|
||||||
"(if(pair? lst_1)"
|
"(if(pair? lst_1)"
|
||||||
"(let-values(((ids_0)(unsafe-car lst_1))"
|
"(let-values(((ids_0)"
|
||||||
|
"(unsafe-car lst_1))"
|
||||||
"((rest_0)"
|
"((rest_0)"
|
||||||
"(unsafe-cdr lst_1)))"
|
"(unsafe-cdr lst_1)))"
|
||||||
"(let-values(((fold-var_1)"
|
"(let-values(((fold-var_1)"
|
||||||
|
@ -65255,7 +65259,8 @@ static const char *startup_source =
|
||||||
"(let-values(((lst_0)"
|
"(let-values(((lst_0)"
|
||||||
"(if syntaxes?_0 val-rhs105_0 val-rhs129_0)))"
|
"(if syntaxes?_0 val-rhs105_0 val-rhs129_0)))"
|
||||||
"(begin"
|
"(begin"
|
||||||
"(if(variable-reference-from-unsafe?(#%variable-reference))"
|
"(if(variable-reference-from-unsafe?"
|
||||||
|
"(#%variable-reference))"
|
||||||
"(void)"
|
"(void)"
|
||||||
"(let-values()(check-list lst_0)))"
|
"(let-values()(check-list lst_0)))"
|
||||||
"((letrec-values(((for-loop_0)"
|
"((letrec-values(((for-loop_0)"
|
||||||
|
@ -65281,7 +65286,9 @@ static const char *startup_source =
|
||||||
"(values"
|
"(values"
|
||||||
" fold-var_2)))))"
|
" fold-var_2)))))"
|
||||||
"(if(not #f)"
|
"(if(not #f)"
|
||||||
"(for-loop_0 fold-var_1 rest_0)"
|
"(for-loop_0"
|
||||||
|
" fold-var_1"
|
||||||
|
" rest_0)"
|
||||||
" fold-var_1)))"
|
" fold-var_1)))"
|
||||||
" fold-var_0)))))"
|
" fold-var_0)))))"
|
||||||
" for-loop_0)"
|
" for-loop_0)"
|
||||||
|
@ -65360,7 +65367,7 @@ static const char *startup_source =
|
||||||
"(let-values()"
|
"(let-values()"
|
||||||
"(raise-syntax-error$1"
|
"(raise-syntax-error$1"
|
||||||
" #f"
|
" #f"
|
||||||
" \"bad syntax\""
|
" \"bad syntax\""
|
||||||
" orig-s_0))"
|
" orig-s_0))"
|
||||||
"(let-values()"
|
"(let-values()"
|
||||||
" flat-s_0))))))"
|
" flat-s_0))))))"
|
||||||
|
@ -65374,7 +65381,7 @@ static const char *startup_source =
|
||||||
" _165_0))"
|
" _165_0))"
|
||||||
"(raise-syntax-error$1"
|
"(raise-syntax-error$1"
|
||||||
" #f"
|
" #f"
|
||||||
" \"bad syntax\""
|
" \"bad syntax\""
|
||||||
" orig-s_0))))))"
|
" orig-s_0))))))"
|
||||||
"(values"
|
"(values"
|
||||||
" _161_0"
|
" _161_0"
|
||||||
|
@ -65382,7 +65389,7 @@ static const char *startup_source =
|
||||||
" _163_0))"
|
" _163_0))"
|
||||||
"(raise-syntax-error$1"
|
"(raise-syntax-error$1"
|
||||||
" #f"
|
" #f"
|
||||||
" \"bad syntax\""
|
" \"bad syntax\""
|
||||||
" orig-s_0))))))"
|
" orig-s_0))))))"
|
||||||
"(values"
|
"(values"
|
||||||
" _157_0"
|
" _157_0"
|
||||||
|
@ -65391,7 +65398,7 @@ static const char *startup_source =
|
||||||
" _160_0))"
|
" _160_0))"
|
||||||
"(raise-syntax-error$1"
|
"(raise-syntax-error$1"
|
||||||
" #f"
|
" #f"
|
||||||
" \"bad syntax\""
|
" \"bad syntax\""
|
||||||
" orig-s_0)))))"
|
" orig-s_0)))))"
|
||||||
"(values"
|
"(values"
|
||||||
" #t"
|
" #t"
|
||||||
|
@ -65448,7 +65455,7 @@ static const char *startup_source =
|
||||||
"(let-values()"
|
"(let-values()"
|
||||||
"(raise-syntax-error$1"
|
"(raise-syntax-error$1"
|
||||||
" #f"
|
" #f"
|
||||||
" \"bad syntax\""
|
" \"bad syntax\""
|
||||||
" orig-s_0))"
|
" orig-s_0))"
|
||||||
"(let-values()"
|
"(let-values()"
|
||||||
" flat-s_0))))))"
|
" flat-s_0))))))"
|
||||||
|
@ -65462,7 +65469,7 @@ static const char *startup_source =
|
||||||
" _173_0))"
|
" _173_0))"
|
||||||
"(raise-syntax-error$1"
|
"(raise-syntax-error$1"
|
||||||
" #f"
|
" #f"
|
||||||
" \"bad syntax\""
|
" \"bad syntax\""
|
||||||
" orig-s_0))))))"
|
" orig-s_0))))))"
|
||||||
"(values"
|
"(values"
|
||||||
" _169_0"
|
" _169_0"
|
||||||
|
@ -65470,9 +65477,13 @@ static const char *startup_source =
|
||||||
" _171_0))"
|
" _171_0))"
|
||||||
"(raise-syntax-error$1"
|
"(raise-syntax-error$1"
|
||||||
" #f"
|
" #f"
|
||||||
" \"bad syntax\""
|
" \"bad syntax\""
|
||||||
" orig-s_0)))))"
|
" orig-s_0)))))"
|
||||||
"(values #t _166_0 clause167_0 _168_0))))))"
|
"(values"
|
||||||
|
" #t"
|
||||||
|
" _166_0"
|
||||||
|
" clause167_0"
|
||||||
|
" _168_0))))))"
|
||||||
" clause167_0)))))"
|
" clause167_0)))))"
|
||||||
"(let-values((()"
|
"(let-values((()"
|
||||||
"(begin"
|
"(begin"
|
||||||
|
@ -65708,9 +65719,15 @@ static const char *startup_source =
|
||||||
"(let-values()"
|
"(let-values()"
|
||||||
"(cons"
|
"(cons"
|
||||||
"(let-values()"
|
"(let-values()"
|
||||||
|
"(let-values(((new-body_0)"
|
||||||
"(add-scope"
|
"(add-scope"
|
||||||
" body_0"
|
" body_0"
|
||||||
" sc_0))"
|
" sc_0)))"
|
||||||
|
"(if rec?_0"
|
||||||
|
"(add-scope"
|
||||||
|
" new-body_0"
|
||||||
|
" body-sc_0)"
|
||||||
|
" new-body_0)))"
|
||||||
" fold-var_1))))"
|
" fold-var_1))))"
|
||||||
"(values"
|
"(values"
|
||||||
" fold-var_2)))))"
|
" fold-var_2)))))"
|
||||||
|
@ -65871,7 +65888,8 @@ static const char *startup_source =
|
||||||
" lst_3)"
|
" lst_3)"
|
||||||
"(begin"
|
"(begin"
|
||||||
" 'for-loop"
|
" 'for-loop"
|
||||||
"(if(if(pair? lst_2)"
|
"(if(if(pair?"
|
||||||
|
" lst_2)"
|
||||||
"(pair? lst_3)"
|
"(pair? lst_3)"
|
||||||
" #f)"
|
" #f)"
|
||||||
"(let-values(((keys_0)"
|
"(let-values(((keys_0)"
|
||||||
|
@ -66123,7 +66141,8 @@ static const char *startup_source =
|
||||||
" lst_0"
|
" lst_0"
|
||||||
" lst_1"
|
" lst_1"
|
||||||
" lst_2)))))"
|
" lst_2)))))"
|
||||||
"(let-values(((expr-ctx_0)(as-expression-context ctx_0)))"
|
"(let-values(((expr-ctx_0)"
|
||||||
|
"(as-expression-context ctx_0)))"
|
||||||
"(let-values(((orig-rrs_0)"
|
"(let-values(((orig-rrs_0)"
|
||||||
"(expand-context-reference-records"
|
"(expand-context-reference-records"
|
||||||
" expr-ctx_0)))"
|
" expr-ctx_0)))"
|
||||||
|
@ -66135,10 +66154,16 @@ static const char *startup_source =
|
||||||
"(let-values(((env184_0)"
|
"(let-values(((env184_0)"
|
||||||
" rec-env_0)"
|
" rec-env_0)"
|
||||||
"((scopes185_0)"
|
"((scopes185_0)"
|
||||||
|
"(let-values(((scopes_0)"
|
||||||
"(cons"
|
"(cons"
|
||||||
" sc_0"
|
" sc_0"
|
||||||
"(expand-context-scopes"
|
"(expand-context-scopes"
|
||||||
" ctx_0)))"
|
" ctx_0))))"
|
||||||
|
"(if rec?_0"
|
||||||
|
"(cons"
|
||||||
|
" body-sc_0"
|
||||||
|
" scopes_0)"
|
||||||
|
" scopes_0)))"
|
||||||
"((reference-records186_0)"
|
"((reference-records186_0)"
|
||||||
"(if split-by-reference?_0"
|
"(if split-by-reference?_0"
|
||||||
"(cons"
|
"(cons"
|
||||||
|
@ -66183,7 +66208,7 @@ static const char *startup_source =
|
||||||
" the-struct_0)))"
|
" the-struct_0)))"
|
||||||
"(raise-argument-error"
|
"(raise-argument-error"
|
||||||
" 'struct-copy"
|
" 'struct-copy"
|
||||||
" \"expand-context/outer?\""
|
" \"expand-context/outer?\""
|
||||||
" the-struct_0))))))"
|
" the-struct_0))))))"
|
||||||
"(let-values(((letrec-values-id_0)"
|
"(let-values(((letrec-values-id_0)"
|
||||||
"(if(not"
|
"(if(not"
|
||||||
|
@ -66381,7 +66406,7 @@ static const char *startup_source =
|
||||||
" the-struct_0)))"
|
" the-struct_0)))"
|
||||||
"(raise-argument-error"
|
"(raise-argument-error"
|
||||||
" 'struct-copy"
|
" 'struct-copy"
|
||||||
" \"expand-context/outer?\""
|
" \"expand-context/outer?\""
|
||||||
" the-struct_0))))))"
|
" the-struct_0))))))"
|
||||||
"(let-values(((bodys192_0)"
|
"(let-values(((bodys192_0)"
|
||||||
" bodys_0)"
|
" bodys_0)"
|
||||||
|
@ -66621,7 +66646,7 @@ static const char *startup_source =
|
||||||
" result-s_0"
|
" result-s_0"
|
||||||
"(attach-disappeared-transformer-bindings"
|
"(attach-disappeared-transformer-bindings"
|
||||||
" result-s_0"
|
" result-s_0"
|
||||||
" trans-idss_0))))))))))))))))))))))))))))))))))))))))))"
|
" trans-idss_0)))))))))))))))))))))))))))))))))))))))))))"
|
||||||
"(define-values"
|
"(define-values"
|
||||||
"(log-let-renames)"
|
"(log-let-renames)"
|
||||||
"(lambda(obs_0 renames-log-tag_0 val-idss_0 val-rhss_0 bodys_0 trans-idss_0 trans-rhss_0 sc_0)"
|
"(lambda(obs_0 renames-log-tag_0 val-idss_0 val-rhss_0 bodys_0 trans-idss_0 trans-rhss_0 sc_0)"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user