diff --git a/collects/graphics/scribblings/info.ss b/collects/graphics/scribblings/info.ss index 2e73e7db75..ab0a8ebe52 100644 --- a/collects/graphics/scribblings/info.ss +++ b/collects/graphics/scribblings/info.ss @@ -2,3 +2,4 @@ (define name "Graphics documentation") (define scribblings '(("graphics.scrbl" (multi-page)))) +(define doc-categories '(legacy)) diff --git a/collects/mzlib/async-channel.ss b/collects/mzlib/async-channel.ss index 6ae4bff9d7..0b360c232f 100644 --- a/collects/mzlib/async-channel.ss +++ b/collects/mzlib/async-channel.ss @@ -1,164 +1,4 @@ +#lang scheme/base -(module async-channel mzscheme - (require (lib "etc.ss") - (lib "contract.ss")) - - ;; This library implements buffered channels with - ;; and optional buffer limit (so that puts block - ;; if the buffer is full). - - ;; We make a fancy structure just so an async-channel - ;; can be supplied directly to `sync'. - ;; The alternative is to use `define-struct' and supply - ;; a `async-channel-get-evt' procedure. - (define-values (struct:ac make-ac async-channel? ac-ref ac-set!) - (make-struct-type 'async-channel #f 5 0 #f - (list (cons prop:evt - ;; This is the guard that is called when - ;; we use an async-channel as an event - ;; (to get). - (lambda (ac) - (async-channel-get-guard ac)))) - (current-inspector) #f)) - (define ac-enqueue-ch (make-struct-field-accessor ac-ref 0)) - (define ac-dequeue-ch (make-struct-field-accessor ac-ref 1)) - (define ac-empty-ch (make-struct-field-accessor ac-ref 2)) - (define ac-full-ch (make-struct-field-accessor ac-ref 3)) - (define ac-thread (make-struct-field-accessor ac-ref 4)) - - ;; Make ---------------------------------------- - - (define make-async-channel - (opt-lambda ([limit #f]) - (let* ([enqueue-ch (make-channel)] ; for puts - [dequeue-ch (make-channel)] ; for gets - [empty-ch (make-channel)] ; for get polls - [full-ch (make-channel)] ; for put polls - [queue-first (mcons #f null)] ; queue head - [queue-last queue-first] ; queue tail - [size 0] ; queue size - ;; Events: - [tell-empty - (channel-put-evt empty-ch (make-semaphore))] ; see poll->ch - [tell-full - (channel-put-evt full-ch (make-semaphore))] ; see poll->ch - [enqueue (handle-evt - enqueue-ch - (lambda (v) - ;; We received a put; enqueue it: - (let ([p (mcons #f null)]) - (set-mcar! queue-last v) - (set-mcdr! queue-last p) - (set! queue-last p) - (set! size (add1 size)))))] - [mk-dequeue - (lambda () - (handle-evt - (channel-put-evt dequeue-ch (mcar queue-first)) - (lambda (ignored) - ;; A get succeeded; dequeue it: - (set! size (sub1 size)) - (set! queue-first (mcdr queue-first)))))] - [manager-thread - ;; This thread is the part that makes the channel asynchronous. - ;; It waits for a combination of gets and puts as appropriate. - ;; Note that we start it with `thread/suspend-kill', and we - ;; resume the manager thread with the current thread everytime - ;; we want to talk to the manager thread, which effectively - ;; means that the manager thread is not bound by a custodian - ;; that is weaker than any of its user's custodians (and thus, - ;; from the user's perspective, is not bound by any custodian - ;; at all). - (thread/suspend-to-kill - (lambda () - (let loop () - (cond - [(zero? size) - ;; The queue is currently empty: - (sync enqueue tell-empty)] - [(or (not limit) (size . < . limit)) - (sync enqueue (mk-dequeue))] - [else - (sync (mk-dequeue) tell-full)]) - (loop))))]) - (make-ac enqueue-ch dequeue-ch empty-ch full-ch manager-thread)))) - - ;; Get ---------------------------------------- - - (define (async-channel-get-guard ac) - ;; Make sure queue manager is running: - (thread-resume (ac-thread ac) (current-thread)) - ;; If it the channel is being polled, it's not - ;; good enough to poll the dequeue channel, because - ;; the server thread may be looping. In that case, - ;; block on the dequeue channel and the empty - ;; channel, and create a new waitable to report - ;; the result. - (poll-guard-evt - (lambda (poll?) - (if poll? - (poll->ch (ac-dequeue-ch ac) (ac-empty-ch ac)) - (ac-dequeue-ch ac))))) - - (define (async-channel-get ac) - (sync ac)) - - (define (async-channel-try-get ac) - (sync/timeout 0 ac)) - - ;; Put ---------------------------------------- - - (define (async-channel-put-evt ac v) - (letrec ([p (wrap-evt - (guard-evt - (lambda () - ;; Make sure queue manager is running: - (thread-resume (ac-thread ac) (current-thread)) - (let ([p (channel-put-evt (ac-enqueue-ch ac) v)]) - ;; Poll handling, as in `async-channel-get-guard': - (poll-guard-evt - (lambda (poll?) - (if poll? - (poll->ch p (ac-full-ch ac)) - p)))))) - (lambda (ignored) p))]) - p)) - - (define (async-channel-put ac v) - (thread-resume (ac-thread ac) (current-thread)) - (sync (channel-put-evt (ac-enqueue-ch ac) v)) - (void)) - - ;; Poll helper ---------------------------------------- - - (define (poll->ch normal not-ready) - (sync - ;; If a value becomes available, - ;; create a waitable that returns - ;; the value: - (wrap-evt - normal - (lambda (v) - ;; Return a waitable for a successful poll: - (wrap-evt - always-evt - (lambda (ignored) v)))) - ;; If not-ready becomes available, - ;; the result is supposed to be - ;; a never-ready waitable: - not-ready)) - - ;; Provides ---------------------------------------- - - (provide async-channel?) - (provide/contract (make-async-channel (case-> - (-> async-channel?) - ((union false/c (lambda (x) - (and (integer? x) - (exact? x) - (positive? x)))) - . -> . async-channel?))) - (async-channel-get (async-channel? . -> . any/c)) - (async-channel-try-get (async-channel? . -> . any/c)) - (async-channel-put (async-channel? any/c . -> . any/c)) - (async-channel-put-evt (async-channel? any/c . -> . evt?)))) +(require scheme/async-channel) +(provide (all-from-out scheme/async-channel)) diff --git a/collects/mzlib/integer-set.ss b/collects/mzlib/integer-set.ss index ac06402253..d2a74be24d 100644 --- a/collects/mzlib/integer-set.ss +++ b/collects/mzlib/integer-set.ss @@ -430,6 +430,9 @@ (subset?-helper (integer-set-contents s1) (integer-set-contents s2))) (define int (flat-named-contract "exact-integer" int?)) + + (provide well-formed-set?) + (provide/contract (struct integer-set ((contents (flat-named-contract "integer-set-list" well-formed-set?)))) (make-range (case-> (-> integer-set?) (int . -> . integer-set?) diff --git a/collects/mzlib/scribblings/awk.scrbl b/collects/mzlib/scribblings/awk.scrbl new file mode 100644 index 0000000000..7e06fa9ec5 --- /dev/null +++ b/collects/mzlib/scribblings/awk.scrbl @@ -0,0 +1,69 @@ +#lang scribble/doc +@(require "common.ss" + (for-label mzlib/awk + scheme/contract)) + +@mzlib[#:mode title awk] + +@defform/subs[ +#:literals (after range / => :range range: :range: else) +(awk next-record-expr + (record field-id ...) + maybe-counter + ((state-variable init-expr) ...) + maybe-continue + clause ...) +([maybe-counter code:blank + id] + [maybe-continue code:blank + id] + [clause (test body ...+) + (test => procedure-expr) + (/ regexp-str / (id-or-false ...+) body ...+) + (range excl-start-test excl-stop-test body ...+) + (:range incl-start-test excl-stop-test body ...+) + (range: excl-start-test incl-stop-test body ...+) + (:range: incl-start-test incl-stop-test body ...+) + (else body ...+) + (after body ...+)] + [test integer + regexp-string + expr] + [excl-start-test test] + [excl-stop-test test] + [incl-start-test test] + [incl-stop-test test] + [id-or-false id + #f])]{ + +The @scheme[awk] macro from Scsh @cite["Shivers06"]. In addition to +@scheme[awk], the Scsh-compatible procedures @scheme[match:start], +@scheme[match:end], @scheme[match:substring], and @scheme[regexp-exec] +are defined. These @schemeidfont{match:} procedures must be used to +extract match information in a regular expression clause when using +the @scheme[=>] form. } + +@deftogether[( +@defproc[(match:start [rec ....] + [which exact-nonnegative-integer? 0]) + exact-nonnegative-integer?] +@defproc[(match:end [rec ....] + [which exact-nonnegative-integer? 0]) + exact-nonnegative-integer?] +@defproc[(match:substring + [rec ....] + [which exact-nonnegative-integer? 0]) + string?] +)]{ + +Extracts a start position, end position, or substring corresponding to +a match. The first argument is the value supplied to the procedure +after @scheme[=>] in a @scheme[awk] clause or the result of +@scheme[regexp-exec].} + + +@defproc[(regexp-exec [re (or/c string? regexp?)] [s string?]) + (or/c .... false/c)]{ + +Matches a regexp to a string, returning a record compatible with +@scheme[match:start], etc.} diff --git a/collects/mzlib/scribblings/class100.scrbl b/collects/mzlib/scribblings/class100.scrbl new file mode 100644 index 0000000000..e7b80da8a3 --- /dev/null +++ b/collects/mzlib/scribblings/class100.scrbl @@ -0,0 +1,83 @@ +#lang scribble/doc +@(require "common.ss" + (for-label mzlib/class100 + mzlib/class + scheme/contract)) + +@mzlib[#:mode title class100] + +The @scheme[class100] and @scheme[class100*] forms provide a syntax +close to that of @scheme[class] and @scheme[class*] in PLT Scheme +versions 100 through 103, but with the semantics of the current +@schememodname[scheme/class]-based class system. For a class defined +with @scheme[class100], keyword-based initialization arguments can be +propagated to the superclass, but by-position arguments are not (i.e., +the expansion of @scheme[class100] to @scheme[class] always includes +an @scheme[init-rest] clause). + +The @scheme[class100] form uses keywords (e.g., @scheme[public]) that +are defined by the @schememodname[mzlib/class] library, so typically +@schememodname[scheme/class] must be imported into any context that +imports @schememodname[mzlib/class100]. + + +@defform/subs[ +#:literals (sequence public override augment pubment + overment augride private private-field inherit + rename) +(class100* superclass-expr (interface-expr ...) init-ids + class100-clause + ...) +([init-ids id + (id ... id-with-default ...) + (id ... id-with-default ... . id) ] + [id-with-default (id default-expr) ] + [class100-clause (sequence expr ...) + (public public-method-decl ...) + (override public-method-decl ...) + (augment public-method-decl ...) + (pubment public-method-decl ...) + (overment public-method-decl ...) + (augride public-method-decl ...) + (private private-method-decl ...) + (private-field private-var-decl ...) + (inherit inherit-method-decl ...) + (rename rename-method-decl ...) ] + [public-method-decl ((internal-id external-id) method-procedure) + (id method-procedure)] + [private-method-decl (id method-procedure)] + [private-var-decl (id initial-value-expr) + (id) + id] + [inherit-method-decl id + (internal-instance-id external-inherited-id)] + [rename-method-decl (internal-id external-id)])] + + +@defform[ +(class100 superclass-expr init-ids + class100-clause + ...) +]{ + +Like @scheme[class100*], but without @scheme[interface-expr]s.} + + +@defform[(class100-asi superclass instance-id-clause ...)]{ + +Like @scheme[class100], but all initialization arguments are +automatically passed on to the superclass initialization procedure by +position.} + + +@defform[(class100*-asi superclass interfaces instance-id-clause ...)]{ + +Like @scheme[class100*], but all initialization arguments are +automatically passed on to the superclass initialization procedure by +position.} + + +@defform[(super-init init-arg-expr ...)]{ + +An alias for @scheme[super-make-object].} + diff --git a/collects/mzlib/scribblings/cmdline.scrbl b/collects/mzlib/scribblings/cmdline.scrbl new file mode 100644 index 0000000000..2d7e91aa9c --- /dev/null +++ b/collects/mzlib/scribblings/cmdline.scrbl @@ -0,0 +1,38 @@ +#lang scribble/doc +@(require "common.ss" + (for-label mzlib/cmdline)) + +@(define-syntax-rule (intro id) + (begin + (require (for-label scheme/cmdline)) + (define id (scheme command-line)))) +@(intro scheme-command-line) + +@mzlib[#:mode title cmdline] + +Provides a @scheme[command-line] from that is similar to the one in +@schememodname[scheme/cmdline], but without using keywords. The +@scheme[parse-command-line] procedure from +@schememodname[scheme/cmdline] is re-exported directly. + +@defform/subs[ +#:literals (multi once-each once-any final help-labels args =>) +(command-line program-name-expr argv-expr clause ...) +([clause (multi flag-spec ...) + (once-each flag-spec ...) + (once-any flag-spec ...) + (final flag-spec ...) + (help-labels string ...) + (args arg-formals body-expr ...+) + (=> finish-proc-expr arg-help-expr help-proc-expr + unknown-proc-expr)] + [flag-spec (flags id ... help-str ...+ body-expr ...+) + (flags => handler-expr help-expr)] + [flags flag-string + (flag-string ...+)] + [arg-formals id + (id ...) + (id ...+ . id)])]{ + +Like @scheme-command-line from @scheme[scheme/cmdline], but without +keywords in the syntax.} diff --git a/collects/mzlib/scribblings/cml.scrbl b/collects/mzlib/scribblings/cml.scrbl new file mode 100644 index 0000000000..3e60a71a58 --- /dev/null +++ b/collects/mzlib/scribblings/cml.scrbl @@ -0,0 +1,45 @@ +#lang scribble/doc +@(require "common.ss" + (for-label mzlib/cml)) + +@mzlib[#:mode title cml] + +The @schememodname[mzlib/cml] library defines a number of procedures +that wrap PLT Scheme concurrency procedures. The wrapper procedures +have names and interfaces that more closely match those of Concurrent +ML @cite["Reppy99"]. + + +@defproc[(spawn [thunk (-> any)]) thread?]{ + +Equivalent to @scheme[(thread/suspend-to-kill thunk)].} + + +@defproc[(channel) channel?]{ + +Equivalent to @scheme[(make-channel)].} + + +@defproc[(channel-recv-evt [ch channel?]) evt?]{ + +Equivalent to @scheme[ch].} + + +@defproc[(channel-send-evt [ch channel?][v any/c]) evt?]{ + +Equivalent to @scheme[(channel-put-evt ch v)].} + + +@defproc[(thread-done-evt [thd thread?]) any]{ + +Equivalent to @scheme[(thread-dead-evt thread)].} + + +@defproc[(current-time) real?]{ + +Equivalent to @scheme[(current-inexact-milliseconds)].} + + +@defproc[(time-evt [tm real?]) evt?]{ + +Equivalent to @scheme[(alarm-evt tm)].} diff --git a/collects/mzlib/scribblings/common.ss b/collects/mzlib/scribblings/common.ss new file mode 100644 index 0000000000..ea43dd7aa8 --- /dev/null +++ b/collects/mzlib/scribblings/common.ss @@ -0,0 +1,19 @@ +#lang scheme/base + +(require (for-syntax scheme/base) + scribble/manual + (for-label mzscheme)) + +(provide mzlib + (all-from-out scribble/manual) + (for-label (all-from-out mzscheme))) + +(define-syntax (mzlib stx) + (syntax-case stx () + [(_ #:mode section name) + (with-syntax ([lib (string->symbol + (format "mzlib/~a" (syntax-e #'name)))]) + #'(begin + (section #:style 'hidden (scheme lib)) + (defmodule lib)))] + [(_ name) #'(mzlib #:mode section name)])) diff --git a/collects/mzlib/scribblings/compat.scrbl b/collects/mzlib/scribblings/compat.scrbl new file mode 100644 index 0000000000..14ba4c9727 --- /dev/null +++ b/collects/mzlib/scribblings/compat.scrbl @@ -0,0 +1,96 @@ +#lang scribble/doc +@(require "common.ss" + scribble/eval + (for-label mzlib/compat)) + +@(define compat-eval (make-base-eval)) + +@interaction-eval[#:eval compat-eval (require mzlib/compat)] + +@mzlib[#:mode title compat] + +The @schememodname[mzlib/compat] library defines a number of +procedures and syntactic forms that are commonly provided by other +Scheme implementations. Most of the procedures are aliases for +@schememodname[mzscheme] procedures. + +@deftogether[( +@defproc[(=? [n number?] ...+) boolean?] +@defproc[(? [n real?] ...+) boolean?] +@defproc[(<=? [n real?] ...+) boolean?] +@defproc[(>=? [n real?] ...+) boolean?] +)]{ + +Same as @scheme[=], @scheme[<], etc.} + +@deftogether[( +@defproc[(1+ [n number?]) number?] +@defproc[(1- [n number?]) number?] +)]{ + +Same as @scheme[add1] and @scheme[sub1].} + + +@defproc[(gentmp [base (or/c string? symbol?) "g"]) symbol?]{ + +Same as @scheme[gensym].} + + +@defproc[(flush-output-port [o output-port? (current-output-port)]) void?]{ + +Same as @scheme[flush-output].} + +@defproc[(real-time) exact-integer?]{ + +Same as @scheme[current-milliseconds].} + + +@defproc[(atom? [v any/c]) any]{ + +Same as @scheme[(not (pair? v))] (which does not actually imply an +atomic value).} + + +@defform*[[(define-structure (name-id field-id ...)) + (define-structure (name-id field-id ...) + ((init-field-id init-expr) ...))]]{ + +Like @scheme[define-struct], except that the @scheme[name-id] is moved +inside the parenthesis for fields. In addition, +@scheme[init-field-id]s can be specified with automatic initial-value +expression. + +The @scheme[init-field-id]s do not have corresponding arguments for +the @schemeidfont{make-}@scheme[name-id] constructor. Instead, each +@scheme[init-field-id]'s @scheme[init-expr] is evaluated to obtain the +field's value when the constructor is called. The @scheme[field-id]s +are bound in @scheme[init-expr]s, but not other +@scheme[init-field-id]s. + +@examples[ +#:eval compat-eval +(define-structure (add left right) ([sum (+ left right)])) +(add-sum (make-add 3 6)) +]} + +@deftogether[( +@defproc[(getprop [sym symbol?][property symbol?][default any/c #f]) any/c] +@defproc[(putprop [sym symbol?][property symbol?][value any/c]) void?] +)]{ + +The @scheme[getprop] function gets a property value associated with +@scheme[sym]. The @scheme[property] argument names the property to be +found. If the property is not found, @scheme[default] is returned. + +The properties obtained with @scheme[getprop] are the ones installed +with @scheme[putprop].} + + +@defproc[(new-cafe [eval-handler (any/c . -> . any) #f]) any]{ + +Emulates Chez Scheme's @scheme[new-cafe] by installing +@scheme[eval-handler] into the @scheme[current-eval] parameter while +running @scheme[read-eval-print]. In addition, @scheme[current-exit] +is set to escape from the call to @scheme[new-cafe].} + diff --git a/collects/mzlib/scribblings/compile.scrbl b/collects/mzlib/scribblings/compile.scrbl new file mode 100644 index 0000000000..49bd63e3b1 --- /dev/null +++ b/collects/mzlib/scribblings/compile.scrbl @@ -0,0 +1,34 @@ +#lang scribble/doc +@(require "common.ss" + (for-label mzlib/compile + compiler/compiler + compiler/cm)) + +@mzlib[#:mode title compile] + +@defproc[(compile-file [src path-string?] + [dest path-string? (let-values ([(base name dir?) (split-path src)]) + (build-path base "compiled" + (path-add-suffix name #".zo")))] + [filter (any/c . -> . any/c) values]) + path?]{ + +Compiles the Scheme file @scheme[src] and saves the compiled code to +@scheme[dest]. If @scheme[dest] is not provided and the +@filepath{compiled} subdirectory does not already exist, the +subdirectory is created. The result of @scheme[compile-file] is the +destination file's path. + +If the @scheme[filter] procedure is provided, it is applied to each +source expression, and the result is compiled. + +The @scheme[compile-file] procedure is designed for compiling modules +files, in that each expression in @scheme[src] is compiled +independently. If @scheme[src] does not contain a single +@scheme[module] expression, then earlier expressions can affect the +compilation of later expressions when @scheme[src] is loaded +directly. An appropriate @scheme[filter] can make compilation behave +like evaluation, but the problem is also solved (as much as possible) +by the @scheme[compile-zos] procedure. + +See also @scheme[managed-compile-zo].} diff --git a/collects/mzlib/scribblings/contract.scrbl b/collects/mzlib/scribblings/contract.scrbl new file mode 100644 index 0000000000..49a2da88e5 --- /dev/null +++ b/collects/mzlib/scribblings/contract.scrbl @@ -0,0 +1,8 @@ +#lang scribble/doc +@(require "common.ss" + (for-label mzlib/contract)) + +@mzlib[#:mode title contract] + +Re-provides much of @schememodname[scheme/contract], except.... + diff --git a/collects/mzlib/scribblings/defmacro.scrbl b/collects/mzlib/scribblings/defmacro.scrbl new file mode 100644 index 0000000000..8106b7a83c --- /dev/null +++ b/collects/mzlib/scribblings/defmacro.scrbl @@ -0,0 +1,67 @@ +#lang scribble/doc +@(require "common.ss" + (for-label mzlib/defmacro + (only-in scheme/base syntax->datum datum->syntax))) + +@(define ref '(lib "scribblings/reference/reference.scrbl")) + +@mzlib[#:mode title defmacro] + +@deftogether[( +@defform*[[(define-macro id expr) + (define-macro (id . formals) body ...+)]] +@defform/subs[(defmacro id formals body ...+) + ([formals (id ...) + id + (id ...+ . id)])] +)]{ + +Defines a (non-hygienic) macro @scheme[id] through a procedure that +manipulates S-expressions, as opposed to @techlink[#:doc ref]{syntax +objects}. + +In the first form, @scheme[expr] must produce a procedure. In the +second form, @scheme[formals] determines the formal arguments of the +procedure, as in @scheme[lambda], and the @scheme[expr]s are the +procedure body. The last form, with @scheme[defmacro], is like the +second form, but with slightly different parentheses. + +In all cases, the procedure is generated in the @techlink[#:doc +ref]{transformer environment}, not the normal environment. + +In a use of the macro, + +@schemeblock[ +(id datum ...) +] + +@scheme[syntax->datum] is applied to the expression, and the +transformer procedure is applied to the @scheme[cdr] of the resulting +list. If the number of @scheme[datum]s does not match the procedure's +arity, or if @scheme[id] is used in a context that does not match the +above pattern, then a syntax error is reported. + +After the macro procedure returns, the result is compared to the +procedure's arguments. For each value that appears exactly once within +the arguments (or, more precisely, within the S-expression derived +from the original source syntax), if the same value appears in the +result, it is replaced with a syntax object from the original +expression. This heuristic substitution preserves source location +information in many cases, despite the macro procedure's operation on +raw S-expressions. + +After substituting syntax objects for preserved values, the entire +macro result is converted to syntax with @scheme[datum->syntax]. The +original expression supplies the lexical context and source location +for converted elements. + +@bold{Important:} Although @scheme[define-macro] is non-hygienic, it +is still restricted by PLT Scheme's phase separation rules. This +means that a macro cannot access run-time bindings, because it is +executed in the syntax-expansion phase. Translating code that +involves @scheme[define-macro] or @scheme[defmacro] from an +implementation without this restriction usually implies separating +macro related functionality into a @scheme[begin-for-syntax] or a +module (that will be imported with @scheme[require-for-syntax]) and +properly distinguishing syntactic information from run-time +information.} \ No newline at end of file diff --git a/collects/mzlib/scribblings/etc.scrbl b/collects/mzlib/scribblings/etc.scrbl new file mode 100644 index 0000000000..6841649dec --- /dev/null +++ b/collects/mzlib/scribblings/etc.scrbl @@ -0,0 +1,272 @@ +#lang scribble/doc +@(require "common.ss" + scribble/eval + (for-label mzlib/etc + scheme/bool + scheme/local + setup/dirs + (only-in scheme build-list build-string build-vector + symbol=?))) + +@(define etc-eval (make-base-eval)) +@interaction-eval[#:eval etc-eval (require mzlib/etc)] + +@(begin + (define-syntax-rule (bind id) + (begin + (require scheme/base) + (define id (scheme lambda)))) + (bind base-lambda)) + +@mzlib[#:mode title etc] + +The @schememodname[mzlib/etc] library re-exports the following +@schememodname[scheme/base] and other libraries: + +@schemeblock[ +boolean=? +true +false +build-list +build-string +build-vector +compose +local +symbol=? +] + +@defform[(begin-lifted expr ...+)] + +Lifts the @scheme[expr]s so that they are evaluated once at the ``top +level'' of the current context, and the result of the last +@scheme[expr] is used for every evaluation of the +@scheme[begin-lifted] form. + +When this form is used as a run-time expression within a module, the +``top level'' corresponds to the module's top level, so that each +@scheme[expr] is evaluated once for each invocation of the +module. When it is used as a run-time expression outside of a module, +the ``top level'' corresponds to the true top level. When this form is +used in a @scheme[define-syntax], @scheme[letrec-syntax], +etc. binding, the ``top level'' corresponds to the beginning of the +binding's right-hand side. Other forms may redefine ``top level'' +(using @scheme[local-expand/capture-lifts]) for the expressions that +they enclose. + + +@defform[(begin-with-definitions defn-or-expr ...)]{ + +Supports a mixture of expressions and mutually recursive definitions, +much like a @scheme[module] body. Unlike in a @scheme[module], +however, syntax definitions cannot be used to generate other immediate +definitions (though they can be used for expressions). + +The result of the @scheme[begin-with-definitions] form is the result +of the last @scheme[defn-or-expr] if it is an expression, +@|void-const| otherwise. If no @scheme[defn-or-expr] is provided +(after flattening @scheme[begin] forms), the result is @|void-const|.} + + + +@defform[(define-syntax-set (id ...) defn ...)]{ + +Similar to @scheme[define-syntaxes], but instead of a single body +expression, a sequence of definitions follows the sequence of defined +identifiers. For each @scheme[identifier], the @scheme[defn]s should +include a definition for @scheme[id]@schemeidfont{/proc}. The value +for @scheme[id]@schemeidfont{/proc} is used as the (expansion-time) +value for @scheme[id]. + +The @scheme[define-syntax-set] form is useful for defining a set of +syntax transformers that share helper functions, though +@scheme[begin-for-syntax] now serves essentially the same purposes. + +@as-examples[ +@schemeblock[ +(define-syntax-set (let-current-continuation + let-current-escape-continuation) + (define (mk call-id) + (lambda (stx) + (syntax-case stx () + [(_ id body1 body ...) + (with-syntax ([call call-id]) + (syntax (call (lambda (id) body1 body ...))))]))) + (define let-current-continuation/proc + (mk (quote-syntax call/cc))) + (define let-current-escape-continuation/proc + (mk (quote-syntax call/ec)))) +]]} + + +@defform*[#:literals (else) + [(evcase key-expr (value-expr body-expr ...) ...+) + (evcase key-expr (value-expr body-expr ...) ... [else body-expr ...])]]{ + +The @scheme[evcase] form is similar to @scheme[case], except that +expressions are provided in each clause instead of a sequence of +data. After @scheme[key-expr] is evaluated, each @scheme[value-expr] +is evaluated until a value is found that is @scheme[eqv?] to the key +value; when a matching value is found, the corresponding +@scheme[body-expr]s are evaluated and the value(s) for the last is the +result of the entire @scheme[evcase] expression.} + + +@defproc[(identity [v any/c]) any/c]{ + +Returns @scheme[v].} + + +@defform/subs[#:literals (val rec vals recs _ values) + (let+ clause body-expr ...+) + ([clause (val target expr) + (rec target expr) + (vals (target ...) expr) + (recs (target expr) ...) + (_ expr ...)] + [target id + (values id ...)])]{ + +A binding construct that specifies scoping on a per-binding basis +instead of a per-expression basis. It helps eliminate rightward-drift +in programs. It looks similar to @scheme[let], except each clause has +an additional keyword tag before the binding variables. + +Each @scheme[clause] has one of the following forms: + +@itemize{ + + @item{@scheme[(val target expr)] : Binds @scheme[target] + non-recursively to @scheme[expr].} + + @item{@scheme[(rec target expr)] : Binds @scheme[target] recursively to + @scheme[expr].} + + @item{@scheme[(vals (target expr) ...)] : The @scheme[target]s are + bound to the @scheme[expr]s. The environment of the @scheme[expr]s is + the environment active before this clause.} + + @item{@scheme[(recs (target expr) ...)] : The @scheme[targets]s are + bound to the @scheme[expr]s. The environment of the @scheme[expr]s + includes all of the @scheme[targets]s.} + + @item{@scheme[(_ expr ...)] : Evaluates the @scheme[expr]s without + binding any variables.} + +} + +The clauses bind left-to-right. When a @scheme[target] is +@scheme[(values id ...)], multiple values returned by the +corresponding expression are bound to the multiple variables. + +@examples[ +#:eval etc-eval +(let+ ([val (values x y) (values 1 2)]) + (list x y)) + +(let ([x 1]) + (let+ ([val x 3] + [val y x]) + y)) +]} + + +@defproc[(loop-until [start any/c][done? (any/c . -> . any)] + [next (any/c . -> . any/c)] + [f (any/c . -> . any)]) + void?]{ + +Repeatedly invokes the @scheme[f] procedure until the @scheme[done?] +procedure returns @scheme[#t]: + +@schemeblock[ +(define loop-until + (lambda (start done? next f) + (let loop ([i start]) + (unless (done? i) + (f i) + (loop (next i)))))) +]} + + +@defproc[(namespace-defined? [sym symbol?]) boolean?]{ + +Returns @scheme[#t] if @scheme[namespace-variable-value] would return +a value for @scheme[sym], @scheme[#f] otherwise.} + + +@defform[(nand expr ...)]{ + +Same as @scheme[(not (and expr ...))].} + + +@defform[(nor expr ...)]{ + +Same as @scheme[(not (or expr ...))].} + + +@defform[(opt-lambda formals body ...+)]{ + +Supports optional (but not keyword) arguments like @base-lambda from +@scheme[scheme/base].} + + +@defform[(recur id bindings body ...+)]{ + +Equivalent to @scheme[(let id bindings body ...+)].} + + +@defform*[[(rec id value-expr) + (rec (id arg-id ...) expr) + (rec (id arg-id ... . rest-id) expr)]]{ + +Equivalent, respectively, to + +@schemeblock[ +(letrec ((id value-expr)) id) +(letrec ((id (lambda (arg-id ...) value-expr))) id) +(letrec ((id (lambda (arg-id ... . rest-id) value-expr))) id) +]} + + +@deftogether[( +@defform[(this-expression-source-directory)] +@defform[(this-expression-file-name)] +)]{ + +@margin-note{See @schememodname[scheme/runtime-path] for a definition form +that works better when creating executables.} + +Expands to an expression that evaluates to the name of the directory +of the file containing the source expression, or the name of the file +containing the source expression. + +If the expression has a source module, then the expansion attempts to +determine the module's run-time location. This location is determined +by preserving the original expression as a syntax object, extracting +its source module path at run time, and then resolving the module +path. + +Otherwise, the source expression's file is determined through source +location information associated with the syntax, if it is present. If +the expression has no source, or if no directory can be determined at +run time, the expansion falls back to using source-location +information associated with the expression. + +As a last resort, @scheme[#f] is used for the file name; for the +directory name, @scheme[current-load-relative-directory] is used if it +is not @scheme[#f], and @scheme[current-directory] is used if all else +fails. + +A directory path is stored in bytes in the expanded code, unless the +file is within the result of @scheme[find-collects-dir], in which case +the expansion records the path relative to +@scheme[(find-collects-dir)] and then reconstructs it using +@scheme[(find-collects-dir)] at run time.} + + +@defform[#:literals (quote unsyntax scheme) + (hash-table (#,(scheme quote) flag) ... (key-expr val-expr) ...)]{ + +Creates a new hash-table providing the quoted flags (if any) to +@scheme[make-hash-table], and them mapping each key to the +corresponding values.} diff --git a/collects/mzlib/scribblings/file.scrbl b/collects/mzlib/scribblings/file.scrbl new file mode 100644 index 0000000000..f39901c25b --- /dev/null +++ b/collects/mzlib/scribblings/file.scrbl @@ -0,0 +1,64 @@ +#lang scribble/doc +@(require "common.ss" + (for-label mzlib/file + scheme/contract)) + + +@mzlib[#:mode title file] + +The @schememodname[mzlib/file] library mostly re-exports from +@schememodname[scheme/file]: + +@schemeblock[ +find-relative-path +explode-path +normalize-path +filename-extension +file-name-from-path +path-only +delete-directory/files +copy-directory/files +make-directory* +make-temporary-file +get-preference +put-preferences +fold-files +find-files +pathlist-closure +] + +@deftogether[( +@defproc[(call-with-input-file* [file path-string?] + [proc (input-port? -> any)] + [mode (one-of/c 'text 'binary) 'binary]) + any] +@defproc[(call-with-output-file* [file path-string?] + [proc (output-port? -> any)] + [mode (one-of/c 'text 'binary) 'binary] + [exists (one-of/c 'error 'append 'update + 'replace 'truncate 'truncate/replace) 'error]) + any] +)]{ + +Like @scheme[call-with-input-file]and @scheme[call-with-output-file], +except that the opened port is closed if control escapes from the body +of @scheme[proc].} + +@deftogether[( +@defproc[(build-relative-path [base (or/c path-string? + (one-of/c 'up 'same))] + [sub (or/c (and/c path-string? + relative-path?) + (one-of/c 'up 'same))] ...) + (and/c path? relative-path?)] +@defproc[(build-absolute-path [base (or/c (and/c path-string? + (not/c relative-path?)) + (one-of/c 'up 'same))] + [sub (or/c (and/c path-string? + (not/c complete-path?)) + (one-of/c 'up 'same))] ...) + (and/c path? absolute-path?)] +)]{ + +Like @scheme[build-path], but with extra constraints to ensure a +relative or absolute result.} diff --git a/collects/mzlib/scribblings/for.scrbl b/collects/mzlib/scribblings/for.scrbl new file mode 100644 index 0000000000..94667146ae --- /dev/null +++ b/collects/mzlib/scribblings/for.scrbl @@ -0,0 +1,45 @@ +#lang scribble/doc +@(require "common.ss" + (for-label mzlib/for)) + +@mzlib[#:mode title for] + +The @schememodname[mzlib/for] library re-exports from +@schememodname[scheme/base]: + +@schemeblock[ +for/fold for*/fold +for for* +for/list for*/list +for/lists for*/lists +for/and for*/and +for/or for*/or +for/first for*/first +for/last for*/last + +for/fold/derived for*/fold/derived + +in-range +in-naturals +in-list +in-vector +in-string +in-bytes +in-input-port-bytes +in-input-port-chars +in-hash-table +in-hash-table-keys +in-hash-table-values +in-hash-table-pairs + +in-parallel +stop-before +stop-after +in-indexed + +sequence? +sequence-generate + +define-sequence-syntax +make-do-sequence +:do-in] diff --git a/collects/mzlib/scribblings/include.scrbl b/collects/mzlib/scribblings/include.scrbl new file mode 100644 index 0000000000..fadd29f02b --- /dev/null +++ b/collects/mzlib/scribblings/include.scrbl @@ -0,0 +1,68 @@ +#lang scribble/doc +@(require "common.ss" + (for-label mzlib/include)) + +@mzlib[#:mode title include] + +Similar to @schememodname[scheme/include], but with a different syntax +for paths. + +@defform/subs[#:literals (build-path lib up same) + (include path-spec) + ([path-spec string + (build-path elem ...+) + (lib file-string collection-string ...)] + [elem string + up + same])]{ + +Inlines the syntax in the designated file in place of the +@scheme[include] expression. The @scheme[path-spec] can be any of the +following: + +@itemize{ + + @item{A literal string that specifies a path to include, parsed + according to the platform's conventions (which means that it is + not portable).} + + @item{A path construction of the form @scheme[(build-path elem + ...+)], where @scheme[build-path] is + @scheme[module-identifier=?] either to the @scheme[build-path] + export from @scheme[mzscheme] or to the top-level + @scheme[build-path], and where each @scheme[elem] is a path + string, @scheme[up] (unquoted), or @scheme[same] (unquoted). + The @scheme[elem]s are combined in the same way as for the + @scheme[build-path] function to obtain the path to include.} + + @item{A path construction of the form @scheme[(lib file-string + collection-string ...)], where @scheme[lib] is free or refers + to a top-level @scheme[lib] variable. The + @scheme[collection-string]s are passed to + @scheme[collection-path] to obtain a directory; if no + @scheme[collection-strings]s are supplied, @scheme["mzlib"] is + used. The @scheme[file-string] is then appended to the + directory using @scheme[build-path] to obtain the path to + include.} + +} + +If @scheme[path-spec] specifies a relative path to include, the path +is resolved relative to the source for the @scheme[include] +expression, if that source is a complete path string. If the source is +not a complete path string, then @scheme[path-spec] is resolved +relative to the current load relative directory if one is available, +or to the current directory otherwise. + +The included syntax is given the lexical context of the +@scheme[include] expression.} + +@deftogether[( +@defform[(include-at/relative-to context source path-spec)] +@defform[(include-at/relative-to/reader context source path-spec reader-expr)] +@defform[(include/reader path-spec reader-expr)] +)]{ + +Variants of @scheme[include] analogous to the variants of +@schememodname[scheme/include].} + diff --git a/collects/mzlib/scribblings/info.ss b/collects/mzlib/scribblings/info.ss new file mode 100644 index 0000000000..9a6b66f6f0 --- /dev/null +++ b/collects/mzlib/scribblings/info.ss @@ -0,0 +1,5 @@ +#lang setup/infotab + +(define name "MzLib documentation") +(define scribblings '(("mzlib.scrbl" (multi-page)))) +(define doc-categories '(legacy)) diff --git a/collects/mzlib/scribblings/integer-set.scrbl b/collects/mzlib/scribblings/integer-set.scrbl new file mode 100644 index 0000000000..f93832c02f --- /dev/null +++ b/collects/mzlib/scribblings/integer-set.scrbl @@ -0,0 +1,145 @@ +#lang scribble/doc +@(require "common.ss" + (for-label mzlib/integer-set)) + +@mzlib[#:mode title integer-set] + +The @schememodname[mzlib/integer-set] library provides functions for +working with finite sets of integers. This module is designed for +sets that are compactly represented as groups of intervals, even when +their cardinality is large. For example, the set of integers from +@math{-1000000} to @math{1000000} except for @math{0}, can be represented as +@math{{[-1000000, -1], [1, 1000000]}}. This data structure would not be +a good choice for the set of all odd integers between @math{0} and +@math{1000000}, which would be @math{{[1, 1], [3, 3], ... [999999, +999999]}}. + +In addition to the @defterm{integer set} abstract type, a +@defterm{well-formed set} is a list of pairs of exact integers, where +each pair represents a closed range of integers, and the entire set is +the union of the ranges. The ranges must be disjoint and increasing. +Further, adjacent ranges must have at least one integer between them. +For example: @scheme['((-1 . 2) (4 . 10))] is a well-formed-set as is +@scheme['((1 . 1) (3 . 3))], but @scheme['((1 . 5) (6 . 7))], +@scheme['((1 . 5) (-3 . -1))], @scheme['((5 . 1))], and @scheme['((1 +. 5) (3 . 6))] are not. + + +@defproc[(make-integer-set [wfs well-formed-set?]) integer-set?]{ + +Creates an integer set from a well-formed set.} + + +@defproc[(integer-set-contents [s integer-set?]) well-formed-set?]{ + +Produces a well-formed set from an integer set.} + + +@defproc[(set-integer-set-contents! [s integer-set?][wfs well-formed-set?]) void?]{ + +Mutates an integer set.} + + +@defproc[(integer-set? [v any/c]) boolean?]{ + +Returns @scheme[#t] if @scheme[v] is an integer set, @scheme[#f] +otherwise.} + +@defproc[(well-formed-set? [v any/c]) boolean?]{ + +Returns @scheme[#t] if @scheme[v] is a well-formed set, @scheme[#f] +otherwise.} + +@defproc*[([(make-range) integer-set?] + [(make-range [elem exact-integer?]) integer-set?] + [(make-range [start exact-integer?] + [end exact-integer?]) integer-set?])]{ + +Produces, respectively, an empty integer set, an integer set +containing only @scheme[elem], or an integer set containing the +integers from @scheme[start] to @scheme[end] inclusive, where +@scheme[(start . <= . end)].} + + +@defproc[(intersect [x integer-set?][y integer-set?]) integer-set?]{ + +Returns the intersection of the given sets.} + + +@defproc[(difference [x integer-set?][y integer-set?]) integer-set?]{ + +Returns the difference of the given sets (i.e., elements in @scheme[x] +that are not in @scheme[y]).} + + +@defproc[(union [x integer-set?][y integer-set?]) integer-set?]{ + +Returns the union of the given sets.} + + +@defproc[(split [x integer-set?][y integer-set?]) integer-set?]{ + +Produces three values: the first is the intersection of @scheme[x] and +@scheme[y], the second is the difference @scheme[x] remove @scheme[y], +and the third is the difference @scheme[y] remove @scheme[x].} + + +@defproc[(complement [s integer-set?] + [start exact-integer?] + [end exact-integer?]) any] + +Returns the a set containing the elements between @scheme[start] to +@scheme[end] inclusive that are not in @scheme[s], where +@scheme[(start-k . <= . end-k)].} + + +@defproc[(xor [x integer-set?][y integer-set?]) integer-set?]{ + +Returns an integer set containing every member of @scheme[x] +and @scheme[y] that is not in both sets.} + + +@defproc[(member? [k exact-integer?][s integer-set?]) boolean?]{ + +Returns @scheme[#t] if @scheme[k] is in @scheme[s], @scheme[#f] +otherwise.} + + +@defproc[(get-integer [integer-set any/c]) (or/c exact-integer? false/c)]{ + +Returns a member of @scheme[integer-set], or @scheme[#f] if +@scheme[integer-set] is empty.} + + +@defproc[(foldr [proc (exact-integer? any/c . -> . any/c)] + [base-v any/c] + [s integer-set?]) + any/c]{ + +Applies @scheme[proc] to each member of @scheme[s] in ascending order, +where the first argument to @scheme[proc] is the set member, and the +second argument is the fold result starting with @scheme[base-v]. For +example, @scheme[(foldr cons null s)] returns a list of all the +integers in @scheme[s], sorted in increasing order.} + + +@defproc[(partition [s integer-set-list?]) (listof integer-set?)]{ + +Returns the coarsest refinement of the sets in @scheme[s] such that +the sets in the result list are pairwise disjoint. For example, +partitioning the sets that represent @scheme['((1 . 2) (5 . 10))] and +@scheme['((2 . 2) (6 . 6) (12 . 12))] produces the a list containing +the sets for @scheme['((1 . 1) (5 . 5) (7 . 10))] @scheme['((2 . 2) (6 +. 6))], and @scheme['((12 . 12))].} + + +@defproc[(card [s integer-set?]) exact-nonnegative-integer?]{ + +Returns the number of integers in the given integer set.} + + +@defproc[(subset? [x integer-set?][y integer-set?]) boolean?]{ + +Returns true if every integer in @scheme[x] is also in +@scheme[y], otherwise @scheme[#f].} + diff --git a/collects/mzlib/scribblings/kw.scrbl b/collects/mzlib/scribblings/kw.scrbl new file mode 100644 index 0000000000..d76cccd645 --- /dev/null +++ b/collects/mzlib/scribblings/kw.scrbl @@ -0,0 +1,447 @@ +#lang scribble/doc +@(require "common.ss" + scribble/eval + (for-label mzlib/kw + mzlib/etc)) + +@(define kw-eval (make-base-eval)) + +@interaction-eval[#:eval kw-eval (require mzscheme)] +@interaction-eval[#:eval kw-eval (require mzlib/kw)] + +@(begin + (define-syntax-rule (bind id) + (begin + (require scheme/base) + (define id (scheme lambda)))) + (bind base-lambda)) + +@mzlib[#:mode title kw] + +@margin-note{The @base-lambda and procedure-application forms of + @scheme[scheme/base] support keyword arguments, and it is + @emph{not} compatible with the @scheme[mzlib/kw] + library.} + +@deftogether[( +@defform[(lambda/kw kw-formals body ...+)] +@defform/subs[ +(define/kw (head args) body ...+) +([kw-formals id + (id ... [#:optional optional-spec ...] + [#:key key-spec ...] + [rest/mode-spec ...]) + (id ... . id)] + [optional-spec id + (id default-expr)] + [key-spec id + (id default-expr) + (id keyword default-expr)] + [rest/mode-spec (code:line #:rest id) + (code:line #:other-keys id) + (code:line #:other-keys+body id) + (code:line #:all-keys id) + (code:line #:body kw-formals) + (code:line #:allow-other-keys) + (code:line #:forbid-other-keys) + (code:line #:allow-duplicate-keys) + (code:line #:forbid-duplicate-keys) + (code:line #:allow-body) + (code:line #:forbid-body) + (code:line #:allow-anything) + (code:line #:forbid-anything)] + [head id + (head . kw-formals)]) +])]{ + +Like @scheme[lambda], but with optional and keyword-based argument +processing. This form is similar to an extended version of Common +Lisp procedure arguments (but note the differences below). When used +with plain variable names, @scheme[lambda/kw] expands to a plain +@scheme[lambda], so @scheme[lambda/kw] is suitable for a language +module that will use it to replace @scheme[lambda]. Also, when used +with only optionals, the resulting procedure is similar to +@scheme[opt-lambda] (but a bit faster). + +In addition to @scheme[lambda/kw], @scheme[define/kw] is similar to +@scheme[define], except that the @scheme[formals] are as in +@scheme[lambda/kw]. Like @scheme[define], this form can be used with +nested parenthesis for curried functions (the MIT-style generalization +of @scheme[define]). + +The syntax of @scheme[lambda/kw] is the same as @scheme[lambda], +except for the list of formal argument specifications. These +specifications can hold (zero or more) plain argument names, then an +optionals (and defaults) section that begins after an +@scheme[#:optional] marker, then a keyword section that is marked by +@scheme[#:keyword], and finally a section holding rest and +``rest''-like arguments which are described below, together with +argument processing flag directives. Each section is optional, but +the order of the sections must be as listed. Of course, all binding +@scheme[id]s must be unique. + +The following sections describe each part of the @scheme[kw-formals].} + +@; ---------------------------------------- + +@section{Required Arguments} + +Required arguments correspond to @scheme[id]s that appear before any +keyword marker in the argument list. They determine the minimum arity +of the resulting procedure. + +@; ---------------------------------------- + +@section{Optional Arguments} + +The optional-arguments section follows an +@as-index{@scheme[#:optional]} marker in the @scheme[_kw-formals]. +Each optional argument can take the form of a parenthesized variable +and a default expression; the latter is used if a value is not given +at the call site. The default expression can be omitted (along with +the parentheses), in which case @scheme[#f] is the default. + +The default expression's environment includes all previous arguments, +both required and optional names. With @math{k} optionals after +@math{n} required arguments, and with no keyword arguments or +rest-like arguments, the resulting procedure accept between @math{n} +and @math{n+k} arguments, inclusive. + +The treatment of optionals is efficient, with an important caveat: +default expressions appear multiple times in the resulting +@scheme[case-lambda]. For example, the default expression for the last +optional argument appears @math{k-1} times (but no expression is ever +evaluated more than once in a procedure call). This expansion risks +exponential blow-up is if @scheme[lambda/kw] is used in a default +expression of a @scheme[lambda/kw], etc. The bottom line, however, is +that @scheme[lambda/kw] is a sensible choice, due to its enhanced +efficiency, even when you need only optional arguments. + +Using both optional and keyword arguments is possible, but note that +the resulting behavior differs from traditional keyword facilities +(including the one in Common Lisp). See the following section for +details. + +@; ---------------------------------------- + +@section{Keyword Arguments} + +A keyword argument section is marked by a @as-index{@scheme[#:key]}. +If it is used with optional arguments, then the keyword specifications +must follow the optional arguments (which mirrors the use in call +sites; where optionals are given before keywords). + +When a procedure accepts both optional and keyword arguments, the +argument-handling convention is slightly different than in traditional +keyword-argument facilities: a keyword after required arguments marks +the beginning of keyword arguments, no matter how many optional +arguments have been provided before the keyword. This convention +restricts the procedure's non-keyword optional arguments to +non-keyword values, but it also avoids confusion when mixing optional +arguments and keywords. For example, when a procedure that takes two +optional arguments and a keyword argument @scheme[#:x] is called with +@scheme[#:x 1], then the optional arguments get their default values +and the keyword argument is bound to @scheme[1]. (The traditional +behavior would bind @scheme[#:x] and @scheme[1] to the two optional +arguments.) When the same procedure is called with @scheme[1 #:x 2], +the first optional argument is bound to @scheme[1], the second +optional argument is bound to its default, and the keyword argument is +bound to @scheme[2]. (The traditional behavior would report an error, +because @scheme[2] is provided where @scheme[#:x] is expected.) + +Like optional arguments, each keyword argument is specified as a +parenthesized variable name and a default expression. The default +expression can be omitted (with the parentheses), in which case +@scheme[#f] is the default value. The keyword used at a call site for +the corresponding variable has the same name as the variable; a third +form of keyword arguments has three parts---a variable name, a +keyword, and a default expression---to allow the name of the locally +bound variable to differ from the keyword used at call sites. + +When calling a procedure with keyword arguments, the required argument +(and all optional arguments, if specified) must be followed by an even +number of arguments, where the first argument is a keyword that +determines which variable should get the following value, etc. If the +same keyword appears multiple times (and if multiple instances of the +keyword are allowed; see @secref["mode-keywords"]), the value after +the first occurrence is used for the variable: + +@examples[ +#:eval kw-eval +((lambda/kw (#:key x [y 2] [z #:zz 3] #:allow-duplicate-keys) + (list x y z)) + #:x 'x #:zz 'z #:x "foo") +] + +Default expressions are evaluated only for keyword arguments that do +not receive a value for a particular call. Like optional arguments, +each default expression is evaluated in an environment that includes +all previous bindings (required, optional, and keywords that were +specified on its left). + +See @secref["mode-keywords"] for information on when duplicate or +unknown keywords are allowed at a call site. + +@; ---------------------------------------- + +@section{Rest and Rest-like Arguments} + +The last @scheme[_kw-formals] section---after the required, optional, +and keyword arguments---may contain specifications for rest-like +arguments and/or mode keywords. Up to five rest-like arguments can be +declared, each with an @scheme[_id] to bind: + +@itemize{ + + @item{@as-index{@scheme[#:rest]} --- The variable is bound to the + list of ``rest'' arguments, which is the list of all values after + the required and the optional values. This list includes all + keyword-value pairs, exactly as they are specified at the call site. + + Scheme's usual dot-notation is accepted in @scheme[_kw-formals] only + if no other meta-keywords are specified, since it is not clear + whether it should specify the same binding as a @scheme[#:rest] or + as a @scheme[#:body]. The dot notation is allowed without + meta-keywords to make the @scheme[lambda/kw] syntax compatible with + @scheme[lambda].} + + @item{@as-index{@scheme[#:body]} --- The variable is bound to all + arguments after keyword--value pairs. (This is different from + Common Lisp's @scheme[&body], which is a synonym for + @scheme[&rest].) More generally, a @scheme[#:body] specification + can be followed by another @scheme[_kw-formals], not just a single + @scheme[_id]; see @secref["kw-body"] for more information.} + + @item{@as-index{@scheme[#:all-keys]} --- the variable is bound to the + list of all keyword-values from the call site, which is always a + proper prefix of a @scheme[#:rest] argument. (If no @scheme[#:body] + arguments are declared, then @scheme[#:all-keys] binds the same as + @scheme[#:rest].) See also @scheme[keyword-get].} + + @item{@scheme[#:other-keys] --- The variable is bound like an + @scheme[#:all-keys] variable, except that all keywords specified in + the @scheme[kw-formals] are removed from the list. When a keyword + is used multiple times at a call cite (and this is allowed), only + the first instances is removed for the @scheme[#:other-keys] + binding.} + + @item{@scheme[#:other-keys+body] --- the variable is bound like a + @scheme[#:rest] variable, except that all keywords specified in the + @scheme[_kw-formals] are removed from the list. When a keyword is + used multiple times at a call site (and this is allowed), only the + first instance us removed for the @scheme[#:other-keys+body] + binding. (When no @scheme[#:body] variables are specified, then + @scheme[#:other-keys+body] is the same as @scheme[#:other-keys].)} + +} + +In the following example, all rest-like arguments are used and have different +bindings: + +@examples[ +#:eval kw-eval +((lambda/kw (#:key x y + #:rest r + #:other-keys+body rk + #:all-keys ak + #:other-keys ok + #:body b) + (list r rk b ak ok)) + #:z 1 #:x 2 2 3 4) +] + +Note that the following invariants always hold: + +@itemize{ +@item{@scheme[_rest] = @scheme[(append _all-keys _body)]} +@item{@scheme[_other-keys+body] = @scheme[(append _other-keys _body)]} +} + +To write a procedure that uses a few keyword argument values, and that +also calls another procedure with the same list of arguments +(including all keywords), use @scheme[#:other-keys] (or +@scheme[#:other-keys+body]). The Common Lisp approach is to specify +@scheme[:allow-other-keys], so that the second procedure call will not +cause an error due to unknown keywords, but the +@scheme[:allow-other-keys] approach risks confusing the two layers of +keywords. + +@; ---------------------------------------- + +@section[#:tag "kw-body"]{Body Argument} + +The most notable divergence from Common Lisp in @scheme[lambda/kw] is +the @scheme[#:body] argument, and the fact that it is possible at a +call site to pass plain values after the keyword-value pairs. The +@scheme[#:body] binding is useful for procedure calls that use +keyword-value pairs as sort of an attribute list before the actual +arguments to the procedure. For example, consider a procedure that +accepts any number of numeric arguments and will apply a procedure to +them, but the procedure can be specified as an optional keyword +argument. It is easily implemented with a @scheme[#:body] argument: + +@examples[ +#:eval kw-eval +(define/kw (mathop #:key [op +] #:body b) + (apply op b)) +(mathop 1 2 3) +(mathop #:op max 1 2 3) +] + +(Note that the first body value cannot itself be a keyword.) + +A @scheme[#:body] declaration works as an arbitrary +@scheme[kw-formals], not just a single variable like @scheme[b] in the +above example. For example, to make the above @scheme[mathop] work +only on three arguments that follow the keyword, use @scheme[(x y z)] +instead of @scheme[b]: + +@examples[ +#:eval kw-eval +(define/kw (mathop #:key [op +] #:body (x y z)) + (op x y z)) +] + +In general, @scheme[#:body] handling is compiled to a sub procedure +using @scheme[lambda/kw], so that a procedure can use more then one +level of keyword arguments. For example: + +@examples[ +#:eval kw-eval +(define/kw (mathop #:key [op +] + #:body (x y z #:key [convert values])) + (op (convert x) (convert y) (convert z))) +(mathop #:op * 2 4 6 #:convert exact->inexact) +] + +Obviously, nested keyword arguments works only when non-keyword +arguments separate the sets. + +Run-time errors during such calls report a mismatch for a procedure +with a name that is based on the original name plus a @schemeidfont{~body} +suffix: + +@examples[ +#:eval kw-eval +(mathop #:op * 2 4) +] + +@; ---------------------------------------- + +@section[#:tag "mode-keywords"]{Mode Keywords} + +Finally, the argument list of a @scheme[lambda/kw] can contain +keywords that serve as mode flags to control error reporting. + +@itemize{ + + @item{@as-index{@scheme[#:allow-other-keys]} --- The keyword-value + sequence at the call site @italic{can} include keywords that are not + listed in the keyword part of the @scheme[lambda/kw] form.} + + @item{@as-index{@scheme[#:forbid-other-keys]} --- The keyword-value + sequence at the call site @italic{cannot} include keywords that are + not listed in the keyword part of the @scheme[lambda/kw] form, + otherwise the @scheme[exn:fail:contract] exception is raised.} + + @item{@as-index{@scheme[#:allow-duplicate-keys]} --- The + keyword-value list at the call site @emph{can} include duplicate + values associated with same keyword, the first one is used.} + + @item{@as-index{@scheme[#:forbid-duplicate-keys]} --- The + keyword-value list at the call site @italic{cannot} include + duplicate values for keywords, otherwise the + @scheme[exn:fail:contract] exception is raised. This restriction + applies only to keywords that are listed in the keyword part of the + @scheme[lambda/kw] form --- if other keys are allowed, this + restriction does not apply to them.} + + @item{@as-index{@scheme[#:allow-body]} --- Body arguments + @italic{can} be specified at the call site after all keyword-value + pairs.} + + @item{@as-index{@scheme[#:forbid-body]} --- Body arguments + @italic{cannot} be specified at the call site after all + keyword-value pairs.} + + @item{@as-index{@scheme[#:allow-anything]} --- Allows all of the + above, and treat a single keyword at the end of an argument list as + a @scheme[#:body], a situation that is usually an error. When this + is used and no rest-like arguments are used except @scheme[#:rest], + an extra loop is saved and calling the procedures is faster (around + 20%).} + + @item{@as-index{@scheme[#:forbid-anything]} --- Forbids all of the + above, ensuring that calls are as restricted as possible.} + +} + +These above mode markers are rarely needed, because the default modes +are determined by the declared rest-like arguments: + +@itemize{ + + @item{The default is to allow other keys if a @scheme[#:rest], + @scheme[#:other-keys+body], @scheme[#:all-keys], or + @scheme[#:other-keys] variable is declared (and an + @scheme[#:other-keys] declaration requires allowing other keys).} + + @item{The default is to allow duplicate keys if a @scheme[#:rest] or + @scheme[#:all-keys] variable is declared.} + + @item{The default is to allow body arguments if a @scheme[#:rest], + @scheme[#:body], or @scheme[#:other-keys+body] variable is declared + (and a @scheme[#:body] argument requires allowing them).} + +} + +Here's an alternate specification, which maps rest-like arguments to +the behavior that they imply: + +@itemize{ + + @item{@scheme[#:rest]: Everything is allowed (a body, other keys, + and duplicate keys);} + + @item{@scheme[#:other-keys+body]: Other keys and body are allowed, + but duplicates are not;} + + @item{@scheme[#:all-keys]: Other keys and duplicate keys are allowed, + but a body is not;} + + @item{@scheme[#:other-keys]: Other keys must be allowed (on by + default, cannot use with @scheme[#:forbid-other-keys]), and + duplicate keys and body are not allowed;} + + @item{@scheme[#:body]: Body must be allowed (on by default, cannot use + with @scheme[#:forbid-body]) and other keys and duplicate keys and + body are not allowed;} + + @item{Except for the previous two ``must''s, defaults can be + overridden by an explicit @scheme[#:allow-...] or a + @scheme[#:forbid-...] mode.} + +} + +@; ---------------------------------------- + +@section[#:tag "keyword-get"]{Property Lists} + +@defproc[(keyword-get [args (listof (cons/c keyword? any/c))] [kw keyword?] + [not-found (-> any)]) + any]{ + +Searches a list of keyword arguments (a ``property list'' or ``plist'' +in Lisp jargon) for the given keyword, and returns the associated +value. It is the facility that is used by @scheme[lambda/kw] to +search for keyword values. + +The @scheme[args] list is scanned from left to right, if the keyword +is found, then the next value is returned. If the @scheme[kw] was not +found, then the @scheme[not-found] thunk is used to produce a value by +applying it. If the @scheme[kw] was not found, and @scheme[not-found] +thunk is not given, @scheme[#f] is returned. (No exception is raised +if the @scheme[args] list is imbalanced, and the search stops at a +non-keyword value.)} + + diff --git a/collects/mzlib/scribblings/mzlib.scrbl b/collects/mzlib/scribblings/mzlib.scrbl new file mode 100644 index 0000000000..e7e051b057 --- /dev/null +++ b/collects/mzlib/scribblings/mzlib.scrbl @@ -0,0 +1,155 @@ +#lang scribble/doc +@(require "common.ss") + +@title{@bold{MzLib}: Legacy PLT Libraries} + +The @filepath{mzlib} collection contains wrappers and libraries for +compatibility with older versions of PLT Scheme. In many ways, the +libraries of the @filepath{mzlib} collection go with the +@schememodname[mzscheme] legacy language. Newer variants of many +libraries reside in the @filepath{scheme} collection. + +@table-of-contents[] + +@; ---------------------------------------------------------------------- + +@mzlib[a-signature] + +Like @schememodname[scheme/signature] in @hash-lang[] form for +defining a single signature within a module, but based on +@schememodname[mzscheme] instead of @schememodname[scheme/base]. + +@; ---------------------------------------------------------------------- + +@mzlib[a-unit] + +Like @schememodname[scheme/unit] in @hash-lang[] form for defining a +single unit within a module, but based on @schememodname[mzscheme] +instead of @schememodname[scheme/base]. + +@; ---------------------------------------------------------------------- + +@mzlib[async-channel] + +Re-exports @schememodname[scheme/async-channel]. + +@; ---------------------------------------------------------------------- + +@include-section["awk.scrbl"] + +@; ---------------------------------------------------------------------- + +@mzlib[class] + +Re-exports @schememodname[scheme/class], except for the contract +constructors. + +@; ---------------------------------------------------------------------- + +@include-section["class100.scrbl"] + +@; ---------------------------------------------------------------------- + +@mzlib[cm] + +Re-exports @schememodname[compiler/cm]. + +@; ---------------------------------------------------------------------- + +@mzlib[cm-accomplice] + +Re-exports @schememodname[compiler/cm-accomplice]. + +@; ---------------------------------------------------------------------- + +@include-section["cmdline.scrbl"] + +@; ---------------------------------------------------------------------- + +@include-section["cml.scrbl"] + +@; ---------------------------------------------------------------------- + +@include-section["compat.scrbl"] + +@; ---------------------------------------------------------------------- + +@include-section["compile.scrbl"] + +@; ---------------------------------------------------------------------- + +@include-section["contract.scrbl"] + +@; ---------------------------------------------------------------------- + +@mzlib[control] + +Re-exports @schememodname[scheme/control]. + +@; ---------------------------------------------------------------------- + +@mzlib[date] + +Re-exports @schememodname[scheme/date]. + +@; ---------------------------------------------------------------------- + +@mzlib[deflate] + +Re-exports @schememodname[file/gzip]. + +@; ---------------------------------------------------------------------- + +@include-section["defmacro.scrbl"] + +@; ---------------------------------------------------------------------- + +@include-section["etc.scrbl"] + +@; ---------------------------------------------------------------------- + +@include-section["file.scrbl"] + +@; ---------------------------------------------------------------------- + +@include-section["for.scrbl"] + +@; ---------------------------------------------------------------------- + +@mzlib[foreign] + +Re-exports @schememodname[scheme/foreign]. + +@; ---------------------------------------------------------------------- + +@include-section["include.scrbl"] + +@; ---------------------------------------------------------------------- + +@mzlib[inflate] + +Re-exports @schememodname[file/gunzip]. + +@; ---------------------------------------------------------------------- + +@include-section["integer-set.scrbl"] + +@; ---------------------------------------------------------------------- + +@include-section["kw.scrbl"] + +@; ---------------------------------------------------------------------- + +@(bibliography + + (bib-entry #:key "Shivers06" + #:title "Scsh Reference Manual" + #:author "Olin Shivers, Brian D. Carlstrom, Martin Gasbichler, and Mike Sperber" + #:date "2006") + + (bib-entry #:key "Reppy99" + #:title @italic{Concurrent Programming in ML} + #:author "John H. Reppy" + #:date "1999") + + ) diff --git a/collects/mzscheme/info.ss b/collects/mzscheme/info.ss index 53559b3f0f..384431df5e 100644 --- a/collects/mzscheme/info.ss +++ b/collects/mzscheme/info.ss @@ -2,4 +2,6 @@ (define name "MzScheme") (define version '(400)) + (define scribblings '(("mzscheme.scrbl" (multi-page)))) +(define doc-categories '(legacy)) diff --git a/collects/r5rs/info.ss b/collects/r5rs/info.ss index 2cb07e8e46..5e9aafb613 100644 --- a/collects/r5rs/info.ss +++ b/collects/r5rs/info.ss @@ -3,7 +3,7 @@ (define name "R5RS") (define scribblings '(("r5rs.scrbl" (multi-page)))) -(define doc-categories '((language -1))) +(define doc-categories '((legacy 1))) (define mzscheme-launcher-names '("PLT R5RS")) (define mzscheme-launcher-libraries '("run.ss")) diff --git a/collects/scheme/async-channel.ss b/collects/scheme/async-channel.ss index f8def658d4..79080675ce 100644 --- a/collects/scheme/async-channel.ss +++ b/collects/scheme/async-channel.ss @@ -1,4 +1,163 @@ #lang scheme/base -(require mzlib/async-channel) -(provide (all-from-out mzlib/async-channel)) +(require scheme/contract) + +;; This library implements buffered channels with +;; and optional buffer limit (so that puts block +;; if the buffer is full). + +;; We make a fancy structure just so an async-channel +;; can be supplied directly to `sync'. +;; The alternative is to use `define-struct' and supply +;; a `async-channel-get-evt' procedure. +(define-values (struct:ac make-ac async-channel? ac-ref ac-set!) + (make-struct-type 'async-channel #f 5 0 #f + (list (cons prop:evt + ;; This is the guard that is called when + ;; we use an async-channel as an event + ;; (to get). + (lambda (ac) + (async-channel-get-guard ac)))) + (current-inspector) #f)) +(define ac-enqueue-ch (make-struct-field-accessor ac-ref 0)) +(define ac-dequeue-ch (make-struct-field-accessor ac-ref 1)) +(define ac-empty-ch (make-struct-field-accessor ac-ref 2)) +(define ac-full-ch (make-struct-field-accessor ac-ref 3)) +(define ac-thread (make-struct-field-accessor ac-ref 4)) + +;; Make ---------------------------------------- + +(define make-async-channel + (lambda ([limit #f]) + (let* ([enqueue-ch (make-channel)] ; for puts + [dequeue-ch (make-channel)] ; for gets + [empty-ch (make-channel)] ; for get polls + [full-ch (make-channel)] ; for put polls + [queue-first (mcons #f null)] ; queue head + [queue-last queue-first] ; queue tail + [size 0] ; queue size + ;; Events: + [tell-empty + (channel-put-evt empty-ch (make-semaphore))] ; see poll->ch + [tell-full + (channel-put-evt full-ch (make-semaphore))] ; see poll->ch + [enqueue (handle-evt + enqueue-ch + (lambda (v) + ;; We received a put; enqueue it: + (let ([p (mcons #f null)]) + (set-mcar! queue-last v) + (set-mcdr! queue-last p) + (set! queue-last p) + (set! size (add1 size)))))] + [mk-dequeue + (lambda () + (handle-evt + (channel-put-evt dequeue-ch (mcar queue-first)) + (lambda (ignored) + ;; A get succeeded; dequeue it: + (set! size (sub1 size)) + (set! queue-first (mcdr queue-first)))))] + [manager-thread + ;; This thread is the part that makes the channel asynchronous. + ;; It waits for a combination of gets and puts as appropriate. + ;; Note that we start it with `thread/suspend-kill', and we + ;; resume the manager thread with the current thread everytime + ;; we want to talk to the manager thread, which effectively + ;; means that the manager thread is not bound by a custodian + ;; that is weaker than any of its user's custodians (and thus, + ;; from the user's perspective, is not bound by any custodian + ;; at all). + (thread/suspend-to-kill + (lambda () + (let loop () + (cond + [(zero? size) + ;; The queue is currently empty: + (sync enqueue tell-empty)] + [(or (not limit) (size . < . limit)) + (sync enqueue (mk-dequeue))] + [else + (sync (mk-dequeue) tell-full)]) + (loop))))]) + (make-ac enqueue-ch dequeue-ch empty-ch full-ch manager-thread)))) + +;; Get ---------------------------------------- + +(define (async-channel-get-guard ac) + ;; Make sure queue manager is running: + (thread-resume (ac-thread ac) (current-thread)) + ;; If it the channel is being polled, it's not + ;; good enough to poll the dequeue channel, because + ;; the server thread may be looping. In that case, + ;; block on the dequeue channel and the empty + ;; channel, and create a new waitable to report + ;; the result. + (poll-guard-evt + (lambda (poll?) + (if poll? + (poll->ch (ac-dequeue-ch ac) (ac-empty-ch ac)) + (ac-dequeue-ch ac))))) + +(define (async-channel-get ac) + (sync ac)) + +(define (async-channel-try-get ac) + (sync/timeout 0 ac)) + +;; Put ---------------------------------------- + +(define (async-channel-put-evt ac v) + (letrec ([p (wrap-evt + (guard-evt + (lambda () + ;; Make sure queue manager is running: + (thread-resume (ac-thread ac) (current-thread)) + (let ([p (channel-put-evt (ac-enqueue-ch ac) v)]) + ;; Poll handling, as in `async-channel-get-guard': + (poll-guard-evt + (lambda (poll?) + (if poll? + (poll->ch p (ac-full-ch ac)) + p)))))) + (lambda (ignored) p))]) + p)) + +(define (async-channel-put ac v) + (thread-resume (ac-thread ac) (current-thread)) + (sync (channel-put-evt (ac-enqueue-ch ac) v)) + (void)) + +;; Poll helper ---------------------------------------- + +(define (poll->ch normal not-ready) + (sync + ;; If a value becomes available, + ;; create a waitable that returns + ;; the value: + (wrap-evt + normal + (lambda (v) + ;; Return a waitable for a successful poll: + (wrap-evt + always-evt + (lambda (ignored) v)))) + ;; If not-ready becomes available, + ;; the result is supposed to be + ;; a never-ready waitable: + not-ready)) + +;; Provides ---------------------------------------- + +(provide async-channel?) +(provide/contract (make-async-channel (case-> + (-> async-channel?) + ((union false/c (lambda (x) + (and (integer? x) + (exact? x) + (positive? x)))) + . -> . async-channel?))) + (async-channel-get (async-channel? . -> . any/c)) + (async-channel-try-get (async-channel? . -> . any/c)) + (async-channel-put (async-channel? any/c . -> . any/c)) + (async-channel-put-evt (async-channel? any/c . -> . evt?))) diff --git a/collects/scheme/fasl.ss b/collects/scheme/fasl.ss new file mode 100644 index 0000000000..e996342a1d --- /dev/null +++ b/collects/scheme/fasl.ss @@ -0,0 +1,30 @@ +#lang scheme/base + +(provide s-exp->fasl + fasl->s-exp) + +(define (s-exp->fasl v [out #f]) + (when out + (unless (output-port? out) + (raise-type-error 'fasl->s-exp "output-port or #f" out))) + (let ([p (or out + (open-output-bytes))]) + (parameterize ([current-namespace (make-base-namespace)]) + (write (compile `(quote ,v)) p)) + (if out + (void) + (get-output-bytes p)))) + +(define (fasl->s-exp b) + (unless (or (bytes? b) + (input-port? b)) + (raise-type-error 'fasl->s-exp "bytes or input-port" b)) + (let ([p (if (bytes? b) + (open-input-bytes b) + b)]) + (let ([e (parameterize ([read-accept-compiled #t]) + (read p))]) + (if (compiled-expression? e) + (parameterize ([current-namespace (make-base-namespace)]) + (eval e)) + e)))) diff --git a/collects/scheme/signature/lang/reader.ss b/collects/scheme/signature/lang/reader.ss index a57d1dfa20..765b406426 100644 --- a/collects/scheme/signature/lang/reader.ss +++ b/collects/scheme/signature/lang/reader.ss @@ -1,3 +1,2 @@ (module reader syntax/module-reader scheme/signature/lang) - diff --git a/collects/scribble/manual.ss b/collects/scribble/manual.ss index daf0434bc8..aa11e6d710 100644 --- a/collects/scribble/manual.ss +++ b/collects/scribble/manual.ss @@ -1856,7 +1856,7 @@ (cond [(string? i) (cond - [(regexp-match #rx"^(.*)([()0-9])(.*)$" i) + [(regexp-match #px"^(.*)([()0-9{}\\[\\]])(.*)$" i) => (lambda (m) (append (loop (cadr m)) (list (caddr m)) diff --git a/collects/scribblings/reference/class.scrbl b/collects/scribblings/reference/class.scrbl index d8bdab0020..3ff6937ee6 100644 --- a/collects/scribblings/reference/class.scrbl +++ b/collects/scribblings/reference/class.scrbl @@ -75,7 +75,7 @@ @title[#:tag "mzlib:class" #:style 'toc]{Classes and Objects} -@note-lib[scheme/class] +@note-lib[scheme/class #:use-sources (scheme/private/class-internal)] @local-table-of-contents[] diff --git a/collects/scribblings/reference/mz.ss b/collects/scribblings/reference/mz.ss index 42e7f08dc0..02fcbcc543 100644 --- a/collects/scribblings/reference/mz.ss +++ b/collects/scribblings/reference/mz.ss @@ -17,17 +17,22 @@ (provide AllUnix) (provide note-lib) - (define-syntax-rule (note-lib lib . more) - (begin - (declare-exporting lib scheme) - (defmodule*/no-declare (lib) - (t "The bindings documented in this section are provided by the " - (schememodname lib) - " and " - (schememodname scheme) - " libraries, but not " (schememodname scheme/base) - "." - . more)))) + (define-syntax note-lib + (syntax-rules () + [(_ lib #:use-sources (src ...) . more) + (begin + (declare-exporting lib scheme #:use-sources (src ...)) + (defmodule*/no-declare (lib) + (t "The bindings documented in this section are provided by the " + (schememodname lib) + " and " + (schememodname scheme) + " libraries, but not " (schememodname scheme/base) + "." + . more)))] + [(_ lib . more) + (note-lib lib #:use-sources () . more)])) + (provide note-lib-only) (define-syntax-rule (note-lib-only lib . more) diff --git a/collects/scribblings/reference/paths.scrbl b/collects/scribblings/reference/paths.scrbl index 0d3c700a33..09d4d5c070 100644 --- a/collects/scribblings/reference/paths.scrbl +++ b/collects/scribblings/reference/paths.scrbl @@ -197,21 +197,22 @@ Returns the path convention type of the current platform: Windows.} -@defproc[(build-path [base path-string?] - [sub (or/c path-string? +@defproc[(build-path [base (or/c path-string? + (one-of/c 'up 'same))] + [sub (or/c (and/c path-string? + (not/c complete-path?)) (one-of/c 'up 'same))] ...) path?]{ Creates a path given a base path and any number of sub-path extensions. If @scheme[base] is an absolute path, the result is an -absolute path; if @scheme[base] is a relative path, the result is a -relative path. +absolute path, otherwise the result is a relative path. -Each @scheme[sub] must be either a relative path, the symbol -@indexed-scheme['up] (indicating the relative parent directory), or -the symbol @indexed-scheme['same] (indicating the relative current -directory). For Windows paths, if @scheme[base] is a drive -specification (with or without a trailing slash) the first +The @scheme[base] and each @scheme[sub] must be either a relative +path, the symbol @indexed-scheme['up] (indicating the relative parent +directory), or the symbol @indexed-scheme['same] (indicating the +relative current directory). For Windows paths, if @scheme[base] is a +drive specification (with or without a trailing slash) the first @scheme[sub] can be an absolute (driveless) path. For all platforms, the last @scheme[sub] can be a filename. diff --git a/collects/scribblings/start/manuals.ss b/collects/scribblings/start/manuals.ss index 84f0215f56..c45991a1b1 100644 --- a/collects/scribblings/start/manuals.ss +++ b/collects/scribblings/start/manuals.ss @@ -30,6 +30,8 @@ "Libraries") (make-sec 'foreign "Low-Level APIs") + (make-sec 'legacy + "Legacy Languages and Libraries") (make-sec 'other "Other"))) @@ -81,7 +83,7 @@ (car new-cat) new-cat)]) (case the-cat - [(getting-started language tool library foreign other omit) + [(getting-started language tool library foreign legacy other omit) the-cat] [else (fprintf (current-error-port) diff --git a/collects/setup/scribble.ss b/collects/setup/scribble.ss index 94e3397a98..61c90ccad0 100644 --- a/collects/setup/scribble.ss +++ b/collects/setup/scribble.ss @@ -5,6 +5,7 @@ "private/doc-path.ss" scheme/class scheme/file + scheme/fasl setup/main-collects scribble/base-render scribble/struct @@ -301,6 +302,10 @@ (and (pair? cat) (eq? (car cat) 'omit)))) + +(define (read-out-sxref) + (fasl->s-exp (current-input-port))) + (define ((get-doc-info only-dirs latex-dest auto-main? auto-user? with-record-error) doc) (let* ([info-out-file (build-path (or latex-dest (doc-dest-dir doc)) "out.sxref")] [info-in-file (build-path (or latex-dest (doc-dest-dir doc)) "in.sxref")] @@ -352,7 +357,7 @@ ((get-doc-info only-dirs latex-dest auto-main? auto-user? with-record-error) doc))]) (let* ([v-in (with-input-from-file info-in-file read)] - [v-out (with-input-from-file info-out-file read)]) + [v-out (with-input-from-file info-out-file read-out-sxref)]) (unless (and (equal? (car v-in) (list vers (doc-flags doc))) (equal? (car v-out) (list vers (doc-flags doc)))) (error "old info has wrong version or flags")) @@ -383,7 +388,7 @@ [ri (send renderer resolve (list v) (list dest-dir) ci)] [out-v (and info-out-time (with-handlers ([exn? (lambda (exn) #f)]) - (let ([v (with-input-from-file info-out-file read)]) + (let ([v (with-input-from-file info-out-file read-out-sxref)]) (unless (equal? (car v) (list vers (doc-flags doc))) (error "old info has wrong version or flags")) v)))] @@ -505,24 +510,24 @@ (when (verbose) (printf " [Caching ~a]\n" info-file)) (with-output-to-file info-file #:exists 'truncate/replace (lambda () - (write ((sel (lambda () - (list (list (info-vers info) (doc-flags doc)) - (info-sci info) - (info-provides info))) - (lambda () - (list (list (info-vers info) (doc-flags doc)) - (info-undef info) - (map (lambda (i) - (path->rel (doc-src-file (info-doc i)))) - (info-deps info)) - (info-searches info)))))))))) + (sel (lambda () + (list (list (info-vers info) (doc-flags doc)) + (info-sci info) + (info-provides info))) + (lambda () + (list (list (info-vers info) (doc-flags doc)) + (info-undef info) + (map (lambda (i) + (path->rel (doc-src-file (info-doc i)))) + (info-deps info)) + (info-searches info)))))))) (define (write-out info) (make-directory* (doc-dest-dir (info-doc info))) - (write- info "out.sxref" (lambda (o i) o))) + (write- info "out.sxref" (lambda (o i) (write-bytes (s-exp->fasl (o)))))) (define (write-in info) (make-directory* (doc-dest-dir (info-doc info))) - (write- info "in.sxref" (lambda (o i) i))) + (write- info "in.sxref" (lambda (o i) (write (i))))) (define (rel->path r) (if (bytes? r) diff --git a/collects/setup/xref.ss b/collects/setup/xref.ss index 533d0fb59e..e2ddab710e 100644 --- a/collects/setup/xref.ss +++ b/collects/setup/xref.ss @@ -2,6 +2,7 @@ (require scribble/xref setup/getinfo + scheme/fasl "private/doc-path.ss") (provide load-collections-xref) @@ -45,7 +46,7 @@ (exn-message exn) (format "~e" exn))) #f)]) - (let ([r (with-input-from-file dest read)]) + (let ([r (call-with-input-file* dest fasl->s-exp)]) (cadr r))))) dests))) cached-xref))))