Interprets brainfuck programs.

Examples

iex> {:ok, program} = Bf.parse("--[>--->->->++>-<<<<<-------]>--.>---------.>--..+++.")
iex> Bf.run(program)
"Hello"

Summary

Types

A parsed and optimized brainfuck program.

Functions

Parses and optimizes a brainfuck program from a string.

Parses and optimizes a brainfuck program from a string, raising on error.

Runs a brainfuck program with the given input and returns its output.

Runs a brainfuck program, streaming its input and output.

Types

program()

@opaque program()

A parsed and optimized brainfuck program.

Its structure is internal and may change in any release. Create programs with parse/1 and run them with run/1.

Functions

parse(source)

@spec parse(String.t()) :: {:ok, program()} | {:error, Bf.ParseError.t()}

Parses and optimizes a brainfuck program from a string.

Returns a Bf.ParseError if the program's brackets don't match.

Examples

iex> {:ok, _program} = Bf.parse("+++++++++[>++++++++<-]>.")

iex> Bf.parse("+[")
{:error, %Bf.ParseError{reason: :unmatched_open, line: 1, column: 2}}

parse!(source)

@spec parse!(String.t()) :: program()

Parses and optimizes a brainfuck program from a string, raising on error.

Examples

iex> Bf.parse!("+[")
** (Bf.ParseError) unmatched [ at line 1, column 2

run(program, input \\ "")

@spec run(program(), binary()) :: binary()

Runs a brainfuck program with the given input and returns its output.

Input and output are bytes. Reading at the end of the input sets the current cell to 0. See run/3 to stream input and output.

Examples

iex> {:ok, program} = Bf.parse(",[.,]")
iex> Bf.run(program, "hello")
"hello"

run(program, input, output)

@spec run(program(), Enumerable.t(), Collectable.t()) :: term()

Runs a brainfuck program, streaming its input and output.

input is an enumerable of binaries. It is only consumed as far as the program reads, one byte per ,. Each byte the program writes is put into the output collectable right away. Returns the collectable's result.

Reading at the end of the input sets the current cell to 0.

Examples

iex> {:ok, program} = Bf.parse(",[.,]")
iex> Bf.run(program, ["he", "llo"], "")
"hello"

To stream stdin and stdout, with stdio in latin1 mode so bytes pass through unchanged:

Bf.run(program, IO.binstream(:stdio, 1), IO.binstream(:stdio, 1))