A minimal, statically-typed systems language with Pascal-style syntax and a C backend.
fn main(): i32 {
name: str = "Zera";
print(f"Hello, {name}!");
return 0;
}
- Overview
- Features
- Quick Start
- Building
- Usage
- Language Basics
- Examples
- Project Structure
- Status
- Contributing
- License
Zera is a compiled, statically-typed systems programming language designed to be:
- Explicit — every variable has a declared type; no hidden magic
- Simple — one canonical way to express each construct
- Interoperable — seamless
extern fnbindings to any C library - Readable —
and/or/notinstead of&&/||/!;name: typedeclarations
The compiler (zerac) parses .z source files, performs semantic analysis, and emits
well-formatted C code that is immediately compiled by the host C compiler.
| Feature | Status |
|---|---|
Pascal-style declarations (x: i32 = 5) |
✅ Implemented |
| Immutable-by-default variables | ✅ Implemented |
Mutable variables (mut) |
✅ Implemented |
Compile-time constants (const) |
✅ Implemented |
Functions (fn) with full type signatures |
✅ Implemented |
| Structs (value semantics) | ✅ Implemented |
| Classes (reference semantics) | ✅ Implemented |
| Enumerations | ✅ Implemented |
F-strings (f"Hello, {name}!") |
✅ Implemented |
Control flow (if/elif/else) |
✅ Implemented |
Loops (for/while/break/continue) |
✅ Implemented |
range() in for loops |
✅ Implemented |
C interop (extern fn) |
✅ Implemented |
Module system (import/from ... import) |
✅ Implemented |
Package declarations (package) |
✅ Implemented |
| Multiple integer/float types | ✅ Implemented |
| Bitwise operators | ✅ Implemented |
match / pattern matching |
🚧 Parsing only |
| Generics | 🚧 Planned |
Option[T] / Result[T, E] |
🚧 Planned |
| Traits / interfaces | 🚧 Planned |
- GCC ≥ 9 (or Clang ≥ 10)
- CMake ≥ 3.15
- Ninja (recommended) or Make
# Configure
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
# Compile
cmake --build build
# Optional: run tests
cd build && ctest -C Release --output-on-failureThe compiler binary is placed at build/bin/zerac.
# Write a program
cat > hello.z <<'EOF'
fn main(): i32 {
print("Hello, World!");
return 0;
}
EOF
# Compile and run
./build/bin/zerac hello.z -o hello && ./hellocmake -S . -B build -G Ninja
cmake --build build -j$(nproc)
sudo cmake --install build # installs to /usr/local/bin/zeracmake # build with GCC
make test # run smoke tests
sudo make installcmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build buildbuild.bat # wraps cmake + MSBuild| CMake Option | Default | Description |
|---|---|---|
ZERA_BUILD_TESTS |
ON |
Enable CTest test suite |
ZERA_USE_GC |
ON |
Link Boehm GC; OFF uses a minimal stub |
CMAKE_BUILD_TYPE |
Release |
Debug adds -g -O0 -DZERA_DEBUG |
zerac [options] <input.z>
Options:
-o <file> Output file (default: a.out on Unix, a.exe on Windows)
-v, --verbose Print compilation pipeline stages
--syntax-only Parse and type-check; do not emit code
--emit-ast Dump the AST and exit
--gen-header Generate a C header (.h) from the source file
--backend=c Use C backend (default)
--backend=llvm Use experimental LLVM text IR backend
--memory=bare Manual memory (no GC)
--memory=auto Scope-based auto-free
--memory=gc Boehm GC (default)
--version Print version and exit
--help Print this help
# Compile a single file
zerac examples/01_hello.z
# Compile with explicit output name
zerac examples/11_fizzbuzz.z -o fizzbuzz && ./fizzbuzz
# Check syntax only (no output)
zerac examples/04_functions.z --syntax-only
# Verbose pipeline dump
zerac examples/06_structs.z -v# Immutable (default)
x: i32 = 42;
name: str = "Alice";
# Mutable
mut counter: i32 = 0;
counter += 1;
# Compile-time constant
const MAX: i32 = 100;
fn add(a: i32, b: i32): i32 {
return a + b;
}
fn greet(name: str) { # void return — type omitted
print(f"Hello, {name}!");
}
if x > 0 {
print("positive");
} elif x == 0 {
print("zero");
} else {
print("negative");
}
for i in range(0, 10) {
print(f"{i}");
}
mut n: i32 = 5;
while n > 0 {
n -= 1;
}
struct Point {
x: f64;
y: f64;
fn magnitude(): f64 {
return self.x * self.x + self.y * self.y;
}
}
class Counter {
mut value: i32;
fn increment() { self.value += 1; }
fn get(): i32 { return self.value; }
}
import math;
from std.strings import len, upper;
fn main(): i32 {
n: i32 = math.abs(-7);
print(f"abs(-7) = {n}");
return 0;
}
extern fn sqrt(x: f64): f64;
extern fn printf(fmt: *i8, ...): i32;
fn main(): i32 {
result: f64 = sqrt(2.0);
printf("sqrt(2) = %f\n", result);
return 0;
}
The examples/ directory contains 16 annotated programs:
| File | What it demonstrates |
|---|---|
01_hello.z |
Hello World |
02_variables.z |
Immutable, mutable, constants |
03_control_flow.z |
if/elif/else, while, for, break, continue |
04_functions.z |
Function definitions, recursion |
05_classes.z |
Classes with methods |
06_structs.z |
Structs with methods |
07_enums.z |
Enums and comparisons |
10_extern.z |
C interop with stdlib |
11_fizzbuzz.z |
Classic FizzBuzz |
12_primes.z |
Sieve of Eratosthenes |
13_sorting.z |
Sorting network |
14_packages.z |
Module import syntax |
15_multi_style.z |
Unified syntax demo |
20_module_demo.z |
Module system demo |
math.z |
Math module example |
zera/
├── src/
│ ├── frontend/
│ │ ├── lexer.c # Tokenizer with binary-search keyword lookup
│ │ ├── parser_core.c # Parser lifecycle, top-level dispatch
│ │ ├── parser_exprs.c # Expression parsing (precedence climbing)
│ │ ├── parser_decls.c # fn / struct / class / enum / import
│ │ ├── parser_stmts.c # Statements, var declarations, control flow
│ │ ├── semantic_scope.c # Symbol tables, scopes, built-in types
│ │ ├── semantic_exprs.c # Expression type inference and checking
│ │ ├── semantic_stmts.c # Statement analysis, 3-pass top-level
│ │ ├── semantic_modules.c # Module loading and symbol import
│ │ ├── ast_types.c / .h # Type nodes
│ │ ├── ast_expr.c / .h # Expression nodes
│ │ ├── ast_stmt.c / .h # Statement nodes
│ │ └── token.c / .h # Token kinds and helpers
│ ├── backend/
│ │ ├── c/
│ │ │ ├── c_codegen_core.c # Code generator lifecycle, top-level emit
│ │ │ ├── c_codegen_expr.c # Expression code generation
│ │ │ ├── c_codegen_stmt.c # Statement code generation
│ │ │ └── c_codegen_utils.c # String builder, emit helpers
│ │ ├── header_gen.c # C header generation (--gen-header)
│ │ └── llvm_text_codegen.c # Experimental LLVM text IR backend
│ ├── common/
│ │ ├── array.c # Generic dynamic array
│ │ ├── error.c # Diagnostics and error context
│ │ ├── memory.c # Allocator (GC / stub / RAII)
│ │ └── strings.c # String builder and utilities
│ ├── compiler.c # Pipeline: lex → parse → sema → codegen
│ └── main.c # CLI argument parsing and entry point
├── include/ # Public headers mirroring src/ layout
├── std/ # Standard library source (.z files)
├── examples/ # 16 annotated example programs
├── tests/ # Test suite (.z files + run_tests.ps1)
├── editors/ # Editor plugins (VS Code, Vim, Neovim, JetBrains)
├── dist/ # Packaging (Debian .deb, Windows Inno Setup)
├── CMakeLists.txt # Primary build system (CMake 3.15+)
├── Makefile # Alternative build (Linux/macOS Make)
├── build.bat # Windows convenience build script
└── LANGUAGE_SPEC.md # Full language reference
v0.1.0 — initial public release.
The compiler is functional and can compile all programs in examples/ to
native executables via the C backend. The test suite (ctest) passes
4 automated integration tests.
Items that are parsed but not yet fully implemented in the code generator:
match/ pattern matching- Generics (
struct List[T]) Option[T]/Result[T, E]types- Traits and interface dispatch
- Fork the repository and create a feature branch.
- Follow Conventional Commits for all commit messages.
- Ensure
cmake --build build && ctest --test-dir buildpasses. - Open a pull request with a clear description of the change.
Commit message format:
<type>(<scope>): <short summary>
[optional body — explain *why*, not *what*]
[optional footer — BREAKING CHANGE: ..., Closes #issue]
Types: feat, fix, refactor, docs, test, chore, perf, ci.
MIT — see LICENSE.
Zera v0.1.0 — work in progress. Contributions welcome.