#S - Scheme for the .NET framework
What is it?
#S (sharp.scheme) is a port of Peter Norvig's Silk written in C# that runs on top of the NET framework. The current version is 0.38. It implements all of r4rs except some limitations. The goal is to provide a simple, portable and embeddable interpreter that expands upon the original, while remaining hackable and small. Additional support for r5rs standard procedures and SRFI libraries is planned, as well as integration with the .NET framework libraries.
Motivation
I've been always interested in programming languages implementation. While writing other simple interpreters, my research led me to a growing interest in multi-paradigm and functional languages like Haskell, Ocaml, Scheme or Lisp. At some point i've decided to try my hand and implement an interpreter for one of them.
Scheme was an obvious choice.
Porting Silk
Silk is a Java implementation of Scheme written by Peter Norvig in 1998 and subsequently adopted by Tim Hickey and Ken Anderson. The latest version from Norvig is 1.4 while the latest full-featured version is not hosted at Sourceforge and dates from 2006.
Porting it to the NET framework offered some great opportunities. First, while there is pretty good implementations of Scheme for Java this is not the case with .NET. As far as i know there is Kawa, Sisc, Sixx, BDC Scheme, SP, PS3I and Mscheme for the Java VM while there is only IronScheme and Common Larceny for the CLR, and while both are really awesome, their source code weight is about 7 MB and 10 MB in size (that's a lot of semicolons!) respectively, so they are not easily embeddable or hackable.
Furthermore porting Silk is a great exercise on learning more about Java and Scheme, (i've used C# before) and it allows me to take an insight in how the program evolution procceeded from the first version to the latest one.
What went right ?
Mostly everything. I've tried to keep things as simple as possible. The rationale is that the interpreter should be easy on you as the user and easy on me as the developer. The full r4rs procedures are working and the interpreter behaves almost exactly as the original. Norvig's code reads like prose. It still fits on 50 KB as Jscheme does. :-)
It took about 25/30 hours to port it. If this seems too long, i'm usually very picky with code readability and how the classes are organized. If it seems too short, i've used some tools wich made my life easier, like refactoring on VS 2008, Vim macros, or Visual J# to debug the original code.
Deviations from the original and design
Changelog as of 0.38a
User visible:
Internal:
I've followed the original code whenever possible. Still, i've made some changes. The big switch statement with the opcodes made me want to shoot myself on the foot so i've changed it to work with function delegates instead. For efficiency the linear lookup of symbols is gone in favor of using HybridDictionaries. This change makes the interpreter a lot faster.
The Primitive class is now abstract and there are three new files, namely: 'ss.r4rs.cs', 'ss.r5rs.ss' and 'ss.rxrs.cs' wich hold the primitives for r4rs, r5rs and extensions respectively. This should make it easy to extend it with new primitives.
The bootstrap proccess works by loading some few scheme primitives at runtime, but most of them are defined in the C# code. Those files are inside the executable so that this is completely transparent by using the embedded resources feature. The final sharp.scheme.exe file weights at about 50 kb. It can also be compiled as a dynamic link library accesible from any other .NET program.
Future roadmap
Carlos Daconcepción archville.mailbox (at) gmail.com