From 88a36a077c39c09eaa2ee7ae2e00647e667eaf71 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Wed, 27 Feb 2013 08:20:32 -0700 Subject: [PATCH] terminology change again: "cross-phases persistent" modules --- collects/compiler/zo-marshal.rkt | 2 +- collects/compiler/zo-parse.rkt | 4 +- collects/compiler/zo-structs.rkt | 2 +- collects/scribblings/raco/zo-struct.scrbl | 4 +- .../scribblings/reference/eval-model.scrbl | 22 ++--- collects/scribblings/reference/kernel.scrbl | 2 +- .../scribblings/reference/syntax-model.scrbl | 28 +++--- collects/tests/racket/cross-phase.rkt | 96 +++++++++++++++++++ collects/tests/racket/phase-collapse.rkt | 96 ------------------- src/racket/src/module.c | 2 +- src/racket/src/optimize.c | 2 +- 11 files changed, 129 insertions(+), 131 deletions(-) create mode 100644 collects/tests/racket/cross-phase.rkt delete mode 100644 collects/tests/racket/phase-collapse.rkt diff --git a/collects/compiler/zo-marshal.rkt b/collects/compiler/zo-marshal.rkt index 60c79b7120..8b17d1178c 100644 --- a/collects/compiler/zo-marshal.rkt +++ b/collects/compiler/zo-marshal.rkt @@ -1091,7 +1091,7 @@ [l (cons lang-info l)] ; lang-info [l (cons (map convert-module post-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 srcname l)] [l (cons (if (pair? name) (car name) name) l)] diff --git a/collects/compiler/zo-parse.rkt b/collects/compiler/zo-parse.rkt index 7af7b06604..0d21c1fd06 100644 --- a/collects/compiler/zo-parse.rkt +++ b/collects/compiler/zo-parse.rkt @@ -251,7 +251,7 @@ (define (read-module v) (match v [`(,submod-path - ,name ,srcname ,self-modidx ,phase-collapsing? + ,name ,srcname ,self-modidx ,cross-phase? ,pre-submods ,post-submods ,lang-info ,functional? ,et-functional? ,rename ,max-let-depth ,dummy @@ -337,7 +337,7 @@ dummy lang-info rename - (if phase-collapsing? '(phase-collapsing) '()) + (if cross-phase? '(cross-phase) '()) (map read-module pre-submods) (map read-module post-submods))]))])) (define (read-module-wrap v) diff --git a/collects/compiler/zo-structs.rkt b/collects/compiler/zo-structs.rkt index f8a392e10c..1221cdad02 100644 --- a/collects/compiler/zo-structs.rkt +++ b/collects/compiler/zo-structs.rkt @@ -139,7 +139,7 @@ [dummy toplevel?] [lang-info (or/c #f (vector/c module-path? symbol? any/c))] [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?)] [post-submodules (listof mod?)])) diff --git a/collects/scribblings/raco/zo-struct.scrbl b/collects/scribblings/raco/zo-struct.scrbl index 652e0ec711..0d46d31b59 100644 --- a/collects/scribblings/raco/zo-struct.scrbl +++ b/collects/scribblings/raco/zo-struct.scrbl @@ -205,7 +205,7 @@ binding, constructor, etc.} [dummy toplevel?] [lang-info (or/c #f (vector/c module-path? symbol? any/c))] [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?)] [post-submodules (listof mod?)])]{ Represents a @racket[module] declaration. @@ -248,7 +248,7 @@ binding, constructor, etc.} syntax-object value embeds an arbitrary lexical context. 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 module contains only definitions of functions, structure types, and structure type properties. diff --git a/collects/scribblings/reference/eval-model.scrbl b/collects/scribblings/reference/eval-model.scrbl index d57cc7b0a4..ef4a06ec7e 100644 --- a/collects/scribblings/reference/eval-model.scrbl +++ b/collects/scribblings/reference/eval-model.scrbl @@ -599,33 +599,33 @@ top-level variables in higher @tech{phases}, while module 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 -@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 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 transformer running in phase 1 raises a syntax error as represented by a @racket[exn:fail:syntax] instance, the instance is recognizable by a phase-0 exception handler wrapping a call to @racket[eval] or @racket[expand] that triggered the syntax error, because the @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, 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 -@racket[#%variable-reference]). See @secref["phase-collapsing-grammar"] for -the syntactic specification of a @tech{phase-collapsing} module +@racket[#%variable-reference]). See @secref["cross-phase persistent-grammar"] for +the syntactic specification of a @tech{cross-phase persistent} module declaration. -A documented module should be assumed non-@tech{phase-collapsing} unless it -is specified as @tech{phase-collapsing} (such as +A documented module should be assumed non-@tech{cross-phase persistent} unless it +is specified as @tech{cross-phase persistent} (such as @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 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 previously instantiated may fail if instantiation for the redeclaration attempts to modify variables that are constant (see diff --git a/collects/scribblings/reference/kernel.scrbl b/collects/scribblings/reference/kernel.scrbl index e1beb4fef6..4ac6a073ab 100644 --- a/collects/scribblings/reference/kernel.scrbl +++ b/collects/scribblings/reference/kernel.scrbl @@ -10,7 +10,7 @@ @title{Kernel Forms and Functions} @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.} ``Minimal'' means that @racketmodname[racket/kernel] includes only diff --git a/collects/scribblings/reference/syntax-model.scrbl b/collects/scribblings/reference/syntax-model.scrbl index 81276c26c0..2cc76999cc 100644 --- a/collects/scribblings/reference/syntax-model.scrbl +++ b/collects/scribblings/reference/syntax-model.scrbl @@ -989,9 +989,9 @@ information. Inferred and property-assigned names are also available 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 it includes no uses of @racket[quote-syntax] or @racket[#%variable-reference], 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 #%plain-app cons list make-struct-type make-struct-type-property) -[phase-collapse-module (module id module-path - (#%plain-module-begin - phase-collapse-form ...))] -[phase-collapse-form (begin phase-collapse-form ...) +[cross-module (module id module-path + (#%plain-module-begin + cross-form ...))] +[cross-form (begin cross-form ...) (#%provide raw-provide-spec ...) submodule-form - (define-values (id ...) - phase-collapse-expr) + (define-values (id ...) cross-expr) (#%require raw-require-spec ...)] -[phase-collapse-expr id - (@#,racket[quote] phase-collapse-datum) +[cross-expr id + (@#,racket[quote] cross-datum) (#%plain-lambda formals expr ...+) (case-lambda (formals expr ...+) ...) (#%plain-app cons expr ...+) (#%plain-app list expr ...+) (#%plain-app make-struct-type expr ...+) - (#%plain-app make-struct-type-property - expr ...+)] -[phase-collapse-datum number + (#%plain-app make-struct-type-property expr ...+)] +[cross-datum number boolean identifier string bytes] ] -This grammar applies after @tech{expansion}, but because a @tech{phase-collapsing} -module imports only from other phase-collapsing modules, the only relevant +This grammar applies after @tech{expansion}, but because a @tech{cross-phase persistent} +module imports only from other cross-phase persistent modules, the only relevant expansion steps are the implicit introduction of @racket[#%plain-module-begin], implicit introduction of @racket[#%plain-app], and implicit introduction and/or expansion of @racket[#%datum]. diff --git a/collects/tests/racket/cross-phase.rkt b/collects/tests/racket/cross-phase.rkt new file mode 100644 index 0000000000..50ecad0f92 --- /dev/null +++ b/collects/tests/racket/cross-phase.rkt @@ -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.") + diff --git a/collects/tests/racket/phase-collapse.rkt b/collects/tests/racket/phase-collapse.rkt deleted file mode 100644 index 4071947cfc..0000000000 --- a/collects/tests/racket/phase-collapse.rkt +++ /dev/null @@ -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.") - diff --git a/src/racket/src/module.c b/src/racket/src/module.c index 1df9e2ff19..ba44696f32 100644 --- a/src/racket/src/module.c +++ b/src/racket/src/module.c @@ -6380,7 +6380,7 @@ static Scheme_Object *do_module_execute(Scheme_Object *data, Scheme_Env *genv, if (old_m && old_m->phaseless) { scheme_contract_error("module->namespace", - "cannot redeclare phase-collapsing module", + "cannot redeclare cross-phase persistent module", "module name", 1, m->modname, NULL); return NULL; diff --git a/src/racket/src/optimize.c b/src/racket/src/optimize.c index 6ae59a8be0..1196fb975d 100644 --- a/src/racket/src/optimize.c +++ b/src/racket/src/optimize.c @@ -5216,7 +5216,7 @@ module_optimize(Scheme_Object *data, Optimize_Info *info, int context) scheme_log(info->logger, SCHEME_LOG_DEBUG, 0, - "compilation of phase-collapsing module: %D", + "compilation of cross-phase persistent module: %D", m->modname); }