I started to write QScheme because I wanted to write a midi sequencer for Linux. I had already written a sequencer about ten years ago, for the popular Atari ST, based upon an optimizing subroutine-threaded Forth. My idea was to use an embedded language in the sequencer, in which I could code most of the GUI and which could offer the user access to all the functions of the sequencer.
SIOD was the first embedded language I looked at. SIOD has good interfacing capabilities with the C language. This looked promising. I also decided to use the Tk toolkit for the GUI. Nice base to start with. I began to code a prototype which worked more or less satisfactorily. The main problem I faced was that SIOD seemed far too slow. It didn't seem feasible to let the user write MIDI sample handling functions in or with SIOD. And even less possible to code the entire GUI using SIOD - it would also have been too slow.
So I looked at the other Scheme implementations available, with emphasis on speed and easy interfacing. I considered SCM, Bigloo, Gambit, STk, Rscheme, Sick and many others. Some were fast but difficult to embed, some were slow but easy to interface, others were just compilers and I did not want to waste time with compilations. After a good deal of searching I had not found a fast and embeddable Scheme. That's why I finally decided to write one.
So, from the outset my goal was to have a fast Scheme, with good C interfacing and painless embedding facilities. My Scheme has these features and I'm proud of it. Now, it's not yet perfect, but it is good enough for my projects.
I should emphasize: QScheme is a really fast intepreter. My current benchmarks (** Table missing **) show it is 2 to 10 times faster than other Scheme interpreters1, and just a little slower than Bigloo, which compiles to C. On most of the benchmarks, QScheme beats Perl and other scripting languages by a factor of 2 and is also faster than Java, without compilation. Yes - it's good enough for me.
QScheme comes with support for modules, dynamic libraries, foreign function calls and foreign variable sharing.
It should be easy to add new types. In fact the string type is already written as a pure extension. New types not only specify how to handle objects but also how to recognize them during parsing (read).
It also should be easy to add new syntactic constructs, because the syntax is table driven. As a general design rule, I used tables as often as possible. This should lead to better flexibility.
Unfortunately the world is bad and QScheme is not perfect. One important limitation being that
QScheme is mostly R5RS compliant, but not all required features are currently implemented. Other possibly significant deviations from the R5RS specs include :
The only way I found to speed up the execution of Scheme code is to compile Scheme expressions to instructions for a virtual machine. The challenge was to create a virtual machine which would be really fast at interpreting code. I chose a Forth-like engine, because I wrote Forth interpreters before and because GCC provides nice features to implement this kind of engine in a very efficient way.
QScheme is fast because it compiles input to a pseudo code and lets the virtual machine execute it. The virtual machine is a stack based engine. It is fast, because it's hopefully well designed and because it builds on specific GCC features (computed gotos) that allow to create a fast interpreter.
One drawback of this design is that the code generated for the virtual machine pseudo code is relatively large compared to other pseudo-codes. This being a case of trading space for speed I think it's acceptable anyway.
The Revised5 Report on the Algorithmic Language Scheme (R5RS) document can be found online at:
http://www-swiss.ai.mit.edu/jaffer/Scheme.html
You may also find many interesting article on Scheme at the Scheme repository:
http://www.cs.indiana.edu/scheme-repository/
Another interesting resource is Schemers.org which can be found at:
http://www.schemers.org/