Modern Ergonomics. Zero Overhead. Pure C.
Write like a high-level language, run like C.
Zen C is a modern systems programming language that compiles to human-readable GNU C/C11. It provides a rich feature set including type inference, pattern matching, generics, traits, async/await, and manual memory management with RAII capabilities, all while maintaining 100% C ABI compatibility.
git clone https://github.com/z-libs/Zen-C.git
cd Zen-C
make
sudo make install
Zen C can be compiled as an Actually Portable Executable (APE) using Cosmopolitan Libc. This produces a single binary (.com) that runs natively on Linux, macOS, Windows, FreeBSD, OpenBSD, and NetBSD on both x86_64 and aarch64 architectures.
Prerequisites:
- cosmocc toolchain (must be in your PATH)
Build & Install:
make ape
sudo env "PATH=$PATH" make install-ape
Artifacts:
- out/bin/zc.com: The portable Zen-C compiler. Includes the standard library embedded within the executable.
- out/bin/zc-boot.com: A self-contained bootstrap installer for setting up new Zen-C projects.
Usage:
# Run on any supported OS
./out/bin/zc.com build hello.zc -o hello
# Compile and run
zc run hello.zc
# Build executable
zc build hello.zc -o hello
# Interactive Shell
zc repl
You can set ZC_ROOT to specify the location of the Standard Library (standard imports like import "std/vector.zc"). This allows you to run zc from any directory.
export ZC_ROOT=/path/to/Zen-C
Zen C distinguishes between compile-time constants and runtime variables.
def)Values that exist only at compile-time (folded into code). Use these for array sizes, fixed configuration, and magic numbers.
def MAX_SIZE = 1024;
let buffer: char[MAX_SIZE]; // Valid array size
let)Storage locations in memory. Can be mutable or read-only (const).
let x = 10; // Mutable
x = 20; // OK
let y: const int = 10; // Read-only (Type qualified)
// y = 20; // Error: cannot assign to const
| Type | C Equivalent | Description |
|---|---|---|
int, uint |
int, unsigned int |
Platform standard integer |
I8 .. I128 or i8 .. i128 |
int8_t .. __int128_t |
Signed fixed-width integers |
U8 .. U128 or u8 .. u128 |
uint8_t .. __uint128_t |
Unsigned fixed-width integers |
isize, usize |
ptrdiff_t, size_t |
Pointer-sized integers |
byte |
uint8_t |
Alias for U8 |
F32, F64 or f32, f64 |
float, double |
Floating point numbers |
bool |
bool |
true or false |
char |
char |
Single character |
string |
char* |
C-string (null-terminated) |
U0, u0, void |
void |
Empty type |
Fixed-size arrays with value semantics.
def SIZE = 5;
let ints: int[SIZE] = {1, 2, 3, 4, 5};
let zeros: [int; SIZE]; // Zero-initialized
Group multiple values together, access elements by index.
let pair = (1, "Hello");
let x = pair.0; // 1
let s = pair.1; // "Hello"
Multiple Return Values
Functions can return tuples to provide multiple results:
fn add_and_subtract(a: int, b: int) -> (int, int) {
return (a + b, a - b);
}
let result = add_and_subtract(3, 2);
let sum = result.0; // 5
let diff = result.1; // 1
Destructuring
Tuples can be destructured directly into variables:
let (sum, diff) = add_and_subtract(3, 2);
// sum = 5, diff = 1
Data structures with optional bitfields.
struct Point {
x: int;
y: int;
}
// Struct initialization
let p = Point { x: 10, y: 20 };
// Bitfields
struct Flags {
valid: U8 : 1;
mode: U8 : 3;
}
Note: Structs use Move Semantics by default. Fields can be accessed via
.even on pointers (Auto-Dereference).
Tagged unions (Sum types) capable of holding data.
enum Shape {
Circle(float), // Holds radius
Rect(float, float), // Holds width, height
Point // No data
}
Standard C unions (unsafe access).
union Data {
i: int;
f: float;
}
Create a new name for an existing type.
alias ID = int;
alias PointMap = Map<string, Point>;
fn add(a: int, b: int) -> int {
return a + b;
}
// Named arguments supported in calls
add(a: 10, b: 20);
Note: Named arguments must strictly follow the defined parameter order.
add(b: 20, a: 10)is invalid.
Function arguments can be marked as const to enforce read-only semantics. This is a type qualifier, not a manifest constant.
fn print_val(v: const int) {
// v = 10; // Error: Cannot assign to const variable
println "{v}";
}
Functions can define default values for trailing arguments. These can be literals, expressions, or valid Zen C code (like struct constructors).
// Simple default value
fn increment(val: int, amount: int = 1) -> int {
return val + amount;
}
// Expression default value (evaluated at call site)
fn offset(val: int, pad: int = 10 * 2) -> int {
return val + pad;
}
// Struct default value
struct Config { debug: bool; }
fn init(cfg: Config = Config { debug: true }) {
if cfg.debug { println "Debug Mode"; }
}
fn main() {
increment(10); // 11
offset(5); // 25
init(); // Prints "Debug Mode"
}
Anonymous functions that can capture their environment.
let factor = 2;
let double = x -> x * factor; // Arrow syntax
let full = fn(x: int) -> int { return x * factor; }; // Block syntax
Zen C supports raw C function pointers using the fn* syntax. This allows seamless interop with C libraries that expect function pointers without closure overhead.
// Function taking a raw function pointer
fn set_callback(cb: fn*(int)) {
cb(42);
}
// Function returning a raw function pointer
fn get_callback() -> fn*(int) {
return my_handler;
}
// Pointers to function pointers are supported (fn**)
let pptr: fn**(int) = &ptr;
Functions can accept a variable number of arguments using ... and the va_list type.
fn log(lvl: int, fmt: char*, ...) {
let ap: va_list;
va_start(ap, fmt);
vprintf(fmt, ap); // Use C stdio
va_end(ap);
}
if x > 10 {
print("Large");
} else if x > 5 {
print("Medium");
} else {
print("Small");
}
// Ternary
let y = x > 10 ? 1 : 0;
Powerful alternative to switch.
match val {
1 => { print "One" },
2 || 3 => { print "Two or Three" }, // OR with ||
4 or 5 => { print "Four or Five" }, // OR with 'or'
6, 7, 8 => { print "Six to Eight" }, // OR with comma
10 .. 15 => { print "10 to 14" }, // Exclusive range (Legacy)
10 ..< 15 => { print "10 to 14" }, // Exclusive range (Explicit)
20 ..= 25 => { print "20 to 25" }, // Inclusive range
_ => { print "Other" },
}
// Destructuring Enums
match shape {
Shape::Circle(r) => println "Radius: {r}",
Shape::Rect(w, h) => println "Area: {w*h}",
Shape::Point => println "Point"
}
To inspect a value without taking ownership (moving it), use the ref keyword in the pattern. This is essential for types that implement Move Semantics (like Option, Result, non-Copy structs).
let opt = Some(NonCopyVal{...});
match opt {
Some(ref x) => {
// 'x' is a pointer to the value inside 'opt'
// 'opt' is NOT moved/consumed here
println "{x.field}";
},
None => {}
}
// Range
for i in 0..10 { ... } // Exclusive (0 to 9)
for i in 0..<10 { ... } // Exclusive (Explicit)
for i in 0..=10 { ... } // Inclusive (0 to 10)
for i in 0..10 step 2 { ... }
// Iterator (Vec, Array, or custom Iterable)
for item in collection { ... }
// While
while x < 10 { ... }
// Infinite with label
outer: loop {
if done { break outer; }
}
// Repeat N times
for _ in 0..5 { ... }
// Guard: Execute else and return if condition is false
guard ptr != NULL else { return; }
// Unless: If not true
unless is_valid { return; }
Zen C supports operator overloading for user-defined structs by implementing specific method names.
| Category | Operator | Method Name |
|---|---|---|
| Arithmetic | +, -, *, /, % |
add, sub, mul, div, rem |
| Comparison | ==, != |
eq, neq |
<, >, <=, >= |
lt, gt, le, ge |
|
| Bitwise | &, \|, ^ |
bitand, bitor, bitxor |
<<, >> |
shl, shr |
|
| Unary | - |
neg |
! |
not |
|
~ |
bitnot |
|
| Index | a[i] |
get(a, i) |
a[i] = v |
set(a, i, v) |
Example:
impl Point {
fn add(self, other: Point) -> Point {
return Point{x: self.x + other.x, y: self.y + other.y};
}
}
let p3 = p1 + p2; // Calls p1.add(p2)
These operators are built-in language features and cannot be overloaded directly.
| Operator | Name | Description |
|---|---|---|
\|> |
Pipeline | x \|> f(y) desugars to f(x, y) |
?? |
Null Coalescing | val ?? default returns default if val is NULL (pointers) |
??= |
Null Assignment | val ??= init assigns if val is NULL |
?. |
Safe Navigation | ptr?.field accesses field only if ptr is not NULL |
? |
Try Operator | res? returns error if present (Result/Option types) |
Auto-Dereference:
Pointer field access (ptr.field) and method calls (ptr.method()) automatically dereference the pointer, equivalent to (*ptr).field.
Zen C provides versatile options for printing to the console, including keywords and concise shorthands.
print "text": Prints to stdout without a trailing newline.println "text": Prints to stdout with a trailing newline.eprint "text": Prints to stderr without a trailing newline.eprintln "text": Prints to stderr with a trailing newline.Zen C allows you to use string literals directly as statements for quick printing:
"Hello World": Equivalent to println "Hello World". (Implicitly adds newline)"Hello World"..: Equivalent to print "Hello World". (No trailing newline)!"Error": Equivalent to eprintln "Error". (Output to stderr)!"Error"..: Equivalent to eprint "Error". (Output to stderr, no newline)You can embed expressions directly into string literals using {} syntax. This works with all printing methods and string shorthands.
let x = 42;
let name = "Zen";
println "Value: {x}, Name: {name}";
"Value: {x}, Name: {name}"; // shorthand println
?)Zen C supports a shorthand for prompting user input using the ? prefix.
? "Prompt text": Prints the prompt (without newline) and waits for input (reads a line).? "Enter age: " (age): Prints prompt and scans input into the variable age.
let age: int;
? "How old are you? " (age);
println "You are {age} years old.";
Zen C allows manual memory management with ergonomic aids.
Execute code when the current scope exits. Defer statements are executed in LIFO (last-in, first-out) order.
let f = fopen("file.txt", "r");
defer fclose(f);
To prevent undefined behavior, control flow statements (
return,break,continue,goto) are not allowed inside adeferblock.
Automatically free the variable when scope exits.
autofree let types = malloc(1024);
Zen C treats types with destructors (like File, Vec, or malloc'd pointers) as Resources. To prevent double-free errors, resources cannot be implicitly duplicated.
Copy behavior, making assignment a duplication.Diagnostics & Philosophy:
If you see an error "Use of moved value", the compiler is telling you: "This type owns a resource (like memory or a handle) and blindly copying it is unsafe."
Contrast: Unlike C/C++, Zen C does not implicitly duplicate resource-owning values.
Function Arguments:
Passing a value to a function follows the same rules as assignment: resources are moved unless passed by reference.
fn process(r: Resource) { ... } // 'r' is moved into function
fn peek(r: Resource*) { ... } // 'r' is borrowed (reference)
Explicit Cloning:
If you do want two copies of a resource, make it explicit:
let b = a.clone(); // Calls the 'clone' method from the Clone trait
Opt-in Copy (Value Types):
For small types without destructors:
struct Point { x: int; y: int; }
impl Copy for Point {} // Opt-in to implicit duplication
fn main() {
let p1 = Point { x: 1, y: 2 };
let p2 = p1; // Copied. p1 stays valid.
}
Implement Drop to run cleanup logic automatically.
impl Drop for MyStruct {
fn drop(self) {
self.free();
}
}
Define methods on types using impl.
impl Point {
// Static method (constructor convention)
fn new(x: int, y: int) -> Self {
return Point{x: x, y: y};
}
// Instance method
fn dist(self) -> float {
return sqrt(self.x * self.x + self.y * self.y);
}
}
Define shared behavior.
struct Circle { radius: f32; }
trait Drawable {
fn draw(self);
}
impl Drawable for Circle {
fn draw(self) { ... }
}
let circle = Circle{};
let drawable: Drawable = &circle;
Zen C includes standard traits that integrate with language syntax.
Iterable
Implement Iterable<T> to enable for-in loops for your custom types.
import "std/iter.zc"
// Define an Iterator
struct MyIter {
curr: int;
stop: int;
}
impl MyIter {
fn next(self) -> Option<int> {
if self.curr < self.stop {
self.curr += 1;
return Option<int>::Some(self.curr - 1);
}
return Option<int>::None();
}
}
// Implement Iterable
impl MyRange {
fn iterator(self) -> MyIter {
return MyIter{curr: self.start, stop: self.end};
}
}
// Use in Loop
for i in my_range {
println "{i}";
}
Drop
Implement Drop to define a destructor that runs when the object goes out of scope (RAII).
import "std/mem.zc"
struct Resource {
ptr: void*;
}
impl Drop for Resource {
fn drop(self) {
if self.ptr != NULL {
free(self.ptr);
}
}
}
Note: If a variable is moved,
dropis NOT called on the original variable. It adheres to Resource Semantics.
Copy
Marker trait to opt-in to Copy behavior (implicit duplication) instead of Move semantics. Used via @derive(Copy).
Rule: Types that implement
Copymust not define a destructor (Drop).
@derive(Copy)
struct Point { x: int; y: int; }
fn main() {
let p1 = Point{x: 1, y: 2};
let p2 = p1; // Copied! p1 remains valid.
}
Clone
Implement Clone to allow explicit duplication of resource-owning types.
import "std/mem.zc"
struct MyBox { val: int; }
impl Clone for MyBox {
fn clone(self) -> MyBox {
return MyBox{val: self.val};
}
}
fn main() {
let b1 = MyBox{val: 42};
let b2 = b1.clone(); // Explicit copy
}
Use use to embed other structs. You can either mix them in (flatten fields) or name them (nest fields).
struct Entity { id: int; }
struct Player {
// Mixin (Unnamed): Flattens fields
use Entity; // Adds 'id' to Player directly
name: string;
}
struct Match {
// Composition (Named): Nests fields
use p1: Player; // Accessed via match.p1
use p2: Player; // Accessed via match.p2
}
Type-safe templates for Structs and Functions.
// Generic Struct
struct Box<T> {
item: T;
}
// Generic Function
fn identity<T>(val: T) -> T {
return val;
}
// Multi-parameter Generics
struct Pair<K, V> {
key: K;
value: V;
}
Built on pthreads.
async fn fetch_data() -> string {
// Runs in background
return "Data";
}
fn main() {
let future = fetch_data();
let result = await future;
}
Run code at compile-time to generate source or print messages.
comptime {
// Generate code at compile-time (written to stdout)
println "let build_date = \"2024-01-01\";";
}
println "Build Date: {build_date}";
Embed files as specified types.
// Default (Slice_char)
let data = embed "assets/logo.png";
// Typed Embed
let text = embed "shader.glsl" as string; // Embbed as C-string
let rom = embed "bios.bin" as u8[1024]; // Embed as fixed array
let wav = embed "sound.wav" as u8[]; // Embed as Slice_u8
Import compiler plugins to extend syntax.
import plugin "regex"
let re = regex! { ^[a-z]+$ };
Pass preprocessor macros through to C.
Tip: For simple constants, use
definstead. Use#definewhen you need C-preprocessor macros or conditional compilation flags.
#define MAX_BUFFER 1024
Decorate functions and structs to modify compiler behavior.
| Attribute | Scope | Description |
|---|---|---|
@must_use |
Fn | Warn if return value is ignored. |
@deprecated("msg") |
Fn/Struct | Warn on usage with message. |
@inline |
Fn | Hint compiler to inline. |
@noinline |
Fn | Prevent inlining. |
@packed |
Struct | Remove padding between fields. |
@align(N) |
Struct | Force alignment to N bytes. |
@constructor |
Fn | Run before main. |
@destructor |
Fn | Run after main exits. |
@unused |
Fn/Var | Suppress unused variable warnings. |
@weak |
Fn | Weak symbol linkage. |
@section("name") |
Fn | Place code in specific section. |
@noreturn |
Fn | Function does not return (e.g. exit). |
@derive(...) |
Struct | Auto-implement traits. Supports Debug, Eq (Smart Derive), Copy, Clone. |
Zen C provides "Smart Derives" that respect Move Semantics:
@derive(Eq): Generates an equality method that takes arguments by reference (fn eq(self, other: T*)).
a == b), the compiler automatically passes b by reference (&b) to avoid moving it.Zen C provides first-class support for inline assembly, transpiling directly to GCC-style extended asm.
Write raw assembly within asm blocks. Strings are concatenated automatically.
asm {
"nop"
"mfence"
}
Prevent the compiler from optimizing away assembly that has side effects.
asm volatile {
"rdtsc"
}
Zen C simplifies the complex GCC constraint syntax with named bindings.
// Syntax: : out(variable) : in(variable) : clobber(reg)
// Uses {variable} placeholder syntax for readability
fn add(a: int, b: int) -> int {
let result: int;
asm {
"add {result}, {a}, {b}"
: out(result)
: in(a), in(b)
: clobber("cc")
}
return result;
}
| Type | Syntax | GCC Equivalent |
|---|---|---|
| Output | : out(variable) |
"=r"(variable) |
| Input | : in(variable) |
"r"(variable) |
| Clobber | : clobber("rax") |
"rax" |
| Memory | : clobber("memory") |
"memory" |
Note: When using Intel syntax (via
-masm=intel), you must ensure your build is configured correctly (for example,//> cflags: -masm=intel). TCC does not support Intel syntax assembly.
Zen C supports special comments at the top of your source file to configure the build process without needing a complex build system or Makefile.
| Directive | Arguments | Description |
|---|---|---|
//> link: |
-lfoo or path/to/lib.a |
Link against a library or object file. |
//> lib: |
path/to/libs |
Add a library search path (-L). |
//> include: |
path/to/headers |
Add an include search path (-I). |
//> cflags: |
-Wall -O3 |
Pass arbitrary flags to the C compiler. |
//> define: |
MACRO or KEY=VAL |
Define a preprocessor macro (-D). |
//> pkg-config: |
gtk+-3.0 |
Run pkg-config and append --cflags and --libs. |
//> shell: |
command |
Execute a shell command during the build. |
//> get: |
http://url/file |
Download a file if specific file does not exist. |
//> include: ./include
//> lib: ./libs
//> link: -lraylib -lm
//> cflags: -Ofast
//> pkg-config: gtk+-3.0
import "raylib.h"
fn main() { ... }
Zen C includes a standard library (std) covering essential functionality.
Browse the Standard Library Documentation
| Module | Description | Docs |
|---|---|---|
std/vec.zc |
Growable dynamic array Vec<T>. |
Docs |
std/string.zc |
Heap-allocated String type with UTF-8 support. |
Docs |
std/queue.zc |
FIFO queue (Ring Buffer). | Docs |
std/map.zc |
Generic Hash Map Map<V>. |
Docs |
std/fs.zc |
File system operations. | Docs |
std/io.zc |
Standard Input/Output (print/println). |
Docs |
std/option.zc |
Optional values (Some/None). |
Docs |
std/result.zc |
Error handling (Ok/Err). |
Docs |
std/path.zc |
Cross-platform path manipulation. | Docs |
std/env.zc |
Process environment variables. | Docs |
Zen C provides a built-in Language Server and REPL to enhance the development experience.
The Zen C Language Server (LSP) supports standard LSP features for editor integration, providing:
To start the language server (typically configured in your editor's LSP settings):
zc lsp
It communicates via standard I/O (JSON-RPC 2.0).
The Read-Eval-Print Loop allows you to experiment with Zen C code interactively.
zc repl
~/.zprep_history.~/.zprep_init.zc.| Command | Description |
|---|---|
:help |
Show available commands. |
:reset |
Clear current session history (variables/functions). |
:vars |
Show active variables. |
:funcs |
Show user-defined functions. |
:structs |
Show user-defined structs. |
:imports |
Show active imports. |
:history |
Show session input history. |
:type <expr> |
Show the type of an expression. |
:c <stmt> |
Show the generated C code for a statement. |
:time <expr> |
Benchmark an expression (runs 1000 iterations). |
:edit [n] |
Edit command n (default: last) in $EDITOR. |
:save <file> |
Save the current session to a .zc file. |
:load <file> |
Load and execute a .zc file into the session. |
:watch <expr> |
Watch an expression (re-evaluated after every entry). |
:unwatch <n> |
Remove a watch. |
:undo |
Remove the last command from the session. |
:delete <n> |
Remove command at index n. |
:clear |
Clear the screen. |
:quit |
Exit the REPL. |
! <cmd> |
Run a shell command (e.g. !ls). |
Zen C is designed to work with most C11 compilers. Some features rely on GNU C extensions, but these often work in other compilers. Use the --cc flag to switch backends.
zc run app.zc --cc clang
zc run app.zc --cc zig
| Compiler | Pass Rate | Supported Features | Known Limitations |
|---|---|---|---|
| GCC | 100% | All Features | None. |
| Clang | 100% | All Features | None. |
| Zig | 100% | All Features | None. Uses zig cc as a drop-in C compiler. |
| TCC | ~70% | Basic Syntax, Generics, Traits | No __auto_type, No Intel ASM, No Nested Functions. |
Recommendation: Use GCC, Clang, or Zig for production builds. TCC is excellent for rapid prototyping due to its compilation speed but misses some advanced C extensions Zen C relies on for full feature support.
Zig's zig cc command provides a drop-in replacement for GCC/Clang with excellent cross-compilation support. To use Zig:
# Compile and run a Zen C program with Zig
zc run app.zc --cc zig
# Build the Zen C compiler itself with Zig
make zig
Zen C can generate C++-compatible code with the --cpp flag, allowing seamless integration with C++ libraries.
# Direct compilation with g++
zc app.zc --cpp
# Or transpile for manual build
zc transpile app.zc --cpp
g++ out.c my_cpp_lib.o -o app
Include C++ headers and use raw blocks for C++ code:
include <vector>
include <iostream>
raw {
std::vector<int> make_vec(int a, int b) {
return {a, b};
}
}
fn main() {
let v = make_vec(1, 2);
raw { std::cout << "Size: " << v.size() << std::endl; }
}
Note: The
--cppflag switches the backend tog++and emits C++-compatible code (usesautoinstead of__auto_type, function overloads instead of_Generic, and explicit casts forvoid*).
Zen C supports GPU programming by transpiling to CUDA C++. This allows you to leverage powerful C++ features (templates, constexpr) within your kernels while maintaining Zen C's ergonomic syntax.
# Direct compilation with nvcc
zc run app.zc --cuda
# Or transpile for manual build
zc transpile app.zc --cuda -o app.cu
nvcc app.cu -o app
| Attribute | CUDA Equivalent | Description |
|---|---|---|
@global |
__global__ |
Kernel function (runs on GPU, called from host) |
@device |
__device__ |
Device function (runs on GPU, called from GPU) |
@host |
__host__ |
Host function (explicit CPU-only) |
Zen C provides a clean launch statement for invoking CUDA kernels:
launch kernel_name(args) with {
grid: num_blocks,
block: threads_per_block,
shared_mem: 1024, // Optional
stream: my_stream // Optional
};
This transpiles to: kernel_name<<<grid, block, shared, stream>>>(args);
Use Zen C function syntax with @global and the launch statement:
import "std/cuda.zc"
@global
fn add_kernel(a: float*, b: float*, c: float*, n: int) {
let i = thread_id();
if i < n {
c[i] = a[i] + b[i];
}
}
fn main() {
const N = 1024;
let d_a = cuda_alloc<float>(N);
let d_b = cuda_alloc<float>(N);
let d_c = cuda_alloc<float>(N);
defer cuda_free(d_a);
defer cuda_free(d_b);
defer cuda_free(d_c);
// ... init data ...
launch add_kernel(d_a, d_b, d_c, N) with {
grid: (N + 255) / 256,
block: 256
};
cuda_sync();
}
std/cuda.zc)Zen C provides a standard library for common CUDA operations to reduce raw blocks:
import "std/cuda.zc"
// Memory management
let d_ptr = cuda_alloc<float>(1024);
cuda_copy_to_device(d_ptr, h_ptr, 1024 * sizeof(float));
defer cuda_free(d_ptr);
// Synchronization
cuda_sync();
// Thread Indexing (use inside kernels)
let i = thread_id(); // Global index
let bid = block_id();
let tid = local_id();
Note: The
--cudaflag setsnvccas the compiler and implies--cppmode. Requires the NVIDIA CUDA Toolkit.
The test suite is your best friend.
# Run all tests (GCC)
make test
# Run specific test
./zc run tests/test_match.zc
# Run with different compiler
./tests/run_tests.sh --cc clang
./tests/run_tests.sh --cc zig
./tests/run_tests.sh --cc tcc
src/parser/ - Recursive descent parser.src/codegen/ - Transpiler logic (Zen C -> GNU C/C11).std/ - Written in Zen C itself.Last modified 17 February 2026