135 lines
6.4 KiB
Racket
135 lines
6.4 KiB
Racket
#lang scribble/doc
|
|
@(require "mz.ss")
|
|
|
|
@title[#:tag "stxcerts"]{Syntax Certificates}
|
|
|
|
A @deftech{syntax certificate} combines a @tech{syntax mark} (see
|
|
@secref["transformer-model"]), a @tech{module path index} or symbol
|
|
module name (see @secref["modpathidx"]), an @tech{inspector} (see
|
|
@secref["modprotect"]), and an arbitrary key object. A certificate
|
|
is attached as either an @deftech{active certificate} or an
|
|
@deftech{inactive certificate}.
|
|
|
|
The @scheme[datum->syntax] procedure never transfers an @tech{active
|
|
certificate} from one syntax object to another. The
|
|
@scheme[syntax-recertify] procedure can be used to transfer a
|
|
certificate from one syntax object to another, but only if the
|
|
certificate's key is provided, or if a sufficiently powerful inspector
|
|
is provided. Thus, a certificate's inspector serves two roles: it
|
|
determines the certificate's power to grant access, and also allows
|
|
the certificate to be moved arbitrarily by anyone with a more powerful
|
|
inspector.
|
|
|
|
The expander generates a certificate when it applies a syntax
|
|
transformer. The @tech{syntax mark} in the certificate is fresh, the
|
|
certificate's module reference corresponds to the module that defined
|
|
the @tech{transformer binding}, the inspector is the inspector for the
|
|
module's declaration (see @secref["modprotect"]), and the key
|
|
object is hidden. (Applying the result of
|
|
@scheme[syntax-local-certifier] can introduce certificates with other
|
|
keys.) The certificate's mark is applied to both the input and output
|
|
of the syntax transformer, so that it identifies every piece of syntax
|
|
that was introduced by the transformer (see
|
|
@secref["transformer-model"]). The expander attaches this
|
|
certificate to parts of the transformer's result, depending on the
|
|
shape and properties of the result:
|
|
|
|
@itemize{
|
|
|
|
@item{If the result has a @indexed-scheme['certify-mode] property
|
|
(see @secref["stxprops"]) that is
|
|
@indexed-scheme['opaque], then the certificate is attached
|
|
to the immediate syntax object.}
|
|
|
|
@item{If the result has a @scheme['certify-mode] property that is
|
|
@indexed-scheme['transparent], then the certificate is also
|
|
propagated recursively to syntax object that corresponds to
|
|
elements of the syntax object's datum as a list (or, more
|
|
precisely, to the @scheme[car]s of the datum as reached by
|
|
any number of @scheme[cdr]s). This recursive propagation
|
|
uses syntax properties and shapes, as for the immediate
|
|
attachment.}
|
|
|
|
@item{If the result has a @scheme['certify-mode] property that is
|
|
@indexed-scheme['transparent-binding], then the certificate
|
|
is attached to similar to @scheme['transparent], but further
|
|
treating the syntax object corresponding to the second list
|
|
element as having a @scheme['transparent] value for the
|
|
@scheme['certify-mode] property if it does not already have
|
|
a @scheme['certify-mode] property value.}
|
|
|
|
@item{If the result has no @scheme['certify-mode] property value,
|
|
but its datum is a pair, and if the syntax object
|
|
corresponding to the @scheme[car] of the pair is an
|
|
identifier bound to @scheme[begin], then the certificate is
|
|
propagated as if the syntax object had the
|
|
@scheme['transparent] property value.}
|
|
|
|
@item{If the result has no @scheme['certify-mode] property value,
|
|
but its datum is a pair, and if the syntax object
|
|
corresponding to the @scheme[car] of the pair is an
|
|
identifier bound to @scheme[define-values] or
|
|
@scheme[define-syntaxes], then the certificate is propagated
|
|
as if the syntax object had the @scheme['transparent-binding]
|
|
property value.}
|
|
|
|
}
|
|
|
|
The the expander attaches a new active certificate to a syntax object,
|
|
it also removes any @tech{inactive certificates} attached to any
|
|
@tech{syntax object} within the one where the certificate is attached,
|
|
and it re-attaches the formerly @tech{inactive certificates} as
|
|
@tech{active certificates} along with the new one.
|
|
|
|
As the expander processes a form, it accumulates @tech{active
|
|
certificates} that are attached to enclosing forms as part of the
|
|
expansion context:
|
|
|
|
@itemize{
|
|
|
|
@item{To check access to an unexported identifier, the expander
|
|
checks each of the identifier's marks and module bindings; if, for
|
|
some mark, the identifier's enclosing expressions include a
|
|
certificate with the mark, the identifier's binding module, and
|
|
with an inspector that controls the module's invocation (as opposed
|
|
to the module's declaration; see again @secref["modprotect"]),
|
|
then the access is allowed. To check access to a protected
|
|
identifier, only the certificate's mark and inspector are used
|
|
(i.e., the module that bound the transformer is irrelevant, as long
|
|
as it was evaluated with a sufficiently powerful inspector). The
|
|
certificate key is not used in checking references.}
|
|
|
|
@item{To check access to a locally bound identifier, the expander
|
|
checks the marks of the binding and reference identifiers; for
|
|
every mark that they have in common, if the reference identifier
|
|
has a certificate for the mark from an enclosing expression, the
|
|
binding identifier must have a certificate for the mark from an
|
|
enclosing expression, otherwise the reference is disallowed. (The
|
|
reference identifier can have additional certificates for marks
|
|
that are not attached to the binding identifier.) The binding
|
|
module (if any) and the certificate key are not used for checking a
|
|
local reference.}
|
|
|
|
@item{When the expander encounters a @scheme[quote-syntax] form, it
|
|
attaches all accumulated @tech{active certificates} from the
|
|
expressions's context to the quoted syntax objects. The
|
|
certificates are attached as @tech{inactive certificates}.}
|
|
|
|
}
|
|
|
|
|
|
@defproc[(syntax-recertify [new-stx syntax?]
|
|
[old-stx syntax?]
|
|
[inspector inspector?]
|
|
[key any/c])
|
|
syntax?]{
|
|
|
|
Copies certain certificates of @scheme[old-stx] to @scheme[new-stx]: a
|
|
certificate is copied if its inspector is either @scheme[inspector] or
|
|
controlled by @scheme[inspector], or if the certificate's key is
|
|
@scheme[key]; otherwise the certificate is not copied. The result is
|
|
a syntax object like @scheme[new-stx], but with the copied
|
|
certificates. (The @scheme[new-stx] object itself is not modified.)
|
|
Both @tech{active certificates} and @tech{inactive certificates} are
|
|
copied.}
|