Simplifying chibi docs with \procedure and \macro utils.

This commit is contained in:
Alex Shinn 2014-02-02 16:26:19 +09:00
parent 87bc0f0106
commit e5c243ee10
16 changed files with 198 additions and 177 deletions

View file

@ -6,14 +6,14 @@
;;> the compiler, and other core types less commonly
;;> needed in user code, plus related utilities.
;;> \subsubsection{Analysis and Expansion}
;;> \section{Analysis and Expansion}
;;> \subsubsubsection{\scheme{(analyze x [env])}}
;;> \procedure{(analyze x [env])}
;;> Expands and analyzes the expression \var{x} and returns the
;;> resulting AST.
;;> \subsubsubsection{\scheme{(optimize ast)}}
;;> \procedure{(optimize ast)}
;;> Runs an optimization pass on \var{ast} and returns the
;;> resulting simplified expression.
@ -109,7 +109,7 @@
((opcode? x) (cond ((opcode-name x) => string->symbol) (else x)))
(else x)))))
;;> \subsubsection{Types}
;;> \section{Types}
;;> All objects have an associated type, and types may have parent
;;> types. When using
@ -169,15 +169,15 @@
;;> \item{\scheme{exception?}}
;;> ]
;;> \subsubsubsection{\scheme{(type-of x)}}
;;> \procedure{(type-of x)}
;;> Returns the type of any object \var{x}.
;;> \subsubsubsection{\scheme{(type-name type)}}
;;> \procedure{(type-name type)}
;;> Returns the name of type \var{type}.
;;> \subsubsubsection{\scheme{(type-parent type)}}
;;> \procedure{(type-parent type)}
;;> Returns the immediate parent of type \var{type},
;;> or \scheme{#f} for a type with no parent.
@ -188,21 +188,21 @@
(> (vector-length v) 1)
(vector-ref v (- (vector-length v) 2)))))
;;> \subsubsubsection{\scheme{(type-cpl type)}}
;;> \procedure{(type-cpl type)}
;;> Returns the class precedence list of type \var{type} as a
;;> vector, or \scheme{#f} for a type with no parent.
;;> \subsubsubsection{\scheme{(type-slots type)}}
;;> \procedure{(type-slots type)}
;;> Returns the slot list of type \var{type}.
;;> \subsubsection{Accessors}
;;> \section{Accessors}
;;> This section describes additional accessors on AST and other core
;;> types.
;;> \subsubsubsection{Procedures}
;;> \subsection{Procedures}
;;> \itemlist[
;;> \item{\scheme{(procedure-code f)} - the compiled bytecode object}
@ -216,7 +216,7 @@
(define (procedure-name-set! x name)
(bytecode-name-set! (procedure-code x) name))
;;> \subsubsubsection{Macros}
;;> \subsection{Macros}
;;> \itemlist[
;;> \item{\scheme{(macro-procedure f)} - the macro procedure}
@ -224,7 +224,7 @@
;;> \item{\scheme{(macro-source f)} - the source location the macro was defined in}
;;> ]
;;> \subsubsubsection{Bytecode Objects}
;;> \subsection{Bytecode Objects}
;;> \itemlist[
;;> \item{\scheme{(bytecode-name bc)} - the macro procedure}
@ -232,7 +232,7 @@
;;> \item{\scheme{(bytecode-source bc)} - the source location the procedure was defined in}
;;> ]
;;> \subsubsubsection{Syntactic Closures}
;;> \subsection{Syntactic Closures}
;;> \itemlist[
;;> \item{\scheme{(syntactic-closure-env sc)}}
@ -243,7 +243,7 @@
;;> Return the environment, free variables, and expression
;;> associated with \var{sc} respectively.
;;> \subsubsubsection{Exceptions}
;;> \subsection{Exceptions}
;;> \itemlist[
;;> \item{\scheme{(exception-kind exn)}}
@ -254,7 +254,7 @@
;;> Return the kind, message, and irritants
;;> associated with \var{exn} respectively.
;;> \subsubsubsection{Lambdas}
;;> \subsection{Lambdas}
;;> \itemlist[
;;> \item{\scheme{(lambda-name lam)} - the name of the lambda, if known}
@ -281,7 +281,7 @@
;;> \item{\scheme{(lambda-source-set! lam x)}}
;;> ]
;;> \subsubsubsection{Conditionals}
;;> \subsection{Conditionals}
;;> \itemlist[
;;> \item{\scheme{(cnd-test cnd)} - the test for the conditional}
@ -292,14 +292,14 @@
;;> \item{\scheme{(cnd-fail-set! cnd x)}}
;;> ]
;;> \subsubsubsection{Sequences}
;;> \subsection{Sequences}
;;> \itemlist[
;;> \item{\scheme{(seq-ls seq)} - the list of sequence expressions}
;;> \item{\scheme{(seq-ls-set! seq x)}}
;;> ]
;;> \subsubsubsection{References}
;;> \subsection{References}
;;> \itemlist[
;;> \item{\scheme{(ref-name ref)} - the name of the referenced variable}
@ -308,7 +308,7 @@
;;> \item{\scheme{(ref-cell-set! ref x)}}
;;> ]
;;> \subsubsubsection{Mutations}
;;> \subsection{Mutations}
;;> \itemlist[
;;> \item{\scheme{(set-var set)} - a reference to the mutated variable}
@ -317,14 +317,14 @@
;;> \item{\scheme{(set-value-set! set x)}}
;;> ]
;;> \subsubsubsection{Literals}
;;> \subsection{Literals}
;;> \itemlist[
;;> \item{\scheme{(lit-value lit)} - the literal value}
;;> \item{\scheme{(lit-value-set! lit x)}}
;;> ]
;;> \subsubsubsection{Pairs}
;;> \subsection{Pairs}
;;> \itemlist[
;;> \item{\scheme{(pair-source x)}}
@ -335,28 +335,28 @@
;;> Source info is represented as another pair whose \var{car} is
;;> the source file name and whose \var{cdr} is the line number.
;;> \subsubsection{Miscellaneous Utilities}
;;> \section{Miscellaneous Utilities}
;;> \subsubsubsection{\scheme{(gc)}}
;;> \procedure{(gc)}
;;> Force a garbage collection.
;;> \subsubsubsection{\scheme{(object-size x)}}
;;> \procedure{(object-size x)}
;;> Returns the heap space directly used by \var{x}, not
;;> counting any elements of \var{x}.
;;> \subsubsubsection{\scheme{(integer->immediate n)}}
;;> \procedure{(integer->immediate n)}
;;> Returns the interpretation of the integer \var{n} as
;;> an immediate object, useful for debugging.
;;> \subsubsubsection{\scheme{(string-contains str pat)}}
;;> \procedure{(string-contains str pat)}
;;> Returns the first string cursor of \var{pat} in \var{str},
;;> of \scheme{#f} if it's not found.
;;> \subsubsubsection{\scheme{(atomically expr)}}
;;> \procedure{(atomically expr)}
;;> Run \var{expr} atomically, disabling yields. Ideally should only be
;;> used for brief, deterministic expressions. If used incorrectly (e.g.

View file

@ -1,30 +1,8 @@
;; Copyright (c) 2005-2009 Alex Shinn. All rights reserved.
;; Copyright (c) 2005-2014 Alex Shinn. All rights reserved.
;; BSD-style license: http://synthcode.com/license.txt
;; Procedure: base64-encode-string str
;; Return a base64 encoded representation of string according to the
;; official base64 standard as described in RFC3548.
;; Procedure: base64-decode-string str
;; Return a base64 decoded representation of string, also interpreting
;; the alternate 62 & 63 valued characters as described in RFC3548.
;; Other out-of-band characters are silently stripped, and = signals
;; the end of the encoded string. No errors will be raised.
;; Procedure: base64-encode [port]
;; Procedure: base64-decode [port]
;; Variations of the above which read and write to ports.
;; Procedure: base64-encode-header enc str [start-col max-col nl]
;; Return a base64 encoded representation of string as above,
;; wrapped in =?ENC?B?...?= as per RFC1522, split across multiple
;; MIME-header lines as needed to keep each lines length less than
;; MAX-COL. The string is encoded as is, and the encoding ENC is
;; just used for the prefix, i.e. you are responsible for ensuring
;; STR is already encoded according to ENC. The optional argument
;; NL is the newline separator, defaulting to CRLF.
;; This API is compatible with the Gauche library rfc.base64.
;;> RFC 3548 base64 encoding and decoding utilities.
;;> This API is compatible with the Gauche library rfc.base64.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; string utils
@ -103,6 +81,11 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; decoding
;;> Return a base64 decoded representation of string, also interpreting
;;> the alternate 62 & 63 valued characters as described in RFC3548.
;;> Other out-of-band characters are silently stripped, and = signals
;;> the end of the encoded string. No errors will be raised.
;; Create a result buffer with the maximum possible length for the
;; input, and pass it to the internal base64-decode-string! utility.
;; If the resulting length used is exact, we can return that buffer,
@ -199,9 +182,8 @@
(extract-bit-field 4 2 b3))))
(+ j 2))))))
;; General port decoder: work in single blocks at a time to avoid
;; allocating memory (crucial for Scheme implementations that don't
;; allow large strings).
;;> Variation of the above to read and write to ports.
(define (base64-decode . o)
(let ((in (if (pair? o) (car o) (current-input-port)))
(out (if (and (pair? o) (pair? (cdr o)))
@ -253,6 +235,9 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; encoding
;;> Return a base64 encoded representation of string according to the
;;> official base64 standard as described in RFC3548.
(define (base64-encode-string str)
(let* ((len (string-length str))
(quot (quotient len 3))
@ -307,6 +292,8 @@
(string-set! res (+ j 3) (enc (bitwise-and #b111111 b3)))
(lp (+ i 3) (+ j 4)))))))
;;> Variation of the above to read and write to ports.
(define (base64-encode . o)
(let ((in (if (pair? o) (car o) (current-input-port)))
(out (if (and (pair? o) (pair? (cdr o)))
@ -322,6 +309,15 @@
(if (= n 2048)
(lp)))))))
;;> Return a base64 encoded representation of the string \var{str} as
;;> above, wrapped in =?ENC?B?...?= as per RFC1522, split across
;;> multiple MIME-header lines as needed to keep each lines length
;;> less than \var{max-col}. The string is encoded as is, and the
;;> encoding \var{enc} is just used for the prefix, i.e. you are
;;> responsible for ensuring \var{str} is already encoded according to
;;> \var{enc}. The optional argument \var{nl} is the newline
;;> separator, defaulting to \var{crlf}.
(define (base64-encode-header encoding str . o)
(define (round4 i) (arithmetic-shift (arithmetic-shift i -2) 2))
(let ((start-col (if (pair? o) (car o) 0))

View file

@ -1,5 +1,5 @@
;; Additional accessors
;;> \section{Additional accessors}
(define (bytevector-u16-ref-le str i)
(+ (bytevector-u8-ref str i)
@ -21,7 +21,7 @@
(arithmetic-shift (bytevector-u8-ref str (+ i 2)) 8)
(bytevector-u8-ref str (+ i 3))))
;; Integer conversion
;;> \section{Integer conversion}
(define (integer->bytevector n)
(cond
@ -49,7 +49,9 @@
(+ (arithmetic-shift n 8)
(bytevector-u8-ref bv i)))))))
;; Hex string conversion (big-endian, guaranteed padded to even length)
;;> \section{Hex string conversion}
;;> Big-endian conversion, guaranteed padded to even length.
(define (integer->hex-string n)
(let* ((res (number->string n 16))

View file

@ -11,7 +11,7 @@
;;> loading these collections from files while allowing extensions
;;> such as configurations from command-line options.
;;> \subsubsection{Background}
;;> \section{Background}
;;>
;;> As any application grows to sufficient complexity, it acquires
;;> options and behaviors that one may want to modify at startup or
@ -40,7 +40,7 @@
;;> users of a group or whole system are likely to want to share, then
;;> it makes sense to cascade multiple config files.
;;> \subsubsection{Syntax}
;;> \section{Syntax}
;;>
;;> With any other language there is a question of config file syntax,
;;> and a few popular choices exist such as .ini syntax. With Scheme
@ -71,7 +71,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;> \subsubsection{Interface}
;;> \section{Interface}
;;> Returns true iff \var{x} is a config object.
@ -112,7 +112,7 @@
(define (alist? x)
(and (list? x) (every pair? x)))
;;> \subsubsubsection{\rawcode{(assoc-get alist key [equal? [default]])}}
;;> \procedure{(assoc-get alist key [equal? [default]])}
;;> Utility analogous to \scheme{conf-get} on a pure alist. Returns
;;> the value of the cell in \var{alist} whose car is \var{equal?} to
@ -138,7 +138,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Loading from files.
;;> \subsubsubsection{\rawcode{(conf-load file [conf])}}
;;> \procedure{(conf-load file [conf])}
;;> Loads the config file \var{file}, prepending to \var{conf} if
;;> provided.
@ -168,7 +168,7 @@
(lp (cdr ls) (conf-load path res))
(lp (cdr ls) res))))))))
;;> \subsubsubsection{\rawcode{(conf-load-cascaded config-path file [include-keyword])}}
;;> \procedure{(conf-load-cascaded config-path file [include-keyword])}
;;> Similar to conf-load-in-path, but also recursively loads any
;;> "include" config files, indicated by a top-level
@ -230,7 +230,7 @@
(or (assq key (conf-alist config))
(search (conf-parent config))))))))
;;> \subsubsubsection{\rawcode{(conf-get config key [default])}}
;;> \procedure{(conf-get config key [default])}
;;> Basic config lookup - retrieves the value from \var{config}
;;> associated with \var{key}. If not present, return \var{default}.
@ -247,7 +247,7 @@
(cadr cell)
(cdr cell)))))
;;> \subsubsubsection{\rawcode{(conf-get-list config key [default])}}
;;> \procedure{(conf-get-list config key [default])}
;;> Equivalent to \scheme{conf-get} but coerces its result to a list
;;> as described in the syntax section.
@ -338,7 +338,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;> \subsubsection{Config Verification}
;;> \section{Config Verification}
(define (conf-default-warn . args)
(for-each

View file

@ -92,10 +92,13 @@
(list (append (map cons vars vals) (car env))))
(define (make-default-doc-env)
`(((section . ,(expand-section 'h1))
(subsection . ,(expand-section 'h2))
(subsubsection . ,(expand-section 'h3))
(subsubsubsection . ,(expand-section 'h4))
`(((title . ,(expand-section 'h1))
(section . ,(expand-section 'h2))
(subsection . ,(expand-section 'h3))
(subsubsection . ,(expand-section 'h4))
(subsubsubsection . ,(expand-section 'h5))
(procedure . ,expand-procedure)
(macro . ,expand-macro)
(centered . center)
(smaller . small)
(larger . large)
@ -240,6 +243,12 @@
(else
sxml)))
(define (expand-procedure sxml env)
((expand-section 'h3) `(,(car sxml) (rawcode ,@(cdr sxml))) env))
(define (expand-macro sxml env)
(expand-procedure sxml env))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; adjustments for html
@ -252,9 +261,18 @@
(match x
(('div ('a ('@ ('name . name)) . _)
((and h (or 'h1 'h2 'h3 'h4 'h5 'h6)) . section))
`((,(header-index h)
(a (@ (href . ,(string-append "#" name)))
,(sxml-strip (cons h section))))))
(let* ((raw-text (sxml-strip (cons h section)))
(text (if (string-prefix? "(" raw-text)
(let ((end (string-find
raw-text
(lambda (ch)
(or (char-whitespace? ch)
(eqv? ch #\)))))))
(substring raw-text 1 end))
raw-text)))
`((,(header-index h)
(a (@ (href . ,(string-append "#" name)))
,text)))))
((a . b)
(append (extract-contents a) (extract-contents b)))
(else
@ -282,9 +300,9 @@
(style (@ (type . "text/css"))
"
body {color: #000; background-color: #FFF}
div#menu {font-size: smaller; position: absolute; top: 50px; left: 0; width: 180px; height: 100%}
div#main {position: absolute; top: 0; left: 200px; width: 520px; height: 100%}
div#notes {position: relative; top: 2em; left: 550px; max-width: 200px; height: 0px; font-size: smaller;}
div#menu {font-size: smaller; position: absolute; top: 50px; left: 0; width: 190px; height: 100%}
div#main {position: absolute; top: 0; left: 200px; width: 540px; height: 100%}
div#notes {position: relative; top: 2em; left: 570px; max-width: 200px; height: 0px; font-size: smaller;}
div#footer {padding-bottom: 50px}
.result { color: #000; background-color: #FFEADF; width: 100%; padding: 3px}
.command { color: #000; background-color: #FFEADF; width: 100%; padding: 5px}
@ -293,7 +311,11 @@ div#footer {padding-bottom: 50px}
"\n")
(body
(div (@ (id . "menu"))
,(get-contents (extract-contents x)))
,(let ((contents (get-contents (extract-contents x))))
(match contents
(('ol (li y sections ...))
sections)
(else contents))))
(div (@ (id . "main"))
,@(map (lambda (x)
(if (and (pair? x) (eq? 'title (car x)))
@ -469,7 +491,10 @@ div#footer {padding-bottom: 50px}
(define section-number
(let ((sections '(section subsection subsubsection subsubsubsection)))
(lambda (x) (length (or (memq x sections) '())))))
(lambda (x)
(cond ((memq x sections) => length)
((memq x '(procedure macro)) (section-number 'subsection))
(else 0)))))
(define (section>=? x n)
(and (pair? x)
@ -479,7 +504,7 @@ div#footer {padding-bottom: 50px}
(define (extract-sxml tag x)
(and (pair? x)
(cond ((eq? tag (car x)) x)
(cond ((if (pair? tag) (memq (car x) tag) (eq? tag (car x))) x)
((memq (car x) '(div))
(any (lambda (y) (extract-sxml tag y)) (sxml-body x)))
(else #f))))
@ -536,14 +561,15 @@ div#footer {padding-bottom: 50px}
(let lp ((ls orig-ls) (rev-pre '()))
(cond
((or (null? ls)
(section>=? (car ls) (section-number 'subsubsubsection)))
(section>=? (car ls) (section-number 'subsection)))
`(,@(reverse rev-pre)
,@(if (and (pair? ls)
(section-describes?
(extract-sxml 'subsubsubsection (car ls))
(extract-sxml '(subsection procedure macro)
(car ls))
name))
'()
`((subsubsubsection
`((subsection
tag: ,(write-to-string name)
(rawcode
,@(if (eq? 'const: (caar sig))

View file

@ -16,7 +16,7 @@
(let-syntax ((call))
. body))))))
;;> \subsubsubsection{\scheme{(define-method (name params ...) body ...)}}
;;> \macro{(define-method (name params ...) body ...)}
;;> Each parameter should be either a single identifier or a list of the form
;;> \scheme{(param type)} where \var{param} is the parameter name and

View file

@ -3,14 +3,14 @@
;;> runtime memory usage doesn't give a good idea of how to optimize
;;> that usage, so this module is provided for profiling.
;;> \subsubsubsection{(heap-stats)}
;;> \procedure{(heap-stats)}
;;> Returns an alist summarizing all heap allocated objects. The
;;> \var{car} of each cell is the type-name, and the \var{cdr} is the
;;> count of objects of that type in the heap. Garbage is collected
;;> before the counts are taken.
;;> \subsubsubsection{(heap-dump [depth])}
;;> \procedure{(heap-dump [depth])}
;;> Returns the same value as \scheme{(heap-stats)}, but also prints
;;> all objects on the heap as it runs. \var{depth} indicates the

View file

@ -39,7 +39,7 @@
(display str out)
(newline out)))
;;> \subsubsubsection{(write-string str [out [start [end]]])}
;;> \procedure{(write-string str [out [start [end]]])}
;;> Writes the characters from \var{start} to \var{end} of string
;;> \var{str} to output port \var{out}, where \var{start} defaults
@ -60,7 +60,7 @@
(display (substring str start end) out))))
(display str out))))
;;> \subsubsubsection{(read-line [in [n]])}
;;> \procedure{(read-line [in [n]])}
;;> Read a line from the input port \var{in}, defaulting to
;;> \scheme{(current-input-port)}, and return the result as
@ -109,7 +109,7 @@
(else
res)))))))
;;> \subsubsubsection{(read-string n [in])}
;;> \procedure{(read-string n [in])}
;;> Reads \var{n} characters from input-port \var{in},
;;> defaulting to \scheme{(current-input-port)}, and
@ -140,7 +140,7 @@
(port-line in)))
(cadr res)))))))
;;> \subsubsubsection{(read-string! str n [in])}
;;> \procedure{(read-string! str n [in])}
;;> Reads \var{n} characters from port \var{in}, which
;;> defaults to \scheme{(current-input-port)}, and writes

View file

@ -124,7 +124,7 @@
. rest))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;> \subsubsection{Iterators}
;;> \section{Iterators}
;; Each gets passed two lists, those items left of the macro and those to
;; the right, followed by a NEXT and REST continuation.
@ -172,7 +172,7 @@
()
. rest))))
;;> \subsubsubsection{\scheme{(for elts [pairs] (in-lists lol [cdr [done?]]))}}
;;> \macro{(for elts [pairs] (in-lists lol [cdr [done?]]))}
;;> Iterator from Taylor R. Campbell. If you know the number of lists
;;> ahead of time it's much more efficient to iterate over each one
@ -215,12 +215,12 @@
(%in-idx < (lambda (x i) (- i 1)) (lambda (x) (- (length x) 1)) (lambda (x) 0) ref tmp seq next . rest))))
))))
;;> \subsubsubsection{\scheme{(for var [index] (in-vector vec))}}
;;> \subsubsubsection{\scheme{(for var [index] (in-vector-reverse vec))}}
;;> \macro{(for var [index] (in-vector vec))}
;;> \macro{(for var [index] (in-vector-reverse vec))}
(define-in-indexed in-vector in-vector-reverse vector-length vector-ref)
;;> \subsubsubsection{\scheme{(for ch [cursor] (in-string str))}}
;;> \macro{(for ch [cursor] (in-string str))}
(define-syntax in-string
(syntax-rules ()
@ -229,7 +229,7 @@
string-cursor-start string-cursor-end string-cursor-ref
tmp s next . rest))))
;;> \subsubsubsection{\scheme{(for ch [cursor] (in-string-reverse str))}}
;;> \macro{(for ch [cursor] (in-string-reverse str))}
(define-syntax in-string-reverse
(syntax-rules ()
@ -258,7 +258,7 @@
. rest))
))
;;> \subsubsubsection{\scheme{(for ch (in-port [input-port [reader [eof?]]]))}}
;;> \macro{(for ch (in-port [input-port [reader [eof?]]]))}
(define-syntax in-port
(syntax-rules ()
@ -278,7 +278,7 @@
()
. rest))))
;;> \subsubsubsection{\scheme{(for ch (in-file [input-port [reader [eof?]]]))}}
;;> \macro{(for ch (in-file [input-port [reader [eof?]]]))}
(define-syntax in-file
(syntax-rules ()
@ -296,7 +296,7 @@
((dummy (close-input-port p)))
. rest))))
;;> \subsubsubsection{\scheme{(for x (up-from [start] [(to limit)] [(by step)]))}}
;;> \macro{(for x (up-from [start] [(to limit)] [(by step)]))}
(define-syntax up-from
(syntax-rules (to by)
@ -322,7 +322,7 @@
(next ((s start)) ((var s (+ var 1))) () () () . rest))
))
;;> \subsubsubsection{\scheme{(for x (down-from [start] [(to limit)] [(by step)]))}}
;;> \macro{(for x (down-from [start] [(to limit)] [(by step)]))}
(define-syntax down-from
(syntax-rules (to by)
@ -371,14 +371,14 @@
((var (final cursor)))
. rest))))
;;> \subsubsubsection{\scheme{(for x [pair] (listing expr))}}
;;> \macro{(for x [pair] (listing expr))}
(define-syntax listing
(syntax-rules ()
((listing args next . rest)
(accumulating (cons reverse '()) args next . rest))))
;;> \subsubsubsection{\scheme{(for x [pair] (listing-reverse expr))}}
;;> \macro{(for x [pair] (listing-reverse expr))}
(define-syntax listing-reverse
(syntax-rules ()
@ -388,28 +388,28 @@
(define (append-reverse rev tail)
(if (null? rev) tail (append-reverse (cdr rev) (cons (car rev) tail))))
;;> \subsubsubsection{\scheme{(for x [pair] (appending expr))}}
;;> \macro{(for x [pair] (appending expr))}
(define-syntax appending
(syntax-rules ()
((appending args next . rest)
(accumulating (append-reverse reverse '()) args next . rest))))
;;> \subsubsubsection{\scheme{(for x [pair] (appending-reverse expr))}}
;;> \macro{(for x [pair] (appending-reverse expr))}
(define-syntax appending-reverse
(syntax-rules ()
((appending-reverse args next . rest)
(accumulating (append-reverse (lambda (x) x) '()) args next . rest))))
;;> \subsubsubsection{\scheme{(for x (summing expr))}}
;;> \macro{(for x (summing expr))}
(define-syntax summing
(syntax-rules ()
((summing args next . rest)
(accumulating (+ (lambda (x) x) 0) args next . rest))))
;;> \subsubsubsection{\scheme{(for x (multiplying expr))}}
;;> \macro{(for x (multiplying expr))}
(define-syntax multiplying
(syntax-rules ()

View file

@ -14,7 +14,7 @@
;;> patterns - patterns in which the same identifier occurs multiple
;;> times, tail patterns after ellipsis, and the experimental tree patterns.
;;> \subsubsection{Patterns}
;;> \section{Patterns}
;;> Patterns are written to look like the printed representation of
;;> the objects they match. The basic usage is
@ -239,10 +239,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;> \subsubsection{Syntax}
;;> \section{Syntax}
;;> \subsubsubsection{\rawcode{(match expr (pattern . body) ...)\br{}
;;> (match expr (pattern (=> failure) . body) ...)}}
;;> \macro{(match expr (pattern . body) ...)\br{}
;;> (match expr (pattern (=> failure) . body) ...)}
;;> The result of \var{expr} is matched against each \var{pattern} in
;;> turn, according to the pattern rules described in the previous
@ -846,7 +846,7 @@
((_ loop (v ...) ((pat expr) . rest) . body)
(match-named-let loop (v ... (pat expr tmp)) rest . body))))
;;> \subsubsubsection{\rawcode{(match-let* ((var value) ...) body ...)}}
;;> \macro{(match-let* ((var value) ...) body ...)}
;;> Similar to \scheme{match-let}, but analogously to \scheme{let*}
;;> matches and binds the variables in sequence, with preceding match

View file

@ -2,8 +2,7 @@
;; Copyright (c) 2004-2014 Alex Shinn. All rights reserved.
;; BSD-style license: http://synthcode.com/license.txt
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Number theoretic utilities
;;> Prime and number theoretic utilities.
;;> Returns a pair whose car is the power of 2 in the factorization of
;;> n, and whose cdr is the product of all remaining primes.

View file

@ -2,9 +2,9 @@
;; Copyright (c) 2003-2013 Alex Shinn. All rights reserved.
;; BSD-style license: http://synthcode.com/license.txt
;; Memory and persistent caching with various levels of control, based
;; on a combination of lru-cache from Hato and an older memoization
;; library for Gauche.
;;> Memory and persistent caching with various levels of control, based
;;> on a combination of lru-cache from Hato and an older memoization
;;> library for Gauche.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; types

View file

@ -11,7 +11,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; association lists
;;> \subsubsubsection{\scheme{(assq-ref ls key [default])}}
;;> \procedure{(assq-ref ls key [default])}
;;> Returns the \scheme{cdr} of the cell in \var{ls} whose
;;> \scheme{car} is \scheme{eq?} to \var{key}, or \var{default}
;;> if not found. Useful for retrieving values associated with
@ -73,9 +73,9 @@
str)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;> \subsubsection{RFC2822 Headers}
;;> \section{RFC2822 Headers}
;;> \subsubsubsection{\scheme{(mime-header-fold kons knil [source [limit [kons-from]]])}}
;;> \procedure{(mime-header-fold kons knil [source [limit [kons-from]]])}
;;>
;;> Performs a fold operation on the MIME headers of source which can be
;;> either a string or port, and defaults to current-input-port. \var{kons}
@ -139,7 +139,7 @@
(else
(out first-line knil 0)))))
;;> \subsubsubsection{\scheme{(mime-headers->list [source])}}
;;> \procedure{(mime-headers->list [source])}
;;> Return an alist of the MIME headers from source with headers all
;;> downcased.
@ -163,7 +163,7 @@
(substring s (+ i 1) (string-length s)))))
(cons (string->symbol (string-downcase-ascii (string-trim s))) ""))))
;;> \subsubsubsection{\scheme{(mime-parse-content-type str)}}
;;> \procedure{(mime-parse-content-type str)}
;;> Parses \var{str} as a Content-Type style-value returning the list
;;> \scheme{(type (attr . val) ...)}.
@ -179,7 +179,7 @@
(cons (caar res) (cdr res))
res)))
;;> \subsubsubsection{\scheme{(mime-decode-header str)}}
;;> \procedure{(mime-decode-header str)}
;;> Replace all occurrences of RFC1522 =?ENC?...?= escapes in \var{str} with
;;> the appropriate decoded and charset converted value.
@ -250,9 +250,9 @@
(lambda (x) (next (mime-convert-part x cte enc)))
(lambda (x) (final (mime-convert-part x cte enc)))))
;;> \subsubsection{RFC2045 MIME Encoding}
;;> \section{RFC2045 MIME Encoding}
;;> \subsubsubsection{\scheme{(mime-message-fold src kons knil [down up headers])}}
;;> \procedure{(mime-message-fold src kons knil [down up headers])}
;;> Performs a tree fold operation on the given string or port
;;> \var{src} as a MIME body corresponding to the headers give in
;;> \var{headers}. If \var{headers} are false or not provided they
@ -339,7 +339,7 @@
(lambda (x) (next (kons parent-headers headers x seed)))
(lambda (x) (final (kons parent-headers headers x seed)))))))))))
;;> \subsubsubsection{\scheme{(mime-message->sxml [src [headers]])}}
;;> \procedure{(mime-message->sxml [src [headers]])}
;;>
;;> Parse the given source as a MIME message and return
;;> the result as an SXML object of the form:

View file

@ -1,45 +1,19 @@
;; quoted-printable.scm -- RFC2045 implementation
;; Copyright (c) 2005-2009 Alex Shinn. All rights reserved.
;; Copyright (c) 2005-2014 Alex Shinn. All rights reserved.
;; BSD-style license: http://synthcode.com/license.txt
;; Procedure: quoted-printable-encode-string str [start-col max-col]
;; Return a quoted-printable encoded representation of string
;; according to the official standard as described in RFC2045.
;;
;; ? and _ are always encoded for compatibility with RFC1522 encoding,
;; and soft newlines are inserted as necessary to keep each lines
;; length less than MAX-COL (default 76). The starting column may be
;; overridden with START-COL (default 0).
;;> RFC 2045 quoted printable encoding and decoding utilities. This
;;> API is backwards compatible with the Gauche library
;;> rfc.quoted-printable.
;; Procedure: quoted-printable-decode-string str [mime?]
;; Return a quoted-printable decoded representation of string. If
;; MIME? is specified and true, _ will be decoded as as space in
;; accordance with RFC1522. No errors will be raised on invalid
;; input.
;; Procedure: quoted-printable-encode [port start-col max-col]
;; Procedure: quoted-printable-decode [port start-col max-col]
;; Variations of the above which read and write to ports.
;; Procedure: quoted-printable-encode-header enc str [start-col max-col]
;; Return a quoted-printable encoded representation of string as
;; above, wrapped in =?ENC?Q?...?= as per RFC1522, split across
;; multiple MIME-header lines as needed to keep each lines length less
;; than MAX-COL. The string is encoded as is, and the encoding ENC is
;; just used for the prefix, i.e. you are responsible for ensuring STR
;; is already encoded according to ENC.
;; Example:
;; (define (mime-encode-header header value charset)
;; (let ((prefix (string-append header ": "))
;; (str (ces-convert value "UTF8" charset)))
;; (string-append
;; prefix
;; (quoted-printable-encode-header charset str (string-length prefix)))))
;; This API is backwards compatible with the Gauche library
;; rfc.quoted-printable.
;;> \schemeblock{
;;> (define (mime-encode-header header value charset)
;;> (let ((prefix (string-append header ": "))
;;> (str (ces-convert value "UTF8" charset)))
;;> (string-append
;;> prefix
;;> (quoted-printable-encode-header charset str (string-length prefix)))))
;;> }
(define *default-max-col* 76)
@ -69,6 +43,14 @@
(string-set! buf (+ col 2) (hex (bitwise-and c #b1111)))
(lp (+ i 1) (+ col 3) res)))))))))
;;> Return a quoted-printable encoded representation of the input
;;> according to the official standard as described in RFC2045.
;;>
;;> ? and _ are always encoded for compatibility with RFC1522
;;> encoding, and soft newlines are inserted as necessary to keep each
;;> lines length less than \var{max-col} (default 76). The starting
;;> column may be overridden with \var{start-col} (default 0).
(define (quoted-printable-encode-string . o)
(let ((src (if (pair? o) (car o) (current-input-port)))
(start-col (if (and (pair? o) (pair? (cdr o))) (cadr o) 0))
@ -78,9 +60,19 @@
(qp-encode (if (string? src) src (read-string #f src))
start-col max-col "=\r\n")))
;;> Variation of the above to read and write to ports.
(define (quoted-printable-encode . o)
(display (apply (quoted-printable-encode-string o))))
;;> Return a quoted-printable encoded representation of string as
;;> above, wrapped in =?ENC?Q?...?= as per RFC1522, split across
;;> multiple MIME-header lines as needed to keep each lines length
;;> less than \var{max-col}. The string is encoded as is, and the
;;> encoding \var{enc} is just used for the prefix, i.e. you are
;;> responsible for ensuring \var{str} is already encoded according to
;;> \var{enc}.
(define (quoted-printable-encode-header encoding . o)
(let ((src (if (pair? o) (car o) (current-input-port)))
(start-col (if (and (pair? o) (pair? (cdr o))) (cadr o) 0))
@ -99,6 +91,11 @@
start-col effective-max-col separator)
"?="))))
;;> Return a quoted-printable decoded representation of \var{str}. If
;;> \var{mime-header?} is specified and true, _ will be decoded as as
;;> space in accordance with RFC1522. No errors will be raised on
;;> invalid input.
(define (quoted-printable-decode-string . o)
(define (hex? c) (or (char-numeric? c) (<= 65 (char->integer c) 70)))
(define (unhex1 c)
@ -152,6 +149,7 @@
(write-char c out)
(lp (+ i 1)))))))))))))
;;> Variation of the above to read and write to ports.
(define (quoted-printable-decode . o)
(display (apply quoted-printable-decode-string o)))

View file

@ -44,7 +44,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; test interface
;;> \subsubsubsection{\scheme{(test [name] expect expr)}}
;;> \macro{(test [name] expect expr)}
;;> Evaluate \var{expr} and check that it is \scheme{equal?}
;;> to \var{expect}. \var{name} is used in reporting, and
@ -68,7 +68,7 @@
((test a ...)
(test-syntax-error 'test "test requires 2 or 3 arguments" (test a ...)))))
;;> \subsubsubsection{\scheme{(test-equal equal [name] expect expr)}}
;;> \macro{(test-equal equal [name] expect expr)}
;;> Equivalent to test, using \var{equal} for comparison instead of
;;> \scheme{equal?}.
@ -79,7 +79,7 @@
(parameterize ((current-test-comparator equal))
(test . args)))))
;;> \subsubsubsection{\scheme{(test-assert [name] expr)}}
;;> \macro{(test-assert [name] expr)}
;;> Like \scheme{test} but evaluates \var{expr} and checks that it's true.
@ -93,7 +93,7 @@
(test-syntax-error 'test-assert "1 or 2 arguments required"
(test a ...)))))
;;> \subsubsubsection{\scheme{(test-not [name] expr)}}
;;> \macro{(test-not [name] expr)}
;;> Like \scheme{test} but evaluates \var{expr} and checks that it's false.
@ -102,7 +102,7 @@
((_ expr) (test-assert (not expr)))
((_ name expr) (test-assert name (not expr)))))
;;> \subsubsubsection{\scheme{(test-values [name] expect expr)}}
;;> \macro{(test-values [name] expect expr)}
;;> Like \scheme{test} but \var{expect} and \var{expr} can both
;;> return multiple values.
@ -115,7 +115,7 @@
(test name (call-with-values (lambda () expect) (lambda results results))
(call-with-values (lambda () expr) (lambda results results))))))
;;> \subsubsubsection{\scheme{(test-error [name] expr)}}
;;> \macro{(test-error [name] expr)}
;;> Like \scheme{test} but evaluates \var{expr} and checks that it
;;> raises an error.
@ -148,7 +148,7 @@
(var-values . ,(list vars ...))
(key . val) ...)))))
;;> \subsubsubsection{\scheme{(test-exit)}}
;;> \macro{(test-exit)}
;;> Exits with a failure status if any tests have failed,
;;> and a successful status otherwise.

View file

@ -20,7 +20,7 @@
;;> Accessors for the URI type.
;;/
;;> \subsubsubsection{\scheme{(make-uri scheme [user host port path query fragment])}}
;;> \procedure{(make-uri scheme [user host port path query fragment])}
(define (make-uri scheme . o)
(let* ((user (if (pair? o) (car o) #f))
@ -209,7 +209,7 @@
res
(cons (substring-cursor str from to) res)))
;;> \subsubsubsection{\scheme{(uri-encode str [plus?])}}
;;> \procedure{(uri-encode str [plus?])}
;;> Return the URI encoded version of the string \var{str},
;;> using hex escapes as needed and replacing spaces with "+"
@ -243,7 +243,7 @@
(lp next next (cons (encode-1 ch)
(collect str from to res)))))))))
;;> \subsubsubsection{\scheme{(uri-decode str [plus?])}}
;;> \procedure{(uri-decode str [plus?])}
;;> Decodes any URI hex escapes in the given string, and
;;> translates any pluses ("+") to space iff the optional
@ -277,7 +277,7 @@
(else
(lp from next res))))))))
;;> \subsubsubsection{\scheme{(uri-query->alist str [plus?])}}
;;> \procedure{(uri-query->alist str [plus?])}
;;> Parses the query part of a URI as a delimited list of
;;> URI encoded \rawcode{VAR=VALUE} pairs, decodes them and
@ -299,7 +299,7 @@
(cons (uri-decode (substring-cursor str i j) plus?) #f))))
(lp (+ j 1) (cons cell res)))))))
;;> \subsubsubsection{\scheme{(uri-alist->query ls [plus?])}}
;;> \procedure{(uri-alist->query ls [plus?])}
;;> The reverse of the above, formats the alist as a URI
;;> query string.