"No ambiguity. No surprises."
Klar is an AI-native application programming language designed for clarity, safety, and simplicity. It is optimized for AI code generation—specifically Claude Code—prioritizing unambiguous syntax and predictable semantics.
Traditional languages present challenges for AI code generation:
- C/C++: Ambiguous syntax, undefined behavior, preprocessor complexity
- Rust: Steep learning curve, complex lifetime annotations, borrow checker friction
- Go/C#: Implicit behaviors, null references, verbose error handling
Klar takes a different approach: maximize clarity, minimize surprises.
- Unambiguous syntax — no context needed to parse
- No undefined behavior — every operation has defined semantics
- Memory safe by default — ownership without lifetime annotations
- Explicit over implicit — no silent type conversions
- One obvious way — minimize redundant syntax forms
- Readable operators —
and,or,notinstead of&&,||,!
| C/C++ Problem | Klar Solution |
|---|---|
| Ambiguous syntax | Keyword-driven, context-free parsing |
| Preprocessor macros | comptime blocks |
| Undefined behavior | Defined semantics + explicit overflow operators |
| Null pointer danger | ?T optional types |
| Memory unsafety | Ownership + borrows, no dangling references |
| Header/source split | Modules |
| Implicit conversions | Explicit .as#[T], .to#[T], .trunc#[T] |
| Complex build systems | Convention-based builds |
fn main() {
println("Hello, Klar!")
}
let x: i32 = 42 // immutable, explicit type required
let y: i64 = 100 // all types must be declared
var counter: i32 = 0 // mutable
// No implicit conversions
let wide: i64 = x.as#[i64] // safe widening
let narrow: i32 = y.to#[i32] // checked narrowing (traps on overflow)
let name: string = "World"
let count: i32 = 42
println("Hello, {name}! Count: {count}")
// If statements (not expressions)
var max: i32
if a > b {
max = a
} else {
max = b
}
// Pattern matching (statement-based)
var result: string
match status {
Status.Ok => { result = "success" }
Status.Error(msg) => { result = "failed: {msg}" }
_ => { result = "unknown" }
}
// Loops
for item in collection {
process(item)
}
for i: i32 in 0..10 {
println("{i}")
}
while condition {
work()
}
fn add(a: i32, b: i32) -> i32 {
return a + b
}
fn greet(name: string) {
println("Hello, {name}!")
}
// Generic functions
fn max#[T: Ordered](a: T, b: T) -> T {
if a > b {
return a
}
return b
}
// Closures require explicit types and return
let double: fn(i32) -> i32 = |x: i32| -> i32 { return x * 2 }
let add: fn(i32, i32) -> i32 = |a: i32, b: i32| -> i32 { return a + b }
let process: fn(i32) -> i32 = |x: i32| -> i32 {
let y: i32 = x * 2
return y + 1
}
// With capturing
let factor: i32 = 10
let scale: fn(i32) -> i32 = |x: i32| -> i32 { return x * factor }
struct Point {
x: f64
y: f64
}
enum Option#[T] {
Some(T)
None
}
enum Message {
Quit
Move { x: i32, y: i32 }
Write(string)
}
// Optional types
let maybe: ?i32 = Some(42)
let value: i32 = maybe ?? 0 // default if None
let forced: i32 = maybe! // trap if None
// Result types with propagation
fn read_config() -> Result#[Config, Error] {
let content: string = read_file(path)? // propagate error
let parsed: Config = parse(content)?
return Ok(parsed)
}
let a: i32 = 2_000_000_000
let b: i32 = a + a // trap on overflow (default, safe)
let c: i32 = a +% a // wrapping arithmetic
let d: i32 = a +| a // saturating arithmetic
- Context-free grammar: Every construct is unambiguous without surrounding context
- Keyword-driven:
and/or/notvs&&/||/!eliminates symbol confusion - Consistent patterns: One way to do things, predictable structure
- Explicit semantics: No hidden behavior or implicit conversions
- Ownership model: Memory safety without garbage collection
- No null: Optional types (
?T) for nullable values - Bounds checking: Array access is checked by default
- Defined overflow: Choose trap, wrap, or saturate explicitly
- No header files: Single source of truth per module
- No preprocessor:
comptimefor compile-time computation - No function overloading: Use generics instead
- Minimal syntax: Fewer ways to express the same thing
Phase 4: Language Completion — Nearing Completion
| Phase | Status | Description |
|---|---|---|
| Phase 1: Tree-Walking Interpreter | ✅ Complete | Lexer, parser, type checker, interpreter |
| Phase 2: Bytecode VM | ✅ Complete | Bytecode compiler and virtual machine |
| Phase 3: Native Compiler | ✅ Complete | LLVM-based native code generation |
| Phase 4: Language Completion | 🟡 Nearing Completion | Generics, traits, modules, stdlib, FFI |
- ✅ LLVM backend with optimization levels (-O0 to -O3)
- ✅ Ownership-based memory management (no GC)
- ✅ Rc/Arc reference counting with automatic drop
- ✅ Closures with capture analysis
- ✅ Optional and Result types with
?operator - ✅ Debug info generation (-g flag)
- ✅ Cross-compilation support (--target flag)
- ✅ 252x speedup over VM for compute-bound code
- ✅ Generic functions, structs, and enums with monomorphization
- ✅ Trait definitions, implementations, bounds, and inheritance
- ✅ Builtin traits: Eq, Ordered, Clone, Drop, Hash, Default
- ✅ Associated types in traits
- ✅ Module system with imports and visibility
- ✅ Standard library core: List, Map, Set, String, Range
- ✅ Iterator protocol with for-loops and adapters
- ✅ Comptime (compile-time evaluation and reflection)
- ✅ Interactive REPL
- ✅ FFI (Foreign Function Interface) — Call C functions, use C types, link C libraries
- 🚧 Filesystem operations (Path, directory operations)
- 🚧 Package manager
- 🚧 Developer tooling (formatter, LSP)
See PLAN.md for implementation details and roadmap.
Requires Zig 0.15+ and LLVM 17+.
# Install LLVM (macOS)
brew install llvm
# Build the compiler
./run-build.sh
# Run tests
./run-tests.sh # Unit tests
./run-native-tests.sh # Native compilation tests
./run-benchmarks.sh # VM vs Native benchmarks# Run a Klar program using the bytecode VM
./zig-out/bin/klar run program.kl# Compile to native executable
./zig-out/bin/klar build program.kl -o program
# Run the compiled binary
./program
# With optimizations
./zig-out/bin/klar build program.kl -o program -O2
# With debug info (for lldb/gdb)
./zig-out/bin/klar build program.kl -o program -g
# Cross-compile for different architectures
./zig-out/bin/klar build program.kl --target x86_64-apple-macosx
./zig-out/bin/klar build program.kl --target aarch64-linux-gnu
# Emit LLVM IR or assembly
./zig-out/bin/klar build program.kl --emit-llvm # Outputs .ll file
./zig-out/bin/klar build program.kl --emit-asm # Outputs .s file| Flag | Description |
|---|---|
-O0 |
No optimizations (default, fastest compile) |
-O1 |
Basic optimizations (constant folding, DCE) |
-O2 |
Standard optimizations (recommended for release) |
-O3 |
Aggressive optimizations (may increase code size) |
The native compiler provides significant speedups over the bytecode VM:
| Benchmark | VM Time | Native Time | Speedup |
|---|---|---|---|
| fib(35) | ~14s | 0.05s | 259x |
| matrix | 0.03s | 0.02s | 1.6x |
| sort | 0.03s | 0.02s | 1.6x |
Run ./run-benchmarks.sh to see current benchmark results.
See the examples/ directory:
hello.kl— Hello Worldfibonacci.kl— Recursive Fibonaccifizzbuzz.kl— Classic FizzBuzz
See the benchmarks/ directory:
fib.kl— Recursive Fibonacci (compute-bound)matrix.kl— Matrix multiplicationsort.kl— Sorting simulationrc_stress.kl— Reference counting stress test
See the examples/apps/ directory for larger reference applications:
mandelbrot.kl— ASCII Mandelbrot set renderercollatz.kl— Collatz conjecture visualizerfibonacci.kl— Fibonacci sequence with bar chartarray_demo.kl— Array features demostruct_demo.kl— Structs and tuplesclosure_demo.kl— Closures and higher-order functionsoptional_demo.kl— Optional types (?T)result_demo.kl— Result types and error handlingrc_demo.kl— Reference counting (Rc/Arc)
.kl
MIT
Klar is designed by Claude Code for Claude Code.