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 by
- 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
Prerequisites (versions are tested by the author)
- 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
$ 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
Low-Level Programming / Forthress
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.
Series of posts on the evolution of TransForth
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.