try module+' in place of slice'

This commit is contained in:
Matthew Flatt 2012-03-13 11:03:09 -06:00
parent 8d6e9e79a4
commit e01ebf6095
7 changed files with 135 additions and 85 deletions

View File

@ -248,7 +248,7 @@
letrec-values letrec-values
with-syntax with-syntax
with-continuation-mark with-continuation-mark
module module* module module* module+
match match-let match-let* match-letrec match match-let match-let* match-letrec
let/cc let/ec letcc catch let/cc let/ec letcc catch
let-syntax letrec-syntax fluid-let-syntax letrec-syntaxes+values let-syntax letrec-syntax fluid-let-syntax letrec-syntaxes+values

View File

@ -10,6 +10,7 @@
"namespace.rkt" "namespace.rkt"
"struct.rkt" "struct.rkt"
"cert.rkt" "cert.rkt"
"submodule.rkt"
(for-syntax "stxcase-scheme.rkt")) (for-syntax "stxcase-scheme.rkt"))
(#%provide (all-from-except "pre-base.rkt" (#%provide (all-from-except "pre-base.rkt"
@ -33,6 +34,7 @@
(all-from-except "qqstx.rkt" quasidatum undatum undatum-splicing) (all-from-except "qqstx.rkt" quasidatum undatum undatum-splicing)
(all-from "namespace.rkt") (all-from "namespace.rkt")
(all-from "cert.rkt") (all-from "cert.rkt")
(all-from "submodule.rkt")
(for-syntax syntax-rules syntax-id-rules ... _) (for-syntax syntax-rules syntax-id-rules ... _)
(rename -open-input-file open-input-file) (rename -open-input-file open-input-file)
(rename -open-output-file open-output-file) (rename -open-output-file open-output-file)

View File

@ -0,0 +1,73 @@
(module module+ '#%kernel
(#%require "more-scheme.rkt"
"modbeg.rkt"
(for-syntax '#%kernel
"stxcase-scheme.rkt"
"more-scheme.rkt"
"letstx-scheme.rkt"
"qqstx.rkt"))
(#%provide module+)
(define-syntaxes (module+)
(lambda (stx)
(case (syntax-local-context)
[(module-begin)
(quasisyntax/loc stx (begin #,stx))]
[(module)
(syntax-case stx ()
[(_ the-submodule e ...)
(begin
(unless (symbol? (syntax-e #'the-submodule))
(raise-syntax-error #f
"expected an identifier for a submodule, found something else"
stx
#'the-submodule))
;; This looks it up the first time and is allowed to create a
;; list and lift a module-end declaration if necessary:
(let ([stxs-box (get-stxs-box stx #'the-submodule #t)])
(set-box! stxs-box
(append (reverse (syntax->list (syntax-local-introduce #'(e ...))))
(unbox stxs-box))))
(syntax/loc stx (begin)))])]
[else
(raise-syntax-error #f
"allowed only in a module body"
stx)])))
(begin-for-syntax
;; The following table is newly instantiated for each module
;; expansion that uses `module+', so it is effectively
;; module-local:
(define-values (submodule->stxs-box) (make-weak-hash))
(define-values (get-stxs-box)
(lambda (form-stx the-submodule-stx lift?)
(hash-ref! submodule->stxs-box (syntax-e the-submodule-stx)
(lambda ()
(when lift?
(syntax-local-lift-module-end-declaration
;; Use the lexical context of the first `module+'
;; form as the context of the implicit `#%module-begin':
(datum->syntax
form-stx
(list #'define-module the-submodule-stx)
form-stx)))
(box null))))))
;; A use of this form is lifted to the end of the enclosing module
;; for each submodule created by `module+':
(define-syntaxes (define-module)
(lambda (stx)
(syntax-case stx ()
[(_ the-submodule)
(let ([stxs-box (get-stxs-box #f #'the-submodule #f)])
;; Propagate the lexical context of the first `module+'
;; for the implicit `#%module-begin':
(datum->syntax
stx
(list*
#'module*
#'the-submodule
#'#f
(map syntax-local-introduce (reverse (unbox stxs-box))))
stx))]))))

View File

@ -1,47 +0,0 @@
#lang racket/base
(require (for-syntax racket/base))
(begin-for-syntax
(define module->submodule->stxs-box (make-weak-hash))
(define (get-stxs-box the-submodule-stx lift?)
(define the-module (syntax-source-module the-submodule-stx))
(define submodule->stxs-box
(hash-ref! module->submodule->stxs-box the-module make-weak-hasheq))
(define the-submodule-id
(syntax->datum the-submodule-stx))
(define stxs-box
(hash-ref! submodule->stxs-box the-submodule-id
(λ ()
(when lift?
(syntax-local-lift-module-end-declaration
(quasisyntax/loc the-submodule-stx
(define-module #,the-submodule-stx))))
(box null))))
stxs-box))
(define-syntax (slice stx)
(syntax-case stx ()
[(_ the-submodule e ...)
(identifier? #'the-submodule)
(begin
;; This looks it up the first time and is allowed to create a
;; list if necessary
(get-stxs-box #'the-submodule #t)
#'(begin-for-syntax
(define stxs-box
(get-stxs-box #'the-submodule #f))
(set-box! stxs-box
(append (unbox stxs-box)
(syntax->list #'(e ...))))))]))
(define-syntax (define-module stx)
(syntax-case stx ()
[(_ the-submodule)
(begin
(define stxs-box
(get-stxs-box #'the-submodule #f))
(quasisyntax/loc #'the-submodule
(module* the-submodule #f
#,@(unbox stxs-box))))]))
(provide slice)

View File

@ -11,7 +11,6 @@
racket/package racket/package
racket/splicing racket/splicing
racket/runtime-path racket/runtime-path
racket/slice
racket/performance-hint)) racket/performance-hint))
@(define require-eval (make-base-eval)) @(define require-eval (make-base-eval))
@ -305,6 +304,22 @@ starts with an empty lexical context in the same way as a top-level
have no effect on the submodule.} have no effect on the submodule.}
@defform[(module+ id form ...)]{
Declares and/or adds to a @tech{submodule} named @racket[id].
Each addition for @racket[id] is combined in order to form the entire
submodule using @racket[(module* id #f ....)] at the end of the
enclosing module. If there is only one @racket[module+] for a given
@racket[id], then @racket[(module+ id form ...)] is equivalent to
@racket[(module* id #f form ...)].
A submodule must not be defined using @racket[module+] @emph{and}
@racket[module] or @racket[module*]. That is, if a submodule is made
of @racket[module+] pieces, then it must be made @emph{only} of
@racket[module+] pieces. }
@defform[(#%module-begin form ...)]{ @defform[(#%module-begin form ...)]{
Legal only in a @tech{module begin context}, and handled by the Legal only in a @tech{module begin context}, and handled by the
@ -320,24 +335,6 @@ Legal only in a @tech{module begin context}, and handled by the
@racket[module] and @racket[module*] forms.} @racket[module] and @racket[module*] forms.}
@;------------------------------------------------------------------------
@subsection[#:tag "slice"]{Slices: @racket[slice]}
@note-lib-only[racket/slice]
@defform[(slice id form ...)]{
Declares a @tech{slice} of a @tech{submodule} named @racket[id].
A @deftech{slice} is a piece of a @tech{submodule}. Each slice of a
submodule is combined to form the entire submodule at
the end of the enclosing module. If there is only one slice, then
@racket[(slice id form ...)] is equivalent to @racket[(module* id #f
form ...)]. It is an error for a submodule to be defined using
@racket[slice] @emph{and} @racket[module] or @racket[module*]. That
is, if a submodule is made of slices, then it must be
made @emph{only} of slices. }
@;------------------------------------------------------------------------ @;------------------------------------------------------------------------
@section[#:tag '("require" "provide")]{Importing and Exporting: @racket[require] and @racket[provide]} @section[#:tag '("require" "provide")]{Importing and Exporting: @racket[require] and @racket[provide]}

View File

@ -1,18 +0,0 @@
#lang racket/base
(module fac1 racket/base
(printf "fac1 running\n")
(require racket/slice)
(define (! n)
(if (zero? n)
1
(* n (! (sub1 n)))))
(slice test
(printf "fac1 testing\n")
(require rackunit)
(check-equal? (! 0) 1))
(slice test
(check-equal? (! 1) 1)
(check-equal? (! 5) 120)))
(require (submod 'fac1 test))

View File

@ -319,6 +319,49 @@
(test '(a) dynamic-require '(submod 'subm-example-12 a) 'a) (test '(a) dynamic-require '(submod 'subm-example-12 a) 'a)
(test 'b dynamic-require '(submod 'subm-example-12 b) 'b) (test 'b dynamic-require '(submod 'subm-example-12 b) 'b)
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; The `section' form:
(module module+-example-1 racket/base
(module+ alpha (define a root) (provide a))
(module+ beta (define b (+ root 1)) (provide b))
(module+ alpha (define aa (+ a a)) (provide aa))
(module+ gamma
(require (submod "." ".." beta))
(provide c)
(define c (+ b 1)))
(module+ beta)
(module+ beta)
(module+ beta)
(define root 1))
(test 1 dynamic-require '(submod 'module+-example-1 alpha) 'a)
(test 2 dynamic-require '(submod 'module+-example-1 alpha) 'aa)
(test 2 dynamic-require '(submod 'module+-example-1 beta) 'b)
(test 3 dynamic-require '(submod 'module+-example-1 gamma) 'c)
(syntax-test #'(module+ a))
(err/rt-test (eval #'(module m racket/base module+)) exn:fail:syntax?)
(err/rt-test (eval #'(module m racket/base (module+))) exn:fail:syntax?)
(err/rt-test (eval #'(module m racket/base (module+ 1))) exn:fail:syntax?)
(err/rt-test (eval #'(module m racket/base (module+ a . 2))) exn:fail:syntax?)
;; Check that `#%module-begin' context is reasonable:
(module module+-example-2 racket/base
(module alt-mod-beg racket/base
(provide (rename-out [module-begin #%module-begin])
module+
#%datum
#%app
void)
(define-syntax-rule (module-begin a b c)
(#%module-begin a (define x (+ b c)) (provide x))))
(module a (submod "." ".." alt-mod-beg)
(module+ b (void) 1 2)
3 4))
(test 3 dynamic-require '(submod 'module+-example-2 a b) 'x)
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(report-errs) (report-errs)