Skip to content

feat: implement generics, explicit type casting, and static globals#306

Merged
LunaStev merged 1 commit intowavefnd:masterfrom
LunaStev:feat/implement-generics-explicit-type-casting,-and-static-globals
Mar 8, 2026
Merged

feat: implement generics, explicit type casting, and static globals#306
LunaStev merged 1 commit intowavefnd:masterfrom
LunaStev:feat/implement-generics-explicit-type-casting,-and-static-globals

Conversation

@LunaStev
Copy link
Member

@LunaStev LunaStev commented Mar 8, 2026

This PR introduces a major leap in Wave's expressiveness and system-level capabilities. It implements the foundational infrastructure for Generic Programming, introduces explicit Type Casting via the as operator, and adds support for Global Static Variables. Additionally, it matures the compiler's cross-platform architecture with robust target-specific preprocessing and granular backend control for x86_64 and ARM64.


Key Changes

1. Generic Programming (Generics)

  • Infrastructure: Added generic_params to FunctionNode and StructNode, and type_args to function calls/struct initializers.
  • Nested Parsing: Enhanced the type parser to correctly handle complex nested generic arguments (e.g., ptr<TypedBuffer<i32>>).
  • Monomorphization: Integrated a monomorphization pass into the compilation runner to generate specialized LLVM IR for generic instances.
  • Stdlib Expansion: Refactored core modules to provide reusable generic utilities, including TypedBuffer<T>, ptr_swap<T>, and numeric functions like num_abs<T> and num_min<T>.

2. Language Primitives: static, as, and null

  • Static Globals: Introduced the static keyword for declaring global variables with persistent storage in the LLVM data segment.
  • Explicit Casting (as): Added the as keyword for explicit type conversions (e.g., x as i64), providing safe widening/narrowing and pointer-to-integer casts.
  • Native null: Added a formal null literal, ensuring strict type compatibility with pointer types across the backend.

3. Backend & Cross-Platform Robustness

  • Target Customization: Expanded BackendOptions to allow users to override target triples, CPU architectures, and ABIs via the CLI.
  • ABI Refinement: Overhauled abi_c.rs to support the System V ABI for both x86_64 and ARM64 on Linux and macOS (Darwin), including optimized aggregate splitting for Apple Silicon.
  • Intelligent Preprocessing: Rebuilt the #[target(os="...")] preprocessor to be "context-aware," ensuring it ignores braces and semicolons inside comments or string literals.

4. Tooling & Documentation

  • Tiered Platform Policy: Updated README.md to formalize Tiers 1–4 of platform support, setting clear expectations for architecture stability.
  • Advanced CLI: Added specialized --llvm and -C flags for fine-grained backend and linker control.
  • Ecosystem: Added a reference to the doom.wave example to showcase the language's capabilities.

Example Usage

Generics & Type Casting:

#[target(os="linux")]
fun platform_id() -> i32 {
    return 1;
}

#[target(os="macos")]
fun platform_id() -> i32 {
    return 2;
}

struct Box<T> {
    value: T;
}

struct Pair<A, B> {
    first: A;
    second: B;
}

fun identity<T>(x: T) -> T {
    return x;
}

fun wrap<T>(x: T) -> Box<T> {
    var boxed: Box<T>;
    boxed.value = x;
    return boxed;
}

fun make_pair<A, B>(a: A, b: B) -> Pair<A, B> {
    var pair_value: Pair<A, B>;
    pair_value.first = a;
    pair_value.second = b;
    return pair_value;
}

fun first_of<A, B>(p: Pair<A, B>) -> A {
    return p.first;
}

fun main() -> i32 {
    var a: i32 = identity<i32>(10);
    if (a != 10) {
        return 1;
    }

    var boxed_i64: Box<i64> = wrap<i64>(1234);
    if (boxed_i64.value != 1234) {
        return 2;
    }

    var p: Pair<i32, i64> = make_pair<i32, i64>(7, 99);
    if (p.first != 7) {
        return 3;
    }

    if (p.second != 99) {
        return 4;
    }

    var nested: Box<Box<i32>> = wrap<Box<i32>>(wrap<i32>(42));
    if (nested.value.value != 42) {
        return 5;
    }

    var p_first: i32 = first_of<i32, i64>(p);
    if (p_first != 7) {
        return 6;
    }

    var os: i32 = platform_id();
    if (os != 1 && os != 2) {
        return 7;
    }

    return 0;
}

Benefits

  • Code Reusability: Generics allow for writing algorithms (like swap or min) once and using them across any type.
  • System Control: static and as provide the low-level primitives necessary for memory-mapped I/O and OS development.
  • Portability: The improved target preprocessor and ARM64 ABI support make Wave a viable tool for modern cross-platform systems programming.

This commit introduces the foundational infrastructure for generic
programming, explicit type casting via the `as` operator, and global
static variables. It also significantly matures the target-specific
preprocessing and backend control.

Changes:
- **Generics Support**:
  - **AST & Parser**: Added `generic_params` to `FunctionNode` and
    `StructNode`. Added `type_args` to function calls.
  - **Parsing**: Implemented `parse_generic_param_names` and enhanced
    the type parser to handle nested generic arguments and
    top-level split logic.
  - **Stdlib**: Refactored core modules to provide generic utilities,
    including `TypedBuffer<T>`, `ptr_swap<T>`, and generic math functions
    (`num_abs`, `num_min`, etc.).
  - **Monomorphization**: Integrated a monomorphization pass into the
    compilation runner.
- **Language Enhancements**:
  - **Type Casting**: Introduced the `as` keyword and `Expression::Cast`
    to support explicit type conversions in both runtime and
    compile-time contexts.
  - **Statics**: Added the `static` keyword for global variables,
    including backend support for global LLVM symbols.
  - **Null Support**: Added a native `null` literal and ensured type
    compatibility with pointers.
- **Backend & Cross-Platform**:
  - **Target Control**: Expanded the `BackendOptions` to allow
    overriding target triples, CPU architectures, and ABIs.
  - **ABI Refinement**: Updated `abi_c.rs` to support both x86_64 and
    Arm64 for Linux and Darwin (macOS), including improved aggregate
    splitting logic for ARM64.
  - **Robust Preprocessing**: Overhauled `#[target(os="...")]`
    preprocessing to correctly ignore braces and semicolons inside
    comments or string literals.
- **CLI & Documentation**:
  - Updated `README.md` to document the new **Tiered Platform Policy**
    and added a section for building from source.
  - Expanded the CLI with advanced `--llvm` and linker options.
  - Added a reference to the `doom.wave` example.

These features significantly increase the expressiveness of the Wave
language and provide the tools necessary for writing reusable,
platform-aware systems code.

Signed-off-by: LunaStev <luna@lunastev.org>
@LunaStev LunaStev merged commit 0da8f5e into wavefnd:master Mar 8, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant