Table of Contents
This project was created as a tool for learning Forth and compilation on the clr. The project is hosted on sourceforge .
Due to implementation limitations, the system does only qualifies as a partial Forth implementation . It does not allow a number of constructs that make Forth what it is (return stack operations).
The IL generation is done with an IL generation lib .
I'm no Forth expert and some of the implementation details and limitations may come from a bad understanding of Forth. I'm no compiler guru so the compiler implementation might suck.
The minimalist approach of Forth makes the implementation of Forth on top of a VM quite stupid. Still, it might a be a tool for learning Forth.
The Fibonnaci number function was used as a benchmark tool. This was chosen as it is a very good fit for the implemented Forth compiler.
The compilation of the fibonacci word generated code that was a few percent (~4%) faster that the C# generated code on my machine. The difference is attributed to the local initialization cost as the forth compiler does not init locals.
In simple functions like simple recursive functions, the generated code should match the C# generated code.
I have used Moving Forth: a series on writing Forth kernels as a help for implementing the system.
A zip file containing the command line executable, the manual and the sources can be donwloaded from sourceforge. No installation program is provided, just unzip.
A minimal console application is provided : MrLoose.Forth.CommandLine.exe. All the arguments on the command line are taken as filenames and their content is evaluated. The interactive evaluation mode is then entered.
Try to use the clr stack as the forth stack.
Build the interpreter with delegate calls.
The return stack cannot be manipulated as the clr does not allow this kind of manipulations.
The clr is not really a stack based vm so a number of Forth stack uses generate poor clr code sequences.
The forth stack is implemented using a clr int array (PS) and an int index (PSP).
The word are implemented in two ways, an implementation that uses PS and PSP and, if possible, and implementation that uses the clr stack.
The interpreter always uses delegates that wraps the implementation using PS/PSP.
The compiler generate code to:
load the required PS elements on the clr stack
execute the word operations operating on the clr stack as the clr stack is the same as PS.
save the clr stack in PS
Words that have return 0 or 1 cell can be implemented using the clr stack if the clr stack matches PS (2 cells might be returned using a long return value but this is not implemented atm). The word is then implemented using a void m(...) or int m(...) method.
Words are compiled as static methods.
We assume that the prolog/epilog of the current word have made the clr stack elements the same as PS.
The word to compile word list calls generation are made as follow:
If the word can be inlined (depending on compiler parameters and the word definition) it is inlined.
If the word can be called using the clr stack, it is the compiled method is call using the call IL opcode.
The word must have the clr stack flushed to PS, the method invoked and the PS reloaded on the stack.