Experimental Forth implementation in LLVM.
Introduction blog post is here: https://medium.com/@riywo/llforth-experimental-implementation-of-forth-in-llvm-2298c76ec3ac
This software is built for a personal research to understand computer architecture. Implementing stack-based programming language(Forth) using a register-based virtual machine (LLVM) is useful to know both machine/language architecture.
LLForth uses following technique:
- Restricted static compiler (
llforthc
) from Forth to LLVM Intermediate Representation (LLVM IR) and Full feature interpreter (llforth
) written in Forth and compiled byllforthc
- Indirect Threaded Code (ITC) to implement inner interpreter by LLVM IR
- Naive memory implementation for Stack and Return Stack by LLVM IR
- Partial memory cell for only word definitions excluding string of name of words
- Foreign Function Interface to delegate platform dependent features (e.g. stdio) to Rust and share it between compiler and interpreter
- CMake (3.13.2)
- LLVM (7.0.0)
- lit (from PyPI or under LLVM source code)
- Rust (1.31.1)
All required steps are declared in CMakeLists.txt
including compiling Rust library, so you just need to execute CMake build:
$ mkdir cmake-build-debug
$ cd cmake-build-debug
# If you install LLVM outside default path like Homebrew:
# export LLVM_DIR=/usr/local/opt/llvm/lib/cmake
$ cmake ..
$ make llforth
llforth
is statically linked with required libraries except libc
:
$ otool -L ./llforth
./llforth:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
Therefore, you can execute it easily:
$ ./llforth --help
llforth 0.1
USAGE:
llforth [FILE]
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
ARGS:
<FILE> Source file
llforth
can read from both stdin and source file. For example, you can run it interectively powered by Rustyline which is Readline like library:
$ ./llforth
> 1 1 + .
2
> : hi ." Hello world!" ;
> hi
Hello world!
Also, you can input via stdin non-interectively:
$ echo '1 2 + .' | ./llforth
3
Finally, you can read a source file on your file system:
$ echo '1 2 + .' > /tmp/test.fs && ./llforth /tmp/test.fs
3
See https://github.com/riywo/llforth/wiki/Supported-words
See https://github.com/riywo/llforth/wiki/Architecture
This project is heavily inspired from a book "Low-Level Programming" which has a great section for implementing Forth using x86_64 assembly only. The code base is also available from the author's repository called Forthress under MIT License. Most of architectures of LLForth are borrowed from Forthless, for example ITC, Memory cell, etc.
On top of the assembly implementation mirrored from Forthress, I implemented some forth words by forth, for example if ... else ... then
or begin ... until
. Those words are borrowed from "Series of posts on the evolution of TransForth" which are awesome read to understand Forth architecture. The code base is also available on TransForth under MIT License.