This section gives some technical informations about QScheme.
A classical Scheme interpreter works in a loop, the famous REPL, which stands for ``Read, Eval, Print Loop''. My Scheme largely conforms to this. In order to achieve speed and flexibility, the REPL has been slightly changed.
The simple eval procedure has been split in 4 parts, namely compile optimize assemble execute.
The compile phase transforms the list given by the read procedure into an intermediate code (icode) representation. This code is stored in a standard array and can be manipulated with the standard Scheme procedures.The icode is describe hereafter.
The optimizer transforms the icode generated by the compiler, mainly to implement tail recursion.
The assembler transforms the icode to a code which can be executed by the virtual machine. The vmcode is an internal code. It cannot be changed from the Scheme interpreter. It only can be printed for debugging purpose, see the disasm function.
With this design, the compiler and the optimizer can be written in Scheme itself.
The compiler takes a list as input and generates an icode array. The input list is typically delivered by the read function.
When the compiler encounters a symbol which is bound to a macro, the macro code is evaluated and the result of this evaluation replaces the original form.
After compilation, the icode array contains assembly instructions. See table 2.
|
The optimizer transforms the icode. The main optimizations are:
The assembler transforms the intermediate code to real virtual machine code. During this transformation, the ``nop'' icodes generated during optimization are ignored and the labels are mapped to actual addresses.
The compiler/assembler is implemented in the asm.c source file. There you can find the complete list of opcodes.
The execute and read functions are located in the s.c file. I'm not totally happy with this and may move these functions elsewhere.