Copied to clipboard!
RedBunny .redb v0.1.0
Made with love by mohamedboukerche22

RedBunny (.redb) Programming Language

RedBunny is a small, fast, compiled programming language with dynamic-feeling variables, a compact function syntax, and an LLVM IR backend. The compiler is written in C and lowers source code into LLVM IR before invoking clang to emit native machine binaries.

LLVM IR Backend

Direct compilation to LLVM intermediate representation linked with native C runtime.

Compact Grammar

Clean syntax with single parameter indices (arg1, arg2) and format string interpolation.

Zero-Dep C Engine

Compiler codebase written in clean C with custom hand-written lexer and recursive descent parser.

1. Installation

One command downloads RedBunny, builds the compiler, installs it, and runs the hello-world example.

Linux / macOS

Bash
curl -fsSL https://raw.githubusercontent.com/Mohamedboukerche22/redbunny/main/scripts/get.sh | bash

Installs to ~/.local. Prefix it with PREFIX=/some/path to install elsewhere. Requires curl or wget, tar, and a C toolchain; the installer installs LLVM, CMake and build tools on common distributions.

Windows

PowerShell
irm https://raw.githubusercontent.com/Mohamedboukerche22/redbunny/main/scripts/get.ps1 | iex

Installs to %LOCALAPPDATA%\RedBunny. Set $env:PREFIX before running to install elsewhere. Requires PowerShell 5+; the installer installs LLVM, CMake and Ninja through Chocolatey.

From a source checkout

Clone the repository, then run the platform installer.

Linux / macOS

Bash
chmod +x scripts/install.sh
./scripts/install.sh

The installer uses CMake to build and copies redb to /usr/local/bin/redb and libredb_runtime.a to /usr/local/lib/. You can override the path via PREFIX=$HOME/.local ./scripts/install.sh.

Windows

PowerShell
Set-ExecutionPolicy Bypass -Scope Process -Force
.\scripts\install.ps1

Manual CMake Build

CMake
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
sudo cmake --install build

Vim/Neovim: syntax highlighting, .redb filetype detection, comments and indentation are in editors/vim. See editors/vim/README.md for package, runtimepath and lazy.nvim setup.

2. Hello World

Save the following program in a file named hello.redb:

hello.redb
@include "std"

main() {
    writeln("Hello, World!");
}

Compile and run with the redb executable:

redb hello.redb -o hello && ./hello

3. Comments & Semicolons

RedBunny uses distinct comment token markers. Semicolons are optional across all statements.

comments.redb
-- Single-line comments start with two dashes

-*
   Multi-line block comments
   are enclosed between -* and *-
*-

main() {
    a = 1;    -- Semicolons are allowed
    b = 2     -- Semicolons can be omitted
    writeln(a + b)
}

4. Program Structure

Every executable program must define exactly one main() block. Top-level scope is strictly restricted to:

  • @include "..." declarations
  • main() { ... } entry point
  • Function assignments like name = do(...) { ... }
Exit Code Rule: main() returns an integer exit code to the operating system. A bare return exits with 0, while return 42 exits with code 42.

5. Variables and Types

Variables are introduced by assignment. The first assignment fixes the static LLVM IR type:

types.redb
main() {
    name = "Mohamed"      -- str
    age = 20             -- int (signed 64-bit)
    pi = 3.14159         -- double (64-bit IEEE)
    alive = true         -- bool

    writeformat("Name: {name}, Age: {age}, pi: {pi}, alive: {alive}\n")
}

Type Reference Table

Type LLVM / Memory Equivalent Description
int i64 Signed 64-bit integer
float float 32-bit IEEE floating point
double double 64-bit IEEE floating point (default for decimals)
str i8* Null-terminated UTF-8 byte string
bool i1 Boolean literal (true / false)
void void Written as {} in function signatures

Arrays

An array holds many values of one element type. Declare one with array<T>, where T is int, float, double, str, auto, or another array type.

arrays.redb
main() {
    array<int> nums(5)          -- 5 elements, all 0
    nums[0] = 10
    nums[4] = 40
    writeln(nums[0] + nums[4])  -- 50
    writeln(nums.size())        -- 5

    nums.resize(7)              -- grow to 7; new elements are 0
    writeln(nums.size())        -- 7

    array<auto> alias = nums    -- element type copied from nums (int)
    alias[1] = 3
    writeln(nums[1])            -- 3: alias and nums are the same array

    array<array<int>> matrix(2) -- two inner arrays, each starts empty
    array<int> row(3)
    row[2] = 9
    matrix[1] = row
    writeln(matrix[1][2])       -- 9
}

Array forms

Form Meaning
array<int> a(5)5 elements, all 0 (0.0 for double, empty for str)
array<int> aEmpty array (size 0)
array<int> a = ba refers to the same array as b
array<auto> a = ba takes the element type of b
array<auto> a(5)No initializer, so the element type defaults to int
a[i], a[i] = xRead or write element i (indexes start at 0)
a.size()Number of elements
a.resize(n)Change the size; new elements are zero or empty
array<array<int>> m(3)Nested arrays; m[0][1] = 7 works

Arrays can be passed to and returned from functions:

total = do(array<int> -> int) {
    return arg1[0] + arg1[1]
}
  • An index outside 0 to size() - 1 stops the program with a runtime error.
  • Assigning one array to another does not copy it; both names share the elements.
  • Inner arrays created by array<array<T>> m(n) start empty. Call resize() on them before indexing.
  • A whole array cannot be printed with write or writeln. Print one element at a time.
  • array and auto are reserved words.

6. Operators

Arithmetic and comparison operators supported by RedBunny backend:

operators.redb
-- String concatenation uses +
full = "Red" + "Bunny"

-- Numerical arithmetic
x = (10 + 2 * 5) / 4

-- Comparison & Logical operators
is_valid = (x >= 3) && !false

7. Output Functions

RedBunny runtime provides 3 primary formatted output primitives:

  • write(val): Prints without a trailing newline.
  • writeln(val): Prints value followed by a newline.
  • writeformat("..."): Variable interpolation inside template strings. Use {{ and }} for literal braces.
format.redb
main() {
    item = "Laptop"
    price = 999.99
    writeformat("Item: {item} | Price: ${price}\n")
    writeformat("Literal brace demo: {{item}}\n")
}

8. Control Flow

If / Else Statements

if (score >= 90) {
    writeln("A")
} else if (score >= 80) {
    writeln("B")
} else {
    writeln("C")
}

Inclusive Range For Loop

The range loop for(i in start to end) is inclusive on both ends:

-- Runs 10 times from 0 through 9
for(i in 0 to 9) {
    writeln(i)
}

Descending Range For Loop

Use downTo to count downward. Both ends are inclusive:

-- Runs 5 times: 5, 4, 3, 2, 1
for(i in 5 downTo 1) {
    writeln(i)
}

While Loop, Break & Continue

n = 0
while (n < 10) {
    n = n + 1
    if (n == 2) { continue }
    if (n == 6) { break }
    write(n)
}

9. Functions & Signatures

RedBunny uses a unique signature format for defining functional variables. Parameters are bound to positional names arg1, arg2, etc.

functions.redb
-- Takes two ints, returns int
add = do(int, int -> int) {
    return arg1 + arg2
}

-- Function taking no args returning int (=> is an alias for ->)
get_answer = doto({} => int) {
    return 42
}

-- Recursion: Functions are hoisted before main
fact = do(int -> int) {
    if (arg1 <= 1) { return 1 }
    return arg1 * fact(arg1 - 1)
}

main() {
    writeln(add(10, 20))
    writeln(fact(5))   -- Output: 120
}

10. Includes (@include)

Include standard or user module source files. Includes resolve relative to the source file first, then the standard library directory (lib/ in a checkout or share/redb/lib when installed). Set REDB_STDLIB to override. The suffix .redb is optional.

@include "std"
@include "mathlib"

main() {
    writeln(square(9))
}

11. Interactive Playground & LLVM IR Visualizer

Test RedBunny syntax, simulate program execution, or view generated LLVM IR code directly in your browser:

sandbox.redb
Terminal Console Output Compiler Status: Ready
Click "Run Code" or "Emit LLVM IR" above to compile...

12. Command Line Interface

Usage: redb <file.redb> [options]

Flag / Option Description
-o <path> Write compiled executable binary to specified path.
-S, --emit-ir Write LLVM IR file only without invoking Clang linker step.
--keep-ir Keep generated .ll IR file alongside binary.
--run Compile and immediately execute output program.

Environment Variables

  • REDB_CC: C compiler executable used to link IR (default: clang).
  • REDB_RUNTIME: Explicit path to static runtime archive libredb_runtime.a.
  • REDB_STDLIB: Directory containing standard library modules (default: lib/ in a checkout or share/redb/lib when installed).

13. Repository Layout & C Architecture

The compiler is written cleanly across modular C files:

Path Compiler Phase Responsibility
include/redb.h Tokens, AST data structures, shared types, and function prototypes.
src/lexer.c Source text stream tokenizer into Lexer token streams.
src/parser.c Recursive-descent parser building Abstract Syntax Tree (AST).
src/include.c File-relative source include resolution (@include).
src/typecheck.c Scope resolution, static type inference, string template lowering.
src/codegen.c Lowers AST nodes into formatted LLVM IR.
runtime/runtime.c Native C runtime library called by generated LLVM code.
lib/mathlib.redb Standard math module: powers, roots, trig, exp/ln, int/double min/max and constants.
src/main.c CLI driver, flags, Clang invocation, and program execution.

14. Runtime C ABI

Generated LLVM IR emits calls into the C runtime ABI (libredb_runtime.a):

void  redb_write(const char *str);
void  redb_writeln(const char *str);
void  redb_write_int(long long value);
void  redb_write_double(double value);
void  redb_write_bool(int value);
void  redb_newline(void);
char *redb_str_concat(const char *left, const char *right);
int   redb_str_eq(const char *left, const char *right);
void *redb_alloc(size_t size);
void  redb_writeformat(const char *fmt, ...);

15. Current Limitations (v0.1.0)

Deliberate Boundaries in v0.1.0:

No maps, structs, or classes
No pointers or manual dereferencing
No closures (functions cannot capture scope)
No Garbage Collector (GC)