added rename option to lazy-require
closes PR 13624 also added examples
This commit is contained in:
parent
2eae24b0b1
commit
1b729d34d8
|
@ -37,59 +37,71 @@
|
||||||
|
|
||||||
(define-syntax (lazy-require1 stx)
|
(define-syntax (lazy-require1 stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(lazy-require1 modpath (name ...) orig-stx)
|
[(lazy-require1 modpath (thing ...) orig-stx)
|
||||||
(with-syntax ([(defn ...)
|
(with-syntax ([((exp-name bind-name) ...)
|
||||||
(for/list ([name (in-list (syntax->list #'(name ...)))])
|
(for/list ([thing-stx (in-list (syntax->list #'(thing ...)))])
|
||||||
(unless (identifier? name)
|
(syntax-case thing-stx ()
|
||||||
(raise-syntax-error #f "expected identifier" #'orig-stx name))
|
[name
|
||||||
(with-syntax ([name name]
|
(identifier? #'name)
|
||||||
[(aux) (generate-temporaries (list name))])
|
(list #'name #'name)]
|
||||||
#`(begin (define aux (make-lazy-function 'name get-sym))
|
[[exp-name bind-name]
|
||||||
(define-syntax name
|
(begin
|
||||||
(make-rename-transformer
|
(unless (identifier? #'exp-name)
|
||||||
(syntax-property (quote-syntax aux)
|
(raise-syntax-error #f "expected identifier"
|
||||||
'not-provide-all-defined #t))))))]
|
#'orig-stx #'exp-name))
|
||||||
[define-mpi-var
|
(unless (identifier? #'bind-name)
|
||||||
(let ([phase (sub1 (variable-reference->phase (#%variable-reference)))])
|
(raise-syntax-error #f "expected identifier"
|
||||||
(if (zero? phase)
|
#'orig-stx #'bind-name))
|
||||||
;; `define-runtime-module-path-index' works right at phase-level 0:
|
(list #'exp-name #'bind-name))]
|
||||||
#'(define-runtime-module-path-index mpi-var (quote modpath))
|
[_
|
||||||
;; need a submodule:
|
(raise-syntax-error #f "expected identifier or pair of identifiers"
|
||||||
(with-syntax ([lazy-require-path-n
|
#'orig-stx thing-stx)]))]
|
||||||
(string->symbol
|
[mpi-var-defn
|
||||||
(format "lazy-require-path-~a-~a"
|
(let ([phase (sub1 (variable-reference->phase (#%variable-reference)))])
|
||||||
phase
|
(if (zero? phase)
|
||||||
counter))]
|
;; `define-runtime-module-path-index' works right at phase-level 0:
|
||||||
;; May need to adjust modpath, since we're interpreting it
|
#'(define-runtime-module-path-index mpi-var (quote modpath))
|
||||||
;; relative to a *submodule* of the original context.
|
;; need a submodule:
|
||||||
;; ie, module-path interpretation is not hygienic!
|
(with-syntax ([lazy-require-path-n
|
||||||
[modpath* (module-path-add-submod-up #'modpath)])
|
(string->symbol
|
||||||
(set! counter (add1 counter))
|
(format "lazy-require-path-~a-~a"
|
||||||
#'(begin
|
phase
|
||||||
(module lazy-require-path-n racket/base
|
counter))]
|
||||||
(require racket/runtime-path
|
;; May need to adjust modpath, since we're interpreting it
|
||||||
(for-syntax racket/base))
|
;; relative to a *submodule* of the original context.
|
||||||
(provide mpi-var)
|
;; ie, module-path interpretation is not hygienic!
|
||||||
(define-runtime-module-path-index mpi-var (quote modpath*)))
|
[modpath* (module-path-add-submod-up #'modpath)])
|
||||||
(require 'lazy-require-path-n)))))])
|
(set! counter (add1 counter))
|
||||||
#'(begin
|
#'(begin
|
||||||
define-mpi-var
|
(module lazy-require-path-n racket/base
|
||||||
(define (get-sym sym)
|
(require racket/runtime-path
|
||||||
(parameterize ((current-namespace (variable-reference->namespace (#%variable-reference))))
|
(for-syntax racket/base))
|
||||||
(begin0
|
(provide mpi-var)
|
||||||
(dynamic-require mpi-var sym)
|
(define-runtime-module-path-index mpi-var (quote modpath*)))
|
||||||
(do-registration (#%variable-reference) (quote modpath)))))
|
(require (submod "." lazy-require-path-n))))))])
|
||||||
defn ...))]))
|
(with-syntax ([(aux-name ...) (generate-temporaries #'(bind-name ...))])
|
||||||
|
#'(begin
|
||||||
|
mpi-var-defn
|
||||||
|
(define (get-sym sym)
|
||||||
|
(parameterize ((current-namespace (variable-reference->namespace (#%variable-reference))))
|
||||||
|
(begin0
|
||||||
|
(dynamic-require mpi-var sym)
|
||||||
|
(do-registration (#%variable-reference) (quote modpath)))))
|
||||||
|
(define aux-name (make-lazy-function 'exp-name 'bind-name get-sym)) ...
|
||||||
|
(define-syntax bind-name
|
||||||
|
(make-rename-transformer
|
||||||
|
(syntax-property (quote-syntax aux-name)
|
||||||
|
'not-provide-all-defined #t))) ...)))]))
|
||||||
|
|
||||||
(define (make-lazy-function name get-sym)
|
(define (make-lazy-function exp-name bind-name get-sym)
|
||||||
;; Use 'delay/sync' because 'delay' promise is not reentrant.
|
;; Use 'delay/sync' because 'delay' promise is not reentrant.
|
||||||
;; FIXME: OTOH, 'delay/sync' promise is not kill-safe.
|
;; FIXME: OTOH, 'delay/sync' promise is not kill-safe.
|
||||||
(let ([fun-p (delay/sync (get-sym name))])
|
(let ([fun-p (delay/sync (get-sym exp-name))])
|
||||||
(procedure-rename
|
(procedure-rename
|
||||||
(make-keyword-procedure
|
(make-keyword-procedure
|
||||||
(lambda (kws kwargs . args)
|
(lambda (kws kwargs . args)
|
||||||
(keyword-apply (force fun-p) kws kwargs args)))
|
(keyword-apply (force fun-p) kws kwargs args)))
|
||||||
name)))
|
bind-name)))
|
||||||
|
|
||||||
(define (do-registration vr modpath)
|
(define (do-registration vr modpath)
|
||||||
(let ([path (resolved-module-path-name
|
(let ([path (resolved-module-path-name
|
||||||
|
|
|
@ -2824,12 +2824,19 @@ heuristics, and should only be used when other inlining attempts (such as
|
||||||
|
|
||||||
@note-lib-only[racket/lazy-require]
|
@note-lib-only[racket/lazy-require]
|
||||||
|
|
||||||
@defform[(lazy-require [module-path (imported-fun-id ...)] ...)]{
|
@(define lazy-require-eval (make-base-eval))
|
||||||
|
@(lazy-require-eval '(require racket/lazy-require))
|
||||||
|
|
||||||
Defines each @racket[imported-fun-id] as a function that, when called,
|
@defform[(lazy-require [module-path (fun-import ...)] ...)
|
||||||
dynamically requires the export named @racket[imported-fun-id] from
|
#:grammar
|
||||||
the module specified by @racket[module-path] and calls it with the
|
([fun-import fun-id
|
||||||
same arguments.
|
(orig-fun-id fun-id)])]{
|
||||||
|
|
||||||
|
Defines each @racket[fun-id] as a function that, when called,
|
||||||
|
dynamically requires the export named @racket[orig-fun-id] from the
|
||||||
|
module specified by @racket[module-path] and calls it with the same
|
||||||
|
arguments. If @racket[orig-fun-id] is not given, it defaults to
|
||||||
|
@racket[fun-id].
|
||||||
|
|
||||||
If the enclosing relative phase level is not 0, then
|
If the enclosing relative phase level is not 0, then
|
||||||
@racket[module-path] is also placed in a submodule (with a use of
|
@racket[module-path] is also placed in a submodule (with a use of
|
||||||
|
@ -2841,4 +2848,20 @@ submodule). Introduced submodules have the names
|
||||||
When the use of a lazily-required function triggers module loading,
|
When the use of a lazily-required function triggers module loading,
|
||||||
@racket[register-external-module] declares a potential compilation
|
@racket[register-external-module] declares a potential compilation
|
||||||
dependency (in case the function is used in the process of compiling a
|
dependency (in case the function is used in the process of compiling a
|
||||||
module).}
|
module).
|
||||||
|
|
||||||
|
@examples[#:eval lazy-require-eval
|
||||||
|
(lazy-require
|
||||||
|
[racket/list (partition)])
|
||||||
|
(partition even? '(1 2 3 4 5))
|
||||||
|
(module hello racket/base
|
||||||
|
(provide hello)
|
||||||
|
(printf "starting hello server\n")
|
||||||
|
(define (hello) (printf "hello!\n")))
|
||||||
|
(lazy-require
|
||||||
|
['hello ([hello greet])])
|
||||||
|
(greet)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
@(close-eval lazy-require-eval)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user