Examples

Learn GX by example. Each snippet is a complete, runnable program.

Basics

Hello World 01_hello_world.gx
// 01_hello_world.ec - The simplest EC program
// Build: ec examples/01_hello_world.ec -o build/01_hello_world.exe

fn main() {
    var a:i32  = 100;
    var b:i32 = 200;
    var name:str = "Afan";
    print("Hello, GXers!! {a} : {b} : {name}\n");
}
Variables 02_variables.gx
// 02_variables.ec - Variable declarations, types, and string interpolation
// Build: ec examples/02_variables.ec -o build/02_variables.exe

fn main() {
    // Type inference with var
    var a = 10;
    var b = 3.14;
    var name = "GX";

    // Explicit types
    var x:i32 = 100;
    var y:f32 = 2.718;
    var big:i64 = 9999999999;
    var precise:f64 = 3.14159265358979;

    // String interpolation
    print("a={a}\n");
    print("b={b}\n");
    print("name={name}\n");
    print("x={x} y={y}\n");
    print("big={big}\n");
    print("precise={precise}\n");

    print("i32 as string: " + x.str() + "\n");
    print("f64 as string: " + precise.str() + "\n");

    // Assignment
    x = x + 1;
    print("x after +1: {x}\n");
}
Print And Strings 03_print_and_strings.gx
// 03_print_and_strings.ec - Print, string concatenation, interpolation, UTF-8
// Build: ec examples/03_print_and_strings.ec -o build/03_print_and_strings.exe

fn main() {
    do_some()
    do_some1()
    // Basic print
    print("Hello GXers!\n");
    var s:str = "Family";
    // String concatenation with +
    var greeting = "Hello" + ", " + "GX {s}!!! \n";
    print(greeting)

    // String interpolation with {expr}
    var x:i32 = 42;


    var f:f32 = 3.14;
    print("int={x} float={f}\n");

    // .str() converts any type to string
    var v = vec3{1.0, 2.0, 3.0};
    print("vec3={v}\n");
    print("vec3 via concat: " + v.str() + "\n");

    // UTF-8 strings
    var utf = "Hello UTF-8: cafe\n";
    print(utf);

    // Escape sequences
    print("Tab:\there\n");
    print("Quote: \"hello\"\n");

    // String + number auto-converts
    print("result=" + (10 + 20).str() + "\n");
}

Data Types

Control Flow 04_control_flow.gx
// 04_control_flow.ec - If/elif/else, while loops, for-range, for-each, collect
// Build: ec examples/04_control_flow.ec -o build/04_control_flow.exe

fn main() {
    // --- If / elif / else ---
    var score:i32 = 75;
    var x:i32 = 10;

    print("Helloo\n");
    if (score >= 90) {
        print("Grade: A\n");
    } elif (score >= 80) {
        print("Grade: B\n");
    } elif (score >= 70) {
        print("Grade: C\n");
    } else {
        print("Grade: F\n");
    }

    // --- While loop ---
    var count:i32 = 0;
    while (count < 5) {
        print("count={count}\n");
        count = count + 1;
    }

    // --- For-range (inclusive) ---
    print("\nFor-range 1 to 5:\n");
    for (i = 1:5) {
        print("  i={i}\n");
    }

    // --- For-each over array ---
    print("\nFor-each:\n");
    var arr:i32[5] = {10, 20, 30, 40, 50};
    for (var x in arr) {
        print("  x={x}\n");
    }

    // --- For-each with where filter ---
    print("\nFiltered (even only):\n");
    var nums:i32[8] = {1, 2, 3, 4, 5, 6, 7, 8};
    for (var n in nums) where (n % 2 == 0) {
        print("  even={n}\n");
    }

    // --- Collect: build array from loop ---
    var evens = for (n in nums) where (n % 2 == 0) collect n;
    print("\nCollected evens ({evens.len()}):");
    for (i = 0:3) {
        print(" {evens.at(i)}");
    }

    print("\n");

    // Collect with transform
    var doubled = for (n in nums) where (n <= 4) collect n * 10;
    print("Doubled small ({doubled.len()}):");
    for (i = 0:3) {
        print(" {doubled.at(i)}");
    }
    print("\n");

    evens.free();
    doubled.free();
}
Arrays 05_arrays.gx
// 05_arrays.ec - Fixed-size arrays: declaration, init, iteration
// Build: ec examples/05_arrays.ec -o build/05_arrays.exe

fn main() {
    // Fixed-size array with initializer
    var scores:i32[5] = {95, 82, 74, 88, 91};

    var win:[]i32 = scores[0:3];

    print("Winners:\n");
    for (var s in win) {
        print(" win {s}\n");
    }

    // Array with inferred size
    var colors:f32[3] = {1.0, 0.0, 0.0};
    print("\nRGB: {colors[0]}, {colors[1]}, {colors[2]}\n");

    // Modify by index
    scores[0] = 100;
    print("\nUpdated first score: {scores[0]}\n");

    // Iterate with range
    print("\nAll scores after update:\n");
    for (i = 0:4) {
        print("  scores[{i}] = {scores[i]}\n");
    }
}
Dynamic Arrays 06_dynamic_arrays.gx
// 06_dynamic_arrays.ec - array<T> dynamic container: init, push, sort, remove, for-each
// Build: ec examples/06_dynamic_arrays.ec -o build/06_dynamic_arrays.exe

fn main() {
    // --- Static array for-each ---
    print("Static array\n");
    var week_days:str[7] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
    for (item:str in week_days) {
        print("Day: {item}\n");
    }

    // --- Dynamic array with initializer syntax ---
    print("\nDynamic array (initializer syntax)\n");
    var darr:array<str> = {"Afan", "Sanela", "Ajdin"};
    defer darr.free();

    // For-each works on dynamic arrays
    for (var item in darr) {
        print("  item: {item}\n");
    }

    // Multiple iterations work fine
    print("\nSecond iteration with index:\n");
    var cnt = 0;
    for (var item in darr) {
        print("  [{cnt}] {item}\n");
        cnt = cnt + 1;
    }

    // Index-based loop also works
    print("\nIndex-based loop:\n");
    for (j = 0:darr.len()-1) {
        print("  {darr.at(j)}\n");
    }

    // --- Dynamic array without initializer (auto-init) ---
    var a:array<i32>;
    defer a.free();

    // Push elements
    a.push(30);
    a.push(10);
    a.push(50);
    a.push(20);
    a.push(40);
    print("\nAfter push: len={a.len()} cap={a.cap()}\n");

    // Access elements
    print("a[0]={a.at(0)} a[1]={a.at(1)} a[2]={a.at(2)}\n");

    // For-each over i32 dynamic array
    print("\nFor-each over i32 array:\n");
    for (var n in a) {
        print("  {n}\n");
    }

    // Sort
    a.sort();
    print("\nAfter sort:\n");
    for (var n in a) {
        print("  {n}\n");
    }

    // Remove (swap with last - O(1))
    a.remove_swap(0);
    print("\nAfter remove_swap(0): len={a.len()}\n");
    for (var n in a) {
        print("  {n}\n");
    }

    // Clear
    a.clear();
    print("\nAfter clear: len={a.len()}\n");

    // --- Collect: create dynamic array from loop ---
    var data:i32[6] = {5, 12, 3, 18, 7, 20};
    var big = for (x in data) where (x >= 10) collect x;
    print("\nCollected (>= 10): ");
    for (var n in big) {
        print("{n} ");
    }
    print("(len={big.len()})\n");
    big.free();

    print("\nDone.\n");
}
Structs 07_structs.gx
// 07_structs.ec - Structs, field access, extension methods
// Build: ec examples/07_structs.ec -o build/07_structs.exe

struct Player {
    id:i32
    name:str
    score:f32
}

ex Player {
    fn greet() {
        print("Player {name} (id={id}) score={score}\n");
    }

    fn add_score(points:f32) {
        score = score + points;
    }
}

struct Vec2i {
    x:i32
    y:i32
}

ex Vec2i {
    fn to_str:str() {
        return "({x}, {y})";
    }
}

fn main() {
    // Create with initializer
    var p = Player{1, "Alice", 0.0};
    p.greet();

    // Modify via extension method
    p.add_score(100.5);
    p.add_score(50.0);
    p.greet();

    // Direct field access
    p.name = "Bob";
    print("Renamed to: {p.name}\n");

    // Custom struct with str conversion
    var pos = Vec2i{10, 20};
    print("Position: " + pos.to_str() + "\n");
}
Enums 08_enums.gx
// 08_enums.ec - Enums: declaration, comparison, branching
// Build: ec examples/08_enums.ec -o build/08_enums.exe

enum Direction {
    North
    South
    East
    West
}

enum Color {
    Red = 0
    Green = 1
    Blue = 2
}

fn main() {
    // Declare enum variables
    var dir:Direction = East;

    // Compare enum values
    if (dir == North) {
        print("Heading North\n");
    } elif (dir == East) {
        print("Heading East\n");
    } elif (dir == South) {
        print("Heading South\n");
    } else {
        print("Heading West\n");
    }

    // Enum to string (shows integer value)
    print("East = {dir}\n");

    // Another enum
    var c:Color = Blue;
    print("Blue = {c}\n");
}

Functions & Control

Vec Mat Math 09_vec_mat_math.gx
// 09_vec_mat_math.ec - Built-in vector and matrix types
// Build: ec examples/09_vec_mat_math.ec -o build/09_vec_mat_math.exe

fn main() {
    // --- Vectors ---
    var a = vec3{1.0, 2.0, 3.0};
    var b = vec3{4.0, 5.0, 6.0};

    // Vector addition
    var c = a + b;
    print("a + b = {c}\n");

    // Scalar multiply
    var d = a * 2.0;
    print("a * 2 = {d}\n");

    // Negate
    var e = -a;

    var len = 32;
    for (i=0:len) {
        print("i = {i}\n");
    }

    print("-a = {e}\n");

    // Field access
    print("a.x={a.x} a.y={a.y} a.z={a.z}\n");

    // --- vec2 and vec4 ---
    var v2 = vec2{10.0, 20.0};
    print("vec2: {v2}\n");

    var v4 = vec4{1.0, 0.0, 0.0, 1.0};
    print("vec4: {v4}\n");

    // --- Swizzle ---
    var sw1 = a.xy;
    print("a.xy = {sw1}\n");

    var sw2 = a.zyx;
    print("a.zyx = {sw2}\n");

    var sw3 = v4.wz;
    print("v4.wz = {sw3}\n");

    var sw4 = v2.yx;
    print("v2.yx = {sw4}\n");

    // Repeat components
    var sw5 = a.xx;
    print("a.xx = {sw5}\n");

    // --- Matrix ---
    var M = mat4{
        vec4{1,0,0,0},
        vec4{0,1,0,0},
        vec4{0,0,1,0},
        vec4{0,0,0,1},
    };
    print("Identity: {M}\n");
}
Functions 10_functions.gx

// 10_functions.ec - Functions, return types, recursion
// Build: ec examples/10_functions.ec -o build/10_functions.exe

fn add:i32(a:i32, b:i32) {
    return a + b;
}

fn larger:i32(a:i32, b:i32) {
    if (a > b) {
        return a;
    }
    return b;
}

fn factorial:i32(n:i32) {
    if (n <= 1) {
        return 1;
    }
    return n * factorial(n - 1);
}

fn greet(name:str) {
    print("Hello, {name}!\n");
}

fn main() {
    // Basic function calls
    var sum = add(10, 20);
    print("add(10, 20) = {sum}\n");

    var m = larger(42, 17);
    print("larger(42, 17) = {m}\n");

    // Recursion
    for (i = 1:8) {
        print("{i}! = {factorial(i)}\n");
    }

    // Void function
    greet("EC");
}
Bool 11_bool.gx
// 11_bool.ec - Boolean literals: true and false
// Build: ec examples/11_bool.ec -o build/11_bool.exe

fn main() {
    var a:bool = true;
    var b:bool = false;

    print("a = {a}\n");
    print("b = {b}\n");

    if (a) {
        print("a is true\n");
    }

    if (!b) {
        print("b is false\n");
    }

    // Boolean logic
    var c = a && b;
    var d = a || b;
    print("true && false = {c}\n");
    print("true || false = {d}\n");

    // Comparison produces bool
    var x = 5;
    var gt = x > 3;
    print("5 > 3 = {gt}\n");

    // Use in conditions directly
    var done = false;
    var count = 0;
    while (!done) {
        count = count + 1;
        if (count == 3) {
            done = true;
        }
    }
    print("counted to {count}\n");
}
Input 12_input.gx
// Example: input() built-in function
// Reads a line from stdin, with an optional prompt string.

fn main() {
    var name:str = input("What is your name? ");
    print("Hello, {name}!\n");

    var color:str = input("Favorite color? ");
    print("{name} likes {color}\n");

    // input() with no prompt
    print("Type something: ");
    var line:str = input();
    print("You said: {line}\n");
}
Bitwise 13_bitwise.gx
// 13_bitwise.ec - Bitwise operators and hex literals
// Build: ec examples/13_bitwise.ec -o build/13_bitwise.exe

fn main() {
    // --- Hex literals ---
    var a:i32 = 0xFF;
    var b:i32 = 0x0F;
    var c:i32 = 0x0A;

    print("Hex literals: a=0xFF={a}, b=0x0F={b}\n");

    // --- Bitwise AND ---
    var and_result:i32 = a & b & c;
    print("\nBitwise AND: 0xFF & 0x0F = {and_result}\n");

    // --- Bitwise OR ---
    var or_result:i32 = 0xF0 | 0x0F;
    print("Bitwise OR:  0xF0 | 0x0F = {or_result}\n");

    // --- Bitwise XOR ---
    var xor_result:i32 = 0xFF ^ 0x0F;
    print("Bitwise XOR: 0xFF ^ 0x0F = {xor_result}\n");

    // --- Bitwise NOT ---
    var not_result:i32 = ~0;
    print("Bitwise NOT: ~0 = {not_result}\n");

    // --- Left shift ---
    var lshift:i32 = 1 << 4;
    print("Left shift:  1 << 4 = {lshift}\n");

    // --- Right shift ---
    var rshift:i32 = 256 >> 3;
    print("Right shift: 256 >> 3 = {rshift}\n");

    // --- Flags pattern ---
    print("\n--- Flags pattern ---\n");
    var FLAG_READ:u32  = 1 << 0;
    var FLAG_WRITE:u32 = 1 << 1;
    var FLAG_EXEC:u32  = 1 << 2;

    var perms:u32 = FLAG_READ | FLAG_EXEC;
    print("Permissions: {perms}\n");
    print("Has READ:  {perms & FLAG_READ}\n");
    print("Has WRITE: {perms & FLAG_WRITE}\n");
    print("Has EXEC:  {perms & FLAG_EXEC}\n");

    // Add write permission
    perms = perms | FLAG_WRITE;
    print("\nAfter adding WRITE: {perms}\n");
    print("Has WRITE: {perms & FLAG_WRITE}\n");

    // Remove exec permission (AND with inverted flag)
    perms = perms & ~FLAG_EXEC;
    print("\nAfter removing EXEC: {perms}\n");
    print("Has EXEC: {perms & FLAG_EXEC}\n");

    // Toggle read with XOR
    perms = perms ^ FLAG_READ;
    print("\nAfter toggling READ: {perms}\n");
    print("Has READ: {perms & FLAG_READ}\n");

    // --- Byte extraction ---
    print("\n--- Byte extraction ---\n");
    var val:i32 = 0xABCD;
    var low:i32 = val & 0xFF;
    var high:i32 = (val >> 8) & 0xFF;
    print("0xABCD low byte:  {low}\n");
    print("0xABCD high byte: {high}\n");

    // --- Bit counting (popcount) ---
    print("\n--- Bit counting ---\n");
    var num:i32 = 0xFF;
    var count:i32 = 0;
    var tmp:i32 = num;
    for (i = 0:31) {
        if (tmp & 1) {
            count = count + 1;
        }
        tmp = tmp >> 1;
    }
    print("Bits set in 0xFF: {count}\n");

    // --- Power of two check ---
    print("\n--- Power of two check ---\n");
    var vals:i32[6] = {1, 2, 3, 4, 16, 255};
    for (var v in vals) {
        var is_pow2:i32 = 0;
        if (v & (v - 1)) {
            is_pow2 = 0;
        } else {
            is_pow2 = 1;
        }
        print("{v} is power of 2: {is_pow2}\n");
    }

    print("\nDone.\n");
}

Advanced Features

Break Continue 21_break_continue.gx
// Break and Continue example

fn main() {
    // Break: exit loop early
    print("Break test: ");
    for (i = 0:20) {
        if (i > 4) {
            break;
        }
        print("{i} ");
    }
    print("\n");

    // Continue: skip even numbers
    print("Continue test: ");
    for (i = 0:10) {
        if (i % 2 == 0) {
            continue;
        }
        print("{i} ");
    }
    print("\n");

    var a:i32 = 10;
    a++;
    a--;
    ++a;
    --a;
    print("a={a}\n");
    // Break in while loop
    print("While break: ");
    var n:i32 = 0;
    while (n < 100) {
        if (n > 5) {
            break;
        }
        print("{n} ");
        n = n + 1;
    }
    print("\n");

    // Continue in while loop
    print("While continue: ");
    var m:i32 = 0;
    while (m < 10) {
        m = m + 1;
        if (m % 3 == 0) {
            continue;
        }
        print("{m} ");
    }
    print("\n");
}
Match 21_match.gx
// 21_match.ec - Match statement: clean multi-way branching
// Build: ec examples/21_match.ec -o build/21_match.exe

// Test 1: Match on integer with single values
fn test_int() {
    var x:i32 = 2;
    match (x) {
        1: print("one\n")
        2: print("two\n")
        3: print("three\n")
        default: print("other\n")
    }
}

// Test 2: Match with comma-separated patterns
fn test_comma() {
    var code:i32 = 5;
    match (code) {
        1, 2, 3: print("low\n")
        4, 5, 6: print("mid\n")
        7, 8, 9: print("high\n")
        default: print("out of range\n")
    }
}

// Test 3: Match with range
fn test_range() {
    var score:i32 = 85;
    match (score) {
        0..59: print("F\n")
        60..69: print("D\n")
        70..79: print("C\n")
        80..89: print("B\n")
        90..100: print("A\n")
        default: print("invalid\n")
    }
}

// Test 4: Match on enum
enum Color { Red Green Blue }

fn test_enum() {
    var c:Color = Green;
    match (c) {
        Red: print("red\n")
        Green: print("green\n")
        Blue: print("blue\n")
    }
}

// Test 5: Match with block body
fn test_block() {
    var n:i32 = 3;
    match (n) {
        1: {
            print("one ");
            print("(single)\n");
        }
        2, 3: {
            print("two or three ");
            print("(group)\n");
        }
        default: print("other\n")
    }
}

fn main() {
    print("--- int match ---\n");
    test_int();
    print("--- comma match ---\n");
    test_comma();
    print("--- range match ---\n");
    test_range();
    print("--- enum match ---\n");
    test_enum();
    print("--- block match ---\n");
    test_block();
}
Func Ptr 22_func_ptr.gx
// Function pointer validation test

fn add:i32(a:i32, b:i32) {
    return a + b;
}

fn negate:i32(x:i32) {
    return 0 - x;
}

fn apply:i32(f:fn(i32):i32, val:i32) {
    return f(val);
}

fn main() {
    // Valid: assign function matching signature
    var op:fn(i32, i32):i32 = add;
    print("add(3,4) = {op(3, 4)}\n");

    // Valid: pass function pointer as argument
    var result:i32 = apply(negate, 42);
    print("negate(42) = {result}\n");

    // Call through function pointer
    var f:fn(i32):i32 = negate;
    print("f(10) = {f(10)}\n");
}
Increment 23_increment.gx
// Increment and Decrement operators

fn main() {
    // Postfix
    var a:i32 = 5;
    a++;
    print("a++ => {a}\n");

    var b:i32 = 10;
    b--;
    print("b-- => {b}\n");

    var h1:i32 = b<11?10:20;
    print("h={h1}\n");
    // Prefix
    var c:i32 = 0;
    ++c;
    ++c;
    ++c;
    c++;
    --c;
    c--;
    print("++c x3 => {c}\n");

    // Prefix vs postfix in expressions
    var e:i32 = 5;
    var f:i32 = e++;
    print("postfix: e={e}, f={f}\n");

    var g:i32 = 5;
    var h:i32 = ++g;
    print("prefix:  g={g}, h={h}\n");
}
Union 24_union.gx
// Example 24: Union Types
// Unions allow multiple fields to share the same memory — only one is valid at a time.
// Use cases: type punning, variant storage, memory-efficient tagged unions.

// --- Basic union: type punning ---
union IntFloat {
    i: i32
    f: f32
}

// --- Tagged union pattern: manual tag + union ---
enum ValueKind {
    IntVal
    FloatVal
    StrVal
}

union ValueData {
    i: i32
    f: f32
    s: str
}

union Actor {
    id:i32
    name:str
}

struct Value {
    kind: ValueKind
    data: ValueData
}

fn print_value(v: Value) {
    match (v.kind) {
        IntVal:   print("int: {v.data.i}\n")
        FloatVal: print("float: {v.data.f}\n")
        StrVal:   print("str: {v.data.s}\n")
    }
}

// --- Color as packed bytes ---
union Color {
    rgba: u32
    bytes: u8[4]
}

fn main() {
    // Type punning: reinterpret i32 bits as f32
    var pun: IntFloat;
    pun.i = 1065353216;  // IEEE 754 for 1.0f
    print("int bits: {pun.i}\n");
    print("as float: {pun.f}\n");

    // Tagged union: variant storage
    var v1: Value;
    v1.kind = IntVal;
    v1.data.i = 42;
    print_value(v1);

    var v2: Value;
    v2.kind = FloatVal;
    v2.data.f = 3.14;
    print_value(v2);

    var v3: Value;
    v3.kind = StrVal;
    v3.data.s = "hello";
    print_value(v3);

    // Packed color: write as u32, read bytes
    var c: Color;
    c.rgba = 0xFF8040FF;
    print("color rgba: {c.rgba}\n");
}
Fat Str 25_fat_str.gx
// Example 25: Fat Strings (ec_str)
// str is now { ptr, len } — O(1) length, proper comparison, safe iteration.

fn main() {
    // Basic str with .len and .cstr
    var s: str = "hello";
    print("s = {s}\n");
    print("s.len = {s.len}\n");

    // String comparison (uses ec_str_eq, not pointer comparison!)
    var a: str = "hello";
    var b: str = "hello";
    var c: str = "world";

    if (a == b) {
        print("a == b: true (correct!)\n");
    }
    if (a != c) {
        print("a != c: true (correct!)\n");
    }

    // String concatenation
    var greeting: str = "Hello, " + "EC!";
    print("greeting = {greeting}\n");
    print("greeting.len = {greeting.len}\n");

    // String interpolation
    var x: i32 = 42;
    var msg: str = "The answer is {x}";
    print("{msg}\n");

    // Empty string
    var empty: str = "";
    print("empty.len = {empty.len}\n");

    // Escape sequences — sizeof handles them correctly
    var newline: str = "a\nb";
    print("newline.len = {newline.len}\n");

    print("\nAll fat string tests passed!\n");
}
Sort 25_sort.gx
// 25_sort.ec - Sort on all container types: fixed array, slice, array<T>
// Build: ec examples/25_sort.ec -o build/25_sort.exe

fn print_arr(label: str, s: []i32) {
    print("{label}: ");
    for (var x in s) {
        print("{x} ");
    }
    print("\n");
}

fn main() {
    // === Fixed array sort ===
    var fixed:i32[6] = {42, 7, 99, 3, 55, 1};
    print_arr("before fixed", fixed);
    fixed.sort();
    print_arr("after  fixed", fixed);

    // === Slice sort ===
    var data:i32[8] = {80, 20, 60, 10, 90, 40, 70, 30};
    var sl:[]i32 = data[2:6];

    print_arr("before slice", sl);
    sl.sort();

    print_arr("after  slice", sl);
    print_arr("full   data ", data);

    // === Dynamic array sort ===
    var dyn:array<i32>;
    dyn.init();
    dyn.push(33);
    dyn.push(11);
    dyn.push(77);
    dyn.push(22);
    dyn.push(55);

    // print via slice
    var ds:[]i32 = dyn;
    print_arr("before dyn  ", ds);
    dyn.sort();

    var ds2:[]i32 = dyn;
    print_arr("after  dyn  ", ds2);
    dyn.free();
}
Sizeof 26_sizeof.gx
// sizeof expression examples

struct Point {
    x: f32
    y: f32
}

struct Color {
    r: u8
    g: u8
    b: u8
    a: u8
}

fn main() {
    // sizeof with built-in types
    print("sizeof(i8)    = {sizeof(i8)}\n");
    print("sizeof(i16)   = {sizeof(i16)}\n");
    print("sizeof(i32)   = {sizeof(i32)}\n");
    print("sizeof(i64)   = {sizeof(i64)}\n");
    print("sizeof(f32)   = {sizeof(f32)}\n");
    print("sizeof(f64)   = {sizeof(f64)}\n");
    print("sizeof(bool)  = {sizeof(bool)}\n");

    // sizeof with user-defined structs (via expression)
    var p:Point = Point{1.0, 2.0};
    print("sizeof(Point) = {sizeof(p)}\n");

    var c:Color = Color{255, 128, 0, 255};
    print("sizeof(Color) = {sizeof(c)}\n");

    // sizeof with vec types
    print("sizeof(vec2)  = {sizeof(vec2)}\n");
    print("sizeof(vec3)  = {sizeof(vec3)}\n");
    print("sizeof(vec4)  = {sizeof(vec4)}\n");

    // sizeof in expressions
    var arr_size:i64 = 10 * sizeof(i32);
    print("10 * sizeof(i32) = {arr_size}\n");
}
Slice 26_slice.gx
// Example 26: Slices and Safe Arrays
// Arrays automatically have .len and work like slices.

fn sum:i32(data: []i32) {
    var total: i32 = 0;
    for (var x in data) {
        total += x;
    }
    return total;
}

fn print_slice(data: []i32) {
    print("[");
    for (var x in data) {
        print("{x} ");
    }
    print("]\n");
}

fn main() {
    var arr: i32[5] = {10, 20, 30, 40, 50};

    // Arrays have .len — compile-time constant, no struct needed
    print("arr.len = {arr.len}\n");

    // Arrays implicitly convert to slices at function boundaries
    print("sum(arr) = {sum(arr)}\n");
    print("arr = ");
    print_slice(arr);

    // Subslicing works directly on arrays
    var mid: []i32 = arr[1:4];
    print("arr[1:4] = ");
    print_slice(mid);
    print("mid.len = {mid.len}\n");

    // Slices work the same way
    var s: []i32 = arr;
    print("s[0] = {s[0]}\n");
    print("s.len = {s.len}\n");

    // Subslice of subslice
    var inner: []i32 = mid[0:2];
    print("inner = ");
    print_slice(inner);

    print("\nAll tests passed!\n");
}
Bounds Check 27_bounds_check.gx
// Example 27: Bounds Checking
// Out-of-bounds access panics in debug mode (default).
// Use -O1 or higher to disable checks for release builds.

fn main() {
    // Fixed array bounds check
    var arr: i32[3] = {10, 20, 30};
    print("arr[0] = {arr[0]}\n");
    print("arr[2] = {arr[2]}\n");
    print("arr.len = {arr.len}\n");

    // Slice bounds check
    var s: []i32 = arr;
    print("s[0] = {s[0]}\n");
    print("s[2] = {s[2]}\n");

    // This will PANIC:
    print("About to access s[10]...\n");
    print("s[10] = {s[10]}\n");
    print("This should never print!\n");
}
Const 28_const.gx
// Example 28: Const declarations and constant folding

// Global constants (no type annotation - inferred)
const PI = 3.14159265358979;
const TAU = PI * 2.0;
const SCREEN_WIDTH = 1920;
const SCREEN_HEIGHT = 1080;
const ASPECT_RATIO = 16.0 / 9.0;

// Global constants with type annotation
const MAX_ENTITIES:i32 = 1024;
const BUFFER_SIZE:i64 = MAX_ENTITIES * 64;

// Const expressions with bitwise ops
const FLAG_READ = 1;
const FLAG_WRITE = 2;
const FLAG_EXEC = 4;
const FLAG_ALL = FLAG_READ | FLAG_WRITE | FLAG_EXEC;

// Boolean consts
const DEBUG_MODE = false;
const IS_WIDE = SCREEN_WIDTH > 1000;


fn main() {
    print("=== Const Declarations ===");
    // Using global consts
    print("PI = {PI}");
    print("TAU = {TAU}");
    print("Screen: {SCREEN_WIDTH}x{SCREEN_HEIGHT}");
    print("Aspect ratio: {ASPECT_RATIO}");
    print("Max entities: {MAX_ENTITIES}");
    print("Buffer size: {BUFFER_SIZE}");

    print("");
    print("=== Const Folding ===");

    // Const folding: these should be computed at compile time
    const AREA = SCREEN_WIDTH * SCREEN_HEIGHT;
    print("Screen area: {AREA}");

    const HALF_PI = PI / 2.0;
    print("PI/2 = {HALF_PI}");

    // Bitwise const
    print("FLAG_ALL = {FLAG_ALL}");

    // Boolean const
    print("Debug mode: {DEBUG_MODE}");
    print("Is wide: {IS_WIDE}");

    print("");
    print("=== Const in Expressions ===");

    // Const used in regular expressions
    var x = SCREEN_WIDTH / 2;
    var y = SCREEN_HEIGHT / 2;
    print("Center: ({x}, {y})");

    // Const in loop bounds
    const LOOP_COUNT = 5;
    for (i=0:LOOP_COUNT) {
        print("  i = {i}");
    }

    print("");
    print("=== Negative and Unary ===");
    const NEG_ONE = -1;
    const NOT_FLAG = ~FLAG_READ;
    print("NEG_ONE = {NEG_ONE}");
    print("~FLAG_READ = {NOT_FLAG}");

    print("Done!");
}

Compile-Time

Comptime If 29_comptime_if.gx
// Example 29: Compile-time conditional compilation (#if)

// Platform detection with @os
#if (@os == "windows") {
    const PLATFORM = "Windows";
}
#else {
    const PLATFORM = "Other";
}

fn main() {
    print("Platform: {PLATFORM}");

    // Statement-level #if with @os
    #if (@os == "windows") {
        print("Running on Windows");
    }
    #else {
        print("Running on non-Windows");
    }

    // #if with user const
    const ENABLE_FEATURE = true;
    #if (ENABLE_FEATURE) {
        print("Feature enabled");
    }

    // @debug check (false unless --debug flag)
    #if (@debug) {
        print("Debug mode ON");
    }
    #else {
        print("Debug mode OFF");
    }

    // @opt level check
    #if (@opt > 0) {
        print("Optimized build");
    }
    #else {
        print("Unoptimized build");
    }

    print("Done!");
}
Comptime Fn 30_comptime_fn.gx
// Example 30: Compile-time functions (#fn)

// Align a size up to the given alignment
#fn align_up:i32(size:i32, align:i32) {
    return (size + align - 1) & ~(align - 1);
}

// Create a bitmask with N bits set
#fn make_bitmask:i32(bits:i32) {
    if (bits <= 0) { return 0; }
    if (bits >= 32) { return -1; }
    return (1 << bits) - 1;
}

// Compile-time fibonacci
#fn fib:i32(n:i32) {
    if (n <= 1) { return n; }
    return fib(n - 1) + fib(n - 2);
}

// Compile-time max
#fn max:i32(a:i32, b:i32) {
    if (a > b) { return a; }
    return b;
}

// Compile-time power
#fn pow:i32(base:i32, exp:i32) {
    var result:i32 = 1;
    var i:i32 = 0;
    while (i < exp) {
        result = result * base;
        i = i + 1;
    }
    return result;
}

// All evaluated at compile time — no runtime computation!
const BUF_SIZE = align_up(100, 64);
const CHANNEL_MASK = make_bitmask(8);
const PIXEL_MASK = make_bitmask(24);
const FIB_10 = fib(10);
const MAX_DIM = max(1920, 1080);
const TWO_TO_10 = pow(2, 10);
const COMBINED = align_up(FIB_10, 16);

fn main() {
    print("=== Compile-Time Functions (#fn) ===");
    print("align_up(100, 64) = {BUF_SIZE}");
    print("make_bitmask(8)   = {CHANNEL_MASK}");
    print("make_bitmask(24)  = {PIXEL_MASK}");
    print("fib(10)           = {FIB_10}");
    print("max(1920, 1080)   = {MAX_DIM}");
    print("pow(2, 10)        = {TWO_TO_10}");
    print("align_up(fib(10), 16) = {COMBINED}");
    print("Done!");
}
Comptime For 31_comptime_for.gx
// Example 31: Compile-time loop unrolling with #for
// #for unrolls the loop at compile time, substituting the iteration
// variable with literal integer values. No runtime loop overhead.

fn main() {
    // Basic #for — unrolls to 5 print calls
    print("=== Compile-Time Loop Unrolling (#for) ===");

    #for (i=0:5) {
        print("iteration {i}");
    }

    // #for with expressions using the loop variable
    var sum:i32 = 0;
    #for (i=1:6) {
        sum += i * i;
    }
    print("sum of squares 1..5 = {sum}");

    // Nested #for — generates 3x3 = 9 iterations
    #for (row=0:3) {
        #for (col=0:3) {
            var val:i32 = row * 3 + col;
            print("  ({row},{col}) = {val}");
        }
    }

    // #for with const bounds
    const N = 4;
    #for (i=0:N) {
        print("channel {i}");
    }

    print("Done!");
}
Struct Comptime 32_struct_comptime.gx
// Example 32: Struct and Enum level comptime expansion (Phase 5)

// Struct with conditional fields based on platform
struct PlatformInfo {
    name: str
    #if (@os == "windows") {
        handle: i64
        registry_key: str
    } #else {
        fd: i32
        path: str
    }
    version: i32
}

// Struct with generated fields via #for
struct Pixel {
    #for (i=0:4) {
        channel_i: f32
    }
}

// Enum with conditional members
enum LogLevel {
    Error
    Warning
    Info
    #if (@debug) {
        Debug
        Trace
    }
}

fn main() {
    print("=== Struct/Enum Comptime Expansion (Phase 5) ===");

    // PlatformInfo has platform-specific fields
    var info: PlatformInfo;
    info.name = "test";
    info.version = 1;
    info.handle = 42;
    info.registry_key = "HKLM";
    print("name = {info.name}");
    print("version = {info.version.str()}");
    print("handle = {info.handle.str()}");
    print("registry_key = {info.registry_key}");

    // Pixel has channel_0 through channel_3 (generated by #for)
    var px: Pixel;
    px.channel_0 = 1.0;
    px.channel_1 = 0.5;
    px.channel_2 = 0.25;
    px.channel_3 = 1.0;
    print("pixel = ({px.channel_0.str()}, {px.channel_1.str()}, {px.channel_2.str()}, {px.channel_3.str()})");

    // LogLevel enum — Debug/Trace only exist in debug builds
    var level: LogLevel = Error;
    print("log level = {level.str()}");

    print("Done!");
}
Reflection 33_reflection.gx
// Example 33: Compile-time reflection (Phase 6)

struct Point {
    x: f32
    y: f32
    z: f32
}

struct Node {
    value: i32
    next: *Node
}

enum Color { Red  Green  Blue }

fn main() {
    print("=== Compile-Time Reflection (Phase 6) ===\n");

    // --- Struct field reflection ---
    print("Point has {@fields(Point)} fields:\n");
    #for (i=0:@fields(Point)) {
        print("  {@field(Point, i)}: {@field_type(Point, i)}\n");
    }

    // --- Field detail intrinsics ---
    print("Node has {@fields(Node)} fields:");
    #for (i=0:@fields(Node)) {
        print("  {@field(Node, i)}: ptr={@field_is_ptr(Node, i)}\n");
    }

    // --- Enum member reflection ---
    print("Color has {@members(Color)} members:\n");
    #for (i=0:@members(Color)) {
        print("  {@member(Color, i)}");
    }

    // --- Type meta ---
    print("@type_kind(Point) = {@type_kind(Point)}\n");
    print("@type_kind(Color) = {@type_kind(Color)}\n");
    print("@type_name(Point) = {@type_name(Point)}\n");

    // Note: Function reflection (@params, @param, @return_type) works
    // but requires multi-file module setup (single-file function
    // declarations have a pre-existing resolver limitation)

    print("Done!");
}
Build Directives 34_build_directives.gx
// Example 34: Build directives (Phase 7)
// @link, @cflags, @ldflags make .ec files self-contained.

// Build directives — these inject linker/compiler flags without CLI args
@link("ucrtbase")

// Platform-conditional linking via #if
#if (@os == "windows") {
    @link("kernel32")
}

fn main() {
    print("=== Build Directives (Phase 7) ===");
    print("@link and @cflags are collected from source");
    print("No CLI flags needed for linking!");
    print("Done!");


}
Templates 35_templates.gx
// Example 35: Compile-time templates (Phase 8)
// #type T declares a type parameter — monomorphized at compile time.

#type T
struct Pair {
    first: T
    second: T
}

fn main() {
    print("=== Compile-Time Templates (Phase 8) ===");

    // Pair<i32> — generates struct Pair_i32 { int32_t first; int32_t second; }
    var pi: Pair<i32>;
    pi.first = 10;
    pi.second = 20;
    print("Pair<i32>: ({pi.first.str()}, {pi.second.str()})");

    // Pair<i64> — generates struct Pair_i64 { int64_t first; int64_t second; }
    var pl: Pair<i64>;
    pl.first = 100;
    pl.second = 200;
    print("Pair<i64>: ({pl.first.str()}, {pl.second.str()})");

    var pf: Pair<f32>;
    pf.first = 100.32;
    pf.second = 200.32;
    print("Pair<f32>: ({pf.first.str()}, {pf.second.str()})");

    var ps: Pair<str>;
    ps.first = "Afan";
    ps.second = "Olovcic";
    print("Pair<f32>: ({ps.first.str()}, {ps.second.str()})");
    {
        var ps:Pair< str >;
        ps.first = "Sanela";
        ps.second = "Gluhovic";
        print("Pair<f32>: ({ps.first.str()}, {ps.second.str()})");
    }
    print("Done!");
}

Standard Library

Pointers 36_pointers.gx
// Example 36: Pointer arithmetic

fn main() {
    print("=== Pointer Arithmetic ===");

    // Basic dereference
    var x:i32 = 42;
    var p:*i32 = &x;
    print("*p = {(*p).str()}");
    *p = 99;
    print("after *p=99: x = {x.str()}#\n");

    // Pointer arithmetic: take address, add offset
    var a:i32 = 10;
    var b:i32 = 20;
    var c:i32 = 30;

    a+=10;
    a++;

    a+=0xFF;

    var pa:*i32 = &a;
    // Test pointer + int type
    var pb:*i32 = pa + 1;
    print("pa+1 deref = {(*pb).str()}");

    // Pointer difference
    var diff:i64 = pb - pa;
    print("pb - pa = {diff.str()}");

    // Pointer indexing
    print("pa[0] = {pa[0].str()}");

    print("Done!");
}
Main Args 37_main_args.gx
// Example 37: Main with string arguments
// Usage: gx 37_main_args.gx -o args.exe && args.exe hello world

fn main(args: str[]) {
    print("Got {args.len} arguments:\n");
    for (var arg in args) {
        print("  - {arg}\n");
    }
}
Par For 37_par_for.gx
// Example 37: Parallel For (par for)
// Uses OpenMP under the hood — requires -O1+ (clang/gcc) for actual parallelism
// With TCC (default), runs sequentially (graceful degradation)

fn main() {
    var data:i32[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // Parallel for-range: each iteration is independent
    par for (i = 0:9) {
        data[i] = data[i] * 2;
        print("{data[i]}\n");
    }

    // Print results
    /*for (i = 0:9) {
        print("{data[i]}\n");
    }*/
}
Strings 38_strings.gx
// 38_strings.gx — String method tests

fn main() {
    var s = "  Hello, World!  "

    // ── trim ─────────────────────────────────
    var trimmed = s.trim()
    var trim_l = s.trim_left()
    var trim_r = s.trim_right()
    print("trim:       '" + trimmed + "'\n")
    print("trim_left:  '" + trim_l + "'\n")
    print("trim_right: '" + trim_r + "'\n")

    var hw = s.trim()

    // ── find / contains ──────────────────────
    var needle1 = "World"
    var needle2 = "xyz"
    var needle3 = "l"
    print("find World:     {hw.find(needle1)}\n")
    print("find xyz:       {hw.find(needle2)}\n")
    print("find_last l:    {hw.find_last(needle3)}\n")
    print("contains Hello: {hw.contains(needle1)}\n")
    print("contains xyz:   {hw.contains(needle2)}\n")

    // ── starts_with / ends_with ──────────────
    var prefix = "Hello"
    var suffix = "!"
    print("starts_with Hello: {hw.starts_with(prefix)}\n")
    print("ends_with !:       {hw.ends_with(suffix)}\n")

    // ── sub ──────────────────────────────────
    var sub1 = hw.sub(0, 5)
    var sub2 = hw.sub(7)
    print("sub(0,5): '" + sub1 + "'\n")
    print("sub(7):   '" + sub2 + "'\n")

    // ── upper / lower ────────────────────────
    var up = hw.upper()
    var lo = hw.lower()
    print("upper: '" + up + "'\n")
    print("lower: '" + lo + "'\n")

    // ── replace ──────────────────────────────
    var old_s = "World"
    var new_s = "GX"
    var rep = hw.replace(old_s, new_s)
    print("replace: '" + rep + "'\n")

    // ── count ────────────────────────────────
    var cnt = hw.count(needle3)
    print("count l: {cnt}\n")

    // ── repeat ───────────────────────────────
    var dash_str = "-"
    var dash = dash_str.repeat(20)
    print(dash + "\n")

    // ── split ────────────────────────────────
    var csv = "one,two,three,four"
    var delim = ","
    var parts = csv.split(delim)
    print("split count: {parts.len}\n")
    for (var p in parts) {
        print("  part: '" + p + "'\n")
    }

    // ── chaining ─────────────────────────────
    var input_str = "  HELLO world  "
    var hello = "hello"
    var hi = "hi"
    var result = input_str.trim().lower().replace(hello, hi)
    print("chained: '" + result + "'\n")

    // ── string interpolation to var ──────────
    var name = "GX"
    var greeting:str = "Hello {name}!"
    print(greeting + "\n")
}
Io 39_io.gx
// 39_io.gx - Test the io module

import io.io
import io.file
import io.fs
import io.path

fn main() {
    // --- Console I/O ---
    println("=== Console I/O ===")
    println("Hello from println!")
    eprintln("This goes to stderr")

    // --- Path utilities ---
    println("\n=== Path Utilities ===")

    var p = "src/frontend/parser/parser.cpp"
    print("  path:      ") println(p)
    print("  dirname:   ") println(dirname(p))
    print("  basename:  ") println(basename(p))
    print("  extension: ") println(extension(p))
    print("  stem:      ") println(stem(p))

    var win = "C:\\Users\\test\\file.txt"
    print("  win path:  ") println(win)
    print("  dirname:   ") println(dirname(win))
    print("  basename:  ") println(basename(win))

    print("  is_absolute('/usr/bin'):  ")
    if (is_absolute("/usr/bin")) { println("true") } else { println("false") }

    print("  is_absolute('C:\\foo'):    ")
    if (is_absolute("C:\\foo")) { println("true") } else { println("false") }

    print("  is_absolute('relative'):  ")
    if (is_absolute("relative")) { println("true") } else { println("false") }

    print("  join('foo','bar'):        ") println(join("foo", "bar"))
    print("  join('foo/','bar'):       ") println(join("foo/", "bar"))

    // --- Filesystem ---
    println("\n=== Filesystem ===")

    print("  exists('examples/39_io.gx'):  ")
    if (exists("examples/39_io.gx")) { println("true") } else { println("false") }

    print("  is_file('examples/39_io.gx'): ")
    if (is_file("examples/39_io.gx")) { println("true") } else { println("false") }

    print("  is_dir('examples'):           ")
    if (is_dir("examples")) { println("true") } else { println("false") }

    print("  is_file('nonexistent'):       ")
    if (is_file("nonexistent")) { println("true") } else { println("false") }

    var sz = file_size("examples/39_io.gx")
    print("  file_size: ") print("{sz}") println(" bytes")

    // --- File I/O ---
    println("\n=== File I/O ===")

    // Write a test file
    var ok = write_all("_test_io.txt", "Hello from GX io module!\nLine 2\n")
    print("  write_all: ") if (ok) { println("ok") } else { println("failed") }

    // Read it back
    var content = read_all("_test_io.txt")
    print("  read_all:  ") print(content)

    // Append to it
    ok = append_all("_test_io.txt", "Line 3 appended\n")
    print("  append:    ") if (ok) { println("ok") } else { println("failed") }

    // Read again
    content = read_all("_test_io.txt")
    print("  after append:\n") print(content)

    // Low-level file API
    var f = file_open("_test_io.txt", "r")
    if (f != 0) {
        var pos = file_tell(f)
        print("  tell at start: ") println("{pos}")
        file_close(f)
    }

    // Clean up test file
    ok = remove_file("_test_io.txt")
    print("  remove:    ") if (ok) { println("ok") } else { println("failed") }

    print("  exists after remove: ")
    if (exists("_test_io.txt")) { println("true") } else { println("false") }

    // make_dir / remove_dir
    ok = make_dir("_test_dir")
    print("\n  make_dir:  ") if (ok) { println("ok") } else { println("failed") }
    print("  is_dir:    ") if (is_dir("_test_dir")) { println("true") } else { println("false") }
    ok = remove_dir("_test_dir")
    print("  remove_dir:") if (ok) { println("ok") } else { println("failed") }

    println("\n=== Done ===")
}
Random 40_random.gx
// 40_random.gx - Test random and noise modules

import random.random
import random.noise

fn main() {
    // --- Random numbers ---
    print("=== Random (default seed) ===\n")
    print("  rand_int(100):     ") print("{rand_int(100)}") print("\n")
    print("  rand_int(100):     ") print("{rand_int(100)}") print("\n")
    print("  rand_range(10,20): ") print("{rand_range(10, 20)}") print("\n")
    print("  rand_f32():        ") print("{rand_f32()}") print("\n")
    print("  rand_bool():       ")
    if (rand_bool()) { print("true\n") } else { print("false\n") }

    // --- Seeded (deterministic) ---
    print("\n=== Seeded (42) ===\n")
    seed(42)
    print("  rand_int(100):     ") print("{rand_int(100)}") print("\n")
    print("  rand_int(100):     ") print("{rand_int(100)}") print("\n")

    // Same seed = same sequence
    print("\n=== Seeded (42) again ===\n")
    seed(42)
    print("  rand_int(100):     ") print("{rand_int(100)}") print("\n")
    print("  rand_int(100):     ") print("{rand_int(100)}") print("\n")

    // --- Float range ---
    print("\n=== Float range ===\n")
    seed(123)
    var i:i32 = 0
    while (i < 5) {
        var v:f32 = rand_f32_range(-1.0, 1.0)
        print("  rand_f32_range(-1,1): ") print("{v}") print("\n")
        i = i + 1
    }

    // --- Simplex noise ---
    print("\n=== Simplex Noise ===\n")
    print("  simplex1(0.5):           ") print("{simplex1(0.5)}") print("\n")
    print("  simplex1(1.0):           ") print("{simplex1(1.0)}") print("\n")
    print("  simplex1(1.5):           ") print("{simplex1(1.5)}") print("\n")

    print("  simplex2(0.5, 0.5):      ") print("{simplex2(0.5, 0.5)}") print("\n")
    print("  simplex2(1.0, 2.0):      ") print("{simplex2(1.0, 2.0)}") print("\n")

    print("  simplex3(0.5, 0.5, 0.5): ") print("{simplex3(0.5, 0.5, 0.5)}") print("\n")
    print("  simplex4(1,2,3,4):       ") print("{simplex4(1.0, 2.0, 3.0, 4.0)}") print("\n")

    // --- fBm ---
    print("\n=== Fractal Brownian Motion ===\n")
    print("  fbm2(0.5, 0.5, 4, 2.0, 0.5): ") print("{fbm2(0.5, 0.5, 4, 2.0, 0.5)}") print("\n")
    print("  fbm3(1, 2, 3, 6, 2.0, 0.5):  ") print("{fbm3(1.0, 2.0, 3.0, 6, 2.0, 0.5)}") print("\n")

    // --- 2D noise map (ASCII) ---
    print("\n=== 2D Noise Map (10x5) ===\n")
    var y:i32 = 0
    while (y < 5) {
        var x:i32 = 0
        while (x < 20) {
            var n:f32 = simplex2(x * 0.2, y * 0.2)
            if (n > 0.3)       { print("#") }
            else if (n > 0.0)  { print("+") }
            else if (n > -0.3) { print(".") }
            else               { print(" ") }
            x = x + 1
        }
        print("\n")
        y = y + 1
    }

    print("\n=== Done ===\n")
}
Out Params 41_out_params.gx
// Example 41: Out Parameters & Const-by-Default Pointers
//
// GX pointer parameters are read-only (const) by default.
// Use 'out' to mark parameters that the function will modify.
// GX functions cannot return pointers — use 'out' params instead.

struct Point {
    x: f32
    y: f32
}

struct Result {
    value: f32
    ok: bool
}

// 'out' pointer param: function CAN modify what the pointer points to
fn init_point(out p: *Point, x: f32, y: f32) {
    p.x = x
    p.y = y
}

fn scale_point(out p: *Point, factor: f32) {
    p.x = p.x * factor
    p.y = p.y * factor
}

// No 'out': pointer is read-only (const Point* in C)
fn print_point(p: *Point) {
    print("({p.x.str()}, {p.y.str()})\n")
    // p.x = 99.0  ← compile error: Cannot write through read-only pointer
}

// out value param: multi-return pattern
// 'out result:f32' becomes 'float*' in C
fn divide:bool(a: f32, b: f32, out result: f32) {
    if (b == 0.0) { return false }
    *result = a / b
    return true
}

// out struct param: fill a result struct
fn compute(a: f32, b: f32, out r: *Result) {
    if (b == 0.0) {
        r.ok = false
        r.value = 0.0
    } else {
        r.ok = true
        r.value = a / b
    }
}

fn main() {
    // === Out pointer param: init and modify ===
    var pt = Point{0.0, 0.0}
    init_point(&pt, 3.0, 4.0)
    print("After init: ")
    print_point(&pt)

    scale_point(&pt, 2.0)
    print("After scale: ")
    print_point(&pt)

    // === Out value param (multi-return) ===
    var result: f32 = 0.0
    if (divide(10.0, 3.0, &result)) {
        print("10 / 3 = {result.str()}\n")
    }
    if (!divide(5.0, 0.0, &result)) {
        print("Division by zero caught!\n")
    }

    // === Out struct param ===
    var r = Result{0.0, false}
    compute(10.0, 4.0, &r)
    if (r.ok) {
        print("10 / 4 = {r.value.str()}\n")
    }
}
Typedef 42_typedef.gx
// Example 42: Type Aliases
//
// `type NewName:ExistingType` creates a type alias.
// The alias is interchangeable with the original type.
// Emits a C `typedef` — zero runtime cost.

// Alias to built-in types
type byte:u8
type size:u64
type real:f32

// Alias to pointer type
type cstring:*c_char

struct Point {
    x: real
    y: real
}

type Vec2D:Point

fn distance:real(a: *Vec2D, b: *Vec2D) {
    var dx:real = b.x - a.x
    var dy:real = b.y - a.y
    return dx * dx + dy * dy
}

fn main() {
    var b:byte = 255
    var s:size = 1024
    var r:real = 3.14

    print("byte: {b.str()}\n")
    print("size: {s.str()}\n")
    print("real: {r.str()}\n")

    var p1 = Vec2D{1.0, 2.0}
    var p2 = Vec2D{4.0, 6.0}
    var d = distance(&p1, &p2)
    print("distance^2: {d.str()}\n")
}
Microaudio 44_microaudio.gx
// Example 44: Microaudio
//
// Minimal audio playback using the microaudio module.
// Loads and plays WAV files.
//
// Run: gx examples/44_microaudio.gx -I modules -o build/audio_test.exe

import microaudio.audio

fn main() {
    audio_init()
    defer audio_shutdown()

    // Load a WAV file (place a .wav file next to the executable)
    var snd = audio_load("test.wav")
    if (snd < 0) {
        print("Could not load test.wav\n")
        print("Place a WAV file named test.wav in the working directory.\n")
        return
    }

    print("Sound loaded (id={snd.str()})\n")

    // Set volume to 80%
    audio_set_volume(snd, 0.8)

    // Play the sound
    audio_play(snd)
    print("Playing... press Enter to stop.\n")

    input()

    audio_stop(snd)
    audio_free(snd)
    print("Done.\n")
}
Json 45_json.gx
// 45_json.gx - JSON module example

// Demonstrates parsing, querying, building, and serializing JSON

import json

fn main() {
    // ---- Parsing JSON ----
    var text = "{\"name\": \"Alice\", \"age\": 30, \"scores\": [95, 87, 92], \"active\": true}"

    var doc = json.gx_json_parse(text.cstr, text.len, 0)
    if (doc == 0) {
        print("Failed to parse JSON\n")
        return
    }
    defer json.gx_json_free(doc)

    var r = json.gx_json_root(doc)

    // ---- Reading values ----
    var name = json.gx_json_get_str(json.gx_json_obj_get(r, "name"))
    var age  = json.gx_json_get_int(json.gx_json_obj_get(r, "age"))
    var active = json.gx_json_get_bool(json.gx_json_obj_get(r, "active"))
    print("Name: {name}\n")
    print("Age:  {age}\n")
    print("Active: {active}\n")

    // ---- Array access ----
    var scores = json.gx_json_obj_get(r, "scores")
    print("Scores:\n")
    // Array access by index
    var s0 = json.gx_json_get_int(json.gx_json_arr_get(scores, 0))
    var s1 = json.gx_json_get_int(json.gx_json_arr_get(scores, 1))
    var s2 = json.gx_json_get_int(json.gx_json_arr_get(scores, 2))
    print("  [0] = {s0}\n")
    print("  [1] = {s1}\n")
    print("  [2] = {s2}\n")

    // ---- Type inspection ----
    var name_type = json.gx_json_type_desc(json.gx_json_obj_get(r, "name"))
    var age_type = json.gx_json_type_desc(json.gx_json_obj_get(r, "age"))
    var scores_type = json.gx_json_type_desc(scores)
    print("Type of name: {name_type}\n")
    print("Type of age:  {age_type}\n")
    print("Type of scores: {scores_type}\n")

    // ---- Serialize back (pretty) ----
    var pretty = json.gx_json_write(doc, json.WRITE_PRETTY)
    print("\nPretty printed:\n{pretty}\n")

    // ---- Build JSON from scratch ----
    print("--- Building JSON ---\n")
    var mdoc = json.gx_json_new_doc()
    defer json.gx_json_mut_free(mdoc)

    var obj = json.gx_json_new_obj(mdoc)
    json.gx_json_set_root(mdoc, obj)

    json.gx_json_obj_add_str(mdoc, obj, "language", "GX")
    json.gx_json_obj_add_int(mdoc, obj, "version", 2)
    json.gx_json_obj_add_bool(mdoc, obj, "fast", true)
    json.gx_json_obj_add_float(mdoc, obj, "pi", 3.14159)

    // Nested array
    var arr = json.gx_json_obj_add_arr(mdoc, obj, "features")
    json.gx_json_arr_add_str(mdoc, arr, "transpiles to C")
    json.gx_json_arr_add_str(mdoc, arr, "zero-cost abstractions")
    json.gx_json_arr_add_str(mdoc, arr, "yyjson powered")

    // Nested object
    var meta = json.gx_json_obj_add_obj(mdoc, obj, "meta")
    json.gx_json_obj_add_str(mdoc, meta, "author", "GX Team")
    json.gx_json_obj_add_int(mdoc, meta, "year", 2026)

    var result = json.gx_json_mut_write(mdoc, json.WRITE_PRETTY)
    print("{result}\n")
}
Time 46_time.gx
// 46_time.gx - Time module example
// Demonstrates clock, date/time, formatting, benchmarking, and sleep

import time

fn main() {
    // ---- Current date and time ----
    var now = time.gx_time_unix()
    var y = time.gx_time_year(now)
    var mo = time.gx_time_month(now)
    var d = time.gx_time_day(now)
    var h = time.gx_time_hour(now)
    var mi = time.gx_time_minute(now)
    var s = time.gx_time_second(now)
    print("Current local time: {y}-{mo}-{d} {h}:{mi}:{s}\n")

    // UTC equivalent
    var uy = time.gx_time_utc_year(now)
    var umo = time.gx_time_utc_month(now)
    var ud = time.gx_time_utc_day(now)
    var uh = time.gx_time_utc_hour(now)
    print("Current UTC time:   {uy}-{umo}-{ud} {uh}:{mi}:{s}\n")

    // ---- Formatting ----
    var formatted = time.gx_time_format(now, "%Y-%m-%d %H:%M:%S")
    print("Formatted (local): {formatted}\n")

    var formatted_utc = time.gx_time_format_utc(now, "%Y-%m-%d %H:%M:%S")
    print("Formatted (UTC):   {formatted_utc}\n")

    // Day of week
    var wd = time.gx_time_weekday(now)
    var day_name = time.gx_time_format(now, "%A")
    print("Weekday: {wd} ({day_name})\n")

    // ---- Benchmarking ----
    print("\n--- Benchmark ---\n")
    var t0 = time.gx_time_now_ns()

    // Do some work
    var sum = 0
    for (i = 0 : 999999) {
        sum = sum + i
    }

    var t1 = time.gx_time_now_ns()
    var ms = time.gx_time_elapsed_ms(t0, t1)
    var us = time.gx_time_elapsed_us(t0, t1)
    print("Sum of 0..999999 = {sum}\n")
    print("Elapsed: {ms} ms ({us} us)\n")

    // ---- Sleep ----
    print("\n--- Sleep test ---\n")
    var s0 = time.gx_time_now_ns()
    time.gx_time_sleep_ms(100)
    var s1 = time.gx_time_now_ns()
    var slept = time.gx_time_elapsed_ms(s0, s1)
    print("Slept ~100ms, measured: {slept} ms\n")

    // ---- Build timestamp ----
    var epoch = time.gx_time_make(2026, 1, 1, 0, 0, 0)
    var new_year = time.gx_time_format(epoch, "%Y-%m-%d %H:%M:%S (%A)")
    print("\nNew Year 2026: {new_year}\n")
}
Xml 47_xml.gx
// 47_xml.gx - XML parsing, navigation, and building example
// Build: gx 47_xml.gx -I modules -o build/47_xml.exe

import xml

fn main() {
    // ---- Parse XML from string ----
    var data = "<library name='City Library'><book id='1'><title>The Rust Programming Language</title><author>Steve Klabnik</author><year>2019</year></book><book id='2'><title>The C Programming Language</title><author>Kernighan and Ritchie</author><year>1978</year></book><book id='3'><title>Structure and Interpretation</title><author>Abelson and Sussman</author><year>1996</year></book></library>"

    var doc = xml.gx_xml_parse(data.cstr, data.len)
    if (xml.gx_xml_has_error(doc)) {
        print("Parse error: {xml.gx_xml_error(doc)}\n")
        xml.gx_xml_free(doc)
        return
    }

    // Root element
    print("Root tag: {xml.gx_xml_name(doc)}\n")

    var lib_name = xml.gx_xml_attr(doc, "name")
    print("Library: {lib_name}\n")

    var num_books = xml.gx_xml_child_count(doc, "book")
    print("Book count: {num_books}\n\n")

    // Iterate children with same tag name
    var book = xml.gx_xml_child(doc, "book")
    while (book != 0) {
        var id = xml.gx_xml_attr(book, "id")
        var title = xml.gx_xml_txt(xml.gx_xml_child(book, "title"))
        var author = xml.gx_xml_txt(xml.gx_xml_child(book, "author"))
        var year = xml.gx_xml_txt(xml.gx_xml_child(book, "year"))
        print("Book {id}: {title} by {author} ({year})\n")
        book = xml.gx_xml_next(book)
    }

    // ---- Build XML from scratch ----
    print("\n--- Building XML ---\n")
    var root = xml.gx_xml_new("config")
    xml.gx_xml_set_attr(root, "version", "1.0")

    var window = xml.gx_xml_add_child(root, "window")
    xml.gx_xml_set_attr(window, "width", "1280")
    xml.gx_xml_set_attr(window, "height", "720")
    xml.gx_xml_set_txt(window, "Main Window")

    var gfx = xml.gx_xml_add_child(root, "graphics")
    xml.gx_xml_set_attr(gfx, "backend", "opengl")

    var res = xml.gx_xml_add_child(gfx, "resolution")
    xml.gx_xml_set_txt(res, "1920x1080")

    var aa = xml.gx_xml_add_child(gfx, "antialiasing")
    xml.gx_xml_set_txt(aa, "4x MSAA")

    // Serialize to string
    var xml_str = xml.gx_xml_to_str(root)
    print("{xml_str}\n")

    xml.gx_xml_free_str(xml_str)
    xml.gx_xml_free(root)
    xml.gx_xml_free(doc)
}
Test Math test_math.gx
// test_math.ec - Verify vec and mat math modules compile and produce correct results

import math.scalar
import math.vec
import math.mat

fn main() {
    // --- scalar tests ---
    print("=== Scalar ===\n");
    var s:f32 = sinf(PI() / 2.0);
    print("sin(PI/2) = {s}\n");

    var c:f32 = cosf(0.0);
    print("cos(0) = {c}\n");

    var sq:f32 = sqrtf(9.0);
    print("sqrt(9) = {sq}\n");
    var sw_pos:vec3 = {1,2,3};
    sw_pos.xy += 10;
    print("sw_pos after .xy += 10: {sw_pos}\n");
    var cl:f32 = clamp_f(5.0, 0.0, 1.0);
    print("clamp(5, 0, 1) = {cl}\n");

    var lr:f32 = lerp_f(0.0, 10.0, 0.25);
    print("lerp(0, 10, 0.25) = {lr}\n");

    var rad:f32 = radians(180.0);
    print("radians(180) = {rad}\n");

    // --- vec3 tests ---
    print("\n=== Vec3 ===\n");
    var a:vec3;
    a.x = 3.0;
    a.y = 0.0;
    a.z = 4.0;

    var len:f32 = length_v3(a);
    print("length(3,0,4) = {len}\n");

    var n:vec3 = normalize_v3(a);
    print("normalize(3,0,4) = {n}\n");

    var b:vec3;
    b.x = 1.0;
    b.y = 2.0;
    b.z = 3.0;

    var d:f32 = distance_v3(a, b);
    print("distance = {d}\n");

    var mid:vec3 = lerp_v3(a, b, 0.5);
    print("lerp(a, b, 0.5) = {mid}\n");

    // --- vec2 tests ---
    print("\n=== Vec2 ===\n");
    var v2:vec2;
    v2.x = 3.0;
    v2.y = 4.0;
    var len2:f32 = length_v2(v2);
    print("length(3,4) = {len2}\n");

    var n2:vec2 = normalize_v2(v2);
    print("normalize(3,4) = {n2}\n");

    // --- mat4 tests ---
    print("\n=== Mat4 ===\n");
    var id:mat4 = identity_mat4();
    print("identity = {id}\n");

    // Test translation
    var pos:vec3;
    pos.x = 10.0;
    pos.y = 20.0;
    pos.z = 30.0;
    var tm:mat4 = translation(pos);
    var tc:vec4 = tm.col[3];
    print("translation(10,20,30) col3 = {tc}\n");

    // Test mul_m4 (identity * translation = translation)
    var result:mat4 = mul_m4(id, tm);
    var rc:vec4 = result.col[3];
    print("I * T col3 = {rc}\n");

    // Test mul_m4v4
    var v:vec4;
    v.x = 1.0;
    v.y = 0.0;
    v.z = 0.0;
    v.w = 1.0;
    var tv:vec4 = mul_m4v4(tm, v);
    print("T * (1,0,0,1) = {tv}\n");

    // Test perspective
    var proj:mat4 = perspective(radians(60.0), 1.333, 0.1, 100.0);
    var p00:f32 = proj.col[0].x;
    print("perspective[0][0] = {p00}\n");

    // Test look_at
    var eye:vec3;
    eye.x = 0.0;
    eye.y = 0.0;
    eye.z = 5.0;
    var target:vec3;
    target.x = 0.0;
    target.y = 0.0;
    target.z = 0.0;
    var up:vec3;
    up.x = 0.0;
    up.y = 1.0;
    up.z = 0.0;
    var view:mat4 = look_at(eye, target, up);
    var vc:vec4 = view.col[3];
    print("look_at col3 = {vc}\n");

    print("\nAll math tests done.\n");
}