try "phase-collapsing" instead of "phaseless"
This commit is contained in:
parent
2e652fc2b3
commit
2646ff6895
|
@ -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 'phaseless flags) #t #f) l)]
|
||||
[l (cons (if (memq 'phase-collapsing flags) #t #f) l)]
|
||||
[l (cons self-modidx l)]
|
||||
[l (cons srcname l)]
|
||||
[l (cons (if (pair? name) (car name) name) l)]
|
||||
|
|
|
@ -251,7 +251,7 @@
|
|||
(define (read-module v)
|
||||
(match v
|
||||
[`(,submod-path
|
||||
,name ,srcname ,self-modidx ,phaseless?
|
||||
,name ,srcname ,self-modidx ,phase-collapsing?
|
||||
,pre-submods ,post-submods
|
||||
,lang-info ,functional? ,et-functional?
|
||||
,rename ,max-let-depth ,dummy
|
||||
|
@ -337,7 +337,7 @@
|
|||
dummy
|
||||
lang-info
|
||||
rename
|
||||
(if phaseless? '(phaseless) '())
|
||||
(if phase-collapsing? '(phase-collapsing) '())
|
||||
(map read-module pre-submods)
|
||||
(map read-module post-submods))]))]))
|
||||
(define (read-module-wrap v)
|
||||
|
|
|
@ -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 'phaseless))]
|
||||
[flags (listof (or/c 'phase-collapsing))]
|
||||
[pre-submodules (listof mod?)]
|
||||
[post-submodules (listof mod?)]))
|
||||
|
||||
|
|
|
@ -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 'phaseless))]
|
||||
[flags (listof (or/c 'phase-collapsing))]
|
||||
[pre-submodules (listof mod?)]
|
||||
[post-submodules (listof mod?)])]{
|
||||
Represents a @racket[module] declaration.
|
||||
|
@ -248,8 +248,8 @@ binding, constructor, etc.}
|
|||
syntax-object value embeds an arbitrary lexical context.
|
||||
|
||||
The @racket[flags] field records certain properties of the module.
|
||||
The @racket['phaseless] flag indicates that the module body is
|
||||
evaluated once and the results shared across all phases; such a
|
||||
The @racket['phase-collapsing] 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.
|
||||
|
||||
|
|
|
@ -599,33 +599,33 @@ top-level variables in higher @tech{phases}, while module
|
|||
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
|
||||
@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
|
||||
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
|
||||
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{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,
|
||||
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
|
||||
@racket[#%variable-reference]). See @secref["phaseless-grammar"] for
|
||||
the syntactic specification of a @tech{phaseless} module
|
||||
@racket[#%variable-reference]). See @secref["phase-collapsing-grammar"] for
|
||||
the syntactic specification of a @tech{phase-collapsing} module
|
||||
declaration.
|
||||
|
||||
A documented module should be assumed non-@tech{phaseless} unless it
|
||||
is specified as @tech{phaseless} (such as
|
||||
A documented module should be assumed non-@tech{phase-collapsing} unless it
|
||||
is specified as @tech{phase-collapsing} (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{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
|
||||
previously instantiated may fail if instantiation for the
|
||||
redeclaration attempts to modify variables that are constant (see
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
@title{Kernel Forms and Functions}
|
||||
|
||||
@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.}
|
||||
|
||||
``Minimal'' means that @racketmodname[racket/kernel] includes only
|
||||
|
|
|
@ -989,9 +989,9 @@ information. Inferred and property-assigned names are also available
|
|||
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
|
||||
it includes no uses of @racket[quote-syntax] or @racket[#%variable-reference],
|
||||
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
|
||||
#%plain-app
|
||||
cons list make-struct-type make-struct-type-property)
|
||||
[phaseless-module (module id module-path
|
||||
(#%plain-module-begin
|
||||
phaseless-form ...))]
|
||||
[phaseless-form (begin phaseless-form ...)
|
||||
[phase-collapse-module (module id module-path
|
||||
(#%plain-module-begin
|
||||
phase-collapse-form ...))]
|
||||
[phase-collapse-form (begin phase-collapse-form ...)
|
||||
(#%provide raw-provide-spec ...)
|
||||
submodule-form
|
||||
(define-values (id ...) phaseless-expr)
|
||||
(define-values (id ...)
|
||||
phase-collapse-expr)
|
||||
(#%require raw-require-spec ...)]
|
||||
[phaseless-expr id
|
||||
(@#,racket[quote] phaseless-datum)
|
||||
[phase-collapse-expr id
|
||||
(@#,racket[quote] phase-collapse-datum)
|
||||
(#%plain-lambda formals expr ...+)
|
||||
(case-lambda (formals 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-property
|
||||
expr ...+)]
|
||||
[phaseless-datum number
|
||||
[phase-collapse-datum number
|
||||
boolean
|
||||
identifier
|
||||
string
|
||||
bytes]
|
||||
]
|
||||
|
||||
This grammar applies after @tech{expansion}, but because a @tech{phaseless}
|
||||
module imports only from other phaseless modules, the only relevant
|
||||
This grammar applies after @tech{expansion}, but because a @tech{phase-collapsing}
|
||||
module imports only from other phase-collapsing 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].
|
||||
|
|
96
collects/tests/racket/phase-collapse.rkt
Normal file
96
collects/tests/racket/phase-collapse.rkt
Normal 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.")
|
||||
|
|
@ -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.")
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
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
|
||||
|
||||
Version 5.3.3.4
|
||||
|
|
|
@ -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 phaseless module",
|
||||
"cannot redeclare phase-collapsing module",
|
||||
"module name", 1, m->modname,
|
||||
NULL);
|
||||
return NULL;
|
||||
|
|
|
@ -5216,7 +5216,7 @@ module_optimize(Scheme_Object *data, Optimize_Info *info, int context)
|
|||
scheme_log(info->logger,
|
||||
SCHEME_LOG_DEBUG,
|
||||
0,
|
||||
"compilation of phaseless module: %D",
|
||||
"compilation of phase-collapsing module: %D",
|
||||
m->modname);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user