Brainlite

Compiler

This document describes how the brainlite compiler (brainuf) works internally.

The compiler takes brainlite source code and transpiles it into brainfuck. It does not execute anything.

Startup

The brainlite class is instantiated and initialized with:

Lexing

lexCode() is called once per line. It:

  1. Skips empty lines.
  2. Skips lines starting with # (comments).
  3. Checks if the line ends with ? — if so, skipIfError is set to true for that line, suppressing errors.
  4. Walks the line character by character, collecting characters into a string called token until a space, semicolon, or newline is hit.
  5. Validates the collected token against validTokens.
  6. If valid, dispatches the corresponding function via exec_func().
  7. argsCollectedLength is returned by keyword handlers to tell the lexer how many characters were consumed as arguments, so the lexer skips past them.

Output

The compiler accumulates brainfuck output into compiled_code, a std::vector<std::string>. Each keyword handler appends one or more brainfuck strings to this vector.

getCode() returns this vector to the caller.

Keywords and What They Emit

set <value>

Sets the current memory cell to a specific value (0–255). Emits a string of + characters equal to the value.

The value is passed through ringBuffer() to clamp it into the 0–255 range.

Does not move the memory pointer.

front / right

Aliases for the same operation. Emits > and increments memory_pointer.

back / left

Aliases for the same operation. Emits < and decrements memory_pointer.

inc

Emits a single +.

dec

Emits a single -.

inctill <limit>

Reads the current logical value of the cell (by scanning compiled_code backwards until a pointer movement is found), then emits enough + characters to reach the limit from the current value.

dectill <limit>

Same as inctill but decrements. Emits - characters from the current value down to the limit.

move <n>

Moves the memory pointer by N cells. Emits N > or < characters depending on direction.

move 0 resets the pointer to cell 0 by emitting as many < as needed.

move -N moves backwards N cells.

Accepts a quoted string. For each character in the string:

  1. Internally calls set() with the ASCII value of the character.
  2. Emits .> to print the character and advance the pointer.

Supports escape sequences: \n, \t, \\.

Double quotes are required. Single quotes do not work.

input <n>

Emits N , characters, collecting N characters of input from stdin into sequential memory cells.

loop <n>

Sets the current cell to N (using set() internally), marks isLooping = true, and records memory_pointer as the loop base address.

The body of the loop is lexed normally by the outer loop in the caller. The end keyword closes it.

end

Closes the most recently opened loop. Emits pointer movements back to the loop’s base address, then emits -] to form the brainfuck loop close.

If end is encountered with no active loop, it exits with an error.

whatis "query"

A debug keyword. Accepts "memorypointer" as the only valid query. Emits brainfuck that sets the current cell to the compile-time value of memory_pointer and prints it.

Known bug: The brainfuck . instruction outputs ASCII, not the raw integer. So if the memory pointer is at address 65, it prints A, not 65.

out

Emits a single .. Prints whatever ASCII character is currently in the active memory cell.

Error Handling

On any error, the compiler prints a message with the offending line and exits. If the line ends with ?, errors are suppressed (skipIfError = true) and the instruction is silently skipped instead.

Error codes used:

End of Document

That covers the compiler’s internal behavior. It makes no attempt at optimization. The output brainfuck is correct but naive.