diff --git a/collects/syntax/boundmap.ss b/collects/syntax/boundmap.ss index 5afb31bc03..971e09c04a 100644 --- a/collects/syntax/boundmap.ss +++ b/collects/syntax/boundmap.ss @@ -3,24 +3,29 @@ (require (lib "contract.ss") "private/boundmap.ss") + (define-syntax provide/contract* + (syntax-rules () + [(_ [(name0 name ...) contract]) + (begin (provide/contract [name0 contract]) + (provide/contract (rename name0 name contract)) ...)] + [(_ [name contract]) + (provide/contract [name contract])] + [(_ [name contract] ...) + (begin (provide/contract* [name contract]) ...)])) + (define-syntax (provide-mapping-code/contract stx) (syntax-case stx () [(_ make-identifier-mapping - identifier-mapping? + identifier-mapping? identifier-mapping?/out identifier-mapping-get identifier-mapping-put! identifier-mapping-for-each identifier-mapping-map identifier=?) - (and (identifier? (syntax identifier-mapping)) - (identifier? (syntax identifier-mapping-get)) - (identifier? (syntax identifier-mapping-put!)) - (identifier? (syntax identifier-mapping-for-each)) - (identifier? (syntax identifier-mapping-map))) (syntax - (provide/contract + (provide/contract* [make-identifier-mapping (-> identifier-mapping?)] - [identifier-mapping? (any/c . -> . boolean?)] + [identifier-mapping?/out (any/c . -> . boolean?)] [identifier-mapping-get (opt->* (identifier-mapping? identifier?) @@ -42,7 +47,7 @@ (provide-mapping-code/contract make-bound-identifier-mapping - bound-identifier-mapping? + bound-identifier-mapping? bound-identifier-mapping? bound-identifier-mapping-get bound-identifier-mapping-put! bound-identifier-mapping-for-each @@ -50,10 +55,11 @@ bound-identifier=?) (provide-mapping-code/contract - make-module-identifier-mapping + [make-module-identifier-mapping make-free-identifier-mapping] module-identifier-mapping? - module-identifier-mapping-get - module-identifier-mapping-put! - module-identifier-mapping-for-each - module-identifier-mapping-map + [module-identifier-mapping? free-identifier-mapping?] + [module-identifier-mapping-get free-identifier-mapping-get] + [module-identifier-mapping-put! free-identifier-mapping-put!] + [module-identifier-mapping-for-each free-identifier-mapping-for-each] + [module-identifier-mapping-map free-identifier-mapping-map] module-identifier=?)) diff --git a/collects/syntax/info.ss b/collects/syntax/info.ss index 7aaae1d2a7..ec6148f893 100644 --- a/collects/syntax/info.ss +++ b/collects/syntax/info.ss @@ -1,3 +1,3 @@ #lang setup/infotab -(define name "Syntax Utilities") +(define scribblings '(("scribblings/syntax.scrbl" (multi-page)))) diff --git a/collects/syntax/scribblings/boundmap.scrbl b/collects/syntax/scribblings/boundmap.scrbl new file mode 100644 index 0000000000..0c685de99b --- /dev/null +++ b/collects/syntax/scribblings/boundmap.scrbl @@ -0,0 +1,123 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/boundmap)) + +@title[#:tag "boundmap"]{Hashing on @scheme[bound-identifier=?] and @scheme[free-identifier=?]} + +@defmodule[syntax/boundmap] + +@defproc[(make-bound-identifier-mapping) bound-identifier-mapping?]{ + +Produces a hash-table-like value for storing a mapping from syntax +identifiers to arbitrary values. + +The mapping uses @scheme[bound-identifier=?] to compare mapping keys, +but also uses a hash table based on symbol equality to make the +mapping efficient in the common case (i.e., where non-equivalent +identifiers are derived from different symbolic names).} + + +@defproc[(bound-identifier-mapping? [v any/c]) boolean?]{ + +Returns @scheme[#t] if @scheme[v] was produced by +@scheme[make-bound-identifier-mapping], @scheme[#f] otherwise.} + + +@defproc[(bound-identifier-mapping-get [bound-map bound-identifier-mapping?] + [id identifier?] + [failure-thunk any/c (lambda () (raise (make-exn:fail ....)))]) + any]{ + +Like @scheme[hash-table-get] for bound-identifier mappings.} + + +@defproc[(bound-identifier-mapping-put! [bound-map bound-identifier-mapping?] + [id identifier?] + [v any/c]) + void?]{ + +Like @scheme[hash-table-put!] for bound-identifier mappings.} + +@defproc[(bound-identifier-mapping-for-each [bound-map boud-identifier-mapping?] + [proc (identifier? any/c . -> . any)]) + void?]{ + +Like @scheme[hash-table-for-each].} + + +@defproc[(bound-identifier-mapping-map [bound-map bound-identifier-mapping?] + [proc (identifier? any/c . -> . any)]) + (listof any?)]{ + +Like @scheme[hash-table-map].} + + +@defproc[(make-free-identifier-mapping) free-identifier-mapping?]{ + +Produces a hash-table-like value for storing a mapping from syntax +identifiers to arbitrary values. + +The mapping uses @scheme[free-identifier=?] to compare mapping keys, +but also uses a hash table based on symbol equality to make the +mapping efficient in the common case (i.e., where non-equivalent +identifiers are derived from different symbolic names at their +definition sites).} + + +@defproc[(free-identifier-mapping? [v any/c]) boolean?]{ + +Returns @scheme[#t] if @scheme[v] was produced by +@scheme[make-free-identifier-mapping], @scheme[#f] otherwise. +} + + +@defproc[(free-identifier-mapping-get [free-map free-identifier-mapping?] + [id identifier?] + [failure-thunk any/c (lambda () (raise (make-exn:fail ....)))]) + any]{ + +Like @scheme[hash-table-get] for free-identifier mappings.} + + +@defproc[(free-identifier-mapping-put! [free-map free-identifier-mapping?] + [id identifier?] + [v any/c]) + void?]{ + +Like @scheme[hash-table-put!] for free-identifier mappings.} + + +@defproc[(free-identifier-mapping-for-each [free-map free-identifier-mapping?] + [proc (identifier? any/c . -> . any)]) + void?]{ + +Like @scheme[hash-table-for-each].} + + +@defproc[(free-identifier-mapping-map [free-map free-identifier-mapping?] + [proc (identifier? any/c . -> . any)]) + (listof any?)]{ + +Like @scheme[hash-table-map].} + + +@deftogether[( +@defproc[(make-module-identifier-mapping) module-identifier-mapping?] +@defproc[(module-identifier-mapping? [v any/c]) boolean?] +@defproc[(module-identifier-mapping-get [module-map module-identifier-mapping?] + [id identifier?] + [failure-thunk any/c (lambda () (raise (make-exn:fail ....)))]) + any] +@defproc[(module-identifier-mapping-put! [module-map module-identifier-mapping?] + [id identifier?] + [v any/c]) + void?] +@defproc[(module-identifier-mapping-for-each [module-map module-identifier-mapping?] + [proc (identifier? any/c . -> . any)]) + void?] +@defproc[(module-identifier-mapping-map [module-map module-identifier-mapping?] + [proc (identifier? any/c . -> . any)]) + (listof any?)] +)]{ + +The same as @scheme[make-module-identifier-mapping], etc.} diff --git a/collects/syntax/scribblings/common.ss b/collects/syntax/scribblings/common.ss new file mode 100644 index 0000000000..9aad38f9ac --- /dev/null +++ b/collects/syntax/scribblings/common.ss @@ -0,0 +1,12 @@ +#lang scheme/base + +(require scribble/manual + (for-label scheme/base + scheme/contract)) + +(provide (all-from-out scribble/manual) + (for-label (all-from-out scheme/base + scheme/contract)) + refman) + +(define refman '(lib "scribblings/reference/reference.scrbl")) diff --git a/collects/syntax/scribblings/context.scrbl b/collects/syntax/scribblings/context.scrbl new file mode 100644 index 0000000000..3e065b50ca --- /dev/null +++ b/collects/syntax/scribblings/context.scrbl @@ -0,0 +1,19 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/context)) + +@title[#:tag "context"]{Support for @scheme[local-expand]} + +@defmodule[syntax/context] + +@defproc[(build-expand-context [v (or/c symbol? list?)]) list?]{ + +Returns a list suitable for use as a context argument to +@scheme[local-expand] for an internal-definition context. The +@scheme[v] argument represents the immediate context for +expansion. The context list builds on @scheme[(syntax-local-context)] +if it is a list.} + +@defproc[(generate-expand-context) list?]{ + +Calls @scheme[build-expand-context] with a generated symbol.} diff --git a/collects/syntax/scribblings/define.scrbl b/collects/syntax/scribblings/define.scrbl new file mode 100644 index 0000000000..5f1f471909 --- /dev/null +++ b/collects/syntax/scribblings/define.scrbl @@ -0,0 +1,33 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/define)) + + +@title[#:tag "define"]{Parsing @scheme[define]-like Forms} + +@defmodule[syntax/define] + +@defproc[(normalize-definition [defn-stx syntax?] + [lambda-id-stx identifier?] + + [check-context? boolean? #t] + [opt+kws? boolean? #t]) + (values identifier? syntax?)]{ + +Takes a definition form whose shape is like @scheme[define] (though +possibly with a different name) and returns two values: the defined +identifier and the right-hand side expression. + +To generate the right-hand side, this function may need to insert uses +of @scheme[lambda]. The @scheme[lambda-id-stx] argument provides a +suitable @scheme[lambda] identifier. + +If the definition is ill-formed, a syntax error is raised. If +@scheme[check-context?] is true, then a syntax error is raised if +@scheme[(syntax-local-context)] indicates that the current context is +an expression context. The default value of @scheme[check-context?] is +@scheme[#t]. + +If @scheme[opt-kws?] is @scheme[#t], then arguments of the form +@scheme[[id expr]], @scheme[keyword id], and @scheme[keyword [id +expr]] are allowed, and they are preserved in the expansion.} diff --git a/collects/syntax/scribblings/docprovide.scrbl b/collects/syntax/scribblings/docprovide.scrbl new file mode 100644 index 0000000000..4161be0df1 --- /dev/null +++ b/collects/syntax/scribblings/docprovide.scrbl @@ -0,0 +1,61 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/docprovide)) + +@title[#:tag "docprovide"]{Attaching Documentation to Exports} + +@defmodule[syntax/docprovide] + +@defform/subs[#:literals (all-from all-from-except) + (provide-and-document doc-label-id doc-row ...) + ([doc-row + (section-string (name type-datum doc-string ...) ...) + (all-from prefix-id module-path doc-label-id) + (all-from-except prefix-id module-path doc-label-id id ...)] + [name + id + (local-name-id external-name-id)])]{ + +A form that exports names and records documentation information. + +The @scheme[doc-label-id] identifier is used as a key for accessing +the documentation through @scheme[lookup-documentation]. The actual +documentation is organized into ``rows'', each with a section title. + +A @scheme[row] has one of the following forms: + +@itemize{ + @item{@scheme[(section-string (name type-datum doc-string ...) ...)] + + Creates a documentation section whose title is @scheme[section-string], + and provides/documents each @scheme[name]. The @scheme[type-datum] is arbitrary, + for use by clients that call @scheme[lookup-documentation]. The + @scheme[doc-string]s are also arbitrary documentation information, + usually concatenated by clients. + + A @scheme[name] is either an identifier or a renaming sequence + @scheme[(local-name-id extenal-name-id)]. + + Multiple @scheme[row]s with the same section name will be merged in the +documentation output. The final order of sections matches the order of +the first mention of each section.} + + @item{@scheme[(all-from prefix-id module-path doc-label-id)]} + @item{@scheme[(all-from-except prefix-id module-path doc-label-id id ...)] + + Merges documentation and provisions from the specified module +into the current one; the @scheme[prefix-id] is used to prefix the imports +into the current module (so they can be re-exported). If @scheme[id]s are +provided, the specified @scheme[id]s are not re-exported and their +documentation is not merged.}}} + +@defproc[(lookup-documentation [module-path-v module-path?] + [label-sym symbol?]) + any]{ + +Returns documentation for the specified module and label. The +@scheme[module-path-v] argument is a quoted module path, like the +argument to @scheme[dynamic-require]. The +@scheme[label-sym] identifies a set of documentation using the symbol +as a label identifier in @scheme[provide-and-document].} + diff --git a/collects/syntax/scribblings/free-vars.scrbl b/collects/syntax/scribblings/free-vars.scrbl new file mode 100644 index 0000000000..fec6d7db0d --- /dev/null +++ b/collects/syntax/scribblings/free-vars.scrbl @@ -0,0 +1,13 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/free-vars)) + +@title[#:tag "free-vars"]{Computing the Free Variables of an Expression} + +@defmodule[syntax/free-vars] + +@defproc[(free-vars [expr-stx syntax?]) (listof identifier?)]{ + +Returns a list of free @scheme[lambda]- and @scheme[let]-bound +identifiers in @scheme[expr-stx]. The expression must be fully +expanded (@secref[#:doc refman "fully-expanded"]).} diff --git a/collects/syntax/scribblings/kerncase.scrbl b/collects/syntax/scribblings/kerncase.scrbl new file mode 100644 index 0000000000..c349d19da6 --- /dev/null +++ b/collects/syntax/scribblings/kerncase.scrbl @@ -0,0 +1,48 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/kerncase)) + +@(define-syntax-rule (intro id) + (begin + (require (for-label mzscheme)) + (define id (scheme if)))) +@(intro mzscheme-if) + +@; ---------------------------------------------------------------------- + +@title[#:tag "kerncase"]{Matching Fully-Expanded Expressions} + +@defmodule[syntax/kerncase] + +@defform[(kernel-syntax-case stx-expr trans?-expr clause ...)]{ + +A syntactic form like @scheme[syntax-case*], except that the literals +are built-in as the names of the primitive PLT Scheme forms as +exported by @schememodname[scheme/base]; see @secref[#:doc refman +"fully-expanded"]. + +The @scheme[trans?-expr] boolean expression replaces the comparison +procedure, and instead selects simply between normal-phase comparisons +or transformer-phase comparisons. The @scheme[clause]s are the same as in +@scheme[syntax-case*]. + +The primitive syntactic forms must have their normal bindings in the +context of the @scheme[kernel-syntax-case] expression. Beware that +@scheme[kernel-syntax-case] does not work in a module whose language +is @scheme[mzscheme], since the binding of @mzscheme-if from +@scheme[mzscheme] is different than the primitive @scheme[if].} + + +@defform[(kernel-syntax-case* stx-expr trans?-expr (extras ...) clause ...)]{ + +A syntactic form like @scheme[kernel-syntax-case], except that it +takes an additional list of extra literals that are in addition to the +primitive PLT Scheme forms.} + + +@defproc[(kernel-form-identifier-list) (listof indentifier?)]{ + +Returns a list of identifiers that are bound normally, +@scheme[for-syntax], and @scheme[for-template] to the primitive PLT +Scheme forms for expressions. This function is useful for generating a +list of stopping points to provide to @scheme[local-expand].} diff --git a/collects/syntax/scribblings/modcode.scrbl b/collects/syntax/scribblings/modcode.scrbl new file mode 100644 index 0000000000..476c32f010 --- /dev/null +++ b/collects/syntax/scribblings/modcode.scrbl @@ -0,0 +1,72 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/modcode)) + +@title[#:tag "modcode"]{Getting Module Compiled Code} + +@defmodule[syntax/modcode] + +@defproc[(get-module-code [module-path-v module-path?] + [compiled-subdir (and/c path-string? relative-path?) "compiled"] + [compile-proc (any/c . -> . any) compile] + [ext-proc (or/c false/c (path? boolean? . -> . any)) #f] + [#:choose choose-proc + (path? path? path? + . -> . + (or/c (symbols 'src 'zo 'so) false/c)) + (lambda (src zo so) #f)] + [#:notify notify-proc (any/c . -> . any) void]) + any]{ + +Returns a compiled expression for the declaration of the module +specified by @scheme[module-path-v]. + +The @scheme[compiled-subdir] argument defaults to @scheme{compiled}; +it specifies the sub-directory to search for a compiled version of the +module. + +The @scheme[compile-proc] argument defaults to @scheme[compile]. This +procedure is used to compile module source if an already-compiled +version is not available. + +The @scheme[ext-proc] argument defaults to @scheme[#f]. If it is not +@scheme[#f], it must be a procedure of two arguments that is called +when a native-code version of @scheme[path] is should be used. In that +case, the arguments to @scheme[ext-proc] are the path for the +extension, and a boolean indicating whether the extension is a @tt{_loader} +file (@scheme[#t]) or not (@scheme[#f]). + +The @scheme[choose-proc] argument is a procedure that takes three +paths: a source path, a @filepath{.zo} file path, and an extension path +(for a non-@tt{_loader} extension). Some of the paths may not +exist. The result should be either @scheme['src], @scheme['zo], +@scheme['so], or @scheme[#f], indicating which variant should be used +or (in the case of @scheme[#f]) that the default choice should be +used. + +The default choice is computed as follows: if a @filepath{.zo} version +of @scheme[path] is available and newer than @scheme[path] itself (in +one of the directories specified by @scheme[compiled-subdir]), then it +is used instead of the source. Native-code versions of @scheme[path] +are ignored, unless only a native-code non-@tt{_loader} version exists +(i.e., @scheme[path] itself does not exist). A @tt{_loader} extension +is selected a last resort. + +If an extension is prefered or is the only file that exists, it is +supplied to @scheme[ext-proc] when @scheme[ext-proc] is @scheme[#f], +or an exception is raised (to report that an extension file cannot be +used) when @scheme[ext-proc] is @scheme[#f]. + +If @scheme[notify-proc] is supplied, it is called for the file +(source, @filepath{.zo} or extension) that is chosen.} + +@defparam[moddep-current-open-input-file proc (path-string? . -> . input-port?)]{ + +A parameter whose value is used like @scheme[open-input-file] to read +a module source or @filepath{.zo} file.} + + +@defstruct[(exn:get-module-code exn) ([path path?])]{ + +An exception structure type for exceptions raised by +@scheme[get-module-code].} diff --git a/collects/syntax/scribblings/modcollapse.scrbl b/collects/syntax/scribblings/modcollapse.scrbl new file mode 100644 index 0000000000..0017d12e0e --- /dev/null +++ b/collects/syntax/scribblings/modcollapse.scrbl @@ -0,0 +1,32 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/modcollapse)) + +@title[#:tag "modcollapse"]{Simplifying Module Paths} + +@defmodule[syntax/modcollapse] + +@defproc[(collapse-module-path [module-path-v module-path?] + [rel-to-module-path-v any/c]) + (or/c path? module-path?)]{ + +Returns a ``simplified'' module path by combining +@scheme[module-path-v] with @scheme[rel-to-module-path-v], where the +latter must have the form @scheme['(lib ....)], @scheme['(file +)], @scheme['(path ....)], a @techlink[#:doc refman]{path}, or +a thunk to generate one of those. + +The result can be a path if @scheme[module-path-v] contains a path +element that is needed for the result, or if +@scheme[rel-to-module-path-v] is a non-string path that is needed for +the result; otherwise, the result is a module path in the sense of +@scheme[module-path?].} + +@defproc[(collapse-module-path-index [module-path-index module-path-index?] + [rel-to-module-path-v any/c]) + (or/c path? module-path?)]{ + +Like @scheme[collapse-module-path], but the input is a @techlink[#:doc +refman]{module path index}; in this case, the +@scheme[rel-to-module-path-v] base is used where the module path index +contains the ``self'' index.} diff --git a/collects/syntax/scribblings/moddep.scrbl b/collects/syntax/scribblings/moddep.scrbl new file mode 100644 index 0000000000..44bb1d52d3 --- /dev/null +++ b/collects/syntax/scribblings/moddep.scrbl @@ -0,0 +1,16 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/moddep)) + +@title[#:tag "moddep"]{Inspecting Modules and Module Dependencies} + +@defmodule[syntax/moddep] + +Re-exports @schememodname[syntax/modread], +@schememodname[syntax/modcode], @schememodname[syntax/modcollapse], +and @schememodname[syntax/modresolve], in addition to the following: + +@defproc[(show-import-tree [module-path-v module-path?]) void?]{ + +A debugging aid that prints the import hierarchy starting from a given +module path.} diff --git a/collects/syntax/scribblings/modread.scrbl b/collects/syntax/scribblings/modread.scrbl new file mode 100644 index 0000000000..f2c338eabf --- /dev/null +++ b/collects/syntax/scribblings/modread.scrbl @@ -0,0 +1,35 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/moddep)) + +@title[#:tag "modread"]{Reading Module Source Code} + +@defmodule[syntax/modread] + +@defproc[(with-module-reading-parameterization [thunk (-> any)]) any]{ + +Calls @scheme[thunk] with all reader parameters reset to their default +values.} + +@defproc[(check-module-form [stx (or/c syntax? eof-object?)] + [expected-module-sym symbol?] + [source-v (or/c string? false/c)]) + (or/c syntax? false/c)]{ + +Inspects @scheme[stx] to check whether evaluating it will declare a +module named @scheme[expected-module-sym]---at least if @scheme[module] is bound +in the top-level to MzScheme's @scheme[module]. The syntax object @scheme[stx] can +contain a compiled expression. Also, @scheme[stx] can be an end-of-file, on +the grounds that @scheme[read-syntax] can produce an end-of-file. + +If @scheme[stx] can declare a module in an appropriate top-level, then +the @scheme[check-module-form] procedure returns a syntax object that +certainly will declare a module (adding explicit context to the +leading @scheme[module] if necessary) in any top-level. Otherwise, if +@scheme[source-v] is not @scheme[#f], a suitable exception is raised +using the @scheme[write] form of the source in the message; if +@scheme[source-v] is @scheme[#f], @scheme[#f] is returned. + +If @scheme[stx] is eof or eof wrapped as a syntax object, then an +error is raised or @scheme[#f] is returned.} + diff --git a/collects/syntax/scribblings/modresolve.scrbl b/collects/syntax/scribblings/modresolve.scrbl new file mode 100644 index 0000000000..ee5f10bdb6 --- /dev/null +++ b/collects/syntax/scribblings/modresolve.scrbl @@ -0,0 +1,27 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/modresolve)) + +@title{Resolving Module Paths to File Paths} + +@defmodule[syntax/modresolve] + +@defproc[(resolve-module-path [module-path-v module-path?] + [rel-to-path-v (or/c path-string? (-> any) false/c)]) + path?]{ + +Resolves a module path to filename path. The module path is resolved +relative to @scheme[rel-to-path-v] if it is a path string (assumed to +be for a file), to the directory result of calling the thunk if it is +a thunk, or to the current directory otherwise.} + +@defproc[(resolve-module-path-index [module-path-index module-path-index?] + [rel-to-path-v (or/c path-string? (-> any) false/c)]) + path?]{ + +Like @scheme[resolve-module-path] but the input is a @techlink[#:doc +refman]{module path index}; in this case, the @scheme[rel-to-path-v] +base is used where the module path index contains the ``self'' index. +If @scheme[module-path-index] depends on the ``self'' module path +index, then an exception is raised unless @scheme[rel-to-path-v] is a +path string.} diff --git a/collects/syntax/scribblings/name.scrbl b/collects/syntax/scribblings/name.scrbl new file mode 100644 index 0000000000..22135b9910 --- /dev/null +++ b/collects/syntax/scribblings/name.scrbl @@ -0,0 +1,16 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/name)) + +@title[#:tag "name"]{Extracting Inferred Names} + +@defmodule[syntax/name] + +@defproc[(syntax-local-infer-name [stx syntax?]) (or/c symbol? false/c)]{ + +Similar to @scheme[syntax-local-name] except that @scheme[stx] is +checked for an @scheme['inferred-name] property (which overrides any +inferred name). If neither @scheme[syntax-local-name] nor +@scheme['inferred-name] produce a name, then a name is constructed +from the source-location information in @scheme[stx], if any. If no +name can be constructed, the result is @scheme[#f].} diff --git a/collects/syntax/scribblings/path-spec.scrbl b/collects/syntax/scribblings/path-spec.scrbl new file mode 100644 index 0000000000..a2e2443475 --- /dev/null +++ b/collects/syntax/scribblings/path-spec.scrbl @@ -0,0 +1,23 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/path-spec)) + +@title[#:tag "path-spec"]{Resolving @scheme[include]-like Paths} + +@defmodule[syntax/path-spec] + +@defproc[(resolve-path-spec [path-spec-stx syntax?] + [source-stx syntax?] + [expr-stx syntax?] + [build-path-stx syntax?]) + complete-path?]{ + +Resolves the syntactic path specification @scheme[path-spec-stx] as +for @scheme[include]. + +The @scheme[source-stx] specifies a syntax object whose +source-location information determines relative-path resolution. The +@scheme[expr-stx] is used for reporting syntax errors. The +@scheme[build-path-stx] is usually @scheme[#'build-path]; it provides +an identifier to compare to parts of @scheme[path-spec-stx] to +recognize the @scheme[build-path] keyword.} diff --git a/collects/syntax/scribblings/readerr.scrbl b/collects/syntax/scribblings/readerr.scrbl new file mode 100644 index 0000000000..517653cb48 --- /dev/null +++ b/collects/syntax/scribblings/readerr.scrbl @@ -0,0 +1,44 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/readerr)) + +@title[#:tag "readerr"]{Raising @scheme[exn:fail:read]} + +@defmodule[syntax/readerr] + +@defproc[(raise-read-error [msg-string string?] + [source any/c] + [line (or/c number? false/c)] + [col (or/c number? false/c)] + [pos (or/c number? false/c)] + [span (or/c number? false/c)]) + any]{ + +Creates and raises an @scheme[exn:fail:read] exception, using +@scheme[msg-string] as the base error message. + +Source-location information is added to the error message using the +last five arguments (if the @scheme[error-print-source-location] +parameter is set to @scheme[#t]). The @scheme[source] argument is an +arbitrary value naming the source location---usually a file path +string. Each of the @scheme[line], @scheme[pos] arguments is +@scheme[#f] or a positive exact integer representing the location +within @scheme[source-name] (as much as known), @scheme[col] is a +non-negative exact integer for the source column (if known), and +@scheme[span] is @scheme[#f] or a non-negative exact integer for an +item range starting from the indicated position. + +The usual location values should point at the beginning of whatever it +is you were reading, and the span usually goes to the point the error +was discovered.} + +@defproc[(raise-read-eof-error [msg-string string?] + [source any/c] + [line (or/c number? false/c)] + [col (or/c number? false/c)] + [pos (or/c number? false/c)] + [span (or/c number? false/c)]) + any]{ + +Like @scheme[raise-read-error], but raises @scheme[exn:fail:read:eof] +instead of @scheme[exn:fail:read].} diff --git a/collects/syntax/scribblings/struct.scrbl b/collects/syntax/scribblings/struct.scrbl new file mode 100644 index 0000000000..3a0282e02d --- /dev/null +++ b/collects/syntax/scribblings/struct.scrbl @@ -0,0 +1,149 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/struct)) + +@title[#:tag "struct"]{Expanding @scheme[define-struct]-like Forms} + +@defmodule[syntax/struct] + +@defproc[(parse-define-struct [stx syntax?] [orig-stx syntax?]) + (values identifier? + (or/c identifier? false/c) + (listof identifier?) + syntax?)]{ + +Parses @scheme[stx] as a @scheme[define-struct] form, but uses +@scheme[orig-stx] to report syntax errors (under the assumption that +@scheme[orig-stx] is the same as @scheme[stx], or that they at least share +sub-forms). The result is four values: an identifier for the struct +type name, a identifier or #f for the super-name, a list of +identifiers for fields, and a syntax object for the inspector +expression.} + +@defproc[(build-struct-names [name-id identifier?] + [field-ids (listof identifier?)] + [omit-sel? boolean?] + [omit-set? boolean?] + [src-stx (or/c syntax? false/c) #f]) + (listof identifier?)]{ + +Generates the names bound by @scheme[define-struct] given an +identifier for the struct type name and a list of identifiers for the +field names. The result is a list of identifiers: + +@itemize{ + @item{@schemeidfont{struct:}@scheme[name-id]} + @item{@schemeidfont{make-}@scheme[name-id]} + @item{@scheme[name-id]@schemeidfont{?}} + @item{@scheme[name-id]@schemeidfont{-}@scheme[_field], for each + @scheme[_field] in @scheme[field-ids].} + @item{@schemeidfont{set-}@scheme[name-id]@schemeidfont{-}@scheme[_field]@schemeidfont{!} + (getter and setter names alternate).} + @item{....}} + +If @scheme[omit-sel?] is true, then the selector names are omitted from the +result list. If @scheme[omit-set?] is true, then the setter names are omitted +from the result list. + +The default @scheme[src-stx] is @scheme[#f]; it is used to provide a +source location to the generated identifiers.} + +@defproc[(build-struct-generation [name-id identifier?] + [field-ids (listof identifier?)] + [omit-sel? boolean?] + [omit-set? boolean?] + + [super-type any/c #f] + [prop-value-list list? empty] + [immutable-k-list list? empty]) + (listof identifier?)]{ + +Takes the same arguments as @scheme[build-struct-names] and generates +an S-expression for code using @scheme[make-struct-type] to generate +the structure type and return values for the identifiers created by +@scheme[build-struct-names]. The optional @scheme[super-type], +@scheme[prop-value-list], and @scheme[immutable-k-list] parameters take +S-expression values that are used as the corresponding arguments to +@scheme[make-struct-type].} + +@defproc[(build-struct-generation* [all-name-ids (listof identifier?)] + [name-id identifier?] + [field-ids (listof identifier?)] + [omit-sel? boolean?] + [omit-set? boolean?] + [super-type any/c #f] + [prop-value-list list? empty] + [immutable-k-list list? empty]) + (listof identifier?)]{ + +Like @scheme[build-struct-generation], but given the names produced by +@scheme[build-struct-names], instead of re-generating them.} + +@defproc[(build-struct-expand-info [name-id identifier?] + [field-ids (listof identifier?)] + [omit-sel? boolean?] + [omit-set? boolean?] + [base-name (or/c identifier? boolean?)] + [base-getters (listof (or/c identifier? false/c))] + [base-setters (listof (or/c identifier? false/c))]) + any]{ + +Takes the same arguments as @scheme[build-struct-names], plus a parent +identifier/@scheme[#t]/@scheme[#f] and a list of accessor and mutator +identifiers (possibly ending in @scheme[#f]) for a parent type, and +generates an S-expression for expansion-time code to be used in the +binding for the structure name. A @scheme[#t] for the +@scheme[base-name] means no super-type, @scheme[#f] means that the +super-type (if any) is unknown, and an identifier indicates the +super-type identifier.} + +@defproc[(struct-declaration-info? [v any/c]) boolean?]{ + +Returns @scheme[#t] if @scheme[x] has the shape of expansion-time +information for structure type declarations, @scheme[#f] otherwise. +See @secref[#:doc refman]{structinfo}.} + +@defproc[(generate-struct-declaration [orig-stx syntax?] + [name-id identifier?] + [super-id-or-false (or/c identifier? false/c)] + [field-id-list (listof identifier?)] + [current-context any/c] + [make-make-struct-type procedure?] + [omit-sel? boolean? #f] + [omit-set? boolean? #f]) + syntax?]{ + +This procedure implements the core of a @scheme[define-struct] +expansion. + +The @scheme[generate-struct-declaration] procedure is called by a +macro expander to generate the expansion, where the @scheme[name-id], +@scheme[super-id-or-false], and @scheme[field-id-list] arguments +provide the main parameters. The @scheme[current-context] argument is +normally the result of @scheme[syntax-local-context]. The +@scheme[orig-stx] argument is used for syntax errors. The optional +@scheme[omit-sel?] and @scheme[omit-set?] arguments default to +@scheme[#f]; a @scheme[#t] value suppresses definitions of field +selectors or mutators, respectively. + +The @scheme[make-struct-type] procedure is called to generate the +expression to actually create the struct type. Its arguments are +@scheme[orig-stx], @scheme[name-id-stx], @scheme[defined-name-stxes], +and @scheme[super-info]. The first two are as provided originally to +@scheme[generate-struct-declaration], the third is the set of names +generated by @scheme[build-struct-names], and the last is super-struct +info obtained by resolving @scheme[super-id-or-false] when it is not +@scheme[#f], @scheme[#f] otherwise. + +The result should be an expression whose values are the same as the +result of @scheme[make-struct-type]. Thus, the following is a basic +@scheme[make-make-struct-type]: + +@SCHEMEBLOCK[ + (lambda (orig-stx name-stx defined-name-stxes super-info) + #`(make-struct-type '#,name-stx + #,(and super-info (list-ref super-info 0)) + #,(/ (- (length defined-name-stxes) 3) 2) + 0 #f))] + +but an actual @scheme[make-make-struct-type] will likely do more.} diff --git a/collects/syntax/scribblings/stx.scrbl b/collects/syntax/scribblings/stx.scrbl new file mode 100644 index 0000000000..537e27d9e6 --- /dev/null +++ b/collects/syntax/scribblings/stx.scrbl @@ -0,0 +1,55 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/stx)) + +@title[#:tag "stx"]{Deconstructing Syntax Objects} + +@defmodule[syntax/stx] + +@defproc[(stx-null? [v any/c]) boolean?]{ + +Returns @scheme[#t] if @scheme[v] is either the empty list or a +@tech[#:doc refman]{syntax object} representing the empty list (i.e., +@scheme[syntax-e] on the @tech[#:doc refman]{syntax object} returns +the empty list).} + +@defproc[(stx-pair? [v any/c]) boolean?]{ + +Returns @scheme[#t] if @scheme[v] is either a pair or a syntax object +representing a pair (see @techlink[#:doc refman]{syntax pair}).} + +@defproc[(stx-list? [v any/c]) boolean?]{ + +Returns @scheme[#t] if @scheme[v] is a list, or if it is a sequence of +pairs leading to a syntax object such that @scheme[syntax->list] would +produce a list.} + +@defproc[(stx->list [stx-list stx-list?]) list?]{ + +Produces a list by flatting out a trailing syntax object using +@scheme[syntax->list].} + +@defproc[(stx-car [v stx-pair?]) any]{ + +Takes the car of a @techlink[#:doc refman]{syntax pair}.} + +@defproc[(stx-cdr [v stx-pair?]) any]{ + +Takes the cdr of a @techlink[#:doc refman]{syntax pair}.} + +@defproc[(module-or-top-identifier=? [a-id identifier?] + [b-id identifier?]) + boolean?]{ + +Returns @scheme[#t] if @scheme[a-id] and @scheme[b-id] are +@scheme[free-identifier=?], or if @scheme[a-id] and @scheme[b-id] have +the same name (as extracted by @scheme[syntax-e]) and @scheme[a-id] +has no binding other than at the top level. + +This procedure is useful in conjunction with @scheme[syntax-case*] to +match procedure names that are normally bound by MzScheme. For +example, the @scheme[include] macro uses this procedure to recognize +@scheme[build-path]; using @scheme[free-identifier=?] would not work +well outside of @scheme[module], since the top-level +@scheme[build-path] is a distinct variable from the MzScheme export +(though it's bound to the same procedure, initially).} diff --git a/collects/syntax/scribblings/syntax.scrbl b/collects/syntax/scribblings/syntax.scrbl new file mode 100644 index 0000000000..f6631512f5 --- /dev/null +++ b/collects/syntax/scribblings/syntax.scrbl @@ -0,0 +1,37 @@ +#lang scribble/doc +@(require "common.ss") + +@title{@bold{Syntax}: Meta-Programming Helpers} + +@table-of-contents[] + +@include-section["stx.scrbl"] +@include-section["kerncase.scrbl"] +@include-section["toplevel.scrbl"] +@include-section["define.scrbl"] +@include-section["struct.scrbl"] +@include-section["name.scrbl"] +@include-section["docprovide.scrbl"] + +@include-section["moddep.scrbl"] +@include-section["modread.scrbl"] +@include-section["modcode.scrbl"] +@include-section["modresolve.scrbl"] +@include-section["modcollapse.scrbl"] + +@include-section["readerr.scrbl"] + +@include-section["boundmap.scrbl"] + +@include-section["path-spec.scrbl"] + +@include-section["zodiac.scrbl"] + +@include-section["context.scrbl"] + +@include-section["trusted-xforms.scrbl"] + +@include-section["to-string.scrbl"] +@include-section["free-vars.scrbl"] + +@index-section[] diff --git a/collects/syntax/scribblings/to-string.scrbl b/collects/syntax/scribblings/to-string.scrbl new file mode 100644 index 0000000000..92b8b44cb9 --- /dev/null +++ b/collects/syntax/scribblings/to-string.scrbl @@ -0,0 +1,13 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/to-string)) + +@title[#:tag "to-string"]{Rendering Syntax Objects with Formatting} + +@defmodule[syntax/to-string] + +@defproc[(syntax->string [stx-list stx-list?]) string?]{ + +Builds a string with newlines and indenting according to the source +locations in @scheme[stx-list]; the outer pair of parens are not +rendered from @scheme[stx-list].} diff --git a/collects/syntax/scribblings/toplevel.scrbl b/collects/syntax/scribblings/toplevel.scrbl new file mode 100644 index 0000000000..c9a17e3b8c --- /dev/null +++ b/collects/syntax/scribblings/toplevel.scrbl @@ -0,0 +1,56 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/toplevel)) + +@title[#:tag "toplevel"]{Helper for Non-Module Compilation And Expansion} + +@defmodule[syntax/toplevel] + +@defproc[(expand-syntax-top-level-with-compile-time-evals [stx syntax?]) + syntax?]{ + +Expands @scheme[stx] as a top-level expression, and evaluates its +compile-time portion for the benefit of later expansions. + +The expander recognizes top-level @scheme[begin] expressions, and +interleaves the evaluation and expansion of of the @scheme[begin] +body, so that compile-time expressions within the @scheme[begin] body +affect later expansions within the body. (In other words, it ensures +that expanding a @scheme[begin] is the same as expanding separate +top-level expressions.) + +The @scheme[stx] should have a context already, possibly introduced with +@scheme[namespace-syntax-introduce].} + +@defproc[(expand-top-level-with-compile-time-evals [stx syntax]) + syntax?]{ + +Like @scheme[expand-syntax-top-level-with-compile-time-evals], but +@scheme[stx] is first given context by applying +@scheme[namespace-syntax-introduce] to it.} + +@defproc[(expand-syntax-top-level-with-compile-time-evals/flatten [stx syntax?]) + (listof syntax?)]{ + +Like @scheme[expand-syntax-top-level-with-compile-time-evals], except +that it returns a list of syntax objects, none of which have a +@scheme[begin]. These syntax objects are the flattened out contents of +any @scheme[begin]s in the expansion of @scheme[stx].} + +@defproc[(eval-compile-time-part-of-top-level [stx syntax?]) + void?]{ + +Evaluates expansion-time code in the fully expanded top-level +expression represented by @scheme[stx] (or a part of it, in the case +of @scheme[begin] expressions). The expansion-time code might affect +the compilation of later top-level expressions. For example, if +@scheme[stx] is a @scheme[require] expression, then +@scheme[namespace-require/expansion-time] is used on each require +specification in the form. Normally, this function is used only by +@scheme[expand-top-level-with-compile-time-evals].} + +@defproc[(eval-compile-time-part-of-top-level/compile [stx syntax?]) + (listof compiled-expression?)]{ + +Like @scheme[eval-compile-time-part-of-top-level], but the result is +compiled code.} diff --git a/collects/syntax/scribblings/trusted-xforms.scrbl b/collects/syntax/scribblings/trusted-xforms.scrbl new file mode 100644 index 0000000000..d60d414e8d --- /dev/null +++ b/collects/syntax/scribblings/trusted-xforms.scrbl @@ -0,0 +1,16 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/trusted-xforms)) + +@title[#:tag "trusted-xforms"]{Trusting Standard Recertifying Transformers} + +@defmodule[syntax/trusted-xforms] + +The @schememodname[syntax/trusted-xforms] library has no exports. It +exists only to require other modules that perform syntax +transformations, where the other transformations must use +@scheme[syntax-recertify]. An application that wishes to provide a +less powerful code inspector to a sub-program should generally attach +@schememodname[syntax/trusted-xforms] to the sub-program's namespace +so that things like the class system from @schememodname[scheme/class] +work properly. diff --git a/collects/syntax/scribblings/zodiac.scrbl b/collects/syntax/scribblings/zodiac.scrbl new file mode 100644 index 0000000000..9fbe758e17 --- /dev/null +++ b/collects/syntax/scribblings/zodiac.scrbl @@ -0,0 +1,13 @@ +#lang scribble/doc +@(require "common.ss" + (for-label syntax/zodiac)) + +@title[#:tag "zodiac"]{Legacy Zodiac Interface} + +@defmodule*[(syntax/zodiac syntax/zodiac-unit syntax/zodiac-sig)] + +The interface is similar to Zodiac---enough to be useful for +porting---but different in many ways. See the source +@filepath{zodiac-sig.ss} for details. New software should not use this +compatibility layer. +