expander: fix problem related to (local-expand 'module-begin ...)

When `local-expand` is used for a 'module-begin context, use a fresh
binding -> definition-unreadable-symbol table for the nested
expansion. That way, the table used for the main expansion is
unchanged, and re-expanding or evaluating the expanded module will
arrive at the same unreadable symbols as the initial expansion.

The report and example are from Alexis.
This commit is contained in:
Matthew Flatt 2018-05-06 07:35:26 -06:00
parent 662a9022c0
commit f231cb2003
3 changed files with 2244 additions and 2192 deletions

View File

@ -2535,6 +2535,53 @@ case of module-leve bindings; it doesn't cover local bindings.
(compile/eval u-code)
(test 'ns-val dynamic-require ''u 'v))))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Another example to check that re-expansion generates definition
;; names consistent with the previoud expansion.
(parameterize ([current-namespace (make-base-namespace)])
(define modbeg-trampoline
'(module modbeg-trampoline racket/base
(require (for-syntax racket/base
syntax/strip-context))
(provide (rename-out [module-begin #%module-begin]))
(define-syntax (module-begin stx)
(syntax-case stx ()
[(_ lang . body)
#'(#%plain-module-begin (module-begin-trampoline lang . body))]))
(define-syntax (module-begin-trampoline stx)
(syntax-case stx ()
[(_ lang . body)
(with-syntax ([[modbeg . [body* ...]] (syntax-local-introduce
(syntax-local-lift-require
(strip-context #'lang)
(datum->syntax #f (cons '#%module-begin
(strip-context #'body)))))])
(with-syntax ([body** (if (= (length (syntax->list #'(body* ...))) 1)
(error "oops")
#'(modbeg . [body* ...]))])
(with-syntax ([(modbeg* form ...) (local-expand #'body** 'module-begin #f)])
(with-syntax ([body*** (local-expand #'(modbeg* form ...) 'module-begin (list #'module*))])
(with-syntax ([(modbeg**:#%plain-module-begin form* ...) #'body***])
(syntax-track-origin #`(begin form* ...) #'body*** #'modbeg**))))))]))))
(define m-use
'(module m-use 'modbeg-trampoline racket/base
(require racket/contract/base)
(provide (contract-out [f (-> number? number?)]))
(define (f x) (+ x 42))
(module* main racket
(require (submod ".."))
(f 10))))
(eval modbeg-trampoline)
(eval (expand m-use))
(dynamic-require '(submod 'm-use main) #f))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(report-errs)

View File

@ -3,6 +3,7 @@
"../common/struct-star.rkt"
"../common/performance.rkt"
"../syntax/syntax.rkt"
"../syntax/debug.rkt"
"../syntax/property.rkt"
"../syntax/scope.rkt"
"../syntax/taint.rkt"
@ -233,7 +234,7 @@
(hash-clear! compiled-submodules)
(set-box! compiled-module-box #f))
(set! again? #t)
;; In case a nested `#%module-begin` expansion is forced, save
;; and restore the module-expansion state:
(define ctx (struct*-copy expand-context mb-init-ctx
@ -249,7 +250,8 @@
#:copy-requires requires+provides))
(with-save-and-restore ([requires+provides new-requires+provides]
[compiled-submodules (make-hasheq)]
[compiled-module-box (box #f)])
[compiled-module-box (box #f)]
[defined-syms (make-hasheq)])
(module-begin-k s ctx)))]))
;; In case `#%module-begin` expansion is forced on syntax that

File diff suppressed because it is too large Load Diff