Sat Jun 1 22:24:43 2024
Chibi-Scheme is a very small library with no external dependencies, intended for use as an extension and scripting language in C programs. In addition to support for lightweight VM-based threads, each VM itself runs in an isolated heap allowing multiple VMs to run simultaneously in different OS threads.
The default language is the R7RS (scheme base) library, with support for all libraries from the small language. Support for additional languages such as JavaScript, Go, Lua and Bash are planned for future releases. Scheme is chosen as a substrate because its first class continuations and guaranteed tail-call optimization makes implementing other languages easy.
The system is designed in optional layers, beginning with a VM based on a small set of opcodes, a set of primitives implemented in C, a default language, a module system implementation, and a set of standard modules. You can choose whichever layer suits your needs best and customize the rest. Adding your own primitives or wrappers around existing C libraries is easy with the C FFI.
Chibi is known to build and run on 32 and 64-bit Linux, FreeBSD, DragonFly, OS X, iOS, Windows (under Cygwin) and Plan9.
To build, just run "make". This will provide a shared library "libchibi-scheme", as well as a sample "chibi-scheme" command-line repl. The "chibi-scheme-static" make target builds an equivalent static executable. If your make doesn't support GNU make conditionals, then you'll need to edit the top of the Makefile to choose the appropriate settings. On Plan9 just run "mk". You can test the build with "make test".
To install run "make install". If you want to try the executable out without installing, you will probably need to set LD_LIBRARY_PATH, depending on your platform. If you have an old version installed, run "make uninstall" first, or manually delete the directory.
You can edit the file chibi/features.h for a number of settings, mostly disabling features to make the executable smaller. You can specify standard options directly as arguments to make, for example
make CFLAGS=-Os CPPFLAGS=-DSEXP_USE_NO_FEATURES=1
to optimize for size, or
make LDFLAGS=-L/usr/local/lib CPPFLAGS=-I/usr/local/include
to compile against a library installed in /usr/local.
By default Chibi uses a custom, precise, non-moving GC (non-moving is important so you can maintain references from C code). You can link against the Boehm conservative GC by editing the features.h file, or directly from make with:
make SEXP_USE_BOEHM=1
To compile a static executable, use
make chibi-scheme-static SEXP_USE_DL=0
Note this static executable has none of the external binary libraries
included, which means among other things you can't load the
(scheme base) default language. You need to specify the
(chibi) or other Scheme-only language to run:
./chibi-scheme-static -q
To compile a static executable with all C libraries statically included, first you need to create a clibs.c file, which can be done with:
make clibs.c
or edited manually. Be sure to run this with a non-static chibi-scheme. Then you can make the static executable with:
make -B chibi-scheme-static SEXP_USE_DL=0
CPPFLAGS="-DSEXP_USE_STATIC_LIBS -DSEXP_USE_STATIC_LIBS_NO_INCLUDE=0"
By default files are installed in /usr/local. You can optionally specify a PREFIX for the installation directory:
make PREFIX=/path/to/install/
sudo make PREFIX=/path/to/install/ install
The include file "chibi/features.h" describes a number of
C preprocessor values which can be enabled or disabled by setting to
1 or 0 respectively. For example, the above commands used the
features SEXP_USE_BOEHM, SEXP_USE_DL and
SEXP_USE_STATIC_LIBS. Many features are still experimental
and may be removed from future releases, but the important features
are listed below.
SEXP_USE_BOEHM- link with the Boehm GC instead of the native Chibi GCSEXP_USE_DL- allow dynamic linking (enabled by default)SEXP_USE_STATIC_LIBS- compile the standard C libs staticallySEXP_USE_MODULES- use the module systemSEXP_USE_GREEN_THREADS- use lightweight threads (enabled by default)SEXP_USE_SIMPLIFY- use a simplification optimizer pass (enabled by default)SEXP_USE_BIGNUMS- use bignums (enabled by default)SEXP_USE_FLONUMS- use flonums (enabled by default)SEXP_USE_RATIOS- use exact ratios (enabled by default)SEXP_USE_COMPLEX- use complex numbers (enabled by default)SEXP_USE_UTF8_STRINGS- Unicode support (enabled by default)SEXP_USE_STRING_INDEX_TABLE- precompute offsets for O(1)string-refSEXP_USE_NO_FEATURES- disable almost all features
The command-line programs chibi-scheme, chibi-doc and
chibi-ffi are installed by default, along with manpages.
chibi-scheme provides a REPL and way to run scripts. Run -?
for a brief list of options, or see the man page for more details.
chibi-doc is the command-line interface to the literate
documentation system described in
(chibi scribble), and used to
build this manual. chibi-ffi is a tool to build wrappers for
C libraries, described in the FFI section below.
See the examples directory for some sample programs.
The default language is the (scheme base) library from
R7RS, which is mostly a
superset of
R5RS.
The reader defaults to case-sensitive, like R6RS and R7RS but unlike R5RS. You can specify the -f option on the command-line to enable case-folding. The default configuration includes the full numeric tower: fixnums, flonums, bignums, exact rationals and complex numbers, though this can be customized at compile time.
Full continuations are supported, but currently continuations don't
take C code into account. This means that you can call from Scheme to
C and then from C to Scheme again, but continuations passing through
this chain may not do what you expect. The only higher-order C
functions (thus potentially running afoul of this) in the standard
environment are load and eval. The result of
invoking a continuation created by a different thread is also
currently unspecified.
In R7RS (and R6RS) semantics it is impossible to use two macros from
different modules which both use the same auxiliary keywords (like
else in cond forms) without renaming one of the
keywords. To minimize conflicts Chibi offers a special module named
(auto) which can export any identifier requested with
only, e.g. (import (only (auto) foo)) will import
an auxiliary syntax foo binding. Separate modules can use
this to get the same binding without needing to know about each other
in advance. This is a Chibi-specific extension so is non-portable, but
you can always define a static (auto) module exporting a list
of all known bindings for other implementations.
load is extended to accept an optional environment argument, like
eval. You can also load shared libraries in addition to
Scheme source files - in this case the function sexp_init_library is
automatically called with the following signature:
sexp_init_library(sexp context, sexp self, sexp_sint_t n, sexp environment,
const char* version, sexp_abi_identifier_t abi);
Note, as R7RS (and earlier reports) states, "in contrast to other dialects of Lisp, the order of evaluation is unspecified [...]". Chibi is one of the few implementations which use a right-to-left evaluation order, which can be surprising to programmers coming from other languages.
Chibi supports the R7RS module system natively, which is a simple static module system. The Chibi implementation is actually a hierarchy of languages in the style of the Scheme48 module system, allowing easy extension of the module system itself. As with most features this is optional, and can be ignored or completely disabled at compile time.
Modules names are hierarchical lists of symbols or numbers. A module definition uses the following form:
(define-library (foo bar baz)
<library-declarations> ...)
where <library-declarations> can be any of
(export <id> ...) ;; specify an export list
(import <import-spec> ...) ;; specify one or more imports
(begin <expr> ...) ;; inline Scheme code
(include <file> ...) ;; load one or more files
(include-ci <file> ...) ;; as include, with case-folding
(include-shared <file> ...) ;; dynamic load a library (non-R7RS)
(alias-for <library>) ;; a library alias (non-R7RS)
<import-spec> can either be a module name or any of
(only <import-spec> <id> ...)
(except <import-spec> <id> ...)
(rename <import-spec> (<from-id> <to-id>) ...)
(prefix <import-spec> <prefix-id>)
(drop-prefix <import-spec> <prefix-id>) ;; non-R7RS
These forms perform basic selection and renaming of individual identifiers from the given module. They may be composed to perform combined selection and renaming.
Note while the repl provides default bindings as a convenience, programs have strict semantics as in R7RS and must start with at least one import, e.g.
(import (scheme base))
(write-string "Hello world!n")
Some modules can be statically included in the initial configuration,
and even more may be included in image files, however in general
modules are searched for in a module load path. The definition of the
module (foo bar baz) is searched for in the file
"foo/bar/baz.sld". The default module path includes the
installed directories, "." and "./lib". Additional
directories can be specified with the command-line options -I
and -A (see the command-line options below) or with the
add-module-directory procedure at runtime. You can search for
a module file with (find-module-file <file>), or load it with
(load-module-file <file> <env>).
Within the module definition, files are loaded relative to the .sld file, and are written with their extension (so you can use whatever suffix you prefer - .scm, .ss, .sls, etc.).
Shared modules, on the other hand, should be specified without the extension - the correct suffix will be added portably (e.g. .so for Unix and .dylib for OS X).
You may also use cond-expand and arbitrary macro expansions in a
module definition to generate <module-declarations>.
syntax-rules macros are provided by default, with the extensions from
SRFI-46.
In addition, low-level hygienic macros are provided with a
syntactic-closures interface, including sc-macro-transformer,
rsc-macro-transformer, and er-macro-transformer. A good
introduction to syntactic-closures can be found at
http://community.schemewiki.org/?syntactic-closures.
identifier?, identifier->symbol, identifier=?, and
make-syntactic-closure and strip-syntactic-closures are
also available.
You can define new record types with SRFI-9, or inherited record types with SRFI-99. These are just syntactic sugar for the following more primitive type constructors:
(register-simple-type <name-string> <parent> <field-names>)
=> <type> ; parent may be #f, field-names should be a list of symbols
(make-type-predicate <opcode-name-string> <type>)
=> <opcode> ; takes 1 arg, returns #t iff that arg is of the type
(make-constructor <constructor-name-string> <type>)
=> <opcode> ; takes 0 args, returns a newly allocated instance of type
(make-getter <getter-name-string> <type> <field-index>)
=> <opcode> ; takes 1 args, retrieves the field located at the index
(make-setter <setter-name-string> <type> <field-index>)
=> <opcode> ; takes 2 args, sets the field located at the index
(type-slot-offset <type> <field-name>)
=> <index> ; returns the index of the field with the given name
Chibi supports Unicode strings and I/O natively. Case mappings and comparisons, character properties, formatting and regular expressions are all Unicode aware, supporting the latest version 13.0 of the Unicode standard.
Internally strings are encoded as UTF-8. This provides easy
interoperability with many C libraries, but means that
string-ref and string-set! are O(n), so they should
be avoided in performance-sensitive code (unless you compile Chibi
with SEXP_USE_STRING_INDEX_TABLE).
In general you should use high-level APIs such as string-map
to ensure fast string iteration. String ports also provide a simple
and portable way to efficiently iterate and construct strings, by
looping over an input string or accumulating characters in an output
string.
The in-string and in-string-reverse iterators in the
(chibi loop) module will also iterate over strings
efficiently while hiding the low-level details.
In the event that you do need a low-level interface, such as when
writing your own iterator protocol, you should use string cursors.
(srfi 130) provides a portable API for this, or you can use
(chibi string) which builds on the following core procedures:
(string-cursor-start str)returns a start cursor for the string
(string-cursor-end str)returns a cursor one past the last valid cursor
(string-cursor-ref str cursor)get the char at the given cursor
(string-cursor-next str cursor)increment to the next cursor
(string-cursor-prev str cursor)decrement to the previous cursor
(substring-cursor str cs1 [cs2])take a substring from the given cursors
(string-cursor<? cs1 cs2)cs1 is before cs2
(string-cursor<=? cs1 cs2)cs1 is before or the same as cs2
(string-cursor=? cs1 cs2)cs1 is the same as cs2
(string-cursor>? cs1 cs2)cs1 is after cs2
(string-cursor>=? cs1 cs2)cs1 is the same or after cs2
To use Chibi-Scheme in a program you need to link against the "libchibi-scheme" library and include the "eval.h" header file:
#include <chibi/eval.h>
All definitions begin with a "sexp_" prefix, or "SEXP_" for constants (deliberately chosen not to conflict with other Scheme implementations which typically use "scm_"). In addition to the prototypes and utility macros, this includes the following type definitions:
sexp- an s-expression, used to represent all Scheme objectssexp_uint_t- an unsigned integer using as many bits as sexpsexp_sint_t- a signed integer using as many bits as sexp
A simple program might look like:
void dostuff(sexp ctx) {
/* declare and preserve local variables *
sexp_gc_var2(obj1, obj2);
sexp_gc_preserve2(ctx, obj1, obj2);
/* load a file containing Scheme code *
obj1 = sexp_c_string(ctx, "/path/to/source/file.scm", -1);
sexp_load(ctx, obj1, NULL);
/* eval a C string as Scheme code *
sexp_eval_string(ctx, "(some scheme expression)", -1, NULL);
/* construct a Scheme expression to eval *
obj1 = sexp_intern(ctx, "my-procedure", -1);
obj2 = sexp_cons(ctx, obj1, SEXP_NULL);
sexp_eval(ctx, obj2, NULL);
/* release the local variables *
sexp_gc_release2(ctx);
}
int main(int argc, char** argv) {
sexp ctx;
sexp_scheme_init();
ctx = sexp_make_eval_context(NULL, NULL, NULL, 0, 0);
sexp_load_standard_env(ctx, NULL, SEXP_SEVEN);
sexp_load_standard_ports(ctx, NULL, stdin, stdout, stderr, 1);
dostuff(ctx);
sexp_destroy_context(ctx);
}
Looking at main, sexp_make_eval_context and
sexp_destroy_context create and destroy a "context", which
manages the heap and VM state. The meaning of the arguments is
explained in detail below, but these values will give reasonable
defaults, in this case constructing an environment with the core
syntactic forms, opcodes, and standard C primitives.
This is still a fairly bare environment, so we call
sexp_load_standard_env to find and load the default
initialization file.
The resulting context can then be used to construct objects, call
functions, and most importantly evaluate code, as is done in
dostuff. The default garbage collector for Chibi is precise,
which means we need to declare and preserve references to any
temporary values we may generate, which is what the
sexp_gc_var2, sexp_gc_preserve2 and
sexp_gc_release2 macros do (there are similar macros for
values 1-6). Precise GCs prevent a class of memory leaks (and
potential attackes based thereon), but if you prefer convenience then
Chibi can be compiled with a conservative GC and you can ignore these.
The interesting part is then the calls to sexp_load,
eval_string and eval which evaluate code stored in
files, C strings, or represented as s-expressions respectively.
Destroying a context runs any finalizers for all objects in the heap and then frees the heap memory (but has no effect on other contexts you or other users of the library may have created).
Contexts represent the state needed to perform evaluation. This includes
keeping track of the heap (when using precise GC), a default environment,
execution stack, and any global values. A program being evaluated in one
context may spawn multiple child contexts, such as when you call eval,
and each child will share the same heap and globals. When using multiple
interpreter threads, each thread has its own context.
You can also create independent contexts with their own separate heaps. These can run simultaneously in multiple OS threads without any need for synchronization.
sexp_make_context(sexp ctx, size_t size, size_t max_size)Creates a new context object. The context has no associated environment, and so cannot be used for evaluation, but can be used to construct Scheme objects and call primitive C functions on them. If
ctxis non-NULL it becomes the "parent" context. The resulting context will share the same heap as its parent, and when using a precise GC preserve any variables preserved by the parent, but the parent will not preserve the child context by default. Typically you either preserve the child manually or use it to perform a single sub-task then discard it and return to using only the parent. Otherwise, a new heap is allocated withsizebytes, expandable to a maximum ofmax_sizebytes, using the system defaults if either is 0. Note this context is not a malloced pointer (it resides inside a malloced heap), and therefore can't be passed tofree(), or stored in a C++ smart pointer. It can only be reclaimed withsexp_destroy_context.sexp_make_eval_context(sexp ctx, sexp stack, sexp env, sexp_uint_t size, sexp_uint_t max_size)Similar to sexp_make_context, but also associates a stack, environment, and additional globals necessary to evaluate code. Either or both of
stackandenvmay be NULL, in which case defaults will be generated. The default environment includes the compiled-in C primitives, as well as the 10 core forms:define,set!,lambda,if,begin,quote,syntax-quote,define-syntax,let-syntax, andletrec-syntax.sexp_load_standard_env(sexp ctx, sexp env, sexp version)Loads the standard parameters for
env, constructs the feature list from pre-compiled defaults, and loads the installed initialization file forversion, which should be the valueSEXP_SEVEN. Also creates aninteraction-environmentparameter and setsenvitself to that.sexp_load_standard_ports(sexp ctx, sexp env, FILE* in, FILE* out, FILE* err, int leave_open)Creates
current-input-port,current-output-port, andcurrent-error-portparameters fromin,outanderr, and binds them inenv. IfenvisNULL the default context environment is used. Any of theFILE*may beNULL , in which case the corresponding port is not set. Ifleave_openis true, then the underlyingFILE*is left open after the Scheme port is closed, otherwise they are both closed together. If you want to reuse these streams from other vms, or from C, you should specify leave_open.sexp_load(sexp ctx, sexp file, sexp env)Searches the installation path for the
fileand loads it in the environmentenv.filemay be a dynamic library or source code.sexp_eval(sexp ctx, sexp obj, sexp env)Evaluates
objas a source form in the environmentenvand returns the result.sexp_eval_string(sexp ctx, const char* str, int len, sexp env)Reads a s-expression from the C string
str(or the firstlenbytes iflenis non-negative), evaluates the resulting form in the environmentenv, and returns the result.sexp_apply(sexp ctx, sexp proc, sexp args)Applies the procedure
procto the arguments in the listargsand returns the result.sexp_context_env(sexp ctx)Returns the current default environment associated with the context
ctx.sexp_env_define(sexp ctx, sexp env, sexp sym, sexp val)Adds a new binding for
syminenvwith valueval.sexp_env_ref(sexp env, sexp sym, sexp dflt)Returns the current binding of
syminenv, ordfltif there is no binding.sexp_env_import(sexp ctx, sexp to, sexp from, sexp ls, sexp immutp)Imports the bindings from environment
frominto environmentto.lsis the list of bindings to import - if it is#fthen import all bindings. Ifimmutpis true the imported bindings are immutable and cannot be redefined.sexp_parameter_ref(sexp ctx, sexp param)Returns the current dynamic value of the parameter
paramin the given context.
Chibi uses a precise garbage collector by default, which means when performing multiple computations on the C side you must explicitly preserve any temporary values. You can declare variables to be preserved with sexp_gc_varn, for n from 1 to 6.
sexp_gc_varn(obj1, obj2, ..., objn)
This is equivalent to the declaration
sexp obj1, obj2, ..., objn;
except it makes preservation possible. Because it is a declaration it must occur at the beginning of your function, and because it includes assignments (in the macro-expanded form) it should occur after all other declarations.
To preserve these variables for a given context, you can then use sexp_gc_preserven:
sexp_gc_preserven(ctx, obj1, obj2, ..., objn)
This can be delayed in your code until you know a potentially memory-allocating computation will be performed, but once you call sexp_gc_preserven it must be paired with a matching sexp_gc_releasen:
sexp_gc_releasen(ctx);
Note each of these have different signatures. sexp_gc_varn just lists the variables to be declared. sexp_gc_preserven prefixes these with the context in which they are to be preserved, and sexp_gc_releasen just needs the context.
A typical usage for these is:
sexp foo(sexp ctx, sexp bar, sexp baz) {
/* variable declarations *
int i, j;
...
sexp_gc_var3(tmp1, tmp2, res);
/* asserts or other shortcut returns *
sexp_assert_type(ctx, sexp_barp, SEXP_BAR, bar);
sexp_assert_type(ctx, sexp_bazp, SEXP_BAZ, baz);
/* preserve the variables in ctx *
sexp_gc_preserve3(ctx, tmp1, tmp2, res);
/* perform your computations *
tmp1 = ...
tmp2 = ...
res = ...
/* release before returning *
sexp_gc_release3(ctx);
return res;
}
If compiled with the Boehm GC, sexp_gc_varn just translates to the plain declaration, while sexp_gc_preserven and sexp_gc_releasen become noops.
When interacting with a garbage collection system from another
language, or communicating between different Chibi managed heaps, you
may want to manually ensure objects are preserved irrespective of any
references to it from other objects in the same heap. This can be
done with the sexp_preserve_object and
sexp_release_object utilities.
sexp_preserve_object(ctx, obj)
Increment the absolute reference count for obj. So long as the
reference count is above 0, obj will not be reclaimed even if
there are no references to it from other object in the Chibi managed
heap.
sexp_release_object(ctx, obj)
Decrement the absolute reference count for obj.
The above sections describe most everything you need for embedding in a typical application, notably creating environments and evaluating code from sexps, strings or files. The following sections expand on additional macros and utilities for inspecting, accessing and creating different Scheme types, and for performing port and string I/O. It is incomplete - see the macros and SEXP_API annotated functions in the include files (sexp.h, eval.h, bignum.h) for more bindings.
Being able to convert from C string to sexp, evaluate it, and convert the result back to a C string forms the basis of the C API. Because Chibi is aimed primarily at minimal size, there are relatively few other utilities or helpers. It is expected most high-level code will be written in Scheme, and most low-level code will be written in pure, Scheme-agnostic C and wrapped via the FFI.
The sexp represents different Scheme types with the use of tag bits for so-called "immediate" values, and a type tag for heap-allocated values. The following predicates can be used to distinguish these types. Note the predicates in C all end in "p". For efficiency they are implemented as macros, and so may evaluate their arguments multiple times.
Note also that the non-immediate type checks will segfault if passed a NULL value. At the Scheme level (and the return values of any exported primitives) NULLs are never exposed, however some unexposed values in C can in certain cases be NULL. If you're not sure you'll need to check manually before applying the predicate.
sexp_booleanp(obj)-objis#tor#fsexp_fixnump(obj)-objis an immediate integersexp_flonump(obj)-objis an inexact realsexp_bignump(obj)-objis a heap-allocated integersexp_integerp(obj)-objis an integer (or flonum truncating without loss)sexp_ratiop(obj)-objis an exact rational (with SEXP_USE_RATIOS)sexp_complexp(obj)-objis a complex number (with SEXP_USE_COMPLEX)sexp_numberp(obj)-objis any kind of numbersexp_charp(obj)-objis a charactersexp_stringp(obj)-objis a stringsexp_string_cursorp(obj)-objis a string cursorsexp_bytesp(obj)-objis a bytevectorsexp_symbolp(obj)-objis a symbolsexp_idp(obj)-objis a symbol or hygienic identifiersexp_nullp(obj)-objis the null valuesexp_pairp(obj)-objis a pairsexp_vectorp(obj)-objis a vectorsexp_iportp(obj)-objis an input portsexp_oportp(obj)-objis an output portsexp_portp(obj)-objis any kind of portsexp_procedurep(obj)-objis a proceduresexp_opcodep(obj)-objis a primitive opcodesexp_applicablep(obj)-objis valid as the first arg to applysexp_typep(obj)-objis a typesexp_exceptionp(obj)-objis an exceptionsexp_contextp(obj)-objis a contextsexp_envp(obj)-objis an environmentsexp_corep(obj)-objis a special formsexp_macrop(obj)-objis a macrosexp_synclop(obj)-objis a syntactic closuresexp_bytecodep(obj)-objis compiled bytecodesexp_cpointerp(obj)-objis an opaque C pointer
The following shortcuts for various immediate values are available.
SEXP_FALSE- the false booleanSEXP_TRUE- the true booleanSEXP_NULL- the empty listSEXP_EOF- the end-of-file objectSEXP_VOID- an undefined value often returned by mutatorsSEXP_ZERO- shortcut for sexp_make_fixnum(0)SEXP_ONE- shortcut for sexp_make_fixnum(1)- ...
SEXP_TEN- shortcut for sexp_make_fixnum(10)SEXP_NEG_ONE- shortcut for sexp_make_fixnum(-1)
Scheme strings are length bounded C strings which can be accessed with the following macros:
char* sexp_string_data(sexp s)- the raw bytes of the stringsexp_uint_t sexp_string_size(sexp s)- the number of raw bytes in the stringsexp_uint_t sexp_string_length(sexp s)- the number of characters encoded ins
Currently all Scheme strings also happen to be NULL-terminated, but you should not rely on this and be sure to use the size as a bounds check. The runtime does not prevent embedded NULLs inside strings, however data after the NULL may be ignored.
By default (unless you compile with -DSEXP_USE_UTF8_STRING=0), strings are interpreted as UTF-8 encoded on the Scheme side, as describe in section Unicode above. In many cases you can ignore this on the C side and just treat the string as an opaque sequence of bytes. However, if you need to you can use the following macros to safely access the contents of the string regardless of the options Chibi was compiled with:
sexp sexp_string_ref(sexp ctx, sexp s, sexp i)- returns the character at index isexp sexp_string_set(sexp ctx, sexp s, sexp i, sexp ch)- sets the character at index isexp sexp_string_cursor_ref(sexp ctx, sexp s, sexp i)- returns the character at raw offset i (a fixnum)sexp sexp_string_cursor_set(sexp ctx, sexp s, sexp i, sexp ch)- sets the character at raw offset i (a fixnum)sexp sexp_string_cursor_next(sexp s, sexp i)- returns the next cursor after raw offsetisexp sexp_string_cursor_prev(sexp s, sexp i)- returns the previous cursor before raw offsetisexp sexp_substring(sexp ctx, sexp s, sexp i, sexp j)- returns the substring between indicesiandjsexp sexp_substring_cursor(sexp ctx, sexp s, sexp i, sexp j)- returns the substring between raw offsetsiandj
When UTF-8 support is not compiled in the cursor and non-cursor variants are equivalent.
The following macros provide access to the different components of the Scheme types. They do no type checking, essentially translating directly to pointer offsets, so you should be sure to use the above predicates to check types first. They only evaluate their arguments once.
sexp_make_boolean(n)-#fifnis 0,#totherwisesexp_unbox_boolean(obj)- 1 ifobjis#t, 0 otherwisesexp_make_fixnum(n)- creates a new fixnum representing intnsexp_unbox_fixnum(obj)- converts a fixnum to a C integersexp_make_flonum(sexp ctx, float f)- creates a new floating point valuesexp_flonum_value(obj)- converts a flonum to a C floatsexp_make_character(ch)- creates a new character representing charchsexp_unbox_character(obj)- converts a character to a C charsexp sexp_make_string_cursor(int offset)- creates a string cursor for the given byte offsetint sexp_unbox_string_cursor(sexp sc)- returns the offset for the given string cursorsexp_car(pair)- the car ofpairsexp_cdr(pair)- the cdr ofpairsexp_ratio_numerator(q)- the numerator of the ratioqsexp_ratio_denominator(q)- the denominator of the ratioqsexp_complex_real(z)- the real part of the complexzsexp_complex_imag(z)- the imaginary part of the complexzsexp_string_length(str)- the byte length ofstras an intsexp_string_ref(str, i)- thei'th byte of stringstrsexp_string_set(str, i, ch)- set thei'th byte of stringstrsexp_bytes_length(bv)- the length ofbvas an intsexp_bytes_data(bv)- the raw char* data ofbvsexp_vector_length(vec)- the length ofvecas an intsexp_vector_ref(vec, i)- thei'th object of vectorvecsexp_vector_set(vec, i, obj)- set thei'th object of vectorvecsexp_bytes_length(bv)- the number of bytes in bytevectorbvsexp_bytes_ref(bv, i)- thei'th byte of bytevectorbvsexp_bytes_set(bv, i, k)- set thei'th byte of bytevectorbv
Constructors allocate memory and so must be passed a context argument. Any of these may fail and return the OOM exception object.
sexp_cons(sexp ctx, sexp obj1, sexp obj2)- create a new pair whose car isobj1and whose cdr isobj2sexp_list1(sexp ctx, sexp obj)- alias for sexp_cons(ctx, obj, SEXP_NULL)sexp_list2(sexp ctx, sexp obj1, sexp obj2)- create a list of two elementssexp_list3(sexp ctx, sexp obj1, sexp obj2, sexp obj3)- create a list of three elementssexp_make_string(sexp ctx, sexp len, sexp ch)- create a new Scheme string oflencharacters, all initialized tochsexp_c_string(sexp ctx, const char* str, int len)- create a new Scheme string copying the firstlencharacters of the C stringstr. Iflenis -1, uses strlen(str).sexp_intern(sexp ctx, const char* str, int len)- interns a symbol from the firstlencharacters of the C stringstr. Iflenis -1, uses strlen(str).sexp_make_bytes(sexp ctx, sexp len, sexp i)- create a new Scheme bytevector oflenbytes, all initialized toisexp_make_vector(sexp ctx, sexp len, sexp obj)- create a new vector oflenelements, all initialized toobjsexp_make_integer(sexp ctx, sexp_sint_t n)- create an integer, heap allocating as a bignum if neededsexp_make_unsigned_integer(sexp ctx, sexp_uint_t n)- create an unsigned integer, heap allocating as a bignum if needed
sexp_read(sexp ctx, sexp in)- read a single datum from portinsexp_write(sexp ctx, sexp obj, sexp out)- writeobjto portoutsexp_write_string(sexp ctx, char* str, sexp out)- write the characters instrto portoutsexp_newline(sexp ctx, sexp out)- write a newline to portoutsexp_print_exception(sexp ctx, sexp exn, sexp out)- print an error message forexnto portoutsexp_current_input_port(sexp ctx)- thecurrent-input-portsexp_current_output_port(sexp ctx)- thecurrent-output-portsexp_current_error_port(sexp ctx)- thecurrent-error-portsexp_debug(sexp ctx, char* msg, sexp obj)- writeobjwith a debug message prefix tocurrent-error-portsexp_read_from_string(sexp ctx, char* str, int len)- read a single datum fromstr, using at mostlenbytes iflenis non-negativesexp_write_to_string(sexp ctx, sexp obj)- return a Scheme string representation ofobjsexp_open_input_string(sexp ctx, sexp str)- equivalent toopen-input-stringsexp_open_output_string(sexp ctx)- equivalent toopen-output-stringsexp_get_output_string(sexp ctx, sexp port)- equivalent toget-output-string
sexp_equalp(sexp ctx, sexp x, sexp y)-equal?sexp_length(sexp ctx, sexp ls)-lengthsexp_listp(sexp ctx, sexp x)-list?sexp_memq(sexp ctx, sexp x, sexp ls)-memqsexp_assq(sexp ctx, sexp x, sexp ls)-assqsexp_reverse(sexp ctx, sexp ls)-reversesexp_nreverse(sexp ctx, sexp ls)-reverse!sexp_append2(sexp ctx, sexp ls1, sexp ls2)-appendfor two argumentssexp_copy_list(sexp ctx, sexp ls)- return a shallow copy oflssexp_list_to_vector(sexp ctx, sexp ls)-list->vectorsexp_symbol_to_string(sexp ctx, sexp sym)-symbol->stringsexp_string_to_symbol(sexp ctx, sexp str)-string->symbolsexp_string_to_number(sexp ctx, sexp str)-string->number
Exceptions can be created with the following:
sexp sexp_make_exception (sexp ctx, sexp kind, sexp message, sexp irritants, sexp procedure, sexp source)Create an exception of the given
kind(a symbol), with the stringmessage, andirritantslist.procedureandsourceprovide information about the error location. From a C function,procedureshould generally beself.sexp sexp_user_exception (sexp ctx, sexp self, const char *msg, sexp x)Shortcut for an exception of kind
user, with the given message and single irritant.sexp sexp_type_exception (sexp ctx, sexp self, sexp_uint_t type_id, sexp x)Shortcut for an exception of kind
type, wherexwas expected to be of typetype_idbut wasn't.sexp sexp_xtype_exception (sexp ctx, sexp self, const char *msg, sexp x)Shortcut for an exception of kind
type, for more general domain errors, wherexfailed to meet the restrictions inmsg.
Returning an exception from a C function by default raises that exception in the VM. If you want to pass an exception as a first class value, you have to wrap it first:
sexp sexp_maybe_wrap_error (sexp ctx, sexp obj)
You can add your own types and primitives with the following functions.
sexp sexp_define_foreign(sexp ctx, sexp env, const char* name, int num_args, sexp_proc1 func)Defines a new primitive procedure with the name
namein the environmentenv. The procedure takesnum_argsarguments and passes them to the C functionfunc. The C function must take the standard calling convention:sexp func(sexp ctx, sexp self, sexp n, sexp arg1, ..., sexp argnum_args)wherectxis the current context,selfis the procedure itself, andnis the number of arguments passed.funcis responsible for checking its own argument types.sexp sexp_define_foreign_opt(sexp ctx, sexp env, const char* name, int num_args, sexp_proc1 func, sexp dflt)Equivalent to
sexp_define_foreign, except the final argument is optional and defaults to the valuedflt.sexp sexp_define_foreign_param(sexp ctx, sexp env, const char* name, int num_args, sexp_proc1 func, const char* param)Equivalent to
sexp_define_foreign_opt, except instead of a fixed default argumentparamshould be the name of a parameter bound inenv.sexp sexp_register_simple_type(sexp ctx, sexp name, sexp parent, sexp slots)Defines a new simple record type having
slotsnew slots in addition to any inherited from the parent typeparent. Ifparentis false, inherits from the defaultobjectrecord type.sexp sexp_register_c_type(sexp ctx, sexp name, sexp finalizer)Shortcut to defines a new type as a wrapper around a C pointer. Returns the type object, which can be used with sexp_make_cpointer to wrap instances of the type. The finalizer may be sexp_finalize_c_type in which case managed pointers are freed as if allocated with malloc, NULL in which case the pointers are never freed, or otherwise a procedure of one argument which should release any resources.
sexp sexp_make_cpointer(sexp ctx, sexp_uint_t type_tag, void* value, sexp parent, int freep)Creates a new instance of the type indicated by type_tag wrapping value. If parent is provided, references to the child will also preserve the parent, important e.g. to preserve an enclosing struct when wrapped references to nested structs are still in use. If freep is true, then when reclaimed by the GC the finalizer for this type, if any, will be called on the instance. You can retrieve the tag from a type object with sexp_type_tag(type).
sexp sexp_lookup_type(sexp ctx, sexp name, sexp tag_or_id)Returns the type whose name matches the string
name. Iftag_or_idis an integer, it is taken as the tag and requires the numeric type tag (as from sexp_type_tag) to also match.If
tag_or_idis a string, it is taken as the unique id of the type, and must match sexp_type_id(type). However, currently sexp_type_id(type) is never set.
See the C FFI for an easy way to automate adding bindings for C functions.
The "chibi-ffi" script reads in the C function FFI definitions from an input file and outputs the appropriate C wrappers into a file with the same base name and the ".c" extension. You can then compile that C file into a shared library:
chibi-ffi file.stub
cc -fPIC -shared file.c -lchibi-scheme
(or using whatever flags are appropriate to generate shared libs on
your platform) and the generated .so file can be loaded directly with
load, or portably using (include-shared "file") in a
module definition (note that include-shared uses no suffix).
The goal of this interface is to make access to C types and functions easy, without requiring the user to write any C code. That means the stubber needs to be intelligent about various C calling conventions and idioms, such as return values passed in actual parameters. Writing C by hand is still possible, and several of the core modules provide C interfaces directly without using the stubber.
(c-include header)- includes the fileheader(c-system-include header)- includes the system fileheader(c-declare args ...)- outputsargsdirectly in the top-level C source(c-init args ...)- evaluatesargsas C code after all other library initializations have been performed, withctx andenv in scope
C structs can be bound as Scheme types with the
define-c-struct form:
(define-c-struct struct_name
[predicate: predicate-name]
[constructor: constructor-name]
[finalizer: c_finalizer_name]
(type c_field_name getter-name setter-name) ...)
struct_name should be the name of a C struct type. If provided,
predicate-name is bound to a procedure which takes one object
and returns #t iff the object is of type struct_name.
If provided, constructor-name is bound to a procedure of zero
arguments which creates and returns a newly allocated instance of the
type.
If a finalizer is provided, c_finalizer_name must be a C
function which takes one argument, a pointer to the struct, and
performs any cleanup or freeing of resources necessary.
The remaining slots are similar to the
SRFI-9 syntax,
except they are prefixed with a C type (described below). The
c_field_name should be a field name of struct_name.
getter-name will then be bound to a procedure of one argument, a
struct_name type, which returns the given field. If provided,
setter-name will be bound to a procedure of two arguments to
mutate the given field.
The variants define-c-class and define-c-union take
the same syntax but define types with the class and
union keywords respectively. define-c-type just
defines accessors to an opaque type without any specific struct-like
keyword.
;; Example: the struct addrinfo returned by getaddrinfo.
(c-system-include "netdb.h")
(define-c-struct addrinfo
finalizer: freeaddrinfo
predicate: address-info?
(int ai_family address-info-family)
(int ai_socktype address-info-socket-type)
(int ai_protocol address-info-protocol)
((link sockaddr) ai_addr address-info-address)
(size_t ai_addrlen address-info-address-length)
((link addrinfo) ai_next address-info-next))
C functions are defined with:
(define-c return-type name-spec (arg-type ...))
where name-space is either a symbol name, or a list of
(scheme-name c_name). If just a symbol is used, the C name
is generated automatically by replacing any dashes (-) in the Scheme
name with underscores (_).
Each arg-type is a type suitable for input validation and
conversion as discussed below.
;; Example: define connect(2) in Scheme
(define-c int connect (int sockaddr int))
Constants can be defined with:
(define-c-const type name-space)
where name-space is the same form as in define-c. This
defines a Scheme variable with the same value as the C constant.
;; Example: define address family constants in Scheme
(define-c-const int (address-family/unix "AF_UNIX"))
(define-c-const int (address-family/inet "AF_INET"))
voidbooleancharsexp(no conversions)
signed-charshortintlongunsigned-charunsigned-shortunsigned-intunsigned-longsize_tpid_tuid_tgid_ttime_t(in seconds, but using the chibi epoch of 2010/01/01)errno(as a return type returns#fon error)
floatdoublelong-double
string- a null-terminated char*env-string- aVAR=VALUEstring represented as a(VAR . VALUE)pair in Scheme(array char)is equivalent tostring
input-portoutput-port
Struct types are by default just referred to by the bare
struct_name from define-c-struct, and it is assumed you
want a pointer to that type. To refer to the full struct, use the
struct modifier, as in (struct struct-name).
Any type may also be written as a list of modifiers followed by the type itself. The supported modifiers are:
constPrepends the "const" C type modifier. As a return or result parameter, makes non-immediates immutable.
freeIt's Scheme's responsibility to "free" this resource. As a return or result parameter, registers the freep flag this causes the type finalizer to be run when GCed.
maybe-nullThis pointer type may be NULL. As a result parameter, NULL is translated to #f normally this would just return a wrapped NULL pointer. As an input parameter, #f is translated to NULL normally this would be a type error.
pointerCreate a pointer to this type. As a return parameter, wraps the result in a vanilla cpointer. As a result parameter, boxes then unboxes the value.
referenceA stack-allocated pointer to this type. As a result parameter, passes a stack-allocated pointer to the value, then returns the dereferenced pointer.
structTreat this struct type as a struct, not a pointer. As an input parameter, dereferences the pointer. As a type field, indicates a nested struct.
linkAdd a gc link. As a field getter, link to the parent object, so the parent won't be GCed so long as we have a reference to the child. This behavior is automatic for nested structs.
resultReturn a result in this parameter. If there are multiple results (including the return type), they are all returned in a list. If there are any result parameters, a return type of errno returns #f on failure, and as eliminated from the list of results otherwise.
(value <expr>)Specify a fixed value. As an input parameter, this parameter is not provided in the Scheme API but always passed as <expr>.
(default <expr>)Specify a default value. As the final input parameter, makes the Scheme parameter optional, defaulting to <expr>.
(array <type> [<length>])An array type. Length must be specified for return and result parameters. If specified, length can be either an integer, indicating a fixed size, or the symbol null, indicating a NULL-terminated array.
A number of SRFIs are provided in the default installation. Note that SRFIs 0, 6, 23, 46 and 62 are built into the default environment so there's no need to import them. SRFI 22 is available with the "-r" command-line option. This list includes popular SRFIs or SRFIs used in standard Chibi modules (many other SRFIs are available on snow-fort):
- (srfi 0) - cond-expand
- (srfi 1) - list library
- (srfi 2) - and-let*
- (srfi 6) - basic string ports
- (srfi 8) - receive
- (srfi 9) - define-record-type
- (srfi 11) - let-values/let*-values
- (srfi 14) - character-set library
- (srfi 16) - case-lambda
- (srfi 18) - multi-threading support
- (srfi 22) - running scheme scripts on Unix
- (srfi 23) - error reporting mechanism
- (srfi 26) - cut/cute partial application
- (srfi 27) - sources of random bits
- (srfi 33) - bitwise operators
- (srfi 38) - read/write shared structures
- (srfi 39) - parameter objects
- (srfi 41) - streams
- (srfi 46) - basic syntax-rules extensions
- (srfi 55) - require-extension
- (srfi 62) - s-expression comments
- (srfi 64) - a scheme API for test suites
- (srfi 69) - basic hash tables
- (srfi 95) - sorting and merging
- (srfi 98) - environment access
- (srfi 99) - ERR5RS records
- (srfi 101) - purely functional random-access pairs and lists
- (srfi 111) - boxes
- (srfi 113) - sets and bags
- (srfi 115) - Scheme regular expressions
- (srfi 116) - immutable list library
- (srfi 117) - mutable queues
- (srfi 121) - generators
- (srfi 124) - ephemerons
- (srfi 125) - intermediate hash tables
- (srfi 127) - lazy sequences
- (srfi 128) - comparators (reduced)
- (srfi 129) - titlecase procedures
- (srfi 130) - cursor-based string library
- (srfi 132) - sort libraries
- (srfi 133) - vector library
- (srfi 134) - immutable deques
- (srfi 135) - immutable texts
- (srfi 139) - syntax parameters
- (srfi 141) - integer division
- (srfi 142) - bitwise operations
- (srfi 143) - fixnums
- (srfi 144) - flonums
- (srfi 145) - assumptions
- (srfi 147) - custom macro transformers
- (srfi 151) - bitwise operators
- (srfi 154) - first-class dynamic extents
- (srfi 158) - generators and accumulators
- (srfi 160) - homogeneous numeric vector libraries
- (srfi 165) - the environment Monad
- (srfi 166) - monadic formatting
- (srfi 179) - nonempty intervals and generalized arrays
- (srfi 188) - splicing binding constructs for syntactic keywords
- (srfi 193) - command-line
- (srfi 211) - scheme macro libaries
- (srfi 219) - define higher-order lambda
- (srfi 227) - optional arguments
- (srfi 229) - tagged procedures
- (srfi 231) - intervals and generalized arrays
Additional non-standard modules are put in the (chibi) module
namespace.
- (chibi app) - Unified option parsing and config
- (chibi ast) - Abstract Syntax Tree and other internal data types
- (chibi assert) - A nicer assert macro
- (chibi base64) - Base64 encoding and decoding
- (chibi binary-record) - Record types with binary serialization
- (chibi bytevector) - Bytevector Utilities
- (chibi config) - General configuration management
- (chibi crypto md5) - MD5 hash
- (chibi crypto rsa) - RSA public key encryption
- (chibi crypto sha2) - SHA-2 hash
- (chibi diff) - LCS Algorithm and diff utilities
- (chibi disasm) - Disassembler for the virtual machine
- (chibi doc) - Chibi documentation utilities
- (chibi edit-distance) - A levenshtein distance implementation
- (chibi equiv) - A version of
equal?which is guaranteed to terminate - (chibi filesystem) - Interface to the filesystem and file descriptor objects
- (chibi generic) - Generic methods for CLOS-style object oriented programming
- (chibi heap-stats) - Utilities for gathering statistics on the heap
- (chibi io) - Various I/O extensions and custom ports
- (chibi iset base) - Compact integer sets
- (chibi iset base) - Compact integer sets
- (chibi iset constructors) - Compact integer set construction
- (chibi iset iterators) - Iterating over compact integer sets
- (chibi json) - JSON reading and writing
- (chibi loop) - Fast and extensible loop syntax
- (chibi match) - Intuitive and widely supported pattern matching syntax
- (chibi math prime) - Prime number utilities
- (chibi memoize) - Procedure memoization
- (chibi mime) - Parse MIME files into SXML
- (chibi modules) - Introspection for the module system itself
- (chibi net) - Simple networking interface
- (chibi net http-server) - Simple http-server with servlet support
- (chibi net servlet) - HTTP servlets for http-server or CGI
- (chibi optional) - Syntax to support optional and named keyword arguments
- (chibi parse) - Parser combinators with convenient syntax
- (chibi pathname) - Utilities to decompose and manipulate pathnames
- (chibi process) - Interface to spawn processes and handle signals
- (chibi repl) - A full-featured Read/Eval/Print Loop
- (chibi shell) - Process combinators with high-level pipeline syntax in the spirit of SCSH.
- (chibi show) - Monadic formattinga.
- (chibi scribble) - A parser for the scribble syntax used to write this manual
- (chibi string) - Cursor-based string library (predecessor to SRFI 130)
- (chibi stty) - A high-level interface to ioctl
- (chibi sxml) - SXML utilities
- (chibi system) - Access to the host system and current user information
- (chibi temp-file) - Temporary file and directory creation
- (chibi test) - A simple unit testing framework
- (chibi time) - An interface to the current system time
- (chibi trace) - A utility to trace procedure calls
- (chibi type-inference) - An easy-to-use type inference system
- (chibi uri) - Utilities to parse and construct URIs
- (chibi weak) - Data structures with weak references
Beyond the distributed modules, Chibi comes with a package manager
based on Snow2
which can be used to share R7RS libraries. Packages are distributed
as tar gzipped files called "snowballs," and may contain multiple
libraries. The program is installed as snow-chibi. The
"help" subcommand can be used to list all subcommands and options.
Note by default snow-chibi uses an image file to speed-up
loading (since it loads many libraries) - if you have any difficulties
with image files on your platform you can run
snow-chibi --noimageto disable this feature.
By default snow-chibi looks for packages in the public
repository http://snow-fort.org/,
though you can customize this with the --repository-uri or
--repo option (e.g. "http://snow-fort.org/s/repo.scm").
Packages can be browsed on the site, but you can also search and query from the command-line tool.
- search terms ... - search for packages
Print a list of available packages matching the given keywords.
- show names ... - show package descriptions
Show detailed information for the listed packages, which can be sexp library names or the dotted shorthand used by chibi. For example,
snow-chibi show "(chibi match)"can be shortened assnow-chibi show chibi.match. - status names ... - print package status
Print the installed version of the given packages. Uninstalled packages will not be shown. If no names are given, prints all currently installed packages.
- implementations - print list of available implementations
Print the currently installed Scheme implementations supported by
snow-chibi. If an implementation is found but has an older version, a warning is printed.
The basic package management functionality, installing upgrading and removing packages.
By default the packages will be managed for Chibi. You can specify
what Scheme implementation to install, upgrade... with
--implementations or --impls option. Specify "all"
to manage all supported implementations.
- install names ... - install packages
Install the given packages. Package names can be sexp lists or use the dotted shorthand. Explicit names for packages are optional, as a package can always be referred to by the name of any library it contains. If multiple packages provide libraries with the same name, you will be asked to confirm which implementation to install.
You can also bypass the repository and install a manually downloaded snowball by giving a path to that file instead of a name. No package dependencies will be checked for install in this case
- upgrade names ... - upgrade installed packages
Upgrade the packages if new versions are available. If no names are given, upgrades all eligible packages.
- remove names ... - remove packages
Uninstalls the given packages. If the packages were not installed with
snow-chibithey cannot be removed. - update - update local cache of remote repository
snow-chibikeeps a local cache of the remote repository and updates only periodically for performance, but you can force an update with this command.
Creating packages can be done with the package command,
though other commands allow for uploading to public repositories.
By default the public repository is
http://snow-fort.org/ but you can
customize this with the --host option.
- package files ... - create a package
Create a package snowball from the given files, which should be R7RS library files containing
define-libraryforms. Include files are inferred and packaged automatically. You can share packages directly, or upload them to a snow repository for easy automated install. - upload files ... - upload packages
Sign and upload to the default snow host. The files may either be .tgz package files, or files containing define-library forms as in the
packagecommand, from which packages are generated automatically. Before you can upload to the default host a key must be generated and registered first with thegen-keyandreg-keycommands. - gen-key - create a new key
Create a new key, with your name, email address, and optionally an RSA public key pair (disabled by default in the current implementation). This is saved locally to ~/.snow/priv-key.scm - you need to register it with reg-key before it can be used for uploads.
- reg-key - register a key
Register your key on the default snow host.
- sign file - sign a package
Sign a file with your key and write it to the .sig file. This can be used with the verify command for testing, but otherwise is not needed as the upload command generates the signature automatically.
- verify sig-file - verify a signature
Print a message verifying if a signature is valid.
To encourage sharing code it's important to make it as easy as
possible to create packages, while encouraging documentation and
tests. In particular, you should never need to duplicate information
anywhere. Thus the package command automatically locates
and packages include files (and data and ffi files) and determines
dependencies for you. In addition, it can automatically handle
versions, docs and tests:
- version - can come explicitly from the
--versionoption, or the--version-file=<file>option - docs - can come explicitly from the
--doc=<file>option, or be extracted automatically from literate documentation withdoc-for-scribble - tests - can come explicitly from the
--test=<prog-file>option, or the--test-library=<lib-name>which will generate a program to run just therun-teststhunk in that library
Other useful meta-info options include:
--authors- specify the package authors (comma-delimited)--maintainers- specify the package maintainers (comma-delimited)--license- specify the package licence
These three are typically always the same, so it's useful to save them in your ~/.snow/config.scm file. This file contains a single sexp and can specify any option, for example:
((repository-uri "http://alopeke.gr/repo.scm")
(command
(package
(authors "Socrates <hemlock@aol.com>")
(doc-from-scribble #t)
(version-file "VERSION")
(test-library (append-to-last -test))
(license gpl))))
Top-level snow options are represented as a flat alist. Options
specific to a command are nested under (command (name ...)),
with most options here being for package. Here unless
overridden on the command-line, all packages will use the given author
and license, try to extract literate docs from the code, look for a
version in the file "VERSION", and try to find a test with the same
library name appended with -test, e.g. for the library
(socratic method), the test library would be
(socratic method-test). This form is an alternate to using
an explicit test-library name, and encourages you to keep your tests
close to the code they test. In the typical case, if using these
conventions, you can thus simply run snow-chibi package
<lib-file> without any other options.
Although the command is called snow-chibi, it supports
several other R7RS implementations. The implementations
command tells you which you currently have installed. The following
are currently supported:
- chibi - version >= 0.7.3
- chicken - version >= 4.9.0 with the
r7rsegg - cyclone - version >= 0.5.3
- foment - version >= 0.4
- gauche - version >= 0.9.4
- kawa - version >= 2.0; you need to add the install dir to the search path, e.g.
-Dkawa.import.path=/usr/local/share/kawa - larceny - version 0.98; you need to add "lib/Snow" to the paths in startup.sch
- sagittarius - version >= 0.98