Skip to content

false-schemers/skint

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cheap and fast R7RS Scheme Interpreter

SKINT is a portable interpreter for the R7RS Scheme programming language. It can be built from five C source files (~11K lines of code) with a single command. You don't have to rely on any distributives or packages; just compile the source files with your favorite C compiler, link them with the standard C runtime libraries, and you're done. Standard libraries are built in; ports of more than 100 SRFIs are available as an optional external directory of .sld library files.

Installation

Here's how you can compile SKINT on a Un*x-like system using GCC (* see Windows command line below):

gcc -o skint [skint].c -lm

Some compilers link <math.h> library automatically, some require explicit option like -lm above. It can be built on 32-bit and 64-bit systems.

For much better performance (especially in floating-point calculations) you may pick another compiler, add optimization flags and some SKINT-specific options, e.g.:

clang -o skint -O3 -D NDEBUG -D NAN_BOXING [skint].c -lm

The NAN_BOXING option assumes that the upper 16 bits of heap pointers are zero (48-bit address space). It is recommended to use this option on 64-bit systems that guarantee this (most of them do).

The resulting interpreter has no dependencies (except for C runtime and standard -lm math library) and can be run from any location. If linked statically, it can be easily moved between systems with the same ABI. Note that this interpreter is a complete R7RS-small system in the sense that it does not require any external files to operate (all standard libraries are built in).

In addition to the standard libraries built into the interpreter, SKINT provides external libraries in the distribution’s lib subdirectory. If you perform a manual install, you can copy this directory to any location you choose and tell SKINT where to find it either with command-line options or an environment variable, as described below. Alternatively, you can hard-code the library path into the interpreter by adding -D LIBDIR=lib_path when you compile it.

For a more traditional install, please follow the instructions below. Skint will be installed as /usr/local/bin/skint command, while the optional external library will go into /usr/local/share/skint/ directory (unless you set a different destination via configure as shown below).

git clone https://github.com/false-schemers/skint.git
cd skint
make
make test
sudo make install
# steps below test and install the optional external library
make libtest
sudo make libinstall

If you would like to use the traditional install, but prefer to install SKINT to a place other than /usr/local, you may insert the configure command between cd skint and the first call to make, e.g.

git clone https://github.com/false-schemers/skint.git
cd skint
./configure --prefix=/home/gwendolyn/tools/skint
make
make test
make install
# steps below test and install the optional external library
make libtest
make libinstall

* Similar build command line works on Windows/MSVC:

cl -O2 -DNDEBUG -DNAN_BOXING -Fe"skint.exe" s.c k.c i.c n.c t.c

The misc subdirectory contains the makefile for the NMAKE utility; to use it, please follow the instructions in misc/README.md.

Scheme Compatibility

SKINT is true to basic Scheme principles -- it features a precise garbage collector, supports proper tail recursion, call/cc, dynamic-wind, multiple return values, has a hygienic macro system, and a library system. It is almost fully compatible with R7RS-small, but has the following known limitations and deviations from the standard:

  • fixnums are 30 bit long, flonums are doubles
  • no support for bignums/rational/complex numbers
  • no support for Unicode; strings are 8-bit clean, use system locale
  • source code literals cannot be circular (R7RS allows this)

Some features of the R7RS-Small standard are not yet implemented or implemented in a simplified or non-conforming way:

  • current-jiffy and jiffies-per-second return inexact integers
  • current-second is defined as C difftime(time(0), 0)+37

Here are some details on SKINT's interactive Read-Eval-Print-Loop (REPL) and evaluation/libraries support:

  • read supports R7RS notation for circular structures, but both eval and load reject them
  • all R7RS-small forms are available in the built-in (skint) library and REPL environment
  • -I and -A command-line options extend library search path (-I prepends, -A appends)
  • the initial path is specified via the SKINT_LIBDIRS environment var
  • if it is set, use the directories in the var, replacing the pseudo-directory named ... with the hardwired libdir directory if one is built in via the -D LIBDIR=dir option during compilation
  • if SKINT_LIBDIRS environment var is not set, use the (./ lib/ libdir ) list as the default
  • directories in the path are separated by colon : (semicolon ; on Windows)
  • cond-expand checks against (features) and available libraries
  • environment may dynamically fetch external library definitions from .sld files
  • both eval and load accept optional environment argument
  • command-line options can be shown by running skint --help
  • both import and define-library forms can be entered interactively into REPL
  • REPL supports single-line “comma-commands” — type ,help for a full list
  • on Un*x-like systems, interactive use of skint with line editing requires external readline wrapper such as rlwrap

Please note that SKINT's interaction environment exposes bindings for all R7RS-small procedures and syntax forms directly, so there is no need to use import. All R7RS-small libraries are built-in and do not rely on any external .sld files.

SRFI support

The optional external library in the lib subtree contains SKINT ports of more than 100 SRFIs. Please check the lib/README.md file for details.

Origins

Parts of SKINT's run-time system and startup code are written in #F, a language for building Scheme-like systems. Its #F source code can be found there in precursors directory:

skint/pre

SKINT's hygienic macroexpander is derived from Al Petrofsky's EIOD 1.17 (please see the t.scm file for the original copyright info). SKINT's VM and compiler follow the stack machine approach described in “Three Implementation Models for Scheme” thesis by R. Kent Dybvig (TR87-011, 1987). Supporting library code comes from #F's LibL library.

Family

Please see SIOF repository for a single-file R7RS-small interpreter. It is more portable and easier to build, but is less complete and runs significantly slower.