diff --git a/collects/scribble/basic.ss b/collects/scribble/basic.ss index 624837b4ed..d43b716def 100644 --- a/collects/scribble/basic.ss +++ b/collects/scribble/basic.ss @@ -1,9 +1,8 @@ -(module basic mzscheme +(module basic (lib "new-lambda.ss" "scribblings") (require "decode.ss" "struct.ss" "config.ss" - (lib "kw.ss") (lib "list.ss") (lib "class.ss")) @@ -19,23 +18,23 @@ (content->string content) "_")) - (define/kw (title #:key [tag #f] [style #f] #:body str) + (define (title #:tag [tag #f] #:style [style #f] . str) (let ([content (decode-content str)]) (make-title-decl (or tag (gen-tag content)) style content))) - (define/kw (section #:key [tag #f] #:body str) + (define (section #:tag [tag #f] . str) (let ([content (decode-content str)]) (make-part-start 0 (or tag (gen-tag content)) content))) - (define/kw (subsection #:key [tag #f] #:body str) + (define (subsection #:tag [tag #f] . str) (let ([content (decode-content str)]) (make-part-start 1 (or tag (gen-tag content)) content))) - (define/kw (subsubsection #:key [tag #f] #:body str) + (define (subsubsection #:tag [tag #f] . str) (let ([content (decode-content str)]) (make-part-start 2 (or tag (gen-tag content)) content))) - (define/kw (subsubsub*section #:key [tag #f] #:body str) + (define (subsubsub*section #:tag [tag #f] . str) (let ([content (decode-content str)]) (make-paragraph (list (make-element 'bold content))))) @@ -50,7 +49,7 @@ (provide itemize item item?) - (define/kw (itemize #:body items) + (define (itemize . items) (let ([items (filter (lambda (v) (not (whitespace? v))) items)]) (for-each (lambda (v) (unless (an-item? v) @@ -63,7 +62,7 @@ (define-struct an-item (flow)) (define (item? x) (an-item? x)) - (define/kw (item #:body str) + (define (item . str) (make-an-item (decode-flow str))) ;; ---------------------------------------- @@ -77,28 +76,28 @@ (define (hspace n) (make-element 'hspace (list (make-string n #\space)))) - (define/kw (elem #:body str) + (define (elem . str) (make-element #f (decode-content str))) - (define/kw (aux-elem #:body s) + (define (aux-elem . s) (make-aux-element #f (decode-content s))) - (define/kw (italic #:body str) + (define (italic . str) (make-element 'italic (decode-content str))) - (define/kw (bold #:body str) + (define (bold . str) (make-element 'bold (decode-content str))) - (define/kw (tt #:body str) + (define (tt . str) (make-element 'tt (decode-content str))) - (define/kw (span-class classname #:body str) + (define (span-class classname . str) (make-element classname (decode-content str))) - (define/kw (subscript #:body str) + (define (subscript . str) (make-element 'subscript (decode-content str))) - (define/kw (superscript #:body str) + (define (superscript . str) (make-element 'superscript (decode-content str))) ;; ---------------------------------------- @@ -116,20 +115,20 @@ word-seq element-seq)) - (define/kw (index* word-seq content-seq #:body s) + (define (index* word-seq content-seq . s) (let ([key (gen-target)]) (record-index word-seq content-seq key (decode-content s)))) - (define/kw (index word-seq #:body s) + (define (index word-seq . s) (let ([word-seq (if (string? word-seq) (list word-seq) word-seq)]) (apply index* word-seq word-seq s))) - (define/kw (as-index #:body s) + (define (as-index . s) (let ([key (gen-target)] [content (decode-content s)]) (record-index (list (content->string content)) diff --git a/collects/scribble/doclang.ss b/collects/scribble/doclang.ss index ad6ee794fa..0d6199fc65 100644 --- a/collects/scribble/doclang.ss +++ b/collects/scribble/doclang.ss @@ -1,11 +1,11 @@ -(module doclang mzscheme +(module doclang (lib "new-lambda.ss" "scribblings") ; <--- temporary (require "struct.ss" "decode.ss" (lib "kw.ss")) (require-for-syntax (lib "kerncase.ss" "syntax")) - (provide (all-from-except mzscheme #%module-begin) + (provide (all-from-except (lib "new-lambda.ss" "scribblings") #%module-begin) (rename *module-begin #%module-begin)) ;; Module wrapper ---------------------------------------- diff --git a/collects/scribble/eval.ss b/collects/scribble/eval.ss index a31d011ef8..e4a660aaa9 100644 --- a/collects/scribble/eval.ss +++ b/collects/scribble/eval.ss @@ -26,7 +26,7 @@ scribble-eval-handler) - (define current-int-namespace (make-parameter (make-namespace))) + (define current-int-namespace (make-parameter (current-namespace))) (define scribble-eval-handler (make-parameter (lambda (c? x) (eval x)))) (define image-counter 0) @@ -108,17 +108,11 @@ #f))))))) (define (do-eval s) - (cond - [(and (list? s) - (eq? 'code:line (car s)) - (= (length s) 3) - (list? (caddr s)) - (eq? 'code:comment (caaddr s))) - (do-eval (cadr s))] - [(and (list? s) - (eq? 'eval:alts (car s)) - (= (length s) 3)) - (do-eval (caddr s))] + (syntax-case s (code:comment eval:alts) + [(code:line v (code:comment . rest)) + (do-eval #'v)] + [(eval:alts p e) + (do-eval #'e)] [else (let ([o (open-output-string)]) (parameterize ([current-output-port o]) @@ -160,17 +154,19 @@ v2)] [else v])) - (define (strip-comments s) - (cond - [(and (pair? s) - (pair? (car s)) - (eq? (caar s) 'code:comment)) - (strip-comments (cdr s))] - [(pair? s) - (cons (strip-comments (car s)) - (strip-comments (cdr s)))] - [(eq? s 'code:blank) (void)] - [else s])) + (define (strip-comments stx) + (syntax-case stx (code:comment code:blank) + [((code:comment . _) . rest) + (strip-comments #'rest)] + [(a . b) + (datum->syntax-object stx + (cons (strip-comments #'a) + (strip-comments #'b)) + stx + stx + stx)] + [code:blank #'(void)] + [else stx])) (define (do-plain-eval s catching-exns?) @@ -181,7 +177,7 @@ (syntax-rules () [(_ e) (#%expression (begin (parameterize ([current-command-line-arguments #()]) - (do-plain-eval (quote e) #f)) + (do-plain-eval (quote-syntax e) #f)) ""))])) @@ -193,7 +189,7 @@ (syntax-rules () [(_ e) (#%expression (parameterize ([current-command-line-arguments #()]) - (show-val (car (do-plain-eval (quote e) #f)))))])) + (show-val (car (do-plain-eval (quote-syntax e) #f)))))])) (define (eval-example-string s) (eval (read (open-input-string s)))) @@ -239,7 +235,7 @@ [(_ t schemeinput* e ...) (interleave t (list (schemeinput* e) ...) - (map do-eval (list (quote e) ...)))])) + (map do-eval (list (quote-syntax e) ...)))])) (define-syntax interaction (syntax-rules () diff --git a/collects/scribble/html-render.ss b/collects/scribble/html-render.ss index f629772215..35e94ce9aa 100644 --- a/collects/scribble/html-render.ss +++ b/collects/scribble/html-render.ss @@ -200,6 +200,11 @@ [(at-right) '((align "right"))] [(at-left) '((align "left"))] [else null]) + ,@(let ([a (and (list? (table-style t)) + (assoc 'style (table-style t)))]) + (if (and a (string? (cadr a))) + `((class ,(cadr a))) + null)) ,@(if (string? (table-style t)) `((class ,(table-style t))) null)) diff --git a/collects/scribble/manual.ss b/collects/scribble/manual.ss index aebaaa9b84..bf95ec17aa 100644 --- a/collects/scribble/manual.ss +++ b/collects/scribble/manual.ss @@ -1,12 +1,11 @@ -(module manual mzscheme +(module manual (lib "new-lambda.ss" "scribblings") (require "decode.ss" "struct.ss" "scheme.ss" "config.ss" "basic.ss" (lib "string.ss") - (lib "kw.ss") (lib "list.ss") (lib "class.ss")) @@ -46,7 +45,10 @@ (define (to-element/id s) (make-element "schemesymbol" (list (to-element/no-color s)))) - (define (keep-s-expr ctx s v) s) + (define (keep-s-expr ctx s v) + (if (symbol? s) + (make-just-context s ctx) + s)) (define (add-sq-prop s name val) (if (eq? name 'paren-shape) (make-shaped-parens s val) @@ -97,41 +99,41 @@ link procedure idefterm) - (define/kw (onscreen #:body str) + (define (onscreen . str) (make-element 'sf (decode-content str))) (define (menuitem menu item) (make-element 'sf (list menu "|" item))) - (define/kw (defterm #:body str) + (define (defterm . str) (make-element 'italic (decode-content str))) - (define/kw (idefterm #:body str) + (define (idefterm . str) (let ([c (decode-content str)]) (make-element 'italic c))) - (define/kw (schemefont #:body str) + (define (schemefont . str) (apply tt str)) - (define/kw (schemevalfont #:body str) + (define (schemevalfont . str) (make-element "schemevalue" (decode-content str))) - (define/kw (schemeresultfont #:body str) + (define (schemeresultfont . str) (make-element "schemeresult" (decode-content str))) - (define/kw (schemeidfont #:body str) + (define (schemeidfont . str) (make-element "schemesymbol" (decode-content str))) - (define/kw (schemeparenfont #:body str) + (define (schemeparenfont . str) (make-element "schemeparen" (decode-content str))) - (define/kw (schememetafont #:body str) + (define (schememetafont . str) (make-element "schememeta" (decode-content str))) - (define/kw (schemekeywordfont #:body str) + (define (schemekeywordfont . str) (make-element "schemekeyword" (decode-content str))) - (define/kw (file #:body str) + (define (file . str) (make-element 'tt (append (list "\"") (decode-content str) (list "\"")))) - (define/kw (exec #:body str) + (define (exec . str) (make-element 'tt (decode-content str))) - (define/kw (procedure #:body str) + (define (procedure . str) (make-element "schemeresult" (append (list "#")))) - (define/kw (link url #:body str) + (define (link url . str) (make-element (make-target-url url) (decode-content str))) (provide t) - (define/kw (t #:body str) + (define (t . str) (decode-paragraph str)) (provide schememodule) @@ -151,7 +153,7 @@ ;; ---------------------------------------- - (provide deftech tech) + (provide deftech tech techlink) (define (*tech make-elem style s) (let* ([c (decode-content s)] @@ -165,12 +167,15 @@ c (format "tech-term:~a" s)))) - (define/kw (deftech #:body s) + (define (deftech . s) (*tech make-target-element #f (list (apply defterm s)))) - (define/kw (tech #:body s) + (define (tech . s) (*tech make-link-element "techlink" s)) + (define (techlink . s) + (*tech make-link-element #f s)) + ;; ---------------------------------------- (provide defproc defproc* defstruct defthing defform defform* defform/subs defform*/subs defform/none @@ -218,21 +223,23 @@ (define-syntax defproc (syntax-rules () [(_ (id arg ...) result desc ...) - (*defproc '[(id arg ...)] + (*defproc (list (quote-syntax id)) + '[(id arg ...)] (list (list (lambda () (arg-contract arg)) ...)) (list (lambda () (schemeblock0 result))) (lambda () (list desc ...)))])) (define-syntax defproc* (syntax-rules () [(_ [[(id arg ...) result] ...] desc ...) - (*defproc '[(id arg ...) ...] + (*defproc (list (quote-syntax id) ...) + '[(id arg ...) ...] (list (list (lambda () (arg-contract arg)) ...) ...) (list (lambda () (schemeblock0 result)) ...) (lambda () (list desc ...)))])) (define-syntax defstruct (syntax-rules () [(_ name fields desc ...) - (*defstruct 'name 'fields (lambda () (list desc ...)))])) + (*defstruct (quote-syntax name) 'name 'fields (lambda () (list desc ...)))])) (define-syntax (defform*/subs stx) (syntax-case stx () [(_ #:literals (lit ...) [spec spec1 ...] ([non-term-id non-term-form ...] ...) desc ...) @@ -245,8 +252,11 @@ '(unsyntax x) #'name) #'rest) - #'spec)])]) - #'(*defforms #t '(lit ...) + #'spec)])] + [spec-id + (syntax-case #'spec () + [(name . rest) #'name])]) + #'(*defforms (quote-syntax spec-id) '(lit ...) '(spec spec1 ...) (list (lambda (x) (schemeblock0 new-spec)) (lambda (ignored) (schemeblock0 spec1)) ...) @@ -260,6 +270,7 @@ #'(fm #:literals () [spec spec1 ...] ([non-term-id non-term-form ...] ...) desc ...)])) (define-syntax (defform* stx) (syntax-case stx () + [(_ #:literals lits [spec ...] desc ...) #'(defform*/subs #:literals lits [spec ...] () desc ...)] [(_ [spec ...] desc ...) #'(defform*/subs [spec ...] () desc ...)])) (define-syntax (defform stx) (syntax-case stx () @@ -312,7 +323,7 @@ (define-syntax defthing (syntax-rules () [(_ id result desc ...) - (*defthing 'id 'result (lambda () (list desc ...)))])) + (*defthing (quote-syntax id) 'id 'result (lambda () (list desc ...)))])) (define-syntax schemegrammar (syntax-rules () [(_ #:literals (lit ...) id clause ...) (*schemegrammar '(lit ...) @@ -342,7 +353,7 @@ (list (make-table style content)))) (list (make-table style content)))) - (define (*defproc prototypes arg-contractss result-contracts content-thunk) + (define (*defproc stx-ids prototypes arg-contractss result-contracts content-thunk) (let ([spacer (hspace 1)] [has-optional? (lambda (arg) (and (pair? arg) @@ -378,7 +389,7 @@ (apply append (map - (lambda (prototype arg-contracts result-contract first?) + (lambda (stx-id prototype arg-contracts result-contract first?) (append (list (list (make-flow @@ -403,7 +414,7 @@ (make-target-element #f (list (to-element (car prototype))) - (register-scheme-definition (car prototype))) + (register-scheme-definition stx-id)) (to-element (car prototype)))) (map arg->elem required) (if (null? optional) @@ -449,25 +460,29 @@ [else null])) (cdr prototype) arg-contracts)))) + stx-ids prototypes arg-contractss result-contracts (cons #t (map (lambda (x) #f) (cdr prototypes)))))) (content-thunk)))))) - (define (make-target-element* content wrappers) + (define (make-target-element* stx-id content wrappers) (if (null? wrappers) content (make-target-element* + stx-id (make-target-element #f (list content) - (register-scheme-definition (string->symbol - (apply string-append - (map symbol->string (car wrappers)))))) + (register-scheme-definition + (datum->syntax-object stx-id + (string->symbol + (apply string-append + (map symbol->string (car wrappers))))))) (cdr wrappers)))) - (define (*defstruct name fields content-thunk) + (define (*defstruct stx-id name fields content-thunk) (define spacer (hspace 1)) (make-splice (cons @@ -481,6 +496,7 @@ (to-element `(,(schemeparenfont "struct") ,(make-target-element* + stx-id (to-element name) (let ([name (if (pair? name) (car name) @@ -515,7 +531,7 @@ fields))) (content-thunk)))) - (define (*defthing name result-contract content-thunk) + (define (*defthing stx-id name result-contract content-thunk) (define spacer (hspace 1)) (make-splice (cons @@ -528,19 +544,19 @@ (list (make-target-element #f (list (to-element name)) - (register-scheme-definition name)) + (register-scheme-definition stx-id)) spacer ":" spacer (to-element result-contract)))))))) (content-thunk)))) (define (meta-symbol? s) (memq s '(... ...+ ?))) - (define (*defforms kw? lits forms form-procs subs sub-procs content-thunk) + (define (*defforms kw-id lits forms form-procs subs sub-procs content-thunk) (parameterize ([current-variable-list (apply append (map (lambda (form) - (let loop ([form (cons (if kw? (cdr form) form) + (let loop ([form (cons (if kw-id (cdr form) form) subs)]) (cond [(symbol? form) (if (or (meta-symbol? form) @@ -568,22 +584,25 @@ (to-element `(,x . ,(cdr form))))))) - (and kw? + (and kw-id (eq? form (car forms)) (make-target-element #f - (list (to-element (car form))) - (register-scheme-form-definition (car form))))))))) + (list (to-element (make-just-context (car form) kw-id))) + (register-scheme-form-definition kw-id)))))))) forms form-procs) - (apply - append - (map (lambda (sub) - (list (list (make-flow (list (make-paragraph (list (tt 'nbsp)))))) - (list (make-flow (list (apply *schemerawgrammar - (map (lambda (f) (f)) sub))))))) - sub-procs)))) + (if (null? sub-procs) + null + (list (list (make-flow (list (make-paragraph (list (tt 'nbsp)))))) + (list (make-flow (list (let ([l (map (lambda (sub) + (map (lambda (f) (f)) sub)) + sub-procs)]) + (*schemerawgrammars + "specgrammar" + (map car l) + (map cdr l)))))))))) (content-thunk))))) - + (define (*specsubform form has-kw? lits form-thunk subs sub-procs content-thunk) (parameterize ([current-variable-list (append (let loop ([form (cons (if has-kw? (cdr form) form) @@ -610,41 +629,47 @@ (if form-thunk (form-thunk) (make-paragraph (list (to-element form))))))) - (apply - append - (map (lambda (sub) - (list (list (make-flow (list (make-paragraph (list (tt 'nbsp)))))) - (list (make-flow (list (apply *schemerawgrammar - (map (lambda (f) (f)) sub))))))) - sub-procs)))) + (if (null? sub-procs) + null + (list (list (make-flow (list (make-paragraph (list (tt 'nbsp)))))) + (list (make-flow (list (let ([l (map (lambda (sub) + (map (lambda (f) (f)) sub)) + sub-procs)]) + (*schemerawgrammars + "specgrammar" + (map car l) + (map cdr l)))))))))) (flow-paragraphs (decode-flow (content-thunk))))))) - (define (*schemerawgrammars nonterms clauseses) + (define (*schemerawgrammars style nonterms clauseses) (make-table - '((valignment baseline baseline baseline baseline baseline) - (alignment right left center left left)) + `((valignment baseline baseline baseline baseline baseline) + (alignment right left center left left) + (style ,style)) (let ([empty-line (make-flow (list (make-paragraph (list (tt 'nbsp)))))] [to-flow (lambda (i) (make-flow (list (make-paragraph (list i)))))]) - (apply append - (map - (lambda (nonterm clauses) - (cons - (list (to-flow nonterm) - empty-line - (to-flow "=") - empty-line - (make-flow (list (car clauses)))) - (map (lambda (clause) - (list empty-line - empty-line - (to-flow "|") - empty-line - (make-flow (list clause)))) - (cdr clauses)))) - nonterms clauseses))))) + (cdr + (apply append + (map + (lambda (nonterm clauses) + (list* + (list empty-line empty-line empty-line empty-line empty-line) + (list (to-flow nonterm) + empty-line + (to-flow "=") + empty-line + (make-flow (list (car clauses)))) + (map (lambda (clause) + (list empty-line + empty-line + (to-flow "|") + empty-line + (make-flow (list clause)))) + (cdr clauses)))) + nonterms clauseses)))))) - (define (*schemerawgrammar nonterm clause1 . clauses) - (*schemerawgrammars (list nonterm) (list (cons clause1 clauses)))) + (define (*schemerawgrammar style nonterm clause1 . clauses) + (*schemerawgrammars style (list nonterm) (list (cons clause1 clauses)))) (define (*schemegrammar lits s-expr clauseses-thunk) (parameterize ([current-variable-list @@ -657,7 +682,7 @@ (loop (cdr form)))] [else null]))]) (let ([l (clauseses-thunk)]) - (*schemerawgrammars (map car l) (map cdr l))))) + (*schemerawgrammars #f (map car l) (map cdr l))))) (define (*var id) (to-element (*var-sym id))) @@ -668,26 +693,26 @@ ;; ---------------------------------------- (provide centerline) - (define/kw (centerline #:body s) + (define (centerline . s) (make-table 'centered (list (list (make-flow (list (decode-paragraph s))))))) (provide commandline) - (define/kw (commandline #:body s) + (define (commandline . s) (make-paragraph (list (hspace 2) (apply tt s)))) (define (secref s) (make-link-element #f null `(part ,s))) - (define/kw (seclink tag #:body s) + (define (seclink tag . s) (make-link-element #f (decode-content s) `(part ,tag))) - (define/kw (*schemelink id #:body s) - (make-link-element #f (decode-content s) (register-scheme-definition id))) + (define (*schemelink stx-id id . s) + (make-link-element #f (decode-content s) (register-scheme-definition stx-id))) (define-syntax schemelink (syntax-rules () - [(_ id . content) (*schemelink 'id . content)])) + [(_ id . content) (*schemelink (quote-syntax id) 'id . content)])) (provide secref seclink schemelink) - (define/kw (pidefterm #:body s) + (define (pidefterm . s) (let ([c (apply defterm s)]) (index (string-append (content->string (element-content c)) "s") c))) @@ -707,7 +732,7 @@ ;; ---------------------------------------- (provide math) - (define/kw (math #:body s) + (define (math . s) (let ([c (decode-content s)]) (make-element #f (apply append (map (lambda (i) @@ -727,7 +752,7 @@ (provide cite) - (define/kw (cite #:key key title author location date) + (define (cite #:key key #:title title #:author author #:location location #:date date) "[...]" #; (make-bibliography-element diff --git a/collects/scribble/scheme.ss b/collects/scribble/scheme.ss index d2dcdc2384..d69d6b37a5 100644 --- a/collects/scribble/scheme.ss +++ b/collects/scribble/scheme.ss @@ -2,7 +2,8 @@ (require "struct.ss" "basic.ss" (lib "class.ss") - (lib "for.ss")) + (lib "for.ss") + (lib "modcollapse.ss" "syntax")) (provide define-code to-element @@ -17,7 +18,8 @@ current-variable-list current-meta-list - (struct shaped-parens (val shape))) + (struct shaped-parens (val shape)) + (struct just-context (val ctx))) (define no-color "schemeplain") (define reader-color "schemeplain") @@ -32,13 +34,12 @@ (define current-keyword-list ;; This is temporary, until the MzScheme manual is filled in... - (make-parameter '(require + (make-parameter null #;'(require provide new send else => and or define-syntax syntax-rules define-struct - quote quasiquote unquote unquote-splicing - syntax quasisyntax unsyntax unsyntax-splicing - set! set!-values))) + quasiquote unquote unquote-splicing + syntax quasisyntax unsyntax unsyntax-splicing))) (define current-variable-list (make-parameter null)) (define current-meta-list @@ -353,8 +354,8 @@ (not (or it? is-var?))) (make-delayed-element (lambda (renderer sec ht) - (let* ([vtag (register-scheme-definition (syntax-e c))] - [stag (register-scheme-form-definition (syntax-e c))] + (let* ([vtag (register-scheme-definition c)] + [stag (register-scheme-form-definition c)] [vd (hash-table-get ht vtag #f)] [sd (hash-table-get ht stag #f)]) (list @@ -431,7 +432,7 @@ (cond [(syntax? v) (let ([mk `(,#'d->s - #f + (quote-syntax ,v) ,(syntax-case v (uncode) [(uncode e) #'e] [else (stx->loc-s-expr (syntax-e v))]) @@ -463,11 +464,22 @@ [(_ code typeset-code) #'(define-code code typeset-code unsyntax)])) - (define (register-scheme-definition sym) - (format "definition:~s" sym)) + (define (register-scheme-definition stx) + (unless (identifier? stx) + (error 'register-scheme-definition "not an identifier: ~e" (syntax-object->datum stx))) + (format "definition:~s" + (let ([b (identifier-binding stx)]) + (cond + [(not b) (format "top:~a" (syntax-e stx))] + [(eq? b 'lexical) (format "lexical:~a" (syntax-e stx))] + [else (format "module:~a:~a" + (if (module-path-index? (car b)) + (collapse-module-path-index (car b) '(lib "ack.ss" "scribble")) + (car b)) + (cadr b))])))) - (define (register-scheme-form-definition sym) - (format "formdefinition:~s" sym)) + (define (register-scheme-form-definition stx) + (format "form~s" (register-scheme-definition stx))) (define syntax-ize-hook (make-parameter (lambda (v col) #f))) @@ -495,6 +507,7 @@ l)))) (define-struct shaped-parens (val shape)) + (define-struct just-context (val ctx)) (define (syntax-ize v col) (cond @@ -504,6 +517,13 @@ (syntax-property (syntax-ize (shaped-parens-val v) col) 'paren-shape (shaped-parens-shape v))] + [(just-context? v) + (let ([s (syntax-ize (just-context-val v) col)]) + (datum->syntax-object (just-context-ctx v) + (syntax-e s) + s + s + (just-context-ctx v)))] [(and (list? v) (pair? v) (memq (car v) '(quote unquote unquote-splicing))) diff --git a/collects/scribble/scribble.css b/collects/scribble/scribble.css index 04ba33ec7c..77e65b9560 100644 --- a/collects/scribble/scribble.css +++ b/collects/scribble/scribble.css @@ -184,6 +184,10 @@ background-color: #ddddff; } + .specgrammar { + float: right; + } + .hspace { font-family: Courier; font-size: 80%; } diff --git a/collects/scribblings/guide/class.scrbl b/collects/scribblings/guide/class.scrbl new file mode 100644 index 0000000000..d1397ce1f4 --- /dev/null +++ b/collects/scribblings/guide/class.scrbl @@ -0,0 +1,400 @@ +#reader(lib "docreader.ss" "scribble") +@require[(lib "manual.ss" "scribble")] +@require[(lib "eval.ss" "scribble")] +@require[(lib "class.ss")] +@require["guide-utils.ss"] + +@title[#:tag "classes"]{Classes and Objects} + +A @scheme[class] expression denotes a first-class value, +just like a @scheme[lambda] expression: + +@specform[(class superclass-expr decl-or-expr ...)] + +The @scheme[_superclass-expr] determines the superclass for the new +class. Each @scheme[_decl-or-expr] is either a declaration related to +methods, fields, and intialization arguments, or it is an expression +that is evaluated each time that the class is instantiated. In other +words, instead of a method-like constructor, a class has +initialization expressions interleaved with field and method +declarations. + +By convention, class names end with @schemeidfont{%}. The built-in root class is +@scheme[object%]. The following expression creates a class with +public methods @scheme[get-size], @scheme[grow], and @scheme[eat]: + +@schemeblock[ +(class object% + (init size) (code:comment #,(t "initialization argument")) + + (define current-size size) (code:comment #,(t "field")) + + (super-new) (code:comment #,(t "superclass initialization")) + + (define/public (get-size) + current-size) + + (define/public (grow amt) + (set! current-size (+ amt current-size))) + + (define/public (eat other-fish) + (grow (send other-fish get-size)))) +] + +@interaction-eval[ +(define fish% +(class object% + (init size) + (define current-size size) + (super-new) + (define/public (get-size) + current-size) + (define/public (grow amt) + (set! current-size (+ amt current-size))) + (define/public (eat other-fish) + (grow (send other-fish get-size)))))] + +The @scheme[size] initialization argument must be supplied via a named + argument when instantiating the class through the @scheme[new] form: + +@schemeblock[ +(new (class object% (init size) ...) [size 10]) +] + +Of course, we can also name the class and its instance: + +@schemeblock[ +(define fish% (class object% (init size) ...)) +(define charlie (new fish% [size 10])) +] + +@interaction-eval[(define charlie (new fish% [size 10]))] + +In the definition of @scheme[fish%], @scheme[current-size] is a +private field that starts out with the value of the @scheme[size] +initialization argument. Initialization arguments like @scheme[size] +are available only during class instantiation, so they cannot be +referenced directly from a method. The @scheme[current-size] field, in +contrast, is available to methods. + +The @scheme[(super-new)] expression in @scheme[fish%] invokes the +initialization of the superclass. In this case, the superclass is +@scheme[object%], which takes no initialization arguments and performs +no work; @scheme[super-new] must be used, anyway, because a class must +always invoke its superclass's initialization. + +Initialization arguments, field declarations, and expressions such as +@scheme[(super-new)] can appear in any order within a @scheme[class], +and they can be interleaved with method declarations. The relative +order of expressions in the class determines the order of evaluation +during instantiation. For example, if a field's initial value requires +calling a method that works only after superclass initialization, then +the field declaration is placed after the @scheme[super-new] +call. Ordering field and initialization declarations in this way helps +avoid imperative assignment. The relative order of method declarations +makes no difference for evaluation, because methods are fully defined +before a class is instantiated. + +@section[#:tag "guide:methods"]{Methods} + +Each of the three @scheme[define/public] declarations in +@scheme[fish%] introduces a new method. The declaration uses the same +syntax as a Scheme function, but a method is not accessible as an +independent function. A call to the @scheme[grow] method of a +@scheme[fish%] object requires the @scheme[send] form: + +@interaction[ +(send charlie grow 6) +(send charlie get-size) +] + +Within @scheme[fish%], self methods can be called like functions, +because the method names are in scope. For example, the @scheme[eat] +method within @scheme[fish%] directly invokes the @scheme[grow] +method. Within a class, attempting to use a method name in any way +other than a method call results in a syntax error. + +In some cases, a class must call methods that are supplied by the superclass +but not overridden. In that case, the class can use @scheme[send] +with @scheme[this] to access the method: + +@def+int[ +(define hungry-fish% (class fish% (super-new) + (define/public (eat-more fish1 fish2) + (send this eat fish1) + (send this eat fish2)))) +] + +Alternately, the class can declare the existence of a method using @scheme[inherit], +which brings the method name into scope for a direct call: + +@def+int[ +(define hungry-fish% (class fish% (super-new) + (inherit eat) + (define/public (eat-more fish1 fish2) + (eat fish1) (eat fish2)))) +] + +With the @scheme[inherit] declaration, if @scheme[fish%] had not +provided an @scheme[eat] method, an error would be signaled in the +evaluation of the @scheme[class] form for @scheme[hungry-fish%]. In +contrast, with @scheme[(send this ...)], an error would not be +signaled until the @scheme[eat-more] method is called and the +@scheme[send] form is evaluated. For this reason, @scheme[inherit] is +preferred. + +Another drawback of @scheme[send] is that it is less efficient than +@scheme[inherit]. Invocation of a method via @scheme[send] involves +finding a method in the target object's class at run time, making +@scheme[send] comparable to an interface-based method call in Java. In +contrast, @scheme[inherit]-based method invocations use an offset +within the class's method table that is computed when the class is +created. + +To achieve performance similar to @scheme[inherit]-based method calls when +invoking a method from outside the method's class, the programmer must use the +@scheme[generic] form, which produces a class- and method-specific +@defterm{generic method} to be invoked with @scheme[send-generic]: + +@def+int[ +(define get-fish-size (generic fish% get-size)) +(send-generic charlie get-fish-size) +(send-generic (new hungry-fish% [size 32]) get-fish-size) +(send-generic (new object%) get-fish-size) +] + +Roughly speaking, the form translates the class and the external +method name to a location in the class's method table. As illustrated +by the last example, sending through a generic method checks that its +argument is an instance of the generic's class. + +Whether a method is called directly within a @scheme[class], +through a generic method, +or through @scheme[send], method overriding works in the usual way: + +@defs+int[ +[ +(define picky-fish% (class fish% (super-new) + (define/override (grow amt) + ;; Doesn't eat all of its food + (super grow (* 3/4 amt))))) +(define daisy (new picky-fish% [size 20])) +] +(send daisy eat charlie) +(send daisy get-size) +] + +The @scheme[grow] method in @scheme[picky-fish%] is declared with +@scheme[define/override] instead of @scheme[define/public], because +@scheme[grow] is meant as an overriding declaration. If @scheme[grow] +had been declared with @scheme[define/public], an error would have +been signaled when evaluating the @scheme[class] expression, because +@scheme[fish%] already supplies @scheme[grow]. + +Using @scheme[define/override] also allows the invocation of the +overridden method via a @scheme[super] call. For example, the +@scheme[grow] implementation in @scheme[picky-fish%] uses +@scheme[super] to delegate to the superclass implementation. + +@section[#:tag "guide:initargs"]{Initialization Arguments} + +Since @scheme[picky-fish%] declares no initialization arguments, any +initialization values supplied in @scheme[(new picky-fish% ...)] are +propagated to the superclass initialization, i.e., to @scheme[fish%]. +A subclass can supply additional initialization arguments for its +superclass in a @scheme[super-new] call, and such initialization +arguments take precedence over arguments supplied to @scheme[new]. For +example, the following @scheme[size-10-fish%] class always generates +fish of size 10: + +@def+int[ +(define size-10-fish% (class fish% (super-new [size 10]))) +(send (new size-10-fish%) get-size) +] + +In the case of @scheme[size-10-fish%], supplying a @scheme[size] +initialization argument with @scheme[new] would result in an +initialization error; because the @scheme[size] in @scheme[super-new] +takes precedence, a @scheme[size] supplied to @scheme[new] would have +no target declaration. + +An initialization argument is optional if the @scheme[class] form +declares a default value. For example, the following @scheme[default-10-fish%] +class accepts a @scheme[size] initialization argument, but its value defaults to +10 if no value is supplied on instantiation: + +@def+int[ +(define default-10-fish% (class fish% + (init [size 10]) + (super-new [size size]))) +(new default-10-fish%) +(new default-10-fish% [size 20]) +] + +In this example, the @scheme[super-new] call propagates its own +@scheme[size] value as the @scheme[size] initialization argument to +the superclass. + +@section[#:tag "guide:intnames"]{Internal and External Names} + +The two uses of @scheme[size] in @scheme[default-10-fish%] expose the +double life of class-member identifiers. When @scheme[size] is the +first identifier of a bracketed pair in @scheme[new] or +@scheme[super-new], @scheme[size] is an @defterm{external name} that +is symbolically matched to an initialization argument in a class. When +@scheme[size] appears as an expression within +@scheme[default-10-fish%], @scheme[size] is an \defterm{internal name} +that is lexically scoped. Similarly, a call to an inherited +@scheme[eat] method uses @scheme[eat] as an internal name, whereas a +@scheme[send] of @scheme[eat] uses @scheme[eat] as an external name. + +The full syntax of the @scheme[class] form allows a programmer to +specify distinct internal and external names for a class member. Since +internal names are local, they can be renamed to avoid shadowing or +conflicts. Such renaming is not frequently necessary, but workarounds +in the absence of renaming can be especially cumbersome. + +@section{Interfaces} + +Interfaces are useful for checking that an object or a class +implements a set of methods with a particular (implied) behavior. +This use of interfaces is helpful even without a static type system +(which is the main reason that Java has interfaces). + +An interface in PLT Scheme is created using the @scheme[interface] +form, which merely declares the method names required to implement the +interface. An interface can extend other interfaces, which means that +implementations of the interface automatically implement the extended +interfaces. + +@specform[(interface (superinterface-expr ...) id ...)] + +To declare that a class implements an interface, the +@scheme[class*] form must be used instead of @scheme[class]: + +@specform[(class* superclass-expr (interface-expr ...) decl-or-expr ...)] + +For example, instead of forcing all fish classes to be derived from +@scheme[fish%], we can define @scheme[fish-interface] and change the +@scheme[fish%] class to declare that it implements +@scheme[fish-interface]: + +@schemeblock[ +(define fish-interface (interface () get-size grow eat)) +(define fish% (class* object% (fish-interface) ...)) +] + +If the definition of @scheme[fish%] does not include +@scheme[get-size], @scheme[grow], and @scheme[eat] methods, then an +error is signaled in the evaluation of the @scheme[class*] form, +because implementing the @scheme[fish-interface] interface requires +those methods. + +The @scheme[is-a?] predicate accepts either a class or interface as +its first argument and an object as its second argument. When given a +class, @scheme[is-a?] checks whether the object is an instance of that +class or a derived class. When given an interface, @scheme[is-a?] +checks whether the object's class implements the interface. In +addition, the @scheme[implementation?] predicate checks whether a +given class implements a given interface. + +@section[#:tag "guide:inner"]{Final, Augment, and Inner} + +As in Java, a method in a @scheme[class] form can be specified as +@defterm{final}, which means that a subclass cannot override the +method. A final method is declared using @scheme[public-final] or +@scheme[override-final], depending on whether the declaration is for a +new method or an overriding implementation. + +Between the extremes of allowing arbitrary overriding and disallowing +overriding entirely, the {class} system also supports Beta-style +@defterm{augmentable} methods~\cite{beta}. A method +declared with @scheme[pubment] is like @scheme[public], but the method +cannot be overridden in subclasses; it can be augmented only. A +@scheme[pubment] method must explicitly invoke an augmentation (if any) +using @scheme[inner]; a subclass augments the method using +@scheme[augment], instead of @scheme[override]. + +In general, a method can switch between augment and override modes in +a class derivation. The @scheme[augride] method specification +indicates an augmentation to a method where the augmentation is itself +overrideable in subclasses (though the superclass's implementation +cannot be overridden). Similarly, @scheme[overment] overrides a method +and makes the overriding implementation augmentable. Our earlier +work~\cite{Super+Inner} motivates and explains these extensions and +their interleaving. + +@section[#:tag "guide:extnames"]{Controlling the Scope of External Names} + +As noted in @secref["guide:intnames"], class members have both +internal and external names. A member definition binds an internal +name locally, and this binding can be locally renamed. External +names, in contrast, have global scope by default, and a member +definition does not bind an external name. Instead, a member +definition refers to an existing binding for an external name, where +the member name is bound to a @defterm{member key}; a class ultimately +maps member keys to methods, fields, and initialization arguments. + +Recall the @scheme[hungry-fish%] @scheme[class] expression: + +@schemeblock[ +(define hungry-fish% (class fish% ... + (inherit eat) + (define/public (eat-more fish1 fish2) + (eat fish1) (eat fish2)))) +] + +During its evaluation, the @scheme[hungry-fish%] and @scheme[fish%] +classes refer to the same global binding of @scheme[eat]. At run +time, calls to @scheme[eat] in @scheme[hungry-fish%] are matched with +the @scheme[eat] method in @scheme[fish%] through the shared method +key that is bound to @scheme[eat]. + +The default binding for an external name is global, but a +programmer can introduce an external-name binding with the +@scheme[define-member-name] form. + +@specform[(define-member-name id member-key-expr)] + +In particular, by using @scheme[(generate-member-key)] as the +@scheme[member-key-expr], an external name can be localized for a +particular scope, because the generated member key is inaccessible +outside the scope. In other words, @scheme[define-member-name] gives +an external name a kind of package-private scope, but generalized from +packages to arbitrary binding scopes in Scheme. + +For example, the following @scheme[fish%] and @scheme[pond%] classes cooperate +via a @scheme[get-depth] method that is only accessible to the +cooperating classes: + +@schemeblock[ +(define-values (fish% pond%) (code:comment #,(t "two mutually recursive classes")) + (let () ; create a local definition scope + (define-member-name get-depth (generate-member-key)) + (define fish% + (class ... (define my-depth ...) + (define my-pond ...) + (define/public (dive amt) + (set! my-depth + (min (+ my-depth amt) + (send my-pond get-depth)))))) + (define pond% + (class ... (define current-depth ...) + (define/public (get-depth) current-depth))) + (values fish% pond%))) +] + +External names are in a namespace that separates them from other Scheme +names. This separate namespace is implicitly used for the method name in +@scheme[send], for initialization-argument names in @scheme[new], or for +the external name in a member definition. The special +@scheme[member-name-key] provides access to the binding of an external name +in an arbitrary expression position: @scheme[(member-name-key id)] form +produces the member-key binding of @scheme[id] in the current scope. + +A member-key value is primarily used on with a +@scheme[define-member-name] form. Normally, then, +@scheme[(member-name-key id)] captures the method key of @scheme[id] +so that it can be communicated to a use of @scheme[define-member-name] +in a different scope. This capability turns out to be useful for +generalizing mixins (see \SecRef{sec:parammixins}). diff --git a/collects/scribblings/guide/define-struct.scrbl b/collects/scribblings/guide/define-struct.scrbl index 758653f9d3..435c1fba6b 100644 --- a/collects/scribblings/guide/define-struct.scrbl +++ b/collects/scribblings/guide/define-struct.scrbl @@ -133,8 +133,8 @@ To make a structure type @defterm{transparent}, use the field-name sequence: @def+int[ -'(define-struct posn (x y) - #:inspector #f) +(define-struct posn (x y) + #:inspector #f) (make-posn 1 2) ] diff --git a/collects/scribblings/guide/define.scrbl b/collects/scribblings/guide/define.scrbl index 4dcfb03978..fe8e47df44 100644 --- a/collects/scribblings/guide/define.scrbl +++ b/collects/scribblings/guide/define.scrbl @@ -2,8 +2,7 @@ @require[(lib "manual.ss" "scribble")] @require[(lib "eval.ss" "scribble")] @require["guide-utils.ss"] - -@interaction-eval[(require (lib "string.ss"))] +@require[(lib "string.ss")] @title{Definitions: @scheme[define]} diff --git a/collects/scribblings/guide/for.scrbl b/collects/scribblings/guide/for.scrbl index a2daa0ce5c..b1de88236e 100644 --- a/collects/scribblings/guide/for.scrbl +++ b/collects/scribblings/guide/for.scrbl @@ -2,8 +2,7 @@ @require[(lib "manual.ss" "scribble")] @require[(lib "eval.ss" "scribble")] @require["guide-utils.ss"] - -@interaction-eval[(require (lib "for.ss"))] +@require[(lib "for.ss")] @title[#:tag "guide:for"]{Iterations and Comprehensions} diff --git a/collects/scribblings/guide/guide-utils.ss b/collects/scribblings/guide/guide-utils.ss index 424712870b..eeb64b2a66 100644 --- a/collects/scribblings/guide/guide-utils.ss +++ b/collects/scribblings/guide/guide-utils.ss @@ -1,13 +1,10 @@ -(module guide-utils mzscheme +(module guide-utils (lib "new-lambda.ss" "scribblings") (require (lib "manual.ss" "scribble") (lib "struct.ss" "scribble") (lib "decode.ss" "scribble") (lib "kw.ss") (lib "eval.ss" "scribble")) - (interaction-eval (require (lib "new-lambda.ss" "scribblings"))) - - (provide Quick MzScheme HtDP tool refdetails @@ -26,7 +23,7 @@ (define (tool name . desc) (apply item (bold name) ", " desc)) - (define/kw (refdetails* tag what #:body s) + (define (refdetails* tag what . s) (apply margin-note (decode-content (append (list "For " what " on ") s @@ -34,10 +31,10 @@ (refsecref tag) "."))))) - (define/kw (refdetails tag #:body s) + (define (refdetails tag . s) (apply refdetails* tag "more" s)) - (define/kw (refdetails/gory tag #:body s) + (define (refdetails/gory tag . s) (apply refdetails* tag "gory details" s)) (define (refsecref s) diff --git a/collects/scribblings/guide/guide.scrbl b/collects/scribblings/guide/guide.scrbl index 01ea6f02ee..894f6e75fa 100644 --- a/collects/scribblings/guide/guide.scrbl +++ b/collects/scribblings/guide/guide.scrbl @@ -38,7 +38,7 @@ describes the acceptable arguments and the result of the procedure using @idefterm{contracts}. @; ---------------------------------------------------------------------- -@section[#:tag "classes"]{Classes and Objects} +@include-section["class.scrbl"] @; ---------------------------------------------------------------------- diff --git a/collects/scribblings/guide/let.scrbl b/collects/scribblings/guide/let.scrbl index 9f5d5dca60..14c9a11970 100644 --- a/collects/scribblings/guide/let.scrbl +++ b/collects/scribblings/guide/let.scrbl @@ -3,8 +3,6 @@ @require[(lib "eval.ss" "scribble")] @require["guide-utils.ss"] -@interaction-eval[(require (lib "file.ss"))] - @title{Local Binding} Although internal @scheme[define]s can be used for local binding, diff --git a/collects/scribblings/guide/lists.scrbl b/collects/scribblings/guide/lists.scrbl index d117516b5d..ed2e83c19b 100644 --- a/collects/scribblings/guide/lists.scrbl +++ b/collects/scribblings/guide/lists.scrbl @@ -3,9 +3,9 @@ @require[(lib "eval.ss" "scribble")] @require[(lib "bnf.ss" "scribble")] @require["guide-utils.ss"] +@require[(lib "list.ss")] +@require[(lib "for.ss")] -@interaction-eval[(require (lib "list.ss"))] -@interaction-eval[(require (lib "for.ss"))] @define[step @elem{=}] @title{Lists, Iteration, and Recursion} @@ -212,12 +212,12 @@ argument @scheme[len]: @schemeblock[ (define (my-length lst) - (code:comment #, @elem{local function @scheme[iter]:}) + (code:comment #, @t{local function @scheme[iter]:}) (define (iter lst len) (cond [(empty? lst) len] [else (iter (rest lst) (+ len 1))])) - (code:comment #, @elem{body of @scheme[my-length] calls @scheme[iter]:}) + (code:comment #, @t{body of @scheme[my-length] calls @scheme[iter]:}) (iter lst 0)) ] diff --git a/collects/scribblings/guide/pairs.scrbl b/collects/scribblings/guide/pairs.scrbl index fc01e2a0ca..81eb188130 100644 --- a/collects/scribblings/guide/pairs.scrbl +++ b/collects/scribblings/guide/pairs.scrbl @@ -2,9 +2,8 @@ @require[(lib "manual.ss" "scribble")] @require[(lib "eval.ss" "scribble")] @require["guide-utils.ss"] - -@interaction-eval[(require (lib "list.ss"))] -@interaction-eval[(define mutable-cons cons)] +@require[(lib "list.ss")] +@define[mutable-cons cons] @title{Pairs and Lists} diff --git a/collects/scribblings/guide/truth.scrbl b/collects/scribblings/guide/truth.scrbl index b9d2d2302e..1303ff2c2f 100644 --- a/collects/scribblings/guide/truth.scrbl +++ b/collects/scribblings/guide/truth.scrbl @@ -2,8 +2,7 @@ @require[(lib "manual.ss" "scribble")] @require[(lib "eval.ss" "scribble")] @require["guide-utils.ss"] - -@interaction-eval[(require (lib "list.ss"))] +@require[(lib "list.ss")] @title{Pairs, Lists, and Scheme Syntax} diff --git a/collects/scribblings/new-lambda.ss b/collects/scribblings/new-lambda.ss index 4dcc82aa29..9b6bcaa17e 100644 --- a/collects/scribblings/new-lambda.ss +++ b/collects/scribblings/new-lambda.ss @@ -1,15 +1,18 @@ (module new-lambda mzscheme (require-for-syntax (lib "name.ss" "syntax") (lib "define.ss" "syntax")) + (require "new-struct.ss") - (provide (all-from-except mzscheme #%datum lambda define #%app) + (provide (all-from-except mzscheme #%datum lambda define #%app define-struct) (rename new-datum #%datum) (rename new-lambda lambda) (rename new-define define) (rename new-app #%app) (rename *make-keyword-procedure make-keyword-procedure) keyword-apply - procedure-keywords) + procedure-keywords + (rename define-struct* define-struct) + struct-field-index) ;; ---------------------------------------- @@ -366,7 +369,7 @@ (make-optional-keyword-procedure with-kws null - '(kw ...) + 'kws no-kws))))] [else ;; just the keywords part dispatches to core, diff --git a/collects/scribblings/new-struct.ss b/collects/scribblings/new-struct.ss new file mode 100644 index 0000000000..7ef679961d --- /dev/null +++ b/collects/scribblings/new-struct.ss @@ -0,0 +1,413 @@ + +;; Based on +;; (planet "struct.ss" ("ryanc" "macros.plt" 1 0))) +;; though, strangely and embarassingly, Matthew didn't know that until +;; after he had mostly re-implemented it. + +(module new-struct mzscheme + (require (lib "stxparam.ss")) + + (provide define-struct* + struct-field-index) + + (define-syntax-parameter struct-field-index + (lambda (stx) + (raise-syntax-error #f "allowed only within a structure type definition" stx))) + + (define (check-struct-type name what) + (when what + (unless (struct-type? what) + (raise-type-error name "struct-type or #f" what))) + what) + + (define (check-inspector name what) + (when what + (unless (inspector? what) + (raise-type-error name "inspector or #f" what))) + what) + + (define-syntax (define-struct* stx) + (define make-field list) + (define field-id car) + (define field-default-value cadr) + (define field-auto? caddr) + (define field-immutable? cadddr) + + (define (struct-declaration-info? x) + (define (identifier/#f? x) + (or (not x) + (identifier? x))) + (define (id/#f-list? id? x) + (or (null? x) + (and (pair? x) + (if (null? (cdr x)) + (identifier/#f? (car x)) + (and (id? (car x)) + (id/#f-list? id? (cdr x))))))) + (and (list? x) + (= (length x) 6) + (identifier/#f? (car x)) + (identifier/#f? (cadr x)) + (identifier/#f? (caddr x)) + (id/#f-list? identifier? (list-ref x 3)) + (id/#f-list? identifier/#f? (list-ref x 4)) + (or (eq? #t (list-ref x 5)) (identifier/#f? (list-ref x 5))))) + + (define (build-name id . parts) + (datum->syntax-object + id + (string->symbol + (apply string-append + (map (lambda (p) + (if (syntax? p) + (symbol->string (syntax-e p)) + p)) + parts))) + id)) + + (define (bad why kw where) + (raise-syntax-error + #f + (format "~a ~a specification~a" + why + (syntax-e kw) + where) + stx + kw)) + + (define (check-exprs n ps) + (let loop ([nps (cdr ps)][n n]) + (unless (zero? n) + (unless (and (pair? nps) + (not (keyword? (syntax-e (car nps))))) + (raise-syntax-error + #f + (format "expected ~a expression~a after keyword~a" + n + (if (= n 1) "" "s") + (if (pair? nps) + ", found a keyword" + "")) + stx + (car ps))) + (loop (cdr nps) (sub1 n))))) + + ;; Parse one field with a sequence of keyword-based specs: + (define (parse-field f) + (syntax-case f () + [id + (identifier? #'id) + (make-field #'id #f #f #f)] + [(id p ...) + (identifier? #'id) + (let loop ([ps (syntax->list #'(p ...))] + [def-val #f] + [auto? #f] + [immutable? #f]) + (cond + [(null? ps) (make-field #'id def-val auto? immutable?)] + [(eq? #:immutable (syntax-e (car ps))) + (when immutable? + (bad "redundant" (car ps) " for field")) + (loop (cdr ps) def-val auto? #t)] + [(eq? #:default (syntax-e (car ps))) + (check-exprs 1 ps) + (when def-val + (bad "multiple" (car ps) " for field")) + (loop (cddr ps) (cadr ps) auto? immutable?)] + [(eq? #:auto (syntax-e (car ps))) + (when auto? + (bad "redundant" (car ps) " for field")) + (loop (cdr ps) def-val #t immutable?)] + [else + (raise-syntax-error + #f + (if (keyword? (syntax-e (car ps))) + "unrecognized field-specification keyword" + "expected a field-spefication keyword") + stx + (car ps))]))] + [_else + (raise-syntax-error + #f + "expected a field identifier or a parenthesized identifier and field-specification sequence" + stx + f)])) + + (define (lookup config s) + (cdr (assq s config))) + + (define (extend-config config s val) + (cond + [(null? config) (error 'struct "internal error: can't find config element: ~s" s)] + [(eq? (caar config) s) (cons (cons s val) (cdr config))] + [else (cons (car config) (extend-config (cdr config) s val))])) + + ;; Parse sequence of keyword-based struct specs + (define (parse-props p super-id) + (let loop ([p p] + [config '((#:super . #f) + (#:inspector . #f) + (#:auto-value . #f) + (#:props . ()) + (#:immutable . #f) + (#:guard . #f) + (#:omit-define-values . #f) + (#:omit-define-syntaxes . #f))]) + (cond + [(null? p) config] + [(eq? #:super (syntax-e (car p))) + (check-exprs 1 p) + (when (lookup config '#:super) + (bad "multiple" (car p) "")) + (when super-id + (raise-syntax-error + #f + (string-append + "#:super specification disallowed because a struct supertype id" + " was supplied with the struct type id") + stx + (car p))) + (loop (cddr p) + (extend-config config '#:super (cadr p)))] + [(memq (syntax-e (car p)) + '(#:inspector #:guard #:auto-value)) + (let ([key (syntax-e (car p))]) + (check-exprs 1 p) + (when (lookup config key) + (bad "multiple" (car p) "")) + (loop (cddr p) + (extend-config config key (cadr p))))] + [(eq? #:property (syntax-e (car p))) + (check-exprs 2 p) + (loop (cdddr p) + (extend-config config + '#:props + (cons (cons (cadr p) (caddr p)) + (lookup config '#:props))))] + [(memq (syntax-e (car p)) + '(#:immutable #:omit-define-values #:omit-define-syntaxes)) + (let ([key (syntax-e (car p))]) + (when (lookup config key) + (bad "redundant" (car p) "")) + (loop (cdr p) + (extend-config config key #t)))] + [else + (raise-syntax-error + #f + (if (keyword? (syntax-e (car p))) + "unrecognized struct-specification keyword" + "expected a struct-spefication keyword") + stx + (car p))]))) + + (syntax-case stx () + [(fm id (field ...) prop ...) + (let-values ([(id super-id) + (if (identifier? #'id) + (values #'id #f) + (syntax-case #'id () + [(id super-id) + (and (identifier? #'id) + (identifier? #'super-id)) + (values #'id #'super-id)] + [else + (raise-syntax-error + #f + (string-append + "expected an identifier for the struct type name, or a parenthesized sequence" + " with an identifier followed by the struct supertype identifier") + stx)]))]) + (let ([super-info + (and super-id + (let ([v (syntax-local-value super-id (lambda () #f))]) + (if (struct-declaration-info? v) + v + (raise-syntax-error + #f + (format "parent struct type not defined~a" + (if v + (format " (~a does not name struct type information)" + (syntax-e super-id)) + "")) + stx + super-id))))]) + (when (and super-info + (not (car super-info))) + (raise-syntax-error + #f + "no structure type descriptor available for supertype" + stx + super-id)) + (let* ([field-stxes (syntax->list #'(field ...))] + [fields (map parse-field field-stxes)] + [dup (check-duplicate-identifier (map field-id fields))]) + (when dup + (raise-syntax-error + #f + "duplicate field identifier" + stx + dup)) + (let ([auto-count + (let loop ([fields fields] [field-stxes field-stxes] [auto? #f]) + (cond + [(null? fields) 0] + [(field-auto? (car fields)) + (+ 1 (loop (cdr fields) (cdr field-stxes) #t))] + [auto? + (raise-syntax-error + #f + "non-auto field after an auto field disallowed" + stx + (car field-stxes))] + [else + (loop (cdr fields) (cdr field-stxes) #f)]))]) + (let-values ([(inspector super-expr props auto-val guard immutable? + omit-define-values? omit-define-syntaxes?) + (let ([config (parse-props (syntax->list #'(prop ...)) super-id)]) + (values (lookup config '#:inspector) + (lookup config '#:super) + (lookup config '#:props) + (lookup config '#:auto-value) + (lookup config '#:guard) + (lookup config '#:immutable) + (lookup config '#:omit-define-values) + (lookup config '#:omit-define-syntaxes)))]) + (when immutable? + (for-each (lambda (f f-stx) + (when (field-immutable? f) + (raise-syntax-error + #f + "redundant #:immutable specification in field" + stx + f-stx))) + fields field-stxes)) + (let ([struct: (build-name id "struct:" id)] + [make- (build-name id "make-" id)] + [? (build-name id id "?")] + [sels (map (lambda (f) + (build-name (field-id f) + id "-" (field-id f))) + fields)] + [sets (if immutable? + null + (let loop ([fields fields]) + (cond + [(null? fields) null] + [(field-immutable? (car fields)) + (loop (cdr fields))] + [else + (cons (build-name (field-id (car fields)) + "set-" + id + "-" + (field-id (car fields)) + "!") + (loop (cdr fields)))])))] + [super-struct: (if super-info + (or (car super-info) + (raise-syntax-error + #f + "no structure type descriptor available for supertype" + stx + super-id)) + (and super-expr + #`(check-struct-type 'fm #,super-expr)))]) + (let ([run-time-defns + (lambda () + (quasisyntax/loc stx + (define-values (#,struct: #,make- #,? #,@sels #,@sets) + (let-values ([(struct: make- ? -ref -set!) + (syntax-parameterize ([struct-field-index + (lambda (stx) + (syntax-case stx #,(map field-id fields) + #,@(let loop ([fields fields][pos 0]) + (cond + [(null? fields) null] + [else (cons #`[(_ #,(field-id (car fields))) #'#,pos] + (loop (cdr fields) (add1 pos)))])) + [(_ name) (raise-syntax-error #f "no such field" stx #'name)]))]) + (make-struct-type '#,id + #,super-struct: + #,(- (length fields) auto-count) + #,auto-count + #,auto-val + #,(if (null? props) + #'null + #`(list #,@(map (lambda (p) + #`(cons #,(car p) #,(cdr p))) + props))) + #,(if inspector + #`(check-inspector 'fm #,inspector) + #`(current-inspector)) + #f + '#,(let loop ([i 0] + [fields fields]) + (cond + [(null? fields) null] + [(or immutable? (field-immutable? (car fields))) + (cons i (loop (add1 i) (cdr fields)))] + [else (loop (add1 i) (cdr fields))])) + #,guard))]) + (values struct: make- ? + #,@(let loop ([i 0][fields fields]) + (if (null? fields) + null + (cons #`(make-struct-field-accessor -ref #,i '#,(field-id (car fields))) + (loop (add1 i) (cdr fields))))) + #,@(if immutable? + null + (let loop ([i 0][fields fields]) + (if (null? fields) + null + (if (field-immutable? (car fields)) + (loop (add1 i) (cdr fields)) + (cons #`(make-struct-field-mutator -set! #,i '#,(field-id (car fields))) + (loop (add1 i) (cdr fields))))))))))))] + [compile-time-defns + (lambda () + (let ([protect (lambda (sel) + (if (syntax-e sel) + #`(c (quote-syntax #,sel)) + sel))]) + (quasisyntax/loc stx + (define-syntaxes (#,id) + (let ([c (syntax-local-certifier)]) + (list-immutable + (c (quote-syntax #,struct:)) + (c (quote-syntax #,make-)) + (c (quote-syntax #,?)) + (list-immutable + #,@(map protect sels) + #,@(if super-info + (map protect (list-ref super-info 3)) + (if super-expr + '(#f) + null))) + (list-immutable + #,@(let loop ([fields fields][sets sets]) + (cond + [(null? fields) null] + [(or immutable? (field-immutable? (car fields))) + (cons #f (loop (cdr fields) sets))] + [else + (cons (protect (car sets)) + (loop (cdr fields) (cdr sets)))])) + #,@(if super-info + (map protect (list-ref super-info 4)) + (if super-expr + '(#f) + null))) + #,(if super-id + (protect super-id) + (if super-expr + #f + #t))))))))]) + (cond + [(and (not omit-define-values?) (not omit-define-syntaxes?)) + #`(begin #,(run-time-defns) #,(compile-time-defns))] + [omit-define-syntaxes? + (run-time-defns)] + [omit-define-values? + (compile-time-defns)] + [else #'(begin)]))))))))]))) diff --git a/collects/scribblings/quick/images/exprs.dat b/collects/scribblings/quick/images/exprs.dat index 47150f4df6..5cca28abc8 100644 --- a/collects/scribblings/quick/images/exprs.dat +++ b/collects/scribblings/quick/images/exprs.dat @@ -1,7 +1,3 @@ -(0 () 0 () () (c! require c! (c! lib c! "slideshow.ss" c! "slideshow"))) -(0 () 0 () () (void)) -(0 () 0 () () (c! require-for-syntax c! mzscheme)) -(0 () 0 () () (void)) (0 () 0 () () 5) (0 () 0 () () 5) (0 () 0 () () "art gallery") diff --git a/collects/scribblings/quick/images/img0.png b/collects/scribblings/quick/images/img0.png index 874a010aca..537837f5ba 100644 Binary files a/collects/scribblings/quick/images/img0.png and b/collects/scribblings/quick/images/img0.png differ diff --git a/collects/scribblings/quick/images/img1.png b/collects/scribblings/quick/images/img1.png index dad8e28ec9..297681fbbd 100644 Binary files a/collects/scribblings/quick/images/img1.png and b/collects/scribblings/quick/images/img1.png differ diff --git a/collects/scribblings/quick/images/img10.png b/collects/scribblings/quick/images/img10.png index 5df51e54d8..e23d216b85 100644 Binary files a/collects/scribblings/quick/images/img10.png and b/collects/scribblings/quick/images/img10.png differ diff --git a/collects/scribblings/quick/images/img11.png b/collects/scribblings/quick/images/img11.png index 9d03e68e45..3aa09ca83d 100644 Binary files a/collects/scribblings/quick/images/img11.png and b/collects/scribblings/quick/images/img11.png differ diff --git a/collects/scribblings/quick/images/img17.png b/collects/scribblings/quick/images/img17.png index 874a010aca..537837f5ba 100644 Binary files a/collects/scribblings/quick/images/img17.png and b/collects/scribblings/quick/images/img17.png differ diff --git a/collects/scribblings/quick/images/img18.png b/collects/scribblings/quick/images/img18.png index defc0a4349..be3efceeae 100644 Binary files a/collects/scribblings/quick/images/img18.png and b/collects/scribblings/quick/images/img18.png differ diff --git a/collects/scribblings/quick/images/img2.png b/collects/scribblings/quick/images/img2.png index 28da54b764..de2d21ac17 100644 Binary files a/collects/scribblings/quick/images/img2.png and b/collects/scribblings/quick/images/img2.png differ diff --git a/collects/scribblings/quick/images/img26.png b/collects/scribblings/quick/images/img26.png index 9978b1ec2d..fef6fc93fd 100644 Binary files a/collects/scribblings/quick/images/img26.png and b/collects/scribblings/quick/images/img26.png differ diff --git a/collects/scribblings/quick/images/img28.png b/collects/scribblings/quick/images/img28.png index e3e6e12afe..1c726f20ac 100644 Binary files a/collects/scribblings/quick/images/img28.png and b/collects/scribblings/quick/images/img28.png differ diff --git a/collects/scribblings/quick/images/img3.png b/collects/scribblings/quick/images/img3.png index dad8e28ec9..297681fbbd 100644 Binary files a/collects/scribblings/quick/images/img3.png and b/collects/scribblings/quick/images/img3.png differ diff --git a/collects/scribblings/quick/images/img4.png b/collects/scribblings/quick/images/img4.png index 28da54b764..de2d21ac17 100644 Binary files a/collects/scribblings/quick/images/img4.png and b/collects/scribblings/quick/images/img4.png differ diff --git a/collects/scribblings/quick/images/img5.png b/collects/scribblings/quick/images/img5.png index 8358c10bd4..d698655327 100644 Binary files a/collects/scribblings/quick/images/img5.png and b/collects/scribblings/quick/images/img5.png differ diff --git a/collects/scribblings/quick/images/img6.png b/collects/scribblings/quick/images/img6.png index defc0a4349..be3efceeae 100644 Binary files a/collects/scribblings/quick/images/img6.png and b/collects/scribblings/quick/images/img6.png differ diff --git a/collects/scribblings/quick/images/img7.png b/collects/scribblings/quick/images/img7.png index ab26eae849..7fae5c5642 100644 Binary files a/collects/scribblings/quick/images/img7.png and b/collects/scribblings/quick/images/img7.png differ diff --git a/collects/scribblings/quick/mred-doc.ss b/collects/scribblings/quick/mred-doc.ss new file mode 100644 index 0000000000..525cfa5561 --- /dev/null +++ b/collects/scribblings/quick/mred-doc.ss @@ -0,0 +1,18 @@ +(module mred-doc mzscheme + + (define mr-eval? (getenv "MREVAL")) + + (define-syntax bounce + (syntax-rules () + [(_ id) + (begin + (provide id) + (define id (if mr-eval? + (dynamic-require '(lib "mred.ss" "mred") 'id) + #f)))] + [(_ id ...) + (begin (bounce id) ...)])) + + (bounce frame% canvas% + bitmap% bitmap-dc% + color%)) diff --git a/collects/scribblings/quick/mreval.ss b/collects/scribblings/quick/mreval.ss index 5d35de1c95..d0d468445b 100644 --- a/collects/scribblings/quick/mreval.ss +++ b/collects/scribblings/quick/mreval.ss @@ -7,6 +7,8 @@ (lib "file.ss") (lib "runtime-path.ss") (lib "serialize.ss") + "slideshow-doc.ss" + "mred-doc.ss" (lib "exn.ss" "scribblings" "quick")) (define-syntax define-mr @@ -17,8 +19,7 @@ (define-syntax mr (syntax-rules () [(_ x (... ...)) - (parameterize ([scribble-eval-handler mr-eval-handler] - [current-int-namespace mr-namespace]) + (parameterize ([scribble-eval-handler mr-eval-handler]) (orig x (... ...)))])))])) (define-mr mr-interaction interaction) @@ -46,7 +47,7 @@ (let ([eh (scribble-eval-handler)] [log-file (open-output-file exprs-dat-file 'truncate/replace)]) (lambda (catching-exns? expr) - (write (serialize expr) log-file) + (write (serialize (syntax-object->datum expr)) log-file) (newline log-file) (flush-output log-file) (let ([result @@ -76,7 +77,7 @@ (if (eof-object? v) (error "expression not in log file") (let ([v (deserialize v)]) - (if (equal? v expr) + (if (equal? v (syntax-object->datum expr)) (let ([v (read log-file)]) (if (eof-object? v) (error "expression result missing in log file") @@ -91,50 +92,22 @@ expr v)))))))))) - (define mr-namespace - (if mred? - ((dynamic-require '(lib "mred.ss" "mred") 'make-namespace-with-mred)) - (let ([ns (make-namespace)]) - (namespace-attach-module (current-namespace) - '(lib "struct.ss" "scribble") - ns) - (namespace-attach-module (current-namespace) - '(lib "exn.ss" "scribblings" "quick") - ns) - ns))) + (define mr-namespace (current-namespace)) (define image-counter 0) - (define (ss:pict?) - (with-handlers ([exn:fail? (lambda (x) (lambda (x) #f))]) - (eval 'pict? mr-namespace))) - (define (ss:pict-width) - (eval 'pict-width mr-namespace)) - (define (ss:pict-height) - (eval 'pict-height mr-namespace)) - (define (ss:make-pict-drawer) - (eval 'make-pict-drawer mr-namespace)) - (define (ss:colorize) - (eval 'colorize mr-namespace)) - (define (mred:canvas%) - (dynamic-require '(lib "mred.ss" "mred") 'canvas%)) - (define (mred:bitmap%) - (dynamic-require '(lib "mred.ss" "mred") 'bitmap%)) - (define (mred:bitmap-dc%) - (dynamic-require '(lib "mred.ss" "mred") 'bitmap-dc%)) - (define (fixup-picts v) (cond - [((ss:pict?) v) + [(pict? v) (let ([fn (format "~a/img~a.png" img-dir image-counter)]) (set! image-counter (add1 image-counter)) - (let* ([bm (make-object (mred:bitmap%) - (inexact->exact (ceiling ((ss:pict-width) v))) - (inexact->exact (ceiling ((ss:pict-height) v))))] - [dc (make-object (mred:bitmap-dc%) bm)]) + (let* ([bm (make-object bitmap% + (inexact->exact (ceiling (pict-width v))) + (inexact->exact (ceiling (pict-height v))))] + [dc (make-object bitmap-dc% bm)]) (send dc set-smoothing 'aligned) (send dc clear) - (((ss:make-pict-drawer) v) dc 0 0) + ((make-pict-drawer (colorize v (make-object color% 0 0 #xAF))) dc 0 0) (send bm save-file fn 'png) (make-element #f (list (make-element (make-image-file fn) (list "[image]"))))))] [(pair? v) (cons (fixup-picts (car v)) diff --git a/collects/scribblings/quick/quick.scrbl b/collects/scribblings/quick/quick.scrbl index a82d36f93a..37cc0f1a34 100644 --- a/collects/scribblings/quick/quick.scrbl +++ b/collects/scribblings/quick/quick.scrbl @@ -7,9 +7,16 @@ @require[(lib "manual.ss" "scribble")] @require["mreval.ss"] @require[(lib "urls.ss" "scribble")] +@require[(lib "class.ss")] +@require["slideshow-doc.ss"] +@require["slideshow-code-doc.ss"] +@require["mred-doc.ss"] +@require-for-syntax[mzscheme] -@mr-interaction-eval[(require (lib "slideshow.ss" "slideshow"))] -@mr-interaction-eval[(require-for-syntax mzscheme)] +@define[filled-flash (lambda args (apply (eval 'filled-flash) args))] +@define[random-gaussian (lambda args (apply (eval 'random-gaussian) args))] +@define-syntax[code (syntax-rules () [(_ v) (typeset-code (quote-syntax v))])] +@provide[filled-flash random-gaussian code] @; ---------------------------------------------------------------------- @section{Why Pictures? Why DrScheme?} diff --git a/collects/scribblings/quick/slideshow-code-doc.ss b/collects/scribblings/quick/slideshow-code-doc.ss new file mode 100644 index 0000000000..3f8786fd0c --- /dev/null +++ b/collects/scribblings/quick/slideshow-code-doc.ss @@ -0,0 +1,18 @@ +(module slideshow-code-doc mzscheme + (require (only "slideshow-doc.ss")) + + (define mr-eval? (getenv "MREVAL")) + + (define-syntax bounce + (syntax-rules () + [(_ id) + (begin + (provide id) + (define id (if mr-eval? + (dynamic-require '(lib "code.ss" "slideshow") 'id) + #f)))] + [(_ id ...) + (begin (bounce id) ...)])) + + (bounce typeset-code)) + diff --git a/collects/scribblings/quick/slideshow-doc.ss b/collects/scribblings/quick/slideshow-doc.ss new file mode 100644 index 0000000000..9ee310e796 --- /dev/null +++ b/collects/scribblings/quick/slideshow-doc.ss @@ -0,0 +1,30 @@ +(module slideshow-doc mzscheme + + (define mr-eval? (getenv "MREVAL")) + + (when mr-eval? + (parameterize ([current-command-line-arguments #()]) + (dynamic-require '(lib "slideshow.ss" "slideshow") #f))) + + (define-syntax bounce + (syntax-rules () + [(_ id) + (begin + (provide id) + (define id (if mr-eval? + (dynamic-require '(lib "slideshow.ss" "slideshow") 'id) + #f)))] + [(_ id ...) + (begin (bounce id) ...)])) + + (bounce circle + rectangle + hc-append + filled-rectangle + vc-append + colorize + scale + bitmap + make-pict-drawer + + pict? pict-width pict-height)) diff --git a/collects/scribblings/reference/for.scrbl b/collects/scribblings/reference/for.scrbl index a9dec0dbb9..f2a8773d23 100644 --- a/collects/scribblings/reference/for.scrbl +++ b/collects/scribblings/reference/for.scrbl @@ -1,7 +1,6 @@ #reader(lib "docreader.ss" "scribble") @require["mz.ss"] - -@interaction-eval[(require (lib "for.ss"))] +@require[(lib "for.ss")] @title[#:tag "mz:for"]{Iterations and Comprehensions: @scheme[for], @scheme[for/list], ...} diff --git a/collects/scribblings/reference/model.scrbl b/collects/scribblings/reference/model.scrbl index fa873dc280..41f9365b66 100644 --- a/collects/scribblings/reference/model.scrbl +++ b/collects/scribblings/reference/model.scrbl @@ -497,11 +497,13 @@ forms. As a result, future references of the @tech{variable} always access the same @tech{location}. @;------------------------------------------------------------------------ -@section{Modules and Module-Level Variables} +@section[#:tag "mz:module-eval-model"]{Modules and Module-Level Variables} Most definitions in PLT Scheme are in modules. In terms of evaluation, a module is essentially a prefix on a defined name, so that different -modules can define the name. +modules can define the name. That is, a @deftech{module-level +variable} is like a @tech{top-level variable} from the perspective of +evaluation. One difference between a module an a top-level definition is that a module can be declared without instantiating its module-level @@ -621,7 +623,7 @@ is created) as all other threads. @;------------------------------------------------------------------------ @section{Parameters} -A @deftech{parameter} is essentially a derived concept in Scheme; they +@deftech{Parameters} are essentially a derived concept in Scheme; they are defined in terms of continuation marks and thread cells. However, parameters are also built in, in the sense that some primitive procedures consult parameter values. For example, the default output diff --git a/collects/scribblings/reference/mz.ss b/collects/scribblings/reference/mz.ss index c90783d8aa..c9f50a7165 100644 --- a/collects/scribblings/reference/mz.ss +++ b/collects/scribblings/reference/mz.ss @@ -5,8 +5,6 @@ (lib "decode.ss" "scribble") (lib "kw.ss")) - (interaction-eval (require (lib "new-lambda.ss" "scribblings"))) - (provide (all-from (lib "manual.ss" "scribble")) (all-from (lib "eval.ss" "scribble"))) diff --git a/collects/scribblings/reference/read.scrbl b/collects/scribblings/reference/read.scrbl index e7ee81691d..7c0390b741 100644 --- a/collects/scribblings/reference/read.scrbl +++ b/collects/scribblings/reference/read.scrbl @@ -19,8 +19,8 @@ Scheme's reader is a recursive-descent parser that can be configured through a @seclink["mz:readtables"]{readtable} and various other -@seclink["parameters"]{parameters}. This section describes the reader's -parsing when using the default readtable. +@tech{parameters}. This section describes the reader's parsing when +using the default readtable. Reading from a stream produces one @defterm{datum}. If the result datum is a compound value, then reading the datum typically requires @@ -28,7 +28,7 @@ the reader to call itself recursively to read the component data. The reader can be invoked in either of two modes: @scheme[read] mode, or @scheme[read-syntax] mode. In @scheme[read-syntax] mode, the result -is always a @seclink["stxobj"]{syntax object} that includes +is always a @techlink{syntax object} that includes source-location and (initially empty) lexical information wrapped around the sort of datum that @scheme[read] mode would produce. In the case of pairs, vectors, and boxes, morever, the content is also @@ -164,7 +164,7 @@ except that @litchar{.} by itself is never parsed as a symbol or character. A @as-index{@litchar{#%}} also starts a symbol. A successful number parse takes precedence over a symbol parse. -When the @scheme[read-case-sensitive] parameter is set to @scheme[#f], +When the @scheme[read-case-sensitive] @tech{parameter} is set to @scheme[#f], characters in the sequence that are not quoted by @litchar["|"] or @litchar["\\"] are first case-normalized. If the reader encounters @as-index{@litchar{#ci}}, @litchar{#CI}, @litchar{#Ci}, or @litchar{#cI}, @@ -202,7 +202,7 @@ which specifies its parsing as an exact or inexact number; see non-terminal names suggest, a number that has no exactness specifier and matches only @nunterm{inexact-number} is normally parsed as an inexact number, otherwise it is parsed as an excat number. If the -@scheme[read-decimal-as-inexact] parameter is set to @scheme[#f], then +@scheme[read-decimal-as-inexact] @tech{parameter} is set to @scheme[#f], then all numbers without an exactness specifier are instead parsed as exact. @@ -344,10 +344,10 @@ being parsed, then the @exnraise[exn:fail:read]. "(1 . 2 . 3)" ] -If the @scheme[read-square-bracket-as-paren] parameter is set to +If the @scheme[read-square-bracket-as-paren] @tech{parameter} is set to @scheme[#f], then when then reader encounters @litchar{[} and @litchar{]}, the @exnraise{exn:fail:read}. Similarly, If the -@scheme[read-curly-brace-as-paren] parameter is set to @scheme[#f], +@scheme[read-curly-brace-as-paren] @tech{parameter} is set to @scheme[#f], then when then reader encounters @litchar["{"] and @litchar["}"], the @exnraise{exn:fail:read}. @@ -701,7 +701,7 @@ external reader procedure and applies it to the current input stream. The reader recursively reads the next datum after @litchar{#reader}, and passes it to the procedure that is the value of the -@scheme[current-reader-guard] parameter; the result is used as a +@scheme[current-reader-guard] @tech{parameter}; the result is used as a module path. The module path is passed to @scheme[dynamic-require] with either @scheme['read] or @scheme['read-syntax] (depending on whether the reader is in @scheme[read] or @scheme[read-syntax] @@ -718,7 +718,7 @@ converted to one using @scheme[datum->syntax-object]. See also @secref["special-comments"] and @secref["recursive-reads"] for information on special-comment results and recursive reads. -If the @scheme[read-accept-reader] parameter is set to @scheme[#f], +If the @scheme[read-accept-reader] @tech{parameter} is set to @scheme[#f], then if the reader encounters @litchar{#reader}, the @exnraise[exn:fail:read]. diff --git a/collects/scribblings/reference/reader-example.ss b/collects/scribblings/reference/reader-example.ss index d20a175167..a64598ccd2 100644 --- a/collects/scribblings/reference/reader-example.ss +++ b/collects/scribblings/reference/reader-example.ss @@ -1,10 +1,9 @@ -(module reader-example mzscheme +(module reader-example (lib "new-lambda.ss" "scribblings") (require (lib "struct.ss" "scribble") (lib "decode.ss" "scribble") (lib "manual.ss" "scribble") (lib "scheme.ss" "scribble") - (lib "kw.ss") (lib "class.ss")) (provide reader-examples @@ -22,10 +21,9 @@ (define spacer (hspace 1)) - (define/kw (reader-examples #:key - [symbols? #t] - [example-note ""] - #:body strs) + (define (reader-examples #:symbols? [symbols? #t] + #:example-note [example-note ""] + . strs) (make-table #f (list @@ -125,7 +123,7 @@ (define (dispatch a . b) (list a (make-element #f (decode-content b)))) - (define/kw (metavar #:body s) + (define (metavar . s) (make-element 'italic (decode-content s))) (define (cilitchar s) diff --git a/collects/scribblings/reference/syntax-model.scrbl b/collects/scribblings/reference/syntax-model.scrbl index d869a01f74..0dcb43fe16 100644 --- a/collects/scribblings/reference/syntax-model.scrbl +++ b/collects/scribblings/reference/syntax-model.scrbl @@ -308,9 +308,9 @@ things: identifier (third case in the previous enumeration), and parsing continues.} - @item{A core syntactic form, which is parsed as described for each - form in @secref["mz:syntax"]. Parsing a core syntactic form - typically involves recursive parsing of sub-forms, and may + @item{A core @deftech{syntactic form}, which is parsed as described + for each form in @secref["mz:syntax"]. Parsing a core syntactic + form typically involves recursive parsing of sub-forms, and may introduce @tech{bindings} that determine the parsing of sub-forms.} @@ -340,7 +340,7 @@ contexts. The possible @tech{contexts} are as follows: @item{@deftech{internal-definition context} : in a nested context that allows both definitions and expressions.} - @item{@deftech{expression content} : in a context where only + @item{@deftech{expression context} : in a context where only expressions are allowed.} } @@ -440,10 +440,10 @@ be @tech{expand}ed (i.e. parsed) before it can be evaluated, and it is expanded at @tech{phase level} 1 instead of @tech{phase level} 0. The if resulting @scheme[value] is a procedure of one argument, then -is it used as a @deftech{transformer procedure}. The procedure is +is it used as a @deftech{syntax transformer}. The procedure is expected to accept a syntax object and return a syntax object. A use of the binding (at @tech{phase level} 0) triggers a call of the -@tech{transformer procedure} by the expander; see +@tech{syntax transformer} by the expander; see @secref["mz:expand-steps"]. Before the expander passes a @tech{syntax object} to a transformer, @@ -547,7 +547,7 @@ If the last expression form turns out to be a @scheme[define-values] or @scheme[define-syntaxes] form, expansion fails with a syntax error. @;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -@subsection{Module Phases} +@subsection[#:tag "mz:mod-parse"]{Module Phases} A @scheme[require] form not only introduces @tech{bindings} at expansion time, but also @deftech{visits} the referenced module when diff --git a/collects/scribblings/reference/syntax.scrbl b/collects/scribblings/reference/syntax.scrbl index def9593188..d9160b502a 100644 --- a/collects/scribblings/reference/syntax.scrbl +++ b/collects/scribblings/reference/syntax.scrbl @@ -50,6 +50,48 @@ Within such specifications, }} } +@;------------------------------------------------------------------------ +@section{Literals: @scheme[quote] and @scheme[#%datum]} + +@defform[(quote datum)]{ + +Produces a constant value corresponding to @scheme[datum] (i.e., the +actual representation of the program fragment) without its +@tech{lexical information} or source location. + +@examples[ +(eval:alts (#,(schemekeywordfont "quote") x) 'x) +(eval:alts (#,(schemekeywordfont "quote") (+ 1 2)) '(+ 1 2)) +] + +} + +@defform[(#%datum . datum)]{ + +Expands to @scheme[(#,(schemekeywordfont "quote") datum)]. See also @secref["mz:expand-steps"] +for information on how the expander introduces @schemeidfont{#%datum} +identifiers. + +@examples[ +(#%datum . 10) +(#%datum . x) +] +} + +@;------------------------------------------------------------------------ +@section{Expression Wrapper: @scheme[#%expression]} + +@defform[(#%expression expr)]{ + +Produces the same result as @scheme[expr]. The only use of +@scheme[#%expression] is to force the parsing of a form as an +expression. + +@examples[ +(#%expression (+ 1 2)) +(#%expression (define x 10)) +]} + @;------------------------------------------------------------------------ @section{Variable References and @scheme[#%top]} @@ -64,7 +106,7 @@ When the expander encounters an @scheme[id] that is not bound by a module-level or local binding, it converts the expression to @scheme[(#, @schemeidfont{#%top} . id)] giving @schemeidfont{#%top} the lexical context of the @scheme[id]; typically, that context refers to -@scheme[#%top]. +@scheme[#%top]. See also @secref["mz:expand-steps"]. @examples[ (define x 10) @@ -75,15 +117,31 @@ x @defform[(#%top . id)]{ -Refers to a top-level definition that could bind @scheme[id], -even if @scheme[id] has a local binding in its context. Such -references are disallowed anywhere within a @scheme[module] form. +Refers to a top-level definition that could bind @scheme[id], even if +@scheme[id] has a local binding in its context. Such references are +disallowed anywhere within a @scheme[module] form. See also +@secref["mz:expand-steps"] for information on how the expander +introduces @schemeidfont{#%top} identifiers. @examples[ (define x 12) (let ([x 5]) (#%top . x)) ]} +@;------------------------------------------------------------------------ +@section{Locations: @scheme[#%variable-reference]} + +@defform*[#:literals (#%top) + [(#%variable-reference id) + (#%variable-reference (#%top . id))]]{ + +Produces an opaque value representing the location of @scheme[id], +which must be bound as a @tech{top-level variable} or +@tech{module-level variable}. + +The result is useful only to low-level extensions; see +@secref["inside-mzscheme"].} + @;------------------------------------------------------------------------ @section[#:tag "mz:application"]{Procedure Applications and @scheme[#%app]} @@ -100,7 +158,8 @@ More precisely, the expander converts this form to @scheme[(#, the lexical context that is associated with the original form (i.e., the pair that combines @scheme[proc-expr] and its arguments). Typically, the lexical context of the pair indicates the -procedure-application @scheme[#%app] that is described next. +procedure-application @scheme[#%app] that is described next. See also +@secref["mz:expand-steps"]. @examples[ (+ 1 2) @@ -138,6 +197,9 @@ the @scheme[_keyword]s, and not their positions. The other @scheme[_arg-expr] values, in contrast, are associated with variables according to their order in the application form. +See also @secref["mz:expand-steps"] for information on how the +expander introduces @schemeidfont{#%app} identifiers. + @examples[ (#%app + 1 2) (#%app (lambda (x #:arg y) (list y x)) #:arg 2 1) @@ -442,8 +504,8 @@ using the @|cvt| meta-function defined as follows: At the top level, the top-level binding @scheme[id] is created after evaluating @scheme[expr], if it does not exist already, and the -top-level mapping of @scheme[id] (see @secref["mz:namespace"]) is set -to the binding at the same time. +top-level mapping of @scheme[id] (in the @techlink{namespace} linked +with the compiled definition) is set to the binding at the same time. @defexamples[ (define x 10) @@ -472,8 +534,9 @@ the @exnraise[exn:fail:contract]. At the top level, the top-level binding for each @scheme[id] is created after evaluating @scheme[expr], if it does not exist already, -and the top-level mapping of each @scheme[id] (see -@secref["mz:namespace"]) is set to the binding at the same time. +and the top-level mapping of each @scheme[id] (in the +@techlink{namespace} linked with the compiled definition) is set to +the binding at the same time. @defexamples[ (define-values () (values)) @@ -526,6 +589,42 @@ in tail position only if no @scheme[body]s are present. (printf "hi\n")) ]} +@;------------------------------------------------------------------------ +@section{Assignment: @scheme[set!] and @scheme[set!-values]} + +@defform[(set! id expr)]{ + +Evaluates @scheme[expr] and installs the result into the location for +@scheme[id], which must be bound as a local variable or defined as a +@tech{top-level variable} or @tech{module-level variable}. If +@scheme[id] refers to a @tech{top-level variable} that has not been +defined, the @exnraise[exn:fail:contract]. + +@defexamples[ +(define x 12) +(set! x (add1 x)) +x +(let ([x 5]) + (set! x (add1 x)) + x) +(set! i-am-not-defined 10) +]} + +@defform[(set!-values (id ...) expr)]{ + +Evaluates @scheme[expr], which must produce as many values as supplied +@scheme[id]s. The location of each @scheme[id] is filled wih to the +corresponding value from @scheme[expr] in the same way as for +@scheme[set!]. + +@examples[ +(let ([a 1] + [b 2]) + (set!-values (a b) (values b a)) + (list a b)) +]} + + @;------------------------------------------------------------------------ @section{Continuation Marks: @scheme[with-continuation-mark]} @@ -540,11 +639,196 @@ current continuation frame (see @secref["mz:contmarks"]), and then @section{Syntax Quoting: @scheme[quote-syntax]} @defform[(quote-syntax datum)]{ -Produces a syntax object that preserves - lexical and source-location information attached to @scheme[datum] - at expansion time. + +Produces a @tech{syntax object} that preserves the @tech{lexical +information} and source-location information attached to +@scheme[datum] at expansion time. @examples[ (syntax? (quote-syntax x)) ] -} \ No newline at end of file +} + +@;------------------------------------------------------------------------ +@section[#:tag "mz:require"]{Importing: @scheme[require], @scheme[require-for-syntax], @scheme[require-for-template]} + +@defform/subs[#:literals (only prefix all-except prefix-all-except rename lib file planet) + (require require-spec ...) + ([require-spec module-path + (only require-spec id-maybe-renamed ...) + (except require-spec id ...) + (prefix require-spec prefix-id) + (rename require-spec [orig-id bind-id] ...)] + [module-path id + rel-string + (lib rel-string) + (file string) + (planet rel-string (user-string pkg-string vers ...))] + [id-maybe-renamed id + [orig-id bind-id]] + [vers nat + (nat nat) + (= nat) + (+ nat) + (- nat)])]{ + +In a @tech{top-level context}, @scheme[require] instantiates modules +(see @secref["mz:module-eval-model"]). In a @tech{module context}, +@scheme[require] visits modules (see @secref["mz:mod-parse"]). In both +contexts, @scheme[require] introduces bindings into a @tech{namespace} +or a module (see @secref["mz:intro-binding"]). A @scheme[require] form +in a @tech{expression context} or @tech{internal-definition context} +is a syntax error. + +A @scheme[require-spec] designates a particular set of identifiers to +be bound in the importing context. Each identifier is mapped to a +particular export of a particular module; the identifier to bind may +be different from the symbolic name of the originally exported +identifier. + + @specsubform[module-path]{ Imports all exported bindings from the + named module, using the export identifier as the local identifiers.} + + @specsubform[#:literals (only) (only require-spec id-maybe-renamed ...)]{ + Like @scheme[require-spec], but constrained to those exports for + which the identifiers to bind match @scheme[id-maybe-renamed]: as + @scheme[id] or as @scheme[orig-id] in @scheme[[orig-id bind-id]]. If + the @scheme[id] of @scheme[orig-id] of any @scheme[id-maybe-renamed] + is not in the set that @scheme[require-spec] describes, a syntax + error is reported.} + + @specsubform[#:literals (except) (except require-spec id ...)]{ Like + @scheme[require-spec], but omitting those exports for which + @scheme[id]s are the identifiers to bind; if any @scheme[id] is not + in the set that @scheme[require-spec] describes, a syntax error is + reported.} + + @specsubform[#:literals (prefix) (prefix require-spec prefix-id)]{ + Like @scheme[require-spec], but adjusting each identifier to be bound + by prefixing it with @scheme[prefix-id].} + + @specsubform[#:literals (rename) + (rename require-spec [orig-id bind-id] ...)]{ + Like @scheme[require-spec], but replacing the identifier to + bind @scheme[orig-id] with @scheme[bind-id]; if any + @scheme[orig-id] is not in the set that @scheme[require-spec] + describes, a syntax error is reported.} + +A @scheme[module-path] identifies a module, either through a concrete +name in the form of an identifier, or through an indirect name that +can trigger automatic loading of the module declaration: + + @specsubform[id]{ Refers to a module previously declared with the name + @scheme[id].} + + @specsubform[rel-string]{A path relative to the containing source (as + determined by @scheme[current-load-relative-directory] or + @scheme[current-directory]). Regardless of the current platform, + @scheme[rel-string] is always parsed as a Unix-format relative path: + @litchar{/} is the path delimiter (multiple adjacent @litchar{/}s are + treated as a single delimiter), @litchar{..} accesses the parent + directory, and @litchar{.} accesses the current directory. The path + cannot be empty or contain a leading or trailing slash.} + + @specsubform[#:literals (lib) (lib rel-string)]{Like the plain + @scheme[rel-string] case, but @scheme[rel-string] must contain at + least two path elements. All path elements up to the last one form a + @tech{collection} path, which is used to locate the relevant + directory (not relative to the containing source), and the last path + element refers to a file.} + + @specsubform[#:literals (file) (file string)]{Similar to the plain + @scheme[rel-string] case, but @scheme[string] is a path (possibly + absolute) using the current platform's path conventions.} + + @specsubform[#:literals(planet) + (planet rel-string (user-string pkg-string vers ...))]{ + Specifies a library available via the @PLaneT server. + } + +No identifier can be bound multiple times by an import, unless all of +the bindings refer to the same original definition in the same module. +In a @tech{module context}, an identifier can be either imported or +defined for a given @tech{phase level}, but not both.} + +@defform[(require-for-syntax require-spec ...)]{ +Like @scheme[require], but @tech{instantiate}s a module at phase 1 +(see @secref["mz:module-eval-model"]) in a @tech{top-level context} or +@tech{module context}, and introduces bindings at phase level 1 (see +@secref["mz:intro-binding"] and @secref["mz:mod-parse"]). +} + +@defform[(require-for-template require-spec ...)]{ Like +@scheme[require], but without @tech{instantiation} (see +@secref["mz:module-eval-model"]) in a @tech{top-level context}, and +introduces bindings at phase level -1 (see @secref["mz:intro-binding"] +and @secref["mz:mod-parse"]). +} + +@;------------------------------------------------------------------------ +@section{Exporting: @scheme[provide] and @scheme[provide-for-syntax]} + +@defform/subs[#:literals (protect all-defined all-from rename except prefix) + (provide protected-provide-spec ...) + ([protected-provide-spec provide-spec + (protect provide-spec)] + [provide-spec id + (all-defined) + (all-from module-name) + (rename [orig-id export-id] ...) + (except provide-spec id ...) + (prefix provide-spec prefix-id)])]{ + +Declares exports from a module. A @scheme[provide] form must appear in +a @tech{module context} or a @tech{module-begin} context. + +A @scheme[provide-spec] indicates one or more bindings to provide, +specifying for each an export symbol that can be different from +the symbolic form of the identifier bound within the module: + + @specsubform[id]{ Exports @scheme[id], which must be @tech{bound} + within the module (i.e., either defined or imported), at @tech{phase + level} 0 using the symbolic form of @scheme[id] as the external + name.} + + @specsubform[#:literals (all-defined) (all-defined)]{ Exports all + identifiers that are defined at @tech{phase level} 0 within the + exporting module. The external name for each identifier is the + symbolic form of the identifier; note that this can lead to an + illegal multiple export for a single symbolic name if different + defined identifiers use the same symbolic name.} + + @specsubform[#:literals (all-from) (all-from module-name)]{ Exports + all identifiers that are imported into the exporting module at + @tech{phase level} 0 using a @scheme[require-spec] built on + @scheme[module-name] (see @secref["mz:require"]). The symbolic name + for export is derived from the name that is bound within the module, + as opposed to the symbolic name of the export from + @scheme[module-name].} + + @specsubform[#:literals (rename) (rename [orig-id export-id] ...)]{ + Exports each @scheme[orig-id], which must be @tech{bound} within the + module at @tech{phase level} 0. The symbolic name for each export is + @scheme[export-id] instead @scheme[orig-d].} + + @specsubform[#:literals (except) (except provide-spec id ...)]{ Like + @scheme[provide-spec], but omitting an export for each binding + @scheme[id]. If @scheme[id] is not specified as an export by + @scheme[provide-spec], a syntax error is reported.} + + @specsubform[#:literals (prefix) (prefix provide-spec prefix-id)]{ + Like @scheme[provide-spec], but with each symbolic export name from + @scheme[provide-spec] prefixed with @scheme[prefix-id].} + +If @scheme[provide] wraps a @scheme[provide-spec], then the exports of +the @scheme[provide-spec] are protected; see +@secref["mz:protected-exports"]. The @scheme[provide-spec] must +specify only bindings that are defined within the exporting module. + +Each export specified within a module must have a distinct symbolic +export name, though the same binding can be specified with the +multiple symbolic names.} + +@defform[(provide-for-syntax protected-provide-spec ...)]{Like +@scheme[provide], but exports at @tech{phase level} 1 bindings within +the module at @tech{phase level} 1.} diff --git a/collects/scribblings/scribble/eval.scrbl b/collects/scribblings/scribble/eval.scrbl index 37ceb7897b..d168f35857 100644 --- a/collects/scribblings/scribble/eval.scrbl +++ b/collects/scribblings/scribble/eval.scrbl @@ -10,24 +10,24 @@ especially to show example uses of defined procedures and syntax. @defform[(interaction datum ...)]{Like @scheme[schemeinput], except that the result for each input @scheme[datum] is shown on the next -line. The result is determined by evaluating the quoted form of the -datum. +line. The result is determined by evaluating the syntax-quoted form of +the @scheme[datum]. Uses of @scheme[code:comment] and @schemeidfont{code:blank} are stipped from each @scheme[datum] before evaluation. -If a datum has the form @scheme[(#,(scheme code:line) #,(svar datum) -(#,(scheme code:comment) ...))], then only the @svar[datum] is -evaluated. +If a @scheme[datum] has the form @scheme[(#,(scheme code:line) +_code-datum (#,(scheme code:comment) ...))], then only +@scheme[_code-datum] is evaluated. If a datum has the form @scheme[(eval:alts #,(svar show-datum) #,(svar eval-datum))], then @svar[show-datum] is typeset, while @svar[eval-datum] is evaluated.} -@defform[(interaction-eval datum)]{Evaluates the quoted form of +@defform[(interaction-eval datum)]{Evaluates the syntax-quoted form of each @scheme[datum] via @scheme[do-eval] and returns the empty string.} -@defform[(interaction-eval-show datum)]{Evaluates the quoted form of +@defform[(interaction-eval-show datum)]{Evaluates the syntax-quoted form of @scheme[datum] and produces an element represeting the printed form of the result.} diff --git a/collects/scribblings/scribble/manual.scrbl b/collects/scribblings/scribble/manual.scrbl index 16d791dd5c..7b5745e92c 100644 --- a/collects/scribblings/scribble/manual.scrbl +++ b/collects/scribblings/scribble/manual.scrbl @@ -14,7 +14,7 @@ more... @defform[(schemeblock datum ...)]{ Typesets the @scheme[datum] sequence as a table of Scheme code inset -by two spaces. The source locations of the @scheme[datum]s determines +by two spaces. The source locations of the @scheme[datum]s determine the generated layout. For example, @schemeblock[ @@ -32,10 +32,13 @@ produces the output with the @scheme[(loop (not x))] indented under @scheme[define], because that's the way it is idented the use of @scheme[schemeblock]. + Furthermore, @scheme[define] is typeset as a keyword (bold and black) and as a hyperlink to @scheme[define]'s definition in the reference manual, because this document was built using information about the -MzScheme manual. Similarly, @scheme[not] is a hyperlink to the its +reference manual, and because the lexical binding of @scheme[define] +(in the source) matches the lexical binding of the definition in the +reference manual. Similarly, @scheme[not] is a hyperlink to the its definition in the reference manual. Use @scheme[unsyntax] to escape back to an expression that produces an @@ -127,7 +130,7 @@ useful with @scheme[verbatim].} @defproc[(schemefont [pre-content any/c] ...) element?]{Typesets the given content as uncolored, unhyperlinked Scheme. This procedure is useful -for typesetting thngs like @scheme{#module}, which are not +for typesetting things like @scheme{#module}, which are not @scheme[read]able by themselves.} @defproc[(schemevalfont [pre-content any/c] ...) element?]{Like @@ -143,7 +146,7 @@ for typesetting thngs like @scheme{#module}, which are not @scheme[schemefont], but colored as a syntactic form name.} @defproc[(procedure [pre-content any/c] ...) element?]{Typesets the given -content as a procedure name in a REPL result (e.g., in typewrite font +content as a procedure name in a REPL result (e.g., in typewriter font with a @schemefont{#} suffix.).} @defform[(var datum)]{Typesets @scheme[var] as an identifier that is @@ -164,9 +167,9 @@ in a form definition.} pre-flow ...)]{ Produces a sequence of flow elements (encaptured in a @scheme[splice]) -to document a procedure named @scheme[id]. The -@scheme[id] is registered so that @scheme[scheme]-typeset uses -of the identifier are hyperlinked to this documentation. +to document a procedure named @scheme[id]. The @scheme[id] is +registered so that @scheme[scheme]-typeset uses of the identifier +(with the same lexical binding) are hyperlinked to this documentation. Each @scheme[arg-spec] must have one of the following forms: @@ -213,39 +216,54 @@ Like @scheme[defproc], but for multiple cases with the same @scheme[id]. } -@defform[(defform (id . datum) pre-flow ...)]{Produces a -a sequence of flow elements (encaptured in a @scheme[splice]) to -document a syntatic form named by @scheme[id]. The -@scheme[id] is registered so that @scheme[scheme]-typeset uses -of the identifier are hyperlinked to this documentation. +@defform/subs[(defform maybe-literals (id . datum) pre-flow ...) + ([maybe-literals code:blank + (code:line #:literals (literal-id ...))])]{ + +Produces a a sequence of flow elements (encaptured in a +@scheme[splice]) to document a syntatic form named by @scheme[id]. The +@scheme[id] is registered so that @scheme[scheme]-typeset uses of the +identifier (with the same lexical binding) are hyperlinked to this +documentation. The @scheme[pre-flow]s list is parsed as a flow that documents the procedure. In this description, a reference to any identifier in -@scheme[datum] is typeset as a sub-form non-terminal. +@scheme[datum] is typeset as a sub-form non-terminal. If +@scheme[#:literals] clause is provided, however, instances of the +@scheme[literal-id]s are typeset normally. The typesetting of @scheme[(id . datum)] preserves the source layout, like @scheme[schemeblock], and unlike @scheme[defproc].} -@defform[(defform* [(id . datum) ..+] pre-flow ...)]{Like @scheme[defform], -but for multiple forms using the same @scheme[id].} +@defform[(defform* maybe-literals [(id . datum) ..+] pre-flow ...)]{ -@defform[(defform/subs (id . datum) - ([nonterm-id clause-datum ...+] ...) - pre-flow ...)]{ +Like @scheme[defform], but for multiple forms using the same +@scheme[id].} + +@defform/subs[(defform/subs maybe-literals (id . datum) + ([nonterm-id clause-datum ...+] ...) + pre-flow ...) + ([maybe-literals code:blank + (code:line #:literals (literal-id ...))])]{ Like @scheme[defform], but including an auxiliary grammar of non-terminals shown with the @scheme[id] form. Each @scheme[nonterm-id] is specified as being any of the corresponding @scheme[clause-datum]s, where the formatting of each @scheme[clause-datum] is preserved.} -@defform[(specform (id . datum) pre-flow ...)]{Like @scheme[defform], -with without registering a definition, and with indenting on the left -for both the specification and the @scheme[pre-flow]s.} +@defform/subs[(specform maybe-literals (id . datum) pre-flow ...) + ([maybe-literals code:blank + (code:line #:literals (literal-id ...))])]{ -@defform[(specsubform datum pre-flow ...)]{Similar to -@scheme[defform], but without any specific identifier being defined, -and the table and flow are typeset indented. This form is intended for -use when refining the syntax of a non-terminal used in a +Like @scheme[defform], with without registering a definition, and with +indenting on the left for both the specification and the +@scheme[pre-flow]s.} + +@defform[(specsubform maybe-literals datum pre-flow ...)]{ + +Similar to @scheme[defform], but without any specific identifier being +defined, and the table and flow are typeset indented. This form is +intended for use when refining the syntax of a non-terminal used in a @scheme[defform] or other @scheme[specsubform]. For example, it is used in the documentation for @scheme[defproc] in the itemization of possible shapes for @svar[arg-spec]. @@ -254,8 +272,9 @@ The @scheme[pre-flow]s list is parsed as a flow that documents the procedure. In this description, a reference to any identifier in @scheme[datum] is typeset as a sub-form non-terminal.} -@defform[(defthing id contract-expr-datum pre-flow ...)]{Like -@scheme[defproc], but for a non-procedure binding.} +@defform[(defthing id contract-expr-datum pre-flow ...)]{ + +Like @scheme[defproc], but for a non-procedure binding.} @defform/subs[(defstruct struct-name ([field-name contract-expr-datum] ...) pre-flow ...) @@ -265,13 +284,19 @@ procedure. In this description, a reference to any identifier in Similar to @scheme[defform] or @scheme[defproc], but for a structure definition.} -@defform/subs[(schemegrammar literals ? id clause-datum ...+) - ([literals (code:line #:literals (literal-id ...))])]{ -Creates a table to define the grammar of @scheme[id]. Each identifier mentioned -in a @scheme[clause-datum] is typeset as a non-terminal, except for the -identifiers listed as @scheme[literal-id]s, which are typeset as with -@scheme[scheme]. -} +@defform/subs[(schemegrammar maybe-literals id clause-datum ...+) + ([maybe-literals code:blank + (code:line #:literals (literal-id ...))])]{ + +Creates a table to define the grammar of @scheme[id]. Each identifier +mentioned in a @scheme[clause-datum] is typeset as a non-terminal, +except for the identifiers listed as @scheme[literal-id]s, which are +typeset as with @scheme[scheme].} + +@defform[(schemegrammar* maybe-literals [id clause-datum ...+] ...)]{ + +Like @scheme[schemegrammar], but for typesetting multiple productions +at once, aligned around the @litchar{=} and @litchar{|}.} @; ------------------------------------------------------------------------ @section{Various String Forms}