Overview of Zen C
mainGNU C/C11. It provides high-level features like type inference, pattern matching, generics, traits, async/await, and RAII-based manual memory management, while maintaining 100% C ABI compatibility.repository·main·Indexed 26 days ago
https://github.com/zenc-lang/zencZen C is a modern systems programming language that compiles to human-readable GNU C/C11, combining high-level ergonomics like type inference and pattern matching with low-level control and 100% C ABI compatibility. The documentation covers the zc CLI tool, the standard library (std), a built-in unit testing framework, and various output backends including C++, CUDA, and Objective-C. It also provides guidance on using the Actually Portable Executable (APE) build via cosmocc and configuring VS Code for debugging.
GNU C/C11. It provides high-level features like type inference, pattern matching, generics, traits, async/await, and RAII-based manual memory management, while maintaining 100% C ABI compatibility..clang-format file to format your code.src/parser/ — Implementation of the recursive descent parser.src/codegen/ — Transpiler logic that converts Zen C to GNU C/C11.std/ — Standard library modules written in Zen C.The Zen C Language Server provides the following editor features:
To install the Zen C compiler (zc) from the source repository, clone the repository, clean previous builds, compile using make, and install to your system.
Prerequisites:
make and a C compiler.Steps:
git clone https://github.com/zenc-lang/zenc.git
cd zenc
make clean # 移除旧的构建文件
make
sudo make installYou can compile Zen C into an Actually Portable Executable (APE) using Cosmopolitan Libc. This generates a single .com file that runs natively on Linux, macOS, Windows, FreeBSD, OpenBSD, and NetBSD across x86_64 and aarch64 architectures.
Prerequisites: The cosmocc toolchain must be in your PATH.
Build and Install:
make ape
sudo env "PATH=$PATH" make install-apeOutputs:
out/bin/zc.com: Portable Zen-C compiler with the standard library embedded.out/bin/zc-boot.com: A self-contained bootstrap installer for new Zen-C projects.Usage:
./out/bin/zc.com build hello.zc -o helloZen C can be compiled as an Actually Portable Executable (APE) using the cosmocc toolchain. This produces a single .com binary that runs natively on Linux, macOS, Windows, FreeBSD, OpenBSD, and NetBSD across both x86_64 and aarch64 architectures.
Prerequisites:
cosmocc toolchain must be in your PATH.Build and Install:
make ape
sudo env "PATH=$PATH" make install-apeArtifacts:
out/bin/zc.com: The portable compiler with the standard library embedded.out/bin/zc-boot.com: A self-contained bootstrap installer.Usage:
./out/bin/zc.com build hello.zc -o helloZen C programs can be debugged using standard C debuggers like LLDB or GDB.
For VS Code, install the official Zen C extension and use the C/C++ (Microsoft) or CodeLLDB extensions.
To enable one-click debugging, create a .vscode directory in your project with the following configurations:
// tasks.json (Build Task)
{
"label": "Zen C: Build Debug",
"type": "shell",
"command": "zc",
"args": [ "${file}", "-g", "-o", "${fileDirname}/app", "-O0" ],
"group": { "kind": "build", "isDefault": true }
}
// launch.json (Debugger Configuration)
{
"name": "Zen C: Debug (LLDB)",
"type": "lldb",
"request": "launch",
"program": "${fileDirname}/app",
"preLaunchTask": "Zen C: Build Debug"
}If you use nvim-lspconfig, you can register zc as a custom server. The following configuration uses lspconfig to define the command, filetypes, and root directory detection.
local lspconfig = require('lspconfig')
local configs = require('lspconfig.configs')
if not configs.zenc then
configs.zenc = {
default_config = {
cmd = { 'zc', 'lsp' },
filetypes = { 'zenc', 'zc' },
root_dir = lspconfig.util.root_pattern('.git', 'build.bat', 'Makefile'),
settings = {},
},
}
end
lspconfig.zenc.setup {}Use the --backend cpp (or --cpp) flag to generate C++ compatible code, allowing seamless integration with C++ libraries. This mode uses auto instead of __auto_type, uses function overloading instead of _Generic, and performs explicit casts for void*.
To use C++ code within Zen C, include C++ headers and wrap the C++ code in a raw block.
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; }
}Compile to Objective-C (.m) using the --backend objc (or --objc) flag to utilize Objective-C frameworks like Cocoa/Foundation. Use include for headers and raw blocks for Objective-C syntax (e.g., @interface, [...]). Zen C string interpolation also works with Objective-C objects (id) by automatically calling debugDescription or description.
//> macos: framework: Foundation
//> linux: cflags: -fconstant-string-class=NSConstantString -D_NATIVE_OBJC_EXCEPTIONS
//> linux: link: -lgnustep-base -lobjc
include <Foundation/Foundation.h>
fn main() {
raw {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Hello from Objective-C!");
[pool drain];
}
println "Zen C funktioniert ebenfalls!";
}Zen C supports GPU programming by transpiling to CUDA C++ via the --backend cuda (or --cuda) flag. This requires the NVIDIA CUDA Toolkit. It provides a launch operator for calling kernels and a standard library std/cuda.zc for memory management and synchronization.
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() {
def 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();
}If your editor supports generic LSP clients, use the following settings to connect to the Zen C server:
zclspstdio.zc