Skip to content

redraiment/brainfuck

Folders and files

NameName
Last commit message
Last commit date

Latest commit

66eb183 · Apr 23, 2023
Apr 23, 2023
Apr 23, 2023
Apr 23, 2023
Apr 23, 2023
Apr 23, 2023
Aug 9, 2022
Apr 23, 2023

Repository files navigation

Brainfuck Interpreters and Compilers

License: GPL v3

This is my learning project to practice building compiler and interpreter with LLVM C API.

The project is too complext for someone, who just want to implement a simple interpreter for Brainfuck. This snippet is a better alternative, which implements the interpreter with one C file only.

About the Project

There are so many LLVM tutorials in C++, however, I'd like to build a compiler and interpreter with LLVM in C. Therefore, I created this project to build a compiler and JIT interpreter for Brainfuck. Brainfuck language is simple enough, and it designed for implementing the smallest possible compiler.

Roadmap

  • Generating Makefile with GNU Autoconf.
  • Generating Makefile with CMake.
  • Building project with GNU Make.
  • Parsing Command line options with getopt.
  • Lexical analysis with flex.
  • Syntax analysis with bison.
  • Creating LLVM IR file with LLVM C API.
  • Creating native object file with LLVM C API.
  • Creating executable file with linker.
  • Running script file with LLVM MCJIT.
  • Deploying with docker.
  • Linking with lld.
  • Static linking with musl.
  • Embedding C runtime library.

Getting Started

The program can only working on Linux for now.

Download pre-build binary file (Recommended)

wget https://github.com/redraiment/brainfuck/releases/download/v0.5.0/brainfuck-0.5.0-x86_64.gz
gunzip brainfuck-0.5.0.x86_64.gz
sudo mv brainfuck-0.5.0.x86_64 /usr/local/bin/brainfuck
brainfuck -v

You can see below version information if the above command run success.

brainfuck v0.5.0

Home page: <https://github.com/redraiment/brainfuck/>.
E-mail bug reports to: <[email protected]>.

Example for creating executable file and run it then:

brainfuck hello-world.bf
./hello-world

You can find the hello-world.bf in test folder.

Install with Source Code

An example on Ubuntu:

sudo apt install --no-install-recommends -y flex bison clang-15 lld-15 liblld-15-dev llvm-15 llvm-15-dev llvm-15-tools zlib1g-dev libtinfo-dev binutils-dev musl-dev xxd make cmake
git clone --depth=1 https://github.com/redraiment/brainfuck.git
cd brainfuck
cmake 'Unix Makefiles' -B build .
cmake --build build

Usage

brainfuck [OPTIONS] <source-file>

It will create an executable file default.

Options

  • -c/--compile: only run preprocess, compile and assemble steps, then emit native object (.o) to output file. By default, the object file name for a source file is made by replacing the extension with .o.
  • -r/--representation: emit LLVM representation (.ll) to standard output.
  • -s/--script: run source file as Brainfuck script.
  • -m/--enable-single-line-comment: enable single line comment command #. It's useful used with Shebang.
  • -o/--output <output-file>: write output to file. This applies to whatever sort of output is being produced, whether it be an executable file, an object file, an IR file. If -o is not specified, the default executable file name for a source file is made by removing the extension.
  • -h/--help: show this help and exit.
  • -v/--version: show version and exit.

Examples

  1. Creating an executable file: brainfuck helloworld.bf
  2. Running a file as scripting: brainfuck -s helloworld.bf
  3. Using with Shebang: #!/usr/local/bin/brainfuck -ms
  4. Creating native object file: brainfuck -c helloworld.bf
  5. Creating LLVM representation file: brainfuck -p helloworld.bf

Language Specification

Here are some key behaviors:

  • Memory size: 30,000 bytes, and initialized to zero.
  • Data pointer initialized to point to the leftmost byte of the array.
  • Two streams of bytes for input and output.
  • End-of-file behavior: setting the cell to 0.
  • Use "\n" for end-of-line.

Commands

Character Meaning
> Increment the data pointer (to point to the next cell to the right).
< Decrement the data pointer (to point to the next cell to the left).
+ Increment (increase by one) the byte at the data pointer.
- Decrement (decrease by one) the byte at the data pointer.
. Output the byte at the data pointer.
, Accept one byte of input, storing its value in the byte at the data pointer.
[ If the byte at the data pointer is zero, then instead of moving the instruction pointer forward to the next command, jump it forward to the command after the matching ] command.
] If the byte at the data pointer is nonzero, then instead of moving the instruction pointer forward to the next command, jump it back to the command after the matching [ command.
# Single line comment. Disabled default.
others Comments

HINT: Single line comment command (#) is an extra command to ignore the text until end-of-line. It was added to avoid command of shebang conflict with Brainfuck commands. For example, there is - in #!/bin/brainfuck -s, which is backward command of Brainfuck.

Snippets

Here some Brainfuck snippets for testing.

Hello World

From Wikipedia. It will write "Hello world" to standard output.

++++++++++
[>+++++++>++++++++++>+++>+<<<<-]
>++.>+.+++++++..+++.>++.<<+++++++++++++++.
>.+++.------.--------.>+.>.

cat

It will read data from standard input and write to standard output directly, until end of file.

,[.,]

wc

from brainfuck.org. the standard (line and) word (and character) count utility.

>>>+>>>>>+>>+>>+[<<],[
    -[-[-[-[-[-[-[-[<+>-[>+<-[>-<-[-[-[<++[<++++++>-]<
        [>>[-<]<[>]<-]>>[<+>-[<->[-]]]]]]]]]]]]]]]]
    <[-<<[-]+>]<<[>>>>>>+<<<<<<-]>[>]>>>>>>>+>[
        <+[
            >+++++++++<-[>-<-]++>[<+++++++>-[<->-]+[+>>>>>>]]
            <[>+<-]>[>>>>>++>[-]]+<
        ]>[-<<<<<<]>>>>
    ],
]+<++>>>[[+++++>>>>>>]<+>+[[<++++++++>-]<.<<<<<]>>>>>>>>]

Contributing

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

Distrubuted under the GPLv3 License. See LICENSE for more information.

Contact

Acknowledgments