terminology change again: "cross-phases persistent" modules

This commit is contained in:
Matthew Flatt 2013-02-27 08:20:32 -07:00
parent c1469b9480
commit 88a36a077c
11 changed files with 129 additions and 131 deletions

View File

@ -1091,7 +1091,7 @@
[l (cons lang-info l)] ; lang-info [l (cons lang-info l)] ; lang-info
[l (cons (map convert-module post-submodules) l)] [l (cons (map convert-module post-submodules) l)]
[l (cons (map convert-module pre-submodules) l)] [l (cons (map convert-module pre-submodules) l)]
[l (cons (if (memq 'phase-collapsing flags) #t #f) l)] [l (cons (if (memq 'cross-phase flags) #t #f) l)]
[l (cons self-modidx l)] [l (cons self-modidx l)]
[l (cons srcname l)] [l (cons srcname l)]
[l (cons (if (pair? name) (car name) name) l)] [l (cons (if (pair? name) (car name) name) l)]

View File

@ -251,7 +251,7 @@
(define (read-module v) (define (read-module v)
(match v (match v
[`(,submod-path [`(,submod-path
,name ,srcname ,self-modidx ,phase-collapsing? ,name ,srcname ,self-modidx ,cross-phase?
,pre-submods ,post-submods ,pre-submods ,post-submods
,lang-info ,functional? ,et-functional? ,lang-info ,functional? ,et-functional?
,rename ,max-let-depth ,dummy ,rename ,max-let-depth ,dummy
@ -337,7 +337,7 @@
dummy dummy
lang-info lang-info
rename rename
(if phase-collapsing? '(phase-collapsing) '()) (if cross-phase? '(cross-phase) '())
(map read-module pre-submods) (map read-module pre-submods)
(map read-module post-submods))]))])) (map read-module post-submods))]))]))
(define (read-module-wrap v) (define (read-module-wrap v)

View File

@ -139,7 +139,7 @@
[dummy toplevel?] [dummy toplevel?]
[lang-info (or/c #f (vector/c module-path? symbol? any/c))] [lang-info (or/c #f (vector/c module-path? symbol? any/c))]
[internal-context (or/c #f #t stx? (vectorof stx?))] [internal-context (or/c #f #t stx? (vectorof stx?))]
[flags (listof (or/c 'phase-collapsing))] [flags (listof (or/c 'cross-phase))]
[pre-submodules (listof mod?)] [pre-submodules (listof mod?)]
[post-submodules (listof mod?)])) [post-submodules (listof mod?)]))

View File

@ -205,7 +205,7 @@ binding, constructor, etc.}
[dummy toplevel?] [dummy toplevel?]
[lang-info (or/c #f (vector/c module-path? symbol? any/c))] [lang-info (or/c #f (vector/c module-path? symbol? any/c))]
[internal-context (or/c #f #t stx? (vectorof stx?))] [internal-context (or/c #f #t stx? (vectorof stx?))]
[flags (listof (or/c 'phase-collapsing))] [flags (listof (or/c 'cross-phase))]
[pre-submodules (listof mod?)] [pre-submodules (listof mod?)]
[post-submodules (listof mod?)])]{ [post-submodules (listof mod?)])]{
Represents a @racket[module] declaration. Represents a @racket[module] declaration.
@ -248,7 +248,7 @@ binding, constructor, etc.}
syntax-object value embeds an arbitrary lexical context. syntax-object value embeds an arbitrary lexical context.
The @racket[flags] field records certain properties of the module. The @racket[flags] field records certain properties of the module.
The @racket['phase-collapsing] flag indicates that the module body is The @racket['cross-phase] flag indicates that the module body is
evaluated once and the results shared across instances for all phases; such a evaluated once and the results shared across instances for all phases; such a
module contains only definitions of functions, structure types, and module contains only definitions of functions, structure types, and
structure type properties. structure type properties.

View File

@ -599,33 +599,33 @@ top-level variables in higher @tech{phases}, while module
top-levels are in corresponding higher @tech{phase}s. top-levels are in corresponding higher @tech{phase}s.
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@subsection[#:tag "phase-collapsing-modules"]{Phase-Collapsing Modules} @subsection[#:tag "cross-phase persistent-modules"]{Cross-Phase Persistent Modules}
Module declarations that fit a highly constrained form create Module declarations that fit a highly constrained form create
@deftech{phase-collapsing} modules. A @tech{phase-collapsing} module's @deftech{cross-phase persistent} modules. A @tech{cross-phase persistent} module's
instantiations across all phases and @tech{module registries} share instantiations across all phases and @tech{module registries} share
the variables produced by the first instantiation of the module. the variables produced by the first instantiation of the module.
The intent of a @tech{phase-collapsing} module is to support values that are The intent of a @tech{cross-phase persistent} module is to support values that are
recognizable after @tech{phase} crossings. For example, when a macro recognizable after @tech{phase} crossings. For example, when a macro
transformer running in phase 1 raises a syntax error as represented by transformer running in phase 1 raises a syntax error as represented by
a @racket[exn:fail:syntax] instance, the instance is recognizable by a a @racket[exn:fail:syntax] instance, the instance is recognizable by a
phase-0 exception handler wrapping a call to @racket[eval] or phase-0 exception handler wrapping a call to @racket[eval] or
@racket[expand] that triggered the syntax error, because the @racket[expand] that triggered the syntax error, because the
@racket[exn:fail:syntax] structure type is defined by a @racket[exn:fail:syntax] structure type is defined by a
@tech{phase-collapsing} module. @tech{cross-phase persistent} module.
A @tech{phase-collapsing} module imports only other @tech{phase-collapsing} modules, A @tech{cross-phase persistent} module imports only other @tech{cross-phase persistent} modules,
and it contains only definitions that bind variables to functions, and it contains only definitions that bind variables to functions,
structure types and related functions, or structure-type properties structure types and related functions, or structure-type properties
and related functions. A @tech{phase-collapsing} module never includes syntax and related functions. A @tech{cross-phase persistent} module never includes syntax
literals (via @racket[quote-syntax]) or variable references (via literals (via @racket[quote-syntax]) or variable references (via
@racket[#%variable-reference]). See @secref["phase-collapsing-grammar"] for @racket[#%variable-reference]). See @secref["cross-phase persistent-grammar"] for
the syntactic specification of a @tech{phase-collapsing} module the syntactic specification of a @tech{cross-phase persistent} module
declaration. declaration.
A documented module should be assumed non-@tech{phase-collapsing} unless it A documented module should be assumed non-@tech{cross-phase persistent} unless it
is specified as @tech{phase-collapsing} (such as is specified as @tech{cross-phase persistent} (such as
@racketmodname[racket/kernel]). @racketmodname[racket/kernel]).
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -647,7 +647,7 @@ redeclared, each redeclaration of the module is immediately
If the current @tech{inspector} does not manage a module's declaration If the current @tech{inspector} does not manage a module's declaration
inspector (see @secref["modprotect"]), then the module cannot be inspector (see @secref["modprotect"]), then the module cannot be
redeclared. Similarly, a @tech{phase-collapsing} module cannot be redeclared. redeclared. Similarly, a @tech{cross-phase persistent} module cannot be redeclared.
Even if redeclrection succeeds, instantiation of a module that is Even if redeclrection succeeds, instantiation of a module that is
previously instantiated may fail if instantiation for the previously instantiated may fail if instantiation for the
redeclaration attempts to modify variables that are constant (see redeclaration attempts to modify variables that are constant (see

View File

@ -10,7 +10,7 @@
@title{Kernel Forms and Functions} @title{Kernel Forms and Functions}
@defmodulelang[racket/kernel]{The @racketmodname[racket/kernel] library @defmodulelang[racket/kernel]{The @racketmodname[racket/kernel] library
is a @tech{phase-collapsing} module that provides a minimal set of syntactic is a @tech{cross-phase persistent} module that provides a minimal set of syntactic
forms and functions.} forms and functions.}
``Minimal'' means that @racketmodname[racket/kernel] includes only ``Minimal'' means that @racketmodname[racket/kernel] includes only

View File

@ -989,9 +989,9 @@ information. Inferred and property-assigned names are also available
to syntax transformers, via @racket[syntax-local-name]. to syntax transformers, via @racket[syntax-local-name].
@;---------------------------------------- @;----------------------------------------
@section[#:tag "phase-collapsing-grammar"]{Phase-Collapsing Module Declarations} @section[#:tag "cross-phase persistent-grammar"]{Cross-Phase Persistent Module Declarations}
A module is @tech{phase-collapsing} only if it fits the following grammar, A module is @tech{cross-phase persistent} only if it fits the following grammar,
which uses non-terminals from @secref["fully-expanded"], only if which uses non-terminals from @secref["fully-expanded"], only if
it includes no uses of @racket[quote-syntax] or @racket[#%variable-reference], it includes no uses of @racket[quote-syntax] or @racket[#%variable-reference],
and only if no module-level binding is @racket[set!]ed. and only if no module-level binding is @racket[set!]ed.
@ -1003,33 +1003,31 @@ and only if no module-level binding is @racket[set!]ed.
set! quote-syntax quote with-continuation-mark set! quote-syntax quote with-continuation-mark
#%plain-app #%plain-app
cons list make-struct-type make-struct-type-property) cons list make-struct-type make-struct-type-property)
[phase-collapse-module (module id module-path [cross-module (module id module-path
(#%plain-module-begin (#%plain-module-begin
phase-collapse-form ...))] cross-form ...))]
[phase-collapse-form (begin phase-collapse-form ...) [cross-form (begin cross-form ...)
(#%provide raw-provide-spec ...) (#%provide raw-provide-spec ...)
submodule-form submodule-form
(define-values (id ...) (define-values (id ...) cross-expr)
phase-collapse-expr)
(#%require raw-require-spec ...)] (#%require raw-require-spec ...)]
[phase-collapse-expr id [cross-expr id
(@#,racket[quote] phase-collapse-datum) (@#,racket[quote] cross-datum)
(#%plain-lambda formals expr ...+) (#%plain-lambda formals expr ...+)
(case-lambda (formals expr ...+) ...) (case-lambda (formals expr ...+) ...)
(#%plain-app cons expr ...+) (#%plain-app cons expr ...+)
(#%plain-app list expr ...+) (#%plain-app list expr ...+)
(#%plain-app make-struct-type expr ...+) (#%plain-app make-struct-type expr ...+)
(#%plain-app make-struct-type-property (#%plain-app make-struct-type-property expr ...+)]
expr ...+)] [cross-datum number
[phase-collapse-datum number
boolean boolean
identifier identifier
string string
bytes] bytes]
] ]
This grammar applies after @tech{expansion}, but because a @tech{phase-collapsing} This grammar applies after @tech{expansion}, but because a @tech{cross-phase persistent}
module imports only from other phase-collapsing modules, the only relevant module imports only from other cross-phase persistent modules, the only relevant
expansion steps are the implicit introduction of expansion steps are the implicit introduction of
@racket[#%plain-module-begin], implicit introduction of @racket[#%plain-app], @racket[#%plain-module-begin], implicit introduction of @racket[#%plain-app],
and implicit introduction and/or expansion of @racket[#%datum]. and implicit introduction and/or expansion of @racket[#%datum].

View File

@ -0,0 +1,96 @@
#lang racket/base
(require compiler/zo-parse)
(define (check-cross-phase is? form)
(parameterize ([current-namespace (make-base-namespace)])
(define o (open-output-bytes))
(write (compile `(module m racket/kernel ,form)) o)
(close-output-port o)
(define i (open-input-bytes (get-output-bytes o)))
(define e (zo-parse i))
(unless (equal? is? (and (memq 'cross-phase (mod-flags (compilation-top-code e))) #t))
(error 'cross-phase "failed: ~s ~s" is? form))))
(check-cross-phase #t '(define-values (x) 5))
(check-cross-phase #t '(define-values (x) '5))
(check-cross-phase #t '(define-values (x) (#%datum . 5)))
(check-cross-phase #t '(define-values (x) #t))
(check-cross-phase #t '(define-values (x) 'x))
(check-cross-phase #t '(define-values (x) "x"))
(check-cross-phase #t '(define-values (x) #"x"))
(check-cross-phase #t '(define-values (x) cons))
(check-cross-phase #t '(define-values (x) (cons 1 2)))
(check-cross-phase #t '(define-values (x) (list 1 2)))
(check-cross-phase #t '(define-values (x) (cons 1 '())))
(check-cross-phase #t '(#%require racket/tcp))
(check-cross-phase #t '(define-values (x) (lambda (x) x)))
(check-cross-phase #t '(define-values (x) (case-lambda [(x) x] [y y])))
(check-cross-phase #t '(define-values (struct: ? -ref) (make-struct-type-property 'p)))
(check-cross-phase #t '(define-values (struct: make- ? -ref -set!) (make-struct-type 's #f 0 0)))
(check-cross-phase #t '(define-values (struct: make- ? -ref -set!) (make-struct-type 's struct:exn 0 0)))
(check-cross-phase #t '(define-values (struct: make- ? -ref -set!) (make-struct-type 's struct:exn 1 0 #f (list (cons prop:procedure 0)))))
(check-cross-phase #t '(begin
(define-values (x) 5)
(define-values (y) 6)))
(check-cross-phase #f '(define-values (x) #(x)))
(check-cross-phase #f '(define-values (x) '(x)))
(check-cross-phase #f '(define-values (x) (lambda () (set! x 8))))
(check-cross-phase #f '(define-values (x) (quote-syntax x)))
(check-cross-phase #f '(define-values (x) (lambda () (quote-syntax x))))
(check-cross-phase #f '(define-values (x) (#%variable-reference)))
(check-cross-phase #f '(define-values (x) (lambda () (#%variable-reference))))
(check-cross-phase #f '(define-values (x) (lambda () (if #f (#%variable-reference) 10))))
(check-cross-phase #f '(define-values (x) (#%variable-reference x)))
(check-cross-phase #f '(#%require racket/base))
(check-cross-phase #t '(module* sub #f (vector 1 2 3)))
(check-cross-phase #t '(module* sub #f (#%variable-reference)))
(check-cross-phase #t '(module* sub racket/base (#%variable-reference)))
(check-cross-phase #t '(module sub racket/base (#%variable-reference)))
;; Check phase crossing via an exception:
(parameterize ([current-namespace (make-base-namespace)])
(eval `(module m racket/kernel
(#%provide s? make-s)
(define-values (struct:s make-s s? s-ref s-set!) (make-struct-type 's #f 0 0))))
(eval '(require 'm))
(define s? (eval 's?))
(eval '(require (for-syntax racket/base 'm)))
(eval '(define-syntax (m stx) (raise (make-s))))
(with-handlers ([s? void])
(eval '(m)))
(define (check-exn)
(with-handlers ([s? void])
(eval '(module n racket/base
(require (for-syntax racket/base 'm))
(begin-for-syntax
(raise (make-s)))))))
(check-exn)
(define (check-attach namespace-attach-module)
(define ns (make-base-namespace))
(namespace-attach-module (current-namespace) ''m ns)
(parameterize ([current-namespace ns])
(check-exn)))
(check-attach namespace-attach-module)
(check-attach namespace-attach-module-declaration))
;; Check disallowing redeclaration:
(parameterize ([current-namespace (make-base-namespace)])
(parameterize ([compile-enforce-module-constants #f])
(eval `(module m racket/kernel
(#%provide x)
(define-values (x) 5)))
(compile `(module m racket/kernel
(#%provide x)
(define-values (x) 6)))
(unless (void?
(with-handlers ([exn:fail? void])
(eval `(module m racket/kernel
(#%provide x)
(define-values (x) 6)))
'ok))
(error 'cross-phase "redeclaration should have been disallowed"))))
(displayln "All tests passed.")

View File

@ -1,96 +0,0 @@
#lang racket/base
(require compiler/zo-parse)
(define (check-phase-collapsing is? form)
(parameterize ([current-namespace (make-base-namespace)])
(define o (open-output-bytes))
(write (compile `(module m racket/kernel ,form)) o)
(close-output-port o)
(define i (open-input-bytes (get-output-bytes o)))
(define e (zo-parse i))
(unless (equal? is? (and (memq 'phase-collapsing (mod-flags (compilation-top-code e))) #t))
(error 'phase-collapsing "failed: ~s ~s" is? form))))
(check-phase-collapsing #t '(define-values (x) 5))
(check-phase-collapsing #t '(define-values (x) '5))
(check-phase-collapsing #t '(define-values (x) (#%datum . 5)))
(check-phase-collapsing #t '(define-values (x) #t))
(check-phase-collapsing #t '(define-values (x) 'x))
(check-phase-collapsing #t '(define-values (x) "x"))
(check-phase-collapsing #t '(define-values (x) #"x"))
(check-phase-collapsing #t '(define-values (x) cons))
(check-phase-collapsing #t '(define-values (x) (cons 1 2)))
(check-phase-collapsing #t '(define-values (x) (list 1 2)))
(check-phase-collapsing #t '(define-values (x) (cons 1 '())))
(check-phase-collapsing #t '(#%require racket/tcp))
(check-phase-collapsing #t '(define-values (x) (lambda (x) x)))
(check-phase-collapsing #t '(define-values (x) (case-lambda [(x) x] [y y])))
(check-phase-collapsing #t '(define-values (struct: ? -ref) (make-struct-type-property 'p)))
(check-phase-collapsing #t '(define-values (struct: make- ? -ref -set!) (make-struct-type 's #f 0 0)))
(check-phase-collapsing #t '(define-values (struct: make- ? -ref -set!) (make-struct-type 's struct:exn 0 0)))
(check-phase-collapsing #t '(define-values (struct: make- ? -ref -set!) (make-struct-type 's struct:exn 1 0 #f (list (cons prop:procedure 0)))))
(check-phase-collapsing #t '(begin
(define-values (x) 5)
(define-values (y) 6)))
(check-phase-collapsing #f '(define-values (x) #(x)))
(check-phase-collapsing #f '(define-values (x) '(x)))
(check-phase-collapsing #f '(define-values (x) (lambda () (set! x 8))))
(check-phase-collapsing #f '(define-values (x) (quote-syntax x)))
(check-phase-collapsing #f '(define-values (x) (lambda () (quote-syntax x))))
(check-phase-collapsing #f '(define-values (x) (#%variable-reference)))
(check-phase-collapsing #f '(define-values (x) (lambda () (#%variable-reference))))
(check-phase-collapsing #f '(define-values (x) (lambda () (if #f (#%variable-reference) 10))))
(check-phase-collapsing #f '(define-values (x) (#%variable-reference x)))
(check-phase-collapsing #f '(#%require racket/base))
(check-phase-collapsing #t '(module* sub #f (vector 1 2 3)))
(check-phase-collapsing #t '(module* sub #f (#%variable-reference)))
(check-phase-collapsing #t '(module* sub racket/base (#%variable-reference)))
(check-phase-collapsing #t '(module sub racket/base (#%variable-reference)))
;; Check phase crossing via an exception:
(parameterize ([current-namespace (make-base-namespace)])
(eval `(module m racket/kernel
(#%provide s? make-s)
(define-values (struct:s make-s s? s-ref s-set!) (make-struct-type 's #f 0 0))))
(eval '(require 'm))
(define s? (eval 's?))
(eval '(require (for-syntax racket/base 'm)))
(eval '(define-syntax (m stx) (raise (make-s))))
(with-handlers ([s? void])
(eval '(m)))
(define (check-exn)
(with-handlers ([s? void])
(eval '(module n racket/base
(require (for-syntax racket/base 'm))
(begin-for-syntax
(raise (make-s)))))))
(check-exn)
(define (check-attach namespace-attach-module)
(define ns (make-base-namespace))
(namespace-attach-module (current-namespace) ''m ns)
(parameterize ([current-namespace ns])
(check-exn)))
(check-attach namespace-attach-module)
(check-attach namespace-attach-module-declaration))
;; Check disallowing redeclaration:
(parameterize ([current-namespace (make-base-namespace)])
(parameterize ([compile-enforce-module-constants #f])
(eval `(module m racket/kernel
(#%provide x)
(define-values (x) 5)))
(compile `(module m racket/kernel
(#%provide x)
(define-values (x) 6)))
(unless (void?
(with-handlers ([exn:fail? void])
(eval `(module m racket/kernel
(#%provide x)
(define-values (x) 6)))
'ok))
(error 'phase-collapsing "redeclaration should have been disallowed"))))
(displayln "All tests passed.")

View File

@ -6380,7 +6380,7 @@ static Scheme_Object *do_module_execute(Scheme_Object *data, Scheme_Env *genv,
if (old_m && old_m->phaseless) { if (old_m && old_m->phaseless) {
scheme_contract_error("module->namespace", scheme_contract_error("module->namespace",
"cannot redeclare phase-collapsing module", "cannot redeclare cross-phase persistent module",
"module name", 1, m->modname, "module name", 1, m->modname,
NULL); NULL);
return NULL; return NULL;

View File

@ -5216,7 +5216,7 @@ module_optimize(Scheme_Object *data, Optimize_Info *info, int context)
scheme_log(info->logger, scheme_log(info->logger,
SCHEME_LOG_DEBUG, SCHEME_LOG_DEBUG,
0, 0,
"compilation of phase-collapsing module: %D", "compilation of cross-phase persistent module: %D",
m->modname); m->modname);
} }