01 / hello.zi
Hello, World!
The smallest complete program.
main :: () {
print("Hello, World!\n");
}build/bin/ziran bundle --root . --entry hello:main -o hello.zib site/examples/hello.zi
build/bin/ziran run hello.zib
# Hello, World!02 / greet.zi
Print values
Each % in a print format takes the next argument, and %% prints a percent sign.
main :: () {
name := "Ziran";
year: s32 = 2026;
print("Hello, %! It is %.\n", name, year);
print("% + % = %\n", 40, 2, 40 + 2);
print("pi is about %, and 100%% sure\n", 3.14159);
}build/bin/ziran bundle --root . --entry greet:main -o greet.zib site/examples/greet.zi
build/bin/ziran run greet.zib
# Hello, Ziran! It is 2026.
# 40 + 2 = 42
# pi is about 3.14159, and 100% sure03 / values.zi
Values
Integers, floats, booleans, and text.
main :: () {
print("text: %\n", "ziran");
print("1 + 1 = %\n", 1 + 1);
print("7.0 / 3.0 = %\n", 7.0 / 3.0);
print("true and false: %\n", true && false);
print("true or false: %\n", true || false);
print("not true: %\n", !true);
}build/bin/ziran bundle --root . --entry values:main -o values.zib site/examples/values.zi
build/bin/ziran run values.zib
# text: ziran
# 1 + 1 = 2
# 7.0 / 3.0 = 2.3333333333333335
# true and false: false
# true or false: true
# not true: false04 / variables.zi
Variables and constants
A declared type, an inferred type, a default zero value, and a compile-time constant.
LIMIT :: 100;
main :: () {
greeting: string = "initial";
print("%\n", greeting);
first: s32 = 1;
second: s32 = 2;
print("% %\n", first, second);
ready := true;
print("%\n", ready);
count: s32;
print("% (a variable starts at zero)\n", count);
fruit := "apple";
print("% and the limit is %\n", fruit, LIMIT);
}build/bin/ziran bundle --root . --entry variables:main -o variables.zib site/examples/variables.zi
build/bin/ziran run variables.zib
# initial
# 1 2
# true
# 0 (a variable starts at zero)
# apple and the limit is 10005 / functions.zi
Functions
Plain calls, default and named arguments, and recursion.
Add :: (a: s32, b: s32) -> s32 {
return a + b;
}
Greet :: (name: string, greeting: string = "Hello") {
print("%, %!\n", greeting, name);
}
Factorial :: (n: s64) -> s64 {
if n <= 1 { return 1; }
return n * Factorial(n - 1);
}
Fibonacci :: (n: s32) -> s32 {
if n < 2 { return n; }
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
main :: () {
print("1 + 2 = %\n", Add(1, 2));
Greet("Ziran");
Greet("world", greeting = "Goodbye");
print("10! = %\n", Factorial(10));
print("fibonacci(20) = %\n", Fibonacci(20));
}build/bin/ziran bundle --root . --entry functions:main -o functions.zib site/examples/functions.zi
build/bin/ziran run functions.zib
# 1 + 2 = 3
# Hello, Ziran!
# Goodbye, world!
# 10! = 3628800
# fibonacci(20) = 676506 / conditions.zi
Conditions
If and else chains, and an if-case that picks a branch by value.
Describe :: (number: s32) -> string {
if number < 0 {
return "negative";
} else if number == 0 {
return "zero";
}
return "positive";
}
DayKind :: (day: s32) -> string {
if day == {
case 6; return "weekend";
case 7; return "weekend";
}
return "weekday";
}
main :: () {
print("-4 is %\n", Describe(-4));
print("0 is %\n", Describe(0));
print("9 is %\n", Describe(9));
if 7 % 2 == 0 {
print("7 is even\n");
} else {
print("7 is odd\n");
}
print("day 3 is a %\n", DayKind(3));
print("day 6 is a %\n", DayKind(6));
}build/bin/ziran bundle --root . --entry conditions:main -o conditions.zib site/examples/conditions.zi
build/bin/ziran run conditions.zib
# -4 is negative
# 0 is zero
# 9 is positive
# 7 is odd
# day 3 is a weekday
# day 6 is a weekend07 / loops.zi
Loops
While, ranges, collections, break, and continue.
main :: () {
index: s32 = 1;
while index <= 3 {
print("while %\n", index);
index += 1;
}
for step: 0..2 {
print("range %\n", step);
}
fruits := string.["apple", "banana", "cherry"];
for fruit, position: fruits {
print("% is at %\n", fruit, position);
}
for number: 0..9 {
if number % 2 == 0 { continue; }
if number > 7 { break; }
print("odd %\n", number);
}
}build/bin/ziran bundle --root . --entry loops:main -o loops.zib site/examples/loops.zi
build/bin/ziran run loops.zib
# while 1
# while 2
# while 3
# range 0
# range 1
# range 2
# apple is at 0
# banana is at 1
# cherry is at 2
# odd 1
# odd 3
# odd 5
# odd 708 / arrays.zi
Arrays and slices
A fixed array, a view into part of it, and a sum.
Sum :: (numbers: []s32) -> s32 {
total: s32 = 0;
for numbers { total += it; }
return total;
}
main :: () {
empty: [5]s32;
print("empty: % % % % %\n", empty[0], empty[1], empty[2], empty[3], empty[4]);
numbers := s32.[1, 2, 3, 4, 5];
numbers[4] = 100;
print("set: %, count: %\n", numbers[4], numbers.count);
middle := numbers[1:4];
print("middle has % items starting with %\n", middle.count, middle[0]);
print("sum of all: %\n", Sum(numbers[:]));
print("sum of middle: %\n", Sum(middle));
}build/bin/ziran bundle --root . --entry arrays:main -o arrays.zib site/examples/arrays.zi
build/bin/ziran run arrays.zib
# empty: 0 0 0 0 0
# set: 100, count: 5
# middle has 3 items starting with 2
# sum of all: 110
# sum of middle: 909 / structs.zi
Structs
Records with fields, passed and returned by value.
Point :: struct {
x: s32;
y: s32;
}
Rectangle :: struct {
origin: Point;
width: s32;
height: s32;
}
Area :: (shape: Rectangle) -> s32 {
return shape.width * shape.height;
}
Grow :: (shape: Rectangle, amount: s32) -> Rectangle {
grown := shape;
grown.width += amount;
grown.height += amount;
return grown;
}
main :: () {
corner := Point.{x = 3, y = 4};
print("point: (%, %)\n", corner.x, corner.y);
box := Rectangle.{origin = corner, width = 10, height = 5};
print("area: %\n", Area(box));
box = Grow(box, 2);
print("grown: %x% with area %\n", box.width, box.height, Area(box));
copy := box;
copy.width = 1;
print("the copy is % wide, the original still %\n", copy.width, box.width);
}build/bin/ziran bundle --root . --entry structs:main -o structs.zib site/examples/structs.zi
build/bin/ziran run structs.zib
# point: (3, 4)
# area: 50
# grown: 12x7 with area 84
# the copy is 1 wide, the original still 1210 / enums.zi
Enums
Named values and a switch over them.
Shape :: enum {
CIRCLE;
SQUARE;
TRIANGLE;
}
Corners :: (shape: Shape) -> s32 {
if shape == {
case .CIRCLE; return 0;
case .SQUARE; return 4;
case .TRIANGLE; return 3;
}
return -1;
}
main :: () {
print("a circle has % corners\n", Corners(.CIRCLE));
print("a square has % corners\n", Corners(.SQUARE));
print("a triangle has % corners\n", Corners(.TRIANGLE));
}build/bin/ziran bundle --root . --entry enums:main -o enums.zib site/examples/enums.zi
build/bin/ziran run enums.zib
# a circle has 0 corners
# a square has 4 corners
# a triangle has 3 corners11 / text_basics.zi
Strings
Length, bytes, slices, and comparison.
CountByte :: (text: string, wanted: u8) -> s32 {
found: s32 = 0;
for byte: text {
if byte == wanted { found += 1; }
}
return found;
}
main :: () {
word := "banana";
print("% has % bytes\n", word, word.count);
print("the first byte is %\n", word[0]);
print("it contains % a's\n", CountByte(word, #char "a"));
print("its middle is %\n", word[1:5]);
print("equal to \"banana\": %\n", word == "banana");
print("equal to \"apple\": %\n", word == "apple");
}build/bin/ziran bundle --root . --entry text_basics:main -o text_basics.zib site/examples/text_basics.zi
build/bin/ziran run text_basics.zib
# banana has 6 bytes
# the first byte is 98
# it contains 3 a's
# its middle is anan
# equal to "banana": true
# equal to "apple": false12 / defer.zi
Defer
A deferred statement runs when its scope ends, last deferred first.
Work :: (name: string) {
print("open %\n", name);
defer print("close %\n", name);
print("use %\n", name);
}
main :: () {
defer print("done\n");
Work("file");
{
defer print("leave the block\n");
print("inside the block\n");
}
}build/bin/ziran bundle --root . --entry defer:main -o defer.zib site/examples/defer.zi
build/bin/ziran run defer.zib
# open file
# use file
# close file
# inside the block
# leave the block
# done13 / fizzbuzz.zi
FizzBuzz
Multiples of 3 print Fizz, of 5 Buzz, and of both FizzBuzz.
main :: () {
for number: 1..20 {
if number % 15 == 0 {
print("FizzBuzz\n");
} else if number % 3 == 0 {
print("Fizz\n");
} else if number % 5 == 0 {
print("Buzz\n");
} else {
print("%\n", number);
}
}
}build/bin/ziran bundle --root . --entry fizzbuzz:main -o fizzbuzz.zib site/examples/fizzbuzz.zi
build/bin/ziran run fizzbuzz.zib
# 1
# 2
# Fizz
# 4
# Buzz
# Fizz
# 7
# 8
# Fizz
# Buzz
# 11
# Fizz
# 13
# 14
# FizzBuzz
# 16
# 17
# Fizz
# 19
# Buzz14 / primes.zi
The Sieve of Eratosthenes
Cross out every multiple of each prime.
LIMIT :: 50;
main :: () {
composite: [LIMIT + 1]bool;
for number: 2..LIMIT {
if composite[number] { continue; }
print("% ", number);
multiple := number * number;
while multiple <= LIMIT {
composite[multiple] = true;
multiple += number;
}
}
print("\n");
}build/bin/ziran bundle --root . --entry primes:main -o primes.zib site/examples/primes.zi
build/bin/ziran run primes.zib
# 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 15 / score.zi
Model a score
Define a record, pass it to a procedure, and return the answer.
Score :: struct {
value: s32;
bonus: s32;
}
Total :: (score: Score) -> s32 {
return score.value + score.bonus;
}
Answer :: () -> s32 {
score: Score = Score.{value = 40, bonus = 2};
return Total(score);
}build/bin/ziran bundle --root . --entry score:Answer -o score.zib site/examples/score.zi
build/bin/ziran run score.zib
# 4216 / text_demo.zi
Use a standard module
Import the text module and test a prefix with ASCII case folding.
#import "text"
Answer :: () -> s32 {
if StartsWithFoldASCII("Ziran", "zi") {
return 1;
}
return 0;
}build/bin/ziran bundle --root . --module-path std --entry text_demo:Answer -o text_demo.zib site/examples/text_demo.zi
build/bin/ziran run text_demo.zib
# 117 / Native output
Generate native code
Every program above prints the same output on the portable runner and as C, C++, Go, Rust, and Python; tests/examples.sh checks it. For Rust, Go, and Python, --exe with an entry writes a runnable program. Go, Cargo, or Python 3.10 is needed only to run that output.
build/bin/ziran build --target=rust --exe --entry fizzbuzz:main --root . -o out/rust site/examples/fizzbuzz.zi
cargo run --manifest-path out/rust/Cargo.toml
build/bin/ziran build --target=go --pkg main --exe --entry fizzbuzz:main --root . -o out/go site/examples/fizzbuzz.zi
(cd out/go && go run .)
build/bin/ziran build --target=py --exe --entry fizzbuzz:main --root . -o out/py site/examples/fizzbuzz.zi
python3 out/pyC and C++ output mirrors the source path, here out/c/site/examples/fizzbuzz.c and its header, which declares fizzbuzz_main; call it from your program, or put #program_export before main to make the output a complete program. --target=plan9-c writes experimental Plan 9 C.
build/bin/ziran build --target=c --root . -o out/c site/examples/fizzbuzz.zi
build/bin/ziran build --target=cpp --root . -o out/cpp site/examples/fizzbuzz.ziNative and portable support can differ by feature. See the current status before choosing a target.