____ ____ _ ___ _____ | _ \/ ___| ___| |__ ___ _ __ ___ ___ / _ \|___ | | |_) \___ \ / __| '_ \ / _ \ '_ ` _ \ / _ \ | | | | / / | _ < ___) | (__| | | | __/ | | | | | __/ | |_| | / / |_| \_\____/ \___|_| |_|\___|_| |_| |_|\___| \___(_)_/
================ RScheme (release 0.7.3.5) =================
This is the README file for RScheme release 0.7.3.5
What is RScheme?
RScheme is an object-oriented, extended version of the Scheme dialect of Lisp. RScheme is freely redistributable, and offers reasonable performance despite being extraordinarily portable. RScheme can be compiled to C, and the C can then compiled with a normal C compiler to generate machine code. This can be done from a running system, and the resulting object code can be dynamically linked into RScheme as a program executes. By default, however, RScheme compiles to bytecodes which are interpreted by a (runtime) virtual machine. This ensures that compilation is fast and keeps code size down. In general, we recommend using the (default) bytecode code generation system, and only compiling your time-critical code to machine code. This allows a nice adjustment of space/time tradeoffs.
To the casual user, RScheme appears to be an interpreter. You can type RScheme code at a read-eval-print loop, and it executes the code and prints the result. In reality, every expression you type to the read-eval-print-loop is compiled and the resulting code is executed.
Features of RScheme
RScheme has a lot of useful features:
A very liberal license, similar to Tcl's, which allows RScheme to be used in commercial software with little burden on the user except to acknowledge the source. See the COPYING file.
R4RS (Revised**4 Report on Scheme) compliant Scheme. It's the full standard Scheme language, making it useful for writing portable programs, or using programs written for other Scheme dialects. Scheme is a small but powerful language with garbage collection, first-class procedures, list processing features, lexical scope, etc. Various introductory texts on Scheme and Scheme programming are available.
Object system. Everything in RScheme is an object in an object-oriented system. That is, RScheme is "objects all the way down" rather than being a hybrid language like C++ or most Lisp object systems---the built-in R4RS Scheme data types are all classes in the class hierarchy, as they should be. Currently, only a simple object system with single inheritance and single dispatching is supported. Our object system is approximately a subset of TinyCLOS, with some Dylan-like extensions.
Threads. RScheme supports user-level threads portably, even on operating systems that don't have threads at all. RScheme multiplexes several user threads onto one OS-level process. These threads appear to be preemptive from the normal user's point of view. (For example, nonblocking I/O can be used automatically so that one thread doing a read from a network socket doesn't block the whole system; the reading thread will actually issue a nonblocking read request and a thread switch will activate a waiting thread. You don't have to schedule threads "cooperatively" --- just use threads and specify nonblocking i/o. RScheme does the rest.) [note: by default, the system uses stdio for input and output. You will require the facilities of the syscalls package to have a useful threads system that does console or network I/O]
Sockets, globbing, etc. Rscheme has several important features for writing serious programs, especially under UNIX. It is suitable for writing networked servers, for example---that's one of the things it was designed for. RScheme does not currently have as many shell programming features as Olin Shivers'
scsh(the Scheme shell), but we will add more, and we may port full scsh to RScheme.
Separately-compilable and linkable modules. The module system is pretty straightforward and simple, similar to Scheme-48's module system and a subset of Dylan's. It makes development easy by supporting separate compilation and dynamic module linking.
Real-time garbage collection, using Wilson and Johnstone's algorithm. This is a hard real-time garbage collector, in principle, though the default configuration is only soft real time. This is sufficient for most purposes, such as writing interactive applications and network servers---e.g., to avoid spurious network timeouts because a thread is delayed by a GC.
Unlike most language implementations that compile to C, RScheme does NOT use conservative pointer finding in its garbage collector. RScheme's strategy for compiling to C supports precise identification of root pointers, as well as pointers in heap-allocated objects, eliminating potential storage leaks and unreliability due to misidentification of pointers. (We don't want to overstate our case here, however---conservative pointer finding works surprisingly well, and Hans Boehm et al. have done an amazing job on free conservative GC's for use with C, C++, etc. We have avoided dependence on conservative pointer finding because we simply didn't need it, and the supprot for precise pointer identification can be helpful for a variety of other purposes.)
[For more on RTGC, see http://www.cs.utexas.edu/users/oops ]
Persistence, using the strategy described in Wilson and Kakkad's "pointer swizzling at page fault time".
Our persistent object store avoids the need to read and write data to files, for most purposes. Data can simply be saved on disk as a special kind of virtual memory image, and processes can open a persistent store and start traversing its data structures in the usual way---pages of data are faulted into virtual memory as needed, on demand, with performance comparable to normal paging.
The ability to hand-code time-critical routines in C and plug them into applications written mostly in RScheme. Since at the moment we can't claim to have a state-of-the-art compiler that generates awesome code for everything, we allow speed freaks to hand-code important things in C and integrate them into their programs. (We discourage the overuse of this feature! RScheme provides acceptable performance for most programs, and for most parts of most other programs, so if you overdo it, you're just making life harder for yourself.)
Big number support. For this, you need to have the gmp libraries and the header file longlong.h from the gmp sources.
Where to get RScheme
This version of RScheme is being hosted on github, so can the sources can be obtained from:
and a stage1-compiled tarball is generally available from
RScheme is also available as a docker image from
The version used to bootstrap the process is tagged as
so you can run it as:
docker run -i -t donovan/rscheme:0.7.3.4-b7 /usr/local/bin/rs
this version is available tagged as
What's in the Distribution
If you have ftp'd and untar'd the distribution, you probably found this file at the top level. Also at this level are several subdirectories, described below.
README.mdThis file -- the one you're reading.
INSTALLHow to configure, compile, and install RScheme
COPYINGLicense for free use
docThis holds the documentation of the system. Included are a user reference and notes on the design and implementation. We currently include the documentation source is not shipped in the distribution, because the toolchain to build the docs is somewhat involved.
modulesThis is the source for the compiler and various other modules, in RScheme. Most of the subdirectories hold the code for some particular module.
handcThis is miscellaneous handwritten C code, mostly runtime support code such as the GC and the low-level parts of the thread system. This source gets copied into
src/by the top-level build process.
compilerThis contains the "cross" compiler, which is written in the language implemented by RScheme 0.6, but compiles code for 0.7. (this is also the off-line module module, rsc, because it works in 0.7 too)
testThis directory holds regression test files
srcThis is the C code generated automatically from RScheme code. The subdirectories correspond to the subdirectories of
modules/, and hold the C code generated from the RScheme code in those directories, plus copies of the subdirectories of
bytcodesThis contains the definitions of the bytecode operations and hooks for the bytecode compiler to make use of the low-level type system.
packagesThis contains the standard, but optional, packages, such as the persistent store (rstore) and posix interface package (syscalls).
Goals of the RScheme project
We have two major goals for RScheme: building a very useful system, and building a clean and powerful system that can be used to implement a variety of langauge constructs, or even entirely different languages, portably and with good performance.
In more detail, our goals are
To build a useful language that has all of the basic features that any good modern programming language should have, and which provides decent performance without being a big complicated monster. To be useful, it should be extremely portable. Nobody should have to worry that the vendor will go out of business and the software won't be ported to new platforms. Hence, we compile to C. As long as there are C compilers on new platforms, it should be very easy to port RScheme and get good performance. We don't expect C to die in the next few decades -- it's the FORTRAN of the next 30 years.
Compiling to C has its drawbacks. C was not designed to be a compiler intermediate representation for other languages, so it is not the optimal backend. On the other hand, we have found novel strategies for mapping RScheme onto C with surprisingly little degradation of performance. (We don't just use C as a portable assembler, as some people do. For example, in many cases, nested RScheme expressions can be compiled to nested C expressions, and the C compiler will do a good job of register allocation and instruction scheduling.)
GNU C provides several handy extensions, such as the ability to use hardware registers to hold important global variables. RScheme will take advantage of these features if the configure process recognizes an opportunity.
To build a useful framework for research and development in programming language design and implementation. RScheme was originally motivated by our frustration with existing language implementations, which are mostly very limited and very inefficient -- or big, hairy, and nonnportable monsters. Typically, implementors of interesting new languages write whole new compilers for them, because none of the existing compilers are flexible enough and understandable enough to make it worth reusing other people's code. As a result, there are a whole lot of mediocre to bad langauge implementations out there, and that's a shame. People keep using languages like C and C++ because they know there will be decent compilers for them everywhere.
We want to leverage C's momentum, and allow better languages to be easily implemented with reliably good performance on essentially all common platforms.
-- Donovan Kolbly RScheme Development Group email@example.com http://www.rscheme.org/~donovan/