start scribbling mzlib (about half done)
svn: r8546
This commit is contained in:
parent
f3bbc44451
commit
8bac4b1d28
|
@ -2,3 +2,4 @@
|
|||
|
||||
(define name "Graphics documentation")
|
||||
(define scribblings '(("graphics.scrbl" (multi-page))))
|
||||
(define doc-categories '(legacy))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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?)
|
||||
|
|
69
collects/mzlib/scribblings/awk.scrbl
Normal file
69
collects/mzlib/scribblings/awk.scrbl
Normal file
|
@ -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.}
|
83
collects/mzlib/scribblings/class100.scrbl
Normal file
83
collects/mzlib/scribblings/class100.scrbl
Normal file
|
@ -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].}
|
||||
|
38
collects/mzlib/scribblings/cmdline.scrbl
Normal file
38
collects/mzlib/scribblings/cmdline.scrbl
Normal file
|
@ -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.}
|
45
collects/mzlib/scribblings/cml.scrbl
Normal file
45
collects/mzlib/scribblings/cml.scrbl
Normal file
|
@ -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)].}
|
19
collects/mzlib/scribblings/common.ss
Normal file
19
collects/mzlib/scribblings/common.ss
Normal file
|
@ -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)]))
|
96
collects/mzlib/scribblings/compat.scrbl
Normal file
96
collects/mzlib/scribblings/compat.scrbl
Normal file
|
@ -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?]
|
||||
@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].}
|
||||
|
34
collects/mzlib/scribblings/compile.scrbl
Normal file
34
collects/mzlib/scribblings/compile.scrbl
Normal file
|
@ -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].}
|
8
collects/mzlib/scribblings/contract.scrbl
Normal file
8
collects/mzlib/scribblings/contract.scrbl
Normal file
|
@ -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....
|
||||
|
67
collects/mzlib/scribblings/defmacro.scrbl
Normal file
67
collects/mzlib/scribblings/defmacro.scrbl
Normal file
|
@ -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.}
|
272
collects/mzlib/scribblings/etc.scrbl
Normal file
272
collects/mzlib/scribblings/etc.scrbl
Normal file
|
@ -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.}
|
64
collects/mzlib/scribblings/file.scrbl
Normal file
64
collects/mzlib/scribblings/file.scrbl
Normal file
|
@ -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.}
|
45
collects/mzlib/scribblings/for.scrbl
Normal file
45
collects/mzlib/scribblings/for.scrbl
Normal file
|
@ -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]
|
68
collects/mzlib/scribblings/include.scrbl
Normal file
68
collects/mzlib/scribblings/include.scrbl
Normal file
|
@ -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].}
|
||||
|
5
collects/mzlib/scribblings/info.ss
Normal file
5
collects/mzlib/scribblings/info.ss
Normal file
|
@ -0,0 +1,5 @@
|
|||
#lang setup/infotab
|
||||
|
||||
(define name "MzLib documentation")
|
||||
(define scribblings '(("mzlib.scrbl" (multi-page))))
|
||||
(define doc-categories '(legacy))
|
145
collects/mzlib/scribblings/integer-set.scrbl
Normal file
145
collects/mzlib/scribblings/integer-set.scrbl
Normal file
|
@ -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].}
|
||||
|
447
collects/mzlib/scribblings/kw.scrbl
Normal file
447
collects/mzlib/scribblings/kw.scrbl
Normal file
|
@ -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.)}
|
||||
|
||||
|
155
collects/mzlib/scribblings/mzlib.scrbl
Normal file
155
collects/mzlib/scribblings/mzlib.scrbl
Normal file
|
@ -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")
|
||||
|
||||
)
|
|
@ -2,4 +2,6 @@
|
|||
|
||||
(define name "MzScheme")
|
||||
(define version '(400))
|
||||
|
||||
(define scribblings '(("mzscheme.scrbl" (multi-page))))
|
||||
(define doc-categories '(legacy))
|
||||
|
|
|
@ -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"))
|
||||
|
|
|
@ -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?)))
|
||||
|
|
30
collects/scheme/fasl.ss
Normal file
30
collects/scheme/fasl.ss
Normal file
|
@ -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))))
|
|
@ -1,3 +1,2 @@
|
|||
(module reader syntax/module-reader
|
||||
scheme/signature/lang)
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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[]
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))))
|
||||
|
|
Loading…
Reference in New Issue
Block a user