brick

Brick Architecture

Overview

Brick compiles .brc source files to C code, then delegates to gcc or clang for machine code generation. The compiler itself is written in C++20.

.bricada → Lexer → Token Stream → Parser → AST → Type Checker → C Codegen → .c file → gcc -O3 → binary
                                ↕
                          Macro Expander
                          Build Eval

Pipeline Stages

1. Lexer (src/lexer/)

File: lexer.cpp, lexer.h

Tokenizes .brc source into a flat token stream. Handles:

2. Parser (src/parser/)

Files: parser.cpp, parser.h, ast.h, package.cpp, package.h, build_eval.cpp, build_eval.h, macro_expander.cpp, macro_expander.h

Recursive-descent parser that produces an AST. Architecture:

Parser
├── Top-level declarations: structs, enums, unions, functions, consts, macros, interfaces, impl blocks, type aliases
├── Expressions: binary ops, unary ops, literals, identifiers, calls, arrays, pointer deref, sizeof/alignof
├── Statements: if, while, for, for-in, return, break, continue, match, defer, block scopes
├── Package resolution: using, export, private, nested packages (MATH.VEC2)
├── Build system: build {}, emit {} compile-time eval
├── Macro system: macro definition, $interpolation, $macro() explicit call, hygiene, varargs
└── C interop: include, link, extern fn, @system

The AST is an untyped tree. Type checking happens separately in the codegen stage.

2a. Macro Expander

Before codegen, the macro expander processes all macro definitions and build/emit blocks:

  1. Collect all macro definitions during parsing
  2. On macro_name(...) call, expand body with $param substitutions
  3. build { ... } evaluates code at compile time
  4. emit { ... } generates code from the build context
  5. Hygiene: __-prefixed variables get unique gensyms
  6. Varargs: args... captures remaining arguments

2b. Build Eval

build {} blocks execute at compile time. Variables inside don’t exist in the final binary. Uses a simple interpreter:

2c. Package Resolution

  1. using PACKAGE → searches for PACKAGE.brc:
    • Current directory
    • -I <dir> paths
    • <dir>/PACKAGE/PACKAGE.brc (nested)
    • <dir>/PACKAGE/main.brc
    • BRICK_PATH environment variable paths
  2. Nested packages: MATH.VEC2MATH/VEC2.brc (dots → directory separators)
  3. export/private visibility enforcement during type checking

3. Type Checker & Codegen (src/codegen/)

Files: codegen.cpp, codegen.h, type_checker.cpp, type_checker.h

Two-phase code generation:

Phase 1: Type Checking (type_checker.cpp)

Phase 2: C Code Generation (codegen.cpp)

Produces readable C code with #line directives for debugging.

Type Map:

Brick C
i8 int8_t
i16 int16_t
i32 int32_t
i64 int64_t
u8 uint8_t
u16 uint16_t
u32 uint32_t
u64 uint64_t
f32 float
f64 double
bool uint8_t
usize size_t
isize ptrdiff_t
String BrickString
void void
T[N] T name[N]
T[] T* name; int64_t name_cnt; int64_t name_cap

Codegen details:

4. Embedded Runtime

Files: embedded_runtime.cpp, embedded_runtime.h

The runtime (block_memory.c, io.c, hot_reload.c, pool_allocator.c) is either:

embedded_runtime.cpp converts runtime C files into C++ string literals at build time.

Runtime Components

Block Memory (runtime/block_memory.c, .h)

Hot Reload (runtime/hot_reload.c, .h)

I/O (runtime/io.c, .h)

Pool Allocator (runtime/pool_allocator.c, .h)

Memory Visualizer (visualizer/memvis.cpp)

Build System

SCons (SConstruct, src/SConscript, runtime/SConscript, tests/SConscript)

SConstruct
├── src/SConscript         → brick compiler binary
├── runtime/SConscript     → runtime C objects
├── tests/SConscript       → test binaries
└── visualizer/SConscript  → TUI visualizer

CLI Usage

brick <input.brc> [-o output]     # compile to C
brick build <files> [-o output]    # compile to binary
brick run <input.brc>              # compile and run
brick new <project>                # scaffold
brick bind <header.h>              # C bindings

VS Code Extension (vscode-ext/)

Debugger (debugger/)

#line directives in generated C map source locations back to .brc files for breakpoints and stack traces.

Test Suite

Performance Characteristics

Operation Time
Block allocation ~3 cycles
Global reset ~5 ns (O(1))
fn call (static inline) 0 cycles (inlined)
fn call (export) ~1-2 cycles
Interface dispatch (vtbl) ~2-3 cycles
Pool alloc (≤64B) O(1)
Compiler throughput ~50K lines/sec
Generated C performance ~gcc -O3 native