CHICKEN (Scheme implementation)
|Original author(s)||Felix Winkelmann|
|Developer(s)||The CHICKEN Team|
|Initial release||July 20, 2000|
4.13.0 / December 11, 2017
|Written in||Scheme and C|
|Standard(s)||R5RS (mostly), R7RS (not in core)|
CHICKEN is a compiler and interpreter for the Scheme programming language that compiles Scheme code to standard C. It is mostly R5RS compliant and offers many extensions to the standard. The newer R7RS standard is supported through an extension library. CHICKEN is free software available under the BSD license. It is implemented mostly in Scheme, with some parts in C for performance or to make embedding into C programs easier.
CHICKEN's focus is immediately clear from its tagline: "A practical and portable Scheme system".
CHICKEN's main focus is the practical application of Scheme for writing "real-world" software. Scheme is well known for its use in computer science curricula and programming language experimentation, but it has not seen much use in business and industry. CHICKEN's community has produced a large set of libraries for performing a variety of tasks. The CHICKEN wiki (the software running it is also a CHICKEN program) also contains a list of software that people have written in CHICKEN.
CHICKEN's other goal is to be portable. By compiling to portable C (like Gambit and Bigloo), programs written in CHICKEN can be compiled for common popular platforms like Linux, Mac OS X and other Unix-like systems as well as Windows, Haiku and the mobile platforms iOS and Android. It also has built-in support for cross-compilation of programs and extensions, which allows it to be used on various embedded platforms.
Like many Scheme compilers, CHICKEN uses standard C as an intermediate language. A Scheme program is translated into C by the CHICKEN compiler, and then a C compiler translates the C program into machine code for the target architecture, producing an executable program. The universal availability of C makes it ideal for this purpose.
CHICKEN's design was inspired by a 1994 paper by Henry Baker that outlined an innovative strategy for Scheme compilation into C. A Scheme program is compiled into C functions. These C functions never reach the return statement; instead, they call a new continuation when complete. These continuations are C functions themselves and are passed on as extra arguments to other C functions. They are calculated by the compiler.
So far, this is the essence of continuation-passing style. Baker's novel idea is to use the C stack for the Scheme heap. Hence, normal C stack operations such as automatic variable creation, variable-sized array allocation, and so on can be used. When the stack fills up (that is, the stack pointer reaches the top of the stack), a garbage collection can be initiated. The design used is a copying garbage collector originally devised by C. J. Cheney, which copies all live continuations and other live objects to the heap. Despite this, the C code does not copy C stack frames, only Scheme objects, so it does not require knowledge of the C implementation.
In full, the Scheme heap consists of the C stack as the nursery together with the two heaps required by the generational garbage collector. This approach gives the speed of the C stack for many operations, and it allows the use of continuations as simple calls to C functions. Further, Baker's solution guarantees asymptotic tail recursive behavior, as required by the Scheme language standard. The implementation in the CHICKEN Scheme compiler is even asymptotically safe for space.
Limitations and deviations from the standard
CHICKEN Scheme is mostly R5RS-compliant, with a few notable limitations and deviations.
There is no support for the full numeric tower in the core system. However, an extension library exists which adds support for the full numeric tower. The next major version will remove this limitation.
The core system has basic support for UTF-8 characters, however the string indexing and manipulation procedures are not UTF-8 aware. Here again there is an extension library which adds support for full UTF-8 awareness.
Initially, these eggs were developed in one central svn repository, in which creating a tag would automatically cause a new version of the extension to become available for download. Currently, eggs can be developed anywhere and under any version control system, while still maintaining "semi-automatic" release management when using most of the popular code hosting sites. This release method is VCS-agnostic in the sense that the user does not need to have these VCSes installed. The developer is free to host anywhere he or she likes, and could even choose to avoid public version control altogether and distribute only plain tarballs.
For all released eggs, the latest version is tested automatically as part of a continuous integration process. Anyone can volunteer to supply additional testing capacity (on different hardware, or different operating systems or on different core releases), but there's also a canonical test server where the core system and all eggs will be tested daily against the most recent development version (to catch regressive bugs) as well as the most recent stable version (to ensure that everything works for users of the stable system).
CHICKEN supports most of R5RS standard Scheme, but it also adds a few nonstandard features which are not available in all Scheme implementations.
Foreign function interface
The fact that CHICKEN compiles to C makes it possible to "inject" custom C code into the compiled result, which eases integration with C libraries. Its foreign function interface supports converting back and forth between most built-in C types and corresponding Scheme objects.
It is relatively easy to cross-compile Scheme code to another platform (for example for embedded use on a device).
In order to make cross-compilation possible for Scheme code, CHICKEN imposes a model of separate compilation: A compiled module consists of two shared libraries. One library contains the actual code which will be used at runtime (compiled for the target platform), and the other is an "import module", which will be used to load the code which runs at compile-time (on the host platform), such as procedural macro code.
The CHICKEN compiler itself can also be easily cross-compiled; after translation to C has been achieved, one can simply use a C compiler which is set up to build for another platform.
Modules and macros
Since version 4, CHICKEN has a built-in module system and support for low-level hygienic macros through explicit renaming (prior to CHICKEN 4 this was available through an add-on library). Standard syntax-rules macros are also supported, as well as implicit renaming macros, which is basically a "reversed" version of explicit renaming.
This mechanism trades in performance for convenience. Each identifier not explicitly "injected" as unhygienic will be automatically renamed to avoid name capture. The performance cost lies in the fact that this "implicit" renaming requires the macro-expander to traverse the expressions an additional two times. This cost is paid at expansion time, so a macro author must consider whether longer compilation times are acceptable.
Since version 4.11, CHICKEN comes shipped with a debugger called "Feathers". When Scheme code is compiled with the necessary debugging option, "debugging events" are injected at specific points in the code. These are implemented as calls to a C function, which is relatively low-overhead when not actually debugging the code. When debugging, it will try to make a TCP connection to a Feathers server process, possibly on a different machine. The process is halted, the user may set breakpoints and start the program. Then, when the breakpoint is hit, the client (process being debugged) enters a command loop, which allows interrogation of the client, to read out variables, or mutate them.
Limited static type analysis
CHICKEN also has support for local flow analysis. This allows the compiler to catch variable type errors at compile-time, and perform type specialisation. This specialisation makes it possible to remove several safety checks for type detection at runtime when the type can be deduced at compile-time. This results in improved run-time performance.
This "scrutinizer" does not allow cross-module flow analysis, so it can only be used to optimize code that's part of one compilation unit (or module).
- Winkelmann, Felix "Announcing the CHICKEN Scheme-to-C compiler"., comp.lang.scheme
- "Scheme FAQ"., section "what is Scheme used for?"
- "Portability". page on the CHICKEN wiki
- "Cross development". - a section from the CHICKEN manual
- Baker, Henry "CONS Should Not CONS Its Arguments, Part II: Cheney on the M.T.A.".
- Cheney, C.J. "A Nonrecursive List Compacting Algorithm". CACM 13,11 (Nov. 1970), 677-678.
- The CHICKEN Team, "Deviations from the standard"., the CHICKEN manual
- The CHICKEN Team, "CHICKEN 5 roadmap".
- Bex, Peter "VCS-independent distribution of language extensions"., blogpost on More magic
- The CHICKEN wiki, "Instructions for popular code hosting methods and VCSes".