This project provides a Brainfuck implementation on the JVM. It leverages GraalVM and Truffle.
About Brainfuck
Brainfuck is a Turing-complete language with a rather bizarre syntax. It consists of only eight simple commands, and one instruction pointer. Its main purpose is to challenge and amuse programmers.
About GraalVM
From the website:
GraalVM is a universal virtual machine for running applications written in JavaScript, Python, Ruby, R, JVM-based languages like Java, Scala, Kotlin, Clojure, and LLVM-based languages such as C and C++.
GraalVM removes the isolation between programming languages and enables interoperability in a shared runtime. It can run either standalone or in the context of OpenJDK, Node.js, Oracle Database, or MySQL.
About Truffle
From the website:
Truffle is an Open Source library for building programming language implementations as interpreters for self-modifying Abstract Syntax Trees. Together with the Open Source Graal compiler, Truffle represents a significant step forward in programming language implementation technology in the current era of dynamic languages.
Although a Brainfuck program isn't very likely to modify its Abstract Syntax Tree, it seems that there is currently no other way to make language run inside GraalVM.
To build or use this project, you need GraalVM. You can obtain it at the GraalVM website. Note that currently there are only distributions for Linux and MacOS.
Make sure to set your JAVA_HOME
environment variable to point to the GraalVM installation!
# Or wherever GraalVM is installed...
# this is a typical MacOS installation path.
export JAVA_HOME="/Library/Java/JavaVirtualMachines/graalvm-ce-java8-21.0.0.2/Contents/Home"
mvn verify
First, you need to install the component into your GraalVM installation:
# Make sure to set JAVA_HOME to your GraalVM installation first!
mvn package
${JAVA_HOME}/bin/gu install -L component/target/brainfuck-component.jar
The integration test suite (in SamplesIT.java
) gives a good idea of how to run Brainfuck programs inside the JVM.
The general pattern is as follows:
final Source source = Source.newBuilder(BrainfuckLanguage.ID, input, null)
.cached(false)
.buildLiteral();
try (final Engine engine = Engine.newBuilder().build();
final Context context = Context.newBuilder().engine(engine).build()) {
context.eval(source);
}
It can be hard to verify whether the AST that was generated is correct.
To visualise the AST, run your program with -Dbrainfuck.ast.dump=true
.
It will generate a file called output.dot
.
You can convert that to an PNG-image using Graphviz: dot -Tpng output.dot -ooutput.png
.
This project has a few modules:
- language - this module contains the actual language implementation.
- launcher - this module contains a simple command line Brainfuck launcher.
- native - this module builds a native executable for the launcher.
The following resources have been very useful while developing this project.
This project is licensed under the MIT license.
See ./LICENSE
for details.