try "phase-collapsing" instead of "phaseless"

This commit is contained in:
Matthew Flatt 2013-02-26 18:36:06 -07:00
parent 2e652fc2b3
commit 2646ff6895
12 changed files with 131 additions and 130 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 'phaseless flags) #t #f) l)] [l (cons (if (memq 'phase-collapsing 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 ,phaseless? ,name ,srcname ,self-modidx ,phase-collapsing?
,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 phaseless? '(phaseless) '()) (if phase-collapsing? '(phase-collapsing) '())
(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 'phaseless))] [flags (listof (or/c 'phase-collapsing))]
[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 'phaseless))] [flags (listof (or/c 'phase-collapsing))]
[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,8 +248,8 @@ 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['phaseless] flag indicates that the module body is The @racket['phase-collapsing] flag indicates that the module body is
evaluated once and the results shared across 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 "phaseless-modules"]{Phaseless Modules} @subsection[#:tag "phase-collapsing-modules"]{Phase-Collapsing Modules}
Module declarations that fit a highly constrained form create Module declarations that fit a highly constrained form create
@deftech{phaseless} modules. A @tech{phaseless} module's @deftech{phase-collapsing} modules. A @tech{phase-collapsing} 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{phaseless} module is to support values that are The intent of a @tech{phase-collapsing} 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{phaseless} module. @tech{phase-collapsing} module.
A @tech{phaseless} module imports only other @tech{phaseless} modules, A @tech{phase-collapsing} module imports only other @tech{phase-collapsing} 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{phaseless} module never includes syntax and related functions. A @tech{phase-collapsing} 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["phaseless-grammar"] for @racket[#%variable-reference]). See @secref["phase-collapsing-grammar"] for
the syntactic specification of a @tech{phaseless} module the syntactic specification of a @tech{phase-collapsing} module
declaration. declaration.
A documented module should be assumed non-@tech{phaseless} unless it A documented module should be assumed non-@tech{phase-collapsing} unless it
is specified as @tech{phaseless} (such as is specified as @tech{phase-collapsing} (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{phaseless} module cannot be redeclared. redeclared. Similarly, a @tech{phase-collapsing} 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}
@defmodule*[(racket/kernel)]{The @racketmodname[racket/kernel] library @defmodule*[(racket/kernel)]{The @racketmodname[racket/kernel] library
is a @tech{phaseless} module that provides a minimal set of syntactic is a @tech{phase-collapsing} 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 "phaseless-grammar"]{Phaseless Module Declarations} @section[#:tag "phase-collapsing-grammar"]{Phase-Collapsing Module Declarations}
A module is @tech{phaseless} only if it fits the following grammar, A module is @tech{phase-collapsing} 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,16 +1003,17 @@ 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)
[phaseless-module (module id module-path [phase-collapse-module (module id module-path
(#%plain-module-begin (#%plain-module-begin
phaseless-form ...))] phase-collapse-form ...))]
[phaseless-form (begin phaseless-form ...) [phase-collapse-form (begin phase-collapse-form ...)
(#%provide raw-provide-spec ...) (#%provide raw-provide-spec ...)
submodule-form submodule-form
(define-values (id ...) phaseless-expr) (define-values (id ...)
phase-collapse-expr)
(#%require raw-require-spec ...)] (#%require raw-require-spec ...)]
[phaseless-expr id [phase-collapse-expr id
(@#,racket[quote] phaseless-datum) (@#,racket[quote] phase-collapse-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 ...+)
@ -1020,15 +1021,15 @@ and only if no module-level binding is @racket[set!]ed.
(#%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 ...+)]
[phaseless-datum number [phase-collapse-datum number
boolean boolean
identifier identifier
string string
bytes] bytes]
] ]
This grammar applies after @tech{expansion}, but because a @tech{phaseless} This grammar applies after @tech{expansion}, but because a @tech{phase-collapsing}
module imports only from other phaseless modules, the only relevant module imports only from other phase-collapsing 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-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/private/stx))
(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

@ -1,96 +0,0 @@
#lang racket/base
(require compiler/zo-parse)
(define (check-phaseless 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 'phaseless (mod-flags (compilation-top-code e))) #t))
(error 'phaseless "failed: ~s ~s" is? form))))
(check-phaseless #t '(define-values (x) 5))
(check-phaseless #t '(define-values (x) '5))
(check-phaseless #t '(define-values (x) (#%datum . 5)))
(check-phaseless #t '(define-values (x) #t))
(check-phaseless #t '(define-values (x) 'x))
(check-phaseless #t '(define-values (x) "x"))
(check-phaseless #t '(define-values (x) #"x"))
(check-phaseless #t '(define-values (x) cons))
(check-phaseless #t '(define-values (x) (cons 1 2)))
(check-phaseless #t '(define-values (x) (list 1 2)))
(check-phaseless #t '(define-values (x) (cons 1 '())))
(check-phaseless #t '(#%require racket/private/stx))
(check-phaseless #t '(define-values (x) (lambda (x) x)))
(check-phaseless #t '(define-values (x) (case-lambda [(x) x] [y y])))
(check-phaseless #t '(define-values (struct: ? -ref) (make-struct-type-property 'p)))
(check-phaseless #t '(define-values (struct: make- ? -ref -set!) (make-struct-type 's #f 0 0)))
(check-phaseless #t '(define-values (struct: make- ? -ref -set!) (make-struct-type 's struct:exn 0 0)))
(check-phaseless #t '(define-values (struct: make- ? -ref -set!) (make-struct-type 's struct:exn 1 0 #f (list (cons prop:procedure 0)))))
(check-phaseless #t '(begin
(define-values (x) 5)
(define-values (y) 6)))
(check-phaseless #f '(define-values (x) #(x)))
(check-phaseless #f '(define-values (x) '(x)))
(check-phaseless #f '(define-values (x) (lambda () (set! x 8))))
(check-phaseless #f '(define-values (x) (quote-syntax x)))
(check-phaseless #f '(define-values (x) (lambda () (quote-syntax x))))
(check-phaseless #f '(define-values (x) (#%variable-reference)))
(check-phaseless #f '(define-values (x) (lambda () (#%variable-reference))))
(check-phaseless #f '(define-values (x) (lambda () (if #f (#%variable-reference) 10))))
(check-phaseless #f '(define-values (x) (#%variable-reference x)))
(check-phaseless #f '(#%require racket/base))
(check-phaseless #t '(module* sub #f (vector 1 2 3)))
(check-phaseless #t '(module* sub #f (#%variable-reference)))
(check-phaseless #t '(module* sub racket/base (#%variable-reference)))
(check-phaseless #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 'phaseless "redeclaration should have been disallowed"))))
(displayln "All tests passed.")

View File

@ -1,5 +1,5 @@
Version 5.3.3.6 Version 5.3.3.6
Added "phaseless" module inference and instantiation Added "phase-collapse" module inference and instantiation
compiler/zo-structs: added flags field to mod compiler/zo-structs: added flags field to mod
Version 5.3.3.4 Version 5.3.3.4

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 phaseless module", "cannot redeclare phase-collapsing 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 phaseless module: %D", "compilation of phase-collapsing module: %D",
m->modname); m->modname);
} }