Skip to content

redraiment/brainfuck

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

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: <redraiment@gmail.com>.

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