Parsing literal docs for FFI files, generating docs for all core modules (mostly stubs).

This commit is contained in:
Alex Shinn 2011-05-18 00:52:54 -07:00
parent 541d7f4550
commit 2b86320652
8 changed files with 364 additions and 152 deletions

View file

@ -169,11 +169,13 @@ lib/%$(SO): lib/%.c $(INCLUDES)
$(CHIBI) tools/chibi-doc $< > $@
doc/lib/chibi/%.html: lib/chibi/%.module tools/chibi-doc chibi-scheme$(EXE)
$(CHIBI) tools/chibi-doc $< > $@
$(CHIBI) tools/chibi-doc chibi.$* > $@
MODULE_DOCS := doc/lib/chibi/match.html
MODULE_DOCS := ast disasm equiv filesystem generic heap-stats io loop \
match mime modules net pathname process repl scribble stty \
system test time type-inference uri weak
doc: doc/chibi.html $(MODULE_DOCS)
doc: doc/chibi.html $(MODULE_DOCS:%=doc/lib/chibi/%.html)
clean:
rm -f *.o *.i *.s *.8

View file

@ -963,117 +963,52 @@ SRFIs used in standard Chibi modules
Additional non-standard modules are put in the @scheme{(chibi)} module
namespace.
@subsection{Internals Interface}
@itemlist[
The @scheme{(chibi ast)} module provides access to the Abstract Syntax Tree and
other internal data structures not typically needed for everyday programs.
@item{@hyperlink["lib/chibi/ast.html"]{(chibi ast) - Abstract Syntax Tree and other internal data types}}
@subsection{Disassember}
@item{@hyperlink["lib/chibi/disasm.html"]{(chibi disasm) - Disassembler for the virtual machine}}
The @scheme{(chibi disasm)} module provides a disassembler for the virtual
machine.
@item{@hyperlink["lib/chibi/equiv.html"]{(chibi equiv) - A version of @scheme{equal?} which is guaranteed to terminate}}
@subsection{Printed Equivalence}
@item{@hyperlink["lib/chibi/filesystem.html"]{(chibi filesystem) - Interface to the filesystem and file descriptor objects}}
The @scheme{(chibi equiv)} module provides the @scheme{equiv?} procedure, which
is similar to @scheme{equal?} but is guaranteed to terminate. It takes two
arguments and returns true iff they would print the same using SRFI-38 style
read/write syntax.
@item{@hyperlink["lib/chibi/generic.html"]{(chibi generic) - Generic methods for CLOS-style object oriented programming}}
@subsection{Filesystem Interface}
@item{@hyperlink["lib/chibi/heap-stats.html"]{(chibi heap-stats) - Utilities for gathering statistics on the heap}}
The @scheme{(chibi filesystem)} module provides access to the filesystem and
file descriptor objects.
@item{@hyperlink["lib/chibi/io.html"]{(chibi io) - Various I/O extensions and custom ports}}
@subsection{Generic Functions}
@item{@hyperlink["lib/chibi/loop.html"]{(chibi loop) - Fast and extensible loop syntax}}
The @scheme{(chibi generic)} module provides generic methods for CLOS-style
object oriented programming.
@item{@hyperlink["lib/chibi/match.html"]{(chibi match) - Intuitive and widely supported pattern matching syntax}}
@subsection{Heap Introspection}
@item{@hyperlink["lib/chibi/mime.html"]{(chibi mime) - Parse MIME files into SXML}}
The @scheme{(chibi heap-stats)} module provides utilities for gathering
statistics on the heap.
@item{@hyperlink["lib/chibi/modules.html"]{(chibi modules) - Introspection for the module system itself}}
@subsection{Input/Output Extensions}
@item{@hyperlink["lib/chibi/net.html"]{(chibi net) - Simple networking interface}}
The @scheme{(chibi io)} module provides various I/O extensions, including
custom ports.
@item{@hyperlink["lib/chibi/pathname.html"]{(chibi pathname) - Utilities to decompose and manipulate pathnames}}
@subsection{Extensible Loop Syntax}
@item{@hyperlink["lib/chibi/process.html"]{(chibi process) - Interface to spawn processes and handle signals}}
The @scheme{(chibi loop)} module provides a fast and extensible loop syntax.
@item{@hyperlink["lib/chibi/repl.html"]{(chibi repl) - A full-featured Read/Eval/Print Loop}}
@subsection{Pattern-Matching}
@item{@hyperlink["lib/chibi/scribble.html"]{(chibi scribble) - A parser for the scribble syntax used to write this manual}}
The @scheme{(chibi match)} module provides an intuitive and widely supported
pattern matching syntax.
@item{@hyperlink["lib/chibi/stty.html"]{(chibi stty) - A high-level interface to ioctl}}
@subsection{RFC2045 MIME}
@item{@hyperlink["lib/chibi/system.html"]{(chibi system) - Access to the host system and current user information}}
The @scheme{(chibi mime)} module provides utilities for parsing MIME
files into an SXML format.
@item{@hyperlink["lib/chibi/test.html"]{(chibi test) - A simple unit testing framework}}
@subsection{Module Introspection}
@item{@hyperlink["lib/chibi/time.html"]{(chibi time) - An interface to the current system time}}
The @scheme{(chibi modules)} module provides introspection utilities for the
module system itself.
@item{@hyperlink["lib/chibi/type-inference.html"]{(chibi type-inference) - An easy-to-use type inference system}}
@subsection{Networking Interface}
@item{@hyperlink["lib/chibi/uri.html"]{(chibi uri) - Utilities to parse and construct URIs}}
The @scheme{(chibi net)} module provides a simple networking interface.
@subsection{Pathname Utilities}
The @scheme{(chibi pathname)} module provides utilities to decompose and
manipulate pathnames.
@subsection{Processes and Signals}
The @scheme{(chibi process)} module provides utilities to spawn processes and
send and handle signals between processes.
@subsection{Read/Eval/Print Loop}
The @scheme{(chibi repl)} module provides a more full-featured repl than the
chibi-scheme executable.
@subsection{Scribble Syntax}
The @scheme{(chibi scribble)} module provides a parser for the scribble syntax
used to write this manual.
@subsection{Stty Interface}
The @scheme{(chibi stty)} provides a high-level interface to ioctl.
@subsection{System Information}
The @scheme{(chibi system)} module provides access to the host system and
current user information.
@subsection{Line Editing}
The @scheme{(chibi term edit-line)} provides an @scheme{edit-line} procedure
for interactive line editing.
@subsection{Testing}
The @scheme{(chibi test)} provides a simple unit testing framework.
@subsection{Times and Dates}
The @scheme{(chibi time)} provides an interface to the current system time.
@subsection{Type Inference}
The @scheme{(chibi type-inference)} is an easy-to-use type inference system.
@subsection{URI Utilities}
The @scheme{(chibi uri)} module provides utilities to parse and construct URIs.
@subsection{Weak References}
The @scheme{(chibi weak)} module provides data structures with weak references.
@item{@hyperlink["lib/chibi/weak.html"]{(chibi weak) - Data structures with weak references}}
]

View file

@ -1,10 +1,10 @@
<html><head>
<html><head><title>(chibi match)</title>
<style type="text/css">
body {color: #000; background-color: #FFF}
div#menu {font-size: smaller; position: absolute; top: 0; left: 0; width: 180px; height: 100%}
div#menu ol {margin-left: 10px; padding-left: 10px}
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#footer {padding-bottom: 50px}
.result { color: #000; background-color: #FFEADF; width: 100%; padding: 3px}
.command { color: #000; background-color: #FFEADF; width: 100%; padding: 5px}
.keyword { color: #800080; background-color: inherit; }
@ -27,8 +27,162 @@ span.paren4 { color: #444444; background-color: inherit; }
span.paren5 { color: #222222; background-color: inherit; }
span.paren6 { color: #000000; background-color: inherit; }
</style>
</head><body><div id="menu"></div><div id="main"><p>(module (chibi match)
(export match match-lambda match-lambda* match-let match-letrec match-let*)
(import-immutable (scheme))
(include "match/match.scm"))
</p></div></body></html>
</head><body><div id="menu"><ol><li><a href="#h3_Patterns">Patterns</a></li><li><a href="#h3_Syntax">Syntax</a><ol><li><a href="#h4_(matchexpr(pattern.body)...)(matchexpr(pattern(=>failure).body)...)">(match expr (pattern . body) ...)
(match expr (pattern (=> failure) . body) ...)</a></li><li><a href="#h4_match-lambda">(match-lambda (pattern . body) ...)</a></li><li><a href="#h4_match-lambda*">(match-lambda* (pattern . body) ...)</a></li><li><a href="#h4_match-let">(match-let ((var value) ...) . body)(match-let loop ((var init) ...) . body)</a></li><li><a href="#h4_match-letrec">(match-letrec ((var value) ...) . body)</a></li><li><a href="#h4_(match-let*((varvalue)...)body...)">(match-let* ((var value) ...) body ...)</a></li></ol></li></ol></div><div id="main"><h1>(chibi match)</h1><p>
This is a full superset of the popular <a href="http://www.cs.indiana.edu/scheme-repository/code.match.html">match</a>
package by Andrew Wright, written in fully portable <code><span>syntax-rules</span></code>
and thus preserving hygiene.
The most notable extensions are the ability to use <em>non-linear</em>
patterns - patterns in which the same identifier occurs multiple
times, tail patterns after ellipsis, and the experimental tree patterns.
</p><div><a name="h3_Patterns"></a><h3>Patterns</h3></div><p>
Patterns are written to look like the printed representation of
the objects they match. The basic usage is
<code>(<span class="keyword">match</span> <span>expr</span> (pat <span>body</span> <span>...</span>) <span>...</span>)</code>
where the result of <code>expr</code> is matched against each pattern in
turn, and the corresponding body is evaluated for the first to
succeed. Thus, a list of three elements matches a list of three
elements.
</p><div><pre><code>(<span class="keyword">let</span> ((ls (list <span>1</span> <span>2</span> <span>3</span>))) (<span class="keyword">match</span> <span>ls</span> ((1 <span>2</span> <span>3</span>) #)))</code></pre><code><div class="result">=> #t</div></code></div><p>
If no patterns match an error is signalled.
Identifiers will match anything, and make the corresponding
binding available in the body.
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span>) ((a <span>b</span> <span>c</span>) <span>b</span>))</code></pre><code><div class="result">=> 2</div></code></div><p>
If the same identifier occurs multiple times, the first instance
will match anything, but subsequent instances must match a value
which is <code><span>equal?</span></code> to the first.
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>1</span>) ((a <span>a</span> <span>b</span>) <span>1</span>) ((a <span>b</span> <span>a</span>) <span>2</span>))</code></pre><code><div class="result">=> 2</div></code></div><p>
The special identifier <code><span>_</span></code> matches anything, no matter how
many times it is used, and does not bind the result in the body.
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>1</span>) ((_ <span>_</span> <span>b</span>) <span>1</span>) ((a <span>b</span> <span>a</span>) <span>2</span>))</code></pre><code><div class="result">=> 1</div></code></div><p>
To match a literal identifier (or list or any other literal), use
<code><span>quote</span></code>.
</p><div><pre><code>(<span class="keyword">match</span> '<span>a</span> ('<span>b</span> <span>1</span>) ('<span>a</span> <span>2</span>))</code></pre><code><div class="result">=> 2</div></code></div><p>
Analogous to its normal usage in scheme, <code><span>quasiquote</span></code> can
be used to quote a mostly literally matching object with selected
parts unquoted.
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span>) (`(1 ,<span>b</span> ,<span>c</span>) (list <span>b</span> <span>c</span>)))</code></pre><code><div class="result">=> (2 3)</div></code></div><p>
Often you want to match any number of a repeated pattern. Inside
a list pattern you can append <code><span>...</span></code> after an element to
match zero or more of that pattern (like a regexp Kleene star).
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span>) ((1 <span>2</span> <span>3</span> <span>...</span>) #))</code></pre><code><div class="result">=> #t</div></code></div><p>
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span>) ((1 <span>2</span> <span>3</span> <span>...</span>) #))</code></pre><code><div class="result">=> #t</div></code></div><p>
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span> <span>3</span> <span>3</span>) ((1 <span>2</span> <span>3</span> <span>...</span>) #))</code></pre><code><div class="result">=> #t</div></code></div><p>
Pattern variables matched inside the repeated pattern are bound to
a list of each matching instance in the body.
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span>) ((a <span>b</span> <span>c</span> <span>...</span>) <span>c</span>))</code></pre><code><div class="result">=> ()</div></code></div><p>
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span>) ((a <span>b</span> <span>c</span> <span>...</span>) <span>c</span>))</code></pre><code><div class="result">=> (3)</div></code></div><p>
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span>) ((a <span>b</span> <span>c</span> <span>...</span>) <span>c</span>))</code></pre><code><div class="result">=> (3 4 5)</div></code></div><p>
More than one <code><span>...</span></code> may not be used in the same list, since
this would require exponential backtracking in the general case.
However, <code><span>...</span></code> need not be the final element in the list,
and may be succeeded by a fixed number of patterns.
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span> <span>4</span>) ((a <span>b</span> <span>c</span> <span>...</span> <span>d</span> <span>e</span>) <span>c</span>))</code></pre><code><div class="result">=> ()</div></code></div><p>
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span>) ((a <span>b</span> <span>c</span> <span>...</span> <span>d</span> <span>e</span>) <span>c</span>))</code></pre><code><div class="result">=> (3)</div></code></div><p>
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> <span>6</span> <span>7</span>) ((a <span>b</span> <span>c</span> <span>...</span> <span>d</span> <span>e</span>) <span>c</span>))</code></pre><code><div class="result">=> (3 4 5)</div></code></div><p>
<code><span>___</span></code> is provided as an alias for <code><span>...</span></code> when it is
inconvenient to use the ellipsis (as in a syntax-rules template).
The <code><span>..1</span></code> syntax is exactly like the <code><span>...</span></code> except
that it matches one or more repetitions (like a regexp "+").
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span>) ((a <span>b</span> <span>c</span> <span>..1</span>) <span>c</span>))</code></pre><code><div class="result">ERROR: match: "no matching pattern"
</div></code></div><p>
</p><div><pre><code>(<span class="keyword">match</span> (list <span>1</span> <span>2</span> <span>3</span>) ((a <span>b</span> <span>c</span> <span>..1</span>) <span>c</span>))</code></pre><code><div class="result">=> (3)</div></code></div><p>
The boolean operators <code><span>and</span></code>, <code><span>or</span></code> and <code><span>not</span></code>
can be used to group and negate patterns analogously to their
Scheme counterparts.
The <code><span>and</span></code> operator ensures that all subpatterns match.
This operator is often used with the idiom <code>(and <span>x</span> <span>pat</span>)</code> to
bind <code>x</code> to the entire value that matches <code>pat</code>
(c.f. "as-patterns" in ML or Haskell). Another common use is in
conjunction with <code><span>not</span></code> patterns to match a general case
with certain exceptions.
</p><div><pre><code>(<span class="keyword">match</span> <span>1</span> ((and) #))</code></pre><code><div class="result">=> #t</div></code></div><p>
</p><div><pre><code>(<span class="keyword">match</span> <span>1</span> ((and <span>x</span>) <span>x</span>))</code></pre><code><div class="result">=> 1</div></code></div><p>
</p><div><pre><code>(<span class="keyword">match</span> <span>1</span> ((and <span>x</span> <span>1</span>) <span>x</span>))</code></pre><code><div class="result">=> 1</div></code></div><p>
The <code><span>or</span></code> operator ensures that at least one subpattern
matches. If the same identifier occurs in different subpatterns,
it is matched independently. All identifiers from all subpatterns
are bound if the <code><span>or</span></code> operator matches, but the binding is
only defined for identifiers from the subpattern which matched.
</p><div><pre><code>(<span class="keyword">match</span> <span>1</span> ((or) #) (<span class="keyword">else</span> #))</code></pre><code><div class="result">=> #f</div></code></div><p>
</p><div><pre><code>(<span class="keyword">match</span> <span>1</span> ((or <span>x</span>) <span>x</span>))</code></pre><code><div class="result">=> 1</div></code></div><p>
</p><div><pre><code>(<span class="keyword">match</span> <span>1</span> ((or <span>x</span> <span>2</span>) <span>x</span>))</code></pre><code><div class="result">=> 1</div></code></div><p>
The <code><span>not</span></code> operator succeeds if the given pattern doesn't
match. None of the identifiers used are available in the body.
</p><div><pre><code>(<span class="keyword">match</span> <span>1</span> ((not <span>2</span>) #))</code></pre><code><div class="result">=> #t</div></code></div><p>
The more general operator <code><span>?</span></code> can be used to provide a
predicate. The usage is <code>(? <span>predicate</span> <span>pat</span> <span>...</span>)</code> where
<code>predicate</code> is a Scheme expression evaluating to a predicate
called on the value to match, and any optional patterns after the
predicate are then matched as in an <code><span>and</span></code> pattern.
</p><div><pre><code>(<span class="keyword">match</span> <span>1</span> ((? <span>odd?</span> <span>x</span>) <span>x</span>))</code></pre><code><div class="result">=> 1</div></code></div><p>
The field operator <code><span>=</span></code> is used to extract an arbitrary
field and match against it. It is useful for more complex or
conditional destructuring that can't be more directly expressed in
the pattern syntax. The usage is <code>(= <span>field</span> <span>pat</span>)</code>, where
<code>field</code> can be any expression, and should result in a
procedure of one argument, which is applied to the value to match
to generate a new value to match against <code>pat</code>.
Thus the pattern <code>(and (= <span>car</span> <span>x</span>) (= <span>cdr</span> <span>y</span>))</code> is equivalent
to <code>(x <span>.</span> <span>y</span>)</code>, except it will result in an immediate error
if the value isn't a pair.
</p><div><pre><code>(<span class="keyword">match</span> '(1 <span>.</span> <span>2</span>) ((= <span>car</span> <span>x</span>) <span>x</span>))</code></pre><code><div class="result">=> 1</div></code></div><p>
</p><div><pre><code>(<span class="keyword">match</span> <span>4</span> ((= <span>sqrt</span> <span>x</span>) <span>x</span>))</code></pre><code><div class="result">=> 2</div></code></div><p>
The record operator <code><span>$</span></code> is used as a concise way to match
records defined by SRFI-9 (or SRFI-99). The usage is
<code>($ <span>rtd</span> <span>field</span> <span>...</span>)</code>, where <code>rtd</code> should be the record
type descriptor specified as the first argument to
<code><span>define-record-type</span></code>, and each <code>field</code> is a subpattern
matched against the fields of the record in order. Not all fields
must be present.
</p><div><pre><code>(<span class="keyword">let</span> ()
(<span class="keyword">define-record-type</span> <span class="function">employee</span>
(make-employee <span>name</span> <span>title</span>)
<span>employee?</span>
(name <span>get-name</span>)
(title <span>get-title</span>))
(<span class="keyword">match</span> (make-employee <span class="string">"Bob"</span> <span class="string">"Doctor"</span>)
(($ <span>employee</span> <span>n</span> <span>t</span>) (list <span>t</span> <span>n</span>))))
</code></pre><code><div class="result">=> ("Doctor" "Bob")</div></code></div><p>
The <code><span>set!</span></code> and <code><span>get!</span></code> operators are used to bind an
identifier to the setter and getter of a field, respectively. The
setter is a procedure of one argument, which mutates the field to
that argument. The getter is a procedure of no arguments which
returns the current value of the field.
</p><div><pre><code>(<span class="keyword">let</span> ((x (cons <span>1</span> <span>2</span>))) (<span class="keyword">match</span> <span>x</span> ((1 <span>.</span> (<span class="keyword">set!</span> <span>s</span>)) (s <span>3</span>) <span>x</span>)))</code></pre><code><div class="result">=> (1 . 3)</div></code></div><p>
</p><div><pre><code>(<span class="keyword">match</span> '(1 <span>.</span> <span>2</span>) ((1 <span>.</span> (get! <span>g</span>)) (g)))</code></pre><code><div class="result">=> 2</div></code></div><p>
The new operator <code><span>***</span></code> can be used to search a tree for
subpatterns. A pattern of the form <code>(x <span>***</span> <span>y</span>)</code> represents
the subpattern <code>y</code> located somewhere in a tree where the path
from the current object to <code>y</code> can be seen as a list of the
form <code>(x <span>...</span>)</code>. <code>y</code> can immediately match the current
object in which case the path is the empty list. In a sense it's
a 2-dimensional version of the <code><span>...</span></code> pattern.
As a common case the pattern <code>(_ <span>***</span> <span>y</span>)</code> can be used to
search for <code>y</code> anywhere in a tree, regardless of the path
used.
</p><div><pre><code>(<span class="keyword">match</span> '(a (a (a <span>b</span>))) ((x <span>***</span> '<span>b</span>) <span>x</span>))</code></pre><code><div class="result">=> (a a a)</div></code></div><p>
</p><div><pre><code>(<span class="keyword">match</span> '(a (b) (c (d <span>e</span>) (f <span>g</span>))) ((x <span>***</span> '<span>g</span>) <span>x</span>))</code></pre><code><div class="result">=> (a c f)</div></code></div><div><a name="h3_Syntax"></a><h3>Syntax</h3></div><p>
</p><div><a name="h4_(matchexpr(pattern.body)...)(matchexpr(pattern(=>failure).body)...)"></a><h4><code>(match expr (pattern . body) ...)<br></br>
(match expr (pattern (=> failure) . body) ...)</code></h4></div><p>
The result of <code>expr</code> is matched against each <code>pattern</code> in
turn, according to the pattern rules described in the previous
section, until the the first <code>pattern</code> matches. When a match is
found, the corresponding <code>body</code>s are evaluated in order,
and the result of the last expression is returned as the result
of the entire <code><span>match</span></code>. If a <code>failure</code> is provided,
then it is bound to a procedure of no arguments which continues,
processing at the next <code>pattern</code>. If no <code>pattern</code> matches,
an error is signalled.</p><div><a name="h4_match-lambda"></a><h4><code>(match-lambda (pattern . body) ...)</code></h4></div><p>Shortcut for <code><span>lambda</span></code> + <code><span>match</span></code>. Creates a
procedure of one argument, and matches that argument against each
clause.</p><div><a name="h4_match-lambda*"></a><h4><code>(match-lambda* (pattern . body) ...)</code></h4></div><p>Similar to <code><span>match-lambda</span></code>. Creates a procedure of any
number of arguments, and matches the argument list against each
clause.</p><div><a name="h4_match-let"></a><h4><code>(match-let ((var value) ...) . body)<br></br>(match-let loop ((var init) ...) . body)</code></h4></div><p>Matches each var to the corresponding expression, and evaluates
the body with all match variables in scope. Raises an error if
any of the expressions fail to match. Syntax analogous to named
let can also be used for recursive functions which match on their
arguments as in <code><span>match-lambda*</span></code>.</p><div><a name="h4_match-letrec"></a><h4><code>(match-letrec ((var value) ...) . body)</code></h4></div><p>Similar to <code><span>match-let</span></code>, but analogously to <code><span>letrec</span></code>
matches and binds the variables with all match variables in scope.</p><div><a name="h4_(match-let*((varvalue)...)body...)"></a><h4><code>(match-let* ((var value) ...) body ...)</code></h4></div><p>
Similar to <code><span>match-let</span></code>, but analogously to <code><span>let*</span></code>
matches and binds the variables in sequence, with preceding match
variables in scope.</p><div id="footer"></div></div></body></html>

View file

@ -1,6 +1,6 @@
(module (chibi modules)
(export module-name module-dir module-includes
(export module-name module-dir module-includes module-shared-includes
module-ast module-ast-set! module-ref module-contains?
analyze-module containing-module load-module module-exports
procedure-analysis)

View file

@ -30,19 +30,31 @@
""
(module-name-prefix name))))
(define (module-metas mod metas)
(let ((mod (if (module? mod) mod (find-module mod))))
(let lp ((ls (module-meta-data mod)) (res '()))
(cond
((not (pair? ls)) (reverse res))
((and (pair? (car ls)) (memq (caar ls) metas))
(lp (cdr ls) (append (reverse (cdar ls)) res)))
(else (lp (cdr ls) res))))))
(define (module-includes mod)
(let* ((mod (if (module? mod) mod (find-module mod)))
(dir (module-dir mod)))
(define (module-file f)
(find-module-file (string-append dir f)))
(let lp ((ls (module-meta-data mod)) (res '()))
(cond
((not (pair? ls))
(reverse res))
((and (pair? (car ls)) (eq? 'include (caar ls)))
(lp (cdr ls) (append (map module-file (reverse (cdar ls))) res)))
(else
(lp (cdr ls) res))))))
(map module-file (module-metas mod '(include)))))
(define (module-shared-includes mod)
(let* ((mod (if (module? mod) mod (find-module mod)))
(dir (module-dir mod)))
(define (module-file f)
(find-module-file (string-append dir f ".stub")))
(let lp ((ls (module-metas mod '(include-shared))) (res '()))
(cond ((null? ls) (reverse res))
((module-file (car ls)) => (lambda (x) (lp (cdr ls) (cons x res))))
(else (lp (cdr ls) res))))))
(define (analyze-module-source name mod recursive?)
(let ((env (module-env mod))

View file

@ -12,7 +12,7 @@
signal/alarm signal/term signal/user1
signal/user2 signal/child signal/continue
signal/stop signal/tty-stop signal/tty-input
signal/tty-output)
signal/tty-output wait/no-hang)
(import-immutable (scheme))
(cond-expand (threads (import (srfi 18))) (else #f))
(include-shared "process")

View file

@ -1,9 +1,15 @@
;;> An interface to spawning processes and sending and
;;> receiving signals between processes.
(c-system-include "sys/types.h")
(c-system-include "sys/wait.h")
(c-system-include "signal.h")
(c-system-include "unistd.h")
;;> The siginfo_t struct is used to return info about the status,
;;> process and user info of a called signal handler.
(define-c-type siginfo_t
predicate: signal-info?
(int si_signo signal-number)
@ -16,9 +22,6 @@
;;(clock_t si_stime signal-system-time)
)
(define-c-type sigset_t
predicate: signal-set?)
(define-c-const int (signal/hang-up "SIGHUP"))
(define-c-const int (signal/interrupt "SIGINT"))
(define-c-const int (signal/quit "SIGQUIT"))
@ -41,9 +44,24 @@
(c-include "signal.c")
;;> @subsubsubsection{@rawcode{(set-signal-action! signal handler)}}
;;> Sets the signal handler for @var{signal} to @var{handler}
;;> and returns the old handler. @var{handler} should be a procedure
;;> of one argument, the signal number, the value @scheme{#t} for
;;> the default signal handler, or @scheme{#f} for no handler.
;;> Signal handlers are queued run in a dedicated thread after the
;;> system handler has returned.
(define-c sexp (set-signal-action! "sexp_set_signal_action")
((value ctx sexp) (value self sexp) sexp sexp))
;;> The sigset_t struct represents a set of signals for masking.
(define-c-type sigset_t
predicate: signal-set?)
(define-c errno (make-signal-set "sigemptyset") ((pointer result sigset_t)))
(define-c errno (signal-set-fill! "sigfillset") ((pointer sigset_t)))
(define-c errno (signal-set-add! "sigaddset") ((pointer sigset_t) int))
@ -59,15 +77,50 @@
(define-c errno (current-signal-mask "sigprocmask")
((value SIG_BLOCK int) (pointer value NULL sigset_t) (pointer result sigset_t)))
;;> Send a @var{signal/alarm} signal to the current process
;;> after @var{unsigned-int} seconds have elapsed.
(define-c unsigned-int alarm (unsigned-int))
;;> Suspend the current process for @var{unsigned-int} seconds.
;;> See SRFI-18 @scheme{thread-sleep!} for a light-weight sleep
;;> for only the current thread.
(define-c unsigned-int sleep (unsigned-int))
;;> Fork the current process. Returns @rawcode{0} for the newly
;;> created process, and the process id of the new process for
;;> the parent.
(define-c pid_t fork ())
(define-c-const int (wait/no-hang "WNOHANG"))
;;(define-c pid_t wait ((result int)))
;;> @subsubsubsection{@rawcode{(waitpid pid options)}}
;;> Wait on the process @var{pid}, or any child process if @var{pid}
;;> is @rawcode{-1}. @var{options} should be 0, or @var{wait/no-hang}
;;> to return immediately if no processes have reported status. Returns
;;> a list whose first element is the actual @var{pid} reporting, and
;;> the second element is the integer status.
(define-c pid_t waitpid (int (result int) int))
;;> Send a signal to the given process.
(define-c errno kill (int int))
;;(define-c errno raise (int))
;;> Exits the current process immediately. Finalizers are not run.
(define-c void exit (int))
;;> Replace the current process with the given command. Finalizers
;;> are not run.
(define-c int (execute execvp) (string (array string)))
(cond-expand

View file

@ -160,9 +160,15 @@
(define (expand-section tag)
(lambda (sxml env)
(let ((body (map (lambda (x) (expand x env)) (cdr sxml))))
`(div (a (^ (name . ,(section-name tag (sxml-strip (cons tag body))))))
(,tag ,@body)))))
(if (null? (cdr sxml))
(error "section must not be empty" sxml)
(let* ((name (and (eq? 'tag: (cadr sxml))
(pair? (cddr sxml))
(sxml-strip (caddr sxml))))
(body (map (lambda (x) (expand x env))
(if name (cdddr sxml) (cdr sxml))))
(name (or name (sxml-strip (cons tag body)))))
`(div (a (^ (name . ,(section-name tag name)))) (,tag ,@body))))))
(define (expand-url sxml env)
(if (not (= 2 (length sxml)))
@ -171,11 +177,10 @@
`(a (^ (href . ,url)) ,url))))
(define (expand-hyperlink sxml env)
(if (not (= 3 (length sxml)))
(error "hyperlink expects two arguments" sxml)
(let ((url (expand (cadr sxml) env))
(text (expand (caddr sxml) env)))
`(a (^ (href . ,url)) ,text))))
(if (not (>= (length sxml) 3))
(error "hyperlink expects at least two arguments" sxml)
(let ((url (expand (cadr sxml) env)))
`(a (^ (href . ,url)) ,(map (lambda (x) (expand x env)) (cddr sxml))))))
(define (expand-note sxml env)
`(div (^ (id . "notes"))
@ -286,10 +291,10 @@
(style (^ (type . "text/css"))
"
body {color: #000; background-color: #FFF}
div#menu {font-size: smaller; position: absolute; top: 0; left: 0; width: 180px; height: 100%}
div#menu ol {margin-left: 10px; padding-left: 10px}
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#footer {padding-bottom: 50px}
.result { color: #000; background-color: #FFEADF; width: 100%; padding: 3px}
.command { color: #000; background-color: #FFEADF; width: 100%; padding: 5px}
"
@ -303,7 +308,8 @@ div#notes {position: relative; top: 2em; left: 550px; max-width: 200px; height:
(if (and (pair? x) (eq? 'title (car x)))
(cons 'h1 (cdr x))
x))
x)))))
x)
(div (^ (id . "footer")))))))
(define (fix-paragraphs x)
(let lp ((ls x) (p '()) (res '()))
@ -349,13 +355,44 @@ div#notes {position: relative; top: 2em; left: 550px; max-width: 200px; height:
(define (get-signature proc source form)
(match form
(('define (name . args) . body)
(cons name args))
(list (cons name args)))
(('define-syntax name ('syntax-rules () (clause . body) ...))
(map (lambda (x) (cons name (cdr x)))
(filter external-clause? clause)))
((procedure? proc)
(procedure-signature proc))
(else
(or (and (procedure? proc) (procedure-signature proc))
(procedure-name proc)))))
'())))
(define (get-ffi-signatures form)
(match form
(('define-c ret-type (or (name _) name) (args ...))
(list (cons name (map (lambda (x) (if (pair? x) (last x) x)) args))))
(('define-c-const type (or (name _) name))
(list (list 'const: type name)))
(((or 'define-c-struct 'define-c-class 'define-c-type) name . rest)
(let lp ((ls rest) (res '()))
(cond
((null? ls)
(reverse res))
((eq? 'predicate: (car ls))
(lp (cddr ls) (cons (list (cadr ls) 'obj) res)))
((eq? 'constructor: (car ls))
(lp (cddr ls)
(cons (if (pair? (cadr ls)) (cadr ls) (list (cadr ls))) res)))
((pair? (car ls))
(lp (cdr ls)
(append (if (pair? (cdddar ls))
(list (list (car (cdddar ls)) name (caar ls)))
'())
(list (list (caddar ls) name))
res)))
((symbol? (car ls))
(lp (cddr ls) res))
(else
(lp (cdr ls) res)))))
(else
#f)))
(define section-number
(let ((sections '(section subsection subsubsection subsubsubsection)))
@ -380,9 +417,16 @@ div#notes {position: relative; top: 2em; left: 550px; max-width: 200px; height:
(symbol->string name))))
(define (insert-signature orig-ls name sig)
(cond
((not (pair? sig))
orig-ls)
(else
(let ((name
(or name (if (eq? 'const: (caar sig)) (caddar sig) (caar sig)))))
(let lp ((ls orig-ls) (rev-pre '()))
(cond
((or (null? ls) (section>=? (car ls) (section-number 'subsubsubsection)))
((or (null? ls)
(section>=? (car ls) (section-number 'subsubsubsection)))
`(,@(reverse rev-pre)
,@(if (and (pair? ls)
(section-describes?
@ -390,17 +434,25 @@ div#notes {position: relative; top: 2em; left: 550px; max-width: 200px; height:
name))
'()
`((subsubsubsection
(rawcode ,@(intersperse (map write-to-string sig) '(br))))))
tag: ,(write-to-string name)
(rawcode
,@(if (eq? 'const: (caar sig))
`((i ,(write-to-string (cadar sig)) ": ")
,(write-to-string (caddar sig)))
(intersperse (map write-to-string sig) '(br)))))))
,@ls))
(else
(lp (cdr ls) (cons (car ls) rev-pre))))))
(lp (cdr ls) (cons (car ls) rev-pre)))))))))
(define (extract-docs file defs res)
(define (extract-docs file defs . o)
(call-with-input-file file
(lambda (in)
(let ((defs (map (lambda (x) `(,(car x) ,(cadr x) ,(cdaddr x)))
(filter (lambda (x) (equal? file (caaddr x))) defs))))
(let lp ((lines '()) (cur '()) (res res))
(let ((lang (or (and (pair? o) (car o)) 'scheme))
(defs (map (lambda (x) `(,(car x) ,(cadr x) ,(cdaddr x)))
(filter (lambda (x) (and (pair? (caddr x))
(equal? file (caaddr x))))
defs))))
(let lp ((lines '()) (cur '()) (res '()))
(define (collect)
(if (pair? lines)
(append
@ -435,6 +487,9 @@ div#notes {position: relative; top: 2em; left: 550px; max-width: 200px; height:
(procs (filter (lambda (x) (<= line1 (caddr x) line2))
(filter caddr defs))))
(cond
((and (eq? lang 'ffi) (get-ffi-signatures x))
=> (lambda (sigs)
(lp '() '() (append (insert-signature cur #f sigs) res))))
((= 1 (length procs))
(let* ((sig (or (get-signature (caar procs) (cdar procs) x)
'()))
@ -573,11 +628,12 @@ div#notes {position: relative; top: 2em; left: 550px; max-width: 200px; height:
(filter (lambda (x) (or (procedure? (cdr x)) (macro? (cdr x))))
(map (lambda (x) (cons x (module-ref mod-name x)))
exports)))))
(let lp ((includes (module-includes mod))
(res `((title ,(write-to-string mod-name)))))
(if (null? includes)
(output (reverse res))
(lp (cdr includes) (extract-docs (car includes) defs res))))))
(output
`((title ,(write-to-string mod-name))
,@(reverse (append-map (lambda (x) (extract-docs x defs))
(module-includes mod)))
,@(reverse (append-map (lambda (x) (extract-docs x defs 'ffi))
(module-shared-includes mod)))))))
(define (main args)
(case (length args)