From a174d220fde7da24fdb21c842f1e246aac72c8c8 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Tue, 17 Feb 2009 13:51:35 +0000 Subject: [PATCH] doc scribble/scheme; add make-element-id-transformer svn: r13691 original commit: db5cab09e7fdcf6cc3b51ffb873ab359ec16a087 --- collects/scribble/scheme.ss | 88 +++++++------ collects/scribblings/scribble/scheme.scrbl | 145 ++++++++++++++++++++- 2 files changed, 190 insertions(+), 43 deletions(-) diff --git a/collects/scribble/scheme.ss b/collects/scribble/scheme.ss index 0a201e60..9767ff7e 100644 --- a/collects/scribble/scheme.ss +++ b/collects/scribble/scheme.ss @@ -24,7 +24,10 @@ (struct-out shaped-parens) (struct-out just-context) (struct-out literal-syntax) - (for-syntax make-variable-id)) + (for-syntax make-variable-id + variable-id? + make-element-id-transformer + element-id-transformer?)) (define no-color "schemeplain") (define reader-color "schemereader") @@ -598,53 +601,56 @@ (define ((to-paragraph/prefix pfx1 pfx sfx) c) (typeset c #t pfx1 pfx sfx #t)) - (begin-for-syntax (define-struct variable-id (sym) #:omit-define-syntaxes)) + (begin-for-syntax + (define-struct variable-id (sym) #:omit-define-syntaxes) + (define-struct element-id-transformer (proc) #:omit-define-syntaxes)) (define-syntax (define-code stx) (syntax-case stx () [(_ code typeset-code uncode d->s stx-prop) (syntax/loc stx (define-syntax (code stx) + (define (wrap-loc v ctx e) + `(,#'d->s ,ctx + ,e + #(code + ,(syntax-line v) + ,(syntax-column v) + ,(syntax-position v) + ,(syntax-span v)))) (define (stx->loc-s-expr v) - (cond - [(and (identifier? v) - (variable-id? (syntax-local-value v (lambda () #f)))) - `(,#'d->s #f - (,#'make-var-id ',(variable-id-sym (syntax-local-value v))) - #(code - ,(syntax-line v) - ,(syntax-column v) - ,(syntax-position v) - ,(syntax-span v)))] - [(syntax? v) - (let ([mk `(,#'d->s - (quote-syntax ,(datum->syntax v 'defcode)) - ,(syntax-case v (uncode) - [(uncode e) #'e] - [else (stx->loc-s-expr (syntax-e v))]) - #(code - ,(syntax-line v) - ,(syntax-column v) - ,(syntax-position v) - ,(syntax-span v)))]) - (let ([prop (syntax-property v 'paren-shape)]) - (if prop - `(,#'stx-prop ,mk 'paren-shape ,prop) - mk)))] - [(null? v) 'null] - [(list? v) `(list . ,(map stx->loc-s-expr v))] - [(pair? v) `(cons ,(stx->loc-s-expr (car v)) - ,(stx->loc-s-expr (cdr v)))] - [(vector? v) `(vector ,@(map - stx->loc-s-expr - (vector->list v)))] - [(and (struct? v) (prefab-struct-key v)) - `(make-prefab-struct (quote ,(prefab-struct-key v)) - ,@(map - stx->loc-s-expr - (cdr (vector->list (struct->vector v)))))] - [(box? v) `(box ,(stx->loc-s-expr (unbox v)))] - [else `(quote ,v)])) + (let ([slv (and (identifier? v) + (syntax-local-value v (lambda () #f)))]) + (cond + [(variable-id? slv) + (wrap-loc v #f `(,#'make-var-id ',(variable-id-sym slv)))] + [(element-id-transformer? slv) + (wrap-loc v #f ((element-id-transformer-proc slv) v))] + [(syntax? v) + (let ([mk (wrap-loc + v + `(quote-syntax ,(datum->syntax v 'defcode)) + (syntax-case v (uncode) + [(uncode e) #'e] + [else (stx->loc-s-expr (syntax-e v))]))]) + (let ([prop (syntax-property v 'paren-shape)]) + (if prop + `(,#'stx-prop ,mk 'paren-shape ,prop) + mk)))] + [(null? v) 'null] + [(list? v) `(list . ,(map stx->loc-s-expr v))] + [(pair? v) `(cons ,(stx->loc-s-expr (car v)) + ,(stx->loc-s-expr (cdr v)))] + [(vector? v) `(vector ,@(map + stx->loc-s-expr + (vector->list v)))] + [(and (struct? v) (prefab-struct-key v)) + `(make-prefab-struct (quote ,(prefab-struct-key v)) + ,@(map + stx->loc-s-expr + (cdr (vector->list (struct->vector v)))))] + [(box? v) `(box ,(stx->loc-s-expr (unbox v)))] + [else `(quote ,v)]))) (define (cvt s) (datum->syntax #'here (stx->loc-s-expr s) #f)) (syntax-case stx () diff --git a/collects/scribblings/scribble/scheme.scrbl b/collects/scribblings/scribble/scheme.scrbl index df959841..5c737673 100644 --- a/collects/scribblings/scribble/scheme.scrbl +++ b/collects/scribblings/scribble/scheme.scrbl @@ -1,6 +1,7 @@ #lang scribble/doc @(require scribble/manual - "utils.ss") + "utils.ss" + (for-label scribble/scheme)) @title[#:tag "scheme"]{Scheme} @@ -8,4 +9,144 @@ provides utilities for typesetting Scheme code. The @scheme[scribble/manual] forms provide a higher-level interface.} -@italic{To do:} document this library! +@defform*[[(define-code id typeset-expr) + (define-code id typeset-expr uncode-id) + (define-code id typeset-expr uncode-id d->s-expr) + (define-code id typeset-expr uncode-id d->s-expr stx-prop-expr)]]{ + +Binds @scheme[id] to a form similar to @scheme[scheme] or +@scheme[schemeblock] for typesetting code. The form generated by +@scheme[define-code] handles source-location information, escapes via +@scheme[unquote], preservation of binding and property information, +and @tech{element transformers}. + +The supplied @scheme[typeset-expr] expression should produce a +procedure that performs the actual typesetting. This expression is +normally @scheme[to-element] or @scheme[to-paragraph]. The argument +supplied to @scheme[typeset-expr] is normally a syntax object, but +more generally it is the result of applying @scheme[d->s-expr]. + +The optional @scheme[uncode-id] specifies the escape from literal code +to be recognized by @scheme[id]. The default is @scheme[unsyntax]. + +The optional @scheme[d->s-expr] should produce a procedure that +accepts three arguments suitable for @scheme[datum->syntax]: a syntax +object or @scheme[#f], an arbitrary value, and a vector for a source +location. The result should record as much or as little of the +argument information as needed by @scheme[typeset-expr] to typeset the +code. Normally, @scheme[d->s-expr] is @scheme[datum->syntax]. + +The @scheme[stx-prop-expr] should produce a procedure for recording a +@scheme['paren-shape] property when the source expression uses with +@scheme[id] has such a property. The default is +@scheme[syntax-property].} + +@defproc[(to-paragraph [v any/c]) block?]{ + +Typesets an S-expression that is represented by a syntax object, where +source-location information in the syntax object controls the +generated layout. + +Identifiers that have @scheme[for-label] bindings are typeset and +hyperlinked based on definitions declared elsewhere (via +@scheme[defproc], @scheme[defform], etc.). The identifiers +@schemeidfont{code:line}, @schemeidfont{code:comment}, and +@schemeidfont{code:blank} are handled as in @scheme[schemeblock], as +are identifiers that start with @litchar{_}. + +In addition, the given @scheme[v] can contain @scheme[var-id], +@scheme[shaped-parens], @scheme[just-context], or +@scheme[literal-syntax] structures to be typeset specially (see each +structure type for details), or it can contain @scheme[element] +structures that are used directly in the output.} + + +@defproc[((to-paragraph/prefix [prefix1 any/c] [prefix any/c] [suffix any/c]) + [v any/c]) + block?]{ + +Like @scheme[to-paragraph], but @scheme[prefix1] is prefixed onto the +first line, @scheme[prefix] is prefix to any subsequent line, and +@scheme[suffix] is added to the end. The @scheme[prefix1], +@scheme[prefix], and @scheme[suffix] arguments are used as +@tech{elements}, except that if @scheme[suffix] is a list of elements, +it is added to the end on its own line.} + + +@defproc[(to-element [v any/c]) element?]{ + +Like @scheme[to-paragraph], except that source-location information is +mostly ignored, since the result is meant to be inlined into a +paragraph.} + +@defproc[(to-element/no-color [v any/c]) element?]{ + +Like @scheme[to-element], but @scheme[for-syntax] bindings are +ignored, and the generated text is uncolored. This variant is +typically used to typeset results.} + + +@defstruct[var-id ([sym (or/c symbol? identifier?)])]{ + +When @scheme[to-paragraph] and variants encounter a @scheme[var-id] +structure, it is typeset as @scheme[sym] in the variable font, like +@scheme[schemevarfont].} + + +@defstruct[shaped-parens ([val any/c] + [shape char?])]{ + +When @scheme[to-paragraph] and variants encounter a +@scheme[shaped-parens] structure, it is typeset like a syntax object +that has a @scheme['paren-shape] property with value @scheme[shape].} + + +@defstruct[just-context ([val any/c] + [context syntax?])]{ + +When @scheme[to-paragraph] and variants encounter a +@scheme[just-context] structure, it is typeset using the +source-location information of @scheme[val] just the lexical context +of @scheme[ctx].} + + +@defstruct[literal-syntax ([stx any/c])]{ + +When @scheme[to-paragraph] and variants encounter a +@scheme[literal-syntax] structure, it is typeset as the string form of +@scheme[stx]. This can be used to typeset a syntax-object value in the +way that the default printer would represent the value.} + + +@defproc[(element-id-transformer? [v any/c]) boolean?]{ + +Provided @scheme[for-syntax]; returns @scheme[#t] if @scheme[v] is an +@tech{element transformer} created by +@scheme[make-element-id-transformer], @scheme[#f] otherwise.} + + +@defproc[(make-element-id-transformer [proc (syntax? . -> . syntax?)]) + element-id-transformer?]{ + +Provided @scheme[for-syntax]; creates an @deftech{element +transformer}. When an identifier has a transformer binding to an +@tech{element transformer}, then forms generated by +@scheme[define-code] (including @scheme[scheme] and +@scheme[schemeblock]) typeset the identifier by applying the +@scheme[proc] to the identifier. The result must be an expression +whose value, typically an @scheme[element], is passed on to functions +like @scheme[to-paragraph] .} + +@defproc[(variable-id? [v any/c]) boolean?]{ + +Provided @scheme[for-syntax]; returns @scheme[#t] if @scheme[v] is an +@tech{element transformer} created by @scheme[make-variable-id], +@scheme[#f] otherwise.} + + +@defproc[(make-variable-id [sym (or/c symbol? identifier?)]) + variable-id?]{ + +Provided @scheme[for-syntax]; like @scheme[element-id-transformer] for +a transformer that produces @scheme[sym] typeset as a variable (like +@scheme[schemevarfont]).}